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);
|
||||
}
|
||||
|
||||
// foreach (ZigbeeNetworkReply *reply, m_pendingReplies.values()) {
|
||||
// // Check if this is a reply if for a ZDO request
|
||||
// if (reply->request().profileId() == Zigbee::ZigbeeProfileDevice) {
|
||||
// // We have a reply which is waiting for a ZDO response, lets check if they match
|
||||
// // 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
|
||||
void ZigbeeNetworkDeconz::handleZigbeeLightLinkIndication(const DeconzApsDataIndication &indication)
|
||||
{
|
||||
ZigbeeClusterLibrary::Frame frame = ZigbeeClusterLibrary::parseFrameData(indication.asdu);
|
||||
//qCDebug(dcZigbeeNetwork()) << "ZCL ZLL" << indication << frame;
|
||||
|
||||
// // Set the response payload of the
|
||||
// qCDebug(dcZigbeeNetwork()) << "Indication response for ZDO request received"
|
||||
// << static_cast<ZigbeeDeviceProfile::ZdoCommand>(reply->request().clusterId())
|
||||
// << "-->"
|
||||
// << static_cast<ZigbeeDeviceProfile::ZdoCommand>(indication.clusterId)
|
||||
// << deviceAdpu;
|
||||
// setReplyResponseData(reply, indication.asdu);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// 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;
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
ZigbeeClusterLibrary::Frame frame = ZigbeeClusterLibrary::parseFrameData(static_cast<Zigbee::ClusterId>(indication.clusterId), indication.asdu);
|
||||
qCDebug(dcZigbeeNetwork()) << "ZCL HA" << indication << frame;
|
||||
ZigbeeClusterLibrary::Frame frame = ZigbeeClusterLibrary::parseFrameData(indication.asdu);
|
||||
//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)
|
||||
@ -32,7 +32,7 @@
|
||||
|
||||
#include "zigbeenetwork.h"
|
||||
#include "zigbeechannelmask.h"
|
||||
#include "zigbeeclusterlibrary.h"
|
||||
#include "zcl/zigbeeclusterlibrary.h"
|
||||
#include "zigbeebridgecontrollerdeconz.h"
|
||||
|
||||
class ZigbeeNetworkDeconz : public ZigbeeNetwork
|
||||
@ -75,6 +75,7 @@ private:
|
||||
void handleZigbeeDeviceProfileIndication(const DeconzApsDataIndication &indication);
|
||||
|
||||
// ZZL
|
||||
void handleZigbeeLightLinkIndication(const DeconzApsDataIndication &indication);
|
||||
|
||||
// HA
|
||||
void handleZigbeeHomeAutomationIndication(const DeconzApsDataIndication &indication);
|
||||
@ -4,30 +4,22 @@ TARGET = nymea-zigbee1
|
||||
TEMPLATE = lib
|
||||
|
||||
SOURCES += \
|
||||
deconz/interface/zigbeeinterfacedeconz.cpp \
|
||||
deconz/interface/zigbeeinterfacedeconzreply.cpp \
|
||||
deconz/zigbeebridgecontrollerdeconz.cpp \
|
||||
deconz/zigbeenetworkdeconz.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 \
|
||||
zcl/zigbeeclusterbasic.cpp \
|
||||
backends/deconz/interface/zigbeeinterfacedeconz.cpp \
|
||||
backends/deconz/interface/zigbeeinterfacedeconzreply.cpp \
|
||||
backends/deconz/zigbeebridgecontrollerdeconz.cpp \
|
||||
backends/deconz/zigbeenetworkdeconz.cpp \
|
||||
zcl/zigbeecluster.cpp \
|
||||
zcl/zigbeeclusterattribute.cpp \
|
||||
zcl/zigbeeclusterlibrary.cpp \
|
||||
zcl/zigbeeclusterreply.cpp \
|
||||
zcl/general/zigbeeclusterbasic.cpp \
|
||||
zdo/zigbeedeviceobject.cpp \
|
||||
zdo/zigbeedeviceobjectreply.cpp \
|
||||
zdo/zigbeedeviceprofile.cpp \
|
||||
zigbeeadpu.cpp \
|
||||
zigbeebridgecontroller.cpp \
|
||||
zigbeechannelmask.cpp \
|
||||
zigbeecluster.cpp \
|
||||
zigbeeclusterattribute.cpp \
|
||||
zigbeeclusterlibrary.cpp \
|
||||
zigbeeclusterlibraryreply.cpp \
|
||||
zigbeedatatype.cpp \
|
||||
zigbeemanufacturer.cpp \
|
||||
zigbeenetwork.cpp \
|
||||
zigbeenetworkdatabase.cpp \
|
||||
@ -42,34 +34,33 @@ SOURCES += \
|
||||
zigbeeutils.cpp \
|
||||
zigbeenode.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 += \
|
||||
deconz/interface/deconz.h \
|
||||
deconz/interface/zigbeeinterfacedeconz.h \
|
||||
deconz/interface/zigbeeinterfacedeconzreply.h \
|
||||
deconz/zigbeebridgecontrollerdeconz.h \
|
||||
deconz/zigbeenetworkdeconz.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 \
|
||||
zcl/zigbeeclusterbasic.h \
|
||||
backends/deconz/interface/deconz.h \
|
||||
backends/deconz/interface/zigbeeinterfacedeconz.h \
|
||||
backends/deconz/interface/zigbeeinterfacedeconzreply.h \
|
||||
backends/deconz/zigbeebridgecontrollerdeconz.h \
|
||||
backends/deconz/zigbeenetworkdeconz.h \
|
||||
zcl/zigbeecluster.h \
|
||||
zcl/zigbeeclusterattribute.h \
|
||||
zcl/zigbeeclusterlibrary.h \
|
||||
zcl/zigbeeclusterreply.h \
|
||||
zcl/general/zigbeeclusterbasic.h \
|
||||
zdo/zigbeedeviceobject.h \
|
||||
zdo/zigbeedeviceobjectreply.h \
|
||||
zdo/zigbeedeviceprofile.h \
|
||||
zigbeeadpu.h \
|
||||
zigbeebridgecontroller.h \
|
||||
zigbeechannelmask.h \
|
||||
zigbeecluster.h \
|
||||
zigbeeclusterattribute.h \
|
||||
zigbeeclusterlibrary.h \
|
||||
zigbeeclusterlibraryreply.h \
|
||||
zigbeedatatype.h \
|
||||
zigbeemanufacturer.h \
|
||||
zigbeenetwork.h \
|
||||
zigbeenetworkdatabase.h \
|
||||
@ -84,7 +75,14 @@ HEADERS += \
|
||||
zigbeeutils.h \
|
||||
zigbeenode.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
|
||||
for (header, HEADERS) {
|
||||
|
||||
@ -34,5 +34,6 @@ Q_LOGGING_CATEGORY(dcZigbeeCluster, "ZigbeeCluster")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeDeviceObject, "ZigbeeDeviceObject")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeClusterLibrary, "ZigbeeClusterLibrary")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeNetworkDatabase, "ZigbeeNetworkDatabase")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")
|
||||
|
||||
@ -38,6 +38,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcZigbeeCluster)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeDeviceObject)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeClusterLibrary)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetworkDatabase)
|
||||
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 "zigbeecluster.h"
|
||||
#include "zcl/zigbeecluster.h"
|
||||
|
||||
class ZigbeeClusterBasic : public ZigbeeCluster
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
friend class ZigbeeNode;
|
||||
friend class ZigbeeNetwork;
|
||||
|
||||
enum Attribute {
|
||||
AttributeZclVersion = 0x0000, // Mandatory
|
||||
AttributeAppVersion = 0x0001,
|
||||
@ -28,7 +31,7 @@ public:
|
||||
};
|
||||
Q_ENUM(Attribute)
|
||||
|
||||
// From attribute 0x0007 power source
|
||||
// Enum for AttributePowerSource(0x0007)
|
||||
enum AttributePowerSourceValue {
|
||||
AttributePowerSourceValueUnknown = 0x00,
|
||||
AttributePowerSourceValueMainsSinglePhase = 0x01,
|
||||
@ -40,9 +43,10 @@ public:
|
||||
};
|
||||
Q_ENUM(AttributePowerSourceValue)
|
||||
|
||||
|
||||
explicit ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
||||
|
||||
private:
|
||||
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
||||
|
||||
signals:
|
||||
|
||||
@ -74,14 +74,14 @@ bool ZigbeeCluster::hasAttribute(quint16 attributeId) const
|
||||
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)
|
||||
{
|
||||
if (hasAttribute(attribute.id())) {
|
||||
if (hasAttribute(attribute.id())) {
|
||||
qCDebug(dcZigbeeCluster()) << this << "update attribute" << attribute;
|
||||
m_attributes[attribute.id()] = 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
|
||||
ZigbeeNetworkRequest request;
|
||||
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);
|
||||
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||
|
||||
// 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;
|
||||
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;
|
||||
|
||||
// ZCL header
|
||||
ZigbeeClusterLibrary::Header header;
|
||||
header.frameControl = frameControl;
|
||||
header.command = ZigbeeClusterLibrary::CommandReadAttributes;
|
||||
header.transactionSequenceNumber = m_network->generateTranactionSequenceNumber();
|
||||
header.transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
// ZCL payload
|
||||
QByteArray payload;
|
||||
@ -125,15 +128,108 @@ ZigbeeNetworkReply *ZigbeeCluster::readAttributes(QList<quint16> attributes)
|
||||
|
||||
// Put them together
|
||||
ZigbeeClusterLibrary::Frame frame;
|
||||
frame.clusterId = m_clusterId;
|
||||
frame.header = header;
|
||||
frame.payload = payload;
|
||||
|
||||
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
||||
request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame));
|
||||
|
||||
qCDebug(dcZigbeeCluster()) << "Send read attributes request" << m_node << m_endpoint << this << attributes;
|
||||
return m_network->sendRequest(request);
|
||||
ZigbeeClusterReply *zclReply = createClusterReply(request, frame);
|
||||
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)
|
||||
@ -143,7 +239,6 @@ QDebug operator<<(QDebug debug, ZigbeeCluster *cluster)
|
||||
<< cluster->clusterName() << ", "
|
||||
<< cluster->direction()
|
||||
<< ")";
|
||||
|
||||
return debug.space();
|
||||
}
|
||||
|
||||
@ -159,3 +254,4 @@ QDebug operator<<(QDebug debug, const ZigbeeClusterAttributeReport &attributeRep
|
||||
|
||||
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 "loggingcategory.h"
|
||||
#include "zigbeeutils.h"
|
||||
|
||||
#include <QDataStream>
|
||||
@ -35,7 +36,7 @@ quint8 ZigbeeClusterLibrary::buildFrameControlByte(const ZigbeeClusterLibrary::F
|
||||
quint8 byte = 0x00;
|
||||
|
||||
// Bit 0-1
|
||||
byte |= FrameTypeClusterSpecific;
|
||||
byte |= frameControl.frameType;
|
||||
|
||||
// Bit 2
|
||||
if (frameControl.manufacturerSpecific)
|
||||
@ -93,7 +94,95 @@ QByteArray ZigbeeClusterLibrary::buildHeader(const ZigbeeClusterLibrary::Header
|
||||
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);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
@ -117,15 +206,12 @@ ZigbeeClusterLibrary::Frame ZigbeeClusterLibrary::parseFrameData(Zigbee::Cluster
|
||||
offset += 1;
|
||||
|
||||
stream >> commandByte;
|
||||
offset += 1;
|
||||
|
||||
header.command = static_cast<Command>(commandByte);
|
||||
offset += 1;
|
||||
|
||||
Frame frame;
|
||||
frame.clusterId = clusterId;
|
||||
frame.header = header;
|
||||
frame.payload = frameData.right(frameData.length() - offset - 1);
|
||||
frame.payload = frameData.right(frameData.length() - offset);
|
||||
return frame;
|
||||
}
|
||||
|
||||
@ -169,8 +255,20 @@ QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Header &header)
|
||||
|
||||
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() << ZigbeeUtils::convertByteArrayToHexString(frame.payload) << ")";
|
||||
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)
|
||||
|
||||
enum GlobalAttribute {
|
||||
GlobalAttributeClusterRevision = 0xfffd,
|
||||
GlobalAttributeAttributeReportingStatus = 0xfffe
|
||||
};
|
||||
Q_ENUM(GlobalAttribute)
|
||||
|
||||
enum AttributeReportingStatus {
|
||||
AttributeReportingStatusPending = 0x00,
|
||||
AttributeReportingStatusComplete = 0x01
|
||||
};
|
||||
Q_ENUM(AttributeReportingStatus)
|
||||
|
||||
// Frame control field
|
||||
enum FrameType {
|
||||
FrameTypeGlobal = 0x00,
|
||||
@ -79,7 +91,7 @@ public:
|
||||
Q_ENUM(Direction)
|
||||
|
||||
typedef struct FrameControl {
|
||||
FrameType frameType = FrameTypeClusterSpecific;
|
||||
FrameType frameType = FrameTypeGlobal;
|
||||
bool manufacturerSpecific = false;
|
||||
Direction direction = DirectionClientToServer;
|
||||
bool disableDefaultResponse = false;
|
||||
@ -93,24 +105,39 @@ public:
|
||||
} ZclHeader;
|
||||
|
||||
typedef struct Frame {
|
||||
Zigbee::ClusterId clusterId;
|
||||
Header header;
|
||||
QByteArray payload;
|
||||
} Frame;
|
||||
|
||||
|
||||
// Read attribute
|
||||
typedef struct ReadAttributeStatusRecord {
|
||||
quint16 attributeId;
|
||||
Zigbee::ZigbeeStatus attributeStatus;
|
||||
Zigbee::DataType dataType;
|
||||
QByteArray data;
|
||||
} ReadAttributeStatusRecord;
|
||||
|
||||
|
||||
// General parse/build methods
|
||||
static quint8 buildFrameControlByte(const FrameControl &frameControl);
|
||||
static FrameControl parseFrameControlByte(quint8 frameControlByte);
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::FrameControl &frameControl);
|
||||
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Header &header);
|
||||
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Frame &frame);
|
||||
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::ReadAttributeStatusRecord &attributeStatusRecord);
|
||||
|
||||
|
||||
#endif // ZIGBEECLUSTERLIBRARY_H
|
||||
@ -1,6 +1,44 @@
|
||||
#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 "zigbeenetworkrequest.h"
|
||||
#include "zigbeeclusterlibrary.h"
|
||||
|
||||
class ZigbeeClusterReply : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class ZigbeeCluster;
|
||||
|
||||
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:
|
||||
void finished();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ class ZigbeeDeviceObjectReply : public QObject
|
||||
|
||||
public:
|
||||
enum Error {
|
||||
ErrorNoError, // All OK, no error occured
|
||||
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.
|
||||
@ -81,7 +81,6 @@ private:
|
||||
QByteArray m_responseData;
|
||||
ZigbeeDeviceProfile::Adpu m_responseAdpu;
|
||||
|
||||
|
||||
signals:
|
||||
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 ++) {
|
||||
settings.setArrayIndex(n);
|
||||
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;
|
||||
endpoint->m_inputClusters.insert(clusterId, cluster);
|
||||
}
|
||||
@ -361,7 +361,7 @@ void ZigbeeNetwork::loadNetwork()
|
||||
for (int n = 0; n < outputClustersCount; n ++) {
|
||||
settings.setArrayIndex(n);
|
||||
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;
|
||||
endpoint->m_outputClusters.insert(clusterId, cluster);
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
#include "zigbeenetworkmanager.h"
|
||||
#include "loggingcategory.h"
|
||||
|
||||
#include "deconz/zigbeenetworkdeconz.h"
|
||||
#include "backends/deconz/zigbeenetworkdeconz.h"
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
|
||||
@ -257,91 +257,6 @@ void ZigbeeNode::setExtendedAddress(const ZigbeeAddress &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
|
||||
{
|
||||
return m_serverMask;
|
||||
@ -704,11 +619,11 @@ void ZigbeeNode::initEndpoint(quint8 endpointId)
|
||||
quint16 clusterId = 0;
|
||||
stream >> 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));
|
||||
|
||||
}
|
||||
|
||||
stream >> outputClusterCount;
|
||||
|
||||
qCDebug(dcZigbeeNode()) << " Output clusters: (" << outputClusterCount << ")";
|
||||
@ -716,7 +631,7 @@ void ZigbeeNode::initEndpoint(quint8 endpointId)
|
||||
quint16 clusterId = 0;
|
||||
stream >> 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));
|
||||
}
|
||||
@ -725,19 +640,81 @@ void ZigbeeNode::initEndpoint(quint8 endpointId)
|
||||
|
||||
if (m_uninitializedEndpoints.isEmpty()) {
|
||||
|
||||
//if (m_shortAddress == 0) {
|
||||
setState(StateInitialized);
|
||||
return;
|
||||
//}
|
||||
if (m_shortAddress == 0) {
|
||||
setState(StateInitialized);
|
||||
return;
|
||||
}
|
||||
|
||||
// Continue with the basic cluster attributes
|
||||
//initBasicCluster();
|
||||
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);
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
debug.nospace().noquote() << "ZigbeeNode(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress());
|
||||
|
||||
@ -284,7 +284,6 @@ private:
|
||||
QList<quint8> m_uninitializedEndpoints;
|
||||
QList<quint16> m_uninitalizedBasicClusterAttributes;
|
||||
|
||||
|
||||
signals:
|
||||
void stateChanged(State state);
|
||||
void connectedChanged(bool connected);
|
||||
|
||||
@ -30,6 +30,8 @@
|
||||
#include "zigbeenode.h"
|
||||
#include "loggingcategory.h"
|
||||
|
||||
#include "zcl/general/zigbeeclusterbasic.h"
|
||||
|
||||
quint8 ZigbeeNodeEndpoint::endpointId() const
|
||||
{
|
||||
return m_endpointId;
|
||||
@ -146,6 +148,17 @@ void ZigbeeNodeEndpoint::setSoftwareBuildId(const QString &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)
|
||||
{
|
||||
m_inputClusters.insert(cluster->clusterId(), cluster);
|
||||
@ -156,21 +169,6 @@ void ZigbeeNodeEndpoint::addOutputCluster(ZigbeeCluster *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
|
||||
{
|
||||
return m_outputClusters.value(clusterId);
|
||||
|
||||
@ -32,9 +32,11 @@
|
||||
|
||||
#include "zigbee.h"
|
||||
#include "zigbeeaddress.h"
|
||||
#include "zigbeecluster.h"
|
||||
#include "zigbeenetworkreply.h"
|
||||
|
||||
#include "zcl/zigbeecluster.h"
|
||||
#include "zcl/general/zigbeeclusterbasic.h"
|
||||
|
||||
class ZigbeeNode;
|
||||
class ZigbeeNetwork;
|
||||
|
||||
@ -74,6 +76,24 @@ public:
|
||||
ZigbeeCluster *getOutputCluster(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:
|
||||
explicit ZigbeeNodeEndpoint(ZigbeeNetwork *network, ZigbeeNode *node, quint8 endpointId, QObject *parent = nullptr);
|
||||
|
||||
@ -84,7 +104,6 @@ private:
|
||||
quint16 m_deviceId = 0;
|
||||
quint8 m_deviceVersion = 0;
|
||||
|
||||
|
||||
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_inputClusters;
|
||||
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_outputClusters;
|
||||
|
||||
@ -99,15 +118,14 @@ private:
|
||||
// Cluster commands
|
||||
//virtual void setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute = ZigbeeClusterAttribute()) = 0;
|
||||
|
||||
ZigbeeCluster *createCluster(Zigbee::ClusterId clusterId, ZigbeeCluster::Direction direction);
|
||||
|
||||
void addInputCluster(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:
|
||||
void clusterAttributeChanged(ZigbeeCluster *cluster, const ZigbeeClusterAttribute &attribute);
|
||||
|
||||
void manufacturerNameChanged(const QString &manufacturerName);
|
||||
void modelIdentifierChanged(const QString &modelIdentifier);
|
||||
void softwareBuildIdChanged(const QString &softwareBuildId);
|
||||
|
||||
@ -276,8 +276,11 @@ QString ZigbeeUtils::clusterIdToString(const Zigbee::ClusterId &clusterId)
|
||||
QMetaEnum metaEnum = metaObject.enumerator(metaObject.indexOfEnumerator("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)
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
#include <QBitArray>
|
||||
|
||||
#include "zigbee.h"
|
||||
#include "zigbeecluster.h"
|
||||
#include "zcl/zigbeecluster.h"
|
||||
|
||||
|
||||
class ZigbeeUtils
|
||||
|
||||
Reference in New Issue
Block a user