diff --git a/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp b/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp index 460db59..3415baa 100644 --- a/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp +++ b/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp @@ -46,7 +46,6 @@ ZigbeeNetworkDeconz::ZigbeeNetworkDeconz(const QUuid &networkUuid, QObject *pare m_pollNetworkStateTimer->setInterval(1000); m_pollNetworkStateTimer->setSingleShot(false); connect(m_pollNetworkStateTimer, &QTimer::timeout, this, &ZigbeeNetworkDeconz::onPollNetworkStateTimeout); - } ZigbeeBridgeController *ZigbeeNetworkDeconz::bridgeController() const diff --git a/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp b/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp index 35d714a..947d020 100644 --- a/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp +++ b/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp @@ -78,12 +78,12 @@ ZigbeeNetworkReply *ZigbeeNetworkNxp::sendRequest(const ZigbeeNetworkRequest &re // Send the request, and keep the reply until transposrt, zigbee trasmission and response arrived connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply](){ if (!m_pendingReplies.values().contains(reply)) { - qCWarning(dcZigbeeNetwork()) << "Reply finished but not in the pending replies list" << reply; + qCWarning(dcZigbeeNetwork()) << "#### Reply finished but not in the pending replies list" << reply; return; } quint8 requestId = m_pendingReplies.key(reply); m_pendingReplies.remove(requestId); - //qCWarning(dcZigbeeNetwork()) << "#### Removed network reply" << reply << "ID:" << requestId << "Current reply count" << m_pendingReplies.count(); + qCWarning(dcZigbeeNetwork()) << "#### Removed network reply" << reply << "ID:" << requestId << "Current reply count" << m_pendingReplies.count(); }); // Finish the reply right the way if the network is offline @@ -110,7 +110,7 @@ ZigbeeNetworkReply *ZigbeeNetworkNxp::sendRequest(const ZigbeeNetworkRequest &re quint8 networkRequestId = interfaceReply->responseData().at(0); //qCDebug(dcZigbeeNetwork()) << "Request has network SQN" << networkRequestId; reply->request().setRequestId(networkRequestId); - //qCWarning(dcZigbeeNetwork()) << "#### Insert network reply" << reply << "ID:" << networkRequestId << "Current reply count" << m_pendingReplies.count(); + qCWarning(dcZigbeeNetwork()) << "#### Insert network reply" << reply << "ID:" << networkRequestId << "Current reply count" << m_pendingReplies.count(); m_pendingReplies.insert(networkRequestId, reply); // The request has been sent successfully to the device, start the timeout timer now startWaitingReply(reply); diff --git a/libnymea-zigbee/zcl/zigbeecluster.cpp b/libnymea-zigbee/zcl/zigbeecluster.cpp index 4f69126..8336c35 100644 --- a/libnymea-zigbee/zcl/zigbeecluster.cpp +++ b/libnymea-zigbee/zcl/zigbeecluster.cpp @@ -171,7 +171,6 @@ ZigbeeClusterReply *ZigbeeCluster::executeGlobalCommand(quint8 command, const QB ZigbeeNetworkReply *networkReply = m_network->sendRequest(request); connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){ if (!verifyNetworkError(zclReply, networkReply)) { - qCWarning(dcZigbeeClusterLibrary()) << "Failed to read attributes from" << m_node << m_endpoint << this << networkReply->error(); finishZclReply(zclReply); return; } @@ -227,9 +226,6 @@ ZigbeeClusterReply *ZigbeeCluster::executeClusterCommand(quint8 command, const Q ZigbeeNetworkReply *networkReply = m_network->sendRequest(request); connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){ if (!verifyNetworkError(zclReply, networkReply)) { - qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request" - << m_node << networkReply->error() - << networkReply->zigbeeApsStatus(); finishZclReply(zclReply); return; } @@ -275,9 +271,6 @@ ZigbeeClusterReply *ZigbeeCluster::sendClusterServerResponse(quint8 command, qui ZigbeeNetworkReply *networkReply = m_network->sendRequest(request); connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){ if (!verifyNetworkError(zclReply, networkReply)) { - qCWarning(dcZigbeeClusterLibrary()) << "Failed to send response" - << m_node << networkReply->error() - << networkReply->zigbeeApsStatus(); finishZclReply(zclReply); return; } @@ -313,28 +306,37 @@ bool ZigbeeCluster::verifyNetworkError(ZigbeeClusterReply *zclReply, ZigbeeNetwo // The request has been transported successfully to he destination, now // wait for the expected indication or check if we already recieved it zclReply->m_apsConfirmReceived = true; - zclReply->m_zigbeeApsStatus = networkReply->zigbeeApsStatus(); - zclReply->m_zigbeeNwkStatus = networkReply->zigbeeNwkStatus(); success = true; break; case ZigbeeNetworkReply::ErrorTimeout: zclReply->m_error = ZigbeeClusterReply::ErrorTimeout; + qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request to" << m_node << zclReply->error(); break; case ZigbeeNetworkReply::ErrorInterfaceError: zclReply->m_error = ZigbeeClusterReply::ErrorInterfaceError; + qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request to" << m_node << zclReply->error(); break; case ZigbeeNetworkReply::ErrorNetworkOffline: zclReply->m_error = ZigbeeClusterReply::ErrorNetworkOffline; + qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request to" << m_node << zclReply->error(); break; case ZigbeeNetworkReply::ErrorZigbeeApsStatusError: zclReply->m_apsConfirmReceived = true; zclReply->m_error = ZigbeeClusterReply::ErrorZigbeeApsStatusError; zclReply->m_zigbeeApsStatus = networkReply->zigbeeApsStatus(); + qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request to" << m_node << zclReply->zigbeeApsStatus(); break; case ZigbeeNetworkReply::ErrorZigbeeNwkStatusError: zclReply->m_apsConfirmReceived = true; zclReply->m_error = ZigbeeClusterReply::ErrorZigbeeNwkStatusError; zclReply->m_zigbeeNwkStatus = networkReply->zigbeeNwkStatus(); + qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request to" << m_node << zclReply->zigbeeNwkStatus(); + break; + case ZigbeeNetworkReply::ErrorZigbeeMacStatusError: + zclReply->m_apsConfirmReceived = true; + zclReply->m_error = ZigbeeClusterReply::ErrorZigbeeMacStatusError; + zclReply->m_zigbeeMacStatus = networkReply->zigbeeMacStatus(); + qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request to" << m_node << zclReply->zigbeeMacStatus(); break; } @@ -345,6 +347,7 @@ void ZigbeeCluster::finishZclReply(ZigbeeClusterReply *zclReply) { m_pendingReplies.remove(zclReply->transactionSequenceNumber()); qCDebug(dcZigbeeCluster()) << "ZigbeeClusterReply finished" << zclReply->request() << zclReply->requestFrame() << zclReply->responseFrame(); + // FIXME: Set the status zclReply->finished(); } diff --git a/libnymea-zigbee/zcl/zigbeeclusterreply.cpp b/libnymea-zigbee/zcl/zigbeeclusterreply.cpp index 39f42dd..fc36d1b 100644 --- a/libnymea-zigbee/zcl/zigbeeclusterreply.cpp +++ b/libnymea-zigbee/zcl/zigbeeclusterreply.cpp @@ -42,6 +42,11 @@ Zigbee::ZigbeeNwkLayerStatus ZigbeeClusterReply::zigbeeNwkStatus() const return m_zigbeeNwkStatus; } +Zigbee::ZigbeeMacLayerStatus ZigbeeClusterReply::zigbeeMacStatus() const +{ + return m_zigbeeMacStatus; +} + ZigbeeNetworkRequest ZigbeeClusterReply::request() const { return m_request; diff --git a/libnymea-zigbee/zcl/zigbeeclusterreply.h b/libnymea-zigbee/zcl/zigbeeclusterreply.h index df369e9..9d47d9e 100644 --- a/libnymea-zigbee/zcl/zigbeeclusterreply.h +++ b/libnymea-zigbee/zcl/zigbeeclusterreply.h @@ -44,7 +44,9 @@ public: ErrorNoError, // All OK, no error occured, the message was transported successfully ErrorTimeout, // The request timeouted ErrorZigbeeApsStatusError, // An APS transport error occured. See zigbeeApsStatus() - ErrorZigbeeNwkStatusError, // An NWK layer error occured. See zigbeeNwkStatus() + ErrorZigbeeNwkStatusError, // A NWK layer error occured. See zigbeeNwkStatus() + ErrorZigbeeMacStatusError, // A MAC layer error occured. See zigbeeNwkStatus() + ErrorZigbeeClusterLibraryError, // A ZCL error occured. See zigbeeClusterLibraryStatus() ErrorInterfaceError, // A transport interface error occured. Could not communicate with the hardware. ErrorNetworkOffline // The network is offline. Cannot send any requests }; @@ -53,6 +55,8 @@ public: Error error() const; Zigbee::ZigbeeApsStatus zigbeeApsStatus() const; Zigbee::ZigbeeNwkLayerStatus zigbeeNwkStatus() const; + Zigbee::ZigbeeMacLayerStatus zigbeeMacStatus() const; + ZigbeeClusterLibrary::Status zigbeeClusterLibraryStatus() const; ZigbeeNetworkRequest request() const; ZigbeeClusterLibrary::Frame requestFrame() const; @@ -78,6 +82,8 @@ private: bool m_apsConfirmReceived = false; Zigbee::ZigbeeApsStatus m_zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess; Zigbee::ZigbeeNwkLayerStatus m_zigbeeNwkStatus = Zigbee::ZigbeeNwkLayerStatusSuccess; + Zigbee::ZigbeeMacLayerStatus m_zigbeeMacStatus = Zigbee::ZigbeeMacLayerStatusSuccess; + ZigbeeClusterLibrary::Status m_zigbeeClusterLibraryStatus = ZigbeeClusterLibrary::StatusSuccess; ZigbeeClusterLibrary::Command m_expectedResponse; diff --git a/libnymea-zigbee/zdo/zigbeedeviceobject.cpp b/libnymea-zigbee/zdo/zigbeedeviceobject.cpp index 9b4a8d6..21217b7 100644 --- a/libnymea-zigbee/zdo/zigbeedeviceobject.cpp +++ b/libnymea-zigbee/zdo/zigbeedeviceobject.cpp @@ -68,10 +68,6 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestNodeDescriptor() ZigbeeNetworkReply *networkReply = m_network->sendRequest(request); connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){ if (!verifyNetworkError(zdoReply, networkReply)) { - qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" - << static_cast(networkReply->request().clusterId()) - << m_node << networkReply->error() - << networkReply->zigbeeApsStatus(); finishZdoReply(zdoReply); return; } @@ -115,10 +111,6 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestPowerDescriptor() ZigbeeNetworkReply *networkReply = m_network->sendRequest(request); connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){ if (!verifyNetworkError(zdoReply, networkReply)) { - qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" - << static_cast(networkReply->request().clusterId()) - << m_node << networkReply->error() - << networkReply->zigbeeApsStatus(); finishZdoReply(zdoReply); return; } @@ -161,10 +153,6 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestActiveEndpoints() ZigbeeNetworkReply *networkReply = m_network->sendRequest(request); connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){ if (!verifyNetworkError(zdoReply, networkReply)) { - qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" - << static_cast(networkReply->request().clusterId()) - << m_node << networkReply->error() - << networkReply->zigbeeApsStatus(); finishZdoReply(zdoReply); return; } @@ -207,10 +195,6 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestSimpleDescriptor(quint8 endp ZigbeeNetworkReply *networkReply = m_network->sendRequest(request); connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){ if (!verifyNetworkError(zdoReply, networkReply)) { - qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" - << static_cast(networkReply->request().clusterId()) - << m_node << networkReply->error() - << networkReply->zigbeeApsStatus(); finishZdoReply(zdoReply); return; } @@ -258,10 +242,6 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestBindShortAddress(quint8 sour ZigbeeNetworkReply *networkReply = m_network->sendRequest(request); connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){ if (!verifyNetworkError(zdoReply, networkReply)) { - qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" - << static_cast(networkReply->request().clusterId()) - << m_node << networkReply->error() - << networkReply->zigbeeApsStatus(); finishZdoReply(zdoReply); return; } @@ -310,10 +290,6 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestBindIeeeAddress(quint8 sourc ZigbeeNetworkReply *networkReply = m_network->sendRequest(request); connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){ if (!verifyNetworkError(zdoReply, networkReply)) { - qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" - << static_cast(networkReply->request().clusterId()) - << m_node << networkReply->error() - << networkReply->zigbeeApsStatus(); finishZdoReply(zdoReply); return; } @@ -365,10 +341,6 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestMgmtLeaveNetwork(bool rejoin ZigbeeNetworkReply *networkReply = m_network->sendRequest(request); connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){ if (!verifyNetworkError(zdoReply, networkReply)) { - qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" - << static_cast(networkReply->request().clusterId()) - << m_node << networkReply->error() - << networkReply->zigbeeApsStatus(); finishZdoReply(zdoReply); return; } @@ -410,10 +382,6 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestMgmtLqi(quint8 startIndex) ZigbeeNetworkReply *networkReply = m_network->sendRequest(request); connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){ if (!verifyNetworkError(zdoReply, networkReply)) { - qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" - << static_cast(networkReply->request().clusterId()) - << m_node << networkReply->error() - << networkReply->zigbeeApsStatus(); finishZdoReply(zdoReply); return; } @@ -467,10 +435,6 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestMgmtBind(quint8 startIndex) ZigbeeNetworkReply *networkReply = m_network->sendRequest(request); connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){ if (!verifyNetworkError(zdoReply, networkReply)) { - qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" - << static_cast(networkReply->request().clusterId()) - << m_node << networkReply->error() - << networkReply->zigbeeApsStatus(); finishZdoReply(zdoReply); return; } @@ -479,7 +443,6 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestMgmtBind(quint8 startIndex) // Now check if the expected indication response received already if (zdoReply->isComplete()) { qCDebug(dcZigbeeDeviceObject()) << "Successfully received response for" << static_cast(networkReply->request().clusterId()); - finishZdoReply(zdoReply); return; } @@ -520,28 +483,36 @@ bool ZigbeeDeviceObject::verifyNetworkError(ZigbeeDeviceObjectReply *zdoReply, Z // The request has been transported successfully to he destination, now // wait for the expected indication or check if we already recieved it zdoReply->m_apsConfirmReceived = true; - zdoReply->m_zigbeeApsStatus = networkReply->zigbeeApsStatus(); - zdoReply->m_zigbeeNwkStatus = networkReply->zigbeeNwkStatus(); success = true; break; case ZigbeeNetworkReply::ErrorInterfaceError: zdoReply->m_error = ZigbeeDeviceObjectReply::ErrorInterfaceError; + qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" << static_cast(networkReply->request().clusterId()) << m_node << networkReply->error(); break; case ZigbeeNetworkReply::ErrorTimeout: zdoReply->m_error = ZigbeeDeviceObjectReply::ErrorTimeout; + qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" << static_cast(networkReply->request().clusterId()) << m_node << networkReply->error(); break; case ZigbeeNetworkReply::ErrorNetworkOffline: zdoReply->m_error = ZigbeeDeviceObjectReply::ErrorNetworkOffline; + qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" << static_cast(networkReply->request().clusterId()) << m_node << networkReply->error(); + break; + case ZigbeeNetworkReply::ErrorZigbeeMacStatusError: + zdoReply->setZigbeeMacLayerStatus(networkReply->zigbeeMacStatus()); + qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" << static_cast(networkReply->request().clusterId()) << m_node << networkReply->zigbeeMacStatus(); + zdoReply->m_apsConfirmReceived = true; break; case ZigbeeNetworkReply::ErrorZigbeeApsStatusError: zdoReply->m_apsConfirmReceived = true; - zdoReply->m_error = ZigbeeDeviceObjectReply::ErrorZigbeeApsStatusError; - zdoReply->m_zigbeeApsStatus = networkReply->zigbeeApsStatus(); + zdoReply->setZigbeeApsStatus(networkReply->zigbeeApsStatus()); + qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" << static_cast(networkReply->request().clusterId()) << m_node << networkReply->zigbeeApsStatus(); + zdoReply->m_apsConfirmReceived = true; break; case ZigbeeNetworkReply::ErrorZigbeeNwkStatusError: zdoReply->m_apsConfirmReceived = true; - zdoReply->m_error = ZigbeeDeviceObjectReply::ErrorZigbeeNwkStatusError; - zdoReply->m_zigbeeNwkStatus = networkReply->zigbeeNwkStatus(); + zdoReply->setZigbeeNwkLayerStatus(networkReply->zigbeeNwkStatus()); + qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" << static_cast(networkReply->request().clusterId()) << m_node << networkReply->zigbeeNwkStatus(); + zdoReply->m_apsConfirmReceived = true; break; } @@ -550,22 +521,18 @@ bool ZigbeeDeviceObject::verifyNetworkError(ZigbeeDeviceObjectReply *zdoReply, Z void ZigbeeDeviceObject::finishZdoReply(ZigbeeDeviceObjectReply *zdoReply) { + // Note: here all layer errors have already been set switch(zdoReply->error()) { case ZigbeeDeviceObjectReply::ErrorNoError: qCDebug(dcZigbeeDeviceObject()) << "Reply finished successfully" << zdoReply->request(); break; - case ZigbeeDeviceObjectReply::ErrorZigbeeApsStatusError: - qCWarning(dcZigbeeDeviceObject()) << "Failed to send request to device" << zdoReply->request() << zdoReply->error() << zdoReply->zigbeeApsStatus(); - break; - case ZigbeeDeviceObjectReply::ErrorZigbeeNwkStatusError: - qCWarning(dcZigbeeDeviceObject()) << "Failed to send request to device" << zdoReply->request() << zdoReply->error() << zdoReply->zigbeeNwkStatus(); + case ZigbeeDeviceObjectReply::ErrorZigbeeDeviceObjectStatusError: + qCWarning(dcZigbeeDeviceObject()) << "Reply finished with error" << zdoReply->request() << zdoReply->zigbeeDeviceObjectStatus(); break; default: - qCWarning(dcZigbeeDeviceObject()) << "Failed to send request to device" << zdoReply->request() << zdoReply->error(); break; } - m_pendingReplies.remove(zdoReply->transactionSequenceNumber()); zdoReply->finished(); } @@ -578,6 +545,7 @@ void ZigbeeDeviceObject::processApsDataIndication(const Zigbee::ApsdeDataIndicat if (zdoReply && indication.clusterId == (zdoReply->request().clusterId() | 0x8000)) { zdoReply->m_responseData = indication.asdu; zdoReply->m_responseAdpu = asdu; + zdoReply->setZigbeeDeviceObjectStatus(asdu.status); zdoReply->m_zdpIndicationReceived = true; if (zdoReply->isComplete()) { finishZdoReply(zdoReply); diff --git a/libnymea-zigbee/zdo/zigbeedeviceobjectreply.cpp b/libnymea-zigbee/zdo/zigbeedeviceobjectreply.cpp index fddbe29..b03a7c7 100644 --- a/libnymea-zigbee/zdo/zigbeedeviceobjectreply.cpp +++ b/libnymea-zigbee/zdo/zigbeedeviceobjectreply.cpp @@ -34,6 +34,38 @@ ZigbeeDeviceObjectReply::ZigbeeDeviceObjectReply(const ZigbeeNetworkRequest &req } +void ZigbeeDeviceObjectReply::setZigbeeApsStatus(Zigbee::ZigbeeApsStatus status) +{ + m_zigbeeApsStatus = status; + if (status != Zigbee::ZigbeeApsStatusSuccess) { + m_error = ErrorZigbeeApsStatusError; + } +} + +void ZigbeeDeviceObjectReply::setZigbeeNwkLayerStatus(Zigbee::ZigbeeNwkLayerStatus status) +{ + m_zigbeeNwkStatus = status; + if (status != Zigbee::ZigbeeNwkLayerStatusSuccess) { + m_error = ErrorZigbeeNwkStatusError; + } +} + +void ZigbeeDeviceObjectReply::setZigbeeMacLayerStatus(Zigbee::ZigbeeMacLayerStatus status) +{ + m_zigbeeMacStatus = status; + if (status != Zigbee::ZigbeeMacLayerStatusSuccess) { + m_error = ErrorZigbeeMacStatusError; + } +} + +void ZigbeeDeviceObjectReply::setZigbeeDeviceObjectStatus(ZigbeeDeviceProfile::Status status) +{ + m_zigbeeDeviceObjectStatus = status; + if (status != ZigbeeDeviceProfile::StatusSuccess) { + m_error = ErrorZigbeeDeviceObjectStatusError; + } +} + ZigbeeDeviceObjectReply::Error ZigbeeDeviceObjectReply::error() const { return m_error; @@ -49,6 +81,11 @@ Zigbee::ZigbeeNwkLayerStatus ZigbeeDeviceObjectReply::zigbeeNwkStatus() const return m_zigbeeNwkStatus; } +Zigbee::ZigbeeMacLayerStatus ZigbeeDeviceObjectReply::zigbeeMacStatus() const +{ + return m_zigbeeMacStatus; +} + ZigbeeNetworkRequest ZigbeeDeviceObjectReply::request() const { return m_request; diff --git a/libnymea-zigbee/zdo/zigbeedeviceobjectreply.h b/libnymea-zigbee/zdo/zigbeedeviceobjectreply.h index aeef278..e3633fb 100644 --- a/libnymea-zigbee/zdo/zigbeedeviceobjectreply.h +++ b/libnymea-zigbee/zdo/zigbeedeviceobjectreply.h @@ -43,9 +43,11 @@ public: enum Error { ErrorNoError, // All OK, no error occured, the message was transported successfully ErrorTimeout, // The request timeouted - ErrorZigbeeApsStatusError, // An APS transport error occured. See zigbeeApsStatus() - ErrorZigbeeNwkStatusError, // An NWK layer error occured. See zigbeeNwkStatus() ErrorInterfaceError, // A transport interface error occured. Could not communicate with the hardware. + ErrorZigbeeApsStatusError, // An APS transport error occured. See zigbeeApsStatus() + ErrorZigbeeNwkStatusError, // A NWK layer error occured. See zigbeeNwkStatus() + ErrorZigbeeMacStatusError, // A MAC layer error occured. See zigbeeMacStatus() + ErrorZigbeeDeviceObjectStatusError, // A ZDP error occured. See zigbeeDeviceObjectStatus() ErrorNetworkOffline // The network is offline. Cannot send any requests }; Q_ENUM(Error) @@ -53,6 +55,8 @@ public: Error error() const; Zigbee::ZigbeeApsStatus zigbeeApsStatus() const; Zigbee::ZigbeeNwkLayerStatus zigbeeNwkStatus() const; + Zigbee::ZigbeeMacLayerStatus zigbeeMacStatus() const; + ZigbeeDeviceProfile::Status zigbeeDeviceObjectStatus() const; ZigbeeNetworkRequest request() const; quint8 transactionSequenceNumber() const; @@ -61,7 +65,6 @@ public: QByteArray responseData() const; ZigbeeDeviceProfile::Adpu responseAdpu() const; - bool isComplete() const; private: @@ -73,12 +76,21 @@ private: ZigbeeNetworkRequest m_request; quint8 m_transactionSequenceNumber = 0; - // APS transport - bool m_apsConfirmReceived = false; + // Transport layer errors Zigbee::ZigbeeApsStatus m_zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess; + void setZigbeeApsStatus(Zigbee::ZigbeeApsStatus status); + Zigbee::ZigbeeNwkLayerStatus m_zigbeeNwkStatus = Zigbee::ZigbeeNwkLayerStatusSuccess; + void setZigbeeNwkLayerStatus(Zigbee::ZigbeeNwkLayerStatus status); + + Zigbee::ZigbeeMacLayerStatus m_zigbeeMacStatus = Zigbee::ZigbeeMacLayerStatusSuccess; + void setZigbeeMacLayerStatus(Zigbee::ZigbeeMacLayerStatus status); + + ZigbeeDeviceProfile::Status m_zigbeeDeviceObjectStatus = ZigbeeDeviceProfile::StatusSuccess; + void setZigbeeDeviceObjectStatus(ZigbeeDeviceProfile::Status status); // ZDP response data + bool m_apsConfirmReceived = false; bool m_zdpIndicationReceived = false; ZigbeeDeviceProfile::ZdoCommand m_expectedResponse; QByteArray m_responseData; diff --git a/libnymea-zigbee/zigbee.h b/libnymea-zigbee/zigbee.h index 1d9c66e..d6b8fb6 100644 --- a/libnymea-zigbee/zigbee.h +++ b/libnymea-zigbee/zigbee.h @@ -278,6 +278,32 @@ public: }; Q_ENUM(Manufacturer) + enum ZigbeeMacLayerStatus { + ZigbeeMacLayerStatusSuccess = 0x00, + ZigbeeMacLayerStatusBeaconLoss = 0xE0, + ZigbeeMacLayerStatusChannelAccessFailure = 0xE1, + ZigbeeMacLayerStatusDenied = 0xE2, + ZigbeeMacLayerStatusDisableTrxFailure = 0xE3, + ZigbeeMacLayerStatusFailedSecurityCheck = 0xE4, + ZigbeeMacLayerStatusFrameToLong = 0xE5, + ZigbeeMacLayerStatusInvalidGts = 0xE6, + ZigbeeMacLayerStatusInvalidHandle = 0xE7, + ZigbeeMacLayerStatusInvalidParameter = 0xE8, + ZigbeeMacLayerStatusNoAck = 0xE9, + ZigbeeMacLayerStatusNoBeacon = 0xEA, + ZigbeeMacLayerStatusNoData = 0xEB, + ZigbeeMacLayerStatusNoShortAddress = 0xEC, + ZigbeeMacLayerStatusOutOfCap = 0xED, + ZigbeeMacLayerStatusPanIdConflict = 0xEE, + ZigbeeMacLayerStatusRealignment = 0xEF, + ZigbeeMacLayerStatusTransactionExpired = 0xF0, + ZigbeeMacLayerStatusTransactionOverflow = 0xF1, + ZigbeeMacLayerStatusTxActive = 0xF2, + ZigbeeMacLayerStatusUnavailableKey = 0xF3, + ZigbeeMacLayerStatusUnsupportedAttribute = 0xF4 + }; + Q_ENUM(ZigbeeMacLayerStatus) + enum ZigbeeNwkLayerStatus { ZigbeeNwkLayerStatusSuccess = 0x00, ZigbeeNwkLayerStatusInvalidParameter = 0xc1, diff --git a/libnymea-zigbee/zigbeenetwork.cpp b/libnymea-zigbee/zigbeenetwork.cpp index 5512df2..7bc50b9 100644 --- a/libnymea-zigbee/zigbeenetwork.cpp +++ b/libnymea-zigbee/zigbeenetwork.cpp @@ -599,9 +599,12 @@ void ZigbeeNetwork::setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::Zig } else { // There has been an error while transporting the request to the device // Note: if the APS status is >= 0xc1, it has to interpreted as NWK layer error - if (zigbeeApsStatus >= 0xc1) { + if (zigbeeApsStatus >= 0xc1 && zigbeeApsStatus <= 0xd3) { reply->m_zigbeeNwkStatus = static_cast(static_cast(zigbeeApsStatus)); finishNetworkReply(reply, ZigbeeNetworkReply::ErrorZigbeeNwkStatusError); + } else if (zigbeeApsStatus >= 0xE0 && zigbeeApsStatus <= 0xF4) { + reply->m_zigbeeMacStatus = static_cast(static_cast(zigbeeApsStatus)); + finishNetworkReply(reply, ZigbeeNetworkReply::ErrorZigbeeMacStatusError); } else { reply->m_zigbeeApsStatus = zigbeeApsStatus; finishNetworkReply(reply, ZigbeeNetworkReply::ErrorZigbeeApsStatusError); @@ -623,6 +626,9 @@ void ZigbeeNetwork::finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkR case ZigbeeNetworkReply::ErrorZigbeeNwkStatusError: qCWarning(dcZigbeeNetwork()) << "Failed to send request to device" << reply->request() << reply->error() << reply->zigbeeNwkStatus(); break; + case ZigbeeNetworkReply::ErrorZigbeeMacStatusError: + qCWarning(dcZigbeeNetwork()) << "Failed to send request to device" << reply->request() << reply->error() << reply->zigbeeMacStatus(); + break; default: qCWarning(dcZigbeeNetwork()) << "Failed to send request to device" << reply->request() << reply->error(); break; diff --git a/libnymea-zigbee/zigbeenetworkreply.cpp b/libnymea-zigbee/zigbeenetworkreply.cpp index f9e9ea6..3db5817 100644 --- a/libnymea-zigbee/zigbeenetworkreply.cpp +++ b/libnymea-zigbee/zigbeenetworkreply.cpp @@ -37,6 +37,11 @@ ZigbeeNetworkRequest ZigbeeNetworkReply::request() const return m_request; } +Zigbee::ZigbeeMacLayerStatus ZigbeeNetworkReply::zigbeeMacStatus() const +{ + return m_zigbeeMacStatus; +} + Zigbee::ZigbeeApsStatus ZigbeeNetworkReply::zigbeeApsStatus() const { return m_zigbeeApsStatus; diff --git a/libnymea-zigbee/zigbeenetworkreply.h b/libnymea-zigbee/zigbeenetworkreply.h index f32f79c..1f310ff 100644 --- a/libnymea-zigbee/zigbeenetworkreply.h +++ b/libnymea-zigbee/zigbeenetworkreply.h @@ -45,9 +45,10 @@ public: enum Error { ErrorNoError, ErrorTimeout, - ErrorZigbeeApsStatusError, - ErrorZigbeeNwkStatusError, ErrorInterfaceError, + ErrorZigbeeMacStatusError, + ErrorZigbeeNwkStatusError, + ErrorZigbeeApsStatusError, ErrorNetworkOffline }; Q_ENUM(Error) @@ -55,8 +56,9 @@ public: Error error() const; ZigbeeNetworkRequest request() const; - Zigbee::ZigbeeApsStatus zigbeeApsStatus() const; + Zigbee::ZigbeeMacLayerStatus zigbeeMacStatus() const; Zigbee::ZigbeeNwkLayerStatus zigbeeNwkStatus() const; + Zigbee::ZigbeeApsStatus zigbeeApsStatus() const; private: explicit ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent = nullptr); @@ -64,6 +66,7 @@ private: QTimer *m_timer = nullptr; Error m_error = ErrorNoError; + Zigbee::ZigbeeMacLayerStatus m_zigbeeMacStatus = Zigbee::ZigbeeMacLayerStatusSuccess; Zigbee::ZigbeeApsStatus m_zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess; Zigbee::ZigbeeNwkLayerStatus m_zigbeeNwkStatus = Zigbee::ZigbeeNwkLayerStatusSuccess; diff --git a/libnymea-zigbee/zigbeenode.cpp b/libnymea-zigbee/zigbeenode.cpp index 89fdfd3..a4460a9 100644 --- a/libnymea-zigbee/zigbeenode.cpp +++ b/libnymea-zigbee/zigbeenode.cpp @@ -154,18 +154,17 @@ void ZigbeeNode::startInitialization() initNodeDescriptor(); } +void ZigbeeNode::removeAllBindings() +{ + +} + void ZigbeeNode::readBindingTableEntries() { - ZigbeeDeviceObjectReply * reply = deviceObject()->requestMgmtBind(); + ZigbeeDeviceObjectReply *reply = deviceObject()->requestMgmtBind(); connect(reply, &ZigbeeDeviceObjectReply::finished, this, [=](){ if (reply->error() != ZigbeeDeviceObjectReply::ErrorNoError) { - qCWarning(dcZigbeeDeviceObject()) << "Failed to read binding table" << reply->error(); - return; - } - - // The request finished, but we received a ZDP error. - if (reply->responseAdpu().status != ZigbeeDeviceProfile::StatusSuccess) { - qCWarning(dcZigbeeNode()) << this << "failed to read node descriptor" << reply->responseAdpu().status; + qCWarning(dcZigbeeNode()) << "Failed to read binding table" << reply->error(); return; } @@ -226,13 +225,6 @@ void ZigbeeNode::initNodeDescriptor() return; } - // The request finished, but we received a ZDP error. - if (reply->responseAdpu().status != ZigbeeDeviceProfile::StatusSuccess) { - qCWarning(dcZigbeeNode()) << this << "failed to read node descriptor" << reply->responseAdpu().status; - emit nodeInitializationFailed(); - return; - } - qCDebug(dcZigbeeNode()) << this << "reading node descriptor finished successfully."; m_nodeDescriptor = ZigbeeDeviceProfile::parseNodeDescriptor(reply->responseAdpu().payload); qCDebug(dcZigbeeNode()) << m_nodeDescriptor; @@ -261,22 +253,14 @@ void ZigbeeNode::initPowerDescriptor() return; } - ZigbeeDeviceProfile::Adpu adpu = reply->responseAdpu(); - if (adpu.status != ZigbeeDeviceProfile::StatusSuccess) { - qCWarning(dcZigbeeNode()) << "Failed to read power descriptor from" << this << adpu.status; - // FIXME: decide what to do, remove the node again from network or continue without powerdescriptor - return; - } - qCDebug(dcZigbeeNode()) << this << "reading power descriptor finished successfully."; - m_requestRetry = 0; - - QDataStream stream(adpu.payload); + QDataStream stream(reply->responseAdpu().payload); stream.setByteOrder(QDataStream::LittleEndian); quint16 powerDescriptorFlag = 0; stream >> powerDescriptorFlag; m_powerDescriptor = ZigbeeDeviceProfile::parsePowerDescriptor(powerDescriptorFlag); qCDebug(dcZigbeeNode()) << m_powerDescriptor; + m_requestRetry = 0; // Continue with endpoint fetching initEndpoints(); @@ -301,15 +285,7 @@ void ZigbeeNode::initEndpoints() return; } - if (reply->responseAdpu().status != ZigbeeDeviceProfile::StatusSuccess) { - qCWarning(dcZigbeeNode()) << "Failed to read active endpoints" << reply->responseAdpu().status; - emit nodeInitializationFailed(); - return; - } - qCDebug(dcZigbeeNode()) << this << "reading active endpoints finished successfully."; - m_requestRetry = 0; - QDataStream stream(reply->responseAdpu().payload); stream.setByteOrder(QDataStream::LittleEndian); quint8 endpointCount = 0; @@ -326,6 +302,8 @@ void ZigbeeNode::initEndpoints() qCDebug(dcZigbeeNode()) << " -" << ZigbeeUtils::convertByteToHexString(m_uninitializedEndpoints.at(i)); } + m_requestRetry = 0; + // If there a no endpoints or all endpoints have already be initialized, continue with reading the basic cluster information if (m_uninitializedEndpoints.isEmpty()) { initBasicCluster(); @@ -357,15 +335,8 @@ void ZigbeeNode::initEndpoint(quint8 endpointId) return; } - if (reply->responseAdpu().status != ZigbeeDeviceProfile::StatusSuccess) { - qCWarning(dcZigbeeNode()) << this << "failed to read simple descriptor from endpoint" << endpointId << reply->responseAdpu().status; - emit nodeInitializationFailed(); - return; - } - qCDebug(dcZigbeeNode()) << this << "reading simple descriptor for endpoint" << endpointId << "finished successfully."; m_requestRetry = 0; - quint8 length = 0; quint8 endpointId = 0; quint16 profileId = 0; quint16 deviceId = 0; quint8 deviceVersion = 0; quint8 inputClusterCount = 0; quint8 outputClusterCount = 0; QList inputClusters; diff --git a/libnymea-zigbee/zigbeenode.h b/libnymea-zigbee/zigbeenode.h index d8ca4f9..95e55c1 100644 --- a/libnymea-zigbee/zigbeenode.h +++ b/libnymea-zigbee/zigbeenode.h @@ -85,6 +85,7 @@ public: // This method starts the node initialization phase (read descriptors and endpoints) void startInitialization(); + void removeAllBindings(); void readBindingTableEntries(); private: