Make node init state more reliable and fix uninitialized node list

This commit is contained in:
Simon Stürz 2020-03-19 17:26:08 +01:00
parent e6fb4fbd08
commit c2d58a6c8d
6 changed files with 69 additions and 27 deletions

View File

@ -71,7 +71,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandErasePersistantData()
{ {
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeErasePersistentData, QByteArray())); ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeErasePersistentData, QByteArray()));
request.setDescription("Erase persistent data"); request.setDescription("Erase persistent data");
request.setTimoutIntervall(5000);
return sendRequest(request); return sendRequest(request);
} }

View File

@ -1073,7 +1073,7 @@ void ZigbeeNetworkNxp::startNetwork()
// FIXME: define if router or coordinator // FIXME: define if router or coordinator
qCDebug(dcZigbeeNetwork()) << "Start network..."; qCDebug(dcZigbeeNetwork()) << "Start network...";
if (state() == StateUninitialized) if (state() == StateUninitialized && !m_factoryResetting)
loadNetwork(); loadNetwork();
// Do a factory reset if there are no network configuration and create a new one from scratch // Do a factory reset if there are no network configuration and create a new one from scratch
@ -1150,9 +1150,9 @@ void ZigbeeNetworkNxp::reset()
void ZigbeeNetworkNxp::factoryResetNetwork() void ZigbeeNetworkNxp::factoryResetNetwork()
{ {
qCDebug(dcZigbeeNetwork()) << "Factory reset network and forget all information. This cannot be undone."; qCDebug(dcZigbeeNetwork()) << "Factory reset network and forget all information. This cannot be undone.";
m_factoryResetting = true;
clearSettings(); clearSettings();
setState(StateUninitialized); setState(StateUninitialized);
m_factoryResetting = true;
qCDebug(dcZigbeeNetwork()) << "The factory reset is finished. Start restart with a fresh network."; qCDebug(dcZigbeeNetwork()) << "The factory reset is finished. Start restart with a fresh network.";
startNetwork(); startNetwork();
} }

View File

@ -73,6 +73,10 @@ void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
switch (m_initState) { switch (m_initState) {
case InitStateNone: case InitStateNone:
m_initStateRetry = 0;
break;
case InitStateError:
break; break;
case InitStateNodeDescriptor: { case InitStateNodeDescriptor: {
qCDebug(dcZigbeeNode()) << "Request node descriptor for" << this; qCDebug(dcZigbeeNode()) << "Request node descriptor for" << this;
@ -82,8 +86,18 @@ void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
if (reply->status() != ZigbeeInterfaceReply::Success) { if (reply->status() != ZigbeeInterfaceReply::Success) {
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
m_initStateRetry++;
if (m_initStateRetry > 3) {
qCWarning(dcZigbeeNode()) << "Failed to get node descriptor after 3 retries. This node will not be added to the network.";
setInitState(InitStateError);
return;
} else {
setInitState(InitStateNodeDescriptor);
return;
}
} }
m_initStateRetry = 0;
setNodeDescriptorRawData(reply->additionalMessage().data()); setNodeDescriptorRawData(reply->additionalMessage().data());
setInitState(InitStatePowerDescriptor); setInitState(InitStatePowerDescriptor);
}); });
@ -97,8 +111,19 @@ void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
if (reply->status() != ZigbeeInterfaceReply::Success) { if (reply->status() != ZigbeeInterfaceReply::Success) {
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
m_initStateRetry++;
if (m_initStateRetry > 3) {
qCWarning(dcZigbeeNode()) << "Failed to get power descriptor after 3 retries. This node will not be added to the network.";
setInitState(InitStateError);
return;
} else {
setInitState(InitStatePowerDescriptor);
return;
}
} }
m_initStateRetry = 0;
QByteArray data = reply->additionalMessage().data(); QByteArray data = reply->additionalMessage().data();
quint8 sequenceNumber = 0; quint8 sequenceNumber = 0;
quint8 status = 0; quint8 status = 0;
@ -119,28 +144,39 @@ void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
if (reply->status() != ZigbeeInterfaceReply::Success) { if (reply->status() != ZigbeeInterfaceReply::Success) {
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
} else { m_initStateRetry++;
QByteArray data = reply->additionalMessage().data(); if (m_initStateRetry > 3) {
quint8 sequenceNumber = 0; qCWarning(dcZigbeeNode()) << "Failed to get active endpoints after 3 retries. This node will not be added to the network.";
quint8 status = 0; setInitState(InitStateError);
quint16 shortAddress = 0; return;
quint8 endpointCount = 0; } else {
setInitState(InitStateActiveEndpoints);
QDataStream stream(&data, QIODevice::ReadOnly); return;
stream >> sequenceNumber >> status >> shortAddress >> endpointCount;
qCDebug(dcZigbeeNode()) << "Active endpoint list received:";
qCDebug(dcZigbeeNode()) << "Sequence number" << sequenceNumber;
qCDebug(dcZigbeeNode()) << "Status:" << status;
qCDebug(dcZigbeeNode()) << "Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
qCDebug(dcZigbeeNode()) << "Endpoint count:" << endpointCount;
for (int i = 0; i < endpointCount; i++) {
quint8 endpointId = 0;
stream >> endpointId;
m_uninitializedEndpoints.append(endpointId);
qCDebug(dcZigbeeNode()) << " - " << ZigbeeUtils::convertByteToHexString(endpointId);
} }
} }
m_initStateRetry = 0;
QByteArray data = reply->additionalMessage().data();
quint8 sequenceNumber = 0;
quint8 status = 0;
quint16 shortAddress = 0;
quint8 endpointCount = 0;
QDataStream stream(&data, QIODevice::ReadOnly);
stream >> sequenceNumber >> status >> shortAddress >> endpointCount;
qCDebug(dcZigbeeNode()) << "Active endpoint list received:";
qCDebug(dcZigbeeNode()) << "Sequence number" << sequenceNumber;
qCDebug(dcZigbeeNode()) << "Status:" << status;
qCDebug(dcZigbeeNode()) << "Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
qCDebug(dcZigbeeNode()) << "Endpoint count:" << endpointCount;
for (int i = 0; i < endpointCount; i++) {
quint8 endpointId = 0;
stream >> endpointId;
m_uninitializedEndpoints.append(endpointId);
qCDebug(dcZigbeeNode()) << " - " << ZigbeeUtils::convertByteToHexString(endpointId);
}
setInitState(InitStateSimpleDescriptors); setInitState(InitStateSimpleDescriptors);
}); });
break; break;
@ -257,9 +293,8 @@ void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
ZigbeeCluster *basicCluster = endpoint->getInputCluster(Zigbee::ClusterIdBasic); ZigbeeCluster *basicCluster = endpoint->getInputCluster(Zigbee::ClusterIdBasic);
if (!basicCluster) { if (!basicCluster) {
qCWarning(dcZigbeeNode()) << "Failed to fetch basic cluster from" << endpoint; qCDebug(dcZigbeeNode()) << "This endpoint has no basic cluster" << endpoint;
setState(StateInitialized); continue;
return;
} }
m_uninitializedEndpoints.clear(); m_uninitializedEndpoints.clear();

