Add cluster and attribute base classes and improve node initialization
This commit is contained in:
parent
2922a87449
commit
7745f09581
@ -14,6 +14,7 @@ ZigbeeInterface::ZigbeeInterface(QObject *parent) :
|
|||||||
|
|
||||||
ZigbeeInterface::~ZigbeeInterface()
|
ZigbeeInterface::~ZigbeeInterface()
|
||||||
{
|
{
|
||||||
|
qCCritical(dcZigbeeInterface()) << "Destroy interface";
|
||||||
disable();
|
disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,14 +128,21 @@ void ZigbeeInterface::onReadyRead()
|
|||||||
// Check message sanity
|
// Check message sanity
|
||||||
quint8 crc = calculateCrc(m_messageTypeValue, m_lengthValue, m_data);
|
quint8 crc = calculateCrc(m_messageTypeValue, m_lengthValue, m_data);
|
||||||
if (crc != m_crcValue) {
|
if (crc != m_crcValue) {
|
||||||
qCWarning(dcZigbeeInterface()) << "Invalid CRC value" << crc << "!=" << m_crcValue;
|
qCWarning(dcZigbeeInterface()) << "Received message end: Invalid CRC value" << crc << "!=" << m_crcValue;
|
||||||
} else if (m_data.count() != m_lengthValue) {
|
} else if (m_data.count() != m_lengthValue) {
|
||||||
qCWarning(dcZigbeeInterface()) << "ERROR:s Invalid data length" << m_data.count() << "!=" << m_lengthValue;
|
qCWarning(dcZigbeeInterface()) << "Received message end: Invalid data length of message" << m_data.count() << "!=" << m_lengthValue;
|
||||||
} else {
|
} else {
|
||||||
// We got a valid message
|
// We got a valid message
|
||||||
ZigbeeInterfaceMessage message(messageType, m_data);
|
ZigbeeInterfaceMessage message(messageType, m_data);
|
||||||
qCDebug(dcZigbeeInterface()) << "<--" << message << "|" << "crc:" << ZigbeeUtils::convertByteToHexString(m_crcValue) << ", length:" << ZigbeeUtils::convertUint16ToHexString(m_lengthValue);
|
qCDebug(dcZigbeeInterface()) << "<--" << message << "|" << "crc:" << ZigbeeUtils::convertByteToHexString(m_crcValue) << ", length:" << ZigbeeUtils::convertUint16ToHexString(m_lengthValue);
|
||||||
emit messageReceived(message);
|
emit messageReceived(message);
|
||||||
|
|
||||||
|
// Clear all information for the next byte
|
||||||
|
m_crcValue = 0;
|
||||||
|
m_messageTypeValue = 0;
|
||||||
|
m_lengthValue = 0;
|
||||||
|
m_escapeDetected = false;
|
||||||
|
m_data.clear();
|
||||||
}
|
}
|
||||||
setReadingState(WaitForStart);
|
setReadingState(WaitForStart);
|
||||||
break;
|
break;
|
||||||
@ -150,6 +158,7 @@ void ZigbeeInterface::onReadyRead()
|
|||||||
// Read data bytes depending on the reading state
|
// Read data bytes depending on the reading state
|
||||||
switch (m_readingState) {
|
switch (m_readingState) {
|
||||||
case WaitForStart:
|
case WaitForStart:
|
||||||
|
qCWarning(dcZigbeeInterfaceTraffic()) << "Wait for start but reviced data:" << byte;
|
||||||
break;
|
break;
|
||||||
case WaitForTypeMsb:
|
case WaitForTypeMsb:
|
||||||
m_messageTypeValue = byte;
|
m_messageTypeValue = byte;
|
||||||
|
|||||||
@ -11,6 +11,8 @@ SOURCES += \
|
|||||||
interface/zigbeeinterfacerequest.cpp \
|
interface/zigbeeinterfacerequest.cpp \
|
||||||
interface/zigbeeinterfacereply.cpp \
|
interface/zigbeeinterfacereply.cpp \
|
||||||
nxp/nxpzigbeenetworkmanager.cpp \
|
nxp/nxpzigbeenetworkmanager.cpp \
|
||||||
|
zigbeecluster.cpp \
|
||||||
|
zigbeeclusterattribute.cpp \
|
||||||
zigbeenetwork.cpp \
|
zigbeenetwork.cpp \
|
||||||
zigbeenetworkmanager.cpp \
|
zigbeenetworkmanager.cpp \
|
||||||
zigbee.cpp \
|
zigbee.cpp \
|
||||||
@ -27,6 +29,8 @@ HEADERS += \
|
|||||||
interface/zigbeeinterfacerequest.h \
|
interface/zigbeeinterfacerequest.h \
|
||||||
interface/zigbeeinterfacereply.h \
|
interface/zigbeeinterfacereply.h \
|
||||||
nxp/nxpzigbeenetworkmanager.h \
|
nxp/nxpzigbeenetworkmanager.h \
|
||||||
|
zigbeecluster.h \
|
||||||
|
zigbeeclusterattribute.h \
|
||||||
zigbeenetwork.h \
|
zigbeenetwork.h \
|
||||||
zigbeenetworkmanager.h \
|
zigbeenetworkmanager.h \
|
||||||
zigbee.h \
|
zigbee.h \
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include "loggingcategory.h"
|
#include "loggingcategory.h"
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(dcZigbeeNetwork, "ZigbeeNetwork")
|
Q_LOGGING_CATEGORY(dcZigbeeNetwork, "ZigbeeNetwork")
|
||||||
|
Q_LOGGING_CATEGORY(dcZigbeeNode, "ZigbeeNode")
|
||||||
Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface")
|
Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface")
|
||||||
Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController")
|
Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController")
|
||||||
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")
|
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetwork)
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetwork)
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNode)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface)
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController)
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic)
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic)
|
||||||
|
|||||||
@ -216,6 +216,7 @@ public:
|
|||||||
|
|
||||||
enum ClusterId {
|
enum ClusterId {
|
||||||
// Basics
|
// Basics
|
||||||
|
ClusterIdUnknown = 0xffff,
|
||||||
ClusterIdBasic = 0x0000,
|
ClusterIdBasic = 0x0000,
|
||||||
ClusterIdPower = 0x0001,
|
ClusterIdPower = 0x0001,
|
||||||
ClusterIdDeviceTemperature = 0x0002,
|
ClusterIdDeviceTemperature = 0x0002,
|
||||||
@ -292,6 +293,24 @@ public:
|
|||||||
};
|
};
|
||||||
Q_ENUM(ClusterId)
|
Q_ENUM(ClusterId)
|
||||||
|
|
||||||
|
enum ClusterAttributeBasic {
|
||||||
|
ClusterAttributeBasicZclVersion = 0x0000,
|
||||||
|
ClusterAttributeBasicApplicationVersion = 0x0001,
|
||||||
|
ClusterAttributeBasicStackVersion = 0x0002,
|
||||||
|
ClusterAttributeBasicHardwareVersion = 0x0003,
|
||||||
|
ClusterAttributeBasicManufacturerName = 0x0004,
|
||||||
|
ClusterAttributeBasicModelIdentifier = 0x0005,
|
||||||
|
ClusterAttributeBasicDataCode = 0x0006,
|
||||||
|
ClusterAttributeBasicPowerSource = 0x0007,
|
||||||
|
ClusterAttributeBasicLocationDescription = 0x0010,
|
||||||
|
ClusterAttributeBasicPhysicalEnvironment = 0x0011,
|
||||||
|
ClusterAttributeBasicDeviceEnabled = 0x0012,
|
||||||
|
ClusterAttributeBasicAlarmMask = 0x0013,
|
||||||
|
ClusterAttributeBasicDisableLocalConfig = 0x0014,
|
||||||
|
ClusterAttributeBasicSoftwareBuildId = 0x4000
|
||||||
|
};
|
||||||
|
Q_ENUM(ClusterAttributeBasic)
|
||||||
|
|
||||||
|
|
||||||
enum LightLinkDevice {
|
enum LightLinkDevice {
|
||||||
// Lightning devices
|
// Lightning devices
|
||||||
|
|||||||
@ -12,6 +12,11 @@ ZigbeeBridgeController::ZigbeeBridgeController(QObject *parent) :
|
|||||||
connect(m_interface, &ZigbeeInterface::messageReceived, this, &ZigbeeBridgeController::onMessageReceived);
|
connect(m_interface, &ZigbeeInterface::messageReceived, this, &ZigbeeBridgeController::onMessageReceived);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeBridgeController::~ZigbeeBridgeController()
|
||||||
|
{
|
||||||
|
qCDebug(dcZigbeeController()) << "Destroy controller";
|
||||||
|
}
|
||||||
|
|
||||||
bool ZigbeeBridgeController::available() const
|
bool ZigbeeBridgeController::available() const
|
||||||
{
|
{
|
||||||
return m_interface->available();
|
return m_interface->available();
|
||||||
@ -247,7 +252,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandAuthenticateDevice(const Zi
|
|||||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeAuthenticateDeviceRequest, data));
|
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeAuthenticateDeviceRequest, data));
|
||||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeAuthenticateDeviceResponse);
|
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeAuthenticateDeviceResponse);
|
||||||
request.setDescription(QString("Authenticate device %1").arg(ieeeAddress.toString()));
|
request.setDescription(QString("Authenticate device %1").arg(ieeeAddress.toString()));
|
||||||
request.setTimoutIntervall(5000);
|
request.setTimoutIntervall(2000);
|
||||||
|
|
||||||
return sendRequest(request);
|
return sendRequest(request);
|
||||||
}
|
}
|
||||||
@ -261,7 +266,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandNodeDescriptorRequest(quint
|
|||||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeNodeDescriptorRequest, data));
|
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeNodeDescriptorRequest, data));
|
||||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeNodeDescriptorRsponse);
|
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeNodeDescriptorRsponse);
|
||||||
request.setDescription("Node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
|
request.setDescription("Node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
|
||||||
request.setTimoutIntervall(10000);
|
request.setTimoutIntervall(5000);
|
||||||
|
|
||||||
return sendRequest(request);
|
return sendRequest(request);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ class ZigbeeBridgeController : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit ZigbeeBridgeController(QObject *parent = nullptr);
|
explicit ZigbeeBridgeController(QObject *parent = nullptr);
|
||||||
|
~ZigbeeBridgeController();
|
||||||
|
|
||||||
bool available() const;
|
bool available() const;
|
||||||
|
|
||||||
|
|||||||
59
libnymea-zigbee/zigbeecluster.cpp
Normal file
59
libnymea-zigbee/zigbeecluster.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#include "zigbeeutils.h"
|
||||||
|
#include "zigbeecluster.h"
|
||||||
|
|
||||||
|
ZigbeeCluster::ZigbeeCluster(Zigbee::ClusterId clusterId, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_clusterId(clusterId)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Zigbee::ClusterId ZigbeeCluster::clusterId() const
|
||||||
|
{
|
||||||
|
return m_clusterId;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ZigbeeCluster::clusterName() const
|
||||||
|
{
|
||||||
|
return ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(m_clusterId));
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ZigbeeClusterAttribute> ZigbeeCluster::attributes() const
|
||||||
|
{
|
||||||
|
return m_attributes.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZigbeeCluster::hasAttribute(quint16 attributeId) const
|
||||||
|
{
|
||||||
|
if (m_attributes.keys().isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_attributes.keys().contains(attributeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterAttribute ZigbeeCluster::attribute(quint16 id)
|
||||||
|
{
|
||||||
|
return m_attributes.value(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeCluster::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||||
|
{
|
||||||
|
if (hasAttribute(attribute.id())) {
|
||||||
|
if (m_attributes.value(attribute.id()) != attribute) {
|
||||||
|
m_attributes[attribute.id()] = attribute;
|
||||||
|
emit attributeChanged(attribute);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_attributes.insert(attribute.id(), attribute);
|
||||||
|
emit attributeChanged(attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster)
|
||||||
|
{
|
||||||
|
debug.nospace().noquote() << "ZigbeeCluster("
|
||||||
|
<< ZigbeeUtils::convertUint16ToHexString(static_cast<quint16>(cluster->clusterId())) << ", "
|
||||||
|
<< cluster->clusterName() << ")";
|
||||||
|
|
||||||
|
return debug.space();
|
||||||
|
}
|
||||||
42
libnymea-zigbee/zigbeecluster.h
Normal file
42
libnymea-zigbee/zigbeecluster.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ifndef ZIGBEECLUSTER_H
|
||||||
|
#define ZIGBEECLUSTER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "zigbee.h"
|
||||||
|
#include "zigbeeclusterattribute.h"
|
||||||
|
|
||||||
|
class ZigbeeCluster : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend class ZigbeeNode;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ZigbeeCluster(Zigbee::ClusterId clusterId, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
Zigbee::ClusterId clusterId() const;
|
||||||
|
QString clusterName() const;
|
||||||
|
|
||||||
|
QList<ZigbeeClusterAttribute> attributes() const;
|
||||||
|
bool hasAttribute(quint16 attributeId) const;
|
||||||
|
|
||||||
|
ZigbeeClusterAttribute attribute(quint16 id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Zigbee::ClusterId m_clusterId = Zigbee::ClusterIdUnknown;
|
||||||
|
QHash<quint16, ZigbeeClusterAttribute> m_attributes;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setAttribute(const ZigbeeClusterAttribute &attribute);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void attributeChanged(const ZigbeeClusterAttribute &attribute);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster);
|
||||||
|
|
||||||
|
#endif // ZIGBEECLUSTER_H
|
||||||
73
libnymea-zigbee/zigbeeclusterattribute.cpp
Normal file
73
libnymea-zigbee/zigbeeclusterattribute.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include "zigbeeutils.h"
|
||||||
|
#include "zigbeeclusterattribute.h"
|
||||||
|
|
||||||
|
ZigbeeClusterAttribute::ZigbeeClusterAttribute()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterAttribute::ZigbeeClusterAttribute(quint16 id, Zigbee::DataType dataType, QByteArray data):
|
||||||
|
m_id(id),
|
||||||
|
m_dataType(dataType),
|
||||||
|
m_data(data)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterAttribute::ZigbeeClusterAttribute(const ZigbeeClusterAttribute &other)
|
||||||
|
{
|
||||||
|
m_id = other.id();
|
||||||
|
m_dataType = other.dataType();
|
||||||
|
m_data = other.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
quint16 ZigbeeClusterAttribute::id() const
|
||||||
|
{
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
Zigbee::DataType ZigbeeClusterAttribute::dataType() const
|
||||||
|
{
|
||||||
|
return m_dataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray ZigbeeClusterAttribute::data() const
|
||||||
|
{
|
||||||
|
return m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterAttribute &ZigbeeClusterAttribute::operator=(const ZigbeeClusterAttribute &other)
|
||||||
|
{
|
||||||
|
m_id = other.id();
|
||||||
|
m_dataType = other.dataType();
|
||||||
|
m_data = other.data();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZigbeeClusterAttribute::operator==(const ZigbeeClusterAttribute &other) const
|
||||||
|
{
|
||||||
|
return m_id == other.id() &&
|
||||||
|
m_dataType == other.dataType() &&
|
||||||
|
m_data == other.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZigbeeClusterAttribute::operator!=(const ZigbeeClusterAttribute &other) const
|
||||||
|
{
|
||||||
|
return !operator==(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZigbeeClusterAttribute::isValid() const
|
||||||
|
{
|
||||||
|
return m_id != 0 ||
|
||||||
|
m_dataType != Zigbee::NoData ||
|
||||||
|
!m_data.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const ZigbeeClusterAttribute &attribute)
|
||||||
|
{
|
||||||
|
debug.nospace().noquote() << "ZigbeeClusterAttribute("
|
||||||
|
<< ZigbeeUtils::convertUint16ToHexString(attribute.id()) << ", "
|
||||||
|
<< attribute.dataType() << ", "
|
||||||
|
<< ZigbeeUtils::convertByteArrayToHexString(attribute.data()) << ")";
|
||||||
|
return debug.space();
|
||||||
|
}
|
||||||
34
libnymea-zigbee/zigbeeclusterattribute.h
Normal file
34
libnymea-zigbee/zigbeeclusterattribute.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef ZIGBEECLUSTERATTRIBUTE_H
|
||||||
|
#define ZIGBEECLUSTERATTRIBUTE_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "zigbee.h"
|
||||||
|
|
||||||
|
class ZigbeeClusterAttribute
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ZigbeeClusterAttribute();
|
||||||
|
ZigbeeClusterAttribute(quint16 id, Zigbee::DataType dataType, QByteArray data);
|
||||||
|
ZigbeeClusterAttribute(const ZigbeeClusterAttribute &other);
|
||||||
|
|
||||||
|
quint16 id() const;
|
||||||
|
Zigbee::DataType dataType() const;
|
||||||
|
QByteArray data() const;
|
||||||
|
|
||||||
|
ZigbeeClusterAttribute &operator=(const ZigbeeClusterAttribute &other);
|
||||||
|
bool operator==(const ZigbeeClusterAttribute &other) const;
|
||||||
|
bool operator!=(const ZigbeeClusterAttribute &other) const;
|
||||||
|
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
quint16 m_id = 0;
|
||||||
|
Zigbee::DataType m_dataType = Zigbee::NoData;
|
||||||
|
QByteArray m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const ZigbeeClusterAttribute &attribute);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ZIGBEECLUSTERATTRIBUTE_H
|
||||||
@ -120,6 +120,12 @@ ZigbeeNode *ZigbeeNetwork::coordinatorNode() const
|
|||||||
|
|
||||||
ZigbeeNode *ZigbeeNetwork::getZigbeeNode(quint16 shortAddress) const
|
ZigbeeNode *ZigbeeNetwork::getZigbeeNode(quint16 shortAddress) const
|
||||||
{
|
{
|
||||||
|
foreach (ZigbeeNode *node, m_uninitializedNodes) {
|
||||||
|
if (node->shortAddress() == shortAddress) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (ZigbeeNode *node, m_nodes) {
|
foreach (ZigbeeNode *node, m_nodes) {
|
||||||
if (node->shortAddress() == shortAddress) {
|
if (node->shortAddress() == shortAddress) {
|
||||||
return node;
|
return node;
|
||||||
@ -131,6 +137,12 @@ ZigbeeNode *ZigbeeNetwork::getZigbeeNode(quint16 shortAddress) const
|
|||||||
|
|
||||||
ZigbeeNode *ZigbeeNetwork::getZigbeeNode(const ZigbeeAddress &address) const
|
ZigbeeNode *ZigbeeNetwork::getZigbeeNode(const ZigbeeAddress &address) const
|
||||||
{
|
{
|
||||||
|
foreach (ZigbeeNode *node, m_uninitializedNodes) {
|
||||||
|
if (node->extendedAddress() == address) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (ZigbeeNode *node, m_nodes) {
|
foreach (ZigbeeNode *node, m_nodes) {
|
||||||
if (node->extendedAddress() == address) {
|
if (node->extendedAddress() == address) {
|
||||||
return node;
|
return node;
|
||||||
@ -164,11 +176,52 @@ void ZigbeeNetwork::saveNetwork()
|
|||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
settings.beginWriteArray("Nodes");
|
settings.beginWriteArray("Nodes");
|
||||||
for (int i = 0; i < nodes().count(); i++) {
|
for (int x = 0; x < nodes().count(); x++) {
|
||||||
settings.setArrayIndex(i);
|
settings.setArrayIndex(x);
|
||||||
settings.setValue("nwkAddress", nodes().at(i)->shortAddress());
|
ZigbeeNode *node = nodes().at(x);
|
||||||
settings.setValue("ieeeAddress", nodes().at(i)->extendedAddress().toString());
|
settings.setValue("nwkAddress", node->shortAddress());
|
||||||
|
settings.setValue("ieeeAddress", node->extendedAddress().toString());
|
||||||
// TODO: save the rest of the node
|
// TODO: save the rest of the node
|
||||||
|
|
||||||
|
// Input clusters
|
||||||
|
settings.beginWriteArray("inputCluster");
|
||||||
|
for (int i = 0; i < node->inputClusters().count(); i++) {
|
||||||
|
settings.setArrayIndex(i);
|
||||||
|
ZigbeeCluster *cluster = node->inputClusters().at(i);
|
||||||
|
settings.setValue("id", static_cast<int>(cluster->clusterId()));
|
||||||
|
settings.beginWriteArray("attributes");
|
||||||
|
|
||||||
|
settings.beginWriteArray("attributes");
|
||||||
|
for (int j = 0; j < cluster->attributes().count(); j++) {
|
||||||
|
settings.setArrayIndex(j);
|
||||||
|
ZigbeeClusterAttribute attribute = cluster->attributes().at(j);
|
||||||
|
settings.setValue("id", attribute.id());
|
||||||
|
settings.setValue("dataType", static_cast<int>(attribute.dataType()));
|
||||||
|
settings.setValue("data", attribute.data());
|
||||||
|
}
|
||||||
|
settings.endArray();
|
||||||
|
}
|
||||||
|
settings.endArray();
|
||||||
|
|
||||||
|
// Output clusters
|
||||||
|
settings.beginWriteArray("outputCluster");
|
||||||
|
for (int i = 0; i < node->outputClusters().count(); i++) {
|
||||||
|
settings.setArrayIndex(i);
|
||||||
|
ZigbeeCluster *cluster = node->outputClusters().at(i);
|
||||||
|
settings.setValue("id", static_cast<int>(cluster->clusterId()));
|
||||||
|
settings.beginWriteArray("attributes");
|
||||||
|
|
||||||
|
settings.beginWriteArray("attributes");
|
||||||
|
for (int j = 0; j < cluster->attributes().count(); j++) {
|
||||||
|
settings.setArrayIndex(j);
|
||||||
|
ZigbeeClusterAttribute attribute = cluster->attributes().at(j);
|
||||||
|
settings.setValue("id", attribute.id());
|
||||||
|
settings.setValue("dataType", static_cast<int>(attribute.dataType()));
|
||||||
|
settings.setValue("data", attribute.data());
|
||||||
|
}
|
||||||
|
settings.endArray();
|
||||||
|
}
|
||||||
|
settings.endArray();
|
||||||
}
|
}
|
||||||
settings.endArray();
|
settings.endArray();
|
||||||
}
|
}
|
||||||
@ -178,27 +231,78 @@ void ZigbeeNetwork::loadNetwork()
|
|||||||
qCDebug(dcZigbeeNetwork()) << "Load current network configuration from" << m_settingsFileName;
|
qCDebug(dcZigbeeNetwork()) << "Load current network configuration from" << m_settingsFileName;
|
||||||
QSettings settings(m_settingsFileName, QSettings::IniFormat, this);
|
QSettings settings(m_settingsFileName, QSettings::IniFormat, this);
|
||||||
settings.beginGroup("Network");
|
settings.beginGroup("Network");
|
||||||
quint64 extendedPanId = static_cast<quint64>(settings.value("panId", 0).toUInt());
|
quint64 extendedPanId = static_cast<quint64>(settings.value("panId", 0).toULongLong());
|
||||||
if (extendedPanId == 0) {
|
if (extendedPanId == 0) {
|
||||||
extendedPanId = ZigbeeUtils::generateRandomPanId();
|
extendedPanId = ZigbeeUtils::generateRandomPanId();
|
||||||
qCDebug(dcZigbeeNetwork()) << "Create new PAN id" << extendedPanId;
|
qCDebug(dcZigbeeNetwork()) << "Create new PAN ID" << extendedPanId;
|
||||||
}
|
}
|
||||||
setExtendedPanId(extendedPanId);
|
setExtendedPanId(extendedPanId);
|
||||||
setChannel(settings.value("channel", 0).toUInt());
|
setChannel(settings.value("channel", 0).toUInt());
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
int nodesCount = settings.beginReadArray("Nodes");
|
int nodesCount = settings.beginReadArray("Nodes");
|
||||||
for (int i = 0; i < nodesCount; i++) {
|
for (int x = 0; x < nodesCount; x++) {
|
||||||
settings.setArrayIndex(i);
|
settings.setArrayIndex(x);
|
||||||
ZigbeeNode *node = new ZigbeeNode(this);
|
ZigbeeNode *node = createNode();
|
||||||
node->setShortAddress(static_cast<quint16>(settings.value("nwkAddress", 0).toUInt()));
|
node->setShortAddress(static_cast<quint16>(settings.value("nwkAddress", 0).toUInt()));
|
||||||
node->setExtendedAddress(ZigbeeAddress(settings.value("ieeeAddress").toString()));
|
node->setExtendedAddress(ZigbeeAddress(settings.value("ieeeAddress").toString()));
|
||||||
// TODO: load the rest of the node
|
// TODO: load the rest of the node
|
||||||
|
|
||||||
|
// Input clusters
|
||||||
|
int inputClusterCount =settings.beginReadArray("inputCluster");
|
||||||
|
for (int i = 0; i < inputClusterCount; i++) {
|
||||||
|
settings.setArrayIndex(i);
|
||||||
|
Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(settings.value("id", 0).toInt());
|
||||||
|
settings.beginWriteArray("attributes");
|
||||||
|
|
||||||
|
int attributeCount = settings.beginReadArray("attributes");
|
||||||
|
if (attributeCount == 0) {
|
||||||
|
node->setClusterAttribute(clusterId);
|
||||||
|
} else {
|
||||||
|
for (int j = 0; j < attributeCount; j++) {
|
||||||
|
settings.setArrayIndex(i);
|
||||||
|
ZigbeeClusterAttribute attribute;
|
||||||
|
quint16 id = static_cast<quint16>(settings.value("id", 0).toInt());
|
||||||
|
Zigbee::DataType dataType = static_cast<Zigbee::DataType>(settings.value("dataType", 0).toInt());
|
||||||
|
QByteArray data = settings.value("data").toByteArray();
|
||||||
|
node->setClusterAttribute(clusterId, ZigbeeClusterAttribute(id, dataType, data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settings.endArray();
|
||||||
|
}
|
||||||
|
settings.endArray();
|
||||||
|
|
||||||
|
// Output clusters
|
||||||
|
int outputClusterCount =settings.beginReadArray("outputCluster");
|
||||||
|
for (int i = 0; i < outputClusterCount; i++) {
|
||||||
|
settings.setArrayIndex(i);
|
||||||
|
Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(settings.value("id", 0).toInt());
|
||||||
|
settings.beginWriteArray("attributes");
|
||||||
|
|
||||||
|
int attributeCount = settings.beginReadArray("attributes");
|
||||||
|
if (attributeCount == 0) {
|
||||||
|
node->setClusterAttribute(clusterId);
|
||||||
|
} else {
|
||||||
|
for (int j = 0; j < attributeCount; j++) {
|
||||||
|
settings.setArrayIndex(i);
|
||||||
|
ZigbeeClusterAttribute attribute;
|
||||||
|
quint16 id = static_cast<quint16>(settings.value("id", 0).toInt());
|
||||||
|
Zigbee::DataType dataType = static_cast<Zigbee::DataType>(settings.value("dataType", 0).toInt());
|
||||||
|
QByteArray data = settings.value("data").toByteArray();
|
||||||
|
node->setClusterAttribute(clusterId, ZigbeeClusterAttribute(id, dataType, data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.endArray();
|
||||||
|
}
|
||||||
|
settings.endArray();
|
||||||
|
|
||||||
|
node->setState(StateInitialized);
|
||||||
addNodeInternally(node);
|
addNodeInternally(node);
|
||||||
}
|
}
|
||||||
settings.endArray();
|
settings.endArray();
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Extended PAN Id:" << m_extendedPanId << ZigbeeUtils::convertUint64ToHexString(m_extendedPanId);
|
qCDebug(dcZigbeeNetwork()) << "Extended PAN ID:" << m_extendedPanId << ZigbeeUtils::convertUint64ToHexString(m_extendedPanId);
|
||||||
qCDebug(dcZigbeeNetwork()) << "Channel" << m_channel;
|
qCDebug(dcZigbeeNetwork()) << "Channel" << m_channel;
|
||||||
qCDebug(dcZigbeeNetwork()) << QStringLiteral("Nodes: (%1)").arg(m_nodes.count());
|
qCDebug(dcZigbeeNetwork()) << QStringLiteral("Nodes: (%1)").arg(m_nodes.count());
|
||||||
foreach (ZigbeeNode *node, nodes()) {
|
foreach (ZigbeeNode *node, nodes()) {
|
||||||
@ -206,16 +310,21 @@ void ZigbeeNetwork::loadNetwork()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ZigbeeNetwork::addNode(ZigbeeNode *node)
|
void ZigbeeNetwork::addNode(ZigbeeNode *node)
|
||||||
{
|
{
|
||||||
if (hasNode(node->extendedAddress())) {
|
addNodeInternally(node);
|
||||||
qCWarning(dcZigbeeNetwork()) << "The node" << node << "has already been added.";
|
saveNetwork();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNetwork::addUnitializedNode(ZigbeeNode *node)
|
||||||
|
{
|
||||||
|
if (m_uninitializedNodes.contains(node)) {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "The uninitialized node" << node << "has already been added.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_nodes.append(node);
|
m_uninitializedNodes.append(node);
|
||||||
emit nodeAdded(node);
|
|
||||||
saveNetwork();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNetwork::addNodeInternally(ZigbeeNode *node)
|
void ZigbeeNetwork::addNodeInternally(ZigbeeNode *node)
|
||||||
@ -231,13 +340,7 @@ void ZigbeeNetwork::addNodeInternally(ZigbeeNode *node)
|
|||||||
|
|
||||||
void ZigbeeNetwork::removeNode(ZigbeeNode *node)
|
void ZigbeeNetwork::removeNode(ZigbeeNode *node)
|
||||||
{
|
{
|
||||||
if (!m_nodes.contains(node)) {
|
removeNodeInternally(node);
|
||||||
qCWarning(dcZigbeeNetwork()) << "Try to remove node" << node << "but not in the node list.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_nodes.removeAll(node);
|
|
||||||
emit nodeRemoved(node);
|
|
||||||
saveNetwork();
|
saveNetwork();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,6 +356,13 @@ void ZigbeeNetwork::removeNodeInternally(ZigbeeNode *node)
|
|||||||
node->deleteLater();
|
node->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeNode *ZigbeeNetwork::createNode()
|
||||||
|
{
|
||||||
|
ZigbeeNode *node = new ZigbeeNode(this);
|
||||||
|
connect(node, &ZigbeeNode::stateChanged, this, &ZigbeeNetwork::onNodeStateChanged);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeNetwork::clearSettings()
|
void ZigbeeNetwork::clearSettings()
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeNetwork()) << "Clear network settings";
|
qCDebug(dcZigbeeNetwork()) << "Clear network settings";
|
||||||
@ -296,3 +406,12 @@ void ZigbeeNetwork::setError(ZigbeeNetwork::Error error)
|
|||||||
emit errorOccured(m_error);
|
emit errorOccured(m_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZigbeeNetwork::onNodeStateChanged(ZigbeeNode::State state)
|
||||||
|
{
|
||||||
|
ZigbeeNode *node = qobject_cast<ZigbeeNode *>(sender());
|
||||||
|
if (state == ZigbeeNode::StateInitialized && m_uninitializedNodes.contains(node)) {
|
||||||
|
m_uninitializedNodes.removeAll(node);
|
||||||
|
addNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -87,15 +87,19 @@ private:
|
|||||||
|
|
||||||
QString m_settingsFileName = "/etc/nymea/nymea-zigbee.conf";
|
QString m_settingsFileName = "/etc/nymea/nymea-zigbee.conf";
|
||||||
QList<ZigbeeNode *> m_nodes;
|
QList<ZigbeeNode *> m_nodes;
|
||||||
|
QList<ZigbeeNode *> m_uninitializedNodes;
|
||||||
|
|
||||||
void saveNetwork();
|
void saveNetwork();
|
||||||
void loadNetwork();
|
void loadNetwork();
|
||||||
|
void addNodeInternally(ZigbeeNode *node);
|
||||||
|
void removeNodeInternally(ZigbeeNode *node);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void addNode(ZigbeeNode *node);
|
void addNode(ZigbeeNode *node);
|
||||||
void addNodeInternally(ZigbeeNode *node);
|
void addUnitializedNode(ZigbeeNode *node);
|
||||||
void removeNode(ZigbeeNode *node);
|
void removeNode(ZigbeeNode *node);
|
||||||
void removeNodeInternally(ZigbeeNode *node);
|
|
||||||
|
ZigbeeNode *createNode();
|
||||||
|
|
||||||
void clearSettings();
|
void clearSettings();
|
||||||
|
|
||||||
@ -118,6 +122,9 @@ signals:
|
|||||||
void stateChanged(State state);
|
void stateChanged(State state);
|
||||||
void errorOccured(Error error);
|
void errorOccured(Error error);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onNodeStateChanged(ZigbeeNode::State state);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void startNetwork() = 0;
|
virtual void startNetwork() = 0;
|
||||||
virtual void stopNetwork() = 0;
|
virtual void stopNetwork() = 0;
|
||||||
|
|||||||
@ -480,8 +480,7 @@ void ZigbeeNetworkManager::processNetworkFormed(const ZigbeeInterfaceMessage &me
|
|||||||
qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(extendedAddress);
|
qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(extendedAddress);
|
||||||
qCDebug(dcZigbeeNetwork()) << " Channel:" << channel;
|
qCDebug(dcZigbeeNetwork()) << " Channel:" << channel;
|
||||||
qCDebug(dcZigbeeNetwork()) << " Extended PAN ID:" << extendedPanId();
|
qCDebug(dcZigbeeNetwork()) << " Extended PAN ID:" << extendedPanId();
|
||||||
qCDebug(dcZigbeeNetwork()) << " Permit joining" << permitJoining();
|
qCDebug(dcZigbeeNetwork()) << " Permit joining:" << permitJoining();
|
||||||
|
|
||||||
|
|
||||||
m_networkRunning = true;
|
m_networkRunning = true;
|
||||||
|
|
||||||
@ -490,7 +489,7 @@ void ZigbeeNetworkManager::processNetworkFormed(const ZigbeeInterfaceMessage &me
|
|||||||
setExtendedAddress(ZigbeeAddress(extendedAddress));
|
setExtendedAddress(ZigbeeAddress(extendedAddress));
|
||||||
setChannel(channel);
|
setChannel(channel);
|
||||||
|
|
||||||
addNode(this);
|
addUnitializedNode(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNetworkManager::onCommandEnableWhitelistFinished()
|
void ZigbeeNetworkManager::onCommandEnableWhitelistFinished()
|
||||||
@ -519,42 +518,40 @@ void ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished()
|
|||||||
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
|
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
|
||||||
qCDebug(dcZigbeeController()) << reply->additionalMessage();
|
qCDebug(dcZigbeeController()) << reply->additionalMessage();
|
||||||
|
|
||||||
quint8 sequenceNumber = static_cast<quint8>(reply->additionalMessage().data().at(0));
|
|
||||||
quint8 status = static_cast<quint8>(reply->additionalMessage().data().at(1));
|
|
||||||
|
|
||||||
Q_UNUSED(sequenceNumber)
|
QByteArray data = reply->additionalMessage().data();
|
||||||
Q_UNUSED(status)
|
|
||||||
|
|
||||||
quint16 shortAddress = static_cast<quint16>(reply->additionalMessage().data().at(2));
|
quint8 sequenceNumber = 0;
|
||||||
shortAddress <<= 8;
|
quint8 status = 0;
|
||||||
shortAddress |= reply->additionalMessage().data().at(3);
|
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;
|
||||||
|
|
||||||
quint16 manufacturerCode = static_cast<quint16>(reply->additionalMessage().data().at(4));
|
QDataStream stream(&data, QIODevice::ReadOnly);
|
||||||
manufacturerCode <<= 8;
|
stream >> sequenceNumber;
|
||||||
manufacturerCode |= reply->additionalMessage().data().at(5);
|
stream >> status;
|
||||||
|
stream >> shortAddress;
|
||||||
quint16 maximalRxSize = static_cast<quint16>(reply->additionalMessage().data().at(6));
|
stream >> manufacturerCode;
|
||||||
maximalRxSize <<= 8;
|
stream >> maximalRxSize;
|
||||||
maximalRxSize |= reply->additionalMessage().data().at(7);
|
stream >> maximalTxSize;
|
||||||
|
stream >> serverMask;
|
||||||
quint16 maximalTxSize = static_cast<quint16>(reply->additionalMessage().data().at(8));
|
stream >> descriptorFlag;
|
||||||
maximalTxSize <<= 8;
|
stream >> macFlags;
|
||||||
maximalTxSize |= reply->additionalMessage().data().at(9);
|
stream >> maxBufferSize;
|
||||||
|
stream >> bitField;
|
||||||
quint16 serverMask = static_cast<quint16>(reply->additionalMessage().data().at(10));
|
|
||||||
serverMask <<= 8;
|
|
||||||
serverMask |= reply->additionalMessage().data().at(11);
|
|
||||||
|
|
||||||
quint8 descriptorFlag = static_cast<quint8>(reply->additionalMessage().data().at(12));
|
|
||||||
quint8 macFlags = static_cast<quint8>(reply->additionalMessage().data().at(13));
|
|
||||||
quint8 maxBufferSize = static_cast<quint8>(reply->additionalMessage().data().at(14));
|
|
||||||
|
|
||||||
quint16 bitField = static_cast<quint16>(reply->additionalMessage().data().at(15));
|
|
||||||
bitField <<= 8;
|
|
||||||
bitField |= reply->additionalMessage().data().at(16);
|
|
||||||
|
|
||||||
// Get node object
|
// Get node object
|
||||||
ZigbeeNode *node = getZigbeeNode(shortAddress);
|
ZigbeeNode *node = getZigbeeNode(shortAddress);
|
||||||
|
if (!node) {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "Could not find node for address" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Set node data
|
// Set node data
|
||||||
node->setManufacturerCode(manufacturerCode);
|
node->setManufacturerCode(manufacturerCode);
|
||||||
@ -570,7 +567,7 @@ void ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished()
|
|||||||
if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
||||||
node->setNodeType(NodeTypeCoordinator);
|
node->setNodeType(NodeTypeCoordinator);
|
||||||
} else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
} else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
||||||
node->setNodeType(NodeTypeCoordinator);
|
node->setNodeType(NodeTypeRouter);
|
||||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
} else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
||||||
node->setNodeType(NodeTypeEndDevice);
|
node->setNodeType(NodeTypeEndDevice);
|
||||||
}
|
}
|
||||||
@ -625,36 +622,39 @@ void ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished()
|
|||||||
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
|
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
|
||||||
qCDebug(dcZigbeeController()) << reply->additionalMessage();
|
qCDebug(dcZigbeeController()) << reply->additionalMessage();
|
||||||
|
|
||||||
quint8 sequenceNumber = static_cast<quint8>(reply->additionalMessage().data().at(0));
|
QByteArray data = reply->additionalMessage().data();
|
||||||
quint8 status = static_cast<quint8>(reply->additionalMessage().data().at(1));
|
|
||||||
|
|
||||||
quint16 nwkAddress = static_cast<quint16>(reply->additionalMessage().data().at(2));
|
quint8 sequenceNumber = 0;
|
||||||
nwkAddress <<= 8;
|
quint8 status = 0;
|
||||||
nwkAddress |= reply->additionalMessage().data().at(3);
|
quint16 shortAddress = 0;
|
||||||
|
quint8 length = 0;
|
||||||
|
quint8 endPoint = 0;
|
||||||
|
quint16 profileId = 0;
|
||||||
|
quint16 deviceId = 0;
|
||||||
|
quint8 bitField = 0;
|
||||||
|
quint8 inputClusterCount = 0;
|
||||||
|
quint8 outputClusterCount = 0;
|
||||||
|
|
||||||
quint8 length = static_cast<quint8>(reply->additionalMessage().data().at(4));
|
QDataStream stream(&data, QIODevice::ReadOnly);
|
||||||
|
stream >> sequenceNumber;
|
||||||
|
stream >> status;
|
||||||
|
stream >> shortAddress;
|
||||||
|
stream >> length;
|
||||||
|
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
qCWarning(dcZigbeeNetwork()) << "Length 0";
|
qCWarning(dcZigbeeNetwork()) << "Simple node descriptior has a length of 0.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 endPoint = static_cast<quint8>(reply->additionalMessage().data().at(5));
|
stream >> endPoint;
|
||||||
|
stream >> profileId;
|
||||||
quint16 profileId = static_cast<quint16>(reply->additionalMessage().data().at(6));
|
stream >> deviceId;
|
||||||
profileId <<= 8;
|
stream >> bitField;
|
||||||
profileId |= reply->additionalMessage().data().at(7);
|
|
||||||
|
|
||||||
quint16 deviceId = static_cast<quint16>(reply->additionalMessage().data().at(8));
|
|
||||||
deviceId <<= 8;
|
|
||||||
deviceId |= reply->additionalMessage().data().at(9);
|
|
||||||
|
|
||||||
quint8 bitField = static_cast<quint8>(reply->additionalMessage().data().at(10));
|
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Node simple descriptor:";
|
qCDebug(dcZigbeeNetwork()) << "Node simple descriptor:";
|
||||||
qCDebug(dcZigbeeNetwork()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
|
qCDebug(dcZigbeeNetwork()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
|
||||||
qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
|
qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
|
||||||
qCDebug(dcZigbeeNetwork()) << " Nwk address:" << ZigbeeUtils::convertUint16ToHexString(nwkAddress);
|
qCDebug(dcZigbeeNetwork()) << " Nwk address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
|
||||||
qCDebug(dcZigbeeNetwork()) << " Lenght:" << ZigbeeUtils::convertByteToHexString(length);
|
qCDebug(dcZigbeeNetwork()) << " Lenght:" << ZigbeeUtils::convertByteToHexString(length);
|
||||||
qCDebug(dcZigbeeNetwork()) << " End Point:" << ZigbeeUtils::convertByteToHexString(endPoint);
|
qCDebug(dcZigbeeNetwork()) << " End Point:" << ZigbeeUtils::convertByteToHexString(endPoint);
|
||||||
qCDebug(dcZigbeeNetwork()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast<Zigbee::ZigbeeProfile>(profileId));
|
qCDebug(dcZigbeeNetwork()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast<Zigbee::ZigbeeProfile>(profileId));
|
||||||
@ -667,30 +667,40 @@ void ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished()
|
|||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << " Bit field:" << ZigbeeUtils::convertByteToHexString(bitField);
|
qCDebug(dcZigbeeNetwork()) << " Bit field:" << ZigbeeUtils::convertByteToHexString(bitField);
|
||||||
|
|
||||||
quint8 inputClusterCount = static_cast<quint8>(reply->additionalMessage().data().at(10));
|
stream >> inputClusterCount;
|
||||||
|
qCDebug(dcZigbeeNetwork()) << " Input clusters: (" << inputClusterCount << ")";
|
||||||
qCDebug(dcZigbeeNetwork()) << " Input clusters:";
|
for (int i = 0; i < inputClusterCount; i+=1) {
|
||||||
QByteArray inputClusterListData = reply->additionalMessage().data().mid(11, inputClusterCount * 2);
|
quint16 clusterId = 0;
|
||||||
for (int i = 0; i < inputClusterListData.count(); i+=2) {
|
stream >> clusterId;
|
||||||
quint16 clusterId = static_cast<quint16>(inputClusterListData.at(i));
|
|
||||||
clusterId <<= 8;
|
|
||||||
clusterId |= inputClusterListData .at(i+1);
|
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
qCDebug(dcZigbeeNetwork()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 outputClusterCount = static_cast<quint8>(reply->additionalMessage().data().at(12 + inputClusterCount * 2));
|
stream >> outputClusterCount;
|
||||||
|
qCDebug(dcZigbeeNetwork()) << " Output clusters: (" << outputClusterCount << ")";
|
||||||
qCDebug(dcZigbeeNetwork()) << " Output clusters:";
|
for (int i = 0; i < outputClusterCount; i+=1) {
|
||||||
QByteArray outputClusterListData = reply->additionalMessage().data().mid(12 + inputClusterCount * 2, outputClusterCount * 2);
|
if (stream.atEnd()) {
|
||||||
for (int i = 0; i < outputClusterListData.count(); i+=2) {
|
qCWarning(dcZigbeeNode()) << "Data stream already at the end but more data expected. Looks like the firmware doesn't provide more data.";
|
||||||
quint16 clusterId = static_cast<quint16>(outputClusterListData.at(i));
|
break;
|
||||||
clusterId <<= 8;
|
}
|
||||||
clusterId |= outputClusterListData .at(i+1);
|
|
||||||
|
|
||||||
|
quint16 clusterId = 0;
|
||||||
|
stream >> clusterId;
|
||||||
qCDebug(dcZigbeeNetwork()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
qCDebug(dcZigbeeNetwork()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get node object
|
||||||
|
ZigbeeNode *node = getZigbeeNode(shortAddress);
|
||||||
|
if (!node) {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "Could not find node for address" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress);
|
||||||
|
if (m_startingState == StartingStateReadSimpleDescriptor) setStartingState(StartingStateReadPowerDescriptor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set node data
|
||||||
|
node->setEndPoint(endPoint);
|
||||||
|
node->setZigbeeProfile(static_cast<Zigbee::ZigbeeProfile>(profileId));
|
||||||
|
node->setDeviceId(deviceId);
|
||||||
|
|
||||||
if (m_startingState == StartingStateReadSimpleDescriptor) setStartingState(StartingStateReadPowerDescriptor);
|
if (m_startingState == StartingStateReadSimpleDescriptor) setStartingState(StartingStateReadPowerDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,8 +709,24 @@ void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished()
|
|||||||
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
|
// Note: get the short address from the request data
|
||||||
|
QByteArray requestData = reply->request().message().data();
|
||||||
|
quint16 shortAddress;
|
||||||
|
QDataStream stream(&requestData, QIODevice::ReadOnly);
|
||||||
|
stream >> shortAddress;
|
||||||
|
|
||||||
if (reply->status() != ZigbeeInterfaceReply::Success) {
|
if (reply->status() != ZigbeeInterfaceReply::Success) {
|
||||||
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
|
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
|
||||||
|
// Note: the power descriptor is the last request from the initialization
|
||||||
|
ZigbeeNode *node = getZigbeeNode(shortAddress);
|
||||||
|
if (!node) {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "Could not find node for address" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress);
|
||||||
|
if (m_startingState == StartingStateReadSimpleDescriptor) setStartingState(StartingStateReadPowerDescriptor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (node->state() != ZigbeeNode::StateInitialized) {
|
||||||
|
node->setState(ZigbeeNode::StateInitialized);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,19 +738,20 @@ void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished()
|
|||||||
|
|
||||||
quint16 bitField = static_cast<quint16>(reply->additionalMessage().data().at(2));
|
quint16 bitField = static_cast<quint16>(reply->additionalMessage().data().at(2));
|
||||||
bitField <<= 8;
|
bitField <<= 8;
|
||||||
bitField |= reply->additionalMessage().data().at(3);
|
bitField |= static_cast<quint8>(reply->additionalMessage().data().at(3));
|
||||||
|
|
||||||
// Bit 0 - 3 Power mode
|
// Bit 0 - 3 Power mode
|
||||||
// 0000: Receiver configured according to “Receiver on when idle” MAC flag in the Node Descriptor
|
// 0000: Receiver configured according to “Receiver on when idle” MAC flag in the Node Descriptor
|
||||||
// 0001: Receiver switched on periodically
|
// 0001: Receiver switched on periodically
|
||||||
// 0010: Receiver switched on when stimulated, e.g. by pressing a button
|
// 0010: Receiver switched on when stimulated, e.g. by pressing a button
|
||||||
|
|
||||||
|
ZigbeeNode::PowerMode powerMode = PowerModeAlwaysOn;
|
||||||
if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
||||||
m_powerMode = PowerModeAlwaysOn;
|
powerMode = PowerModeAlwaysOn;
|
||||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
} else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
||||||
m_powerMode = PowerModeOnPeriodically;
|
powerMode = PowerModeOnPeriodically;
|
||||||
} else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
} else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
||||||
m_powerMode = PowerModeOnWhenStimulated;
|
powerMode = PowerModeOnWhenStimulated;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bit 4 - 7 Available power sources
|
// Bit 4 - 7 Available power sources
|
||||||
@ -733,21 +760,23 @@ void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished()
|
|||||||
// Bit 2: Disposable battery
|
// Bit 2: Disposable battery
|
||||||
// Bit 4: Reserved
|
// Bit 4: Reserved
|
||||||
|
|
||||||
|
QList<ZigbeeNode::PowerSource> availablePowerSources;
|
||||||
if (ZigbeeUtils::checkBitUint16(bitField, 4)) {
|
if (ZigbeeUtils::checkBitUint16(bitField, 4)) {
|
||||||
m_availablePowerSources.append(PowerSourcePermanentMainSupply);
|
availablePowerSources.append(PowerSourcePermanentMainSupply);
|
||||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 5)) {
|
} else if (ZigbeeUtils::checkBitUint16(bitField, 5)) {
|
||||||
m_availablePowerSources.append(PowerSourceRecharchableBattery);
|
availablePowerSources.append(PowerSourceRecharchableBattery);
|
||||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 6)) {
|
} else if (ZigbeeUtils::checkBitUint16(bitField, 6)) {
|
||||||
m_availablePowerSources.append(PowerSourceDisposableBattery);
|
availablePowerSources.append(PowerSourceDisposableBattery);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bit 8 - 11 Active source: according to the same schema as available power sources
|
// Bit 8 - 11 Active source: according to the same schema as available power sources
|
||||||
|
ZigbeeNode::PowerSource powerSource = PowerSourcePermanentMainSupply;
|
||||||
if (ZigbeeUtils::checkBitUint16(bitField, 8)) {
|
if (ZigbeeUtils::checkBitUint16(bitField, 8)) {
|
||||||
m_powerSource = PowerSourcePermanentMainSupply;
|
powerSource = PowerSourcePermanentMainSupply;
|
||||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 9)) {
|
} else if (ZigbeeUtils::checkBitUint16(bitField, 9)) {
|
||||||
m_powerSource = PowerSourceRecharchableBattery;
|
powerSource = PowerSourceRecharchableBattery;
|
||||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 10)) {
|
} else if (ZigbeeUtils::checkBitUint16(bitField, 10)) {
|
||||||
m_powerSource = PowerSourceDisposableBattery;
|
powerSource = PowerSourceDisposableBattery;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bit 12 - 15: Battery level if available
|
// Bit 12 - 15: Battery level if available
|
||||||
@ -755,15 +784,15 @@ void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished()
|
|||||||
// 0100: Approximately 33%
|
// 0100: Approximately 33%
|
||||||
// 1000: Approximately 66%
|
// 1000: Approximately 66%
|
||||||
// 1100: Approximately 100% (near fully charged)
|
// 1100: Approximately 100% (near fully charged)
|
||||||
|
ZigbeeNode::PowerLevel powerLevel = PowerLevelCriticalLow;
|
||||||
if (!ZigbeeUtils::checkBitUint16(bitField, 14) && !ZigbeeUtils::checkBitUint16(bitField, 15)) {
|
if (!ZigbeeUtils::checkBitUint16(bitField, 14) && !ZigbeeUtils::checkBitUint16(bitField, 15)) {
|
||||||
m_powerLevel = PowerLevelCriticalLow;
|
powerLevel = PowerLevelCriticalLow;
|
||||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 14) && !ZigbeeUtils::checkBitUint16(bitField, 15)) {
|
} else if (ZigbeeUtils::checkBitUint16(bitField, 14) && !ZigbeeUtils::checkBitUint16(bitField, 15)) {
|
||||||
m_powerLevel = PowerLevelLow;
|
powerLevel = PowerLevelLow;
|
||||||
} else if (!ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) {
|
} else if (!ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) {
|
||||||
m_powerLevel = PowerLevelOk;
|
powerLevel = PowerLevelOk;
|
||||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) {
|
} else if (ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) {
|
||||||
m_powerLevel = PowerLevelFull;
|
powerLevel = PowerLevelFull;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Node power descriptor:";
|
qCDebug(dcZigbeeNetwork()) << "Node power descriptor:";
|
||||||
@ -772,12 +801,32 @@ void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished()
|
|||||||
qCDebug(dcZigbeeNetwork()) << " Bitfiled:" << ZigbeeUtils::convertUint16ToHexString(bitField);
|
qCDebug(dcZigbeeNetwork()) << " Bitfiled:" << ZigbeeUtils::convertUint16ToHexString(bitField);
|
||||||
qCDebug(dcZigbeeNetwork()) << " Power mode:" << m_powerMode;
|
qCDebug(dcZigbeeNetwork()) << " Power mode:" << m_powerMode;
|
||||||
qCDebug(dcZigbeeNetwork()) << " Available power sources:";
|
qCDebug(dcZigbeeNetwork()) << " Available power sources:";
|
||||||
foreach (const PowerSource &source, m_availablePowerSources) {
|
foreach (const PowerSource &source, availablePowerSources) {
|
||||||
qCDebug(dcZigbeeNetwork()) << " " << source;
|
qCDebug(dcZigbeeNetwork()) << " " << source;
|
||||||
}
|
}
|
||||||
qCDebug(dcZigbeeNetwork()) << " Power source:" << m_powerSource;
|
qCDebug(dcZigbeeNetwork()) << " Power source:" << powerSource;
|
||||||
qCDebug(dcZigbeeNetwork()) << " Power level:" << m_powerLevel;
|
qCDebug(dcZigbeeNetwork()) << " Power level:" << powerLevel;
|
||||||
|
|
||||||
|
// Get node object
|
||||||
|
ZigbeeNode *node = getZigbeeNode(shortAddress);
|
||||||
|
if (!node) {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "Could not find node for address" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress);
|
||||||
|
if (m_startingState == StartingStateReadSimpleDescriptor) setStartingState(StartingStateReadPowerDescriptor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set node data
|
||||||
|
node->setPowerMode(powerMode);
|
||||||
|
node->setPowerSource(powerSource);
|
||||||
|
node->setAvailablePowerSources(availablePowerSources);
|
||||||
|
node->setPowerLevel(powerLevel);
|
||||||
|
|
||||||
|
// Note: the power descriptor is the last request from the initialization
|
||||||
|
if (node->state() != ZigbeeNode::StateInitialized) {
|
||||||
|
node->setState(ZigbeeNode::StateInitialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: the power descriptor request for the coordinator is the last step from the network init process
|
||||||
if (m_startingState == StartingStateReadPowerDescriptor) {
|
if (m_startingState == StartingStateReadPowerDescriptor) {
|
||||||
setStartingState(StartingStateNone);
|
setStartingState(StartingStateNone);
|
||||||
setState(StateRunning);
|
setState(StateRunning);
|
||||||
@ -1013,7 +1062,7 @@ void ZigbeeNetworkManager::processDeviceAnnounce(const ZigbeeInterfaceMessage &m
|
|||||||
qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(ieeeAddress);
|
qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(ieeeAddress);
|
||||||
qCDebug(dcZigbeeNetwork()) << " Mac capabilities:" << ZigbeeUtils::convertByteToHexString(macCapabilitiesFlag);
|
qCDebug(dcZigbeeNetwork()) << " Mac capabilities:" << ZigbeeUtils::convertByteToHexString(macCapabilitiesFlag);
|
||||||
|
|
||||||
ZigbeeNode *node = new ZigbeeNode(this);
|
ZigbeeNode *node = createNode();
|
||||||
node->setShortAddress(shortAddress);
|
node->setShortAddress(shortAddress);
|
||||||
node->setExtendedAddress(ZigbeeAddress(ieeeAddress));
|
node->setExtendedAddress(ZigbeeAddress(ieeeAddress));
|
||||||
node->setMacCapabilitiesFlag(macCapabilitiesFlag);
|
node->setMacCapabilitiesFlag(macCapabilitiesFlag);
|
||||||
@ -1021,7 +1070,8 @@ void ZigbeeNetworkManager::processDeviceAnnounce(const ZigbeeInterfaceMessage &m
|
|||||||
qCDebug(dcZigbeeNetwork()) << " Node:" << node;
|
qCDebug(dcZigbeeNetwork()) << " Node:" << node;
|
||||||
|
|
||||||
// FIXME: check if node already added, and if we have to update it
|
// FIXME: check if node already added, and if we have to update it
|
||||||
addNode(node);
|
addUnitializedNode(node);
|
||||||
|
node->setState(StateInitializing);
|
||||||
|
|
||||||
ZigbeeInterfaceReply *reply = nullptr;
|
ZigbeeInterfaceReply *reply = nullptr;
|
||||||
reply = m_controller->commandAuthenticateDevice(node->extendedAddress(), securityConfiguration().globalTrustCenterLinkKey());
|
reply = m_controller->commandAuthenticateDevice(node->extendedAddress(), securityConfiguration().globalTrustCenterLinkKey());
|
||||||
@ -1071,8 +1121,13 @@ void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: find node and set attribute value
|
ZigbeeNode *node = getZigbeeNode(sourceAddress);
|
||||||
|
if (!node) {
|
||||||
|
qCWarning(dcZigbeeNode()) << "Received an attribute report from an unknown node. Ignoring data.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->setClusterAttribute(static_cast<Zigbee::ClusterId>(clusterId), ZigbeeClusterAttribute(attributeId, dataType, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNetworkManager::processLeaveIndication(const ZigbeeInterfaceMessage &message)
|
void ZigbeeNetworkManager::processLeaveIndication(const ZigbeeInterfaceMessage &message)
|
||||||
@ -1080,23 +1135,16 @@ void ZigbeeNetworkManager::processLeaveIndication(const ZigbeeInterfaceMessage &
|
|||||||
QByteArray data = message.data();
|
QByteArray data = message.data();
|
||||||
quint64 extendedAddress = 0;
|
quint64 extendedAddress = 0;
|
||||||
bool rejoining = 0;
|
bool rejoining = 0;
|
||||||
|
|
||||||
QDataStream stream(&data, QIODevice::ReadOnly);
|
QDataStream stream(&data, QIODevice::ReadOnly);
|
||||||
stream >> extendedAddress;
|
stream >> extendedAddress;
|
||||||
stream >> rejoining;
|
stream >> rejoining;
|
||||||
|
|
||||||
ZigbeeAddress address(extendedAddress);
|
ZigbeeAddress address(extendedAddress);
|
||||||
|
|
||||||
// ZigbeeAddress extendedAddress = ZigbeeAddress(ZigbeeUtils::convertByteArrayToUint64(message.data().mid(0, 8)));
|
|
||||||
// quint8 rejoining = static_cast<quint8>(message.data().at(9));
|
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Node leaving indication:" << address.toString() << "rejoining:" << rejoining;
|
qCDebug(dcZigbeeNetwork()) << "Node leaving indication:" << address.toString() << "rejoining:" << rejoining;
|
||||||
|
|
||||||
ZigbeeNode *node = getZigbeeNode(address);
|
ZigbeeNode *node = getZigbeeNode(address);
|
||||||
if (node) {
|
if (node) removeNode(node);
|
||||||
removeNode(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remove node
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNetworkManager::processRestartProvisioned(const ZigbeeInterfaceMessage &message)
|
void ZigbeeNetworkManager::processRestartProvisioned(const ZigbeeInterfaceMessage &message)
|
||||||
|
|||||||
@ -10,6 +10,11 @@ ZigbeeNode::ZigbeeNode(QObject *parent) :
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeNode::State ZigbeeNode::state() const
|
||||||
|
{
|
||||||
|
return m_state;
|
||||||
|
}
|
||||||
|
|
||||||
quint16 ZigbeeNode::shortAddress() const
|
quint16 ZigbeeNode::shortAddress() const
|
||||||
{
|
{
|
||||||
return m_shortAddress;
|
return m_shortAddress;
|
||||||
@ -50,6 +55,11 @@ quint16 ZigbeeNode::manufacturerCode() const
|
|||||||
return m_manufacturerCode;
|
return m_manufacturerCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quint16 ZigbeeNode::deviceId() const
|
||||||
|
{
|
||||||
|
return m_deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
bool ZigbeeNode::complexDescriptorAvailable() const
|
bool ZigbeeNode::complexDescriptorAvailable() const
|
||||||
{
|
{
|
||||||
return m_complexDescriptorAvailable;
|
return m_complexDescriptorAvailable;
|
||||||
@ -75,6 +85,36 @@ quint8 ZigbeeNode::maximumBufferSize() const
|
|||||||
return m_maximumBufferSize;
|
return m_maximumBufferSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<ZigbeeCluster *> ZigbeeNode::inputClusters() const
|
||||||
|
{
|
||||||
|
return m_inputClusters.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeCluster *ZigbeeNode::getInputCluster(Zigbee::ClusterId clusterId) const
|
||||||
|
{
|
||||||
|
return m_inputClusters.value(clusterId);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZigbeeNode::hasInputCluster(Zigbee::ClusterId clusterId) const
|
||||||
|
{
|
||||||
|
return m_inputClusters.keys().contains(clusterId);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ZigbeeCluster *> ZigbeeNode::outputClusters() const
|
||||||
|
{
|
||||||
|
return m_outputClusters.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZigbeeNode::hasOutputCluster(Zigbee::ClusterId clusterId) const
|
||||||
|
{
|
||||||
|
return m_outputClusters.keys().contains(clusterId);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeCluster *ZigbeeNode::getOutputCluster(Zigbee::ClusterId clusterId) const
|
||||||
|
{
|
||||||
|
return m_outputClusters.value(clusterId);
|
||||||
|
}
|
||||||
|
|
||||||
bool ZigbeeNode::isPrimaryTrustCenter() const
|
bool ZigbeeNode::isPrimaryTrustCenter() const
|
||||||
{
|
{
|
||||||
return m_isPrimaryTrustCenter;
|
return m_isPrimaryTrustCenter;
|
||||||
@ -170,6 +210,16 @@ ZigbeeNode::PowerLevel ZigbeeNode::powerLevel() const
|
|||||||
return m_powerLevel;
|
return m_powerLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZigbeeNode::setState(ZigbeeNode::State state)
|
||||||
|
{
|
||||||
|
if (m_state == state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
qCDebug(dcZigbeeNode()) << "State changed" << state;
|
||||||
|
m_state = state;
|
||||||
|
emit stateChanged(m_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//void ZigbeeNode::identify()
|
//void ZigbeeNode::identify()
|
||||||
//{
|
//{
|
||||||
@ -246,6 +296,11 @@ void ZigbeeNode::setManufacturerCode(quint16 manufacturerCode)
|
|||||||
m_manufacturerCode = manufacturerCode;
|
m_manufacturerCode = manufacturerCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZigbeeNode::setDeviceId(quint16 deviceId)
|
||||||
|
{
|
||||||
|
m_deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeNode::setMaximumRxSize(quint16 size)
|
void ZigbeeNode::setMaximumRxSize(quint16 size)
|
||||||
{
|
{
|
||||||
m_maximumRxSize = size;
|
m_maximumRxSize = size;
|
||||||
@ -303,6 +358,57 @@ void ZigbeeNode::setDescriptorFlag(quint8 descriptorFlag)
|
|||||||
m_extendedSimpleDescriptorListAvailable = ((descriptorFlag >> 1) & 0x01);
|
m_extendedSimpleDescriptorListAvailable = ((descriptorFlag >> 1) & 0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZigbeeNode::setPowerMode(ZigbeeNode::PowerMode powerMode)
|
||||||
|
{
|
||||||
|
m_powerMode = powerMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNode::setPowerSource(ZigbeeNode::PowerSource powerSource)
|
||||||
|
{
|
||||||
|
m_powerSource = powerSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNode::setAvailablePowerSources(QList<ZigbeeNode::PowerSource> availablePowerSources)
|
||||||
|
{
|
||||||
|
m_availablePowerSources = availablePowerSources;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNode::setPowerLevel(ZigbeeNode::PowerLevel powerLevel)
|
||||||
|
{
|
||||||
|
m_powerLevel = powerLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNode::setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute)
|
||||||
|
{
|
||||||
|
//qCDebug(dcZigbeeNode()) << this << "cluster attribute changed" << clusterId << attribute;
|
||||||
|
ZigbeeCluster *cluster = m_outputClusters.value(clusterId);
|
||||||
|
|
||||||
|
// Note: create the cluster if not there yet
|
||||||
|
bool clusterCreated = false;
|
||||||
|
if (!cluster) {
|
||||||
|
cluster = new ZigbeeCluster(clusterId, this);
|
||||||
|
qCWarning(dcZigbeeNode()) << "Created cluster" << cluster;
|
||||||
|
connect(cluster, &ZigbeeCluster::attributeChanged, this, &ZigbeeNode::onClusterAttributeChanged);
|
||||||
|
m_outputClusters.insert(clusterId, cluster);
|
||||||
|
clusterCreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the attribute if valid
|
||||||
|
if (attribute.isValid())
|
||||||
|
cluster->setAttribute(attribute);
|
||||||
|
|
||||||
|
if (clusterCreated)
|
||||||
|
emit clusterAdded(cluster);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNode::onClusterAttributeChanged(const ZigbeeClusterAttribute &attribute)
|
||||||
|
{
|
||||||
|
ZigbeeCluster *cluster = static_cast<ZigbeeCluster *>(sender());
|
||||||
|
qCDebug(dcZigbeeNode()) << "Cluster" << cluster << "attribute changed" << attribute;
|
||||||
|
emit clusterAttributeChanged(cluster, attribute);
|
||||||
|
}
|
||||||
|
|
||||||
//void ZigbeeNode::onRequestUserDescriptorFinished()
|
//void ZigbeeNode::onRequestUserDescriptorFinished()
|
||||||
//{
|
//{
|
||||||
// ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
// ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "zigbee.h"
|
#include "zigbee.h"
|
||||||
|
#include "zigbeecluster.h"
|
||||||
#include "zigbeeaddress.h"
|
#include "zigbeeaddress.h"
|
||||||
|
|
||||||
class ZigbeeNode : public QObject
|
class ZigbeeNode : public QObject
|
||||||
@ -14,6 +15,13 @@ class ZigbeeNode : public QObject
|
|||||||
friend class ZigbeeNetworkManager;
|
friend class ZigbeeNetworkManager;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum State {
|
||||||
|
StateUninitialized,
|
||||||
|
StateInitializing,
|
||||||
|
StateInitialized
|
||||||
|
};
|
||||||
|
Q_ENUM(State)
|
||||||
|
|
||||||
enum NodeType {
|
enum NodeType {
|
||||||
NodeTypeCoordinator = 0,
|
NodeTypeCoordinator = 0,
|
||||||
NodeTypeRouter = 1,
|
NodeTypeRouter = 1,
|
||||||
@ -63,7 +71,7 @@ public:
|
|||||||
};
|
};
|
||||||
Q_ENUM(PowerLevel)
|
Q_ENUM(PowerLevel)
|
||||||
|
|
||||||
ZigbeeNode(QObject *parent = nullptr);
|
State state() const;
|
||||||
|
|
||||||
quint16 shortAddress() const;
|
quint16 shortAddress() const;
|
||||||
ZigbeeAddress extendedAddress() const;
|
ZigbeeAddress extendedAddress() const;
|
||||||
@ -75,6 +83,7 @@ public:
|
|||||||
Relationship relationship() const;
|
Relationship relationship() const;
|
||||||
Zigbee::ZigbeeProfile profile() const;
|
Zigbee::ZigbeeProfile profile() const;
|
||||||
quint16 manufacturerCode() const;
|
quint16 manufacturerCode() const;
|
||||||
|
quint16 deviceId() const;
|
||||||
|
|
||||||
bool complexDescriptorAvailable() const;
|
bool complexDescriptorAvailable() const;
|
||||||
bool userDescriptorAvailable() const;
|
bool userDescriptorAvailable() const;
|
||||||
@ -83,6 +92,14 @@ public:
|
|||||||
quint16 maximumTxSize() const;
|
quint16 maximumTxSize() const;
|
||||||
quint8 maximumBufferSize() const;
|
quint8 maximumBufferSize() const;
|
||||||
|
|
||||||
|
QList<ZigbeeCluster *> inputClusters() const;
|
||||||
|
ZigbeeCluster *getInputCluster(Zigbee::ClusterId clusterId) const;
|
||||||
|
bool hasInputCluster(Zigbee::ClusterId clusterId) const;
|
||||||
|
|
||||||
|
QList<ZigbeeCluster *> outputClusters() const;
|
||||||
|
ZigbeeCluster *getOutputCluster(Zigbee::ClusterId clusterId) const;
|
||||||
|
bool hasOutputCluster(Zigbee::ClusterId clusterId) const;
|
||||||
|
|
||||||
// Server Mask
|
// Server Mask
|
||||||
bool isPrimaryTrustCenter() const;
|
bool isPrimaryTrustCenter() const;
|
||||||
bool isBackupTrustCenter() const;
|
bool isBackupTrustCenter() const;
|
||||||
@ -111,6 +128,12 @@ public:
|
|||||||
PowerLevel powerLevel() const;
|
PowerLevel powerLevel() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ZigbeeNode(QObject *parent = nullptr);
|
||||||
|
State m_state = StateUninitialized;
|
||||||
|
|
||||||
|
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_inputClusters;
|
||||||
|
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_outputClusters;
|
||||||
|
|
||||||
quint16 m_shortAddress = 0;
|
quint16 m_shortAddress = 0;
|
||||||
ZigbeeAddress m_extendedAddress;
|
ZigbeeAddress m_extendedAddress;
|
||||||
quint8 m_endPoint = 1;
|
quint8 m_endPoint = 1;
|
||||||
@ -120,6 +143,7 @@ private:
|
|||||||
Relationship m_relationship = Parent;
|
Relationship m_relationship = Parent;
|
||||||
Zigbee::ZigbeeProfile m_profile;
|
Zigbee::ZigbeeProfile m_profile;
|
||||||
quint16 m_manufacturerCode = 0;
|
quint16 m_manufacturerCode = 0;
|
||||||
|
quint16 m_deviceId = 0;
|
||||||
|
|
||||||
bool m_complexDescriptorAvailable = false;
|
bool m_complexDescriptorAvailable = false;
|
||||||
bool m_userDescriptorAvailable = false;
|
bool m_userDescriptorAvailable = false;
|
||||||
@ -156,6 +180,8 @@ private:
|
|||||||
bool m_extendedSimpleDescriptorListAvailable = false;
|
bool m_extendedSimpleDescriptorListAvailable = false;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void setState(State state);
|
||||||
|
|
||||||
void setShortAddress(const quint16 &shortAddress);
|
void setShortAddress(const quint16 &shortAddress);
|
||||||
void setExtendedAddress(const ZigbeeAddress &extendedAddress);
|
void setExtendedAddress(const ZigbeeAddress &extendedAddress);
|
||||||
void setEndPoint(quint8 endPoint);
|
void setEndPoint(quint8 endPoint);
|
||||||
@ -165,6 +191,7 @@ protected:
|
|||||||
void setRelationship(Relationship relationship);
|
void setRelationship(Relationship relationship);
|
||||||
void setZigbeeProfile(Zigbee::ZigbeeProfile profile);
|
void setZigbeeProfile(Zigbee::ZigbeeProfile profile);
|
||||||
void setManufacturerCode(quint16 manufacturerCode);
|
void setManufacturerCode(quint16 manufacturerCode);
|
||||||
|
void setDeviceId(quint16 deviceType);
|
||||||
|
|
||||||
void setMaximumRxSize(quint16 size);
|
void setMaximumRxSize(quint16 size);
|
||||||
void setMaximumTxSize(quint16 size);
|
void setMaximumTxSize(quint16 size);
|
||||||
@ -176,6 +203,22 @@ protected:
|
|||||||
void setMacCapabilitiesFlag(quint16 macFlag);
|
void setMacCapabilitiesFlag(quint16 macFlag);
|
||||||
void setDescriptorFlag(quint8 descriptorFlag);
|
void setDescriptorFlag(quint8 descriptorFlag);
|
||||||
|
|
||||||
|
void setPowerMode(PowerMode powerMode);
|
||||||
|
void setPowerSource(PowerSource powerSource);
|
||||||
|
void setAvailablePowerSources(QList<PowerSource> availablePowerSources);
|
||||||
|
void setPowerLevel(PowerLevel powerLevel);
|
||||||
|
|
||||||
|
// Cluster commands
|
||||||
|
void setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute = ZigbeeClusterAttribute());
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void stateChanged(State state);
|
||||||
|
void clusterAdded(ZigbeeCluster *cluster);
|
||||||
|
void clusterAttributeChanged(ZigbeeCluster *cluster, const ZigbeeClusterAttribute &attribute);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onClusterAttributeChanged(const ZigbeeClusterAttribute &attribute);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, ZigbeeNode *node);
|
QDebug operator<<(QDebug debug, ZigbeeNode *node);
|
||||||
|
|||||||
@ -11,6 +11,16 @@ ZigbeeSecurityConfiguration::ZigbeeSecurityConfiguration(const ZigbeeSecurityCon
|
|||||||
m_globalTrustCenterLinkKey = other.networkKey();
|
m_globalTrustCenterLinkKey = other.networkKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeSecurityConfiguration::ZigbeeSecurityMode ZigbeeSecurityConfiguration::zigbeeSecurityMode() const
|
||||||
|
{
|
||||||
|
return m_zigbeeSecurityMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeSecurityConfiguration::setZigbeeSecurityMode(ZigbeeSecurityConfiguration::ZigbeeSecurityMode zigbeeSecurityMode)
|
||||||
|
{
|
||||||
|
m_zigbeeSecurityMode = zigbeeSecurityMode;
|
||||||
|
}
|
||||||
|
|
||||||
QString ZigbeeSecurityConfiguration::networkKey() const
|
QString ZigbeeSecurityConfiguration::networkKey() const
|
||||||
{
|
{
|
||||||
return m_networkKey;
|
return m_networkKey;
|
||||||
@ -33,12 +43,14 @@ void ZigbeeSecurityConfiguration::setGlobalTrustCenterlinkKey(const QString &glo
|
|||||||
|
|
||||||
void ZigbeeSecurityConfiguration::clear()
|
void ZigbeeSecurityConfiguration::clear()
|
||||||
{
|
{
|
||||||
|
m_zigbeeSecurityMode = ZigbeeSecurityModeNone;
|
||||||
m_networkKey.clear();
|
m_networkKey.clear();
|
||||||
|
m_globalTrustCenterLinkKey = "5A6967426565416C6C69616E63653039";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZigbeeSecurityConfiguration::operator==(const ZigbeeSecurityConfiguration &other) const
|
bool ZigbeeSecurityConfiguration::operator==(const ZigbeeSecurityConfiguration &other) const
|
||||||
{
|
{
|
||||||
return m_networkKey == other.networkKey() && m_globalTrustCenterLinkKey == other.globalTrustCenterLinkKey();
|
return m_networkKey == other.networkKey() && m_globalTrustCenterLinkKey == other.globalTrustCenterLinkKey() && m_zigbeeSecurityMode == other.zigbeeSecurityMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZigbeeSecurityConfiguration::operator!=(const ZigbeeSecurityConfiguration &other) const
|
bool ZigbeeSecurityConfiguration::operator!=(const ZigbeeSecurityConfiguration &other) const
|
||||||
|
|||||||
@ -6,9 +6,18 @@
|
|||||||
class ZigbeeSecurityConfiguration
|
class ZigbeeSecurityConfiguration
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum ZigbeeSecurityMode {
|
||||||
|
ZigbeeSecurityModeNone,
|
||||||
|
ZigbeeSecurityModeNetworkLayer,
|
||||||
|
ZigbeeSecurityModeApplicationLayer
|
||||||
|
};
|
||||||
|
|
||||||
explicit ZigbeeSecurityConfiguration();
|
explicit ZigbeeSecurityConfiguration();
|
||||||
ZigbeeSecurityConfiguration(const ZigbeeSecurityConfiguration &other);
|
ZigbeeSecurityConfiguration(const ZigbeeSecurityConfiguration &other);
|
||||||
|
|
||||||
|
ZigbeeSecurityMode zigbeeSecurityMode() const;
|
||||||
|
void setZigbeeSecurityMode(ZigbeeSecurityMode zigbeeSecurityMode);
|
||||||
|
|
||||||
QString networkKey() const;
|
QString networkKey() const;
|
||||||
void setNetworkKey(const QString &networkKey);
|
void setNetworkKey(const QString &networkKey);
|
||||||
|
|
||||||
@ -21,6 +30,8 @@ public:
|
|||||||
bool operator!=(const ZigbeeSecurityConfiguration &other) const;
|
bool operator!=(const ZigbeeSecurityConfiguration &other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ZigbeeSecurityMode m_zigbeeSecurityMode = ZigbeeSecurityModeNone;
|
||||||
|
|
||||||
// This is the local network key
|
// This is the local network key
|
||||||
QString m_networkKey;
|
QString m_networkKey;
|
||||||
|
|
||||||
|
|||||||
@ -133,7 +133,6 @@ QString ZigbeeUtils::profileIdToString(const Zigbee::ZigbeeProfile &profileId)
|
|||||||
|
|
||||||
quint64 ZigbeeUtils::generateRandomPanId()
|
quint64 ZigbeeUtils::generateRandomPanId()
|
||||||
{
|
{
|
||||||
srand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch() / 1000));
|
qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch() / 1000));
|
||||||
srand(static_cast<uint>(qrand()));
|
|
||||||
return static_cast<quint64>((ULLONG_MAX - 0) * (qrand()/static_cast<double>(RAND_MAX)));
|
return static_cast<quint64>((ULLONG_MAX - 0) * (qrand()/static_cast<double>(RAND_MAX)));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user