From 69a6cfb0d09618f10c9cedc0e6192de9d4fd6018 Mon Sep 17 00:00:00 2001 From: Justin Hammond Date: Tue, 12 Nov 2019 16:54:06 +0800 Subject: [PATCH] Update Topics with Instance and CC info --- qt-ozwdaemon/mqttpublisher.cpp | 123 +++++++++++++++++++++++++++++++-- qt-ozwdaemon/mqttpublisher.h | 14 +++- 2 files changed, 129 insertions(+), 8 deletions(-) diff --git a/qt-ozwdaemon/mqttpublisher.cpp b/qt-ozwdaemon/mqttpublisher.cpp index 6560a43..60ee1a8 100644 --- a/qt-ozwdaemon/mqttpublisher.cpp +++ b/qt-ozwdaemon/mqttpublisher.cpp @@ -504,10 +504,25 @@ QString mqttpublisher::getNodeTopic(QString topic, quint8 node) { t.append(topic.arg(static_cast(node))); return t; } -QString mqttpublisher::getValueTopic(QString topic, quint8 node, quint64 vid) { + +QString mqttpublisher::getInstanceTopic(QString topic, quint8 node, quint8 instance) { QString t(MQTT_OZW_TOP_TOPIC); t = t.arg(settings->value("Instance", 1).toInt()); - t.append(topic.arg(static_cast(node)).arg(static_cast(vid))); + t.append(topic.arg(static_cast(node)).arg(static_cast(instance))); + return t; +} + +QString mqttpublisher::getCommandClassTopic(QString topic, quint8 node, quint8 instance, quint8 cc) { + QString t(MQTT_OZW_TOP_TOPIC); + t = t.arg(settings->value("Instance", 1).toInt()); + t.append(topic.arg(static_cast(node)).arg(static_cast(instance)).arg(static_cast(cc))); + return t; +} + +QString mqttpublisher::getValueTopic(QString topic, quint8 node, quint8 instance, quint8 cc, quint64 vid) { + QString t(MQTT_OZW_TOP_TOPIC); + t = t.arg(settings->value("Instance", 1).toInt()); + t.append(topic.arg(static_cast(node)).arg(static_cast(instance)).arg(static_cast(cc)).arg(static_cast(vid))); return t; } @@ -604,14 +619,46 @@ bool mqttpublisher::sendNodeUpdate(quint8 node) { bool mqttpublisher::sendValueUpdate(quint64 vidKey) { quint8 node = this->m_valueModel->getValueData(vidKey, QTOZW_ValueIds::Node).value(); + quint8 instance = this->m_valueModel->getValueData(vidKey, QTOZW_ValueIds::Instance).value(); + quint8 cc = this->m_valueModel->getValueData(vidKey, QTOZW_ValueIds::CommandClass).value(); if (node == 0) { qCWarning(ozwmp) << "sendValueUpdate: Can't find Node for Value: " << vidKey; return false; } + if (instance == 0) { + qCWarning(ozwmp) << "sendValueUpdate: Can't find instance for Value: " << vidKey; + return false; + } + if (cc == 0) { + qCWarning(ozwmp) << "sendValueUpdate: Can't find CC for Value: " << vidKey; + return false; + } QT2JS::SetUInt64(*this->m_values[vidKey], "TimeStamp", QDateTime::currentSecsSinceEpoch()); - this->m_client->publish(QMqttTopicName(getValueTopic(MQTT_OZW_VID_TOPIC, node, vidKey)), QT2JS::getJSON(*this->m_values[vidKey]), 0, true); + this->m_client->publish(QMqttTopicName(getValueTopic(MQTT_OZW_VID_TOPIC, node, instance, cc, vidKey)), QT2JS::getJSON(*this->m_values[vidKey]), 0, true); return true; } + +bool mqttpublisher::sendInstanceUpdate(quint8 node, quint8 instance) { + rapidjson::Document *jsinstance = nullptr; + if (!(jsinstance = this->getInstanceJSON(node, instance))) { + return false; + } + QT2JS::SetUInt64(*jsinstance, "TimeStamp", QDateTime::currentSecsSinceEpoch()); + this->m_client->publish(QMqttTopicName(getInstanceTopic(MQTT_OZW_INSTANCE_TOPIC, node, instance)), QT2JS::getJSON(*jsinstance), 0, true); + return true; +} + +bool mqttpublisher::sendCommandClassUpdate(quint8 node, quint8 instance, quint8 cc) { + rapidjson::Document *jsCommandClass = nullptr; + if (!(jsCommandClass = this->getCommandClassJSON(node, instance, cc))) { + return false; + } + QT2JS::SetUInt64(*jsCommandClass, "TimeStamp", QDateTime::currentSecsSinceEpoch()); + this->m_client->publish(QMqttTopicName(getCommandClassTopic(MQTT_OZW_COMMANDCLASS_TOPIC, node, instance, cc)), QT2JS::getJSON(*jsCommandClass), 0, true); + return true; +} + + void mqttpublisher::sendCommandUpdate(QString command, rapidjson::Document &js) { QT2JS::SetUInt64(js, "TimeStamp", QDateTime::currentSecsSinceEpoch()); this->m_client->publish(QMqttTopicName(getCommandResponseTopic(command.toLower())), QT2JS::getJSON(js), 0, false); @@ -625,11 +672,24 @@ bool mqttpublisher::delNodeTopic(quint8 node) { bool mqttpublisher::delValueTopic(quint64 vidKey) { quint8 node = this->m_valueModel->getValueData(vidKey, QTOZW_ValueIds::Node).value(); + quint8 instance = this->m_valueModel->getValueData(vidKey, QTOZW_ValueIds::Instance).value(); + quint8 cc = this->m_valueModel->getValueData(vidKey, QTOZW_ValueIds::CommandClass).value(); if (node == 0) { qCWarning(ozwmp) << "delValueTopic: Can't find Node for Value: " << vidKey; return false; } - this->m_client->publish(QMqttTopicName(getValueTopic(MQTT_OZW_VID_TOPIC, node, vidKey)), NULL, 0, false); + if (instance == 0) { + qCWarning(ozwmp) << "sendValueUpdate: Can't find instance for Value: " << vidKey; + return false; + } + if (cc == 0) { + qCWarning(ozwmp) << "sendValueUpdate: Can't find CC for Value: " << vidKey; + return false; + } + this->m_client->publish(QMqttTopicName(getValueTopic(MQTT_OZW_VID_TOPIC, node, instance, cc, vidKey)), NULL, 0, false); + /* XXX TODO: Scan though remaining Values, and see if any other Values are under the same CC or instance + * if not - Then we should delete the CC/instance topic as well + */ return true; } @@ -641,6 +701,29 @@ void mqttpublisher::ready() { } void mqttpublisher::valueAdded(quint64 vidKey) { qCDebug(ozwmp) << "Publishing Event valueAdded:" << vidKey; + /* create instance and CC Topics if necessary */ + rapidjson::Document *jsinstance = nullptr; + quint8 node = this->m_valueModel->getValueData(vidKey, QTOZW_ValueIds::Node).value(); + quint8 instance = this->m_valueModel->getValueData(vidKey, QTOZW_ValueIds::Instance).value(); + quint8 cc = this->m_valueModel->getValueData(vidKey, QTOZW_ValueIds::CommandClass).value(); + + if (!(jsinstance = this->getInstanceJSON(node, instance))) { + jsinstance = new rapidjson::Document(rapidjson::kObjectType); + QT2JS::SetInt(*jsinstance, "Instance", instance); + this->m_instances[node][instance] = jsinstance; + } + this->sendInstanceUpdate(node, instance); + + rapidjson::Document *jsCommandClass = nullptr; + if (!(jsCommandClass = this->getCommandClassJSON(node, instance, cc))) { + jsCommandClass = new rapidjson::Document(rapidjson::kObjectType); + QT2JS::SetInt(*jsCommandClass, "Instance", instance); + QT2JS::SetInt(*jsCommandClass, "CommandClassId", cc); + QT2JS::SetString(*jsCommandClass, "CommandClass", this->getQTOZWManager()->getCommandClassString(cc)); + this->m_CommandClasses[node][instance][cc] = jsCommandClass; + } + this->sendCommandClassUpdate(node, instance, cc); + if (this->m_values.find(vidKey) == this->m_values.end()) { this->m_values.insert(vidKey, new rapidjson::Document()); } @@ -693,14 +776,20 @@ void mqttpublisher::nodeRemoved(quint8 node) { this->delNodeTopic(node); if (this->m_nodes.find(node) == this->m_nodes.end()) { this->m_nodes.remove(node); - } + } + /* XXX TODO: Scan Through Instance, CC and Value Lists and make sure + * they are all deleted as well + */ } void mqttpublisher::nodeReset(quint8 node) { qCDebug(ozwmp) << "Publishing Event nodeReset:" << node; this->delNodeTopic(node); if (this->m_nodes.find(node) == this->m_nodes.end()) { this->m_nodes.remove(node); - } + } + /* XXX TODO: Scan Through Instance, CC and Value Lists and make sure + * they are all deleted as well + */ } void mqttpublisher::nodeNaming(quint8 node) { qCDebug(ozwmp) << "Publishing Event nodeNaming:" << node; @@ -743,18 +832,21 @@ void mqttpublisher::driverFailed(quint32 homeID) { QT2JS::SetString(this->m_ozwstatus, "Status", "driverFailed"); QT2JS::SetUint(this->m_ozwstatus, "homeID", homeID); this->sendStatusUpdate(); + /* XXX TODO: Scan Nodes, Instances, CC and Value Lists and delete them */ } void mqttpublisher::driverReset(quint32 homeID) { qCDebug(ozwmp) << "Publishing Event driverReset:" << homeID; QT2JS::SetString(this->m_ozwstatus, "Status", "driverReset"); QT2JS::SetUint(this->m_ozwstatus, "homeID", homeID); this->sendStatusUpdate(); + /* XXX TODO: Scan Nodes, Instances, CC and Value Lists and delete them */ } void mqttpublisher::driverRemoved(quint32 homeID) { qCDebug(ozwmp) << "Publishing Event driverRemoved:" << homeID; QT2JS::SetString(this->m_ozwstatus, "Status", "driverRemoved"); QT2JS::SetUint(this->m_ozwstatus, "homeID", homeID); this->sendStatusUpdate(); + /* XXX TODO: Scan Nodes, Instances, CC and Value Lists and delete them */ } void mqttpublisher::driverAllNodesQueriedSomeDead() { qCDebug(ozwmp) << "Publishing Event driverAllNodesQueriedSomeDead:" ; @@ -913,3 +1005,22 @@ void mqttpublisher::stopped(quint32 homeID) { QTOZWManager *mqttpublisher::getQTOZWManager() { return this->m_qtozwdeamon->getManager(); } + +rapidjson::Document *mqttpublisher::getInstanceJSON(quint8 node, quint8 instance) { + if (this->m_instances.find(node) != this->m_instances.end()) { + if (this->m_instances[node].find(instance) != this->m_instances[node].end()) { + return this->m_instances[node][instance]; + } + } + return nullptr; +} +rapidjson::Document *mqttpublisher::getCommandClassJSON(quint8 node, quint8 instance, quint8 cc) { + if (this->m_CommandClasses.find(node) != this->m_CommandClasses.end()) { + if (this->m_CommandClasses[node].find(instance) != this->m_CommandClasses[node].end()) { + if (this->m_CommandClasses[node][instance].find(cc) != this->m_CommandClasses[node][instance].end()) { + return this->m_CommandClasses[node][instance][cc]; + } + } + } + return nullptr; +} diff --git a/qt-ozwdaemon/mqttpublisher.h b/qt-ozwdaemon/mqttpublisher.h index 2f16cfa..79bd811 100644 --- a/qt-ozwdaemon/mqttpublisher.h +++ b/qt-ozwdaemon/mqttpublisher.h @@ -17,7 +17,9 @@ class MqttCommands; #define MQTT_OZW_STATS_NODE_TOPIC "node/%1/statistics/" #define MQTT_OZW_STATUS_TOPIC "status/" #define MQTT_OZW_NODE_TOPIC "node/%1/" -#define MQTT_OZW_VID_TOPIC "node/%1/value/%2/" +#define MQTT_OZW_INSTANCE_TOPIC "node/%1/%2/" +#define MQTT_OZW_VID_TOPIC "node/%1/%2/value/%3/%4/" +#define MQTT_OZW_COMMANDCLASS_TOPIC "node/%1/%2/value/%3/" #define MQTT_OZW_COMMAND_TOPIC "command/%1/" #define MQTT_OZW_RESPONSE_TOPIC "event/%1/" @@ -99,17 +101,25 @@ private: QString getTopic(QString); QString getNodeTopic(QString, quint8); - QString getValueTopic(QString, quint8, quint64); + QString getInstanceTopic(QString, quint8, quint8); + QString getCommandClassTopic(QString, quint8, quint8, quint8); + QString getValueTopic(QString, quint8, quint8, quint8, quint64); QString getCommandTopic(); QString getCommandResponseTopic(QString); bool sendStatusUpdate(); bool sendNodeUpdate(quint8); bool sendValueUpdate(quint64); + bool sendInstanceUpdate(quint8, quint8); + bool sendCommandClassUpdate(quint8, quint8, quint8); bool delNodeTopic(quint8); bool delValueTopic(quint64); + rapidjson::Document *getInstanceJSON(quint8, quint8); + rapidjson::Document *getCommandClassJSON(quint8, quint8, quint8); rapidjson::Document m_ozwstatus; QMap m_nodes; + QMap > m_instances; + QMap > > m_CommandClasses; mqttNodeModel *m_nodeModel; QMap m_values; mqttValueIDModel *m_valueModel;