View File

@ -43,6 +43,7 @@ class ZigbeeNodeNxp : public ZigbeeNode
public: public:
enum InitState { enum InitState {
InitStateNone, InitStateNone,
InitStateError,
InitStateNodeDescriptor, InitStateNodeDescriptor,
InitStatePowerDescriptor, InitStatePowerDescriptor,
InitStateActiveEndpoints, InitStateActiveEndpoints,
@ -58,6 +59,7 @@ public:
private: private:
ZigbeeBridgeControllerNxp *m_controller = nullptr; ZigbeeBridgeControllerNxp *m_controller = nullptr;
InitState m_initState = InitStateNone; InitState m_initState = InitStateNone;
int m_initStateRetry = 0;
QList<quint8> m_uninitializedEndpoints; QList<quint8> m_uninitializedEndpoints;
QList<quint16> m_uninitalizedBasicClusterAttributes; QList<quint16> m_uninitalizedBasicClusterAttributes;

View File

@ -335,7 +335,7 @@ public:
ClusterIdPressureMeasurement = 0x0403, ClusterIdPressureMeasurement = 0x0403,
ClusterIdFlowMeasurement = 0x0404, ClusterIdFlowMeasurement = 0x0404,
ClusterIdRelativeHumidityMeasurement = 0x0405, ClusterIdRelativeHumidityMeasurement = 0x0405,
ClusterIdOccapancySensing = 0x0406, ClusterIdOccupancySensing = 0x0406,
// Security and Safty // Security and Safty
ClusterIdIasZone = 0x0500, ClusterIdIasZone = 0x0500,

View File

@ -324,6 +324,11 @@ void ZigbeeNetwork::clearSettings()
removeNode(node); removeNode(node);
} }
foreach (ZigbeeNode *node, m_uninitializedNodes) {
m_uninitializedNodes.removeAll(node);
node->deleteLater();
}
qCDebug(dcZigbeeNetwork()) << "Clear network settings" << m_settingsFileName; qCDebug(dcZigbeeNetwork()) << "Clear network settings" << m_settingsFileName;
QSettings settings(m_settingsFileName, QSettings::IniFormat, this); QSettings settings(m_settingsFileName, QSettings::IniFormat, this);
settings.clear(); settings.clear();