From e2d5910e30dc6fe4d0fd590977665212ffcc4502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Mon, 14 Dec 2020 18:49:24 +0100 Subject: [PATCH] Fix deconz init interrupion due to timeout or uart flickering and retry 3 times before giving up --- .../deconz/zigbeebridgecontrollerdeconz.cpp | 1 - .../backends/deconz/zigbeenetworkdeconz.cpp | 57 ++++++++++++++----- .../backends/deconz/zigbeenetworkdeconz.h | 4 ++ .../backends/nxp/zigbeenetworknxp.cpp | 8 +-- libnymea-zigbee/zigbeenetwork.cpp | 11 ++++ libnymea-zigbee/zigbeenetwork.h | 7 ++- 6 files changed, 64 insertions(+), 24 deletions(-) diff --git a/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.cpp b/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.cpp index 1b632ec..9e5b057 100644 --- a/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.cpp +++ b/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.cpp @@ -767,7 +767,6 @@ void ZigbeeBridgeControllerDeconz::readDataIndication() return; } - // APS data indication received, process the content qCDebug(dcZigbeeController()) << "Reading data indication finished successfully" << "SQN:" << reply->sequenceNumber(); processDataIndication(reply->responseData()); diff --git a/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp b/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp index 4793a0e..1c75d36 100644 --- a/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp +++ b/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp @@ -294,8 +294,19 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo qCDebug(dcZigbeeController()) << "Configured network key successfully. SQN:" << reply->sequenceNumber(); } - // Configuration finished, lets start the network - setCreateNetworkState(CreateNetworkStateStartNetwork); + // Re-read the configurations + // Read all network parameters + ZigbeeInterfaceDeconzReply *reply = m_controller->readNetworkParameters(); + connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){ + if (reply->statusCode() != Deconz::StatusCodeSuccess) { + qCWarning(dcZigbeeController()) << "Could not read network parameters during network start up. SQN:" << reply->sequenceNumber() << reply->statusCode(); + } + + qCDebug(dcZigbeeController()) << m_controller->networkConfiguration(); + + // Configuration finished, lets start the network + setCreateNetworkState(CreateNetworkStateStartNetwork); + }); }); }); }); @@ -351,8 +362,9 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo } qCDebug(dcZigbeeNetwork()) << "We already have the coordinator node. Network starting done."; - m_database->saveNode(m_coordinatorNode); m_initializing = false; + setNodeInformation(m_coordinatorNode, "deCONZ", "", bridgeController()->firmwareVersion()); + setState(StateRunning); setPermitJoining(0); return; @@ -378,18 +390,8 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo } } -void ZigbeeNetworkDeconz::startNetworkInternally() +void ZigbeeNetworkDeconz::runNetworkInitProcess() { - qCDebug(dcZigbeeNetwork()) << "Start zigbee network internally"; - - m_createNewNetwork = false; - // Check if we have to create a pan ID and select the channel - if (panId() == 0 || !m_coordinatorNode) { - qCDebug(dcZigbeeNetwork()) << "Generate new extended PAN ID..."; - setExtendedPanId(ZigbeeUtils::generateRandomPanId()); - m_createNewNetwork = true; - } - // - Read the firmware version // - Read the network configuration parameters // - Read the network state @@ -403,9 +405,18 @@ void ZigbeeNetworkDeconz::startNetworkInternally() connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){ if (reply->statusCode() != Deconz::StatusCodeSuccess) { qCWarning(dcZigbeeController()) << "Request" << reply->command() << "finished with error" << reply->statusCode(); - // FIXME: set an appropriate error + m_initRetry++; + if (m_initRetry < 3) { + qCDebug(dcZigbeeNetwork()) << "Retry to initialize network" << m_initRetry << "/ 3"; + runNetworkInitProcess(); + } else { + qCWarning(dcZigbeeNetwork()) << "Failed to read firmware version after 3 attempts. Giving up"; + m_controller->disable(); + } return; } + + m_initRetry = 0; qCDebug(dcZigbeeNetwork()) << "Version request finished successfully" << ZigbeeUtils::convertByteArrayToHexString(reply->responseData()); // Note: version is an uint32 value, little endian, but we can read the individual bytes in reversed order quint8 majorVersion = static_cast(reply->responseData().at(3)); @@ -498,6 +509,22 @@ void ZigbeeNetworkDeconz::startNetworkInternally() }); } +void ZigbeeNetworkDeconz::startNetworkInternally() +{ + qCDebug(dcZigbeeNetwork()) << "Start zigbee network internally"; + + m_createNewNetwork = false; + // Check if we have to create a pan ID and select the channel + if (panId() == 0 || !m_coordinatorNode) { + qCDebug(dcZigbeeNetwork()) << "Generate new extended PAN ID..."; + setExtendedPanId(ZigbeeUtils::generateRandomPanId()); + m_createNewNetwork = true; + } + + m_initRetry = 0; + runNetworkInitProcess(); +} + void ZigbeeNetworkDeconz::onControllerAvailableChanged(bool available) { if (!available) { diff --git a/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.h b/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.h index c380fdb..55d5b85 100644 --- a/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.h +++ b/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.h @@ -71,6 +71,10 @@ private: QTimer *m_pollNetworkStateTimer = nullptr; void setCreateNetworkState(CreateNetworkState state); + // Init procedure + int m_initRetry = 0; + void runNetworkInitProcess(); + ZigbeeNetworkReply *requestSetPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe); protected: diff --git a/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp b/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp index 27eb3f8..ae3da8a 100644 --- a/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp +++ b/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp @@ -393,7 +393,6 @@ void ZigbeeNetworkNxp::onControllerStateChanged(ZigbeeBridgeControllerNxp::Contr qCDebug(dcZigbeeNetwork()) << "We already have the coordinator node. Network starting done."; setNodeInformation(m_coordinatorNode, "NXP", "JN516x", bridgeController()->firmwareVersion()); - m_database->saveNode(m_coordinatorNode); setPermitJoining(0); setState(StateRunning); return; @@ -448,11 +447,8 @@ void ZigbeeNetworkNxp::onControllerStateChanged(ZigbeeBridgeControllerNxp::Contr case ZigbeeBridgeControllerNxp::ControllerStateRunningUninitialized: { // Create the database if there is no database available setState(StateStarting); - if (!m_database) { - QString networkDatabaseFileName = settingsDirectory().absolutePath() + QDir::separator() + QString("zigbee-network-%1.db").arg(networkUuid().toString().remove('{').remove('}')); - qCDebug(dcZigbeeNetwork()) << "Using ZigBee network database" << QFileInfo(networkDatabaseFileName).fileName(); - m_database = new ZigbeeNetworkDatabase(this, networkDatabaseFileName, this); - } + + initializeDatabase(); qCDebug(dcZigbeeNetwork()) << "Request controller version"; ZigbeeInterfaceNxpReply *reply = m_controller->requestVersion(); diff --git a/libnymea-zigbee/zigbeenetwork.cpp b/libnymea-zigbee/zigbeenetwork.cpp index 004f268..5d7e3ba 100644 --- a/libnymea-zigbee/zigbeenetwork.cpp +++ b/libnymea-zigbee/zigbeenetwork.cpp @@ -455,6 +455,15 @@ void ZigbeeNetwork::removeNodeInternally(ZigbeeNode *node) node->deleteLater(); } +void ZigbeeNetwork::initializeDatabase() +{ + if (!m_database) { + QString networkDatabaseFileName = settingsDirectory().absolutePath() + QDir::separator() + QString("zigbee-network-%1.db").arg(networkUuid().toString().remove('{').remove('}')); + qCDebug(dcZigbeeNetwork()) << "Using ZigBee network database" << QFileInfo(networkDatabaseFileName).fileName(); + m_database = new ZigbeeNetworkDatabase(this, networkDatabaseFileName, this); + } +} + ZigbeeNode *ZigbeeNetwork::createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent) { return new ZigbeeNode(this, shortAddress, extendedAddress, parent); @@ -627,6 +636,8 @@ void ZigbeeNetwork::setNodeInformation(ZigbeeNode *node, const QString &manufact node->m_version = version; emit node->versionChanged(node->version()); + + m_database->saveNode(m_coordinatorNode); } void ZigbeeNetwork::setState(ZigbeeNetwork::State state) diff --git a/libnymea-zigbee/zigbeenetwork.h b/libnymea-zigbee/zigbeenetwork.h index d36f3f2..8f6d3e7 100644 --- a/libnymea-zigbee/zigbeenetwork.h +++ b/libnymea-zigbee/zigbeenetwork.h @@ -138,6 +138,9 @@ private: qint32 m_serialBaudrate = 115200; ZigbeeAddress m_macAddress; + ZigbeeNetworkDatabase *m_database = nullptr; + bool m_networkLoaded = false; + // Continuous ASP sequence number for network requests quint8 m_sequenceNumber = 0; @@ -164,8 +167,8 @@ protected: Error m_error = ErrorNoError; ZigbeeNode *m_coordinatorNode = nullptr; ZigbeeSecurityConfiguration m_securityConfiguration; - ZigbeeNetworkDatabase *m_database = nullptr; - bool m_networkLoaded = false; + + void initializeDatabase(); ZigbeeNode *createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent); ZigbeeNode *createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, quint8 macCapabilities, QObject *parent);