Merge PR #80: Rework the reachable refreshing and manual LQI/RTG fetching

electricalmeasurement-formatting
jenkins 2023-02-21 17:42:44 +01:00
commit d5df291bf3
2 changed files with 40 additions and 30 deletions

View File

@ -52,12 +52,12 @@ ZigbeeNetwork::ZigbeeNetwork(const QUuid &networkUuid, QObject *parent) :
}); });
m_reachableRefreshTimer = new QTimer(this); m_reachableRefreshTimer = new QTimer(this);
m_reachableRefreshTimer->setInterval(120000); m_reachableRefreshTimer->setInterval(60000);
connect(m_reachableRefreshTimer, &QTimer::timeout, this, &ZigbeeNetwork::evaluateNodeReachableStates); connect(m_reachableRefreshTimer, &QTimer::timeout, this, &ZigbeeNetwork::evaluateNodeReachableStates);
connect(this, &ZigbeeNetwork::stateChanged, this, [this](ZigbeeNetwork::State state){ connect(this, &ZigbeeNetwork::stateChanged, this, [this](ZigbeeNetwork::State state){
if (state == ZigbeeNetwork::StateRunning) { if (state == ZigbeeNetwork::StateRunning) {
evaluateNodeReachableStates(); refreshNeighborTables();
m_reachableRefreshTimer->start(); m_reachableRefreshTimer->start();
} else { } else {
foreach (ZigbeeNode *node, m_nodes) { foreach (ZigbeeNode *node, m_nodes) {
@ -334,10 +334,10 @@ void ZigbeeNetwork::refreshNeighborTables()
{ {
foreach (ZigbeeNode *node, m_nodes) { foreach (ZigbeeNode *node, m_nodes) {
if (node->macCapabilities().receiverOnWhenIdle) { if (node->macCapabilities().receiverOnWhenIdle) {
m_refreshNeighborTableAddresses.append(node->extendedAddress()); m_refreshLqiAndRtgTablesAddresses.append(node->extendedAddress());
} }
} }
fetchNextNodeLqiTable(); fetchNextNodeLqiAndRtgTables();
} }
void ZigbeeNetwork::printNetwork() void ZigbeeNetwork::printNetwork()
@ -467,21 +467,18 @@ ZigbeeNode *ZigbeeNetwork::createNode(quint16 shortAddress, const ZigbeeAddress
return node; return node;
} }
void ZigbeeNetwork::fetchNextNodeLqiTable() void ZigbeeNetwork::fetchNextNodeLqiAndRtgTables()
{ {
ZigbeeNode *node = nullptr; ZigbeeNode *node = nullptr;
while (!node && !m_refreshNeighborTableAddresses.isEmpty()) { while (!node && !m_refreshLqiAndRtgTablesAddresses.isEmpty()) {
node = getZigbeeNode(m_refreshNeighborTableAddresses.takeFirst()); node = getZigbeeNode(m_refreshLqiAndRtgTablesAddresses.takeFirst());
}
while (!node && !m_reachableRefreshAddresses.isEmpty()) {
node = getZigbeeNode(m_reachableRefreshAddresses.takeFirst());
} }
if (!node) { if (!node) {
// Nothing to do... // Nothing to do...
return; return;
} }
qCDebug(dcZigbeeNetwork()) << "Refreshing LQI neighbor table for node" << node->shortAddress() << node->modelName(); qCDebug(dcZigbeeNetwork()) << "Fetching LQI and RTG tables for node" << node->shortAddress() << node->modelName();
// Make a lqi request in order to check if the node is reachable // Make a lqi request in order to check if the node is reachable
ZigbeeReply *reply = node->readLqiTableEntries(); ZigbeeReply *reply = node->readLqiTableEntries();
@ -489,20 +486,15 @@ void ZigbeeNetwork::fetchNextNodeLqiTable()
if (reply->error()) { if (reply->error()) {
qCWarning(dcZigbeeNetwork()) << node << "seems not to be reachable" << reply->error(); qCWarning(dcZigbeeNetwork()) << node << "seems not to be reachable" << reply->error();
setNodeReachable(node, false); setNodeReachable(node, false);
fetchNextNodeLqiAndRtgTables();
return;
} else { } else {
setNodeReachable(node, true); setNodeReachable(node, true);
} }
ZigbeeReply *reply = node->readRoutingTableEntries(); ZigbeeReply *reply = node->readRoutingTableEntries();
connect(reply, &ZigbeeReply::finished, this, [=]() { connect(reply, &ZigbeeReply::finished, this, [=]() {
fetchNextNodeLqiAndRtgTables();
// While we still need to refresh neighbor tables, send the next request right away...
if (!m_refreshNeighborTableAddresses.isEmpty()) {
fetchNextNodeLqiTable();
} else {
// ... else be easier on the resources for the cyclic refresh
QTimer::singleShot(5000, this, &ZigbeeNetwork::fetchNextNodeLqiTable);
}
}); });
}); });
} }
@ -958,16 +950,15 @@ void ZigbeeNetwork::evaluateNodeReachableStates()
foreach (ZigbeeNode *node, m_nodes) { foreach (ZigbeeNode *node, m_nodes) {
if (node->shortAddress() == 0x0000) { if (node->shortAddress() == 0x0000) {
// While we wouldn't need to check ourselves for being reachable, do it nevertheless so we keep the continue;
// neighbor table in sync which is useful in logs }
if (!m_reachableRefreshAddresses.contains(node->extendedAddress())) {
m_reachableRefreshAddresses.append(node->extendedAddress()); if (m_reachableRefreshAddresses.contains(node->extendedAddress())) {
} // Node is already scheduled for refresh
continue; continue;
} }
if (node->macCapabilities().receiverOnWhenIdle) { if (node->macCapabilities().receiverOnWhenIdle) {
// Lets send a request to all things which are not reachable // Lets send a request to all things which are not reachable
if (!node->reachable()) { if (!node->reachable()) {
if (!m_reachableRefreshAddresses.contains(node->extendedAddress())) { if (!m_reachableRefreshAddresses.contains(node->extendedAddress())) {
@ -980,8 +971,7 @@ void ZigbeeNetwork::evaluateNodeReachableStates()
// Lets send a request to nodes which have not been seen more than 10 min // Lets send a request to nodes which have not been seen more than 10 min
qulonglong msSinceLastSeen = node->lastSeen().msecsTo(QDateTime::currentDateTimeUtc()); qulonglong msSinceLastSeen = node->lastSeen().msecsTo(QDateTime::currentDateTimeUtc());
qCDebug(dcZigbeeNetwork()) << node << "has been seen the last time" << QTime::fromMSecsSinceStartOfDay(msSinceLastSeen).toString() << "ago."; qCDebug(dcZigbeeNetwork()) << node << "has been seen the last time" << QTime::fromMSecsSinceStartOfDay(msSinceLastSeen).toString() << "ago.";
// 10 min = 10 * 60 * 1000 = 600000 ms if (msSinceLastSeen > 60 * 60 * 1000) { // 1 hour
if (msSinceLastSeen > 600000 && !m_reachableRefreshAddresses.contains(node->extendedAddress())) {
qCDebug(dcZigbeeNetwork()) << node << "has not been seen in" << (msSinceLastSeen / 1000 / 60) << "minutes. Scheduling LQI request."; qCDebug(dcZigbeeNetwork()) << node << "has not been seen in" << (msSinceLastSeen / 1000 / 60) << "minutes. Scheduling LQI request.";
m_reachableRefreshAddresses.append(node->extendedAddress()); m_reachableRefreshAddresses.append(node->extendedAddress());
} }
@ -999,7 +989,26 @@ void ZigbeeNetwork::evaluateNodeReachableStates()
} }
} }
fetchNextNodeLqiTable(); ZigbeeNode *node = nullptr;
while (!node && !m_reachableRefreshAddresses.isEmpty()) {
node = getZigbeeNode(m_reachableRefreshAddresses.takeFirst());
}
if (!node) {
// Nothing to do...
return;
}
// Make a lqi request in order to check if the node is reachable
qCDebug(dcZigbeeNetwork()) << "Polling Node" << node->shortAddress() << node->manufacturerName() << node->modelName() << "for reachability";
ZigbeeReply *reply = node->readLqiTableEntries();
connect(reply, &ZigbeeReply::finished, this, [=](){
if (reply->error()) {
qCWarning(dcZigbeeNetwork()) << node << "seems not to be reachable" << reply->error();
setNodeReachable(node, false);
} else {
setNodeReachable(node, true);
}
});
} }
QDebug operator<<(QDebug debug, ZigbeeNetwork *network) QDebug operator<<(QDebug debug, ZigbeeNetwork *network)

View File

@ -187,8 +187,9 @@ protected:
QTimer *m_reachableRefreshTimer = nullptr; QTimer *m_reachableRefreshTimer = nullptr;
QList<ZigbeeAddress> m_reachableRefreshAddresses; QList<ZigbeeAddress> m_reachableRefreshAddresses;
QList<ZigbeeAddress> m_refreshNeighborTableAddresses;
void fetchNextNodeLqiTable(); void fetchNextNodeLqiAndRtgTables();
QList<ZigbeeAddress> m_refreshLqiAndRtgTablesAddresses;
void setPermitJoiningState(bool permitJoiningEnabled, quint8 duration = 0); void setPermitJoiningState(bool permitJoiningEnabled, quint8 duration = 0);