summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Ranostay <matt.ranostay@konsulko.com>2018-05-01 23:15:58 -0700
committerMatt Ranostay <matt.ranostay@konsulko.com>2018-05-13 17:43:33 -0700
commitbb1aee701bc3516c2072a79d3129ee83918df7fd (patch)
tree150edc50142429ee566edf629a8d3f5dfb3a8557
parent6465961f28f40ff5a2da31876f1c23ea3c7f7cec (diff)
message: add response message support
Add support for callid sequencing, and request data being included with the response message. Bug-AGL: SPEC-1404 Change-Id: I259ae3da68e55de17eafe9db534258db5fbc3ef8 Signed-off-by: Matt Ranostay <matt.ranostay@konsulko.com>
-rw-r--r--CMakeLists.txt3
-rw-r--r--bluetooth.cpp13
-rw-r--r--bluetooth.h2
-rw-r--r--message.cpp26
-rw-r--r--message.h10
-rw-r--r--messageengine.cpp77
-rw-r--r--messageengine.h5
-rw-r--r--responsemessage.cpp49
-rw-r--r--responsemessage.h37
9 files changed, 182 insertions, 40 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ec89c39..b5ffaaa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,6 +15,7 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qtappfw.pc
DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig)
add_library(qtappfw SHARED message.cpp messageengine.cpp
+ responsemessage.cpp
bluetooth.cpp bluetoothmessage.cpp
mediaplayer.cpp mediaplayermessage.cpp
telephony.cpp telephonymessage.cpp
@@ -23,7 +24,7 @@ target_link_libraries(qtappfw Qt5::WebSockets)
set_target_properties(qtappfw PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION 1
- PUBLIC_HEADER "message.h;messageengine.h;bluetooth.h;bluetoothmessage.h;mediaplayer.h;mediaplayermessage.h;telephony.h;telephonymessage.h;weather.h;weathermessage.h")
+ PUBLIC_HEADER "message.h;messageengine.h;bluetooth.h;bluetoothmessage.h;mediaplayer.h;mediaplayermessage.h;responsemessage.h;telephony.h;telephonymessage.h;weather.h;weathermessage.h")
target_include_directories(qtappfw PRIVATE .)
install(TARGETS qtappfw
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
diff --git a/bluetooth.cpp b/bluetooth.cpp
index 6e21ad1..cc5f496 100644
--- a/bluetooth.cpp
+++ b/bluetooth.cpp
@@ -18,6 +18,7 @@
#include "messageengine.h"
#include "bluetooth.h"
#include "bluetoothmessage.h"
+#include "responsemessage.h"
Bluetooth::Bluetooth (QUrl &url, QObject * parent) :
QObject(parent),
@@ -214,11 +215,13 @@ void Bluetooth::onMessageReceived(MessageType type, Message *msg)
} else if (tmsg->isDeviceUpdatedEvent()) {
emit deviceUpdatedEvent(tmsg->eventData());
}
- } else if (msg->isReply() && type == GenericMessage) {
- if (this->isDiscoveryListResponse(msg)) {
- emit deviceListEvent(msg->replyData());
- } else if (this->isPowerResponse(msg)) {
- m_power = msg->replyData().value("power").toString() == "on";
+ } else if (msg->isReply() && type == ResponseRequestMessage) {
+ ResponseMessage *tmsg = qobject_cast<ResponseMessage*>(msg);
+
+ if (tmsg->requestVerb() == "discovery_result") {
+ emit deviceListEvent(tmsg->replyData());
+ } else if (tmsg->requestVerb() == "power") {
+ m_power = tmsg->replyData().value("power").toString() == "on";
emit powerChanged(m_power);
}
}
diff --git a/bluetooth.h b/bluetooth.h
index 118516e..24605cf 100644
--- a/bluetooth.h
+++ b/bluetooth.h
@@ -75,8 +75,6 @@ class Bluetooth : public QObject
void onMessageReceived(MessageType, Message*);
QString process_uuid(QString uuid) { if (uuid.length() == 36) return uuid; return uuids.value(uuid); };
- bool isDiscoveryListResponse(Message *tmsg) { return (tmsg->replyInfo() == "BT - Scan Result is Displayed"); };
- bool isPowerResponse(Message *tmsg) { return (tmsg->replyInfo() == "Radio - Power set"); };
// values
bool m_power;
diff --git a/message.cpp b/message.cpp
index 33211da..3cd4bb9 100644
--- a/message.cpp
+++ b/message.cpp
@@ -34,15 +34,12 @@ bool Message::createRequest(QString api, QString verb, QJsonValue parameter)
return false;
}
- m_request.append(Call);
- m_request.append(9999);
- m_request.append(api + (QString)("/") + verb);
- m_request.append(QJsonValue(parameter));
+ m_request["msgid"] = Call;
+ m_request["callid"] = 0;
+ m_request["api"] = api;
+ m_request["verb"] = verb;
+ m_request["parameter"] = parameter;
- QJsonDocument jdoc;
- jdoc.setArray(m_request);
-
- m_jdoc = jdoc;
m_init = true;
return true;
@@ -50,7 +47,7 @@ bool Message::createRequest(QString api, QString verb, QJsonValue parameter)
bool Message::fromJson(QByteArray jsonData)
{
- QJsonDocument jdoc(QJsonDocument::fromJson(jsonData));
+ QJsonDocument jdoc(QJsonDocument::fromJson(jsonData));
if (jdoc.isNull()) {
qWarning("Imported invalid JSON: empty appfw message");
@@ -142,5 +139,14 @@ bool Message::fromJDoc(QJsonDocument jdoc)
QByteArray Message::toJson(QJsonDocument::JsonFormat format)
{
- return m_jdoc.toJson(format).data();
+ QJsonArray array;
+ array.append(m_request["msgid"].toInt());
+ array.append(m_request["callid"].toInt());
+ array.append(m_request["api"].toString() + "/" + m_request["verb"].toString());
+ array.append(m_request["parameter"].toJsonValue());
+
+ QJsonDocument jdoc;
+ jdoc.setArray(array);
+
+ return jdoc.toJson(format).data();
}
diff --git a/message.h b/message.h
index 37dc740..062ca58 100644
--- a/message.h
+++ b/message.h
@@ -18,7 +18,8 @@
#define MESSAGE_H
#include <QObject>
-#include <QJsonArray>
+#include <QMap>
+#include <QVariant>
#include <QJsonDocument>
#include <QJsonObject>
@@ -31,6 +32,7 @@ enum MessageId {
enum MessageType {
GenericMessage,
+ ResponseRequestMessage,
TelephonyEventMessage,
WeatherEventMessage,
MediaplayerEventMessage,
@@ -90,10 +92,14 @@ class Message : public QObject
return m_init;
}
+ inline void setCallId(qint32 callId) {
+ m_request["callid"] = callId;
+ }
+
protected:
bool m_event, m_init, m_reply;
QString m_event_api, m_event_name, m_reply_info, m_reply_status, m_reply_uuid;
- QJsonArray m_request;
+ QMap<QString, QVariant> m_request;
QJsonDocument m_jdoc;
QJsonObject m_event_data, m_reply_data;
};
diff --git a/messageengine.cpp b/messageengine.cpp
index 4cc5bf3..87c2630 100644
--- a/messageengine.cpp
+++ b/messageengine.cpp
@@ -18,6 +18,7 @@
#include "messageengine.h"
#include "bluetoothmessage.h"
#include "mediaplayermessage.h"
+#include "responsemessage.h"
#include "telephonymessage.h"
#include "weathermessage.h"
@@ -25,6 +26,7 @@
MessageEngine::MessageEngine(const QUrl &url, QObject *parent) :
QObject(parent),
+ m_callid(0),
m_url(url)
{
connect(&m_websocket, &QWebSocket::connected, this, &MessageEngine::onConnected);
@@ -33,15 +35,32 @@ MessageEngine::MessageEngine(const QUrl &url, QObject *parent) :
m_websocket.open(url);
}
+unsigned int MessageEngine::requestCallId()
+{
+ int callid;
+
+ m_mutex.lock();
+ callid = ++m_callid;
+ m_mutex.unlock();
+
+ return callid;
+}
+
bool MessageEngine::sendMessage(Message *message)
{
if (!message->isValid())
return false;
- qint64 size = m_websocket.sendTextMessage(message->toJson().data());
+ auto callid = requestCallId();
+ message->setCallId(callid);
+
+ QByteArray data = message->toJson().data();
+ qint64 size = m_websocket.sendTextMessage(data);
if (size == 0)
return false;
+ m_calls.insert(callid, data);
+
return true;
}
@@ -67,28 +86,46 @@ void MessageEngine::onTextMessageReceived(QString jsonStr)
}
QJsonArray msg = jdoc.array();
- QStringList api_str_list = msg[1].toString().split(QRegExp("/"));
- QString api = api_str_list[0];
+ int msgid = msg[0].toInt();
Message *message;
MessageType type;
- // FIXME: This should be rewritten using a factory class with a
- // parser parameter to remove API specific handling here
- if (api == "Bluetooth-Manager") {
- message = new BluetoothMessage;
- type = BluetoothEventMessage;
- } else if (api == "telephony") {
- message = new TelephonyMessage;
- type = TelephonyEventMessage;
- } else if (api == "weather") {
- message = new WeatherMessage;
- type = WeatherEventMessage;
- } else if (api == "mediaplayer") {
- message = new MediaplayerMessage;
- type = MediaplayerEventMessage;
- } else {
- message = new Message;
- type = GenericMessage;
+
+ switch (msgid) {
+ case RetOk:
+ case RetErr: {
+ auto callid = msg[1].toString().toInt();
+ message = new ResponseMessage(m_calls[callid]);
+ type = ResponseRequestMessage;
+ m_calls.remove(callid);
+ break;
+ }
+ case Event: {
+ QStringList api_str_list = msg[1].toString().split(QRegExp("/"));
+ QString api = api_str_list[0];
+
+ // FIXME: This should be rewritten using a factory class with a
+ // parser parameter to remove API specific handling here
+ if (api == "Bluetooth-Manager") {
+ message = new BluetoothMessage;
+ type = BluetoothEventMessage;
+ } else if (api == "telephony") {
+ message = new TelephonyMessage;
+ type = TelephonyEventMessage;
+ } else if (api == "weather") {
+ message = new WeatherMessage;
+ type = WeatherEventMessage;
+ } else if (api == "mediaplayer") {
+ message = new MediaplayerMessage;
+ type = MediaplayerEventMessage;
+ } else {
+ message = new Message;
+ type = GenericMessage;
+ }
+ break;
+ }
+ default:
+ break;
}
if (message->fromJDoc(jdoc) == false) {
diff --git a/messageengine.h b/messageengine.h
index 0ba75fa..6b2233f 100644
--- a/messageengine.h
+++ b/messageengine.h
@@ -17,6 +17,7 @@
#ifndef MESSAGEENGINE_H
#define MESSAGEENGINE_H
+#include <QMutex>
#include <QThread>
#include <QUrl>
#include <QWebSocket>
@@ -29,6 +30,7 @@ class MessageEngine : public QObject
public:
explicit MessageEngine(const QUrl &url, QObject *parent = Q_NULLPTR);
bool sendMessage(Message *message);
+ unsigned int requestCallId();
Q_SIGNALS:
void disconnected();
@@ -42,7 +44,10 @@ class MessageEngine : public QObject
private:
QWebSocket m_websocket;
+ QMap<qint32, QByteArray> m_calls;
QUrl m_url;
+ QMutex m_mutex;
+ unsigned int m_callid;
};
#endif // MESSAGEENGINE_H
diff --git a/responsemessage.cpp b/responsemessage.cpp
new file mode 100644
index 0000000..0e2ad5a
--- /dev/null
+++ b/responsemessage.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 Konsulko Group
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <QDebug>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonValue>
+
+#include "responsemessage.h"
+
+ResponseMessage::ResponseMessage(QByteArray request)
+{
+
+ QJsonDocument jdoc(QJsonDocument::fromJson(request));
+
+ if (!jdoc.isArray()) {
+ qWarning("Invalid appfw message: not an array");
+ return;
+ }
+
+ QJsonArray msg = jdoc.array();
+
+ if (msg.size() != 4) {
+ qWarning("Invalid appfw message: invalid array size");
+ return;
+ }
+
+ QStringList api_str_list = msg[2].toString().split(QRegExp("/"));
+
+ m_request["msgid"] = msg.at(0);
+ m_request["callid"] = msg.at(1);
+ m_request["api"] = api_str_list[0];
+ m_request["verb"] = api_str_list[1];
+ m_request["parameter"] = msg.at(3);
+}
diff --git a/responsemessage.h b/responsemessage.h
new file mode 100644
index 0000000..fd9406a
--- /dev/null
+++ b/responsemessage.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 Konsulko Group
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RESPONSEMESSAGE_H
+#define RESPONSEMESSAGE_H
+
+#include <QObject>
+
+#include "message.h"
+
+class ResponseMessage : public Message
+{
+ Q_OBJECT
+
+ public:
+ explicit ResponseMessage(QByteArray request = nullptr);
+
+ inline QString requestVerb() const
+ {
+ return m_request["verb"].toString();
+ }
+};
+
+#endif // RESPONSEMESSAGE_H