Implement basic cluster comands and commuication
This commit is contained in:
parent
029ca76bae
commit
4e897686bb
@ -327,42 +327,70 @@ void ZigbeeNetworkDeconz::handleZigbeeDeviceProfileIndication(const DeconzApsDat
|
|||||||
}
|
}
|
||||||
|
|
||||||
node->deviceObject()->processApsDataIndication(indication.destinationEndpoint, indication.sourceEndpoint, indication.clusterId, indication.asdu, indication.lqi, indication.rssi);
|
node->deviceObject()->processApsDataIndication(indication.destinationEndpoint, indication.sourceEndpoint, indication.clusterId, indication.asdu, indication.lqi, indication.rssi);
|
||||||
|
}
|
||||||
|
|
||||||
// foreach (ZigbeeNetworkReply *reply, m_pendingReplies.values()) {
|
void ZigbeeNetworkDeconz::handleZigbeeLightLinkIndication(const DeconzApsDataIndication &indication)
|
||||||
// // Check if this is a reply if for a ZDO request
|
{
|
||||||
// if (reply->request().profileId() == Zigbee::ZigbeeProfileDevice) {
|
ZigbeeClusterLibrary::Frame frame = ZigbeeClusterLibrary::parseFrameData(indication.asdu);
|
||||||
// // We have a reply which is waiting for a ZDO response, lets check if they match
|
//qCDebug(dcZigbeeNetwork()) << "ZCL ZLL" << indication << frame;
|
||||||
// // Check if this is the response to the sent request command
|
|
||||||
// if (indication.clusterId == (reply->request().clusterId() | 0x8000)) {
|
|
||||||
// // Now check if the id matches, if so set the ADPU as response to the reply, otherwise this is not the message for this reply
|
|
||||||
// ZigbeeDeviceProfile::Adpu deviceAdpu = ZigbeeDeviceProfile::parseAdpu(indication.asdu);
|
|
||||||
// if (deviceAdpu.transactionSequenceNumber == reply->request().requestId()) {
|
|
||||||
// // We found the correct reply
|
|
||||||
|
|
||||||
// // Set the response payload of the
|
// Get the node
|
||||||
// qCDebug(dcZigbeeNetwork()) << "Indication response for ZDO request received"
|
ZigbeeNode *node = getZigbeeNode(indication.sourceShortAddress);
|
||||||
// << static_cast<ZigbeeDeviceProfile::ZdoCommand>(reply->request().clusterId())
|
if (!node) {
|
||||||
// << "-->"
|
qCWarning(dcZigbeeNetwork()) << "Received a ZCL indication for an unrecognized node. There is no such node in the system. Ignoring indication" << indication;
|
||||||
// << static_cast<ZigbeeDeviceProfile::ZdoCommand>(indication.clusterId)
|
return;
|
||||||
// << deviceAdpu;
|
}
|
||||||
// setReplyResponseData(reply, indication.asdu);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//qCWarning(dcZigbeeNetwork()) << "FIXME: Unhandled ZDO indication" << indication;
|
// Get the endpoint
|
||||||
|
ZigbeeNodeEndpoint *endpoint = node->getEndpoint(indication.sourceEndpoint);
|
||||||
|
if (!endpoint) {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "Received a ZCL indication for an unrecognized endpoint. There is no such endpoint on" << node << ". Ignoring indication" << indication;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the cluster
|
||||||
|
ZigbeeCluster *cluster = endpoint->getOutputCluster(static_cast<Zigbee::ClusterId>(indication.clusterId));
|
||||||
|
if (!cluster) {
|
||||||
|
cluster = endpoint->getInputCluster(static_cast<Zigbee::ClusterId>(indication.clusterId));
|
||||||
|
if (!cluster) {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "Received a ZCL indication for an unrecognized cluster. There is no such cluster on" << node << endpoint << "in the system. Ignoring indication" << indication;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cluster->processApsDataIndication(indication.asdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNetworkDeconz::handleZigbeeHomeAutomationIndication(const DeconzApsDataIndication &indication)
|
void ZigbeeNetworkDeconz::handleZigbeeHomeAutomationIndication(const DeconzApsDataIndication &indication)
|
||||||
{
|
{
|
||||||
ZigbeeClusterLibrary::Frame frame = ZigbeeClusterLibrary::parseFrameData(static_cast<Zigbee::ClusterId>(indication.clusterId), indication.asdu);
|
ZigbeeClusterLibrary::Frame frame = ZigbeeClusterLibrary::parseFrameData(indication.asdu);
|
||||||
qCDebug(dcZigbeeNetwork()) << "ZCL HA" << indication << frame;
|
//qCDebug(dcZigbeeNetwork()) << "ZCL HA" << indication << frame;
|
||||||
|
|
||||||
|
// Get the node
|
||||||
|
ZigbeeNode *node = getZigbeeNode(indication.sourceShortAddress);
|
||||||
|
if (!node) {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "Received a ZCL indication for an unrecognized node. There is no such node in the system. Ignoring indication" << indication;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the endpoint
|
||||||
|
ZigbeeNodeEndpoint *endpoint = node->getEndpoint(indication.sourceEndpoint);
|
||||||
|
if (!endpoint) {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "Received a ZCL indication for an unrecognized endpoint. There is no such endpoint on" << node << ". Ignoring indication" << indication;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the cluster
|
||||||
|
ZigbeeCluster *cluster = endpoint->getOutputCluster(static_cast<Zigbee::ClusterId>(indication.clusterId));
|
||||||
|
if (!cluster) {
|
||||||
|
cluster = endpoint->getInputCluster(static_cast<Zigbee::ClusterId>(indication.clusterId));
|
||||||
|
if (!cluster) {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "Received a ZCL indication for an unrecognized cluster. There is no such cluster on" << node << endpoint << "in the system. Ignoring indication" << indication;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cluster->processApsDataIndication(indication.asdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNetworkDeconz::setPermitJoiningInternal(bool permitJoining)
|
void ZigbeeNetworkDeconz::setPermitJoiningInternal(bool permitJoining)
|
||||||
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
#include "zigbeenetwork.h"
|
#include "zigbeenetwork.h"
|
||||||
#include "zigbeechannelmask.h"
|
#include "zigbeechannelmask.h"
|
||||||
#include "zigbeeclusterlibrary.h"
|
#include "zcl/zigbeeclusterlibrary.h"
|
||||||
#include "zigbeebridgecontrollerdeconz.h"
|
#include "zigbeebridgecontrollerdeconz.h"
|
||||||
|
|
||||||
class ZigbeeNetworkDeconz : public ZigbeeNetwork
|
class ZigbeeNetworkDeconz : public ZigbeeNetwork
|
||||||
@ -75,6 +75,7 @@ private:
|
|||||||
void handleZigbeeDeviceProfileIndication(const DeconzApsDataIndication &indication);
|
void handleZigbeeDeviceProfileIndication(const DeconzApsDataIndication &indication);
|
||||||
|
|
||||||
// ZZL
|
// ZZL
|
||||||
|
void handleZigbeeLightLinkIndication(const DeconzApsDataIndication &indication);
|
||||||
|
|
||||||
// HA
|
// HA
|
||||||
void handleZigbeeHomeAutomationIndication(const DeconzApsDataIndication &indication);
|
void handleZigbeeHomeAutomationIndication(const DeconzApsDataIndication &indication);
|
||||||
@ -4,30 +4,22 @@ TARGET = nymea-zigbee1
|
|||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
deconz/interface/zigbeeinterfacedeconz.cpp \
|
backends/deconz/interface/zigbeeinterfacedeconz.cpp \
|
||||||
deconz/interface/zigbeeinterfacedeconzreply.cpp \
|
backends/deconz/interface/zigbeeinterfacedeconzreply.cpp \
|
||||||
deconz/zigbeebridgecontrollerdeconz.cpp \
|
backends/deconz/zigbeebridgecontrollerdeconz.cpp \
|
||||||
deconz/zigbeenetworkdeconz.cpp \
|
backends/deconz/zigbeenetworkdeconz.cpp \
|
||||||
# nxp/interface/zigbeeinterface.cpp \
|
zcl/zigbeecluster.cpp \
|
||||||
# nxp/interface/zigbeeinterfacemessage.cpp \
|
zcl/zigbeeclusterattribute.cpp \
|
||||||
# nxp/interface/zigbeeinterfacerequest.cpp \
|
zcl/zigbeeclusterlibrary.cpp \
|
||||||
# nxp/interface/zigbeeinterfacereply.cpp \
|
|
||||||
# nxp/zigbeenetworknxp.cpp \
|
|
||||||
# nxp/zigbeebridgecontrollernxp.cpp \
|
|
||||||
# nxp/zigbeenodeendpointnxp.cpp \
|
|
||||||
# nxp/zigbeenodenxp.cpp \
|
|
||||||
zcl/zigbeeclusterbasic.cpp \
|
|
||||||
zcl/zigbeeclusterreply.cpp \
|
zcl/zigbeeclusterreply.cpp \
|
||||||
|
zcl/general/zigbeeclusterbasic.cpp \
|
||||||
zdo/zigbeedeviceobject.cpp \
|
zdo/zigbeedeviceobject.cpp \
|
||||||
zdo/zigbeedeviceobjectreply.cpp \
|
zdo/zigbeedeviceobjectreply.cpp \
|
||||||
zdo/zigbeedeviceprofile.cpp \
|
zdo/zigbeedeviceprofile.cpp \
|
||||||
zigbeeadpu.cpp \
|
zigbeeadpu.cpp \
|
||||||
zigbeebridgecontroller.cpp \
|
zigbeebridgecontroller.cpp \
|
||||||
zigbeechannelmask.cpp \
|
zigbeechannelmask.cpp \
|
||||||
zigbeecluster.cpp \
|
zigbeedatatype.cpp \
|
||||||
zigbeeclusterattribute.cpp \
|
|
||||||
zigbeeclusterlibrary.cpp \
|
|
||||||
zigbeeclusterlibraryreply.cpp \
|
|
||||||
zigbeemanufacturer.cpp \
|
zigbeemanufacturer.cpp \
|
||||||
zigbeenetwork.cpp \
|
zigbeenetwork.cpp \
|
||||||
zigbeenetworkdatabase.cpp \
|
zigbeenetworkdatabase.cpp \
|
||||||
@ -42,34 +34,33 @@ SOURCES += \
|
|||||||
zigbeeutils.cpp \
|
zigbeeutils.cpp \
|
||||||
zigbeenode.cpp \
|
zigbeenode.cpp \
|
||||||
zigbeeaddress.cpp \
|
zigbeeaddress.cpp \
|
||||||
|
# nxp/interface/zigbeeinterface.cpp \
|
||||||
|
# nxp/interface/zigbeeinterfacemessage.cpp \
|
||||||
|
# nxp/interface/zigbeeinterfacerequest.cpp \
|
||||||
|
# nxp/interface/zigbeeinterfacereply.cpp \
|
||||||
|
# nxp/zigbeenetworknxp.cpp \
|
||||||
|
# nxp/zigbeebridgecontrollernxp.cpp \
|
||||||
|
# nxp/zigbeenodeendpointnxp.cpp \
|
||||||
|
# nxp/zigbeenodenxp.cpp \
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
deconz/interface/deconz.h \
|
backends/deconz/interface/deconz.h \
|
||||||
deconz/interface/zigbeeinterfacedeconz.h \
|
backends/deconz/interface/zigbeeinterfacedeconz.h \
|
||||||
deconz/interface/zigbeeinterfacedeconzreply.h \
|
backends/deconz/interface/zigbeeinterfacedeconzreply.h \
|
||||||
deconz/zigbeebridgecontrollerdeconz.h \
|
backends/deconz/zigbeebridgecontrollerdeconz.h \
|
||||||
deconz/zigbeenetworkdeconz.h \
|
backends/deconz/zigbeenetworkdeconz.h \
|
||||||
# nxp/interface/zigbeeinterface.h \
|
zcl/zigbeecluster.h \
|
||||||
# nxp/interface/zigbeeinterfacemessage.h \
|
zcl/zigbeeclusterattribute.h \
|
||||||
# nxp/interface/zigbeeinterfacerequest.h \
|
zcl/zigbeeclusterlibrary.h \
|
||||||
# nxp/interface/zigbeeinterfacereply.h \
|
|
||||||
# nxp/zigbeenetworknxp.h \
|
|
||||||
# nxp/zigbeebridgecontrollernxp.h \
|
|
||||||
# nxp/zigbeenodeendpointnxp.h \
|
|
||||||
# nxp/zigbeenodenxp.h \
|
|
||||||
zcl/zigbeeclusterbasic.h \
|
|
||||||
zcl/zigbeeclusterreply.h \
|
zcl/zigbeeclusterreply.h \
|
||||||
|
zcl/general/zigbeeclusterbasic.h \
|
||||||
zdo/zigbeedeviceobject.h \
|
zdo/zigbeedeviceobject.h \
|
||||||
zdo/zigbeedeviceobjectreply.h \
|
zdo/zigbeedeviceobjectreply.h \
|
||||||
zdo/zigbeedeviceprofile.h \
|
zdo/zigbeedeviceprofile.h \
|
||||||
zigbeeadpu.h \
|
zigbeeadpu.h \
|
||||||
zigbeebridgecontroller.h \
|
zigbeebridgecontroller.h \
|
||||||
zigbeechannelmask.h \
|
zigbeechannelmask.h \
|
||||||
zigbeecluster.h \
|
zigbeedatatype.h \
|
||||||
zigbeeclusterattribute.h \
|
|
||||||
zigbeeclusterlibrary.h \
|
|
||||||
zigbeeclusterlibraryreply.h \
|
|
||||||
zigbeemanufacturer.h \
|
zigbeemanufacturer.h \
|
||||||
zigbeenetwork.h \
|
zigbeenetwork.h \
|
||||||
zigbeenetworkdatabase.h \
|
zigbeenetworkdatabase.h \
|
||||||
@ -84,7 +75,14 @@ HEADERS += \
|
|||||||
zigbeeutils.h \
|
zigbeeutils.h \
|
||||||
zigbeenode.h \
|
zigbeenode.h \
|
||||||
zigbeeaddress.h \
|
zigbeeaddress.h \
|
||||||
|
# nxp/interface/zigbeeinterface.h \
|
||||||
|
# nxp/interface/zigbeeinterfacemessage.h \
|
||||||
|
# nxp/interface/zigbeeinterfacerequest.h \
|
||||||
|
# nxp/interface/zigbeeinterfacereply.h \
|
||||||
|
# nxp/zigbeenetworknxp.h \
|
||||||
|
# nxp/zigbeebridgecontrollernxp.h \
|
||||||
|
# nxp/zigbeenodeendpointnxp.h \
|
||||||
|
# nxp/zigbeenodenxp.h \
|
||||||
|
|
||||||
# install header file with relative subdirectory
|
# install header file with relative subdirectory
|
||||||
for (header, HEADERS) {
|
for (header, HEADERS) {
|
||||||
|
|||||||
@ -34,5 +34,6 @@ Q_LOGGING_CATEGORY(dcZigbeeCluster, "ZigbeeCluster")
|
|||||||
Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface")
|
Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface")
|
||||||
Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController")
|
Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController")
|
||||||
Q_LOGGING_CATEGORY(dcZigbeeDeviceObject, "ZigbeeDeviceObject")
|
Q_LOGGING_CATEGORY(dcZigbeeDeviceObject, "ZigbeeDeviceObject")
|
||||||
|
Q_LOGGING_CATEGORY(dcZigbeeClusterLibrary, "ZigbeeClusterLibrary")
|
||||||
Q_LOGGING_CATEGORY(dcZigbeeNetworkDatabase, "ZigbeeNetworkDatabase")
|
Q_LOGGING_CATEGORY(dcZigbeeNetworkDatabase, "ZigbeeNetworkDatabase")
|
||||||
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")
|
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")
|
||||||
|
|||||||
@ -38,6 +38,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcZigbeeCluster)
|
|||||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface)
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController)
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeDeviceObject)
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeDeviceObject)
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeClusterLibrary)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetworkDatabase)
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetworkDatabase)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic)
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic)
|
||||||
|
|
||||||
|
|||||||
21
libnymea-zigbee/zcl/general/zigbeeclusterbasic.cpp
Normal file
21
libnymea-zigbee/zcl/general/zigbeeclusterbasic.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include "zigbeeclusterbasic.h"
|
||||||
|
#include "loggingcategory.h"
|
||||||
|
|
||||||
|
ZigbeeClusterBasic::ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent) :
|
||||||
|
ZigbeeCluster(network, node, endpoint, Zigbee::ClusterIdBasic, direction, parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeClusterBasic::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||||
|
{
|
||||||
|
if (hasAttribute(attribute.id())) {
|
||||||
|
qCDebug(dcZigbeeCluster()) << this << "update attribute" << static_cast<Attribute>(attribute.id()) << attribute.dataType() << attribute.data();
|
||||||
|
m_attributes[attribute.id()] = attribute;
|
||||||
|
emit attributeChanged(attribute);
|
||||||
|
} else {
|
||||||
|
qCDebug(dcZigbeeCluster()) << this << "add attribute" << static_cast<Attribute>(attribute.id()) << attribute.dataType() << attribute.data();
|
||||||
|
m_attributes.insert(attribute.id(), attribute);
|
||||||
|
emit attributeChanged(attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,13 +3,16 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "zigbeecluster.h"
|
#include "zcl/zigbeecluster.h"
|
||||||
|
|
||||||
class ZigbeeClusterBasic : public ZigbeeCluster
|
class ZigbeeClusterBasic : public ZigbeeCluster
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
friend class ZigbeeNode;
|
||||||
|
friend class ZigbeeNetwork;
|
||||||
|
|
||||||
enum Attribute {
|
enum Attribute {
|
||||||
AttributeZclVersion = 0x0000, // Mandatory
|
AttributeZclVersion = 0x0000, // Mandatory
|
||||||
AttributeAppVersion = 0x0001,
|
AttributeAppVersion = 0x0001,
|
||||||
@ -28,7 +31,7 @@ public:
|
|||||||
};
|
};
|
||||||
Q_ENUM(Attribute)
|
Q_ENUM(Attribute)
|
||||||
|
|
||||||
// From attribute 0x0007 power source
|
// Enum for AttributePowerSource(0x0007)
|
||||||
enum AttributePowerSourceValue {
|
enum AttributePowerSourceValue {
|
||||||
AttributePowerSourceValueUnknown = 0x00,
|
AttributePowerSourceValueUnknown = 0x00,
|
||||||
AttributePowerSourceValueMainsSinglePhase = 0x01,
|
AttributePowerSourceValueMainsSinglePhase = 0x01,
|
||||||
@ -40,9 +43,10 @@ public:
|
|||||||
};
|
};
|
||||||
Q_ENUM(AttributePowerSourceValue)
|
Q_ENUM(AttributePowerSourceValue)
|
||||||
|
|
||||||
|
|
||||||
explicit ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
explicit ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
@ -74,14 +74,14 @@ bool ZigbeeCluster::hasAttribute(quint16 attributeId) const
|
|||||||
return m_attributes.keys().contains(attributeId);
|
return m_attributes.keys().contains(attributeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeClusterAttribute ZigbeeCluster::attribute(quint16 id)
|
ZigbeeClusterAttribute ZigbeeCluster::attribute(quint16 attributeId)
|
||||||
{
|
{
|
||||||
return m_attributes.value(id);
|
return m_attributes.value(attributeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeCluster::setAttribute(const ZigbeeClusterAttribute &attribute)
|
void ZigbeeCluster::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||||
{
|
{
|
||||||
if (hasAttribute(attribute.id())) {
|
if (hasAttribute(attribute.id())) {
|
||||||
qCDebug(dcZigbeeCluster()) << this << "update attribute" << attribute;
|
qCDebug(dcZigbeeCluster()) << this << "update attribute" << attribute;
|
||||||
m_attributes[attribute.id()] = attribute;
|
m_attributes[attribute.id()] = attribute;
|
||||||
emit attributeChanged(attribute);
|
emit attributeChanged(attribute);
|
||||||
@ -92,28 +92,31 @@ void ZigbeeCluster::setAttribute(const ZigbeeClusterAttribute &attribute)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeNetworkReply *ZigbeeCluster::readAttributes(QList<quint16> attributes)
|
ZigbeeClusterReply *ZigbeeCluster::readAttributes(QList<quint16> attributes)
|
||||||
{
|
{
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Read attributes from" << m_node << m_endpoint << this << attributes;
|
||||||
|
|
||||||
// Build the request
|
// Build the request
|
||||||
ZigbeeNetworkRequest request;
|
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||||
request.setRequestId(m_network->generateSequenceNumber());
|
|
||||||
request.setDestinationAddressMode(Zigbee::DestinationAddressModeShortAddress);
|
|
||||||
request.setDestinationShortAddress(static_cast<quint16>(m_node->shortAddress()));
|
|
||||||
request.setProfileId(m_endpoint->profile());
|
|
||||||
request.setClusterId(m_clusterId);
|
|
||||||
request.setSourceEndpoint(m_endpoint->endpointId());
|
|
||||||
request.setRadius(10);
|
|
||||||
|
|
||||||
// Build ZCL frame
|
// Build ZCL frame
|
||||||
|
|
||||||
|
// Note: for basic commands the frame control files has to be zero accoring to spec ZCL 2.4.1.1
|
||||||
ZigbeeClusterLibrary::FrameControl frameControl;
|
ZigbeeClusterLibrary::FrameControl frameControl;
|
||||||
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeGlobal; // Note: for general commands always use global
|
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeGlobal;
|
||||||
|
frameControl.manufacturerSpecific = false;
|
||||||
|
if (m_direction == Direction::Input) {
|
||||||
|
frameControl.direction = ZigbeeClusterLibrary::DirectionClientToServer;
|
||||||
|
} else {
|
||||||
|
frameControl.direction = ZigbeeClusterLibrary::DirectionServerToClient;
|
||||||
|
}
|
||||||
frameControl.disableDefaultResponse = true;
|
frameControl.disableDefaultResponse = true;
|
||||||
|
|
||||||
// ZCL header
|
// ZCL header
|
||||||
ZigbeeClusterLibrary::Header header;
|
ZigbeeClusterLibrary::Header header;
|
||||||
header.frameControl = frameControl;
|
header.frameControl = frameControl;
|
||||||
header.command = ZigbeeClusterLibrary::CommandReadAttributes;
|
header.command = ZigbeeClusterLibrary::CommandReadAttributes;
|
||||||
header.transactionSequenceNumber = m_network->generateTranactionSequenceNumber();
|
header.transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||||
|
|
||||||
// ZCL payload
|
// ZCL payload
|
||||||
QByteArray payload;
|
QByteArray payload;
|
||||||
@ -125,15 +128,108 @@ ZigbeeNetworkReply *ZigbeeCluster::readAttributes(QList<quint16> attributes)
|
|||||||
|
|
||||||
// Put them together
|
// Put them together
|
||||||
ZigbeeClusterLibrary::Frame frame;
|
ZigbeeClusterLibrary::Frame frame;
|
||||||
frame.clusterId = m_clusterId;
|
|
||||||
frame.header = header;
|
frame.header = header;
|
||||||
frame.payload = payload;
|
frame.payload = payload;
|
||||||
|
|
||||||
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
||||||
request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame));
|
request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame));
|
||||||
|
|
||||||
qCDebug(dcZigbeeCluster()) << "Send read attributes request" << m_node << m_endpoint << this << attributes;
|
ZigbeeClusterReply *zclReply = createClusterReply(request, frame);
|
||||||
return m_network->sendRequest(request);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The request was successfully sent to the device
|
||||||
|
// Now check if the expected indication response received already
|
||||||
|
if (zclReply->isComplete()) {
|
||||||
|
finishZclReply(zclReply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return zclReply;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterReply *ZigbeeCluster::createClusterReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame frame)
|
||||||
|
{
|
||||||
|
ZigbeeClusterReply *zclReply = new ZigbeeClusterReply(request, frame, this);
|
||||||
|
connect(zclReply, &ZigbeeClusterReply::finished, zclReply, &ZigbeeClusterReply::deleteLater);
|
||||||
|
zclReply->m_transactionSequenceNumber = frame.header.transactionSequenceNumber;
|
||||||
|
m_pendingReplies.insert(zclReply->transactionSequenceNumber(), zclReply);
|
||||||
|
return zclReply;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeNetworkRequest ZigbeeCluster::createGeneralRequest()
|
||||||
|
{
|
||||||
|
// Build the request
|
||||||
|
ZigbeeNetworkRequest request;
|
||||||
|
request.setRequestId(m_network->generateSequenceNumber());
|
||||||
|
request.setDestinationAddressMode(Zigbee::DestinationAddressModeShortAddress);
|
||||||
|
request.setDestinationShortAddress(m_node->shortAddress());
|
||||||
|
request.setProfileId(Zigbee::ZigbeeProfileHomeAutomation); // Note: in Zigbee 3.0 this is the Application Profile (0x0104)
|
||||||
|
request.setClusterId(m_clusterId);
|
||||||
|
request.setSourceEndpoint(0x01);
|
||||||
|
request.setDestinationEndpoint(m_endpoint->endpointId());
|
||||||
|
request.setRadius(10);
|
||||||
|
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZigbeeCluster::verifyNetworkError(ZigbeeClusterReply *zclReply, ZigbeeNetworkReply *networkReply)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
switch (networkReply->error()) {
|
||||||
|
case ZigbeeNetworkReply::ErrorNoError:
|
||||||
|
// 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();
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
case ZigbeeNetworkReply::ErrorInterfaceError:
|
||||||
|
zclReply->m_error = ZigbeeClusterReply::ErrorInterfaceError;
|
||||||
|
break;
|
||||||
|
case ZigbeeNetworkReply::ErrorNetworkOffline:
|
||||||
|
zclReply->m_error = ZigbeeClusterReply::ErrorNetworkOffline;
|
||||||
|
break;
|
||||||
|
case ZigbeeNetworkReply::ErrorZigbeeApsStatusError:
|
||||||
|
zclReply->m_error = ZigbeeClusterReply::ErrorZigbeeApsStatusError;
|
||||||
|
zclReply->m_apsConfirmReceived = true;
|
||||||
|
zclReply->m_zigbeeApsStatus = networkReply->zigbeeApsStatus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeCluster::finishZclReply(ZigbeeClusterReply *zclReply)
|
||||||
|
{
|
||||||
|
m_pendingReplies.remove(zclReply->transactionSequenceNumber());
|
||||||
|
zclReply->finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeCluster::processApsDataIndication(QByteArray payload)
|
||||||
|
{
|
||||||
|
ZigbeeClusterLibrary::Frame frame = ZigbeeClusterLibrary::parseFrameData(payload);
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << this << "received data indication" << frame;
|
||||||
|
|
||||||
|
if (m_pendingReplies.contains(frame.header.transactionSequenceNumber)) {
|
||||||
|
ZigbeeClusterReply *reply = m_pendingReplies.value(frame.header.transactionSequenceNumber);
|
||||||
|
reply->m_responseData = payload;
|
||||||
|
reply->m_responseFrame = frame;
|
||||||
|
reply->m_zclIndicationReceived = true;
|
||||||
|
|
||||||
|
if (reply->isComplete())
|
||||||
|
finishZclReply(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster)
|
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster)
|
||||||
@ -143,7 +239,6 @@ QDebug operator<<(QDebug debug, ZigbeeCluster *cluster)
|
|||||||
<< cluster->clusterName() << ", "
|
<< cluster->clusterName() << ", "
|
||||||
<< cluster->direction()
|
<< cluster->direction()
|
||||||
<< ")";
|
<< ")";
|
||||||
|
|
||||||
return debug.space();
|
return debug.space();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,3 +254,4 @@ QDebug operator<<(QDebug debug, const ZigbeeClusterAttributeReport &attributeRep
|
|||||||
|
|
||||||
return debug.space();
|
return debug.space();
|
||||||
}
|
}
|
||||||
|
|
||||||
213
libnymea-zigbee/zcl/zigbeecluster.h
Normal file
213
libnymea-zigbee/zcl/zigbeecluster.h
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 ZIGBEECLUSTER_H
|
||||||
|
#define ZIGBEECLUSTER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "zigbee.h"
|
||||||
|
#include "zigbeeclusterreply.h"
|
||||||
|
#include "zigbeeclusterlibrary.h"
|
||||||
|
#include "zigbeeclusterattribute.h"
|
||||||
|
|
||||||
|
struct ZigbeeClusterReportConfigurationRecord {
|
||||||
|
quint8 direction;
|
||||||
|
Zigbee::DataType dataType;
|
||||||
|
quint16 attributeId;
|
||||||
|
quint16 minInterval;
|
||||||
|
quint16 maxInterval;
|
||||||
|
quint16 timeout;
|
||||||
|
quint8 change;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct ZigbeeClusterAttributeReport {
|
||||||
|
quint16 sourceAddress;
|
||||||
|
quint8 endpointId;
|
||||||
|
Zigbee::ClusterId clusterId;
|
||||||
|
quint16 attributeId;
|
||||||
|
Zigbee::ZigbeeStatus attributeStatus;
|
||||||
|
Zigbee::DataType dataType;
|
||||||
|
QByteArray data;
|
||||||
|
} ZigbeeClusterAttributeReport;
|
||||||
|
|
||||||
|
class ZigbeeNode;
|
||||||
|
class ZigbeeNetwork;
|
||||||
|
class ZigbeeNodeEndpoint;
|
||||||
|
class ZigbeeNetworkReply;
|
||||||
|
|
||||||
|
class ZigbeeCluster : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend class ZigbeeNode;
|
||||||
|
friend class ZigbeeNetwork;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Direction {
|
||||||
|
Input,
|
||||||
|
Output
|
||||||
|
};
|
||||||
|
Q_ENUM(Direction)
|
||||||
|
|
||||||
|
|
||||||
|
// // Power configuration cluster 0x0001
|
||||||
|
|
||||||
|
// enum PowerConfigurationAttribute {
|
||||||
|
// PowerConfigurationAttributeMainsInformation = 0x0000,
|
||||||
|
// PowerConfigurationAttributeMainsSettings = 0x0001,
|
||||||
|
// PowerConfigurationAttributeBatteryInformation = 0x0002,
|
||||||
|
// PowerConfigurationAttributeBatterySettings = 0x0003,
|
||||||
|
// PowerConfigurationAttributeBatterySource2Information = 0x0004,
|
||||||
|
// PowerConfigurationAttributeBattterySource2Settings = 0x0005,
|
||||||
|
// PowerConfigurationAttributeBatterySource3Information = 0x0006,
|
||||||
|
// PowerConfigurationAttributeBattterySource3Settings = 0x0007
|
||||||
|
// };
|
||||||
|
// Q_ENUM(PowerConfigurationAttribute)
|
||||||
|
|
||||||
|
// // On Off Cluster 0x0006
|
||||||
|
|
||||||
|
// enum OnOffClusterAttribute {
|
||||||
|
// OnOffClusterAttributeOnOff = 0x0000,
|
||||||
|
// OnOffClusterAttributeGlobalSceneControl = 0x4000,
|
||||||
|
// OnOffClusterAttributeOnTime = 0x4001,
|
||||||
|
// OnOffClusterAttributeOffWaitTime = 0x4002
|
||||||
|
// };
|
||||||
|
// Q_ENUM(OnOffClusterAttribute)
|
||||||
|
|
||||||
|
// enum OnOffClusterCommand {
|
||||||
|
// OnOffClusterCommandOff = 0x00,
|
||||||
|
// OnOffClusterCommandOn = 0x01,
|
||||||
|
// OnOffClusterCommandToggle = 0x02
|
||||||
|
// };
|
||||||
|
// Q_ENUM(OnOffClusterCommand)
|
||||||
|
|
||||||
|
|
||||||
|
// // Level cluster 0x0008
|
||||||
|
|
||||||
|
// enum LevelClusterAttribute {
|
||||||
|
// LevelClusterAttributeCurrentLevel = 0x0000,
|
||||||
|
// LevelClusterAttributeRemainingTime = 0x0001,
|
||||||
|
// LevelClusterAttributeOnOffTransitionTime = 0x0010,
|
||||||
|
// LevelClusterAttributeOnLevel = 0x0011,
|
||||||
|
// LevelClusterAttributeOnTransitionTime = 0x0012,
|
||||||
|
// LevelClusterAttributeOffTransitionTime = 0x0013,
|
||||||
|
// LevelClusterAttributeDefaultMoveRate = 0x0014
|
||||||
|
// };
|
||||||
|
// Q_ENUM(LevelClusterAttribute)
|
||||||
|
|
||||||
|
// enum LevelClusterCommand {
|
||||||
|
// LevelClusterCommandMoveToLevel = 0x00,
|
||||||
|
// LevelClusterCommandMove = 0x01,
|
||||||
|
// LevelClusterCommandStep = 0x02,
|
||||||
|
// LevelClusterCommandStop = 0x03,
|
||||||
|
// LevelClusterCommandMoveToLevelWithOnOff = 0x04,
|
||||||
|
// LevelClusterCommandMoveWithOnOff = 0x05,
|
||||||
|
// LevelClusterCommandStepWithOnOff = 0x06,
|
||||||
|
// LevelClusterCommandStopWithOnOff = 0x07,
|
||||||
|
// };
|
||||||
|
// Q_ENUM(LevelClusterCommand)
|
||||||
|
|
||||||
|
// // Color cluster 0x0300
|
||||||
|
|
||||||
|
// enum ColorControlClusterAttribute {
|
||||||
|
// ColorControlClusterAttributeCurrentHue = 0x0000,
|
||||||
|
// ColorControlClusterAttributeCurrentSaturation = 0x0001,
|
||||||
|
// ColorControlClusterAttributeRemainingTime = 0x0002,
|
||||||
|
// ColorControlClusterAttributeCurrentX = 0x0003,
|
||||||
|
// ColorControlClusterAttributeCurrentY = 0x0004,
|
||||||
|
// ColorControlClusterAttributeDriftCompensation = 0x0005,
|
||||||
|
// ColorControlClusterAttributeCompensationText = 0x0006,
|
||||||
|
// ColorControlClusterAttributeColorTemperatureMireds = 0x0007,
|
||||||
|
// ColorControlClusterAttributeColorMode = 0x0008,
|
||||||
|
// ColorControlClusterAttributeEnhancedCurrentHue = 0x4000,
|
||||||
|
// ColorControlClusterAttributeEnhancedColorMode = 0x4001,
|
||||||
|
// ColorControlClusterAttributeColorLoopActive = 0x4002,
|
||||||
|
// ColorControlClusterAttributeColorLoopDirection = 0x4003,
|
||||||
|
// ColorControlClusterAttributeColorLoopTime = 0x4004,
|
||||||
|
// ColorControlClusterAttributeColorLoopStartEnhancedHue = 0x4005,
|
||||||
|
// ColorControlClusterAttributeColorLoopStoredEnhancedHue = 0x4006,
|
||||||
|
// ColorControlClusterAttributeColorCapabilities = 0x400a,
|
||||||
|
// ColorControlClusterAttributeColorTempPhysicalMinMireds = 0x400b,
|
||||||
|
// ColorControlClusterAttributeColorTempPhysicalMaxMireds = 0x400c
|
||||||
|
// };
|
||||||
|
// Q_ENUM(ColorControlClusterAttribute)
|
||||||
|
|
||||||
|
// enum ColorControlClusterColorMode {
|
||||||
|
// ColorControlClusterColorModeHueSaturation = 0x00,
|
||||||
|
// ColorControlClusterColorModeXY = 0x01,
|
||||||
|
// ColorControlClusterColorModeColorTemperatureMired = 0x02
|
||||||
|
// };
|
||||||
|
// Q_ENUM(ColorControlClusterColorMode)
|
||||||
|
|
||||||
|
explicit ZigbeeCluster(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Zigbee::ClusterId clusterId, Direction direction, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
Direction direction() const;
|
||||||
|
|
||||||
|
Zigbee::ClusterId clusterId() const;
|
||||||
|
QString clusterName() const;
|
||||||
|
|
||||||
|
QList<ZigbeeClusterAttribute> attributes() const;
|
||||||
|
bool hasAttribute(quint16 attributeId) const;
|
||||||
|
ZigbeeClusterAttribute attribute(quint16 attributeId);
|
||||||
|
|
||||||
|
// ZCL global commands
|
||||||
|
ZigbeeClusterReply *readAttributes(QList<quint16> attributes);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ZigbeeNetwork *m_network = nullptr;
|
||||||
|
ZigbeeNode *m_node = nullptr;
|
||||||
|
ZigbeeNodeEndpoint *m_endpoint= nullptr;
|
||||||
|
|
||||||
|
Zigbee::ClusterId m_clusterId = Zigbee::ClusterIdUnknown;
|
||||||
|
Direction m_direction = Input;
|
||||||
|
QHash<quint16, ZigbeeClusterAttribute> m_attributes;
|
||||||
|
|
||||||
|
ZigbeeNetworkRequest createGeneralRequest();
|
||||||
|
quint8 m_transactionSequenceNumber = 0;
|
||||||
|
QHash<quint8, ZigbeeClusterReply *> m_pendingReplies;
|
||||||
|
ZigbeeClusterReply *createClusterReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame frame);
|
||||||
|
|
||||||
|
bool verifyNetworkError(ZigbeeClusterReply *zclReply, ZigbeeNetworkReply *networkReply);
|
||||||
|
void finishZclReply(ZigbeeClusterReply *zclReply);
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void setAttribute(const ZigbeeClusterAttribute &attribute);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void attributeChanged(const ZigbeeClusterAttribute &attribute);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void processApsDataIndication(QByteArray payload);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster);
|
||||||
|
QDebug operator<<(QDebug debug, const ZigbeeClusterAttributeReport &attributeReport);
|
||||||
|
|
||||||
|
#endif // ZIGBEECLUSTER_H
|
||||||
@ -1,7 +0,0 @@
|
|||||||
#include "zigbeeclusterbasic.h"
|
|
||||||
|
|
||||||
ZigbeeClusterBasic::ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent) :
|
|
||||||
ZigbeeCluster(network, node, endpoint, Zigbee::ClusterIdBasic, direction, parent)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -26,6 +26,7 @@
|
|||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#include "zigbeeclusterlibrary.h"
|
#include "zigbeeclusterlibrary.h"
|
||||||
|
#include "loggingcategory.h"
|
||||||
#include "zigbeeutils.h"
|
#include "zigbeeutils.h"
|
||||||
|
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
@ -35,7 +36,7 @@ quint8 ZigbeeClusterLibrary::buildFrameControlByte(const ZigbeeClusterLibrary::F
|
|||||||
quint8 byte = 0x00;
|
quint8 byte = 0x00;
|
||||||
|
|
||||||
// Bit 0-1
|
// Bit 0-1
|
||||||
byte |= FrameTypeClusterSpecific;
|
byte |= frameControl.frameType;
|
||||||
|
|
||||||
// Bit 2
|
// Bit 2
|
||||||
if (frameControl.manufacturerSpecific)
|
if (frameControl.manufacturerSpecific)
|
||||||
@ -93,7 +94,95 @@ QByteArray ZigbeeClusterLibrary::buildHeader(const ZigbeeClusterLibrary::Header
|
|||||||
return headerData;
|
return headerData;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeClusterLibrary::Frame ZigbeeClusterLibrary::parseFrameData(Zigbee::ClusterId clusterId, const QByteArray &frameData)
|
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> ZigbeeClusterLibrary::parseAttributeStatusRecords(const QByteArray &payload)
|
||||||
|
{
|
||||||
|
// Read attribute status records
|
||||||
|
QList<ReadAttributeStatusRecord> attributeStatusRecords;
|
||||||
|
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Parse attribute status records from" << ZigbeeUtils::convertByteArrayToHexString(payload);
|
||||||
|
|
||||||
|
QDataStream stream(payload);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
quint16 attributeId; quint8 statusInt; quint8 dataTypeInt; quint16 numberOfElenemts; quint8 elementType;
|
||||||
|
QByteArray data;
|
||||||
|
|
||||||
|
while (!stream.atEnd()) {
|
||||||
|
// Reset variables
|
||||||
|
attributeId = 0; statusInt = 0; dataTypeInt = 0; numberOfElenemts = 0; elementType = 0;
|
||||||
|
data.clear();
|
||||||
|
|
||||||
|
// Read attribute id and status
|
||||||
|
stream >> attributeId >> statusInt;
|
||||||
|
Zigbee::ZigbeeStatus status = static_cast<Zigbee::ZigbeeStatus>(statusInt);
|
||||||
|
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Parse:" << ZigbeeUtils::convertUint16ToHexString(attributeId) << status;
|
||||||
|
|
||||||
|
if (status != Zigbee::ZigbeeStatusSuccess) {
|
||||||
|
qCWarning(dcZigbeeCluster()) << "Attribute status record" << ZigbeeUtils::convertUint16ToHexString(attributeId) << "finished with error" << status;
|
||||||
|
// If not success, we are done and can continue with the next status record
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
stream >> dataTypeInt;
|
||||||
|
Zigbee::DataType dataType = static_cast<Zigbee::DataType>(dataTypeInt);
|
||||||
|
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Parse:" << dataType;
|
||||||
|
|
||||||
|
// Parse data depending on the type
|
||||||
|
if (dataType == Zigbee::Array || dataType == Zigbee::Set || dataType == Zigbee::Bag) {
|
||||||
|
stream >> elementType >> numberOfElenemts;
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Parse (array, set, bag): Element type" << ZigbeeUtils::convertByteToHexString(elementType) << "Number of elements:" << numberOfElenemts;
|
||||||
|
if (numberOfElenemts == 0xffff) {
|
||||||
|
qCWarning(dcZigbeeCluster()) << "ZigbeeStatusRecord contains invalid elements" << ZigbeeUtils::convertUint16ToHexString(attributeId) << dataType;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < numberOfElenemts; i++) {
|
||||||
|
quint8 element = 0;
|
||||||
|
stream >> element;
|
||||||
|
data.append(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (dataType == Zigbee::Structure) {
|
||||||
|
stream >> numberOfElenemts;
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Parse (structure)" << "Number of elements:" << numberOfElenemts;
|
||||||
|
if (numberOfElenemts == 0xffff) {
|
||||||
|
qCWarning(dcZigbeeCluster()) << "ZigbeeStatusRecord contains invalid elements" << ZigbeeUtils::convertUint16ToHexString(attributeId) << dataType;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
stream >> elementType;
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Parse (structure)" << "Element type:" << ZigbeeUtils::convertByteToHexString(elementType);
|
||||||
|
for (int i = 0; i < numberOfElenemts; i++) {
|
||||||
|
quint8 element = 0;
|
||||||
|
stream >> element;
|
||||||
|
//qCDebug(dcZigbeeClusterLibrary()) << "Parse (structure)" << "Element value:" << ZigbeeUtils::convertByteToHexString(element);
|
||||||
|
data.append(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Normal data type
|
||||||
|
quint8 length = 0;
|
||||||
|
stream >> length;
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Parse (normal data type)" << "Number of elements:" << length;
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
quint8 element = 0;
|
||||||
|
stream >> element;
|
||||||
|
data.append(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadAttributeStatusRecord attributeRecord;
|
||||||
|
attributeRecord.attributeId = attributeId;
|
||||||
|
attributeRecord.attributeStatus = status;
|
||||||
|
attributeRecord.dataType = dataType;
|
||||||
|
attributeRecord.data = data;
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << attributeRecord;
|
||||||
|
attributeStatusRecords.append(attributeRecord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributeStatusRecords;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterLibrary::Frame ZigbeeClusterLibrary::parseFrameData(const QByteArray &frameData)
|
||||||
{
|
{
|
||||||
QDataStream stream(frameData);
|
QDataStream stream(frameData);
|
||||||
stream.setByteOrder(QDataStream::LittleEndian);
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
@ -117,15 +206,12 @@ ZigbeeClusterLibrary::Frame ZigbeeClusterLibrary::parseFrameData(Zigbee::Cluster
|
|||||||
offset += 1;
|
offset += 1;
|
||||||
|
|
||||||
stream >> commandByte;
|
stream >> commandByte;
|
||||||
offset += 1;
|
|
||||||
|
|
||||||
header.command = static_cast<Command>(commandByte);
|
header.command = static_cast<Command>(commandByte);
|
||||||
offset += 1;
|
offset += 1;
|
||||||
|
|
||||||
Frame frame;
|
Frame frame;
|
||||||
frame.clusterId = clusterId;
|
|
||||||
frame.header = header;
|
frame.header = header;
|
||||||
frame.payload = frameData.right(frameData.length() - offset - 1);
|
frame.payload = frameData.right(frameData.length() - offset);
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,8 +255,20 @@ QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Header &header)
|
|||||||
|
|
||||||
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Frame &frame)
|
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Frame &frame)
|
||||||
{
|
{
|
||||||
debug.nospace() << "Zigbee Cluster Library Frame(" << frame.clusterId << ", ";
|
debug.nospace() << "Frame(";
|
||||||
debug.nospace() << frame.header;
|
debug.nospace() << frame.header;
|
||||||
debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(frame.payload) << ")";
|
debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(frame.payload) << ")";
|
||||||
return debug.space();
|
return debug.space();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::ReadAttributeStatusRecord &attributeStatusRecord)
|
||||||
|
{
|
||||||
|
debug.nospace().noquote() << "ReadAttributeStatusRecord("
|
||||||
|
<< ZigbeeUtils::convertUint16ToHexString(attributeStatusRecord.attributeId) << ", "
|
||||||
|
<< attributeStatusRecord.attributeStatus << ", "
|
||||||
|
<< attributeStatusRecord.dataType << ", "
|
||||||
|
<< attributeStatusRecord.data
|
||||||
|
<< ")";
|
||||||
|
|
||||||
|
return debug.space();
|
||||||
|
}
|
||||||
@ -65,6 +65,18 @@ public:
|
|||||||
};
|
};
|
||||||
Q_ENUM(Command)
|
Q_ENUM(Command)
|
||||||
|
|
||||||
|
enum GlobalAttribute {
|
||||||
|
GlobalAttributeClusterRevision = 0xfffd,
|
||||||
|
GlobalAttributeAttributeReportingStatus = 0xfffe
|
||||||
|
};
|
||||||
|
Q_ENUM(GlobalAttribute)
|
||||||
|
|
||||||
|
enum AttributeReportingStatus {
|
||||||
|
AttributeReportingStatusPending = 0x00,
|
||||||
|
AttributeReportingStatusComplete = 0x01
|
||||||
|
};
|
||||||
|
Q_ENUM(AttributeReportingStatus)
|
||||||
|
|
||||||
// Frame control field
|
// Frame control field
|
||||||
enum FrameType {
|
enum FrameType {
|
||||||
FrameTypeGlobal = 0x00,
|
FrameTypeGlobal = 0x00,
|
||||||
@ -79,7 +91,7 @@ public:
|
|||||||
Q_ENUM(Direction)
|
Q_ENUM(Direction)
|
||||||
|
|
||||||
typedef struct FrameControl {
|
typedef struct FrameControl {
|
||||||
FrameType frameType = FrameTypeClusterSpecific;
|
FrameType frameType = FrameTypeGlobal;
|
||||||
bool manufacturerSpecific = false;
|
bool manufacturerSpecific = false;
|
||||||
Direction direction = DirectionClientToServer;
|
Direction direction = DirectionClientToServer;
|
||||||
bool disableDefaultResponse = false;
|
bool disableDefaultResponse = false;
|
||||||
@ -93,24 +105,39 @@ public:
|
|||||||
} ZclHeader;
|
} ZclHeader;
|
||||||
|
|
||||||
typedef struct Frame {
|
typedef struct Frame {
|
||||||
Zigbee::ClusterId clusterId;
|
|
||||||
Header header;
|
Header header;
|
||||||
QByteArray payload;
|
QByteArray payload;
|
||||||
} Frame;
|
} Frame;
|
||||||
|
|
||||||
|
|
||||||
|
// Read attribute
|
||||||
|
typedef struct ReadAttributeStatusRecord {
|
||||||
|
quint16 attributeId;
|
||||||
|
Zigbee::ZigbeeStatus attributeStatus;
|
||||||
|
Zigbee::DataType dataType;
|
||||||
|
QByteArray data;
|
||||||
|
} ReadAttributeStatusRecord;
|
||||||
|
|
||||||
|
|
||||||
// General parse/build methods
|
// General parse/build methods
|
||||||
static quint8 buildFrameControlByte(const FrameControl &frameControl);
|
static quint8 buildFrameControlByte(const FrameControl &frameControl);
|
||||||
static FrameControl parseFrameControlByte(quint8 frameControlByte);
|
static FrameControl parseFrameControlByte(quint8 frameControlByte);
|
||||||
|
|
||||||
static QByteArray buildHeader(const Header &header);
|
static QByteArray buildHeader(const Header &header);
|
||||||
|
|
||||||
static Frame parseFrameData(Zigbee::ClusterId clusterId, const QByteArray &frameData);
|
static QList<ReadAttributeStatusRecord> parseAttributeStatusRecords(const QByteArray &payload);
|
||||||
|
|
||||||
|
//static QByteArray readAttributeData(const QDataStream &stream, Zigbee::DataType dataType);
|
||||||
|
|
||||||
|
|
||||||
|
static Frame parseFrameData(const QByteArray &frameData);
|
||||||
static QByteArray buildFrame(const Frame &frame);
|
static QByteArray buildFrame(const Frame &frame);
|
||||||
};
|
};
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::FrameControl &frameControl);
|
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::FrameControl &frameControl);
|
||||||
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Header &header);
|
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Header &header);
|
||||||
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Frame &frame);
|
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Frame &frame);
|
||||||
|
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::ReadAttributeStatusRecord &attributeStatusRecord);
|
||||||
|
|
||||||
|
|
||||||
#endif // ZIGBEECLUSTERLIBRARY_H
|
#endif // ZIGBEECLUSTERLIBRARY_H
|
||||||
@ -1,6 +1,44 @@
|
|||||||
#include "zigbeeclusterreply.h"
|
#include "zigbeeclusterreply.h"
|
||||||
|
|
||||||
ZigbeeClusterReply::ZigbeeClusterReply(QObject *parent) : QObject(parent)
|
ZigbeeClusterReply::Error ZigbeeClusterReply::error() const
|
||||||
|
{
|
||||||
|
return m_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeNetworkRequest ZigbeeClusterReply::request() const
|
||||||
|
{
|
||||||
|
return m_request;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterLibrary::Frame ZigbeeClusterReply::requestFrame() const
|
||||||
|
{
|
||||||
|
return m_requestFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint8 ZigbeeClusterReply::transactionSequenceNumber() const
|
||||||
|
{
|
||||||
|
return m_transactionSequenceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray ZigbeeClusterReply::responseData() const
|
||||||
|
{
|
||||||
|
return m_responseData;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterLibrary::Frame ZigbeeClusterReply::responseFrame() const
|
||||||
|
{
|
||||||
|
return m_responseFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZigbeeClusterReply::isComplete() const
|
||||||
|
{
|
||||||
|
return m_apsConfirmReceived && m_zclIndicationReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterReply::ZigbeeClusterReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame requestFrame, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_request(request),
|
||||||
|
m_requestFrame(requestFrame)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,13 +3,59 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "zigbeenetworkrequest.h"
|
||||||
|
#include "zigbeeclusterlibrary.h"
|
||||||
|
|
||||||
class ZigbeeClusterReply : public QObject
|
class ZigbeeClusterReply : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend class ZigbeeCluster;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ZigbeeClusterReply(QObject *parent = nullptr);
|
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()
|
||||||
|
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;
|
||||||
|
|
||||||
|
ZigbeeNetworkRequest request() const;
|
||||||
|
ZigbeeClusterLibrary::Frame requestFrame() const;
|
||||||
|
|
||||||
|
quint8 transactionSequenceNumber() const;
|
||||||
|
|
||||||
|
QByteArray responseData() const;
|
||||||
|
ZigbeeClusterLibrary::Frame responseFrame() const;
|
||||||
|
|
||||||
|
bool isComplete() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit ZigbeeClusterReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame requestFrame, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
Error m_error = ErrorNoError;
|
||||||
|
|
||||||
|
// Request
|
||||||
|
quint8 m_transactionSequenceNumber = 0;
|
||||||
|
ZigbeeNetworkRequest m_request;
|
||||||
|
ZigbeeClusterLibrary::Frame m_requestFrame;
|
||||||
|
|
||||||
|
// Response
|
||||||
|
bool m_apsConfirmReceived = false;
|
||||||
|
Zigbee::ZigbeeApsStatus m_zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess;
|
||||||
|
|
||||||
|
ZigbeeClusterLibrary::Command m_expectedResponse;
|
||||||
|
|
||||||
|
bool m_zclIndicationReceived = false;
|
||||||
|
QByteArray m_responseData;
|
||||||
|
ZigbeeClusterLibrary::Frame m_responseFrame;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void finished();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,7 @@ class ZigbeeDeviceObjectReply : public QObject
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
enum Error {
|
enum Error {
|
||||||
ErrorNoError, // All OK, no error occured
|
ErrorNoError, // All OK, no error occured, the message was transported successfully
|
||||||
ErrorTimeout, // The request timeouted
|
ErrorTimeout, // The request timeouted
|
||||||
ErrorZigbeeApsStatusError, // An APS transport error occured. See zigbeeApsStatus()
|
ErrorZigbeeApsStatusError, // An APS transport error occured. See zigbeeApsStatus()
|
||||||
ErrorInterfaceError, // A transport interface error occured. Could not communicate with the hardware.
|
ErrorInterfaceError, // A transport interface error occured. Could not communicate with the hardware.
|
||||||
@ -81,7 +81,6 @@ private:
|
|||||||
QByteArray m_responseData;
|
QByteArray m_responseData;
|
||||||
ZigbeeDeviceProfile::Adpu m_responseAdpu;
|
ZigbeeDeviceProfile::Adpu m_responseAdpu;
|
||||||
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void finished();
|
void finished();
|
||||||
|
|
||||||
|
|||||||
@ -1,234 +0,0 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
||||||
*
|
|
||||||
* 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 ZIGBEECLUSTER_H
|
|
||||||
#define ZIGBEECLUSTER_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
#include "zigbee.h"
|
|
||||||
#include "zigbeeclusterlibrary.h"
|
|
||||||
#include "zigbeeclusterattribute.h"
|
|
||||||
|
|
||||||
struct ZigbeeClusterReportConfigurationRecord {
|
|
||||||
quint8 direction;
|
|
||||||
Zigbee::DataType dataType;
|
|
||||||
quint16 attributeId;
|
|
||||||
quint16 minInterval;
|
|
||||||
quint16 maxInterval;
|
|
||||||
quint16 timeout;
|
|
||||||
quint8 change;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct ZigbeeClusterAttributeReport {
|
|
||||||
quint16 sourceAddress;
|
|
||||||
quint8 endpointId;
|
|
||||||
Zigbee::ClusterId clusterId;
|
|
||||||
quint16 attributeId;
|
|
||||||
Zigbee::ZigbeeStatus attributeStatus;
|
|
||||||
Zigbee::DataType dataType;
|
|
||||||
QByteArray data;
|
|
||||||
} ZigbeeClusterAttributeReport;
|
|
||||||
|
|
||||||
|
|
||||||
class ZigbeeNode;
|
|
||||||
class ZigbeeNetwork;
|
|
||||||
class ZigbeeNodeEndpoint;
|
|
||||||
class ZigbeeNetworkReply;
|
|
||||||
|
|
||||||
class ZigbeeCluster : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
friend class ZigbeeNode;
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum Direction {
|
|
||||||
Input,
|
|
||||||
Output
|
|
||||||
};
|
|
||||||
Q_ENUM(Direction)
|
|
||||||
|
|
||||||
// Basic clustr 0x0000
|
|
||||||
|
|
||||||
// Attributes from the basic cluster 0x0000
|
|
||||||
enum BasicAttribute {
|
|
||||||
BasicAttributeZclVersion = 0x0000, // Mandatory
|
|
||||||
BasicAttributeAppVersion = 0x0001,
|
|
||||||
BasicAttributeStackVersion = 0x0002,
|
|
||||||
BasicAttributeHardwareVersion = 0x0003,
|
|
||||||
BasicAttributeManufacturerName = 0x0004,
|
|
||||||
BasicAttributeModelIdentifier = 0x0005,
|
|
||||||
BasicAttributeDateCode = 0x0006, // ISO 8601 YYYYMMDD
|
|
||||||
BasicAttributePowerSource = 0x0007, // Mandatory
|
|
||||||
BasicAttributeLocationDescription = 0x0010,
|
|
||||||
BasicAttributePhysicalEnvironment = 0x0011,
|
|
||||||
BasicAttributeDeviceEnabled = 0x0012, // 0: disabled, 1: enabled
|
|
||||||
BasicAttributeAlarmMask = 0x0013,
|
|
||||||
BasicAttributeDisableLocalConfig = 0x0014,
|
|
||||||
BasicAttributeSwBuildId = 0x4000
|
|
||||||
};
|
|
||||||
Q_ENUM(BasicAttribute)
|
|
||||||
|
|
||||||
// From the Basic cluster attribute 0x0007 power source
|
|
||||||
enum BasicAttributePowerSourceValue {
|
|
||||||
BasicAttributePowerSourceValueUnknown = 0x00,
|
|
||||||
BasicAttributePowerSourceValueMainsSinglePhase = 0x01,
|
|
||||||
BasicAttributePowerSourceValueMainsThreePhase = 0x02,
|
|
||||||
BasicAttributePowerSourceValueBattery = 0x03,
|
|
||||||
BasicAttributePowerSourceValueDcSource = 0x04,
|
|
||||||
BasicAttributePowerSourceValueEmergencyMainsConstantlyPowered = 0x05,
|
|
||||||
BasicAttributePowerSourceValueEmergencyMainsTransferSwitch = 0x06
|
|
||||||
};
|
|
||||||
Q_ENUM(BasicAttributePowerSourceValue)
|
|
||||||
|
|
||||||
// Power configuration cluster 0x0001
|
|
||||||
|
|
||||||
enum PowerConfigurationAttribute {
|
|
||||||
PowerConfigurationAttributeMainsInformation = 0x0000,
|
|
||||||
PowerConfigurationAttributeMainsSettings = 0x0001,
|
|
||||||
PowerConfigurationAttributeBatteryInformation = 0x0002,
|
|
||||||
PowerConfigurationAttributeBatterySettings = 0x0003,
|
|
||||||
PowerConfigurationAttributeBatterySource2Information = 0x0004,
|
|
||||||
PowerConfigurationAttributeBattterySource2Settings = 0x0005,
|
|
||||||
PowerConfigurationAttributeBatterySource3Information = 0x0006,
|
|
||||||
PowerConfigurationAttributeBattterySource3Settings = 0x0007
|
|
||||||
};
|
|
||||||
Q_ENUM(PowerConfigurationAttribute)
|
|
||||||
|
|
||||||
// On Off Cluster 0x0006
|
|
||||||
|
|
||||||
enum OnOffClusterAttribute {
|
|
||||||
OnOffClusterAttributeOnOff = 0x0000,
|
|
||||||
OnOffClusterAttributeGlobalSceneControl = 0x4000,
|
|
||||||
OnOffClusterAttributeOnTime = 0x4001,
|
|
||||||
OnOffClusterAttributeOffWaitTime = 0x4002
|
|
||||||
};
|
|
||||||
Q_ENUM(OnOffClusterAttribute)
|
|
||||||
|
|
||||||
enum OnOffClusterCommand {
|
|
||||||
OnOffClusterCommandOff = 0x00,
|
|
||||||
OnOffClusterCommandOn = 0x01,
|
|
||||||
OnOffClusterCommandToggle = 0x02
|
|
||||||
};
|
|
||||||
Q_ENUM(OnOffClusterCommand)
|
|
||||||
|
|
||||||
|
|
||||||
// Level cluster 0x0008
|
|
||||||
|
|
||||||
enum LevelClusterAttribute {
|
|
||||||
LevelClusterAttributeCurrentLevel = 0x0000,
|
|
||||||
LevelClusterAttributeRemainingTime = 0x0001,
|
|
||||||
LevelClusterAttributeOnOffTransitionTime = 0x0010,
|
|
||||||
LevelClusterAttributeOnLevel = 0x0011,
|
|
||||||
LevelClusterAttributeOnTransitionTime = 0x0012,
|
|
||||||
LevelClusterAttributeOffTransitionTime = 0x0013,
|
|
||||||
LevelClusterAttributeDefaultMoveRate = 0x0014
|
|
||||||
};
|
|
||||||
Q_ENUM(LevelClusterAttribute)
|
|
||||||
|
|
||||||
enum LevelClusterCommand {
|
|
||||||
LevelClusterCommandMoveToLevel = 0x00,
|
|
||||||
LevelClusterCommandMove = 0x01,
|
|
||||||
LevelClusterCommandStep = 0x02,
|
|
||||||
LevelClusterCommandStop = 0x03,
|
|
||||||
LevelClusterCommandMoveToLevelWithOnOff = 0x04,
|
|
||||||
LevelClusterCommandMoveWithOnOff = 0x05,
|
|
||||||
LevelClusterCommandStepWithOnOff = 0x06,
|
|
||||||
LevelClusterCommandStopWithOnOff = 0x07,
|
|
||||||
};
|
|
||||||
Q_ENUM(LevelClusterCommand)
|
|
||||||
|
|
||||||
// Color cluster 0x0300
|
|
||||||
|
|
||||||
enum ColorControlClusterAttribute {
|
|
||||||
ColorControlClusterAttributeCurrentHue = 0x0000,
|
|
||||||
ColorControlClusterAttributeCurrentSaturation = 0x0001,
|
|
||||||
ColorControlClusterAttributeRemainingTime = 0x0002,
|
|
||||||
ColorControlClusterAttributeCurrentX = 0x0003,
|
|
||||||
ColorControlClusterAttributeCurrentY = 0x0004,
|
|
||||||
ColorControlClusterAttributeDriftCompensation = 0x0005,
|
|
||||||
ColorControlClusterAttributeCompensationText = 0x0006,
|
|
||||||
ColorControlClusterAttributeColorTemperatureMireds = 0x0007,
|
|
||||||
ColorControlClusterAttributeColorMode = 0x0008,
|
|
||||||
ColorControlClusterAttributeEnhancedCurrentHue = 0x4000,
|
|
||||||
ColorControlClusterAttributeEnhancedColorMode = 0x4001,
|
|
||||||
ColorControlClusterAttributeColorLoopActive = 0x4002,
|
|
||||||
ColorControlClusterAttributeColorLoopDirection = 0x4003,
|
|
||||||
ColorControlClusterAttributeColorLoopTime = 0x4004,
|
|
||||||
ColorControlClusterAttributeColorLoopStartEnhancedHue = 0x4005,
|
|
||||||
ColorControlClusterAttributeColorLoopStoredEnhancedHue = 0x4006,
|
|
||||||
ColorControlClusterAttributeColorCapabilities = 0x400a,
|
|
||||||
ColorControlClusterAttributeColorTempPhysicalMinMireds = 0x400b,
|
|
||||||
ColorControlClusterAttributeColorTempPhysicalMaxMireds = 0x400c
|
|
||||||
};
|
|
||||||
Q_ENUM(ColorControlClusterAttribute)
|
|
||||||
|
|
||||||
enum ColorControlClusterColorMode {
|
|
||||||
ColorControlClusterColorModeHueSaturation = 0x00,
|
|
||||||
ColorControlClusterColorModeXY = 0x01,
|
|
||||||
ColorControlClusterColorModeColorTemperatureMired = 0x02
|
|
||||||
};
|
|
||||||
Q_ENUM(ColorControlClusterColorMode)
|
|
||||||
|
|
||||||
|
|
||||||
explicit ZigbeeCluster(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Zigbee::ClusterId clusterId, Direction direction, QObject *parent = nullptr);
|
|
||||||
|
|
||||||
Direction direction() const;
|
|
||||||
|
|
||||||
Zigbee::ClusterId clusterId() const;
|
|
||||||
QString clusterName() const;
|
|
||||||
|
|
||||||
QList<ZigbeeClusterAttribute> attributes() const;
|
|
||||||
bool hasAttribute(quint16 attributeId) const;
|
|
||||||
|
|
||||||
ZigbeeClusterAttribute attribute(quint16 id);
|
|
||||||
|
|
||||||
// FIXME: this should not be public
|
|
||||||
void setAttribute(const ZigbeeClusterAttribute &attribute);
|
|
||||||
|
|
||||||
// ZCL global commands
|
|
||||||
ZigbeeNetworkReply *readAttributes(QList<quint16> attributes);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ZigbeeNetwork *m_network = nullptr;
|
|
||||||
ZigbeeNode *m_node = nullptr;
|
|
||||||
ZigbeeNodeEndpoint *m_endpoint= nullptr;
|
|
||||||
|
|
||||||
Zigbee::ClusterId m_clusterId = Zigbee::ClusterIdUnknown;
|
|
||||||
Direction m_direction = Input;
|
|
||||||
QHash<quint16, ZigbeeClusterAttribute> m_attributes;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void attributeChanged(const ZigbeeClusterAttribute &attribute);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster);
|
|
||||||
QDebug operator<<(QDebug debug, const ZigbeeClusterAttributeReport &attributeReport);
|
|
||||||
|
|
||||||
#endif // ZIGBEECLUSTER_H
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
#include "zigbeeclusterlibraryreply.h"
|
|
||||||
|
|
||||||
ZigbeeNetworkRequest ZigbeeClusterLibraryReply::request() const
|
|
||||||
{
|
|
||||||
return m_request;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZigbeeClusterLibrary::Frame ZigbeeClusterLibraryReply::requestFrame() const
|
|
||||||
{
|
|
||||||
return m_requestFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint8 ZigbeeClusterLibraryReply::transactionSequenceNumber() const
|
|
||||||
{
|
|
||||||
return m_requestFrame.header.transactionSequenceNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZigbeeClusterLibraryReply::ZigbeeClusterLibraryReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame requestFrame, QObject *parent) :
|
|
||||||
QObject(parent),
|
|
||||||
m_request(request),
|
|
||||||
m_requestFrame(requestFrame)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
#ifndef ZIGBEECLUSTERLIBRARYREPLY_H
|
|
||||||
#define ZIGBEECLUSTERLIBRARYREPLY_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
#include "zigbeenetworkrequest.h"
|
|
||||||
#include "zigbeeclusterlibrary.h"
|
|
||||||
|
|
||||||
class ZigbeeClusterLibraryReply : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
friend class ZigbeeCluster;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ZigbeeNetworkRequest request() const;
|
|
||||||
ZigbeeClusterLibrary::Frame requestFrame() const;
|
|
||||||
|
|
||||||
quint8 transactionSequenceNumber() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
explicit ZigbeeClusterLibraryReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame requestFrame, QObject *parent = nullptr);
|
|
||||||
|
|
||||||
ZigbeeNetworkRequest m_request;
|
|
||||||
ZigbeeClusterLibrary::Frame m_requestFrame;
|
|
||||||
ZigbeeClusterLibrary::Command m_expectedResponse;
|
|
||||||
|
|
||||||
ZigbeeClusterLibrary::Frame m_responseFrame;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void finished();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ZIGBEECLUSTERLIBRARYREPLY_H
|
|
||||||
480
libnymea-zigbee/zigbeedatatype.cpp
Normal file
480
libnymea-zigbee/zigbeedatatype.cpp
Normal file
@ -0,0 +1,480 @@
|
|||||||
|
#include "zigbeedatatype.h"
|
||||||
|
|
||||||
|
ZigbeeDataType::ZigbeeDataType(Zigbee::DataType dataType, const QByteArray &data):
|
||||||
|
m_dataType(dataType),
|
||||||
|
m_data(data)
|
||||||
|
{
|
||||||
|
switch (dataType) {
|
||||||
|
case Zigbee::NoData:
|
||||||
|
m_name = "No data";
|
||||||
|
m_className = "Null";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
m_data.clear();
|
||||||
|
break;
|
||||||
|
case Zigbee::Data8:
|
||||||
|
m_name = "8-bit data";
|
||||||
|
m_className = "General data discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::Data16:
|
||||||
|
m_name = "16-bit data";
|
||||||
|
m_className = "General data discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::Data24:
|
||||||
|
m_name = "24-bit data";
|
||||||
|
m_className = "General data discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::Data32:
|
||||||
|
m_name = "32-bit data";
|
||||||
|
m_className = "General data discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::Data40:
|
||||||
|
m_name = "40-bit data";
|
||||||
|
m_className = "General data discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::Data48:
|
||||||
|
m_name = "48-bit data";
|
||||||
|
m_className = "General data discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::Data56:
|
||||||
|
m_name = "56-bit data";
|
||||||
|
m_className = "General data discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::Data64:
|
||||||
|
m_name = "64-bit data";
|
||||||
|
m_className = "General data discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::Bool:
|
||||||
|
m_name = "Bool";
|
||||||
|
m_className = "Logical discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap8:
|
||||||
|
m_name = "8-bit bitmap";
|
||||||
|
m_className = "Bitmap discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap16:
|
||||||
|
m_name = "16-bit bitmap";
|
||||||
|
m_className = "Bitmap discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap24:
|
||||||
|
m_name = "24-bit bitmap";
|
||||||
|
m_className = "Bitmap discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap32:
|
||||||
|
m_name = "32-bit bitmap";
|
||||||
|
m_className = "Bitmap discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap40:
|
||||||
|
m_name = "40-bit bitmap";
|
||||||
|
m_className = "Bitmap discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap48:
|
||||||
|
m_name = "48-bit bitmap";
|
||||||
|
m_className = "Bitmap discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap56:
|
||||||
|
m_name = "56-bit bitmap";
|
||||||
|
m_className = "Bitmap discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap64:
|
||||||
|
m_name = "64-bit bitmap";
|
||||||
|
m_className = "Bitmap discrete";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint8:
|
||||||
|
m_name = "Unsigned 8-bit integer";
|
||||||
|
m_className = "Unsigned integer analog";
|
||||||
|
m_typeLength = typeLength(m_dataType);
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint16:
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint24:
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint32:
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint40:
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint48:
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint56:
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint64:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int8:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int16:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int24:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int32:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int40:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int48:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int56:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int64:
|
||||||
|
break;
|
||||||
|
case Zigbee::Enum8:
|
||||||
|
break;
|
||||||
|
case Zigbee::Enum16:
|
||||||
|
break;
|
||||||
|
case Zigbee::FloatSemi:
|
||||||
|
break;
|
||||||
|
case Zigbee::FloatSingle:
|
||||||
|
break;
|
||||||
|
case Zigbee::FloatDouble:
|
||||||
|
break;
|
||||||
|
case Zigbee::OctetString:
|
||||||
|
break;
|
||||||
|
case Zigbee::CharString:
|
||||||
|
break;
|
||||||
|
case Zigbee::LongOctetString:
|
||||||
|
break;
|
||||||
|
case Zigbee::LongCharString:
|
||||||
|
break;
|
||||||
|
case Zigbee::Array:
|
||||||
|
break;
|
||||||
|
case Zigbee::Structure:
|
||||||
|
break;
|
||||||
|
case Zigbee::Set:
|
||||||
|
break;
|
||||||
|
case Zigbee::Bag:
|
||||||
|
break;
|
||||||
|
case Zigbee::TimeOfDay:
|
||||||
|
break;
|
||||||
|
case Zigbee::Date:
|
||||||
|
break;
|
||||||
|
case Zigbee::UtcTime:
|
||||||
|
break;
|
||||||
|
case Zigbee::Cluster:
|
||||||
|
break;
|
||||||
|
case Zigbee::Attribute:
|
||||||
|
break;
|
||||||
|
case Zigbee::BacnetId:
|
||||||
|
break;
|
||||||
|
case Zigbee::IeeeAddress:
|
||||||
|
break;
|
||||||
|
case Zigbee::BitKey128:
|
||||||
|
break;
|
||||||
|
case Zigbee::Unknown:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
switch (dataType) {
|
||||||
|
case Zigbee::NoData:
|
||||||
|
break;
|
||||||
|
case Zigbee::Data8:
|
||||||
|
break;
|
||||||
|
case Zigbee::Data16:
|
||||||
|
break;
|
||||||
|
case Zigbee::Data24:
|
||||||
|
break;
|
||||||
|
case Zigbee::Data32:
|
||||||
|
break;
|
||||||
|
case Zigbee::Data40:
|
||||||
|
break;
|
||||||
|
case Zigbee::Data48:
|
||||||
|
break;
|
||||||
|
case Zigbee::Data56:
|
||||||
|
break;
|
||||||
|
case Zigbee::Data64:
|
||||||
|
break;
|
||||||
|
case Zigbee::Bool:
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap8:
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap16:
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap24:
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap32:
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap40:
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap48:
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap56:
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap64:
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint8:
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint16:
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint24:
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint32:
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint40:
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint48:
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint56:
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint64:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int8:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int16:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int24:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int32:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int40:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int48:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int56:
|
||||||
|
break;
|
||||||
|
case Zigbee::Int64:
|
||||||
|
break;
|
||||||
|
case Zigbee::Enum8:
|
||||||
|
break;
|
||||||
|
case Zigbee::Enum16:
|
||||||
|
break;
|
||||||
|
case Zigbee::FloatSemi:
|
||||||
|
break;
|
||||||
|
case Zigbee::FloatSingle:
|
||||||
|
break;
|
||||||
|
case Zigbee::FloatDouble:
|
||||||
|
break;
|
||||||
|
case Zigbee::OctetString:
|
||||||
|
break;
|
||||||
|
case Zigbee::CharString:
|
||||||
|
break;
|
||||||
|
case Zigbee::LongOctetString:
|
||||||
|
break;
|
||||||
|
case Zigbee::LongCharString:
|
||||||
|
break;
|
||||||
|
case Zigbee::Array:
|
||||||
|
break;
|
||||||
|
case Zigbee::Structure:
|
||||||
|
break;
|
||||||
|
case Zigbee::Set:
|
||||||
|
break;
|
||||||
|
case Zigbee::Bag:
|
||||||
|
break;
|
||||||
|
case Zigbee::TimeOfDay:
|
||||||
|
break;
|
||||||
|
case Zigbee::Date:
|
||||||
|
break;
|
||||||
|
case Zigbee::UtcTime:
|
||||||
|
break;
|
||||||
|
case Zigbee::Cluster:
|
||||||
|
break;
|
||||||
|
case Zigbee::Attribute:
|
||||||
|
break;
|
||||||
|
case Zigbee::BacnetId:
|
||||||
|
break;
|
||||||
|
case Zigbee::IeeeAddress:
|
||||||
|
break;
|
||||||
|
case Zigbee::BitKey128:
|
||||||
|
break;
|
||||||
|
case Zigbee::Unknown:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZigbeeDataType::typeLength(Zigbee::DataType dataType)
|
||||||
|
{
|
||||||
|
int length = 0;
|
||||||
|
switch (dataType) {
|
||||||
|
case Zigbee::NoData:
|
||||||
|
break;
|
||||||
|
case Zigbee::Data8:
|
||||||
|
length = 1;
|
||||||
|
break;
|
||||||
|
case Zigbee::Data16:
|
||||||
|
length = 2;
|
||||||
|
break;
|
||||||
|
case Zigbee::Data24:
|
||||||
|
length = 3;
|
||||||
|
break;
|
||||||
|
case Zigbee::Data32:
|
||||||
|
length = 4;
|
||||||
|
break;
|
||||||
|
case Zigbee::Data40:
|
||||||
|
length = 5;
|
||||||
|
break;
|
||||||
|
case Zigbee::Data48:
|
||||||
|
length = 6;
|
||||||
|
break;
|
||||||
|
case Zigbee::Data56:
|
||||||
|
length = 7;
|
||||||
|
break;
|
||||||
|
case Zigbee::Data64:
|
||||||
|
length = 8;
|
||||||
|
break;
|
||||||
|
case Zigbee::Bool:
|
||||||
|
length = 1;
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap8:
|
||||||
|
length = 1;
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap16:
|
||||||
|
length = 2;
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap24:
|
||||||
|
length = 3;
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap32:
|
||||||
|
length = 4;
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap40:
|
||||||
|
length = 5;
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap48:
|
||||||
|
length = 6;
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap56:
|
||||||
|
length = 7;
|
||||||
|
break;
|
||||||
|
case Zigbee::BitMap64:
|
||||||
|
length = 8;
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint8:
|
||||||
|
length = 1;
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint16:
|
||||||
|
length = 2;
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint24:
|
||||||
|
length = 3;
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint32:
|
||||||
|
length = 4;
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint40:
|
||||||
|
length = 5;
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint48:
|
||||||
|
length = 6;
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint56:
|
||||||
|
length = 7;
|
||||||
|
break;
|
||||||
|
case Zigbee::Uint64:
|
||||||
|
length = 8;
|
||||||
|
break;
|
||||||
|
case Zigbee::Int8:
|
||||||
|
length = 1;
|
||||||
|
break;
|
||||||
|
case Zigbee::Int16:
|
||||||
|
length = 2;
|
||||||
|
break;
|
||||||
|
case Zigbee::Int24:
|
||||||
|
length = 3;
|
||||||
|
break;
|
||||||
|
case Zigbee::Int32:
|
||||||
|
length = 4;
|
||||||
|
break;
|
||||||
|
case Zigbee::Int40:
|
||||||
|
length = 5;
|
||||||
|
break;
|
||||||
|
case Zigbee::Int48:
|
||||||
|
length = 6;
|
||||||
|
break;
|
||||||
|
case Zigbee::Int56:
|
||||||
|
length = 7;
|
||||||
|
break;
|
||||||
|
case Zigbee::Int64:
|
||||||
|
length = 8;
|
||||||
|
break;
|
||||||
|
case Zigbee::Enum8:
|
||||||
|
length = 1;
|
||||||
|
break;
|
||||||
|
case Zigbee::Enum16:
|
||||||
|
length = 2;
|
||||||
|
break;
|
||||||
|
case Zigbee::FloatSemi:
|
||||||
|
length = 2;
|
||||||
|
break;
|
||||||
|
case Zigbee::FloatSingle:
|
||||||
|
length = 4;
|
||||||
|
break;
|
||||||
|
case Zigbee::FloatDouble:
|
||||||
|
length = 8;
|
||||||
|
break;
|
||||||
|
case Zigbee::OctetString:
|
||||||
|
// first byte is length
|
||||||
|
length = -1;
|
||||||
|
break;
|
||||||
|
case Zigbee::CharString:
|
||||||
|
// first byte is length
|
||||||
|
length = -1;
|
||||||
|
break;
|
||||||
|
case Zigbee::LongOctetString:
|
||||||
|
// first 2 byte is length
|
||||||
|
length = -1;
|
||||||
|
break;
|
||||||
|
case Zigbee::LongCharString:
|
||||||
|
// first 2 byte is length
|
||||||
|
length = -1;
|
||||||
|
break;
|
||||||
|
case Zigbee::Array:
|
||||||
|
// 2 + sum of lengths of content
|
||||||
|
length = -1;
|
||||||
|
break;
|
||||||
|
case Zigbee::Structure:
|
||||||
|
// 2 + sum of lengths of content
|
||||||
|
length = -1;
|
||||||
|
break;
|
||||||
|
case Zigbee::Set:
|
||||||
|
// 2 + sum of lengths of content
|
||||||
|
length = -1;
|
||||||
|
break;
|
||||||
|
case Zigbee::Bag:
|
||||||
|
// 2 + sum of lengths of content
|
||||||
|
length = -1;
|
||||||
|
break;
|
||||||
|
case Zigbee::TimeOfDay:
|
||||||
|
length = 4;
|
||||||
|
break;
|
||||||
|
case Zigbee::Date:
|
||||||
|
length = 4;
|
||||||
|
break;
|
||||||
|
case Zigbee::UtcTime:
|
||||||
|
length = 4;
|
||||||
|
break;
|
||||||
|
case Zigbee::Cluster:
|
||||||
|
length = 2;
|
||||||
|
break;
|
||||||
|
case Zigbee::Attribute:
|
||||||
|
length = 2;
|
||||||
|
break;
|
||||||
|
case Zigbee::BacnetId:
|
||||||
|
length = 4;
|
||||||
|
break;
|
||||||
|
case Zigbee::IeeeAddress:
|
||||||
|
length = 8;
|
||||||
|
break;
|
||||||
|
case Zigbee::BitKey128:
|
||||||
|
length = 16;
|
||||||
|
break;
|
||||||
|
case Zigbee::Unknown:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
26
libnymea-zigbee/zigbeedatatype.h
Normal file
26
libnymea-zigbee/zigbeedatatype.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef ZIGBEEDATATYPE_H
|
||||||
|
#define ZIGBEEDATATYPE_H
|
||||||
|
|
||||||
|
#include "zigbee.h"
|
||||||
|
|
||||||
|
class ZigbeeDataType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ZigbeeDataType(Zigbee::DataType dataType, const QByteArray &data = QByteArray());
|
||||||
|
|
||||||
|
Zigbee::DataType dataType() const;
|
||||||
|
QString name() const;
|
||||||
|
QString className() const;
|
||||||
|
QByteArray data() const;
|
||||||
|
|
||||||
|
static int typeLength(Zigbee::DataType dataType);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Zigbee::DataType m_dataType = Zigbee::NoData;
|
||||||
|
QByteArray m_data;
|
||||||
|
QString m_name = "Unknown";
|
||||||
|
QString m_className = "Null";
|
||||||
|
int m_typeLength = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ZIGBEEDATATYPE_H
|
||||||
@ -351,7 +351,7 @@ void ZigbeeNetwork::loadNetwork()
|
|||||||
for (int n = 0; n < inputClustersCount; n ++) {
|
for (int n = 0; n < inputClustersCount; n ++) {
|
||||||
settings.setArrayIndex(n);
|
settings.setArrayIndex(n);
|
||||||
Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(settings.value("clusterId", 0).toUInt());
|
Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(settings.value("clusterId", 0).toUInt());
|
||||||
ZigbeeCluster *cluster = new ZigbeeCluster(this, node, endpoint, clusterId, ZigbeeCluster::Input, endpoint);
|
ZigbeeCluster *cluster = endpoint->createCluster(clusterId, ZigbeeCluster::Input);
|
||||||
//qCDebug(dcZigbeeNetwork()) << "Created" << cluster;
|
//qCDebug(dcZigbeeNetwork()) << "Created" << cluster;
|
||||||
endpoint->m_inputClusters.insert(clusterId, cluster);
|
endpoint->m_inputClusters.insert(clusterId, cluster);
|
||||||
}
|
}
|
||||||
@ -361,7 +361,7 @@ void ZigbeeNetwork::loadNetwork()
|
|||||||
for (int n = 0; n < outputClustersCount; n ++) {
|
for (int n = 0; n < outputClustersCount; n ++) {
|
||||||
settings.setArrayIndex(n);
|
settings.setArrayIndex(n);
|
||||||
Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(settings.value("clusterId", 0).toUInt());
|
Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(settings.value("clusterId", 0).toUInt());
|
||||||
ZigbeeCluster *cluster = new ZigbeeCluster(this, node, endpoint, clusterId, ZigbeeCluster::Output, endpoint);
|
ZigbeeCluster *cluster = endpoint->createCluster(clusterId, ZigbeeCluster::Output);
|
||||||
//qCDebug(dcZigbeeNetwork()) << "Created" << cluster;
|
//qCDebug(dcZigbeeNetwork()) << "Created" << cluster;
|
||||||
endpoint->m_outputClusters.insert(clusterId, cluster);
|
endpoint->m_outputClusters.insert(clusterId, cluster);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
#include "zigbeenetworkmanager.h"
|
#include "zigbeenetworkmanager.h"
|
||||||
#include "loggingcategory.h"
|
#include "loggingcategory.h"
|
||||||
|
|
||||||
#include "deconz/zigbeenetworkdeconz.h"
|
#include "backends/deconz/zigbeenetworkdeconz.h"
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
|
|||||||
@ -257,91 +257,6 @@ void ZigbeeNode::setExtendedAddress(const ZigbeeAddress &extendedAddress)
|
|||||||
m_extendedAddress = extendedAddress;
|
m_extendedAddress = extendedAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
//void ZigbeeNode::setNodeDescriptorRawData(const QByteArray nodeDescriptorRawData)
|
|
||||||
//{
|
|
||||||
// m_nodeDescriptorRawData = nodeDescriptorRawData;
|
|
||||||
|
|
||||||
// // Parse the raw data
|
|
||||||
// quint8 sequenceNumber = 0;
|
|
||||||
// quint8 status = 0;
|
|
||||||
// quint16 shortAddress = 0;
|
|
||||||
// quint16 manufacturerCode = 0;
|
|
||||||
// quint16 maximalRxSize = 0;
|
|
||||||
// quint16 maximalTxSize = 0;
|
|
||||||
// quint16 serverMask = 0;
|
|
||||||
// quint8 descriptorFlag = 0;
|
|
||||||
// quint8 macFlags = 0;
|
|
||||||
// quint8 maxBufferSize = 0;
|
|
||||||
// quint16 bitField = 0;
|
|
||||||
|
|
||||||
// QDataStream stream(&m_nodeDescriptorRawData, QIODevice::ReadOnly);
|
|
||||||
// stream >> sequenceNumber;
|
|
||||||
// stream >> status;
|
|
||||||
// stream >> shortAddress;
|
|
||||||
// stream >> manufacturerCode;
|
|
||||||
// stream >> maximalRxSize;
|
|
||||||
// stream >> maximalTxSize;
|
|
||||||
// stream >> serverMask;
|
|
||||||
// stream >> descriptorFlag;
|
|
||||||
// stream >> macFlags;
|
|
||||||
// stream >> maxBufferSize;
|
|
||||||
// stream >> bitField;
|
|
||||||
|
|
||||||
// // Set node data
|
|
||||||
// m_manufacturerCode = manufacturerCode;
|
|
||||||
// m_maximumRxSize = maximalRxSize;
|
|
||||||
// m_maximumTxSize = maximalTxSize;
|
|
||||||
// m_maximumBufferSize = maxBufferSize;
|
|
||||||
|
|
||||||
// setServerMask(serverMask);
|
|
||||||
// setMacCapabilitiesFlag(macFlags);
|
|
||||||
// setDescriptorFlag(descriptorFlag);
|
|
||||||
|
|
||||||
// // Parse bit field
|
|
||||||
// // 0-2 Bit = logical type, 0 = coordinator, 1 = router, 2 = end device
|
|
||||||
// if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
|
||||||
// m_nodeType = NodeTypeCoordinator;
|
|
||||||
// } else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
|
||||||
// m_nodeType = NodeTypeRouter;
|
|
||||||
// } else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
|
||||||
// m_nodeType = NodeTypeEndDevice;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// m_complexDescriptorAvailable = (bitField >> 3) & 0x0001;
|
|
||||||
// m_userDescriptorAvailable = (bitField >> 4) & 0x0001;
|
|
||||||
|
|
||||||
// qCDebug(dcZigbeeNode()) << "Node descriptor:";
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Node type:" << nodeType();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode);
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(maximumRxSize());
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(maximumTxSize());
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(maximumBufferSize());
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask);
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Primary Trust center:" << isPrimaryTrustCenter();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Backup Trust center:" << isBackupTrustCenter();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Primary Binding cache:" << isPrimaryBindingCache();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Backup Binding cache:" << isBackupBindingCache();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Primary Discovery cache:" << isPrimaryDiscoveryCache();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Backup Discovery cache:" << isBackupDiscoveryCache();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Network Manager:" << isNetworkManager();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorFlag);
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Extended active endpoint list available:" << extendedActiveEndpointListAvailable();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Extended simple descriptor list available:" << extendedSimpleDescriptorListAvailable();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macFlags);
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Alternate PAN coordinator:" << alternatePanCoordinator();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Device type:" << deviceType();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Power source flag main power:" << powerSourceFlagMainPower();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Receiver on when idle:" << receiverOnWhenIdle();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Security capability:" << securityCapability();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Allocate address:" << allocateAddress();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Bit field:" << ZigbeeUtils::convertUint16ToHexString(bitField);
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Complex desciptor available:" << complexDescriptorAvailable();
|
|
||||||
// qCDebug(dcZigbeeNode()) << " User desciptor available:" << userDescriptorAvailable();
|
|
||||||
//}
|
|
||||||
|
|
||||||
quint16 ZigbeeNode::serverMask() const
|
quint16 ZigbeeNode::serverMask() const
|
||||||
{
|
{
|
||||||
return m_serverMask;
|
return m_serverMask;
|
||||||
@ -704,11 +619,11 @@ void ZigbeeNode::initEndpoint(quint8 endpointId)
|
|||||||
quint16 clusterId = 0;
|
quint16 clusterId = 0;
|
||||||
stream >> clusterId;
|
stream >> clusterId;
|
||||||
if (!endpoint->hasInputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
if (!endpoint->hasInputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
||||||
endpoint->addInputCluster(new ZigbeeCluster(m_network, this, endpoint, static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Input, endpoint));
|
endpoint->addInputCluster(endpoint->createCluster(static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Input));
|
||||||
}
|
}
|
||||||
qCDebug(dcZigbeeNode()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
qCDebug(dcZigbeeNode()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stream >> outputClusterCount;
|
stream >> outputClusterCount;
|
||||||
|
|
||||||
qCDebug(dcZigbeeNode()) << " Output clusters: (" << outputClusterCount << ")";
|
qCDebug(dcZigbeeNode()) << " Output clusters: (" << outputClusterCount << ")";
|
||||||
@ -716,7 +631,7 @@ void ZigbeeNode::initEndpoint(quint8 endpointId)
|
|||||||
quint16 clusterId = 0;
|
quint16 clusterId = 0;
|
||||||
stream >> clusterId;
|
stream >> clusterId;
|
||||||
if (!endpoint->hasOutputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
if (!endpoint->hasOutputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
||||||
endpoint->addOutputCluster(new ZigbeeCluster(m_network, this, endpoint, static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Output, endpoint));
|
endpoint->addOutputCluster(endpoint->createCluster(static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Output));
|
||||||
}
|
}
|
||||||
qCDebug(dcZigbeeNode()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
qCDebug(dcZigbeeNode()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||||
}
|
}
|
||||||
@ -725,19 +640,81 @@ void ZigbeeNode::initEndpoint(quint8 endpointId)
|
|||||||
|
|
||||||
if (m_uninitializedEndpoints.isEmpty()) {
|
if (m_uninitializedEndpoints.isEmpty()) {
|
||||||
|
|
||||||
//if (m_shortAddress == 0) {
|
if (m_shortAddress == 0) {
|
||||||
setState(StateInitialized);
|
setState(StateInitialized);
|
||||||
return;
|
return;
|
||||||
//}
|
}
|
||||||
|
|
||||||
// Continue with the basic cluster attributes
|
// Continue with the basic cluster attributes
|
||||||
//initBasicCluster();
|
initBasicCluster();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNode::initBasicCluster()
|
void ZigbeeNode::initBasicCluster()
|
||||||
{
|
{
|
||||||
|
ZigbeeClusterBasic *basicCluster = m_endpoints.first()->inputCluster<ZigbeeClusterBasic>(Zigbee::ClusterIdBasic);
|
||||||
|
|
||||||
|
if (!basicCluster) {
|
||||||
|
qCWarning(dcZigbeeNode()) << this << "could not find basic server cluster";
|
||||||
|
setState(StateInitialized);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterBasic::Attribute attributeId = ZigbeeClusterBasic::AttributeManufacturerName;
|
||||||
|
qCDebug(dcZigbeeNode()) << "Reading attribute" << attributeId;
|
||||||
|
ZigbeeClusterReply *reply = basicCluster->readAttributes({static_cast<quint16>(attributeId)});
|
||||||
|
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()) {
|
||||||
|
qCDebug(dcZigbeeNode()) << attributeStatusRecords.first();
|
||||||
|
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecords.first().dataType, attributeStatusRecords.first().data));
|
||||||
|
m_endpoints.first()->m_manufacturerName = QString::fromUtf8(attributeStatusRecords.first().data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterBasic::Attribute attributeId = ZigbeeClusterBasic::AttributeModelIdentifier;
|
||||||
|
qCDebug(dcZigbeeNode()) << "Reading attribute" << attributeId;
|
||||||
|
ZigbeeClusterReply *reply = basicCluster->readAttributes({static_cast<quint16>(attributeId)});
|
||||||
|
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()) {
|
||||||
|
qCDebug(dcZigbeeNode()) << attributeStatusRecords.first();
|
||||||
|
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecords.first().dataType, attributeStatusRecords.first().data));
|
||||||
|
m_endpoints.first()->m_modelIdentifier = QString::fromUtf8(attributeStatusRecords.first().data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZigbeeClusterBasic::Attribute attributeId = ZigbeeClusterBasic::AttributeSwBuildId;
|
||||||
|
qCDebug(dcZigbeeNode()) << "Reading attribute" << attributeId;
|
||||||
|
ZigbeeClusterReply *reply = basicCluster->readAttributes({static_cast<quint16>(attributeId)});
|
||||||
|
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()) {
|
||||||
|
qCDebug(dcZigbeeNode()) << attributeStatusRecords.first();
|
||||||
|
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecords.first().dataType, attributeStatusRecords.first().data));
|
||||||
|
m_endpoints.first()->m_softwareBuildId = QString::fromUtf8(attributeStatusRecords.first().data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finished with reading basic cluster, the node is initialized. TODO: read other cluster information
|
||||||
|
setState(StateInitialized);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -748,41 +725,6 @@ void ZigbeeNode::onClusterAttributeChanged(const ZigbeeClusterAttribute &attribu
|
|||||||
emit clusterAttributeChanged(cluster, attribute);
|
emit clusterAttributeChanged(cluster, attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void ZigbeeNode::onRequestUserDescriptorFinished()
|
|
||||||
//{
|
|
||||||
// ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
|
||||||
// reply->deleteLater();
|
|
||||||
|
|
||||||
// if (reply->status() != ZigbeeInterfaceReply::Success) {
|
|
||||||
// qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
|
|
||||||
// qCDebug(dcZigbeeController()) << reply->additionalMessage();
|
|
||||||
|
|
||||||
// quint8 sequenceNumber = static_cast<quint8>(reply->additionalMessage().data().at(0));
|
|
||||||
// quint8 status = static_cast<quint8>(reply->additionalMessage().data().at(1));
|
|
||||||
|
|
||||||
// quint16 nwkAddress = static_cast<quint16>(reply->additionalMessage().data().at(2));
|
|
||||||
// nwkAddress <<= 8;
|
|
||||||
// nwkAddress |= reply->additionalMessage().data().at(3);
|
|
||||||
|
|
||||||
// quint8 length = static_cast<quint8>(reply->additionalMessage().data().at(4));
|
|
||||||
|
|
||||||
// QByteArray data;
|
|
||||||
// if (length > 0) {
|
|
||||||
// data = reply->additionalMessage().data().mid(5, length);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// qCDebug(dcZigbeeNode()) << "User descriptor:";
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Attribute address:" << ZigbeeUtils::convertUint16ToHexString(nwkAddress);
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Lenght:" << ZigbeeUtils::convertByteToHexString(length);
|
|
||||||
// qCDebug(dcZigbeeNode()) << " Data:" << data;
|
|
||||||
//}
|
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, ZigbeeNode *node)
|
QDebug operator<<(QDebug debug, ZigbeeNode *node)
|
||||||
{
|
{
|
||||||
debug.nospace().noquote() << "ZigbeeNode(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress());
|
debug.nospace().noquote() << "ZigbeeNode(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress());
|
||||||
|
|||||||
@ -284,7 +284,6 @@ private:
|
|||||||
QList<quint8> m_uninitializedEndpoints;
|
QList<quint8> m_uninitializedEndpoints;
|
||||||
QList<quint16> m_uninitalizedBasicClusterAttributes;
|
QList<quint16> m_uninitalizedBasicClusterAttributes;
|
||||||
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void stateChanged(State state);
|
void stateChanged(State state);
|
||||||
void connectedChanged(bool connected);
|
void connectedChanged(bool connected);
|
||||||
|
|||||||
@ -30,6 +30,8 @@
|
|||||||
#include "zigbeenode.h"
|
#include "zigbeenode.h"
|
||||||
#include "loggingcategory.h"
|
#include "loggingcategory.h"
|
||||||
|
|
||||||
|
#include "zcl/general/zigbeeclusterbasic.h"
|
||||||
|
|
||||||
quint8 ZigbeeNodeEndpoint::endpointId() const
|
quint8 ZigbeeNodeEndpoint::endpointId() const
|
||||||
{
|
{
|
||||||
return m_endpointId;
|
return m_endpointId;
|
||||||
@ -146,6 +148,17 @@ void ZigbeeNodeEndpoint::setSoftwareBuildId(const QString &softwareBuildId)
|
|||||||
emit softwareBuildIdChanged(m_softwareBuildId);
|
emit softwareBuildIdChanged(m_softwareBuildId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeCluster *ZigbeeNodeEndpoint::createCluster(Zigbee::ClusterId clusterId, ZigbeeCluster::Direction direction)
|
||||||
|
{
|
||||||
|
switch (clusterId) {
|
||||||
|
case Zigbee::ClusterIdBasic:
|
||||||
|
return new ZigbeeClusterBasic(m_network, m_node, this, direction, this);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return new ZigbeeCluster(m_network, m_node, this, clusterId, direction, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeNodeEndpoint::addInputCluster(ZigbeeCluster *cluster)
|
void ZigbeeNodeEndpoint::addInputCluster(ZigbeeCluster *cluster)
|
||||||
{
|
{
|
||||||
m_inputClusters.insert(cluster->clusterId(), cluster);
|
m_inputClusters.insert(cluster->clusterId(), cluster);
|
||||||
@ -156,21 +169,6 @@ void ZigbeeNodeEndpoint::addOutputCluster(ZigbeeCluster *cluster)
|
|||||||
m_outputClusters.insert(cluster->clusterId(), cluster);
|
m_outputClusters.insert(cluster->clusterId(), cluster);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeNetworkReply *ZigbeeNodeEndpoint::createNetworkReply(const ZigbeeNetworkRequest &request)
|
|
||||||
{
|
|
||||||
ZigbeeNetworkReply *reply = new ZigbeeNetworkReply(request, this);
|
|
||||||
// Make sure the reply will be deleted
|
|
||||||
connect(reply, &ZigbeeNetworkReply::finished, reply, &ZigbeeNetworkReply::deleteLater);
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZigbeeNodeEndpoint::finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkReply::Error error, Zigbee::ZigbeeApsStatus zigbeeApsStatus)
|
|
||||||
{
|
|
||||||
reply->m_error = error;
|
|
||||||
reply->m_zigbeeApsStatus = zigbeeApsStatus;
|
|
||||||
reply->finished();
|
|
||||||
}
|
|
||||||
|
|
||||||
ZigbeeCluster *ZigbeeNodeEndpoint::getOutputCluster(Zigbee::ClusterId clusterId) const
|
ZigbeeCluster *ZigbeeNodeEndpoint::getOutputCluster(Zigbee::ClusterId clusterId) const
|
||||||
{
|
{
|
||||||
return m_outputClusters.value(clusterId);
|
return m_outputClusters.value(clusterId);
|
||||||
|
|||||||
@ -32,9 +32,11 @@
|
|||||||
|
|
||||||
#include "zigbee.h"
|
#include "zigbee.h"
|
||||||
#include "zigbeeaddress.h"
|
#include "zigbeeaddress.h"
|
||||||
#include "zigbeecluster.h"
|
|
||||||
#include "zigbeenetworkreply.h"
|
#include "zigbeenetworkreply.h"
|
||||||
|
|
||||||
|
#include "zcl/zigbeecluster.h"
|
||||||
|
#include "zcl/general/zigbeeclusterbasic.h"
|
||||||
|
|
||||||
class ZigbeeNode;
|
class ZigbeeNode;
|
||||||
class ZigbeeNetwork;
|
class ZigbeeNetwork;
|
||||||
|
|
||||||
@ -74,6 +76,24 @@ public:
|
|||||||
ZigbeeCluster *getOutputCluster(Zigbee::ClusterId clusterId) const;
|
ZigbeeCluster *getOutputCluster(Zigbee::ClusterId clusterId) const;
|
||||||
bool hasOutputCluster(Zigbee::ClusterId clusterId) const;
|
bool hasOutputCluster(Zigbee::ClusterId clusterId) const;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline T* inputCluster(Zigbee::ClusterId clusterId)
|
||||||
|
{
|
||||||
|
if (!hasInputCluster(clusterId))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return qobject_cast<T *>(getInputCluster(clusterId));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline T* outputCluster(Zigbee::ClusterId clusterId)
|
||||||
|
{
|
||||||
|
if (!hasOutputCluster(clusterId))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return qobject_cast<T *>(getOutputCluster(clusterId));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit ZigbeeNodeEndpoint(ZigbeeNetwork *network, ZigbeeNode *node, quint8 endpointId, QObject *parent = nullptr);
|
explicit ZigbeeNodeEndpoint(ZigbeeNetwork *network, ZigbeeNode *node, quint8 endpointId, QObject *parent = nullptr);
|
||||||
|
|
||||||
@ -84,7 +104,6 @@ private:
|
|||||||
quint16 m_deviceId = 0;
|
quint16 m_deviceId = 0;
|
||||||
quint8 m_deviceVersion = 0;
|
quint8 m_deviceVersion = 0;
|
||||||
|
|
||||||
|
|
||||||
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_inputClusters;
|
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_inputClusters;
|
||||||
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_outputClusters;
|
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_outputClusters;
|
||||||
|
|
||||||
@ -99,15 +118,14 @@ private:
|
|||||||
// Cluster commands
|
// Cluster commands
|
||||||
//virtual void setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute = ZigbeeClusterAttribute()) = 0;
|
//virtual void setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute = ZigbeeClusterAttribute()) = 0;
|
||||||
|
|
||||||
|
ZigbeeCluster *createCluster(Zigbee::ClusterId clusterId, ZigbeeCluster::Direction direction);
|
||||||
|
|
||||||
void addInputCluster(ZigbeeCluster *cluster);
|
void addInputCluster(ZigbeeCluster *cluster);
|
||||||
void addOutputCluster(ZigbeeCluster *cluster);
|
void addOutputCluster(ZigbeeCluster *cluster);
|
||||||
|
|
||||||
// Network reply methods
|
|
||||||
ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest());
|
|
||||||
void finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkReply::Error error = ZigbeeNetworkReply::ErrorNoError, Zigbee::ZigbeeApsStatus zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void clusterAttributeChanged(ZigbeeCluster *cluster, const ZigbeeClusterAttribute &attribute);
|
void clusterAttributeChanged(ZigbeeCluster *cluster, const ZigbeeClusterAttribute &attribute);
|
||||||
|
|
||||||
void manufacturerNameChanged(const QString &manufacturerName);
|
void manufacturerNameChanged(const QString &manufacturerName);
|
||||||
void modelIdentifierChanged(const QString &modelIdentifier);
|
void modelIdentifierChanged(const QString &modelIdentifier);
|
||||||
void softwareBuildIdChanged(const QString &softwareBuildId);
|
void softwareBuildIdChanged(const QString &softwareBuildId);
|
||||||
|
|||||||
@ -276,8 +276,11 @@ QString ZigbeeUtils::clusterIdToString(const Zigbee::ClusterId &clusterId)
|
|||||||
QMetaEnum metaEnum = metaObject.enumerator(metaObject.indexOfEnumerator("ClusterId"));
|
QMetaEnum metaEnum = metaObject.enumerator(metaObject.indexOfEnumerator("ClusterId"));
|
||||||
|
|
||||||
QString enumString = metaEnum.valueToKey(clusterId);
|
QString enumString = metaEnum.valueToKey(clusterId);
|
||||||
|
QString clusterName = enumString.remove("Zigbee::ClusterId(ClusterId").remove(")").append(QString("(%1)").arg(ZigbeeUtils::convertUint16ToHexString(clusterId)));
|
||||||
|
if (clusterName.isEmpty())
|
||||||
|
clusterName = "Unknown";
|
||||||
|
|
||||||
return enumString.remove("Zigbee::ClusterId(ClusterId").remove(")").append(QString("(%1)").arg(ZigbeeUtils::convertUint16ToHexString(clusterId)));
|
return clusterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ZigbeeUtils::profileIdToString(const Zigbee::ZigbeeProfile &profileId)
|
QString ZigbeeUtils::profileIdToString(const Zigbee::ZigbeeProfile &profileId)
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
#include <QBitArray>
|
#include <QBitArray>
|
||||||
|
|
||||||
#include "zigbee.h"
|
#include "zigbee.h"
|
||||||
#include "zigbeecluster.h"
|
#include "zcl/zigbeecluster.h"
|
||||||
|
|
||||||
|
|
||||||
class ZigbeeUtils
|
class ZigbeeUtils
|
||||||
|
|||||||
Reference in New Issue
Block a user