diff --git a/libnymea-core/jsonrpc/zigbeehandler.cpp b/libnymea-core/jsonrpc/zigbeehandler.cpp index 453e3add..1cd1add7 100644 --- a/libnymea-core/jsonrpc/zigbeehandler.cpp +++ b/libnymea-core/jsonrpc/zigbeehandler.cpp @@ -47,6 +47,8 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) : registerEnum(); registerEnum(); registerObject(); + registerEnum(); + registerEnum(); // Network object describing a network instance QVariantMap zigbeeNetworkDescription; @@ -66,6 +68,22 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) : zigbeeNetworkDescription.insert("networkState", enumRef()); registerObject("ZigbeeNetwork", zigbeeNetworkDescription); + QVariantMap zigbeeNeighborTableRecordDescription; + zigbeeNeighborTableRecordDescription.insert("networkAddress", enumValueName(Uint)); + zigbeeNeighborTableRecordDescription.insert("relationship", enumRef()); + zigbeeNeighborTableRecordDescription.insert("lqi", enumValueName(Uint)); + zigbeeNeighborTableRecordDescription.insert("depth", enumValueName(Uint)); + zigbeeNeighborTableRecordDescription.insert("permitJoining", enumValueName(Bool)); + registerObject("ZigbeeNeighborTableRecord", zigbeeNeighborTableRecordDescription); + + QVariantMap zigbeeRoutingTableRecordDescription; + zigbeeRoutingTableRecordDescription.insert("destinationAddress", enumValueName(Uint)); + zigbeeRoutingTableRecordDescription.insert("nextHopAddress", enumValueName(Uint)); + zigbeeRoutingTableRecordDescription.insert("status", enumRef()); + zigbeeRoutingTableRecordDescription.insert("manyToOne", enumValueName(Bool)); + zigbeeRoutingTableRecordDescription.insert("memoryConstrained", enumValueName(Bool)); + registerObject("ZigbeeRoutingTableRecord", zigbeeRoutingTableRecordDescription); + // Zigbee node description QVariantMap zigbeeNodeDescription; zigbeeNodeDescription.insert("networkUuid", enumValueName(Uuid)); @@ -80,6 +98,8 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) : zigbeeNodeDescription.insert("reachable", enumValueName(Bool)); zigbeeNodeDescription.insert("lqi", enumValueName(Uint)); zigbeeNodeDescription.insert("lastSeen", enumValueName(Uint)); + zigbeeNodeDescription.insert("neighborTableRecords", QVariantList() << objectRef("ZigbeeNeighborTableRecord")); + zigbeeNodeDescription.insert("routingTableRecords", QVariantList() << objectRef("ZigbeeRoutingTableRecord")); registerObject("ZigbeeNode", zigbeeNodeDescription); QVariantMap params, returns; @@ -182,6 +202,12 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) : returns.insert("zigbeeError", enumRef()); registerMethod("SetPermitJoin", description, params, returns); + params.clear(); returns.clear(); + description = "Refresh the neighbor table for all nodes. Note that calling this may cause a lot of traffic in the ZigBee network."; + params.insert("networkUuid", enumValueName(Uuid)); + returns.insert("zigbeeError", enumRef()); + registerMethod("RefreshNeighborTables", description, params, returns); + // GetNodes params.clear(); returns.clear(); description = "Returns the list of ZigBee nodes from the network the given \'networkUuid\' in the system."; @@ -397,6 +423,12 @@ JsonReply *ZigbeeHandler::RemoveNode(const QVariantMap ¶ms) return createReply(returnMap); } +JsonReply *ZigbeeHandler::RefreshNeighborTables(const QVariantMap ¶ms) +{ + ZigbeeManager::ZigbeeError error = m_zigbeeManager->refreshNeighborTables(params.value("networkUuid").toUuid()); + return createReply({{"zigbeeError", enumValueName(error)}}); +} + JsonReply *ZigbeeHandler::GetNetworks(const QVariantMap ¶ms) { Q_UNUSED(params) @@ -497,6 +529,28 @@ QVariantMap ZigbeeHandler::packNode(ZigbeeNode *node) nodeMap.insert("reachable", node->reachable()); nodeMap.insert("lqi", node->lqi()); nodeMap.insert("lastSeen", node->lastSeen().toMSecsSinceEpoch() / 1000); + QVariantList neighborTableRecords; + foreach (const ZigbeeDeviceProfile::NeighborTableListRecord &record, node->neighborTableRecords()) { + QVariantMap recordMap; + recordMap.insert("networkAddress", record.shortAddress); + recordMap.insert("depth", record.depth); + recordMap.insert("lqi", record.lqi); + recordMap.insert("relationship", enumValueName(static_cast(record.relationship))); + recordMap.insert("permitJoining", record.permitJoining); + neighborTableRecords.append(recordMap); + } + nodeMap.insert("neighborTableRecords", neighborTableRecords); + QVariantList routingTableRecords; + foreach (const ZigbeeDeviceProfile::RoutingTableListRecord &record, node->routingTableRecords()) { + QVariantMap recordMap; + recordMap.insert("destinationAddress", record.destinationAddress); + recordMap.insert("nextHopAddress", record.nextHopAddress); + recordMap.insert("status", enumValueName(static_cast(record.status))); + recordMap.insert("memoryConstrained", record.memoryConstrained); + recordMap.insert("manyToOne", record.manyToOne); + routingTableRecords.append(recordMap); + } + nodeMap.insert("routingTableRecords", routingTableRecords); return nodeMap; } diff --git a/libnymea-core/jsonrpc/zigbeehandler.h b/libnymea-core/jsonrpc/zigbeehandler.h index b9e5c24b..9fca2f31 100644 --- a/libnymea-core/jsonrpc/zigbeehandler.h +++ b/libnymea-core/jsonrpc/zigbeehandler.h @@ -45,6 +45,24 @@ class ZigbeeHandler : public JsonHandler { Q_OBJECT public: + enum ZigbeeNodeRelationship { + ZigbeeNodeRelationshipParent, + ZigbeeNodeRelationshipChild, + ZigbeeNodeRelationshipSibling, + ZigbeeNodeRelationshipNone, + ZigbeeNodeRelationshipPreviousChild + }; + Q_ENUM(ZigbeeNodeRelationship) + + enum ZigbeeNodeRouteStatus { + ZigbeeNodeRouteStatusActive, + ZigbeeNodeRouteStatusDiscoveryUnderway, + ZigbeeNodeRouteStatusDiscoveryFailed, + ZigbeeNodeRouteStatusInactive, + ZigbeeNodeRouteStatusValidationUnderway + }; + Q_ENUM(ZigbeeNodeRouteStatus) + explicit ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent = nullptr); QString name() const override; @@ -61,6 +79,8 @@ public: Q_INVOKABLE JsonReply *GetNodes(const QVariantMap ¶ms); Q_INVOKABLE JsonReply *RemoveNode(const QVariantMap ¶ms); + Q_INVOKABLE JsonReply *RefreshNeighborTables(const QVariantMap ¶ms); + QVariantMap packNetwork(ZigbeeNetwork *network); QVariantMap packNode(ZigbeeNode *node); diff --git a/libnymea-core/zigbee/zigbeemanager.cpp b/libnymea-core/zigbee/zigbeemanager.cpp index 31267196..a2aff02b 100644 --- a/libnymea-core/zigbee/zigbeemanager.cpp +++ b/libnymea-core/zigbee/zigbeemanager.cpp @@ -237,7 +237,7 @@ ZigbeeManager::ZigbeeError ZigbeeManager::setZigbeeNetworkPermitJoin(const QUuid ZigbeeManager::ZigbeeError ZigbeeManager::factoryResetNetwork(const QUuid &networkUuid) { - if (!m_zigbeeNetworks.keys().contains(networkUuid)) { + if (!m_zigbeeNetworks.contains(networkUuid)) { qCWarning(dcZigbee()) << "Could not factory reset network with uuid" << networkUuid.toString() << "because there is no network with this uuid."; return ZigbeeManager::ZigbeeErrorNetworkUuidNotFound; } @@ -248,6 +248,16 @@ ZigbeeManager::ZigbeeError ZigbeeManager::factoryResetNetwork(const QUuid &netwo return ZigbeeManager::ZigbeeErrorNoError; } +ZigbeeManager::ZigbeeError ZigbeeManager::refreshNeighborTables(const QUuid &networkUuid) +{ + if (!m_zigbeeNetworks.contains(networkUuid)) { + qCWarning(dcZigbee()) << "No network with uuid" << networkUuid.toString(); + return ZigbeeManager::ZigbeeErrorNetworkUuidNotFound; + } + m_zigbeeNetworks.value(networkUuid)->refreshNeighborTable(); + return ZigbeeManager::ZigbeeErrorNoError; +} + void ZigbeeManager::saveNetwork(ZigbeeNetwork *network) { NymeaSettings settings(NymeaSettings::SettingsRoleZigbee); @@ -690,6 +700,10 @@ void ZigbeeManager::setupNodeSignals(ZigbeeNode *node) connect(node, &ZigbeeNode::reachableChanged, this, [=](){ emit nodeChanged(node->networkUuid(), node); }); + + connect(node, &ZigbeeNode::neighborTableRecordsChanged, this, [=](){ + emit nodeChanged(node->networkUuid(), node); + }); } diff --git a/libnymea-core/zigbee/zigbeemanager.h b/libnymea-core/zigbee/zigbeemanager.h index b3cae493..7f1ec426 100644 --- a/libnymea-core/zigbee/zigbeemanager.h +++ b/libnymea-core/zigbee/zigbeemanager.h @@ -95,6 +95,7 @@ public: ZigbeeError removeZigbeeNetwork(const QUuid &networkUuid); ZigbeeError setZigbeeNetworkPermitJoin(const QUuid &networkUuid, quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, uint duration = 120); ZigbeeError factoryResetNetwork(const QUuid &networkUuid); + ZigbeeError refreshNeighborTables(const QUuid &networkUuid); private: ZigbeeAdapters m_adapters; diff --git a/nymea.pro b/nymea.pro index 9fec9c53..99042487 100644 --- a/nymea.pro +++ b/nymea.pro @@ -5,7 +5,7 @@ NYMEA_VERSION_STRING=$$system('dpkg-parsechangelog | sed -n -e "s/^Version: //p" # define protocol versions JSON_PROTOCOL_VERSION_MAJOR=6 -JSON_PROTOCOL_VERSION_MINOR=1 +JSON_PROTOCOL_VERSION_MINOR=2 JSON_PROTOCOL_VERSION="$${JSON_PROTOCOL_VERSION_MAJOR}.$${JSON_PROTOCOL_VERSION_MINOR}" LIBNYMEA_API_VERSION_MAJOR=7 LIBNYMEA_API_VERSION_MINOR=3 diff --git a/tests/auto/api.json b/tests/auto/api.json index dffb76d2..4943ddde 100644 --- a/tests/auto/api.json +++ b/tests/auto/api.json @@ -1,4 +1,4 @@ -6.1 +6.2 { "enums": { "BasicType": [ @@ -509,6 +509,20 @@ "ZigbeeNetworkStateOnline", "ZigbeeNetworkStateError" ], + "ZigbeeNodeRelationship": [ + "ZigbeeNodeRelationshipParent", + "ZigbeeNodeRelationshipChild", + "ZigbeeNodeRelationshipSibling", + "ZigbeeNodeRelationshipNone", + "ZigbeeNodeRelationshipPreviousChild" + ], + "ZigbeeNodeRouteStatus": [ + "ZigbeeNodeRouteStatusActive", + "ZigbeeNodeRouteStatusDiscoveryUnderway", + "ZigbeeNodeRouteStatusDiscoveryFailed", + "ZigbeeNodeRouteStatusInactive", + "ZigbeeNodeRouteStatusValidationUnderway" + ], "ZigbeeNodeState": [ "ZigbeeNodeStateUninitialized", "ZigbeeNodeStateInitializing", @@ -2198,6 +2212,16 @@ "zigbeeError": "$ref:ZigbeeError" } }, + "Zigbee.RefreshNeighborTables": { + "description": "Refresh the neighbor table for all nodes. Note that calling this may cause a lot of traffic in the ZigBee network.", + "params": { + "networkUuid": "Uuid" + }, + "permissionScope": "PermissionScopeAdmin", + "returns": { + "zigbeeError": "$ref:ZigbeeError" + } + }, "Zigbee.RemoveNetwork": { "description": "Remove the ZigBee network with the given network uuid.", "params": { @@ -3252,6 +3276,13 @@ "ZigbeeAdapters": [ "$ref:ZigbeeAdapter" ], + "ZigbeeNeighborTableRecord": { + "depth": "Uint", + "lqi": "Uint", + "networkAddress": "Uint", + "permitJoining": "Bool", + "relationship": "$ref:ZigbeeNodeRelationship" + }, "ZigbeeNetwork": { "backend": "String", "baudRate": "Uint", @@ -3274,13 +3305,26 @@ "lqi": "Uint", "manufacturer": "String", "model": "String", + "neighborTableRecords": [ + "$ref:ZigbeeNeighborTableRecord" + ], "networkAddress": "Uint", "networkUuid": "Uuid", "reachable": "Bool", "receiverOnWhileIdle": "Bool", + "routingTableRecords": [ + "$ref:ZigbeeRoutingTableRecord" + ], "state": "$ref:ZigbeeNodeState", "type": "$ref:ZigbeeNodeType", "version": "String" + }, + "ZigbeeRoutingTableRecord": { + "destinationAddress": "Uint", + "manyToOne": "Bool", + "memoryConstrained": "Bool", + "nextHopAddress": "Uint", + "status": "$ref:ZigbeeNodeRouteStatus" } } }