From 317cc255617192efb4ca65f7bcbb93196ac8e875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Fri, 17 May 2019 15:35:26 +0200 Subject: [PATCH] Add attribute report fix for firmware bug --- libnymea-zigbee/zigbeenetworkmanager.cpp | 138 +++++++++++------------ libnymea-zigbee/zigbeenetworkmanager.h | 6 +- 2 files changed, 72 insertions(+), 72 deletions(-) diff --git a/libnymea-zigbee/zigbeenetworkmanager.cpp b/libnymea-zigbee/zigbeenetworkmanager.cpp index 7570afd..0a70171 100644 --- a/libnymea-zigbee/zigbeenetworkmanager.cpp +++ b/libnymea-zigbee/zigbeenetworkmanager.cpp @@ -38,7 +38,19 @@ void ZigbeeNetworkManager::setPermitJoining(bool permitJoining) return; ZigbeeInterfaceReply *reply = m_controller->commandPermitJoin(0, (permitJoining ? 255 : 0)); - connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandPermitJoiningFinished); + connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply, permitJoining](){ + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully." << permitJoining; + + // Read the permit joining status back in order to update the state + readPermitJoinStatus(); + }); } void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState state) @@ -67,8 +79,7 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState } case StartingStateGetVersion: { qCDebug(dcZigbeeNetwork()) << "Starting state changed: Get controller version"; - ZigbeeInterfaceReply *reply = m_controller->commandGetVersion(); - connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandGetVersionFinished); + readControllerVersion(); break; } case StartingStateSetPanId: { @@ -115,8 +126,7 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState } case StartingStateGetPermitJoinStatus: { qCDebug(dcZigbeeNetwork()) << "Starting state changed: Get permit join status"; - ZigbeeInterfaceReply *reply = m_controller->commandGetPermitJoinStatus(); - connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandGetPermitJoiningStatusFinished); + readPermitJoinStatus(); break; } case StartingStateReadeNodeDescriptor: { @@ -140,6 +150,57 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState } } +void ZigbeeNetworkManager::readControllerVersion() +{ + ZigbeeInterfaceReply *reply = m_controller->commandGetVersion(); + connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply](){ + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + if (reply->additionalMessage().data().count() != 4) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << ":" << "Invalid payload size"; + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + + // Parse version + quint16 majorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(0, 2)); + quint16 minorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(2, 2)); + + m_controllerFirmwareVersion = QString("%1.%2").arg(majorVersion).arg(minorVersion); + qCDebug(dcZigbeeNetwork()) << "Controller version:" << m_controllerFirmwareVersion; + + if (m_startingState == StartingStateGetVersion) setStartingState(StartingStateSetPanId); + + }); +} + +void ZigbeeNetworkManager::readPermitJoinStatus() +{ + ZigbeeInterfaceReply *reply = m_controller->commandGetPermitJoinStatus(); + connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply](){ + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + qCDebug(dcZigbeeController()) << reply->additionalMessage(); + + m_permitJoining = static_cast(reply->additionalMessage().data().at(0)); + emit permitJoiningChanged(m_permitJoining); + + if (m_startingState == StartingStateGetPermitJoinStatus) setStartingState(StartingStateReadeNodeDescriptor); + }); +} + //void ZigbeeNetworkManager::requestMatchDescriptor(const quint16 &shortAddress, const Zigbee::ZigbeeProfile &profile) //{ @@ -209,33 +270,6 @@ void ZigbeeNetworkManager::onCommandErasePersistentDataFinished() } } -void ZigbeeNetworkManager::onCommandGetVersionFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - if (reply->additionalMessage().data().count() != 4) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << ":" << "Invalid payload size"; - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - - // Parse version - quint16 majorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(0, 2)); - quint16 minorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(2, 2)); - - m_controllerFirmwareVersion = QString("%1.%2").arg(majorVersion).arg(minorVersion); - qCDebug(dcZigbeeNetwork()) << "Controller version:" << m_controllerFirmwareVersion; - - if (m_startingState == StartingStateGetVersion) setStartingState(StartingStateSetPanId); -} - void ZigbeeNetworkManager::onCommandSetExtendedPanIdFinished() { ZigbeeInterfaceReply *reply = static_cast(sender()); @@ -309,42 +343,6 @@ void ZigbeeNetworkManager::onCommandStartScanFinished() processNetworkFormed(reply->additionalMessage()); } -void ZigbeeNetworkManager::onCommandGetPermitJoiningStatusFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - qCDebug(dcZigbeeController()) << reply->additionalMessage(); - - m_permitJoining = static_cast(reply->additionalMessage().data().at(0)); - emit permitJoiningChanged(m_permitJoining); - - if (m_startingState == StartingStateGetPermitJoinStatus) setStartingState(StartingStateReadeNodeDescriptor); -} - -void ZigbeeNetworkManager::onCommandPermitJoiningFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - - // Read the permit joining status back in order to update the state - ZigbeeInterfaceReply *getJoiningReply = m_controller->commandGetPermitJoinStatus(); - connect(getJoiningReply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandGetPermitJoiningStatusFinished); -} - void ZigbeeNetworkManager::onCommandRequestMatchDescriptorFinished() { ZigbeeInterfaceReply *reply = static_cast(sender()); @@ -473,10 +471,10 @@ void ZigbeeNetworkManager::processNetworkFormed(const ZigbeeInterfaceMessage &me quint8 channel = static_cast(data.at(11)); qCDebug(dcZigbeeNetwork()).noquote() << "Network" << networkStatusString; + qCDebug(dcZigbeeNetwork()) << " Extended PAN ID:" << extendedPanId(); qCDebug(dcZigbeeNetwork()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(extendedAddress); qCDebug(dcZigbeeNetwork()) << " Channel:" << channel; - qCDebug(dcZigbeeNetwork()) << " Extended PAN ID:" << extendedPanId(); qCDebug(dcZigbeeNetwork()) << " Permit joining:" << permitJoining(); m_networkRunning = true; @@ -829,6 +827,7 @@ void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished() if (m_startingState == StartingStateReadPowerDescriptor) { setStartingState(StartingStateNone); setState(StateRunning); + readControllerVersion(); foreach (ZigbeeNode *node, nodes()) { node->setConnected(true); } @@ -1108,6 +1107,7 @@ void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage & QByteArray attributeData = data.left(dataSize); if (attributeData.length() != dataSize) { + qCCritical(dcZigbeeNetwork()) << "HACK"; // Note: the NXP firmware for JN5169 has a bug here and does not send the attributeStatus. // Repars data without attribute status sequenceNumber = 0; diff --git a/libnymea-zigbee/zigbeenetworkmanager.h b/libnymea-zigbee/zigbeenetworkmanager.h index 83d4de4..feddf74 100644 --- a/libnymea-zigbee/zigbeenetworkmanager.h +++ b/libnymea-zigbee/zigbeenetworkmanager.h @@ -54,6 +54,9 @@ private: bool m_networkRunning = false; bool m_factoryResetting = false; + void readControllerVersion(); + void readPermitJoinStatus(); + signals: void permitJoiningChanged(bool permitJoining); @@ -65,14 +68,11 @@ private slots: void onCommandResetControllerFinished(); void onCommandSoftResetControllerFinished(); void onCommandErasePersistentDataFinished(); - void onCommandGetVersionFinished(); void onCommandSetExtendedPanIdFinished(); void onCommandSetChannelMaskFinished(); void onCommandSetNodeTypeFinished(); void onCommandStartNetworkFinished(); void onCommandStartScanFinished(); - void onCommandGetPermitJoiningStatusFinished(); - void onCommandPermitJoiningFinished(); void onCommandEnableWhitelistFinished(); void onCommandNodeDescriptorRequestFinished();