From 74995ce40152ccf04300d09bd9f625350444d9dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Sat, 30 May 2020 16:30:39 +0200 Subject: [PATCH] Implement NWL Layer error handling --- .../deconz/zigbeebridgecontrollerdeconz.cpp | 8 ++--- libnymea-zigbee/zcl/zigbeecluster.cpp | 14 +++++--- libnymea-zigbee/zcl/zigbeeclusterreply.cpp | 10 ++++++ libnymea-zigbee/zcl/zigbeeclusterreply.h | 4 +++ libnymea-zigbee/zdo/zigbeedeviceobject.cpp | 25 ++++++++++++-- .../zdo/zigbeedeviceobjectreply.cpp | 15 ++++++--- libnymea-zigbee/zdo/zigbeedeviceobjectreply.h | 5 ++- libnymea-zigbee/zigbee.h | 10 +++--- libnymea-zigbee/zigbeenetwork.cpp | 33 +++++++++++++++---- libnymea-zigbee/zigbeenetworkreply.cpp | 5 +++ libnymea-zigbee/zigbeenetworkreply.h | 3 ++ libnymea-zigbee/zigbeenodeendpoint.cpp | 18 ++++++++++ libnymea-zigbee/zigbeenodeendpoint.h | 7 ++++ 13 files changed, 130 insertions(+), 27 deletions(-) diff --git a/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.cpp b/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.cpp index 906bbff..7d3eca3 100644 --- a/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.cpp +++ b/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.cpp @@ -81,7 +81,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestVersion() stream << static_cast(5); // Frame length ZigbeeInterfaceDeconzReply *reply = new ZigbeeInterfaceDeconzReply(Deconz::CommandVersion, sequenceNumber, this); - connect(reply, &ZigbeeInterfaceDeconzReply::finished, reply, &ZigbeeInterfaceDeconzReply::deleteLater); + connect(reply, &ZigbeeInterfaceDeconzReply::finished, reply, &ZigbeeInterfaceDeconzReply::deleteLater, Qt::QueuedConnection); m_pendingReplies.insert(sequenceNumber, reply); m_interface->sendPackage(message); @@ -105,7 +105,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestDeviceState() stream << static_cast(0); // Reserverd ZigbeeInterfaceDeconzReply *reply = new ZigbeeInterfaceDeconzReply(Deconz::CommandDeviceState, sequenceNumber, this); - connect(reply, &ZigbeeInterfaceDeconzReply::finished, reply, &ZigbeeInterfaceDeconzReply::deleteLater); + connect(reply, &ZigbeeInterfaceDeconzReply::finished, reply, &ZigbeeInterfaceDeconzReply::deleteLater, Qt::QueuedConnection); m_pendingReplies.insert(sequenceNumber, reply); m_interface->sendPackage(message); @@ -381,7 +381,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::createReply(Deconz::Co ZigbeeInterfaceDeconzReply *reply = new ZigbeeInterfaceDeconzReply(command, sequenceNumber, parent); // Auto delete the object on finished - connect(reply, &ZigbeeInterfaceDeconzReply::finished, reply, &ZigbeeInterfaceDeconzReply::deleteLater); + connect(reply, &ZigbeeInterfaceDeconzReply::finished, reply, &ZigbeeInterfaceDeconzReply::deleteLater, Qt::QueuedConnection); // Add it to the pending list m_pendingReplies.insert(sequenceNumber, reply); @@ -402,7 +402,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters( // Create an independent reply for finishing the entire read sequence ZigbeeInterfaceDeconzReply *readNetworkParametersReply = new ZigbeeInterfaceDeconzReply(Deconz::CommandReadParameter, m_sequenceNumber, this); - connect(readNetworkParametersReply, &ZigbeeInterfaceDeconzReply::finished, readNetworkParametersReply, &ZigbeeInterfaceDeconzReply::deleteLater); + connect(readNetworkParametersReply, &ZigbeeInterfaceDeconzReply::finished, readNetworkParametersReply, &ZigbeeInterfaceDeconzReply::deleteLater, Qt::QueuedConnection); // Read MAC address of the bridge ZigbeeInterfaceDeconzReply *replyMacAddress = requestReadParameter(Deconz::ParameterMacAddress); diff --git a/libnymea-zigbee/zcl/zigbeecluster.cpp b/libnymea-zigbee/zcl/zigbeecluster.cpp index f4f9d00..1f3fc23 100644 --- a/libnymea-zigbee/zcl/zigbeecluster.cpp +++ b/libnymea-zigbee/zcl/zigbeecluster.cpp @@ -137,9 +137,7 @@ ZigbeeClusterReply *ZigbeeCluster::readAttributes(QList attributes) 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 << m_endpoint << this << networkReply->error() - << networkReply->zigbeeApsStatus(); + qCWarning(dcZigbeeClusterLibrary()) << "Failed to read attributes from" << m_node << m_endpoint << this << networkReply->error(); finishZclReply(zclReply); return; } @@ -158,7 +156,7 @@ ZigbeeClusterReply *ZigbeeCluster::readAttributes(QList attributes) ZigbeeClusterReply *ZigbeeCluster::createClusterReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame frame) { ZigbeeClusterReply *zclReply = new ZigbeeClusterReply(request, frame, this); - connect(zclReply, &ZigbeeClusterReply::finished, zclReply, &ZigbeeClusterReply::deleteLater); + connect(zclReply, &ZigbeeClusterReply::finished, zclReply, &ZigbeeClusterReply::deleteLater, Qt::QueuedConnection); zclReply->m_transactionSequenceNumber = frame.header.transactionSequenceNumber; m_pendingReplies.insert(zclReply->transactionSequenceNumber(), zclReply); return zclReply; @@ -189,6 +187,7 @@ bool ZigbeeCluster::verifyNetworkError(ZigbeeClusterReply *zclReply, ZigbeeNetwo // 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::ErrorInterfaceError: @@ -198,10 +197,15 @@ bool ZigbeeCluster::verifyNetworkError(ZigbeeClusterReply *zclReply, ZigbeeNetwo zclReply->m_error = ZigbeeClusterReply::ErrorNetworkOffline; break; case ZigbeeNetworkReply::ErrorZigbeeApsStatusError: - zclReply->m_error = ZigbeeClusterReply::ErrorZigbeeApsStatusError; zclReply->m_apsConfirmReceived = true; + zclReply->m_error = ZigbeeClusterReply::ErrorZigbeeApsStatusError; zclReply->m_zigbeeApsStatus = networkReply->zigbeeApsStatus(); break; + case ZigbeeNetworkReply::ErrorZigbeeNwkStatusError: + zclReply->m_apsConfirmReceived = true; + zclReply->m_error = ZigbeeClusterReply::ErrorZigbeeNwkStatusError; + zclReply->m_zigbeeNwkStatus = networkReply->zigbeeNwkStatus(); + break; } return success; diff --git a/libnymea-zigbee/zcl/zigbeeclusterreply.cpp b/libnymea-zigbee/zcl/zigbeeclusterreply.cpp index e0f18fe..39f42dd 100644 --- a/libnymea-zigbee/zcl/zigbeeclusterreply.cpp +++ b/libnymea-zigbee/zcl/zigbeeclusterreply.cpp @@ -32,6 +32,16 @@ ZigbeeClusterReply::Error ZigbeeClusterReply::error() const return m_error; } +Zigbee::ZigbeeApsStatus ZigbeeClusterReply::zigbeeApsStatus() const +{ + return m_zigbeeApsStatus; +} + +Zigbee::ZigbeeNwkLayerStatus ZigbeeClusterReply::zigbeeNwkStatus() const +{ + return m_zigbeeNwkStatus; +} + ZigbeeNetworkRequest ZigbeeClusterReply::request() const { return m_request; diff --git a/libnymea-zigbee/zcl/zigbeeclusterreply.h b/libnymea-zigbee/zcl/zigbeeclusterreply.h index 0135967..df369e9 100644 --- a/libnymea-zigbee/zcl/zigbeeclusterreply.h +++ b/libnymea-zigbee/zcl/zigbeeclusterreply.h @@ -44,12 +44,15 @@ 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() ErrorInterfaceError, // A transport interface error occured. Could not communicate with the hardware. ErrorNetworkOffline // The network is offline. Cannot send any requests }; Q_ENUM(Error) Error error() const; + Zigbee::ZigbeeApsStatus zigbeeApsStatus() const; + Zigbee::ZigbeeNwkLayerStatus zigbeeNwkStatus() const; ZigbeeNetworkRequest request() const; ZigbeeClusterLibrary::Frame requestFrame() const; @@ -74,6 +77,7 @@ private: // Response bool m_apsConfirmReceived = false; Zigbee::ZigbeeApsStatus m_zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess; + Zigbee::ZigbeeNwkLayerStatus m_zigbeeNwkStatus = Zigbee::ZigbeeNwkLayerStatusSuccess; ZigbeeClusterLibrary::Command m_expectedResponse; diff --git a/libnymea-zigbee/zdo/zigbeedeviceobject.cpp b/libnymea-zigbee/zdo/zigbeedeviceobject.cpp index 7afdb3b..5954a0e 100644 --- a/libnymea-zigbee/zdo/zigbeedeviceobject.cpp +++ b/libnymea-zigbee/zdo/zigbeedeviceobject.cpp @@ -295,7 +295,7 @@ ZigbeeNetworkRequest ZigbeeDeviceObject::buildZdoRequest(quint16 zdoRequest) ZigbeeDeviceObjectReply *ZigbeeDeviceObject::createZigbeeDeviceObjectReply(const ZigbeeNetworkRequest &request, quint8 transactionSequenceNumber) { ZigbeeDeviceObjectReply *zdoReply = new ZigbeeDeviceObjectReply(request, this); - connect(zdoReply, &ZigbeeDeviceObjectReply::finished, zdoReply, &ZigbeeDeviceObjectReply::deleteLater); + connect(zdoReply, &ZigbeeDeviceObjectReply::finished, zdoReply, &ZigbeeDeviceObjectReply::deleteLater, Qt::QueuedConnection); zdoReply->m_expectedResponse = static_cast(request.clusterId() | 0x8000); zdoReply->m_transactionSequenceNumber = transactionSequenceNumber; m_pendingReplies.insert(transactionSequenceNumber, zdoReply); @@ -311,6 +311,7 @@ bool ZigbeeDeviceObject::verifyNetworkError(ZigbeeDeviceObjectReply *zdoReply, Z // 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: @@ -320,10 +321,15 @@ bool ZigbeeDeviceObject::verifyNetworkError(ZigbeeDeviceObjectReply *zdoReply, Z zdoReply->m_error = ZigbeeDeviceObjectReply::ErrorNetworkOffline; break; case ZigbeeNetworkReply::ErrorZigbeeApsStatusError: - zdoReply->m_error = ZigbeeDeviceObjectReply::ErrorZigbeeApsStatusError; zdoReply->m_apsConfirmReceived = true; + zdoReply->m_error = ZigbeeDeviceObjectReply::ErrorZigbeeApsStatusError; zdoReply->m_zigbeeApsStatus = networkReply->zigbeeApsStatus(); break; + case ZigbeeNetworkReply::ErrorZigbeeNwkStatusError: + zdoReply->m_apsConfirmReceived = true; + zdoReply->m_error = ZigbeeDeviceObjectReply::ErrorZigbeeNwkStatusError; + zdoReply->m_zigbeeNwkStatus = networkReply->zigbeeNwkStatus(); + break; } return success; @@ -331,6 +337,21 @@ bool ZigbeeDeviceObject::verifyNetworkError(ZigbeeDeviceObjectReply *zdoReply, Z void ZigbeeDeviceObject::finishZdoReply(ZigbeeDeviceObjectReply *zdoReply) { + 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(); + break; + default: + qCWarning(dcZigbeeDeviceObject()) << "Failed to send request to device" << zdoReply->request() << zdoReply->error(); + break; + } + m_pendingReplies.remove(zdoReply->transactionSequenceNumber()); zdoReply->finished(); } diff --git a/libnymea-zigbee/zdo/zigbeedeviceobjectreply.cpp b/libnymea-zigbee/zdo/zigbeedeviceobjectreply.cpp index 43d113b..fddbe29 100644 --- a/libnymea-zigbee/zdo/zigbeedeviceobjectreply.cpp +++ b/libnymea-zigbee/zdo/zigbeedeviceobjectreply.cpp @@ -39,6 +39,16 @@ ZigbeeDeviceObjectReply::Error ZigbeeDeviceObjectReply::error() const return m_error; } +Zigbee::ZigbeeApsStatus ZigbeeDeviceObjectReply::zigbeeApsStatus() const +{ + return m_zigbeeApsStatus; +} + +Zigbee::ZigbeeNwkLayerStatus ZigbeeDeviceObjectReply::zigbeeNwkStatus() const +{ + return m_zigbeeNwkStatus; +} + ZigbeeNetworkRequest ZigbeeDeviceObjectReply::request() const { return m_request; @@ -64,11 +74,6 @@ ZigbeeDeviceProfile::Adpu ZigbeeDeviceObjectReply::responseAdpu() const return m_responseAdpu; } -Zigbee::ZigbeeApsStatus ZigbeeDeviceObjectReply::zigbeeApsStatus() const -{ - return m_zigbeeApsStatus; -} - bool ZigbeeDeviceObjectReply::isComplete() const { return m_apsConfirmReceived && m_zdpIndicationReceived; diff --git a/libnymea-zigbee/zdo/zigbeedeviceobjectreply.h b/libnymea-zigbee/zdo/zigbeedeviceobjectreply.h index 1117415..aeef278 100644 --- a/libnymea-zigbee/zdo/zigbeedeviceobjectreply.h +++ b/libnymea-zigbee/zdo/zigbeedeviceobjectreply.h @@ -44,12 +44,15 @@ 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() ErrorInterfaceError, // A transport interface error occured. Could not communicate with the hardware. ErrorNetworkOffline // The network is offline. Cannot send any requests }; Q_ENUM(Error) Error error() const; + Zigbee::ZigbeeApsStatus zigbeeApsStatus() const; + Zigbee::ZigbeeNwkLayerStatus zigbeeNwkStatus() const; ZigbeeNetworkRequest request() const; quint8 transactionSequenceNumber() const; @@ -58,7 +61,6 @@ public: QByteArray responseData() const; ZigbeeDeviceProfile::Adpu responseAdpu() const; - Zigbee::ZigbeeApsStatus zigbeeApsStatus() const; bool isComplete() const; @@ -74,6 +76,7 @@ private: // APS transport bool m_apsConfirmReceived = false; Zigbee::ZigbeeApsStatus m_zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess; + Zigbee::ZigbeeNwkLayerStatus m_zigbeeNwkStatus = Zigbee::ZigbeeNwkLayerStatusSuccess; // ZDP response data bool m_zdpIndicationReceived = false; diff --git a/libnymea-zigbee/zigbee.h b/libnymea-zigbee/zigbee.h index 376c2d6..c22a77f 100644 --- a/libnymea-zigbee/zigbee.h +++ b/libnymea-zigbee/zigbee.h @@ -391,8 +391,7 @@ public: Q_ENUM(Manufacturer) enum ZigbeeNwkLayerStatus { - ZigbeeNwkLayerStatusJointNetwork = 0x00, - ZigbeeNwkLayerStatusFormedNetwork = 0x01, + ZigbeeNwkLayerStatusSuccess = 0x00, ZigbeeNwkLayerStatusInvalidParameter = 0xc1, ZigbeeNwkLayerStatusInvalidRequest = 0xc2, ZigbeeNwkLayerStatusNotPermitted = 0xc3, @@ -403,10 +402,13 @@ public: ZigbeeNwkLayerStatusUnknownDevice = 0xc8, ZigbeeNwkLayerStatusUnsupportedAttribute = 0xc9, ZigbeeNwkLayerStatusNoNetworks = 0xca, - ZigbeeNwkLayerStatusLeaveUnconfirmed = 0xcb, ZigbeeNwkLayerStatusMaxFrmCntr = 0xcc, ZigbeeNwkLayerStatusNoKey = 0xcd, - ZigbeeNwkLayerStatusBadCcmOutput = 0xce + ZigbeeNwkLayerStatusBadCcmOutput = 0xce, + ZigbeeNwkLayerStatusRouteDiscoveryFailed = 0xd0, + ZigbeeNwkLayerStatusRouteError = 0xd1, + ZigbeeNwkLayerStatusBtTableFull = 0xd2, + ZigbeeNwkLayerStatusFrameNotBuffered = 0xd3 }; Q_ENUM(ZigbeeNwkLayerStatus) diff --git a/libnymea-zigbee/zigbeenetwork.cpp b/libnymea-zigbee/zigbeenetwork.cpp index 52f8307..8378ccb 100644 --- a/libnymea-zigbee/zigbeenetwork.cpp +++ b/libnymea-zigbee/zigbeenetwork.cpp @@ -541,25 +541,46 @@ ZigbeeNetworkReply *ZigbeeNetwork::createNetworkReply(const ZigbeeNetworkRequest { ZigbeeNetworkReply *reply = new ZigbeeNetworkReply(request, this); // Make sure the reply will be deleted - connect(reply, &ZigbeeNetworkReply::finished, reply, &ZigbeeNetworkReply::deleteLater); + connect(reply, &ZigbeeNetworkReply::finished, reply, &ZigbeeNetworkReply::deleteLater, Qt::QueuedConnection); return reply; } void ZigbeeNetwork::setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::ZigbeeApsStatus zigbeeApsStatus) { - reply->m_zigbeeApsStatus = zigbeeApsStatus; - - if (reply->m_zigbeeApsStatus == Zigbee::ZigbeeApsStatusSuccess) { + if (zigbeeApsStatus == Zigbee::ZigbeeApsStatusSuccess) { + // The request has been sent successfully to the device finishNetworkReply(reply); } else { - finishNetworkReply(reply, ZigbeeNetworkReply::ErrorZigbeeApsStatusError); + // 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) { + reply->m_zigbeeNwkStatus = static_cast(static_cast(zigbeeApsStatus)); + finishNetworkReply(reply, ZigbeeNetworkReply::ErrorZigbeeNwkStatusError); + } else { + reply->m_zigbeeApsStatus = zigbeeApsStatus; + finishNetworkReply(reply, ZigbeeNetworkReply::ErrorZigbeeApsStatusError); + } } } void ZigbeeNetwork::finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkReply::Error error) { - qCDebug(dcZigbeeNetwork()) << "Reply finished" << error << reply->request(); reply->m_error = error; + switch(reply->error()) { + case ZigbeeNetworkReply::ErrorNoError: + qCDebug(dcZigbeeNetwork()) << "Network request sent successfully to device" << reply->request(); + break; + case ZigbeeNetworkReply::ErrorZigbeeApsStatusError: + qCWarning(dcZigbeeNetwork()) << "Failed to send request to device" << reply->request() << reply->error() << reply->zigbeeApsStatus(); + break; + case ZigbeeNetworkReply::ErrorZigbeeNwkStatusError: + qCWarning(dcZigbeeNetwork()) << "Failed to send request to device" << reply->request() << reply->error() << reply->zigbeeNwkStatus(); + break; + default: + qCWarning(dcZigbeeNetwork()) << "Failed to send request to device" << reply->request() << reply->error(); + break; + } + reply->finished(); } diff --git a/libnymea-zigbee/zigbeenetworkreply.cpp b/libnymea-zigbee/zigbeenetworkreply.cpp index 4ab80fd..8077a17 100644 --- a/libnymea-zigbee/zigbeenetworkreply.cpp +++ b/libnymea-zigbee/zigbeenetworkreply.cpp @@ -42,6 +42,11 @@ Zigbee::ZigbeeApsStatus ZigbeeNetworkReply::zigbeeApsStatus() const return m_zigbeeApsStatus; } +Zigbee::ZigbeeNwkLayerStatus ZigbeeNetworkReply::zigbeeNwkStatus() const +{ + return m_zigbeeNwkStatus; +} + ZigbeeNetworkReply::ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent) : QObject(parent), m_request(request) diff --git a/libnymea-zigbee/zigbeenetworkreply.h b/libnymea-zigbee/zigbeenetworkreply.h index 96eadad..6018d25 100644 --- a/libnymea-zigbee/zigbeenetworkreply.h +++ b/libnymea-zigbee/zigbeenetworkreply.h @@ -44,6 +44,7 @@ public: enum Error { ErrorNoError, ErrorZigbeeApsStatusError, + ErrorZigbeeNwkStatusError, ErrorInterfaceError, ErrorNetworkOffline }; @@ -53,6 +54,7 @@ public: ZigbeeNetworkRequest request() const; Zigbee::ZigbeeApsStatus zigbeeApsStatus() const; + Zigbee::ZigbeeNwkLayerStatus zigbeeNwkStatus() const; private: explicit ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent = nullptr); @@ -60,6 +62,7 @@ private: Error m_error = ErrorNoError; Zigbee::ZigbeeApsStatus m_zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess; + Zigbee::ZigbeeNwkLayerStatus m_zigbeeNwkStatus = Zigbee::ZigbeeNwkLayerStatusSuccess; signals: void finished(); diff --git a/libnymea-zigbee/zigbeenodeendpoint.cpp b/libnymea-zigbee/zigbeenodeendpoint.cpp index 348d41d..6f18d54 100644 --- a/libnymea-zigbee/zigbeenodeendpoint.cpp +++ b/libnymea-zigbee/zigbeenodeendpoint.cpp @@ -122,6 +122,24 @@ bool ZigbeeNodeEndpoint::hasOutputCluster(Zigbee::ClusterId clusterId) const return m_outputClusters.keys().contains(clusterId); } +void ZigbeeNodeEndpoint::createInputCluster(quint16 clusterId) +{ + Zigbee::ClusterId id = static_cast(clusterId); + if (hasInputCluster(id)) + return; + + addInputCluster(createCluster(static_cast(clusterId), ZigbeeCluster::Server)); +} + +void ZigbeeNodeEndpoint::createOutputCluster(quint16 clusterId) +{ + Zigbee::ClusterId id = static_cast(clusterId); + if (hasInputCluster(id)) + return; + + addOutputCluster(createCluster(static_cast(clusterId), ZigbeeCluster::Client)); +} + ZigbeeNodeEndpoint::ZigbeeNodeEndpoint(ZigbeeNetwork *network, ZigbeeNode *node, quint8 endpointId, QObject *parent) : QObject(parent), m_network(network), diff --git a/libnymea-zigbee/zigbeenodeendpoint.h b/libnymea-zigbee/zigbeenodeendpoint.h index 2434770..cdaf5d1 100644 --- a/libnymea-zigbee/zigbeenodeendpoint.h +++ b/libnymea-zigbee/zigbeenodeendpoint.h @@ -108,6 +108,13 @@ public: return qobject_cast(getOutputCluster(clusterId)); } + // Note: these methods can be used for devices which do not + // show the clusters in the simple descriptor. By default these methods + // should not be neccessary + void createInputCluster(quint16 clusterId); + void createOutputCluster(quint16 clusterId); + + private: explicit ZigbeeNodeEndpoint(ZigbeeNetwork *network, ZigbeeNode *node, quint8 endpointId, QObject *parent = nullptr); ~ZigbeeNodeEndpoint();