Restructure error handling depnding on layer and add MAC layer errors to replies

pull/10/head
Simon Stürz 2020-11-24 18:14:54 +01:00
parent 0768903b07
commit 61114fc773
14 changed files with 155 additions and 113 deletions

View File

@ -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

View File

@ -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);

View File

@ -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();
}

View File

@ -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;

View File

@ -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;

View File

@ -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<ZigbeeDeviceProfile::ZdoCommand>(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<ZigbeeDeviceProfile::ZdoCommand>(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<ZigbeeDeviceProfile::ZdoCommand>(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<ZigbeeDeviceProfile::ZdoCommand>(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<ZigbeeDeviceProfile::ZdoCommand>(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<ZigbeeDeviceProfile::ZdoCommand>(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<ZigbeeDeviceProfile::ZdoCommand>(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<ZigbeeDeviceProfile::ZdoCommand>(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<ZigbeeDeviceProfile::ZdoCommand>(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<ZigbeeDeviceProfile::ZdoCommand>(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<ZigbeeDeviceProfile::ZdoCommand>(networkReply->request().clusterId()) << m_node << networkReply->error();
break;
case ZigbeeNetworkReply::ErrorTimeout:
zdoReply->m_error = ZigbeeDeviceObjectReply::ErrorTimeout;
qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" << static_cast<ZigbeeDeviceProfile::ZdoCommand>(networkReply->request().clusterId()) << m_node << networkReply->error();
break;
case ZigbeeNetworkReply::ErrorNetworkOffline:
zdoReply->m_error = ZigbeeDeviceObjectReply::ErrorNetworkOffline;
qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" << static_cast<ZigbeeDeviceProfile::ZdoCommand>(networkReply->request().clusterId()) << m_node << networkReply->error();
break;
case ZigbeeNetworkReply::ErrorZigbeeMacStatusError:
zdoReply->setZigbeeMacLayerStatus(networkReply->zigbeeMacStatus());
qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" << static_cast<ZigbeeDeviceProfile::ZdoCommand>(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<ZigbeeDeviceProfile::ZdoCommand>(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<ZigbeeDeviceProfile::ZdoCommand>(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);

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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<Zigbee::ZigbeeNwkLayerStatus>(static_cast<quint8>(zigbeeApsStatus));
finishNetworkReply(reply, ZigbeeNetworkReply::ErrorZigbeeNwkStatusError);
} else if (zigbeeApsStatus >= 0xE0 && zigbeeApsStatus <= 0xF4) {
reply->m_zigbeeMacStatus = static_cast<Zigbee::ZigbeeMacLayerStatus>(static_cast<quint8>(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;

View File

@ -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;

View File

@ -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;

View File

@ -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<quint16> inputClusters;

View File

@ -85,6 +85,7 @@ public:
// This method starts the node initialization phase (read descriptors and endpoints)
void startInitialization();
void removeAllBindings();
void readBindingTableEntries();
private: