Add pressure cluster and improve nxp backend APS handling

pull/10/head
Simon Stürz 2020-11-11 15:50:28 +01:00
parent 339719c03c
commit af26efac17
19 changed files with 291 additions and 51 deletions

View File

@ -57,6 +57,8 @@ public:
NotificationNetworkStarted = 0x7E,
NotificationApsDataConfirm = 0x80,
NotificationApsDataIndication = 0x81,
NotificationNodeJoined = 0x90,
NotificationNodeLeft = 0x91,
NotificationDebugMessage = 0xFE
};
Q_ENUM(Notification)

View File

@ -328,7 +328,7 @@ ZigbeeInterfaceNxpReply *ZigbeeBridgeControllerNxp::requestEnqueueSendDataGroup(
payloadStream << profileId;
payloadStream << clusterId;
payloadStream << sourceEndpoint;
payloadStream << static_cast<quint8>(0x00); // Network and application layer security
payloadStream << static_cast<quint8>(SecurityModeUnsecure);
payloadStream << radius;
payloadStream << static_cast<quint16>(asdu.size());
for (int i = 0; i < asdu.size(); i++) {
@ -364,7 +364,7 @@ ZigbeeInterfaceNxpReply *ZigbeeBridgeControllerNxp::requestEnqueueSendDataShortA
payloadStream << profileId;
payloadStream << clusterId;
payloadStream << sourceEndpoint;
payloadStream << static_cast<quint8>(0x00); // Network and application layer security
payloadStream << static_cast<quint8>(SecurityModeUnsecure);
payloadStream << radius;
payloadStream << static_cast<quint16>(asdu.size());
for (int i = 0; i < asdu.size(); i++) {
@ -400,7 +400,7 @@ ZigbeeInterfaceNxpReply *ZigbeeBridgeControllerNxp::requestEnqueueSendDataIeeeAd
payloadStream << profileId;
payloadStream << clusterId;
payloadStream << sourceEndpoint;
payloadStream << static_cast<quint8>(0x00); // Network and application layer security
payloadStream << static_cast<quint8>(SecurityModeUnsecure);
payloadStream << radius;
payloadStream << static_cast<quint16>(asdu.size());
for (int i = 0; i < asdu.size(); i++) {
@ -559,6 +559,18 @@ void ZigbeeBridgeControllerNxp::onInterfacePackageReceived(const QByteArray &pac
emit apsDataIndicationReceived(indication);
break;
}
case Nxp::NotificationNodeJoined: {
break;
}
case Nxp::NotificationNodeLeft: {
QDataStream stream(&payload, QIODevice::ReadOnly);
stream.setByteOrder(QDataStream::LittleEndian);
quint64 ieeeAddress; quint8 rejoining;
stream >> ieeeAddress >> rejoining;
emit nodeLeft(ZigbeeAddress(ieeeAddress), static_cast<bool>(rejoining));
break;
}
case Nxp::NotificationDebugMessage: {
if (payload.isEmpty()) {
qCWarning(dcZigbeeController()) << "Received empty debug log notification";
@ -567,9 +579,9 @@ void ZigbeeBridgeControllerNxp::onInterfacePackageReceived(const QByteArray &pac
Nxp::LogLevel logLevel = static_cast<Nxp::LogLevel>(payload.at(0));
QString debugMessage = QString::fromLocal8Bit(payload.right(payload.length() - 1));
if (static_cast<quint8>(logLevel) <= static_cast<quint8>(Nxp::LogLevelWarning)) {
qCWarning(dcZigbeeController()) << "***** Controller DEBUG *****" << logLevel << debugMessage;
qCWarning(dcZigbeeControllerDebug()) << "====== Controller DEBUG" << logLevel << debugMessage;
} else {
qCDebug(dcZigbeeController()) << "***** Controller DEBUG *****" << logLevel << debugMessage;
qCDebug(dcZigbeeControllerDebug()) << "====== Controller DEBUG" << logLevel << debugMessage;
}
break;
}

View File

@ -61,6 +61,15 @@ public:
};
Q_ENUM(ControllerState)
enum SecurityMode {
SecurityModeUnsecure = 0x00,
SecurityModeSecure = 0x01,
SecurityModeSecureNwk = 0x02,
SecurityModeExtendedNonde = 0x10,
SecurityModeWildProfile = 0x20
};
Q_ENUM(SecurityMode)
ControllerState controllerState() const;
void refreshControllerState();
@ -91,6 +100,7 @@ public:
signals:
void controllerStateChanged(ControllerState controllerState);
void interfaceNotificationReceived(Nxp::Notification notification, const QByteArray &data);
void nodeLeft(const ZigbeeAddress &address, bool rejoining);
private:
ZigbeeInterfaceNxp *m_interface = nullptr;

View File

@ -42,6 +42,7 @@ ZigbeeNetworkNxp::ZigbeeNetworkNxp(const QUuid &networkUuid, QObject *parent) :
connect(m_controller, &ZigbeeBridgeControllerNxp::controllerStateChanged, this, &ZigbeeNetworkNxp::onControllerStateChanged);
connect(m_controller, &ZigbeeBridgeControllerNxp::apsDataConfirmReceived, this, &ZigbeeNetworkNxp::onApsDataConfirmReceived);
connect(m_controller, &ZigbeeBridgeControllerNxp::apsDataIndicationReceived, this, &ZigbeeNetworkNxp::onApsDataIndicationReceived);
connect(m_controller, &ZigbeeBridgeControllerNxp::nodeLeft, this, &ZigbeeNetworkNxp::onNodeLeftIndication);
connect(m_controller, &ZigbeeBridgeControllerNxp::canUpdateChanged, this, [](bool canUpdate){
if (canUpdate) {
qCDebug(dcZigbeeNetwork()) << "The controller of this network can be updated.";
@ -566,6 +567,19 @@ void ZigbeeNetworkNxp::onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress iee
node->startInitialization();
}
void ZigbeeNetworkNxp::onNodeLeftIndication(const ZigbeeAddress &ieeeAddress, bool rejoining)
{
qCDebug(dcZigbeeNetwork()) << "Received node left indication" << ieeeAddress.toString() << "rejoining:" << rejoining;
if (!hasNode(ieeeAddress)) {
qCWarning(dcZigbeeNetwork()) << "Unknown node left the network" << ieeeAddress.toString();
return;
}
ZigbeeNode *node = getZigbeeNode(ieeeAddress);
qCDebug(dcZigbeeNetwork()) << node << "left the network";
removeNode(node);
}
void ZigbeeNetworkNxp::startNetwork()
{
loadNetwork();

View File

@ -73,7 +73,7 @@ private slots:
void onApsDataIndicationReceived(const Zigbee::ApsdeDataIndication &indication);
void onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities);
void onNodeLeftIndication(const ZigbeeAddress &ieeeAddress, bool rejoining);
signals:

View File

@ -25,6 +25,7 @@ SOURCES += \
zcl/lighting/zigbeeclustercolorcontrol.cpp \
zcl/measurement/zigbeeclusterilluminancemeasurment.cpp \
zcl/measurement/zigbeeclusteroccupancysensing.cpp \
zcl/measurement/zigbeeclusterpressuremeasurement.cpp \
zcl/measurement/zigbeeclusterrelativehumiditymeasurement.cpp \
zcl/measurement/zigbeeclustertemperaturemeasurement.cpp \
zcl/ota/zigbeeclusterota.cpp \
@ -79,6 +80,7 @@ HEADERS += \
zcl/lighting/zigbeeclustercolorcontrol.h \
zcl/measurement/zigbeeclusterilluminancemeasurment.h \
zcl/measurement/zigbeeclusteroccupancysensing.h \
zcl/measurement/zigbeeclusterpressuremeasurement.h \
zcl/measurement/zigbeeclusterrelativehumiditymeasurement.h \
zcl/measurement/zigbeeclustertemperaturemeasurement.h \
zcl/ota/zigbeeclusterota.h \

View File

@ -37,5 +37,6 @@ Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController")
Q_LOGGING_CATEGORY(dcZigbeeDeviceObject, "ZigbeeDeviceObject")
Q_LOGGING_CATEGORY(dcZigbeeAdapterMonitor, "ZigbeeAdapterMonitor")
Q_LOGGING_CATEGORY(dcZigbeeClusterLibrary, "ZigbeeClusterLibrary")
Q_LOGGING_CATEGORY(dcZigbeeControllerDebug, "ZigbeeControllerDebug")
Q_LOGGING_CATEGORY(dcZigbeeNetworkDatabase, "ZigbeeNetworkDatabase")
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")

View File

@ -41,6 +41,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeDeviceObject)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeAdapterMonitor)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeClusterLibrary)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeControllerDebug)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetworkDatabase)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic)

View File

@ -49,14 +49,17 @@ public:
// Mains information
AttributeMainsVoltage = 0x0000,
AttributeMainsFrequency = 0x0001,
// Mains settings
AttributeMainsAlarmMask = 0x0010,
AttributeMainsVoltageMinThreshold = 0x0011,
AttributeMainsVoltageMaxThreshold = 0x0012,
AttributeMainsVoltageDwellTripPoint = 0x0013,
// Battery information
AttributeBatteryVoltage = 0x0020,
AttributeBatteryPercentageRemaining = 0x0021,
// Battery settings
AttributeBatteryManufacturer = 0x0030,
AttributeBatterySize = 0x0031,
@ -84,7 +87,6 @@ public:
Q_ENUM(MainsAlarmMask)
Q_DECLARE_FLAGS(MainsAlarmMaskFlag, MainsAlarmMask)
explicit ZigbeeClusterPowerConfiguration(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
private:

View File

@ -50,10 +50,12 @@ public:
// Occupancy sensor information set
AttributeOccupancy = 0x0000,
AttributeOccupancySensorType = 0x0001,
// PRI configuration set
AttributePirOccupiedToUnoccupiedDelay = 0x0010,
AttributePirUnoccupiedToOccupiedDelay = 0x0011,
AttributePirUnoccupiedToOccupiedThreshold = 0x0012,
// Ultrasonic configuration set
AttributeUltrasonicOccupiedToUnoccupiedDelay = 0x0020,
AttributeUltrasonicUnoccupiedToOccupiedDelay = 0x0021,

View File

@ -0,0 +1,68 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea-zigbee.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; version 3.
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "zigbeeclusterpressuremeasurement.h"
#include "zigbeenetworkreply.h"
#include "loggingcategory.h"
#include "zigbeenetwork.h"
ZigbeeClusterPressureMeasurement::ZigbeeClusterPressureMeasurement(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, ZigbeeCluster::Direction direction, QObject *parent) :
ZigbeeCluster(network, node, endpoint, ZigbeeClusterLibrary::ClusterIdPressureMeasurement, direction, parent)
{
}
void ZigbeeClusterPressureMeasurement::setAttribute(const ZigbeeClusterAttribute &attribute)
{
qCDebug(dcZigbeeCluster()) << "Update attribute" << m_node << m_endpoint << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
if (hasAttribute(attribute.id())) {
m_attributes[attribute.id()] = attribute;
emit attributeChanged(attribute);
} else {
m_attributes.insert(attribute.id(), attribute);
emit attributeChanged(attribute);
}
// Parse the information for convinience
if (attribute.id() == AttributeMeasuredValue) {
bool valueOk = false;
qint16 value = attribute.dataType().toInt16(&valueOk);
if (valueOk) {
double pressure = value / 10.0;
qCDebug(dcZigbeeCluster()) << "Pressure changed on" << m_node << m_endpoint << this << pressure << "kPa";
emit pressureChanged(pressure);
}
} else if (attribute.id() == AttributeScaledValue) {
bool valueOk = false;
qint16 value = attribute.dataType().toInt16(&valueOk);
if (valueOk) {
double pressureScaled = value / 10.0;
qCDebug(dcZigbeeCluster()) << "Pressure scaled changed on" << m_node << m_endpoint << this << pressureScaled << "Pa";
emit pressureScaledChanged(pressureScaled);
}
}
}

View File

@ -0,0 +1,78 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea-zigbee.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; version 3.
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef ZIGBEECLUSTERPRESSUREMEASUREMENT_H
#define ZIGBEECLUSTERPRESSUREMEASUREMENT_H
#include <QObject>
#include "zcl/zigbeecluster.h"
#include "zcl/zigbeeclusterreply.h"
class ZigbeeNode;
class ZigbeeNetwork;
class ZigbeeNodeEndpoint;
class ZigbeeNetworkReply;
class ZigbeeClusterPressureMeasurement : public ZigbeeCluster
{
Q_OBJECT
friend class ZigbeeNode;
friend class ZigbeeNetwork;
public:
enum Attribute {
AttributeMeasuredValue = 0x0000,
AttributeMinMeasuredValue = 0x0001,
AttributeMaxMeasuredValue = 0x0002,
AttributeTolerance = 0x0003,
// Extended pressure measurment information
AttributeScaledValue = 0x0010,
AttributeMinScaledValue = 0x0011,
AttributeMaxScaledValue = 0x0012,
AttributeScaledTolerance = 0x0013,
AttributeScale = 0x0014
};
Q_ENUM(Attribute)
explicit ZigbeeClusterPressureMeasurement(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
private:
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
signals:
// kPa
void pressureChanged(double pressure);
// Pa
void pressureScaledChanged(double pressure);
};
#endif // ZIGBEECLUSTERPRESSUREMEASUREMENT_H

View File

@ -51,7 +51,7 @@ public:
bool operator!=(const ZigbeeAddress &other) const;
private:
quint64 m_address;
quint64 m_address = 0;
};

View File

@ -422,6 +422,11 @@ ZigbeeNode *ZigbeeNetwork::createNode(quint16 shortAddress, const ZigbeeAddress
void ZigbeeNetwork::loadNetwork()
{
if (m_networkLoaded) {
qCDebug(dcZigbeeNetwork()) << "Network already loaded";
return;
}
qCDebug(dcZigbeeNetwork()) << "Loading network from settings directory" << m_settingsDirectory.absolutePath();
if (!m_database) {
QString networkDatabaseFileName = m_settingsDirectory.absolutePath() + QDir::separator() + QString("zigbee-network-%1.db").arg(m_networkUuid.toString().remove('{').remove('}'));
@ -434,6 +439,8 @@ void ZigbeeNetwork::loadNetwork()
node->setState(ZigbeeNode::StateInitialized);
addNodeInternally(node);
}
m_networkLoaded = true;
}
void ZigbeeNetwork::clearSettings()
@ -462,6 +469,7 @@ void ZigbeeNetwork::clearSettings()
// Reset network configurations
qCDebug(dcZigbeeNetwork()) << "Clear network properties";
m_networkLoaded = false;
setExtendedPanId(0);
setChannel(0);
setSecurityConfiguration(ZigbeeSecurityConfiguration());

View File

@ -125,6 +125,8 @@ public:
virtual ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) = 0;
void loadNetwork();
void removeZigbeeNode(const ZigbeeAddress &address);
private:
@ -162,6 +164,7 @@ protected:
ZigbeeNode *m_coordinatorNode = nullptr;
ZigbeeSecurityConfiguration m_securityConfiguration;
ZigbeeNetworkDatabase *m_database = nullptr;
bool m_networkLoaded = false;
ZigbeeNode *createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent);
ZigbeeNode *createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, quint8 macCapabilities, QObject *parent);
@ -176,7 +179,6 @@ protected:
void setPermitJoiningDuration(quint8 duration);
void setPermitJoiningRemaining(quint8 remaining);
void loadNetwork();
void clearSettings();
bool hasUninitializedNode(const ZigbeeAddress &address) const;

View File

@ -39,6 +39,8 @@ class ZigbeeNetwork;
class ZigbeeNodeEndpoint;
class ZigbeeClusterAttribute;
class QSqlDatabase;
class ZigbeeNetworkDatabase : public QObject
{
Q_OBJECT

View File

@ -445,24 +445,35 @@ void ZigbeeNode::readManufacturerName(ZigbeeClusterBasic *basicCluster)
connect(reply, &ZigbeeClusterReply::finished, this, [this, basicCluster, reply, attributeId](){
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
qCWarning(dcZigbeeNode()) << "Error occured during initialization of" << this << "Failed to read basic cluster attribute" << attributeId << reply->error();
} else {
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully";
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
if (!attributeStatusRecords.isEmpty()) {
ZigbeeClusterLibrary::ReadAttributeStatusRecord attributeStatusRecord = attributeStatusRecords.first();
qCDebug(dcZigbeeNode()) << attributeStatusRecord;
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecord.dataType));
bool valueOk = false;
QString manufacturerName = attributeStatusRecord.dataType.toString(&valueOk);
if (valueOk) {
endpoints().first()->m_manufacturerName = manufacturerName;
} else {
qCWarning(dcZigbeeNode()) << "Could not convert manufacturer name attribute data to string" << attributeStatusRecord.dataType;
}
if (m_requestRetry < 3) {
m_requestRetry++;
qCDebug(dcZigbeeNode()) << "Retry to read manufacturer name from" << this << basicCluster << m_requestRetry << "/" << "3 attempts.";
readManufacturerName(basicCluster);
} else {
qCWarning(dcZigbeeNode()) << "Failed to read manufacturer name from" << this << basicCluster << "after 3 attempts. Giving up and continue...";
m_requestRetry = 0;
readModelIdentifier(basicCluster);
}
return;
}
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully";
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
if (!attributeStatusRecords.isEmpty()) {
ZigbeeClusterLibrary::ReadAttributeStatusRecord attributeStatusRecord = attributeStatusRecords.first();
qCDebug(dcZigbeeNode()) << attributeStatusRecord;
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecord.dataType));
bool valueOk = false;
QString manufacturerName = attributeStatusRecord.dataType.toString(&valueOk);
if (valueOk) {
endpoints().first()->m_manufacturerName = manufacturerName;
} else {
qCWarning(dcZigbeeNode()) << "Could not convert manufacturer name attribute data to string" << attributeStatusRecord.dataType;
}
}
// Continue eiterh way with attribute reading
m_requestRetry = 0;
readModelIdentifier(basicCluster);
});
}
@ -493,24 +504,35 @@ void ZigbeeNode::readModelIdentifier(ZigbeeClusterBasic *basicCluster)
connect(reply, &ZigbeeClusterReply::finished, this, [this, basicCluster, reply, attributeId](){
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
qCWarning(dcZigbeeNode()) << "Error occured during initialization of" << this << "Failed to read basic cluster attribute" << attributeId << reply->error();
} else {
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully";
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
if (!attributeStatusRecords.isEmpty()) {
ZigbeeClusterLibrary::ReadAttributeStatusRecord attributeStatusRecord = attributeStatusRecords.first();
qCDebug(dcZigbeeNode()) << attributeStatusRecord;
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecord.dataType));
bool valueOk = false;
QString modelIdentifier = attributeStatusRecord.dataType.toString(&valueOk);
if (valueOk) {
endpoints().first()->m_modelIdentifier = modelIdentifier;
} else {
qCWarning(dcZigbeeNode()) << "Could not convert model identifier attribute data to string" << attributeStatusRecord.dataType;
}
if (m_requestRetry < 3) {
m_requestRetry++;
qCDebug(dcZigbeeNode()) << "Retry to read model identifier from" << this << basicCluster << m_requestRetry << "/" << "3 attempts.";
readModelIdentifier(basicCluster);
} else {
qCWarning(dcZigbeeNode()) << "Failed to read model identifier from" << this << basicCluster << "after 3 attempts. Giving up and continue...";
m_requestRetry = 0;
readSoftwareBuildId(basicCluster);
}
return;
}
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully";
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
if (!attributeStatusRecords.isEmpty()) {
ZigbeeClusterLibrary::ReadAttributeStatusRecord attributeStatusRecord = attributeStatusRecords.first();
qCDebug(dcZigbeeNode()) << attributeStatusRecord;
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecord.dataType));
bool valueOk = false;
QString modelIdentifier = attributeStatusRecord.dataType.toString(&valueOk);
if (valueOk) {
endpoints().first()->m_modelIdentifier = modelIdentifier;
} else {
qCWarning(dcZigbeeNode()) << "Could not convert model identifier attribute data to string" << attributeStatusRecord.dataType;
}
}
// Continue eiterh way with attribute reading
m_requestRetry = 0;
readSoftwareBuildId(basicCluster);
});
}
@ -523,20 +545,30 @@ void ZigbeeNode::readSoftwareBuildId(ZigbeeClusterBasic *basicCluster)
connect(reply, &ZigbeeClusterReply::finished, this, [this, basicCluster, reply, attributeId](){
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
qCWarning(dcZigbeeNode()) << "Error occured during initialization of" << this << "Failed to read basic cluster attribute" << attributeId << reply->error();
} else {
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully";
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
if (!attributeStatusRecords.isEmpty()) {
ZigbeeClusterLibrary::ReadAttributeStatusRecord attributeStatusRecord = attributeStatusRecords.first();
qCDebug(dcZigbeeNode()) << attributeStatusRecord;
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecord.dataType));
bool valueOk = false;
QString softwareBuildId = attributeStatusRecord.dataType.toString(&valueOk);
if (valueOk) {
endpoints().first()->m_softwareBuildId = softwareBuildId;
} else {
qCWarning(dcZigbeeNode()) << "Could not convert software build id attribute data to string" << attributeStatusRecord.dataType;
}
if (m_requestRetry < 3) {
m_requestRetry++;
qCDebug(dcZigbeeNode()) << "Retry to read model identifier from" << this << basicCluster << m_requestRetry << "/" << "3 attempts.";
readModelIdentifier(basicCluster);
} else {
qCWarning(dcZigbeeNode()) << "Failed to read model identifier from" << this << basicCluster << "after 3 attempts. Giving up and continue...";
m_requestRetry = 0;
readSoftwareBuildId(basicCluster);
}
return;
}
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully";
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
if (!attributeStatusRecords.isEmpty()) {
ZigbeeClusterLibrary::ReadAttributeStatusRecord attributeStatusRecord = attributeStatusRecords.first();
qCDebug(dcZigbeeNode()) << attributeStatusRecord;
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecord.dataType));
bool valueOk = false;
QString softwareBuildId = attributeStatusRecord.dataType.toString(&valueOk);
if (valueOk) {
endpoints().first()->m_softwareBuildId = softwareBuildId;
} else {
qCWarning(dcZigbeeNode()) << "Could not convert software build id attribute data to string" << attributeStatusRecord.dataType;
}
}

View File

@ -194,6 +194,9 @@ ZigbeeCluster *ZigbeeNodeEndpoint::createCluster(ZigbeeClusterLibrary::ClusterId
case ZigbeeClusterLibrary::ClusterIdOccupancySensing:
return new ZigbeeClusterOccupancySensing(m_network, m_node, this, direction, this);
break;
case ZigbeeClusterLibrary::ClusterIdPressureMeasurement:
return new ZigbeeClusterPressureMeasurement(m_network, m_node, this, direction, this);
break;
// Colsures
case ZigbeeClusterLibrary::ClusterIdDoorLock:

View File

@ -49,6 +49,7 @@
#include "zcl/measurement/zigbeeclusterilluminancemeasurment.h"
#include "zcl/measurement/zigbeeclustertemperaturemeasurement.h"
#include "zcl/measurement/zigbeeclusterrelativehumiditymeasurement.h"
#include "zcl/measurement/zigbeeclusterpressuremeasurement.h"
#include "zcl/lighting/zigbeeclustercolorcontrol.h"