diff options
author | Raquel Medina <raquel.medina@konsulko.com> | 2020-03-18 23:56:31 +0100 |
---|---|---|
committer | Raquel Medina <raquel.medina@konsulko.com> | 2020-03-23 14:02:28 +0100 |
commit | 0ed292d3ccf93c889734960676a321d1166d3f66 (patch) | |
tree | b8d64d1685d2f4bf599ab3867a0d3ff557ff0479 | |
parent | 5c750385d02116a92fa4c120ccc26abb8267bc97 (diff) |
rework message hierarchy
Rework message hierarchy with the final objective
of splitting libqtappfw into several libraries.
This commit carries the following changes:
- Simplify message hierarchy, keeping abstract
Message class, adding specialization for call and
event messages, keeping ResponseMessage, and
removing all module specific specializations.
- Add MessageFactory class to create message
objects.
- Change messages life cycle: using smart pointers
and removing QObject from message hierarchy (a
Message is not a QObject anymore and thus
'deleteLater()' is not available).
- Adapt all modules to use new message hierarchy.
- Keep ResponseMessage original constructor to
avoid breaking TaskManager.
- Message constructors have been kept public, but
will go private on a follow-up patch (once
TaskManager class has been modified to use new
MessageFactory).
Bug-AGL: SPEC-3112
Signed-off-by: Raquel Medina <raquel.medina@konsulko.com>
Change-Id: I3a7a6325209ddeca2293f1ac745371861a947bfb
52 files changed, 1307 insertions, 899 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e769b33..b2f826f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,8 +61,8 @@ set (SUBDIRS voice-capabilities weather) -add_headers(message.h messageengine.h responsemessage.h) -add_sources(message.cpp messageengine.cpp responsemessage.cpp) +add_headers(message.h messagefactory.h messageengine.h responsemessage.h callmessage.h eventmessage.h) +add_sources(message.cpp messagefactory.cpp messageengine.cpp responsemessage.cpp callmessage.cpp eventmessage.cpp) foreach(subdir ${SUBDIRS}) add_subdirectory(${subdir}) diff --git a/bluetooth/CMakeLists.txt b/bluetooth/CMakeLists.txt index cdefb0d..0e05d3b 100644 --- a/bluetooth/CMakeLists.txt +++ b/bluetooth/CMakeLists.txt @@ -1,2 +1,2 @@ -add_headers(bluetooth.h bluetoothmessage.h bluetoothmodel.h) -add_sources(bluetooth.cpp bluetoothmessage.cpp bluetoothmodel.cpp) +add_headers(bluetooth.h bluetoothmodel.h) +add_sources(bluetooth.cpp bluetoothmodel.cpp) diff --git a/bluetooth/bluetooth.cpp b/bluetooth/bluetooth.cpp index f74d60d..e39270a 100644 --- a/bluetooth/bluetooth.cpp +++ b/bluetooth/bluetooth.cpp @@ -16,13 +16,13 @@ #include <QDebug> -#include "message.h" -#include "bluetoothmessage.h" +#include "callmessage.h" +#include "eventmessage.h" #include "responsemessage.h" +#include "messagefactory.h" #include "messageengine.h" -#include "bluetoothmodel.h" #include "bluetooth.h" - +#include "bluetoothmodel.h" Bluetooth::Bluetooth (QUrl &url, QQmlContext *context, QObject * parent) : @@ -58,10 +58,13 @@ Bluetooth::~Bluetooth() void Bluetooth::send_command(QString verb, QJsonObject parameter) { - BluetoothMessage *tmsg = new BluetoothMessage(); - tmsg->createRequest(verb, parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* btmsg = static_cast<CallMessage*>(msg.get()); + btmsg->createRequest("Bluetooth-Manager", verb, parameter); + m_mloop->sendMessage(std::move(msg)); } void Bluetooth::setPower(bool state) @@ -261,32 +264,39 @@ void Bluetooth::processAdapterChangesEvent(QJsonObject data) m_discoverable = false; } -void Bluetooth::onMessageReceived(MessageType type, Message *msg) +void Bluetooth::onMessageReceived(std::shared_ptr<Message> msg) { - if (msg->isEvent() && type == MessageType::BluetoothEventMessage) { - BluetoothMessage *tmsg = qobject_cast<BluetoothMessage*>(msg); - - if (tmsg->isDeviceChangesEvent()) { - processDeviceChangesEvent(tmsg->eventData()); - } else if (tmsg->isAdapterChangesEvent()) { - processAdapterChangesEvent(tmsg->eventData()); - } else if (tmsg->isAgentEvent()) { - emit requestConfirmationEvent(tmsg->eventData()); - } + if (!msg) + return; - } else if (msg->isReply() && type == MessageType::ResponseRequestMessage) { - ResponseMessage *tmsg = qobject_cast<ResponseMessage*>(msg); + if (msg->isEvent()) { + std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg); + QString ename = emsg->eventName(); + QString eapi = emsg->eventApi(); + QJsonObject data = emsg->eventData(); + if (eapi != "Bluetooth-Manager") + return; + if (ename == "device_changes") { + processDeviceChangesEvent(data); + } else if (ename == "adapter_changes") { + processAdapterChangesEvent(data); + } else if (ename == "agent") { + emit requestConfirmationEvent(data); + } - if (tmsg->requestVerb() == "managed_objects") { - populateDeviceList(tmsg->replyData()); - } else if (tmsg->requestVerb() == "adapter_state") { - bool powered = tmsg->replyData().value("powered").toBool(); + } else if (msg->isReply()) { + std::shared_ptr<ResponseMessage> rmsg = std::static_pointer_cast<ResponseMessage>(msg); + //get api name + QString verb = rmsg->requestVerb(); + QJsonObject data = rmsg->replyData(); + if (verb == "managed_objects") { + populateDeviceList(data); + } else if (verb == "adapter_state") { + bool powered = data.value("powered").toBool(); if (m_power != powered) { m_power = powered; emit powerChanged(m_power); } } } - - msg->deleteLater(); } diff --git a/bluetooth/bluetooth.h b/bluetooth/bluetooth.h index 815e180..3953fe6 100644 --- a/bluetooth/bluetooth.h +++ b/bluetooth/bluetooth.h @@ -17,17 +17,16 @@ #ifndef BLUETOOTH_H #define BLUETOOTH_H +#include <memory> #include <QObject> -#include <QJsonArray> #include <QJsonObject> +#include <QJsonArray> #include <QtQml/QQmlContext> class BluetoothModel; class MessageEngine; class Message; -enum class MessageType; - class Bluetooth : public QObject { Q_OBJECT @@ -80,7 +79,7 @@ class Bluetooth : public QObject // slots void onConnected(); void onDisconnected(); - void onMessageReceived(MessageType, Message*); + void onMessageReceived(std::shared_ptr<Message>); QString process_uuid(QString uuid) { if (uuid.length() == 36) return uuid; return uuids.value(uuid); }; diff --git a/callmessage.cpp b/callmessage.cpp new file mode 100644 index 0000000..4afb071 --- /dev/null +++ b/callmessage.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2020 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 <QJsonValue> + +#include "callmessage.h" +#include "message.h" + + +bool CallMessage::createRequest(QString api, QString verb, QJsonValue parameter) +{ + if (!m_request.isEmpty()){ + qWarning("Message instance has already been used. Cannot send another request."); + return false; + } + + m_request["msgid"] = static_cast<unsigned int>(MessageId::Call); + m_request["callid"] = 0; + m_request["api"] = api; + m_request["verb"] = verb; + m_request["parameter"] = parameter; + + m_init = true; + + return m_init; +} + +QByteArray CallMessage::serialize(QJsonDocument::JsonFormat format) +{ + 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/callmessage.h b/callmessage.h new file mode 100644 index 0000000..41098bc --- /dev/null +++ b/callmessage.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2020 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 CALLMESSAGE_H +#define CALLMESSAGE_H + +#include "message.h" + + +class CallMessage : public Message +{ + public: + CallMessage() = default; + + bool createRequest(QString api, QString verb, QJsonValue parameter = "None"); + + bool isEvent() override + { + return false; + } + + bool isReply() override + { + return false; + } + + void updateCallId(unsigned int id) override + { + m_request["callid"] = qint32(id); + } + + QByteArray serialize(QJsonDocument::JsonFormat format = QJsonDocument::Compact) override; + + private: + QMap<QString, QVariant> m_request; +}; + +#endif // CALLMESSAGE_H diff --git a/eventmessage.cpp b/eventmessage.cpp new file mode 100644 index 0000000..818830f --- /dev/null +++ b/eventmessage.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2020 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 "eventmessage.h" + +EventMessage::EventMessage(QJsonDocument content): Message() +{ + QJsonArray msg = content.array(); + if (!msg[2].isObject()) { + qWarning("Invalid appfw payload: no JSON object"); + return; + } + + //deserialize: + QJsonObject payload = msg[2].toObject(); + + auto data_iter = payload.find("data"); + m_event_data = data_iter.value().toObject(); + + auto event_iter = payload.find("event"); + auto event_string = event_iter.value().toString(); + if (event_string.isEmpty()) { + qWarning("Invalid appfw event message: empty event name"); + return; + } + QStringList event_strings = event_string.split(QRegExp("/")); + if (event_strings.size() != 2) { + qWarning("Invalid appfw event message: malformed event name"); + return; + } + m_event_api = event_strings[0]; + m_event_name = event_strings[1]; + m_init = true; +} + +QByteArray EventMessage::serialize(QJsonDocument::JsonFormat format) +{ + QJsonArray array; + array.append(static_cast<int>(MessageId::Event)); + array.append(0); //unused field + array.append(m_event_api + "/" + m_event_name); + array.append(m_event_data); + + QJsonDocument jdoc; + jdoc.setArray(array); + + return jdoc.toJson(format).data(); +} diff --git a/eventmessage.h b/eventmessage.h new file mode 100644 index 0000000..41bf7b6 --- /dev/null +++ b/eventmessage.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2020 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 EVENTMESSAGE_H +#define EVENTMESSAGE_H + +#include "message.h" + + +class EventMessage : public Message +{ + public: + explicit EventMessage(QJsonDocument data); + + inline QString eventApi() const + { + return m_event_api; + } + + inline QString eventName() const + { + return m_event_name; + } + + inline QJsonObject eventData() const + { + return m_event_data; + } + + bool isEvent() override + { + return true; + } + + bool isReply() override + { + return false; + } + + QByteArray serialize(QJsonDocument::JsonFormat format = QJsonDocument::Compact) override; + + private: + QString m_event_api, m_event_name; + QJsonObject m_event_data; +}; + +#endif // EVENTMESSAGE_H diff --git a/hvac/CMakeLists.txt b/hvac/CMakeLists.txt index 0ee635a..b5124cb 100644 --- a/hvac/CMakeLists.txt +++ b/hvac/CMakeLists.txt @@ -1,2 +1,2 @@ -add_headers(hvac.h hvacmessage.h) -add_sources(hvac.cpp hvacmessage.cpp) +add_headers(hvac.h) +add_sources(hvac.cpp) diff --git a/hvac/hvac.cpp b/hvac/hvac.cpp index f9e509b..23aef30 100644 --- a/hvac/hvac.cpp +++ b/hvac/hvac.cpp @@ -19,9 +19,9 @@ #include <QMimeDatabase> #include <QtQml/QQmlEngine> -#include "message.h" -#include "hvacmessage.h" -#include "responsemessage.h" +#include "callmessage.h" +#include "eventmessage.h" +#include "messagefactory.h" #include "messageengine.h" #include "hvac.h" @@ -45,13 +45,16 @@ HVAC::~HVAC() void HVAC::control(QString verb, QString field, int value) { - HVACMessage *tmsg = new HVACMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* hmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert(field, value); - tmsg->createRequest(verb, parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + hmsg->createRequest("hvac", verb, parameter); + m_mloop->sendMessage(std::move(msg)); } void HVAC::set_fanspeed(int speed) @@ -75,14 +78,19 @@ void HVAC::set_temp_right_zone(int temp) emit rightTemperatureChanged(temp); } -void HVAC::onMessageReceived(MessageType type, Message *msg) +void HVAC::onMessageReceived(std::shared_ptr<Message> msg) { - if (msg->isEvent() && type == MessageType::HVACEventMessage) { - HVACMessage *tmsg = qobject_cast<HVACMessage*>(msg); + if (!msg) + return; + + if (msg->isEvent()) { + std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg); + if (emsg->eventApi() != "hvac") + return; - if (tmsg->isLanguageEvent()) { + if (emsg->eventName() == "language") { // TODO: cannot be currently tested with identity service - QVariantMap data = tmsg->eventData().toVariantMap(); + QVariantMap data = emsg->eventData().toVariantMap(); emit languageChanged(data.value("language").toString()); } } diff --git a/hvac/hvac.h b/hvac/hvac.h index 47a9e08..81378e4 100644 --- a/hvac/hvac.h +++ b/hvac/hvac.h @@ -17,6 +17,7 @@ #ifndef HVAC_H #define HVAC_H +#include <memory> #include <QObject> #include <QJsonArray> #include <QtQml/QQmlContext> @@ -25,8 +26,6 @@ class MessageEngine; class Message; -enum class MessageType; - class HVAC : public QObject { Q_OBJECT @@ -62,7 +61,7 @@ class HVAC : public QObject void set_temp_right_zone(int temp); // slots - void onMessageReceived(MessageType, Message*); + void onMessageReceived(std::shared_ptr<Message>); }; #endif // HVAC_H diff --git a/map/CMakeLists.txt b/map/CMakeLists.txt index 2e58fbe..044f81a 100644 --- a/map/CMakeLists.txt +++ b/map/CMakeLists.txt @@ -1,2 +1,2 @@ -add_headers(map.h mapmessage.h) -add_sources(map.cpp mapmessage.cpp) +add_headers(map.h) +add_sources(map.cpp) diff --git a/map/map.cpp b/map/map.cpp index 666efa1..e7a4157 100644 --- a/map/map.cpp +++ b/map/map.cpp @@ -16,9 +16,10 @@ #include <QDebug> -#include "message.h" -#include "mapmessage.h" +#include "callmessage.h" +#include "eventmessage.h" #include "responsemessage.h" +#include "messagefactory.h" #include "messageengine.h" #include "map.h" @@ -39,77 +40,76 @@ Map::~Map() void Map::compose(QString recipient, QString message) { - MapMessage *tmsg = new MapMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + CallMessage* btmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("recipient", recipient); parameter.insert("message", message); - tmsg->createRequest("compose", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + btmsg->createRequest("bluetooth-map", "compose", parameter); + m_mloop->sendMessage(std::move(msg)); } void Map::message(QString handle) { - MapMessage *tmsg = new MapMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + CallMessage* btmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("handle", handle); - tmsg->createRequest("message", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + btmsg->createRequest("bluetooth-map", "message", parameter); + m_mloop->sendMessage(std::move(msg)); } void Map::listMessages(QString folder) { - MapMessage *tmsg = new MapMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + CallMessage* btmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("folder", folder); - tmsg->createRequest("list_messages", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + btmsg->createRequest("bluetooth-map", "list_messages", parameter); + m_mloop->sendMessage(std::move(msg)); } void Map::onConnected() { - MapMessage *tmsg = new MapMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + CallMessage* btmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("value", "notification"); - tmsg->createRequest("subscribe", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + btmsg->createRequest("bluetooth-map", "subscribe", parameter); + m_mloop->sendMessage(std::move(msg)); listMessages(); } void Map::onDisconnected() { - MapMessage *tmsg = new MapMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + CallMessage* btmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("value", "notification"); - tmsg->createRequest("unsubscribe", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + btmsg->createRequest("bluetooth-map", "unsubscribe", parameter); + m_mloop->sendMessage(std::move(msg)); } -void Map::onMessageReceived(MessageType type, Message *msg) +void Map::onMessageReceived(std::shared_ptr<Message> msg) { - if (type == MessageType::MapEventMessage) { - MapMessage *tmsg = qobject_cast<MapMessage*>(msg); + if (msg->isEvent()) { + std::shared_ptr<EventMessage> tmsg = std::static_pointer_cast<EventMessage>(msg); - if (tmsg->isNotificationEvent()) { + if (tmsg->eventApi() != "bluetooth-map") + return; + if (tmsg->eventName() == "notification") { emit notificationEvent(tmsg->eventData().toVariantMap()); } - } else if (msg->isReply() && type == MessageType::ResponseRequestMessage) { - ResponseMessage *tmsg = qobject_cast<ResponseMessage*>(msg); - - if (tmsg->requestVerb() == "list_messages") { - QString folder = tmsg->requestParameters().value("folder").toString(); - QVariantMap listing = tmsg->replyData().value("messages").toObject().toVariantMap(); + } else if (msg->isReply()) { + auto rmsg = std::static_pointer_cast<ResponseMessage>(msg); + if (rmsg->requestVerb() == "list_messages") { + QString folder = rmsg->requestParameters().value("folder").toString(); + QVariantMap listing = rmsg->replyData().value("messages").toObject().toVariantMap(); emit listMessagesResult(folder, listing); - } else if (tmsg->requestVerb() == "message") { - QString handle = tmsg->requestParameters().value("handle").toString(); - emit messageResult(handle, tmsg->replyData().toVariantMap()); + } else if (rmsg->requestVerb() == "message") { + QString handle = rmsg->requestParameters().value("handle").toString(); + emit messageResult(handle, rmsg->replyData().toVariantMap()); } } - - msg->deleteLater(); } @@ -17,6 +17,7 @@ #ifndef MAP_H #define MAP_H +#include <memory> #include <QObject> #include <QJsonArray> #include <QtQml/QQmlContext> @@ -25,8 +26,6 @@ class MessageEngine; class Message; -enum class MessageType; - class Map : public QObject { Q_OBJECT @@ -50,7 +49,7 @@ class Map : public QObject // slots void onConnected(); void onDisconnected(); - void onMessageReceived(MessageType, Message*); + void onMessageReceived(std::shared_ptr<Message>); }; #endif // MAP_H diff --git a/mediaplayer/CMakeLists.txt b/mediaplayer/CMakeLists.txt index fd7e3f3..75bbca1 100644 --- a/mediaplayer/CMakeLists.txt +++ b/mediaplayer/CMakeLists.txt @@ -1,2 +1,2 @@ -add_headers(mediaplayer.h mediaplayermessage.h) -add_sources(mediaplayer.cpp mediaplayermessage.cpp) +add_headers(mediaplayer.h) +add_sources(mediaplayer.cpp) diff --git a/mediaplayer/mediaplayer.cpp b/mediaplayer/mediaplayer.cpp index 69b2dea..e723d5d 100644 --- a/mediaplayer/mediaplayer.cpp +++ b/mediaplayer/mediaplayer.cpp @@ -16,9 +16,10 @@ #include <QDebug> -#include "message.h" -#include "mediaplayermessage.h" +#include "callmessage.h" +#include "eventmessage.h" #include "messageengine.h" +#include "messagefactory.h" #include "mediaplayer.h" @@ -89,13 +90,15 @@ void Mediaplayer::updatePlaylist(QVariantMap playlist) void Mediaplayer::control(QString control, QJsonObject parameter) { - MediaplayerMessage *tmsg = new MediaplayerMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + CallMessage* mpmsg = static_cast<CallMessage*>(msg.get()); parameter.insert("value", control); - tmsg->createRequest("controls", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + mpmsg->createRequest("mediaplayer", "controls", parameter); + m_mloop->sendMessage(std::move(msg)); } @@ -186,44 +189,54 @@ void Mediaplayer::loop(QString state) void Mediaplayer::onConnected() { QStringListIterator eventIterator(events); - MediaplayerMessage *tmsg; while (eventIterator.hasNext()) { - tmsg = new MediaplayerMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* mpmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("value", eventIterator.next()); - tmsg->createRequest("subscribe", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + mpmsg->createRequest("mediaplayer", "subscribe", parameter); + m_mloop->sendMessage(std::move(msg)); } } void Mediaplayer::onDisconnected() { QStringListIterator eventIterator(events); - MediaplayerMessage *tmsg; while (eventIterator.hasNext()) { - tmsg = new MediaplayerMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* mpmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("value", eventIterator.next()); - tmsg->createRequest("unsubscribe", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + mpmsg->createRequest("mediaplayer", "unsubscribe", parameter); + m_mloop->sendMessage(std::move(msg)); } } -void Mediaplayer::onMessageReceived(MessageType type, Message *message) +void Mediaplayer::onMessageReceived(std::shared_ptr<Message> msg) { - if (type == MessageType::MediaplayerEventMessage) { - MediaplayerMessage *tmsg = - qobject_cast<MediaplayerMessage*>(message); - - if (tmsg->isEvent()) { - if (tmsg->isPlaylistEvent()) { - updatePlaylist(tmsg->eventData().toVariantMap()); - } else if (tmsg->isMetadataEvent()) { - QVariantMap map = tmsg->eventData().toVariantMap(); + if (!msg) + return; + + if (msg->isEvent()){ + std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg); + QString ename = emsg->eventName(); + QString eapi = emsg->eventApi(); + QJsonObject data = emsg->eventData(); + if (eapi != "mediaplayer") + return; + + if (ename == "playlist") { + updatePlaylist(data.toVariantMap()); + } else if (ename == "metadata") { + QVariantMap map = data.toVariantMap(); if (map.contains("track")) { QVariantMap track = map.value("track").toMap(); @@ -247,6 +260,4 @@ void Mediaplayer::onMessageReceived(MessageType type, Message *message) emit metadataChanged(map); } } - } - message->deleteLater(); } diff --git a/mediaplayer/mediaplayer.h b/mediaplayer/mediaplayer.h index f3930f4..374ab06 100644 --- a/mediaplayer/mediaplayer.h +++ b/mediaplayer/mediaplayer.h @@ -17,6 +17,7 @@ #ifndef MEDIAPLAYER_H #define MEDIAPLAYER_H +#include <memory> #include <QObject> #include <QtQml/QQmlContext> #include <QtQml/QQmlListProperty> @@ -24,8 +25,6 @@ class MessageEngine; class Message; -enum class MessageType; - class Playlist : public QObject { Q_OBJECT @@ -106,7 +105,7 @@ class Mediaplayer : public QObject void onConnected(); void onDisconnected(); - void onMessageReceived(MessageType, Message*); + void onMessageReceived(std::shared_ptr<Message>); const QStringList events { "playlist", diff --git a/message.cpp b/message.cpp index 3cd4bb9..1865f14 100644 --- a/message.cpp +++ b/message.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Konsulko Group + * Copyright (C) 2017-2020 Konsulko Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,59 +17,25 @@ #include <QDebug> #include <QJsonArray> #include <QJsonDocument> -#include <QJsonObject> -#include <QJsonValue> +#include <QWebSocket> #include "message.h" -Message::Message() - : m_init(false), m_event(false), m_reply(false) -{ -} - -bool Message::createRequest(QString api, QString verb, QJsonValue parameter) -{ - if (!m_request.isEmpty()){ - qWarning("Message instance has already been used. Cannot send another request."); - return false; - } - - m_request["msgid"] = Call; - m_request["callid"] = 0; - m_request["api"] = api; - m_request["verb"] = verb; - m_request["parameter"] = parameter; - - m_init = true; - - return true; -} - -bool Message::fromJson(QByteArray jsonData) +MessageId Message::isValid(QJsonDocument candidate) { - QJsonDocument jdoc(QJsonDocument::fromJson(jsonData)); - - if (jdoc.isNull()) { - qWarning("Imported invalid JSON: empty appfw message"); - return false; - } - - return Message::fromJDoc(jdoc); -} + MessageId id = MessageId::Invalid; -bool Message::fromJDoc(QJsonDocument jdoc) -{ // Validate message is array - if (!jdoc.isArray()) { + if (!candidate.isArray()) { qWarning("Invalid appfw message: not an array"); - return false; + return id; } - QJsonArray msg = jdoc.array(); + QJsonArray msg = candidate.array(); // Validate array is proper length if ((msg.size() < 3) || (msg.size() > 4)) { qWarning("Invalid appfw message: invalid array size"); - return false; + return id; } // Validate msgid type @@ -78,75 +44,36 @@ bool Message::fromJDoc(QJsonDocument jdoc) msgid = msg[0].toDouble(); } else { qWarning("Invalid appfw message: invalid msgid type"); - return false; + return id; } // Validate msgid element - if ((msgid < Call) || (msgid > Event)) { - qWarning("Invalid appfw message: msgid out of range"); - return false; - } - - // Validate that the payload has a request object - QJsonObject payload; - if (msg[2].isObject()) { - payload = msg[2].toObject(); - } else { - qWarning("Invalid appfw payload: no JSON object"); - return false; - } - - if ((msgid == RetOk) || (msgid == RetErr)) { - auto request_iter = payload.find("request"); - auto request = request_iter.value().toObject(); - if (request.empty()) { - qWarning("Invalid appfw reply message: empty request data"); - return false; - } - auto status_iter = request.find("status"); - auto info_iter = request.find("info"); - auto response_iter = payload.find("response"); - auto response = response_iter.value().toObject(); - m_reply_status = status_iter.value().toString(); - m_reply_info = info_iter.value().toString(); - m_reply_data = response; - m_reply = true; - } else if (msgid == Event) { - // If event, save data object - auto data_iter = payload.find("data"); - m_event_data = data_iter.value().toObject(); + if ((msgid >= static_cast<double>(MessageId::Call)) && (msgid <= static_cast<double>(MessageId::Event))) + id = static_cast<MessageId>(msgid); - auto event_iter = payload.find("event"); - auto event_string = event_iter.value().toString(); - if (event_string.isEmpty()) { - qWarning("Invalid appfw event message: empty event name"); - return false; - } - QStringList event_strings = event_string.split(QRegExp("/")); - if (event_strings.size() != 2) { - qWarning("Invalid appfw event message: malformed event name"); - return false; - } - m_event_api = event_strings[0]; - m_event_name = event_strings[1]; - m_event = true; - } - - m_jdoc = jdoc; - m_init = true; - return m_init; + return id; } -QByteArray Message::toJson(QJsonDocument::JsonFormat format) +Message::Message() + : m_init(false) { - 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); +QByteArray Message::serialize(QJsonDocument::JsonFormat format) +{ + QByteArray dummy; + return dummy; + } - return jdoc.toJson(format).data(); +QByteArray Message::send(QWebSocket& transport, unsigned int id) +{ + QByteArray blob; + qint64 size = 0; + updateCallId(id); + if (m_init) + blob = serialize().data(); + if (!blob.isEmpty()) + size = transport.sendTextMessage(blob); + + return blob; } @@ -23,103 +23,44 @@ #include <QJsonDocument> #include <QJsonObject> -enum MessageId { +enum class MessageId { + Invalid = 0, Call = 2, RetOk = 3, RetErr = 4, Event = 5, }; -enum class MessageType { - GenericMessage, - ResponseRequestMessage, - TelephonyEventMessage, - WeatherEventMessage, - MediaplayerEventMessage, - NetworkEventMessage, - BluetoothEventMessage, - PbapEventMessage, - RadioEventMessage, - MapEventMessage, - NavigationEventMessage, - VoiceEventMessage, - SignalComposerEventMessage, - GuiMetadataCapabilityEventMessage, - HVACEventMessage, -}; +class QWebSocket; -class Message : public QObject +class Message { - Q_OBJECT - Q_ENUM(MessageId) - public: Message(); + void setAdditionalData(QByteArray data) {}; + QByteArray send(QWebSocket& transport, unsigned int callid); - bool fromJson(QByteArray jsonData); - virtual bool fromJDoc(QJsonDocument jdocData); - QByteArray toJson(QJsonDocument::JsonFormat format = QJsonDocument::Compact); - bool createRequest(QString api, QString verb, QJsonValue parameter = "None"); - inline QString eventApi() const - { - return m_event_api; - } - - inline QString eventName() const - { - return m_event_name; - } - - inline QJsonObject eventData() const + inline bool isComplete() const { - return m_event_data; - } - - inline QString replyStatus() const - { - return m_reply_status; - } - - inline QString replyInfo() const - { - return m_reply_info; - } - - inline QJsonObject replyData() const - { - return m_reply_data; - } - - inline bool isEvent() const - { - return m_event; - } - - inline bool isReply() const - { - return m_reply; + return m_init; } - inline bool isValid() const + virtual bool getCallId(unsigned int *id) const { - return m_init; + return false; } - inline void setCallId(qint32 callId) { - m_request["callid"] = callId; - } + static MessageId isValid(QJsonDocument ); - inline QMap<QString, QVariant> requestData() const - { - return m_request; - } + virtual bool isEvent() = 0; + virtual bool isReply() = 0; protected: - bool m_event, m_init, m_reply; - QString m_event_api, m_event_name, m_reply_info, m_reply_status, m_reply_uuid; - QMap<QString, QVariant> m_request; + virtual void updateCallId(unsigned int id) {}; + virtual QByteArray serialize(QJsonDocument::JsonFormat format = QJsonDocument::Compact); + + bool m_init; QJsonDocument m_jdoc; - QJsonObject m_event_data, m_reply_data; }; #endif // MESSAGE_H diff --git a/messageengine.cpp b/messageengine.cpp index 6f31d0f..2633545 100644 --- a/messageengine.cpp +++ b/messageengine.cpp @@ -14,24 +14,13 @@ * limitations under the License. */ +#include <QJsonArray> +#include <QDebug> + #include "message.h" +#include "messagefactory.h" #include "messageengine.h" -#include "bluetoothmessage.h" -#include "guimetadatamessage.h" -#include "hvacmessage.h" -#include "mapmessage.h" -#include "mediaplayermessage.h" -#include "navigationmessage.h" -#include "networkmessage.h" -#include "pbapmessage.h" -#include "radiomessage.h" -#include "responsemessage.h" -#include "signalcomposermessage.h" -#include "telephonymessage.h" -#include "weathermessage.h" -#include "voicemessage.h" -#include <QJsonArray> MessageEngine::MessageEngine(const QUrl &url, QObject *parent) : QObject(parent), @@ -44,31 +33,17 @@ 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) +bool MessageEngine::sendMessage(std::unique_ptr<Message> msg) { - if (!message->isValid()) + if (!msg) return false; - auto callid = requestCallId(); - message->setCallId(callid); - - QByteArray data = message->toJson().data(); - qint64 size = m_websocket.sendTextMessage(data); - if (size == 0) + unsigned int callid = m_callid++; + QByteArray forkeeps = msg->send(m_websocket, callid); + if (forkeeps.isEmpty()) return false; - m_calls.insert(callid, data); + m_calls.insert(callid, forkeeps); return true; } @@ -94,83 +69,20 @@ void MessageEngine::onTextMessageReceived(QString jsonStr) return; } - QJsonArray msg = jdoc.array(); - int msgid = msg[0].toInt(); + MessageId id = Message::isValid(jdoc); + if (id == MessageId::Invalid) { + qWarning() << "Received unknown message, discarding"; + return; + } - Message *message; - MessageType type; + std::shared_ptr<Message> message = MessageFactory::getInstance().createInboundMessage(id, jdoc); - switch (msgid) { - case RetOk: - case RetErr: { - auto callid = msg[1].toString().toInt(); - message = new ResponseMessage(m_calls[callid]); - type = MessageType::ResponseRequestMessage; + unsigned int callid; + if (message->isReply() && message->getCallId(&callid)) { + message->setAdditionalData(m_calls[callid]); m_calls.remove(callid); - break; - } - case Event: { - QStringList api_str_list = msg[1].toString().split(QRegExp("/")); - QString api = api_str_list[0].toLower(); - - // 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 = MessageType::BluetoothEventMessage; - } else if (api == "bluetooth-pbap") { - message = new PbapMessage; - type = MessageType::PbapEventMessage; - } else if (api == "telephony") { - message = new TelephonyMessage; - type = MessageType::TelephonyEventMessage; - } else if (api == "weather") { - message = new WeatherMessage; - type = MessageType::WeatherEventMessage; - } else if (api == "mediaplayer") { - message = new MediaplayerMessage; - type = MessageType::MediaplayerEventMessage; - } else if (api == "navigation") { - message = new NavigationMessage; - type = MessageType::NavigationEventMessage; - } else if (api == "network-manager") { - message = new NetworkMessage; - type = MessageType::NetworkEventMessage; - } else if (api == "radio") { - message = new RadioMessage; - type = MessageType::RadioEventMessage; - } else if (api == "bluetooth-map") { - message = new MapMessage; - type = MessageType::MapEventMessage; - } else if (api == "vshl-core" ) { - message = new VoiceMessage; - type = MessageType::VoiceEventMessage; - } else if (api == "vshl-capabilities" ) { - // NOTE: Will need to look at event name to differentiate - // capabilities if more support (e.g. navigation or - // local media control) is added. - message = new GuiMetadataCapabilityMessage; - type = MessageType::GuiMetadataCapabilityEventMessage; - } else if (api == "signal-composer") { - message = new SignalComposerMessage; - type = MessageType::SignalComposerEventMessage; - } else if (api == "hvac") { - message = new HVACMessage; - type = MessageType::HVACEventMessage; - } else { - message = new Message; - type = MessageType::GenericMessage; - } - break; - } - default: - break; - } - - if (message->fromJDoc(jdoc) == false) { - delete message; - return; } - emit messageReceived(type, message); + if (message->isComplete()) + emit messageReceived(message); } diff --git a/messageengine.h b/messageengine.h index 6b2233f..b682ec5 100644 --- a/messageengine.h +++ b/messageengine.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Konsulko Group + * Copyright (C) 2017-2020 Konsulko Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,8 @@ #ifndef MESSAGEENGINE_H #define MESSAGEENGINE_H -#include <QMutex> -#include <QThread> +#include <memory> +#include <atomic> #include <QUrl> #include <QWebSocket> @@ -29,13 +29,12 @@ class MessageEngine : public QObject Q_OBJECT public: explicit MessageEngine(const QUrl &url, QObject *parent = Q_NULLPTR); - bool sendMessage(Message *message); - unsigned int requestCallId(); + bool sendMessage(std::unique_ptr<Message> message); Q_SIGNALS: void disconnected(); void connected(); - void messageReceived(MessageType type, Message *message); + void messageReceived(std::shared_ptr<Message> message); private Q_SLOTS: void onConnected(); @@ -46,8 +45,7 @@ class MessageEngine : public QObject QWebSocket m_websocket; QMap<qint32, QByteArray> m_calls; QUrl m_url; - QMutex m_mutex; - unsigned int m_callid; + std::atomic<unsigned int> m_callid; }; #endif // MESSAGEENGINE_H diff --git a/messagefactory.cpp b/messagefactory.cpp new file mode 100644 index 0000000..6740e25 --- /dev/null +++ b/messagefactory.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 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 "messagefactory.h" +#include "message.h" +#include "responsemessage.h" +#include "eventmessage.h" +#include "callmessage.h" + +std::unique_ptr<Message> MessageFactory::createInboundMessage(MessageId id, QJsonDocument data) +{ + std::unique_ptr<Message> msg(nullptr); + if ((id == MessageId::RetOk) || (id == MessageId::RetErr)) + msg.reset(new ResponseMessage(data)); + else if (id == MessageId::Event) + msg.reset(new EventMessage(data)); + return msg; +} + +std::unique_ptr<Message> MessageFactory::createOutboundMessage(MessageId id) +{ + std::unique_ptr<Message> msg(nullptr); + if (id == MessageId::Call) + msg.reset(new CallMessage()); + return msg; +} diff --git a/messagefactory.h b/messagefactory.h new file mode 100644 index 0000000..f826483 --- /dev/null +++ b/messagefactory.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 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 MESSAGEFACTORY_H +#define MESSAGEFACTORY_H + +#include <memory> +#include <QJsonDocument> + +class Message; +enum class MessageId; + +class MessageFactory { + public: + static MessageFactory& getInstance() { + static MessageFactory instance; + return instance; + } + std::unique_ptr<Message> createInboundMessage(MessageId id, QJsonDocument content); + std::unique_ptr<Message> createOutboundMessage(MessageId); + MessageFactory(MessageFactory const&) = delete; + void operator=(MessageFactory const&) = delete; + + private: + MessageFactory() = default; + ~MessageFactory() = default; +}; + +#endif // MESSAGEFACTORY_H diff --git a/navigation/CMakeLists.txt b/navigation/CMakeLists.txt index 9bea511..ec76041 100644 --- a/navigation/CMakeLists.txt +++ b/navigation/CMakeLists.txt @@ -1,2 +1,2 @@ -add_headers(navigation.h navigationmessage.h) -add_sources(navigation.cpp navigationmessage.cpp) +add_headers(navigation.h) +add_sources(navigation.cpp) diff --git a/navigation/navigation.cpp b/navigation/navigation.cpp index ce6b91d..e0078c2 100644 --- a/navigation/navigation.cpp +++ b/navigation/navigation.cpp @@ -16,9 +16,9 @@ #include <QDebug> -#include "message.h" -#include "navigationmessage.h" -#include "responsemessage.h" +#include "callmessage.h" +#include "eventmessage.h" +#include "messagefactory.h" #include "messageengine.h" #include "navigation.h" @@ -40,21 +40,28 @@ Navigation::~Navigation() void Navigation::sendWaypoint(double lat, double lon) { - NavigationMessage *nmsg = new NavigationMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter, point; QJsonArray points; point.insert("latitude", lat); point.insert("longitude", lon); points.append(point); parameter.insert("points", points); - nmsg->createRequest("broadcast_waypoints", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("navigation", "broadcast_waypoints", parameter); + m_mloop->sendMessage(std::move(msg)); } void Navigation::broadcastPosition(double lat, double lon, double drc, double dst) { - NavigationMessage *nmsg = new NavigationMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("position", "car"); @@ -63,14 +70,17 @@ void Navigation::broadcastPosition(double lat, double lon, double drc, double ds parameter.insert("direction", drc); parameter.insert("distance", dst); - nmsg->createRequest("broadcast_position", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("navigation", "broadcast_position", parameter); + m_mloop->sendMessage(std::move(msg)); } void Navigation::broadcastRouteInfo(double lat, double lon, double route_lat, double route_lon) { - NavigationMessage *nmsg = new NavigationMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("position", "route"); @@ -79,66 +89,75 @@ void Navigation::broadcastRouteInfo(double lat, double lon, double route_lat, do parameter.insert("route_latitude", route_lat); parameter.insert("route_longitude", route_lon); - nmsg->createRequest("broadcast_position", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("navigation", "broadcast_position", parameter); + m_mloop->sendMessage(std::move(msg)); } void Navigation::broadcastStatus(QString state) { - NavigationMessage *nmsg = new NavigationMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("state", state); - nmsg->createRequest("broadcast_status", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("navigation", "broadcast_status", parameter); + m_mloop->sendMessage(std::move(msg)); } void Navigation::onConnected() { QStringListIterator eventIterator(events); - NavigationMessage *nmsg; while (eventIterator.hasNext()) { - nmsg = new NavigationMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("value", eventIterator.next()); - nmsg->createRequest("subscribe", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("navigation", "subscribe", parameter); + m_mloop->sendMessage(std::move(msg)); } } void Navigation::onDisconnected() { QStringListIterator eventIterator(events); - NavigationMessage *nmsg; while (eventIterator.hasNext()) { - nmsg = new NavigationMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("value", eventIterator.next()); - nmsg->createRequest("unsubscribe", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("navigation", "unsubscribe", parameter); + m_mloop->sendMessage(std::move(msg)); } } -void Navigation::onMessageReceived(MessageType type, Message *msg) +void Navigation::onMessageReceived(std::shared_ptr<Message> msg) { - if (type == MessageType::NavigationEventMessage) { - NavigationMessage *tmsg = qobject_cast<NavigationMessage*>(msg); + if (!msg) + return; - if (tmsg->isPositionEvent()) { - emit positionEvent(tmsg->eventData().toVariantMap()); + if (msg->isEvent()) { + std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg); + if (emsg->eventApi() != "navigation") + return; + + if (emsg->eventName() == "position") { + emit positionEvent(emsg->eventData().toVariantMap()); } - if (tmsg->isStatusEvent()) { - emit statusEvent(tmsg->eventData().toVariantMap()); + else if (emsg->eventName() == "status") { + emit statusEvent(emsg->eventData().toVariantMap()); } - if (tmsg->isWaypointsEvent()) { - emit waypointsEvent(tmsg->eventData().toVariantMap()); + else if (emsg->eventName() == "waypoints") { + emit waypointsEvent(emsg->eventData().toVariantMap()); } } - - msg->deleteLater(); } diff --git a/navigation/navigation.h b/navigation/navigation.h index c407d0f..87e5636 100644 --- a/navigation/navigation.h +++ b/navigation/navigation.h @@ -17,6 +17,7 @@ #ifndef NAVIGATION_H #define NAVIGATION_H +#include <memory> #include <QObject> #include <QJsonArray> #include <QtQml/QQmlListProperty> @@ -24,8 +25,6 @@ class MessageEngine; class Message; -enum class MessageType; - class Navigation : public QObject { Q_OBJECT @@ -50,7 +49,7 @@ class Navigation : public QObject MessageEngine *m_mloop; // slots - void onMessageReceived(MessageType, Message*); + void onMessageReceived(std::shared_ptr<Message> msg); void onConnected(); void onDisconnected(); diff --git a/network/CMakeLists.txt b/network/CMakeLists.txt index e6d93bd..fcf21ac 100644 --- a/network/CMakeLists.txt +++ b/network/CMakeLists.txt @@ -1,8 +1,8 @@ -add_headers(network.h networkmessage.h +add_headers(network.h networkadapter.h wifiadapter.h wiredadapter.h wifinetworkmodel.h wirednetworkmodel.h abstractnetworkmodel.h connectionprofile.h) -add_sources(network.cpp networkmessage.cpp +add_sources(network.cpp wifiadapter.cpp wiredadapter.cpp wifinetworkmodel.cpp wirednetworkmodel.cpp abstractnetworkmodel.cpp connectionprofile.cpp) diff --git a/network/network.cpp b/network/network.cpp index b858206..2472279 100644 --- a/network/network.cpp +++ b/network/network.cpp @@ -17,9 +17,10 @@ #include <QDebug> #include <QtQml/QQmlEngine> -#include "message.h" -#include "networkmessage.h" +#include "callmessage.h" +#include "eventmessage.h" #include "responsemessage.h" +#include "messagefactory.h" #include "messageengine.h" #include "networkadapter.h" #include "network.h" @@ -48,38 +49,47 @@ Network::~Network() void Network::connect(QString service) { - NetworkMessage *nmsg = new NetworkMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("service", service); - nmsg->createRequest("connect_service", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("network-manager", "connect_service", parameter); + m_mloop->sendMessage(std::move(msg)); } void Network::disconnect(QString service) { - NetworkMessage *nmsg = new NetworkMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("service", service); - nmsg->createRequest("disconnect_service", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("network-manager", "disconnect_service", parameter); + m_mloop->sendMessage(std::move(msg)); } void Network::remove(QString service) { - NetworkMessage *nmsg = new NetworkMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("service", service); - nmsg->createRequest("remove_service", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("network-manager", "remove_service", parameter); + m_mloop->sendMessage(std::move(msg)); } void Network::power(bool on, QString type) @@ -92,21 +102,28 @@ void Network::power(bool on, QString type) void Network::input(int id, QString passphrase) { - NetworkMessage *nmsg = new NetworkMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter, fields; parameter.insert("id", id); fields.insert("passphrase", passphrase); parameter.insert("fields", fields); - nmsg->createRequest("agent_response", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("network-manager", "agent_response", parameter); + m_mloop->sendMessage(std::move(msg)); } void Network::configureAddress(QString service, QVariantList paramlist) { - NetworkMessage *nmsg = new NetworkMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter, type, properties; QJsonArray values = QJsonArray::fromVariantList(paramlist); @@ -123,14 +140,17 @@ void Network::configureAddress(QString service, QVariantList paramlist) parameter.insert("properties", type); parameter.insert("service", service); - nmsg->createRequest("set_property", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("network-manager", "set_property", parameter); + m_mloop->sendMessage(std::move(msg)); } void Network::configureNameServer(QString service, QVariantList paramlist) { - NetworkMessage *nmsg = new NetworkMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter, properties; QJsonArray values = QJsonArray::fromVariantList(paramlist); @@ -146,19 +166,21 @@ void Network::configureNameServer(QString service, QVariantList paramlist) parameter.insert("properties", properties); parameter.insert("service", service); - nmsg->createRequest("set_property", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("network-manager", "set_property", parameter); + m_mloop->sendMessage(std::move(msg)); } void Network::getServices() { - NetworkMessage *nmsg = new NetworkMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; - nmsg->createRequest("services", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("network-manager", "services", parameter); + m_mloop->sendMessage(std::move(msg)); } AdapterIf* Network::findAdapter(QString type) @@ -208,38 +230,44 @@ void Network::addServices(QJsonArray services) void Network::scanServices(QString type) { - NetworkMessage *nmsg = new NetworkMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("technology", type); - nmsg->createRequest("scan_services", parameter); - m_mloop->sendMessage(nmsg); - - delete nmsg; + nmsg->createRequest("network-manager", "scan_services", parameter); + m_mloop->sendMessage(std::move(msg)); } void Network::disableTechnology(QString type) { - NetworkMessage *nmsg = new NetworkMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("technology", type); - nmsg->createRequest("disable_technology", parameter); - m_mloop->sendMessage(nmsg); - - delete nmsg; + nmsg->createRequest("network-manager", "disable_technology", parameter); + m_mloop->sendMessage(std::move(msg)); } void Network::enableTechnology(QString type) { - NetworkMessage *nmsg = new NetworkMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("technology", type); - nmsg->createRequest("enable_technology", parameter); - m_mloop->sendMessage(nmsg); - - delete nmsg; + nmsg->createRequest("network-manager", "enable_technology", parameter); + m_mloop->sendMessage(std::move(msg)); } void Network::parseTechnologies(QJsonArray technologies) @@ -257,28 +285,38 @@ void Network::parseTechnologies(QJsonArray technologies) void Network::getTechnologies() { - NetworkMessage *nmsg = new NetworkMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; - nmsg->createRequest("technologies", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("network-manager", "technologies", parameter); + m_mloop->sendMessage(std::move(msg)); } -void Network::processEvent(NetworkMessage *nmsg) +void Network::processEvent(std::shared_ptr<Message> msg) { - if (nmsg->eventName() == "agent") { - QJsonObject agent = nmsg->eventData(); - QJsonObject fields = agent.value("fields").toObject(); + std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg); + QString ename = emsg->eventName(); + QString eapi = emsg->eventApi(); + QJsonObject data = emsg->eventData(); + + if (eapi != "network-manager") + return; + + if (ename == "agent") { + QJsonObject fields = data.value("fields").toObject(); QJsonObject passphrase = fields.value("passphrase").toObject(); QString type = passphrase.value("type").toString(); QString reqmt = passphrase.value("requirement").toString(); if (((type == "psk") || (type == "wep")) && (reqmt == "mandatory")) { - int id = agent.value("id").toInt(); + int id = data.value("id").toInt(); emit inputRequest(id); } - } else if (nmsg->eventName() == "services") { - QJsonArray services = nmsg->eventData().value("values").toArray(); + } else if (ename == "services") { + QJsonArray services = data.value("values").toArray(); for (auto value : services) { QJsonObject service = value.toObject(); QString action = service.value("action").toString(); @@ -288,54 +326,59 @@ void Network::processEvent(NetworkMessage *nmsg) removeService(service); } } - } else if (nmsg->eventName() == "service_properties") { - updateServiceProperties(nmsg->eventData()); - } else if (nmsg->eventName() == "technology_properties") { - QJsonObject technology = nmsg->eventData(); - QJsonObject properties = technology.value("properties").toObject(); - QString type = technology.value("technology").toString(); + } else if (ename == "service_properties") { + updateServiceProperties(data); + } else if (ename == "technology_properties") { + QJsonObject properties = data.value("properties").toObject(); + QString type = data.value("technology").toString(); AdapterIf* adapter = findAdapter(type); if (adapter) adapter->updateStatus(properties); } } -void Network::processReply(ResponseMessage *rmsg) +void Network::processReply(std::shared_ptr<Message> msg) { - if (rmsg->requestVerb() == "services") { - addServices(rmsg->replyData().value("values").toArray()); - } else if (rmsg->requestVerb() == "technologies") { - parseTechnologies(rmsg->replyData().value("values").toArray()); - } else if (rmsg->requestVerb() == "connect_service") { + std::shared_ptr<ResponseMessage> rmsg = std::static_pointer_cast<ResponseMessage>(msg); + QString verb = rmsg->requestVerb(); + QJsonObject data = rmsg->replyData(); + + if (verb == "services") { + addServices(data.value("values").toArray()); + } else if (verb == "technologies") { + parseTechnologies(data.value("values").toArray()); + } else if (verb == "connect_service") { if (rmsg->replyStatus() == "failed" && rmsg->replyInfo().contains("invalid-key")) { - emit invalidPassphrase(rmsg->requestData()["parameter"].toMap()["service"].toString()); + emit invalidPassphrase(rmsg->requestParameters()["service"].toString()); } } } -void Network::onMessageReceived(MessageType type, Message *msg) +void Network::onMessageReceived(std::shared_ptr<Message> msg) { - if (msg->isEvent() && (type == MessageType::NetworkEventMessage)) { - processEvent(qobject_cast<NetworkMessage*>(msg)); - } else if (msg->isReply() && (type == MessageType::ResponseRequestMessage)) { - processReply(qobject_cast<ResponseMessage*>(msg)); - } + if (!msg) + return; - msg->deleteLater(); + if (msg->isEvent()) + processEvent(msg); + else if (msg->isReply()) + processReply(msg); } void Network::onConnected() { QStringListIterator eventIterator(events); - NetworkMessage *nmsg; while (eventIterator.hasNext()) { - nmsg = new NetworkMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("value", eventIterator.next()); - nmsg->createRequest("subscribe", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("network-manager", "subscribe", parameter); + m_mloop->sendMessage(std::move(msg)); } getTechnologies(); @@ -344,15 +387,16 @@ void Network::onConnected() void Network::onDisconnected() { QStringListIterator eventIterator(events); - NetworkMessage *nmsg; while (eventIterator.hasNext()) { - nmsg = new NetworkMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + CallMessage *nmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("value", eventIterator.next()); - nmsg->createRequest("unsubscribe", parameter); - m_mloop->sendMessage(nmsg); - delete nmsg; + nmsg->createRequest("network-manager", "unsubscribe", parameter); + m_mloop->sendMessage(std::move(msg)); } getTechnologies(); diff --git a/network/network.h b/network/network.h index ebaeb6e..b40b432 100644 --- a/network/network.h +++ b/network/network.h @@ -17,6 +17,7 @@ #ifndef NETWORK_H #define NETWORK_H +#include <memory> #include <QObject> #include <QJsonArray> #include <QtQml/QQmlContext> @@ -27,10 +28,6 @@ class MessageEngine; class Message; -class NetworkMessage; -class ResponseMessage; - -enum class MessageType; class Network : public QObject { @@ -72,11 +69,11 @@ class Network : public QObject void enableTechnology(QString type); void parseTechnologies(QJsonArray technologies); void getTechnologies(); - void processEvent(NetworkMessage *nmsg); - void processReply(ResponseMessage *rmsg); + void processEvent(std::shared_ptr<Message> msg); + void processReply(std::shared_ptr<Message> msg); // slots - void onMessageReceived(MessageType, Message*); + void onMessageReceived(std::shared_ptr<Message>); void onConnected(); void onDisconnected(); diff --git a/pbap/CMakeLists.txt b/pbap/CMakeLists.txt index 99edd7d..441280f 100644 --- a/pbap/CMakeLists.txt +++ b/pbap/CMakeLists.txt @@ -1,2 +1,2 @@ -add_headers(pbap.h pbapmessage.h) -add_sources(pbap.cpp pbapmessage.cpp) +add_headers(pbap.h) +add_sources(pbap.cpp) diff --git a/pbap/pbap.cpp b/pbap/pbap.cpp index 7b7829f..a0b84f4 100644 --- a/pbap/pbap.cpp +++ b/pbap/pbap.cpp @@ -19,9 +19,10 @@ #include <QMimeDatabase> #include <QtQml/QQmlEngine> -#include "message.h" -#include "pbapmessage.h" +#include "callmessage.h" +#include "eventmessage.h" #include "responsemessage.h" +#include "messagefactory.h" #include "messageengine.h" #include "pbap.h" @@ -102,50 +103,62 @@ Pbap::~Pbap() void Pbap::importContacts(int max_entries) { - PbapMessage *tmsg = new PbapMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* pmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; - tmsg->createRequest("import", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + pmsg->createRequest("bluetooth-pbap", "import", parameter); + m_mloop->sendMessage(std::move(msg)); } void Pbap::refreshContacts(int max_entries) { - PbapMessage *tmsg = new PbapMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* pmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; - tmsg->createRequest("contacts", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + pmsg->createRequest("bluetooth-pbap", "contacts", parameter); + m_mloop->sendMessage(std::move(msg)); } void Pbap::refreshCalls(int max_entries) { - PbapMessage *tmsg = new PbapMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* pmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("list", "cch"); if (max_entries >= 0) parameter.insert("max_entries", max_entries); - tmsg->createRequest("history", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + pmsg->createRequest("bluetooth-pbap", "history", parameter); + m_mloop->sendMessage(std::move(msg)); } void Pbap::search(QString number) { - PbapMessage *tmsg = new PbapMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* pmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; if (!number.isEmpty()) parameter.insert("number", number); parameter.insert("max_entries", 1); - tmsg->createRequest("search", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + pmsg->createRequest("bluetooth-pbap", "search", parameter); + m_mloop->sendMessage(std::move(msg)); } bool compareContactPtr(QObject *a, QObject *b) @@ -253,55 +266,71 @@ void Pbap::sendSearchResults(QJsonArray results) void Pbap::onConnected() { QStringListIterator eventIterator(events); - PbapMessage *tmsg; while (eventIterator.hasNext()) { - tmsg = new PbapMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* pmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("value", eventIterator.next()); - tmsg->createRequest("subscribe", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + pmsg->createRequest("bluetooth-pbap", "subscribe", parameter); + m_mloop->sendMessage(std::move(msg)); } } void Pbap::onDisconnected() { QStringListIterator eventIterator(events); - PbapMessage *tmsg; while (eventIterator.hasNext()) { - tmsg = new PbapMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* pmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("value", eventIterator.next()); - tmsg->createRequest("unsubscribe", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + pmsg->createRequest("bluetooth-pbap", "unsubscribe", parameter); + m_mloop->sendMessage(std::move(msg)); } } -void Pbap::onMessageReceived(MessageType type, Message *msg) +void Pbap::onMessageReceived(std::shared_ptr<Message> msg) { - if (msg->isEvent() && type == MessageType::PbapEventMessage) { - PbapMessage *tmsg = qobject_cast<PbapMessage*>(msg); - - if (tmsg->isStatusEvent()) { - emit statusChanged(tmsg->connected()); - if (tmsg->connected() == true) { + if (!msg) + return; + + if (msg->isEvent()) { + std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg); + QString ename = emsg->eventName(); + QString eapi = emsg->eventApi(); + QVariantMap data = emsg->eventData().toVariantMap(); + + if (eapi != "pbap") + return; + + bool connected = data.find("connected").value().toBool(); + if (ename == "status") { + emit statusChanged(connected); + if (connected) refreshContacts(-1); } - } - } else if (msg->isReply() && type == MessageType::ResponseRequestMessage) { - ResponseMessage *tmsg = qobject_cast<ResponseMessage*>(msg); - - if (tmsg->requestVerb() == "contacts" || tmsg->requestVerb() == "import") { - updateContacts(tmsg->replyData().value("vcards").toArray()); - } else if (tmsg->requestVerb() == "history") { - updateCalls(tmsg->replyData().value("vcards").toArray()); - } else if (tmsg->requestVerb() == "search") { - sendSearchResults(tmsg->replyData().value("results").toArray()); + } else if (msg->isReply()) { + std::shared_ptr<ResponseMessage> rmsg = std::static_pointer_cast<ResponseMessage>(msg); + QString api = rmsg->requestApi(); + if (api != "pbap") + return; + + QString verb = rmsg->requestVerb(); + QJsonObject data = rmsg->replyData(); + if (verb == "contacts" || verb == "import") { + updateContacts(data.value("vcards").toArray()); + } else if (verb == "history") { + updateCalls(data.value("vcards").toArray()); + } else if (verb == "search") { + sendSearchResults(data.value("results").toArray()); } } - - msg->deleteLater(); } diff --git a/pbap/pbap.h b/pbap/pbap.h index a89bf2b..4deb9c6 100644 --- a/pbap/pbap.h +++ b/pbap/pbap.h @@ -17,6 +17,7 @@ #ifndef PBAP_H #define PBAP_H +#include <memory> #include <QObject> #include <QJsonArray> #include <QtQml/QQmlContext> @@ -25,8 +26,6 @@ class MessageEngine; class Message; -enum class MessageType; - class PhoneNumber : public QObject { Q_OBJECT @@ -169,7 +168,7 @@ class Pbap : public QObject // slots void onConnected(); void onDisconnected(); - void onMessageReceived(MessageType, Message*); + void onMessageReceived(std::shared_ptr<Message>); const QStringList events { "status", diff --git a/radio/CMakeLists.txt b/radio/CMakeLists.txt index 46ac12b..a6b8db4 100644 --- a/radio/CMakeLists.txt +++ b/radio/CMakeLists.txt @@ -1,2 +1,2 @@ -add_headers(radio.h radiomessage.h) -add_sources(radio.cpp radiomessage.cpp) +add_headers(radio.h) +add_sources(radio.cpp) diff --git a/radio/radio.cpp b/radio/radio.cpp index 1627cd7..b7c407c 100644 --- a/radio/radio.cpp +++ b/radio/radio.cpp @@ -16,9 +16,10 @@ #include <QDebug> -#include "message.h" -#include "radiomessage.h" +#include "callmessage.h" +#include "eventmessage.h" #include "responsemessage.h" +#include "messagefactory.h" #include "messageengine.h" #include "radio.h" @@ -48,18 +49,25 @@ Radio::~Radio() void Radio::setBand(int band) { - RadioMessage *rmsg = new RadioMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("band", band ? "FM": "AM"); - rmsg->createRequest("band", parameter); - m_mloop->sendMessage(rmsg); - delete rmsg; + rmsg->createRequest("radio", "band", parameter); + m_mloop->sendMessage(std::move(msg)); } void Radio::setFrequency(int frequency) { - RadioMessage *rmsg = new RadioMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; if (m_scanning) @@ -69,9 +77,8 @@ void Radio::setFrequency(int frequency) return; parameter.insert("value", QString::number(frequency)); - rmsg->createRequest("frequency", parameter); - m_mloop->sendMessage(rmsg); - delete rmsg; + rmsg->createRequest("radio", "frequency", parameter); + m_mloop->sendMessage(std::move(msg)); // To improve UI responsiveness, signal the change here immediately // This fixes visual glitchiness in the slider caused by the frequency @@ -86,22 +93,27 @@ void Radio::setFrequency(int frequency) void Radio::start() { - RadioMessage *rmsg = new RadioMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; - rmsg->createRequest("start", parameter); - m_mloop->sendMessage(rmsg); - delete rmsg; + rmsg->createRequest("radio", "start", parameter); + m_mloop->sendMessage(std::move(msg)); } void Radio::stop() { - RadioMessage *rmsg = new RadioMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; - rmsg->createRequest("stop", parameter); - m_mloop->sendMessage(rmsg); - delete rmsg; + rmsg->createRequest("radio", "stop", parameter); + m_mloop->sendMessage(std::move(msg)); } void Radio::scanForward() @@ -109,16 +121,15 @@ void Radio::scanForward() if (m_scanning) return; - RadioMessage *rmsg = new RadioMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("direction", "forward"); - rmsg->createRequest("scan_start", parameter); - m_mloop->sendMessage(rmsg); + rmsg->createRequest("radio", "scan_start", parameter); + m_mloop->sendMessage(std::move(msg)); m_scanning = true; emit scanningChanged(m_scanning); - - delete rmsg; } void Radio::scanBackward() @@ -126,60 +137,70 @@ void Radio::scanBackward() if (m_scanning) return; - RadioMessage *rmsg = new RadioMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("direction", "backward"); - rmsg->createRequest("scan_start", parameter); - m_mloop->sendMessage(rmsg); + rmsg->createRequest("radio", "scan_start", parameter); + m_mloop->sendMessage(std::move(msg)); m_scanning = true; emit scanningChanged(m_scanning); - - delete rmsg; } void Radio::scanStop() { - RadioMessage *rmsg = new RadioMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; - rmsg->createRequest("scan_stop", parameter); - m_mloop->sendMessage(rmsg); + rmsg->createRequest("radio", "scan_stop", parameter); + m_mloop->sendMessage(std::move(msg)); m_scanning = false; emit scanningChanged(m_scanning); - - delete rmsg; } void Radio::updateFrequencyBandParameters() { - RadioMessage *rmsg = new RadioMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("band", m_band ? "FM" : "AM"); - rmsg->createRequest("frequency_range", parameter); - m_mloop->sendMessage(rmsg); - delete rmsg; - - rmsg = new RadioMessage(); - rmsg->createRequest("frequency_step", parameter); - m_mloop->sendMessage(rmsg); - delete rmsg; + rmsg->createRequest("radio", "frequency_range", parameter); + m_mloop->sendMessage(std::move(msg)); + + std::unique_ptr<Message> msg2 = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg2) + return; + + rmsg = static_cast<CallMessage*>(msg2.get()); + rmsg->createRequest("radio", "frequency_step", parameter); + m_mloop->sendMessage(std::move(msg2)); } void Radio::onConnected() { QStringListIterator eventIterator(events); - RadioMessage *rmsg; while (eventIterator.hasNext()) { - rmsg = new RadioMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("value", eventIterator.next()); - rmsg->createRequest("subscribe", parameter); - m_mloop->sendMessage(rmsg); - delete rmsg; + rmsg->createRequest("radio", "subscribe", parameter); + m_mloop->sendMessage(std::move(msg)); } // Trigger initial update of frequency band parameters (min/max/step) @@ -189,51 +210,63 @@ void Radio::onConnected() void Radio::onDisconnected() { QStringListIterator eventIterator(events); - RadioMessage *rmsg; while (eventIterator.hasNext()) { - rmsg = new RadioMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("value", eventIterator.next()); - rmsg->createRequest("unsubscribe", parameter); - m_mloop->sendMessage(rmsg); - delete rmsg; + rmsg->createRequest("radio", "unsubscribe", parameter); + m_mloop->sendMessage(std::move(msg)); } } -void Radio::onMessageReceived(MessageType type, Message *msg) +void Radio::onMessageReceived(std::shared_ptr<Message> msg) { - if (msg->isEvent() && type == MessageType::RadioEventMessage) { - RadioMessage *rmsg = qobject_cast<RadioMessage*>(msg); + if (!msg) + return; - if (rmsg->isFrequencyEvent()) { - unsigned int frequency = rmsg->eventData().value("value").toInt(); + if (msg->isEvent()) { + std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg); + QString ename = emsg->eventName(); + QString eapi = emsg->eventApi(); + QJsonObject data = emsg->eventData(); + if (ename == "frequency") { + unsigned int frequency = data.value("value").toInt(); m_frequency = frequency; if (!m_scanning && (m_frequency != frequency)) { emit frequencyChanged(m_frequency); } - } else if (rmsg->isStationFoundEvent()) { + } else if (ename == "station_found") { m_scanning = false; emit scanningChanged(m_scanning); - m_frequency = rmsg->eventData().value("value").toInt(); + m_frequency = data.value("value").toInt(); emit frequencyChanged(m_frequency); - } else if (rmsg->isStatusEvent()) { - if (rmsg->eventData().value("value") == QString("playing")) { + } else if (ename == "status") { + if (data.value("value") == QString("playing")) { m_playing = true; emit playingChanged(m_playing); - } else if (rmsg->eventData().value("value") == QString("stopped")) { + } else if (data.value("value") == QString("stopped")) { m_playing = false; emit playingChanged(m_playing); } } - } else if (msg->isReply() && type == MessageType::ResponseRequestMessage) { - ResponseMessage *rmsg = qobject_cast<ResponseMessage*>(msg); - - if (rmsg->requestVerb() == "frequency_range") { - m_minFrequency = rmsg->replyData().value("min").toInt(); + } else if (msg->isReply()) { + std::shared_ptr<ResponseMessage> rmsg = std::static_pointer_cast<ResponseMessage>(msg); + QString api = rmsg->requestApi(); + if (api != "radio") + return; + + QString verb = rmsg->requestVerb(); + QJsonObject data = rmsg->replyData(); + if (verb == "frequency_range") { + m_minFrequency = data.value("min").toInt(); emit minFrequencyChanged(m_minFrequency); - m_maxFrequency = rmsg->replyData().value("max").toInt(); + m_maxFrequency = data.value("max").toInt(); emit maxFrequencyChanged(m_maxFrequency); // Handle start up @@ -241,10 +274,9 @@ void Radio::onMessageReceived(MessageType type, Message *msg) m_frequency = m_minFrequency; emit frequencyChanged(m_frequency); } - } else if (rmsg->requestVerb() == "frequency_step") { - m_frequencyStep = rmsg->replyData().value("step").toInt(); + } else if (verb == "frequency_step") { + m_frequencyStep = data.value("step").toInt(); emit frequencyStepChanged(m_frequencyStep); } } - msg->deleteLater(); } diff --git a/radio/radio.h b/radio/radio.h index 9e72a5a..77b78d2 100644 --- a/radio/radio.h +++ b/radio/radio.h @@ -17,13 +17,13 @@ #ifndef RADIO_H #define RADIO_H +#include <memory> #include <QObject> #include <QtQml/QQmlContext> class MessageEngine; class Message; -enum class MessageType; class Radio : public QObject { @@ -90,7 +90,7 @@ class Radio : public QObject void updateFrequencyBandParameters(); void onConnected(); void onDisconnected(); - void onMessageReceived(MessageType type, Message *msg); + void onMessageReceived(std::shared_ptr<Message> msg); const QStringList events { "frequency", diff --git a/responsemessage.cpp b/responsemessage.cpp index 0e2ad5a..96dab97 100644 --- a/responsemessage.cpp +++ b/responsemessage.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Konsulko Group + * Copyright (C) 2018-2020 Konsulko Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,28 +22,105 @@ #include "responsemessage.h" +//deprecated method call new constructor and setAdditionalData() instead: ResponseMessage::ResponseMessage(QByteArray request) { - QJsonDocument jdoc(QJsonDocument::fromJson(request)); + QJsonDocument jdoc(QJsonDocument::fromJson(request)); - if (!jdoc.isArray()) { - qWarning("Invalid appfw message: not an array"); - return; - } + if (!jdoc.isArray()) { + qWarning("Invalid appfw message: not an array"); + return; + } - QJsonArray msg = jdoc.array(); + QJsonArray msg = jdoc.array(); - if (msg.size() != 4) { - qWarning("Invalid appfw message: invalid array size"); - return; - } + if (msg.size() != 4) { + qWarning("Invalid appfw message: invalid array size"); + return; + } - QStringList api_str_list = msg[2].toString().split(QRegExp("/")); + 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); + 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); +} + +ResponseMessage::ResponseMessage(QJsonDocument content) +{ + QJsonArray msg = content.array(); + if (!msg[2].isObject()) { + qWarning("Invalid appfw payload: no JSON object"); + return; + } + + //deserialize: + auto callid = msg[1].toString().toInt(); + QJsonObject payload = msg[2].toObject(); + + auto request_iter = payload.find("request"); + auto request = request_iter.value().toObject(); + if (request.empty()) { + qWarning("Invalid appfw reply message: empty request data"); + return; + } + + auto status_iter = request.find("status"); + auto info_iter = request.find("info"); + auto response_iter = payload.find("response"); + auto response = response_iter.value().toObject(); + m_reply_status = status_iter.value().toString(); + m_reply_info = info_iter.value().toString(); + m_reply_data = response; + m_reply_callid = callid; + m_init = false; //not complete yet, missing matching request data +} + +bool ResponseMessage::setAdditionalData(QByteArray data) +{ + QJsonDocument jdoc(QJsonDocument::fromJson(data)); + if (!jdoc.isArray()) { + qWarning("Invalid data: not an array"); + return false; + } + + QJsonArray content = jdoc.array(); + if (content.size() != 4) { + qWarning("Invalid data: invalid array size"); + return false; + } + + QStringList api_str_list = content[2].toString().split(QRegExp("/")); + m_request["msgid"] = content.at(0); + m_request["callid"] = content.at(1); + m_request["api"] = api_str_list[0]; + m_request["verb"] = api_str_list[1]; + m_request["parameter"] = content.at(3); + m_init = true; + return true; +} + +bool ResponseMessage::copyCallId(unsigned int *id) +{ + *id = m_reply_callid; + return true; +} + +QByteArray ResponseMessage::serialize(QJsonDocument::JsonFormat format) +{ + QJsonArray array; + (m_reply_status == "failed")? + array.append(static_cast<int>(MessageId::RetErr)) : + array.append(static_cast<int>(MessageId::RetOk)); + array.append(static_cast<int>(m_reply_callid)); + array.append(m_request["api"].toString() + "/" + m_request["verb"].toString()); + array.append(m_reply_data); + + QJsonDocument jdoc; + jdoc.setArray(array); + + return jdoc.toJson(format).data(); } diff --git a/responsemessage.h b/responsemessage.h index dd85150..edad3b1 100644 --- a/responsemessage.h +++ b/responsemessage.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Konsulko Group + * Copyright (C) 2018-2020 Konsulko Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,26 +17,69 @@ #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(); - } + public: + //deprecated: + explicit ResponseMessage(QByteArray request = nullptr); - inline QVariantMap requestParameters() const - { - return m_request["parameter"].toMap(); - } + explicit ResponseMessage(QJsonDocument data); + + inline QString requestApi() const + { + return m_request["api"].toString(); + } + + inline QString requestVerb() const + { + return m_request["verb"].toString(); + } + + inline QVariantMap requestParameters() const + { + return m_request["parameter"].toMap(); + } + + inline QString replyStatus() const + { + return m_reply_status; + } + + inline QString replyInfo() const + { + return m_reply_info; + } + + inline QJsonObject replyData() const + { + return m_reply_data; + } + + bool isEvent() override + { + return false; + } + + bool isReply() override + { + return true; + } + + bool setAdditionalData(QByteArray data); + bool copyCallId(unsigned int *id); + + QByteArray serialize(QJsonDocument::JsonFormat format = QJsonDocument::Compact) override; + + private: + QString m_reply_info, m_reply_status, m_reply_uuid; + unsigned int m_reply_callid; + QJsonObject m_reply_data; + QMap<QString, QVariant> m_request; }; #endif // RESPONSEMESSAGE_H diff --git a/signal-composer/CMakeLists.txt b/signal-composer/CMakeLists.txt index 18f3a0a..f517d27 100644 --- a/signal-composer/CMakeLists.txt +++ b/signal-composer/CMakeLists.txt @@ -1,2 +1,2 @@ -add_headers(signalcomposer.h signalcomposermessage.h) -add_sources(signalcomposer.cpp signalcomposermessage.cpp) +add_headers(signalcomposer.h) +add_sources(signalcomposer.cpp) diff --git a/signal-composer/signalcomposer.cpp b/signal-composer/signalcomposer.cpp index 59395f5..1296162 100644 --- a/signal-composer/signalcomposer.cpp +++ b/signal-composer/signalcomposer.cpp @@ -16,8 +16,9 @@ #include <QDebug> -#include "message.h" -#include "signalcomposermessage.h" +#include "callmessage.h" +#include "eventmessage.h" +#include "messagefactory.h" #include "messageengine.h" #include "signalcomposer.h" @@ -40,56 +41,63 @@ SignalComposer::~SignalComposer() void SignalComposer::onConnected() { QStringListIterator eventIterator(events); - SignalComposerMessage *tmsg; while (eventIterator.hasNext()) { - tmsg = new SignalComposerMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* tmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("signal", eventIterator.next()); - tmsg->createRequest("subscribe", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + tmsg->createRequest("signal-composer", "subscribe", parameter); + m_mloop->sendMessage(std::move(msg)); } } void SignalComposer::onDisconnected() { QStringListIterator eventIterator(events); - SignalComposerMessage *tmsg; while (eventIterator.hasNext()) { - tmsg = new SignalComposerMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage* tmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; parameter.insert("signal", eventIterator.next()); - tmsg->createRequest("unsubscribe", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + tmsg->createRequest("signal-composer", "unsubscribe", parameter); + m_mloop->sendMessage(std::move(msg)); } } -void SignalComposer::onMessageReceived(MessageType type, Message *message) +void SignalComposer::onMessageReceived(std::shared_ptr<Message> msg) { - if (type == MessageType::SignalComposerEventMessage) { - SignalComposerMessage *tmsg = qobject_cast<SignalComposerMessage*>(message); + if (!msg) + return; + + if (msg->isEvent()) { + std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg); + if (emsg->eventApi() != "signal-composer") + return; - if (tmsg->isEvent()) { - QString uid = tmsg->eventData().value("uid").toString(); - QVariant v = tmsg->eventData().value("value").toVariant(); - QString value; - if(v.canConvert(QMetaType::QString)) - value = v.toString(); - else - qWarning() << "Unconvertible value type for uid " << uid; - QString units = tmsg->eventData().value("unit").toString(); - v = tmsg->eventData().value("timestamp").toVariant(); - quint64 timestamp = 0; - if(v.canConvert(QMetaType::ULongLong)) - timestamp = v.toULongLong(); - else - qWarning() << "Unconvertible timestamp type for uid " << uid; + QJsonObject data = emsg->eventData(); + QString uid = data.value("uid").toString(); + QVariant v = data.value("value").toVariant(); + QString value; + if(v.canConvert(QMetaType::QString)) + value = v.toString(); + else + qWarning() << "Unconvertible value type for uid " << uid; + QString units = data.value("unit").toString(); + v = data.value("timestamp").toVariant(); + quint64 timestamp = 0; + if(v.canConvert(QMetaType::ULongLong)) + timestamp = v.toULongLong(); + else + qWarning() << "Unconvertible timestamp type for uid " << uid; - emit signalEvent(uid, value, units, timestamp); - } + emit signalEvent(uid, value, units, timestamp); } - message->deleteLater(); } diff --git a/signal-composer/signalcomposer.h b/signal-composer/signalcomposer.h index 13d26c6..382b6e9 100644 --- a/signal-composer/signalcomposer.h +++ b/signal-composer/signalcomposer.h @@ -17,14 +17,13 @@ #ifndef SIGNALCOMPOSER_H #define SIGNALCOMPOSER_H +#include <memory> #include <QObject> #include <QJsonArray> class MessageEngine; class Message; -enum class MessageType; - class SignalComposer : public QObject { Q_OBJECT @@ -41,7 +40,7 @@ class SignalComposer : public QObject void onConnected(); void onDisconnected(); - void onMessageReceived(MessageType, Message*); + void onMessageReceived(std::shared_ptr<Message>); const QStringList events { "event.vehicle.speed", diff --git a/telephony/CMakeLists.txt b/telephony/CMakeLists.txt index 1dfcd63..196ad53 100644 --- a/telephony/CMakeLists.txt +++ b/telephony/CMakeLists.txt @@ -1,2 +1,2 @@ -add_headers(telephony.h telephonymessage.h) -add_sources(telephony.cpp telephonymessage.cpp) +add_headers(telephony.h) +add_sources(telephony.cpp) diff --git a/telephony/telephony.cpp b/telephony/telephony.cpp index e0fe2bd..0660156 100644 --- a/telephony/telephony.cpp +++ b/telephony/telephony.cpp @@ -16,8 +16,9 @@ #include <QDebug> -#include "message.h" -#include "telephonymessage.h" +#include "callmessage.h" +#include "eventmessage.h" +#include "messagefactory.h" #include "messageengine.h" #include "telephony.h" @@ -41,26 +42,35 @@ Telephony::~Telephony() void Telephony::dial(QString number) { - TelephonyMessage *tmsg = new TelephonyMessage(); - tmsg->createRequest("dial", number); - m_mloop->sendMessage(tmsg); - delete tmsg; + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage *tmsg = static_cast<CallMessage*>(msg.get()); + tmsg->createRequest("telephony", "dial", number); + m_mloop->sendMessage(std::move(msg)); } void Telephony::answer() { - TelephonyMessage *tmsg = new TelephonyMessage(); - tmsg->createRequest("answer"); - m_mloop->sendMessage(tmsg); - delete tmsg; + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage *tmsg = static_cast<CallMessage*>(msg.get()); + tmsg->createRequest("telephony", "answer"); + m_mloop->sendMessage(std::move(msg)); } void Telephony::hangup() { - TelephonyMessage *tmsg = new TelephonyMessage(); - tmsg->createRequest("hangup"); - m_mloop->sendMessage(tmsg); - delete tmsg; + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage *tmsg = static_cast<CallMessage*>(msg.get()); + tmsg->createRequest("telephony", "hangup"); + m_mloop->sendMessage(std::move(msg)); } void Telephony::onConnected() @@ -72,13 +82,15 @@ void Telephony::onConnected() "terminatedCall", "online"}; QStringListIterator eventIterator(events); - TelephonyMessage *tmsg; while (eventIterator.hasNext()) { - tmsg = new TelephonyMessage(); - tmsg->createRequest("subscribe", eventIterator.next()); - m_mloop->sendMessage(tmsg); - delete tmsg; + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage *tmsg = static_cast<CallMessage*>(msg.get()); + tmsg->createRequest("telephony", "subscribe", eventIterator.next()); + m_mloop->sendMessage(std::move(msg)); } setConnected(true); @@ -89,28 +101,31 @@ void Telephony::onDisconnected() setConnected(false); } -void Telephony::onMessageReceived(MessageType type, Message *message) +void Telephony::onMessageReceived(std::shared_ptr<Message> msg) { - if (type == MessageType::TelephonyEventMessage) { - TelephonyMessage *tmsg = qobject_cast<TelephonyMessage*>(message); - - if (tmsg->isEvent()) { - if (tmsg->isCallStateChanged()) { - setCallState(tmsg->state()); - } else if (tmsg->isDialingCall()) { - m_colp = tmsg->colp(); + if (!msg) + return; + + if (msg->isEvent()) { + std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg); + if (emsg->eventApi() != "telephony"); + return; + QString ename = emsg->eventName(); + QJsonObject data = emsg->eventData(); + if (ename == "callStateChanged") { + setCallState(data.find("state").value().toString()); + } else if (ename == "dialingCall") { + m_colp = data.find("colp").value().toString(); setCallState("dialing"); - } else if (tmsg->isIncomingCall()) { - m_clip = tmsg->clip(); + } else if (ename == "incomingCall") { + m_clip = data.find("clip").value().toString(); setCallState("incoming"); - } else if (tmsg->isTerminatedCall()) { + } else if (ename == "terminatedCall") { setCallState("disconnected"); m_colp = ""; m_clip = ""; - } else if (tmsg->isOnline()) { - setOnlineState(tmsg->connected()); + } else if (ename == "online") { + setOnlineState(data.find("connected").value().toBool()); } } - } - message->deleteLater(); } diff --git a/telephony/telephony.h b/telephony/telephony.h index 097310f..ca1e52a 100644 --- a/telephony/telephony.h +++ b/telephony/telephony.h @@ -17,13 +17,12 @@ #ifndef TELEPHONY_H #define TELEPHONY_H +#include <memory> #include <QObject> class MessageEngine; class Message; -enum class MessageType; - class Telephony : public QObject { Q_OBJECT @@ -78,7 +77,7 @@ class Telephony : public QObject QString m_colp; void onConnected(); void onDisconnected(); - void onMessageReceived(MessageType, Message*); + void onMessageReceived(std::shared_ptr<Message>); }; #endif // TELEPHONY_H diff --git a/voice-capabilities/CMakeLists.txt b/voice-capabilities/CMakeLists.txt index e1a6089..e3c0de7 100644 --- a/voice-capabilities/CMakeLists.txt +++ b/voice-capabilities/CMakeLists.txt @@ -1,2 +1,2 @@ -add_headers(guimetadata.h guimetadatamessage.h) -add_sources(guimetadata.cpp guimetadatamessage.cpp) +add_headers(guimetadata.h) +add_sources(guimetadata.cpp) diff --git a/voice-capabilities/guimetadata.cpp b/voice-capabilities/guimetadata.cpp index 949cb58..4c597c1 100644 --- a/voice-capabilities/guimetadata.cpp +++ b/voice-capabilities/guimetadata.cpp @@ -17,8 +17,9 @@ #include <QDebug> #include <QJsonArray> -#include "message.h" -#include "guimetadatamessage.h" +#include "callmessage.h" +#include "eventmessage.h" +#include "messagefactory.h" #include "messageengine.h" #include "guimetadata.h" @@ -308,19 +309,20 @@ bool GuiMetadata::updateWeatherMetadata(QJsonObject &data) void GuiMetadata::onConnected() { - QStringListIterator eventIterator(events); - GuiMetadataCapabilityMessage *tmsg; + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; - tmsg = new GuiMetadataCapabilityMessage(); + CallMessage *tmsg = static_cast<CallMessage*>(msg.get()); + QStringListIterator eventIterator(events); QJsonObject parameter; QJsonArray actions; while (eventIterator.hasNext()) { actions.append(QJsonValue(eventIterator.next())); } parameter.insert("actions", actions); - tmsg->createRequest("guimetadata/subscribe", parameter); - m_mloop->sendMessage(tmsg); - delete tmsg; + tmsg->createRequest("vshl-capabilities", "guimetadata/subscribe", parameter); + m_mloop->sendMessage(std::move(msg)); } void GuiMetadata::onDisconnected() @@ -328,18 +330,21 @@ void GuiMetadata::onDisconnected() // vshl-capabilities currently has no unsubscribe verb... } -void GuiMetadata::onMessageReceived(MessageType type, Message *message) +void GuiMetadata::onMessageReceived(std::shared_ptr<Message> msg) { - if (type == MessageType::GuiMetadataCapabilityEventMessage) { - GuiMetadataCapabilityMessage *tmsg = qobject_cast<GuiMetadataCapabilityMessage*>(message); - if (tmsg->isEvent()) { - if (tmsg->isGuiMetadataRenderTemplateEvent()) { - if(updateMetadata(tmsg->eventData())) - emit renderTemplate(); - } else if (tmsg->isGuiMetadataClearTemplateEvent()) { - emit clearTemplate(); - } + if (!msg) + return; + + if (msg->isEvent()) { + std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg); + if (emsg->eventApi() != "vshl-capabilities"); + return; + QString ename = emsg->eventName(); + QJsonObject data = emsg->eventData(); + if ((ename == "render-template") && updateMetadata(data)) { + emit renderTemplate(); + } else if (ename == "clear_template") { + emit clearTemplate(); } } - message->deleteLater(); } diff --git a/voice-capabilities/guimetadata.h b/voice-capabilities/guimetadata.h index ae90cba..f082d52 100644 --- a/voice-capabilities/guimetadata.h +++ b/voice-capabilities/guimetadata.h @@ -17,13 +17,13 @@ #ifndef GUIMETADATA_H #define GUIMETADATA_H +#include <memory> #include <QObject> #include <QtQml/QQmlContext> class MessageEngine; class Message; -enum class MessageType; class GuiMetadata : public QObject { @@ -128,7 +128,7 @@ private: void onConnected(); void onDisconnected(); - void onMessageReceived(MessageType, Message*); + void onMessageReceived(std::shared_ptr<Message>); const QStringList events { "render_template", diff --git a/voice/CMakeLists.txt b/voice/CMakeLists.txt index 61b8fe2..6363c3b 100644 --- a/voice/CMakeLists.txt +++ b/voice/CMakeLists.txt @@ -1,4 +1,4 @@ -add_headers(voice.h voicemessage.h +add_headers(voice.h voiceagentregistry.h voiceagentprofile.h voiceagentmodel.h) -add_sources(voice.cpp voicemessage.cpp +add_sources(voice.cpp voiceagentregistry.cpp voiceagentprofile.cpp voiceagentmodel.cpp) diff --git a/voice/voice.cpp b/voice/voice.cpp index 3c93960..5961882 100644 --- a/voice/voice.cpp +++ b/voice/voice.cpp @@ -16,9 +16,10 @@ #include <QDebug> #include <QStringList> -#include "message.h" +#include "callmessage.h" #include "responsemessage.h" -#include "voicemessage.h" +#include "eventmessage.h" +#include "messagefactory.h" #include "messageengine.h" #include "voiceagentregistry.h" #include "voice.h" @@ -46,12 +47,15 @@ Voice::~Voice() void Voice::scan() { - VoiceMessage *vmsg = new VoiceMessage(); + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage *vmsg = static_cast<CallMessage*>(msg.get()); QJsonObject parameter; - vmsg->createRequest("enumerateVoiceAgents", parameter); - m_loop->sendMessage(vmsg); - delete vmsg; + vmsg->createRequest("vshl-core", "enumerateVoiceAgents", parameter); + m_loop->sendMessage(std::move(msg)); } void Voice::getCBLpair(QString id) @@ -61,41 +65,50 @@ void Voice::getCBLpair(QString id) void Voice::subscribeAgentToVshlEvents(QString id) { + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage *vmsg = static_cast<CallMessage*>(msg.get()); QJsonArray events = QJsonArray::fromStringList(vshl_events); - VoiceMessage *vmsg = new VoiceMessage(); QJsonObject parameter; parameter.insert("va_id", id); parameter.insert("events", events); - vmsg->createRequest("subscribe", parameter); - m_loop->sendMessage(vmsg); - delete vmsg; + vmsg->createRequest("vshl-core", "subscribe", parameter); + m_loop->sendMessage(std::move(msg)); } void Voice::unsubscribeAgentFromVshlEvents(QString id) { + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage *vmsg = static_cast<CallMessage*>(msg.get()); QJsonArray events = QJsonArray::fromStringList(vshl_events); - VoiceMessage *vmsg = new VoiceMessage(); QJsonObject parameter; parameter.insert("va_id", id); parameter.insert("events", events); - vmsg->createRequest("unsubscribe", parameter); - m_loop->sendMessage(vmsg); - delete vmsg; + vmsg->createRequest("vshl-core", "unsubscribe", parameter); + m_loop->sendMessage(std::move(msg)); } void Voice::triggerCBLProcess(QString id) { + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage *vmsg = static_cast<CallMessage*>(msg.get()); QJsonArray events; - VoiceMessage *vmsg = new VoiceMessage(); QJsonObject parameter; parameter.insert("va_id", id); parameter.insert("events", events); - vmsg->createRequest("subscribeToLoginEvents", parameter); - m_loop->sendMessage(vmsg); - delete vmsg; + vmsg->createRequest("vshl-core", "subscribeToLoginEvents", parameter); + m_loop->sendMessage(std::move(msg)); } void Voice::parseAgentsList(QJsonArray agents) @@ -109,14 +122,20 @@ void Voice::parseAgentsList(QJsonArray agents) -void Voice::processEvent(VoiceMessage *vmsg) +void Voice::processEvent(std::shared_ptr<Message> msg) { - const QString str = vmsg->eventName(); - QJsonObject data = vmsg->eventData(); + std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg); + QString eapi = emsg->eventApi(); + + if (eapi != "vshl-core") + return; + + QString ename = emsg->eventName(); + QJsonObject data = emsg->eventData(); QString agentId = data.value("va_id").toString(); QString state = data.value("state").toString(); - if (vmsg->isAuthStateEvent()) { + if (ename.contains("voice_authstate_event")) { m_var->setAuthState( agentId, static_cast<VoiceAgentRegistry::ServiceAuthState>( @@ -124,47 +143,48 @@ void Voice::processEvent(VoiceMessage *vmsg) return; } - else if (vmsg->isConnectionStateEvent()) { + else if (ename.contains("voice_connectionstate_event")) { m_var->setConnectionState( agentId, static_cast<VoiceAgentRegistry::AgentConnectionState>( m_var->stringToEnum(state, "AgentConnectionState"))); return; } - else if (vmsg->isDialogStateEvent()) { + else if (ename.contains("voice_dialogstate_event")) { m_var->setDialogState( agentId, static_cast<VoiceAgentRegistry::VoiceDialogState>( m_var->stringToEnum(state, "VoiceDialogState"))); return; } - else if (vmsg->isCblEvent()) { + else if (ename.contains("cbl")) { QJsonObject payload = data.value("payload").toObject(); QString url = payload.value("url").toString(); QString code = payload.value("code").toString(); - if (str.contains("expired")) + if (ename.contains("expired")) m_var->updateLoginData(agentId, code, url, true); - else if (str.contains("received")) { + else if (ename.contains("received")) { m_var->updateLoginData(agentId, code, url, false); } else qWarning() << "Unknown cbl event"; return; } - qWarning() << "Unknown vshl event:" << str; + qWarning() << "Unknown vshl event:" << ename; } -void Voice::processReply(ResponseMessage *rmsg) +void Voice::processReply(std::shared_ptr<Message> msg) { + std::shared_ptr<ResponseMessage> rmsg = std::static_pointer_cast<ResponseMessage>(msg); + QString verb = rmsg->requestVerb(); + QJsonObject data = rmsg->replyData(); if (rmsg->replyStatus() == "failed") { - qWarning() << "Reply Failed received for verb:" << rmsg->requestVerb(); - } else if (rmsg->requestVerb() == "enumerateVoiceAgents") { - parseAgentsList(rmsg->replyData().value("agents").toArray()); - m_var->setDefaultId( - rmsg->replyData().value("default").toString()); + qWarning() << "Reply Failed received for verb:" << verb; + } else if (verb == "enumerateVoiceAgents") { + parseAgentsList(data.value("agents").toArray()); + m_var->setDefaultId(data.value("default").toString()); } else - qDebug() << "discarding reply received for verb:" << - rmsg->requestVerb(); + qDebug() << "discarding reply received for verb:" << verb; } void Voice::onConnected() @@ -180,13 +200,12 @@ void Voice::onDisconnected() unsubscribeAgentFromVshlEvents(*it); } -void Voice::onMessageReceived(MessageType type, Message *msg) +void Voice::onMessageReceived(std::shared_ptr<Message> msg) { - if (msg->isEvent() && type == MessageType::VoiceEventMessage) { - processEvent(qobject_cast<VoiceMessage*>(msg)); - } else if (msg->isReply() && (type == MessageType::ResponseRequestMessage)) { - processReply(qobject_cast<ResponseMessage*>(msg)); + if (msg->isEvent()) { + processEvent(msg); + } else if (msg->isReply()) { + processReply(msg); } else - qWarning() << "Received unknown message type:" << static_cast<double>(type); - msg->deleteLater(); + qWarning() << "Received invalid inbound message"; } diff --git a/voice/voice.h b/voice/voice.h index e3132be..ea0649b 100644 --- a/voice/voice.h +++ b/voice/voice.h @@ -17,6 +17,7 @@ #ifndef VOICE_H #define VOICE_H +#include <memory> #include <QObject> #include <QJsonArray> #include <QtQml/QQmlContext> @@ -24,10 +25,6 @@ class VoiceAgentRegistry; class MessageEngine; class Message; -class ResponseMessage; -class VoiceMessage; - -enum class MessageType; class Voice : public QObject { @@ -51,16 +48,16 @@ class Voice : public QObject void unsubscribeAgentFromVshlEvents(QString id); void triggerCBLProcess(QString id); void parseAgentsList(QJsonArray agents); - void processVshlEvent(VoiceMessage *vmsg); - void processLoginEvent(VoiceMessage *vmsg); + void processVshlEvent(std::shared_ptr<Message> msg); + void processLoginEvent(std::shared_ptr<Message> msg); - void processEvent(VoiceMessage *vmsg); - void processReply(ResponseMessage *rmsg); + void processEvent(std::shared_ptr<Message> emsg); + void processReply(std::shared_ptr<Message> rmsg); // slots void onConnected(); void onDisconnected(); - void onMessageReceived(MessageType type, Message *msg); + void onMessageReceived(std::shared_ptr<Message> msg); const QStringList vshl_events { "voice_authstate_event", diff --git a/weather/CMakeLists.txt b/weather/CMakeLists.txt index 44b4d4d..bd94755 100644 --- a/weather/CMakeLists.txt +++ b/weather/CMakeLists.txt @@ -1,2 +1,2 @@ -add_headers(weather.h weathermessage.h) -add_sources(weather.cpp weathermessage.cpp) +add_headers(weather.h) +add_sources(weather.cpp) diff --git a/weather/weather.cpp b/weather/weather.cpp index d4992d4..298f32c 100644 --- a/weather/weather.cpp +++ b/weather/weather.cpp @@ -17,8 +17,9 @@ #include <QDebug> #include <QJsonArray> -#include "message.h" -#include "weathermessage.h" +#include "callmessage.h" +#include "eventmessage.h" +#include "messagefactory.h" #include "messageengine.h" #include "weather.h" @@ -40,32 +41,41 @@ Weather::~Weather() void Weather::onConnected() { - WeatherMessage *tmsg = new WeatherMessage(); - tmsg->createRequest("subscribe", "weather"); - m_mloop->sendMessage(tmsg); - delete tmsg; + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage *tmsg = static_cast<CallMessage*>(msg.get()); + tmsg->createRequest("weather", "subscribe", "weather"); + m_mloop->sendMessage(std::move(msg)); } void Weather::onDisconnected() { - WeatherMessage *tmsg = new WeatherMessage(); - tmsg->createRequest("unsubscribe", "weather"); - m_mloop->sendMessage(tmsg); - delete tmsg; + std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); + if (!msg) + return; + + CallMessage *tmsg = static_cast<CallMessage*>(msg.get()); + tmsg->createRequest("weater", "unsubscribe", "weather"); + m_mloop->sendMessage(std::move(msg)); } -void Weather::onMessageReceived(MessageType type, Message *message) +void Weather::onMessageReceived(std::shared_ptr<Message> msg) { - if (type == MessageType::WeatherEventMessage) { - WeatherMessage *tmsg = qobject_cast<WeatherMessage*>(message); + if (!msg) + return; + + if (msg->isEvent()) { + std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg); + if (emsg->eventApi() != "weather") + return; - if (tmsg->isEvent()) { - m_temperature = tmsg->temperature(); - m_condition = tmsg->condition(); + QJsonObject data = emsg->eventData(); + m_temperature = QString::number(data.value("main").toObject().value("temp").toDouble()); + m_condition = data.value("weather").toArray().at(0).toObject().value("description").toString(); emit temperatureChanged(m_temperature); emit conditionChanged(m_condition); } - } - message->deleteLater(); } diff --git a/weather/weather.h b/weather/weather.h index 6d33a15..75054d5 100644 --- a/weather/weather.h +++ b/weather/weather.h @@ -17,13 +17,12 @@ #ifndef WEATHER_H #define WEATHER_H +#include <memory> #include <QObject> class MessageEngine; class Message; -enum class MessageType; - class Weather : public QObject { Q_OBJECT @@ -48,7 +47,7 @@ class Weather : public QObject void onConnected(); void onDisconnected(); - void onMessageReceived(MessageType, Message*); + void onMessageReceived(std::shared_ptr<Message>); }; #endif // WEATHER_H |