From 2893f39e61680deb8b02a3458f528553f2dd9321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Thu, 10 Dec 2020 18:22:03 +0100 Subject: [PATCH] Improve reachable refresh behaviour --- .../backends/nxp/zigbeenetworknxp.cpp | 4 +- libnymea-zigbee/zigbeenetwork.cpp | 46 ++++++++++++++----- libnymea-zigbee/zigbeenetwork.h | 2 + 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp b/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp index f38b393..e9f37d1 100644 --- a/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp +++ b/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp @@ -94,7 +94,7 @@ ZigbeeNetworkReply *ZigbeeNetworkNxp::sendRequest(const ZigbeeNetworkRequest &re // Enqueu reply and send next one if we have enouth capacity m_replyQueue.enqueue(reply); - qCDebug(dcZigbeeNetwork()) << "=== Pending replies count (enqueued)" << m_replyQueue.count(); + //qCDebug(dcZigbeeNetwork()) << "=== Pending replies count (enqueued)" << m_replyQueue.count(); sendNextReply(); return reply; @@ -182,7 +182,7 @@ void ZigbeeNetworkNxp::sendNextReply() ZigbeeNetworkReply *reply = m_replyQueue.dequeue(); - qCDebug(dcZigbeeNetwork()) << "=== Pending replies count (dequeued)" << m_replyQueue.count(); + //qCDebug(dcZigbeeNetwork()) << "=== Pending replies count (dequeued)" << m_replyQueue.count(); ZigbeeInterfaceNxpReply *interfaceReply = m_controller->requestSendRequest(reply->request()); connect(interfaceReply, &ZigbeeInterfaceNxpReply::finished, reply, [this, reply, interfaceReply](){ diff --git a/libnymea-zigbee/zigbeenetwork.cpp b/libnymea-zigbee/zigbeenetwork.cpp index fbf6eeb..9335e5b 100644 --- a/libnymea-zigbee/zigbeenetwork.cpp +++ b/libnymea-zigbee/zigbeenetwork.cpp @@ -414,8 +414,6 @@ void ZigbeeNetwork::addNodeInternally(ZigbeeNode *node) emit macAddressChanged(m_macAddress); } - // FIXME: check when and how the note will be reachable - // Update database metrics of the node connect(node, &ZigbeeNode::lqiChanged, this, [this, node](quint8 lqi){ m_database->updateNodeLqi(node, lqi); @@ -469,6 +467,31 @@ ZigbeeNode *ZigbeeNetwork::createNode(quint16 shortAddress, const ZigbeeAddress return node; } +void ZigbeeNetwork::evaluateNextNodeReachableState() +{ + if (m_reachableRefreshAddresses.isEmpty()) + return; + + ZigbeeAddress address = m_reachableRefreshAddresses.takeFirst(); + ZigbeeNode *node = getZigbeeNode(address); + if (!node) { + // Not does not exit any more...continue + evaluateNextNodeReachableState(); + return; + } + + // Make a lqi request in order to check if the node is reachable + ZigbeeDeviceObjectReply *zdoReply = node->deviceObject()->requestMgmtLqi(); + connect(zdoReply, &ZigbeeDeviceObjectReply::finished, this, [=](){ + if (zdoReply->error()) { + qCWarning(dcZigbeeNetwork()) << node << "seems not to be reachable" << zdoReply->error(); + setNodeReachable(node, false); + } + + evaluateNextNodeReachableState(); + }); +} + void ZigbeeNetwork::loadNetwork() { if (m_networkLoaded) { @@ -757,11 +780,12 @@ void ZigbeeNetwork::verifyUnrecognizedNode(quint16 shortAddress) QByteArray response = zdoReply->responseData(); QDataStream stream(&response, QIODevice::ReadOnly); stream.setByteOrder(QDataStream::LittleEndian); - quint8 sqn; quint8 statusInt; quint64 ieeeAddressInt; - stream >> sqn >> statusInt >> ieeeAddressInt; + quint8 sqn; quint8 statusInt; quint64 ieeeAddressInt; quint16 nwkAddress; + stream >> sqn >> statusInt >> ieeeAddressInt >> nwkAddress; ZigbeeDeviceProfile::Status status = static_cast(statusInt); ZigbeeAddress ieeeAddress(ieeeAddressInt); - qCDebug(dcZigbeeDeviceObject()) << "Get IEEE address from unrecognized node finished" << status << ieeeAddress.toString() << node << ZigbeeUtils::convertByteArrayToHexString(zdoReply->responseData()); + node->m_extendedAddress = ieeeAddress; + qCDebug(dcZigbeeDeviceObject()) << "Get IEEE address from unrecognized node finished" << status << ieeeAddress.toString() << ZigbeeUtils::convertUint16ToHexString(nwkAddress) << ZigbeeUtils::convertByteArrayToHexString(zdoReply->responseData()); if (hasNode(ieeeAddress)) { // We know this node with this IEEE address, let's update the network address and save the new address in the database @@ -886,15 +910,11 @@ void ZigbeeNetwork::onNodeClusterAttributeChanged(ZigbeeCluster *cluster, const void ZigbeeNetwork::evaluateNodeReachableStates() { qCDebug(dcZigbeeNetwork()) << "Evaluate reachable state of nodes"; + m_reachableRefreshAddresses.clear(); + foreach (ZigbeeNode *node, m_nodes) { if (node->macCapabilities().receiverOnWhenIdle && node->shortAddress() != 0x0000) { - ZigbeeDeviceObjectReply *zdoReply = node->deviceObject()->requestMgmtLqi(); - connect(zdoReply, &ZigbeeDeviceObjectReply::finished, this, [=](){ - if (zdoReply->error()) { - qCWarning(dcZigbeeNetwork()) << node << "seems not to be reachable" << zdoReply->error(); - setNodeReachable(node, false); - } - }); + m_reachableRefreshAddresses.append(node->extendedAddress()); } else { // Note: sleeping devices should send some message within 6 hours, // otherwise the device might not be reachable any more @@ -908,6 +928,8 @@ void ZigbeeNetwork::evaluateNodeReachableStates() } } } + + evaluateNextNodeReachableState(); } QDebug operator<<(QDebug debug, ZigbeeNetwork *network) diff --git a/libnymea-zigbee/zigbeenetwork.h b/libnymea-zigbee/zigbeenetwork.h index ac85a93..7ee9d81 100644 --- a/libnymea-zigbee/zigbeenetwork.h +++ b/libnymea-zigbee/zigbeenetwork.h @@ -177,6 +177,8 @@ protected: quint8 m_permitJoiningRemaining = 0; QTimer *m_reachableRefreshTimer = nullptr; + QList m_reachableRefreshAddresses; + void evaluateNextNodeReachableState(); void setPermitJoiningEnabled(bool permitJoiningEnabled); void setPermitJoiningDuration(quint8 duration);