From 7ab98f65f7cd5f95655f86eeba52b51ec42a924d Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 16 Nov 2020 15:14:17 +0100 Subject: [PATCH] Improve the plugin <-> node matching mechanism * A ZigbeeNode can now only be claimed by 1 plugin. * Unhandled nodes will now be re-evaluated on restart as there might have been new plugins installed which could handle this node now. --- .../zigbeehardwareresourceimplementation.cpp | 59 +++++++++++++++++-- .../zigbeehardwareresourceimplementation.h | 7 ++- .../hardware/zigbee/zigbeehardwareresource.h | 2 +- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/libnymea-core/hardware/zigbee/zigbeehardwareresourceimplementation.cpp b/libnymea-core/hardware/zigbee/zigbeehardwareresourceimplementation.cpp index 09cddf8e..46d84594 100644 --- a/libnymea-core/hardware/zigbee/zigbeehardwareresourceimplementation.cpp +++ b/libnymea-core/hardware/zigbee/zigbeehardwareresourceimplementation.cpp @@ -69,14 +69,32 @@ void ZigbeeHardwareResourceImplementation::registerHandler(ZigbeeHandler *handle m_handlers.insert(type, handler); } -ZigbeeNode *ZigbeeHardwareResourceImplementation::getNode(const QUuid &networkUuid, const ZigbeeAddress &extendedAddress) +ZigbeeNode *ZigbeeHardwareResourceImplementation::claimNode(ZigbeeHandler *handler, const QUuid &networkUuid, const ZigbeeAddress &extendedAddress) { + if (!m_handlers.values().contains(handler)) { + qCWarning(dcZigbeeResource()) << "Handler" << handler->name() << "is not registered. Not allowing node to be claimed."; + return nullptr; + } + ZigbeeNetwork *network = m_zigbeeManager->zigbeeNetworks().value(networkUuid); if (!network) { qCWarning(dcZigbeeResource()) << "Network" << networkUuid << "not found."; return nullptr; } - return network->getZigbeeNode(extendedAddress); + + ZigbeeNode *node = network->getZigbeeNode(extendedAddress); + if (!node) { + qCWarning(dcZigbeeResource()) << "Node with address" << extendedAddress << "not found in Zigbee network" << networkUuid.toString(); + return nullptr; + } + + if (m_nodeHandlers.contains(node)) { + qCWarning(dcZigbeeResource()) << "Node with address" << extendedAddress << "is already claimed by another handler (" << m_nodeHandlers.value(node)->name() << "). Not allowing node to be reclaimed."; + return nullptr; + } + + m_nodeHandlers.insert(node, handler); + return node; } void ZigbeeHardwareResourceImplementation::removeNodeFromNetwork(const QUuid &networkUuid, ZigbeeNode *node) @@ -142,6 +160,24 @@ bool ZigbeeHardwareResourceImplementation::disable() return true; } +void ZigbeeHardwareResourceImplementation::thingsLoaded() +{ + m_thingsLoaded = true; + + // We can assume here that all handled nodes have been claimed by plugins + // In case we started up and loaded new zigbee plugins, let's try to get all previously joined nodes handled now... + foreach (ZigbeeNetwork *network, m_zigbeeManager->zigbeeNetworks()) { + if (network->state() == ZigbeeNetwork::StateRunning) { + foreach (ZigbeeNode *node, network->nodes()) { + if (!m_nodeHandlers.contains(node)) { + qCDebug(dcZigbeeResource()) << "Node" << node << "is not yet handled by any plugin. Trying to find a suitable plugin."; + onZigbeeNodeAdded(network->networkUuid(), node); + } + } + } + } +} + void ZigbeeHardwareResourceImplementation::onZigbeeAvailableChanged(bool available) { if (available) { @@ -156,6 +192,18 @@ void ZigbeeHardwareResourceImplementation::onZigbeeAvailableChanged(bool availab void ZigbeeHardwareResourceImplementation::onZigbeeNetworkChanged(ZigbeeNetwork *network) { emit networkStateChanged(network->networkUuid(), network->state()); + + // If the network is now ready and things have been loaded already, check if there are + // unclaimed nodes that might be handled now. This might happen if a node joins the network + // but no appropriate plugin had been installed at the time. If additional plugins have + // been installed now, such nodes might be handled by them now. + if (network->state() == ZigbeeNetwork::StateRunning && m_thingsLoaded) { + foreach (ZigbeeNode *node, network->nodes()) { + if (!m_nodeHandlers.contains(node)) { + onZigbeeNodeAdded(network->networkUuid(), node); + } + } + } } void ZigbeeHardwareResourceImplementation::onZigbeeNodeAdded(const QUuid &networkUuid, ZigbeeNode *node) @@ -165,6 +213,7 @@ void ZigbeeHardwareResourceImplementation::onZigbeeNodeAdded(const QUuid &networ foreach (ZigbeeHandler *tmp, m_handlers) { if (tmp->handleNode(node, networkUuid)) { handler = tmp; + m_nodeHandlers.insert(node, handler); qCDebug(dcZigbeeResource()) << "Node" << node << "taken by handler" << handler->name(); break; } @@ -179,10 +228,10 @@ void ZigbeeHardwareResourceImplementation::onZigbeeNodeRemoved(const QUuid &netw { qCDebug(dcZigbeeResource()) << node << "left the network" << m_zigbeeManager->zigbeeNetworks().value(networkUuid); - foreach (ZigbeeHandler *tmp, m_handlers) { - tmp->handleRemoveNode(node, networkUuid); + ZigbeeHandler *handler = m_nodeHandlers.value(node); + if (handler) { + handler->handleRemoveNode(node, networkUuid); } - } } diff --git a/libnymea-core/hardware/zigbee/zigbeehardwareresourceimplementation.h b/libnymea-core/hardware/zigbee/zigbeehardwareresourceimplementation.h index fa84f6a0..c01e2b8b 100644 --- a/libnymea-core/hardware/zigbee/zigbeehardwareresourceimplementation.h +++ b/libnymea-core/hardware/zigbee/zigbeehardwareresourceimplementation.h @@ -50,7 +50,7 @@ public: void registerHandler(ZigbeeHandler *handler, HandlerType type = HandlerTypeVendor) override; - ZigbeeNode* getNode(const QUuid &networkUuid, const ZigbeeAddress &extendedAddress) override; + ZigbeeNode* claimNode(ZigbeeHandler *handler, const QUuid &networkUuid, const ZigbeeAddress &extendedAddress) override; void removeNodeFromNetwork(const QUuid &networkUuid, ZigbeeNode *node) override; ZigbeeNetwork::State networkState(const QUuid &networkUuid) override; @@ -59,6 +59,8 @@ public slots: bool enable(); bool disable(); + void thingsLoaded(); + protected: void setEnabled(bool enabled) override; @@ -75,6 +77,9 @@ private: QMultiMap m_handlers; + bool m_thingsLoaded = false; + QHash m_nodeHandlers; + }; } diff --git a/libnymea/hardware/zigbee/zigbeehardwareresource.h b/libnymea/hardware/zigbee/zigbeehardwareresource.h index dcbe5e6a..5f8a64a7 100644 --- a/libnymea/hardware/zigbee/zigbeehardwareresource.h +++ b/libnymea/hardware/zigbee/zigbeehardwareresource.h @@ -55,7 +55,7 @@ public: virtual ~ZigbeeHardwareResource() = default; virtual void registerHandler(ZigbeeHandler *handler, HandlerType type = HandlerTypeVendor) = 0; - virtual ZigbeeNode* getNode(const QUuid &networkUuid, const ZigbeeAddress &extendedAddress) = 0; + virtual ZigbeeNode* claimNode(ZigbeeHandler *hanlder, const QUuid &networkUuid, const ZigbeeAddress &extendedAddress) = 0; virtual void removeNodeFromNetwork(const QUuid &networkUuid, ZigbeeNode *node) = 0; virtual ZigbeeNetwork::State networkState(const QUuid &networkUuid) = 0;