diff options
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | bluetooth.cpp | 13 | ||||
-rw-r--r-- | bluetooth.h | 2 | ||||
-rw-r--r-- | message.cpp | 26 | ||||
-rw-r--r-- | message.h | 10 | ||||
-rw-r--r-- | messageengine.cpp | 77 | ||||
-rw-r--r-- | messageengine.h | 5 | ||||
-rw-r--r-- | responsemessage.cpp | 49 | ||||
-rw-r--r-- | responsemessage.h | 37 |
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(); } @@ -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 |