Add cluster and attribute base classes and improve node initialization

This commit is contained in:
Simon Stürz 2019-05-16 02:54:17 +02:00
parent 2922a87449
commit 7745f09581
19 changed files with 725 additions and 132 deletions

View File

@ -14,6 +14,7 @@ ZigbeeInterface::ZigbeeInterface(QObject *parent) :
ZigbeeInterface::~ZigbeeInterface()
{
qCCritical(dcZigbeeInterface()) << "Destroy interface";
disable();
}
@ -127,14 +128,21 @@ void ZigbeeInterface::onReadyRead()
// Check message sanity
quint8 crc = calculateCrc(m_messageTypeValue, m_lengthValue, m_data);
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) {
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 {
// We got a valid message
ZigbeeInterfaceMessage message(messageType, m_data);
qCDebug(dcZigbeeInterface()) << "<--" << message << "|" << "crc:" << ZigbeeUtils::convertByteToHexString(m_crcValue) << ", length:" << ZigbeeUtils::convertUint16ToHexString(m_lengthValue);
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);
break;
@ -150,6 +158,7 @@ void ZigbeeInterface::onReadyRead()
// Read data bytes depending on the reading state
switch (m_readingState) {
case WaitForStart:
qCWarning(dcZigbeeInterfaceTraffic()) << "Wait for start but reviced data:" << byte;
break;
case WaitForTypeMsb:
m_messageTypeValue = byte;

View File

@ -11,6 +11,8 @@ SOURCES += \
interface/zigbeeinterfacerequest.cpp \
interface/zigbeeinterfacereply.cpp \
nxp/nxpzigbeenetworkmanager.cpp \
zigbeecluster.cpp \
zigbeeclusterattribute.cpp \
zigbeenetwork.cpp \
zigbeenetworkmanager.cpp \
zigbee.cpp \
@ -27,6 +29,8 @@ HEADERS += \
interface/zigbeeinterfacerequest.h \
interface/zigbeeinterfacereply.h \
nxp/nxpzigbeenetworkmanager.h \
zigbeecluster.h \
zigbeeclusterattribute.h \
zigbeenetwork.h \
zigbeenetworkmanager.h \
zigbee.h \

View File

@ -1,6 +1,7 @@
#include "loggingcategory.h"
Q_LOGGING_CATEGORY(dcZigbeeNetwork, "ZigbeeNetwork")
Q_LOGGING_CATEGORY(dcZigbeeNode, "ZigbeeNode")
Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface")
Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController")
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")

View File

@ -5,6 +5,7 @@
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetwork)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNode)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic)

View File

@ -216,6 +216,7 @@ public:
enum ClusterId {
// Basics
ClusterIdUnknown = 0xffff,
ClusterIdBasic = 0x0000,
ClusterIdPower = 0x0001,
ClusterIdDeviceTemperature = 0x0002,
@ -292,6 +293,24 @@ public:
};
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 {
// Lightning devices

View File

@ -12,6 +12,11 @@ ZigbeeBridgeController::ZigbeeBridgeController(QObject *parent) :
connect(m_interface, &ZigbeeInterface::messageReceived, this, &ZigbeeBridgeController::onMessageReceived);
}
ZigbeeBridgeController::~ZigbeeBridgeController()
{
qCDebug(dcZigbeeController()) << "Destroy controller";
}
bool ZigbeeBridgeController::available() const
{
return m_interface->available();
@ -247,7 +252,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandAuthenticateDevice(const Zi
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeAuthenticateDeviceRequest, data));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeAuthenticateDeviceResponse);
request.setDescription(QString("Authenticate device %1").arg(ieeeAddress.toString()));
request.setTimoutIntervall(5000);
request.setTimoutIntervall(2000);
return sendRequest(request);
}
@ -261,7 +266,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandNodeDescriptorRequest(quint
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeNodeDescriptorRequest, data));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeNodeDescriptorRsponse);
request.setDescription("Node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
request.setTimoutIntervall(10000);
request.setTimoutIntervall(5000);
return sendRequest(request);
}

View File

@ -16,6 +16,7 @@ class ZigbeeBridgeController : public QObject
Q_OBJECT
public:
explicit ZigbeeBridgeController(QObject *parent = nullptr);
~ZigbeeBridgeController();
bool available() const;

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

View 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

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

View 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

View File

@ -120,6 +120,12 @@ ZigbeeNode *ZigbeeNetwork::coordinatorNode() const
ZigbeeNode *ZigbeeNetwork::getZigbeeNode(quint16 shortAddress) const
{
foreach (ZigbeeNode *node, m_uninitializedNodes) {
if (node->shortAddress() == shortAddress) {
return node;
}
}
foreach (ZigbeeNode *node, m_nodes) {
if (node->shortAddress() == shortAddress) {
return node;
@ -131,6 +137,12 @@ ZigbeeNode *ZigbeeNetwork::getZigbeeNode(quint16 shortAddress) const
ZigbeeNode *ZigbeeNetwork::getZigbeeNode(const ZigbeeAddress &address) const
{
foreach (ZigbeeNode *node, m_uninitializedNodes) {
if (node->extendedAddress() == address) {
return node;
}
}
foreach (ZigbeeNode *node, m_nodes) {
if (node->extendedAddress() == address) {
return node;
@ -164,11 +176,52 @@ void ZigbeeNetwork::saveNetwork()
settings.endGroup();
settings.beginWriteArray("Nodes");
for (int i = 0; i < nodes().count(); i++) {
settings.setArrayIndex(i);
settings.setValue("nwkAddress", nodes().at(i)->shortAddress());
settings.setValue("ieeeAddress", nodes().at(i)->extendedAddress().toString());
for (int x = 0; x < nodes().count(); x++) {
settings.setArrayIndex(x);
ZigbeeNode *node = nodes().at(x);
settings.setValue("nwkAddress", node->shortAddress());
settings.setValue("ieeeAddress", node->extendedAddress().toString());
// 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();
}
@ -178,27 +231,78 @@ void ZigbeeNetwork::loadNetwork()
qCDebug(dcZigbeeNetwork()) << "Load current network configuration from" << m_settingsFileName;
QSettings settings(m_settingsFileName, QSettings::IniFormat, this);
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) {
extendedPanId = ZigbeeUtils::generateRandomPanId();
qCDebug(dcZigbeeNetwork()) << "Create new PAN id" << extendedPanId;
qCDebug(dcZigbeeNetwork()) << "Create new PAN ID" << extendedPanId;
}
setExtendedPanId(extendedPanId);
setChannel(settings.value("channel", 0).toUInt());
settings.endGroup();
int nodesCount = settings.beginReadArray("Nodes");
for (int i = 0; i < nodesCount; i++) {
settings.setArrayIndex(i);
ZigbeeNode *node = new ZigbeeNode(this);
for (int x = 0; x < nodesCount; x++) {
settings.setArrayIndex(x);
ZigbeeNode *node = createNode();
node->setShortAddress(static_cast<quint16>(settings.value("nwkAddress", 0).toUInt()));
node->setExtendedAddress(ZigbeeAddress(settings.value("ieeeAddress").toString()));
// 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);
}
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()) << QStringLiteral("Nodes: (%1)").arg(m_nodes.count());
foreach (ZigbeeNode *node, nodes()) {
@ -206,16 +310,21 @@ void ZigbeeNetwork::loadNetwork()
}
}
void ZigbeeNetwork::addNode(ZigbeeNode *node)
{
if (hasNode(node->extendedAddress())) {
qCWarning(dcZigbeeNetwork()) << "The node" << node << "has already been added.";
addNodeInternally(node);
saveNetwork();
}
void ZigbeeNetwork::addUnitializedNode(ZigbeeNode *node)
{
if (m_uninitializedNodes.contains(node)) {
qCWarning(dcZigbeeNetwork()) << "The uninitialized node" << node << "has already been added.";
return;
}
m_nodes.append(node);
emit nodeAdded(node);
saveNetwork();
m_uninitializedNodes.append(node);
}
void ZigbeeNetwork::addNodeInternally(ZigbeeNode *node)
@ -231,13 +340,7 @@ void ZigbeeNetwork::addNodeInternally(ZigbeeNode *node)
void ZigbeeNetwork::removeNode(ZigbeeNode *node)
{
if (!m_nodes.contains(node)) {
qCWarning(dcZigbeeNetwork()) << "Try to remove node" << node << "but not in the node list.";
return;
}
m_nodes.removeAll(node);
emit nodeRemoved(node);
removeNodeInternally(node);
saveNetwork();
}
@ -253,6 +356,13 @@ void ZigbeeNetwork::removeNodeInternally(ZigbeeNode *node)
node->deleteLater();
}
ZigbeeNode *ZigbeeNetwork::createNode()
{
ZigbeeNode *node = new ZigbeeNode(this);
connect(node, &ZigbeeNode::stateChanged, this, &ZigbeeNetwork::onNodeStateChanged);
return node;
}
void ZigbeeNetwork::clearSettings()
{
qCDebug(dcZigbeeNetwork()) << "Clear network settings";
@ -296,3 +406,12 @@ void ZigbeeNetwork::setError(ZigbeeNetwork::Error 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);
}
}

View File

@ -87,15 +87,19 @@ private:
QString m_settingsFileName = "/etc/nymea/nymea-zigbee.conf";
QList<ZigbeeNode *> m_nodes;
QList<ZigbeeNode *> m_uninitializedNodes;
void saveNetwork();
void loadNetwork();
void addNodeInternally(ZigbeeNode *node);
void removeNodeInternally(ZigbeeNode *node);
protected:
void addNode(ZigbeeNode *node);
void addNodeInternally(ZigbeeNode *node);
void addUnitializedNode(ZigbeeNode *node);
void removeNode(ZigbeeNode *node);
void removeNodeInternally(ZigbeeNode *node);
ZigbeeNode *createNode();
void clearSettings();
@ -118,6 +122,9 @@ signals:
void stateChanged(State state);
void errorOccured(Error error);
private slots:
void onNodeStateChanged(ZigbeeNode::State state);
public slots:
virtual void startNetwork() = 0;
virtual void stopNetwork() = 0;

View File

@ -480,8 +480,7 @@ void ZigbeeNetworkManager::processNetworkFormed(const ZigbeeInterfaceMessage &me
qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(extendedAddress);
qCDebug(dcZigbeeNetwork()) << " Channel:" << channel;
qCDebug(dcZigbeeNetwork()) << " Extended PAN ID:" << extendedPanId();
qCDebug(dcZigbeeNetwork()) << " Permit joining" << permitJoining();
qCDebug(dcZigbeeNetwork()) << " Permit joining:" << permitJoining();
m_networkRunning = true;
@ -490,7 +489,7 @@ void ZigbeeNetworkManager::processNetworkFormed(const ZigbeeInterfaceMessage &me
setExtendedAddress(ZigbeeAddress(extendedAddress));
setChannel(channel);
addNode(this);
addUnitializedNode(this);
}
void ZigbeeNetworkManager::onCommandEnableWhitelistFinished()
@ -519,42 +518,40 @@ void ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished()
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));
Q_UNUSED(sequenceNumber)
Q_UNUSED(status)
QByteArray data = reply->additionalMessage().data();
quint16 shortAddress = static_cast<quint16>(reply->additionalMessage().data().at(2));
shortAddress <<= 8;
shortAddress |= reply->additionalMessage().data().at(3);
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;
quint16 manufacturerCode = static_cast<quint16>(reply->additionalMessage().data().at(4));
manufacturerCode <<= 8;
manufacturerCode |= reply->additionalMessage().data().at(5);
quint16 maximalRxSize = static_cast<quint16>(reply->additionalMessage().data().at(6));
maximalRxSize <<= 8;
maximalRxSize |= reply->additionalMessage().data().at(7);
quint16 maximalTxSize = static_cast<quint16>(reply->additionalMessage().data().at(8));
maximalTxSize <<= 8;
maximalTxSize |= reply->additionalMessage().data().at(9);
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);
QDataStream stream(&data, QIODevice::ReadOnly);
stream >> sequenceNumber;
stream >> status;
stream >> shortAddress;
stream >> manufacturerCode;
stream >> maximalRxSize;
stream >> maximalTxSize;
stream >> serverMask;
stream >> descriptorFlag;
stream >> macFlags;
stream >> maxBufferSize;
stream >> bitField;
// Get node object
ZigbeeNode *node = getZigbeeNode(shortAddress);
if (!node) {
qCWarning(dcZigbeeNetwork()) << "Could not find node for address" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress);
return;
}
// Set node data
node->setManufacturerCode(manufacturerCode);
@ -570,7 +567,7 @@ void ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished()
if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
node->setNodeType(NodeTypeCoordinator);
} 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)) {
node->setNodeType(NodeTypeEndDevice);
}
@ -625,36 +622,39 @@ void ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished()
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));
QByteArray data = reply->additionalMessage().data();
quint16 nwkAddress = static_cast<quint16>(reply->additionalMessage().data().at(2));
nwkAddress <<= 8;
nwkAddress |= reply->additionalMessage().data().at(3);
quint8 sequenceNumber = 0;
quint8 status = 0;
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) {
qCWarning(dcZigbeeNetwork()) << "Length 0";
qCWarning(dcZigbeeNetwork()) << "Simple node descriptior has a length of 0.";
return;
}
quint8 endPoint = static_cast<quint8>(reply->additionalMessage().data().at(5));
quint16 profileId = static_cast<quint16>(reply->additionalMessage().data().at(6));
profileId <<= 8;
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));
stream >> endPoint;
stream >> profileId;
stream >> deviceId;
stream >> bitField;
qCDebug(dcZigbeeNetwork()) << "Node simple descriptor:";
qCDebug(dcZigbeeNetwork()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
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()) << " End Point:" << ZigbeeUtils::convertByteToHexString(endPoint);
qCDebug(dcZigbeeNetwork()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast<Zigbee::ZigbeeProfile>(profileId));
@ -667,30 +667,40 @@ void ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished()
qCDebug(dcZigbeeNetwork()) << " Bit field:" << ZigbeeUtils::convertByteToHexString(bitField);
quint8 inputClusterCount = static_cast<quint8>(reply->additionalMessage().data().at(10));
qCDebug(dcZigbeeNetwork()) << " Input clusters:";
QByteArray inputClusterListData = reply->additionalMessage().data().mid(11, inputClusterCount * 2);
for (int i = 0; i < inputClusterListData.count(); i+=2) {
quint16 clusterId = static_cast<quint16>(inputClusterListData.at(i));
clusterId <<= 8;
clusterId |= inputClusterListData .at(i+1);
stream >> inputClusterCount;
qCDebug(dcZigbeeNetwork()) << " Input clusters: (" << inputClusterCount << ")";
for (int i = 0; i < inputClusterCount; i+=1) {
quint16 clusterId = 0;
stream >> 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));
qCDebug(dcZigbeeNetwork()) << " Output clusters:";
QByteArray outputClusterListData = reply->additionalMessage().data().mid(12 + inputClusterCount * 2, outputClusterCount * 2);
for (int i = 0; i < outputClusterListData.count(); i+=2) {
quint16 clusterId = static_cast<quint16>(outputClusterListData.at(i));
clusterId <<= 8;
clusterId |= outputClusterListData .at(i+1);
stream >> outputClusterCount;
qCDebug(dcZigbeeNetwork()) << " Output clusters: (" << outputClusterCount << ")";
for (int i = 0; i < outputClusterCount; i+=1) {
if (stream.atEnd()) {
qCWarning(dcZigbeeNode()) << "Data stream already at the end but more data expected. Looks like the firmware doesn't provide more data.";
break;
}
quint16 clusterId = 0;
stream >> 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);
}
@ -699,8 +709,24 @@ void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished()
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
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) {
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;
}
@ -712,19 +738,20 @@ void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished()
quint16 bitField = static_cast<quint16>(reply->additionalMessage().data().at(2));
bitField <<= 8;
bitField |= reply->additionalMessage().data().at(3);
bitField |= static_cast<quint8>(reply->additionalMessage().data().at(3));
// Bit 0 - 3 Power mode
// 0000: Receiver configured according to “Receiver on when idle” MAC flag in the Node Descriptor
// 0001: Receiver switched on periodically
// 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)) {
m_powerMode = PowerModeAlwaysOn;
powerMode = PowerModeAlwaysOn;
} 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)) {
m_powerMode = PowerModeOnWhenStimulated;
powerMode = PowerModeOnWhenStimulated;
}
// Bit 4 - 7 Available power sources
@ -733,21 +760,23 @@ void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished()
// Bit 2: Disposable battery
// Bit 4: Reserved
QList<ZigbeeNode::PowerSource> availablePowerSources;
if (ZigbeeUtils::checkBitUint16(bitField, 4)) {
m_availablePowerSources.append(PowerSourcePermanentMainSupply);
availablePowerSources.append(PowerSourcePermanentMainSupply);
} else if (ZigbeeUtils::checkBitUint16(bitField, 5)) {
m_availablePowerSources.append(PowerSourceRecharchableBattery);
availablePowerSources.append(PowerSourceRecharchableBattery);
} 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
ZigbeeNode::PowerSource powerSource = PowerSourcePermanentMainSupply;
if (ZigbeeUtils::checkBitUint16(bitField, 8)) {
m_powerSource = PowerSourcePermanentMainSupply;
powerSource = PowerSourcePermanentMainSupply;
} else if (ZigbeeUtils::checkBitUint16(bitField, 9)) {
m_powerSource = PowerSourceRecharchableBattery;
powerSource = PowerSourceRecharchableBattery;
} else if (ZigbeeUtils::checkBitUint16(bitField, 10)) {
m_powerSource = PowerSourceDisposableBattery;
powerSource = PowerSourceDisposableBattery;
}
// Bit 12 - 15: Battery level if available
@ -755,15 +784,15 @@ void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished()
// 0100: Approximately 33%
// 1000: Approximately 66%
// 1100: Approximately 100% (near fully charged)
ZigbeeNode::PowerLevel powerLevel = PowerLevelCriticalLow;
if (!ZigbeeUtils::checkBitUint16(bitField, 14) && !ZigbeeUtils::checkBitUint16(bitField, 15)) {
m_powerLevel = PowerLevelCriticalLow;
powerLevel = PowerLevelCriticalLow;
} 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)) {
m_powerLevel = PowerLevelOk;
powerLevel = PowerLevelOk;
} else if (ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) {
m_powerLevel = PowerLevelFull;
powerLevel = PowerLevelFull;
}
qCDebug(dcZigbeeNetwork()) << "Node power descriptor:";
@ -772,12 +801,32 @@ void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished()
qCDebug(dcZigbeeNetwork()) << " Bitfiled:" << ZigbeeUtils::convertUint16ToHexString(bitField);
qCDebug(dcZigbeeNetwork()) << " Power mode:" << m_powerMode;
qCDebug(dcZigbeeNetwork()) << " Available power sources:";
foreach (const PowerSource &source, m_availablePowerSources) {
foreach (const PowerSource &source, availablePowerSources) {
qCDebug(dcZigbeeNetwork()) << " " << source;
}
qCDebug(dcZigbeeNetwork()) << " Power source:" << m_powerSource;
qCDebug(dcZigbeeNetwork()) << " Power level:" << m_powerLevel;
qCDebug(dcZigbeeNetwork()) << " Power source:" << powerSource;
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) {
setStartingState(StartingStateNone);
setState(StateRunning);
@ -1013,7 +1062,7 @@ void ZigbeeNetworkManager::processDeviceAnnounce(const ZigbeeInterfaceMessage &m
qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(ieeeAddress);
qCDebug(dcZigbeeNetwork()) << " Mac capabilities:" << ZigbeeUtils::convertByteToHexString(macCapabilitiesFlag);
ZigbeeNode *node = new ZigbeeNode(this);
ZigbeeNode *node = createNode();
node->setShortAddress(shortAddress);
node->setExtendedAddress(ZigbeeAddress(ieeeAddress));
node->setMacCapabilitiesFlag(macCapabilitiesFlag);
@ -1021,7 +1070,8 @@ void ZigbeeNetworkManager::processDeviceAnnounce(const ZigbeeInterfaceMessage &m
qCDebug(dcZigbeeNetwork()) << " Node:" << node;
// FIXME: check if node already added, and if we have to update it
addNode(node);
addUnitializedNode(node);
node->setState(StateInitializing);
ZigbeeInterfaceReply *reply = nullptr;
reply = m_controller->commandAuthenticateDevice(node->extendedAddress(), securityConfiguration().globalTrustCenterLinkKey());
@ -1071,8 +1121,13 @@ void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &
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)
@ -1080,23 +1135,16 @@ void ZigbeeNetworkManager::processLeaveIndication(const ZigbeeInterfaceMessage &
QByteArray data = message.data();
quint64 extendedAddress = 0;
bool rejoining = 0;
QDataStream stream(&data, QIODevice::ReadOnly);
stream >> extendedAddress;
stream >> rejoining;
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;
ZigbeeNode *node = getZigbeeNode(address);
if (node) {
removeNode(node);
}
// TODO: remove node
if (node) removeNode(node);
}
void ZigbeeNetworkManager::processRestartProvisioned(const ZigbeeInterfaceMessage &message)

View File

@ -10,6 +10,11 @@ ZigbeeNode::ZigbeeNode(QObject *parent) :
}
ZigbeeNode::State ZigbeeNode::state() const
{
return m_state;
}
quint16 ZigbeeNode::shortAddress() const
{
return m_shortAddress;
@ -50,6 +55,11 @@ quint16 ZigbeeNode::manufacturerCode() const
return m_manufacturerCode;
}
quint16 ZigbeeNode::deviceId() const
{
return m_deviceId;
}
bool ZigbeeNode::complexDescriptorAvailable() const
{
return m_complexDescriptorAvailable;
@ -75,6 +85,36 @@ quint8 ZigbeeNode::maximumBufferSize() const
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
{
return m_isPrimaryTrustCenter;
@ -170,6 +210,16 @@ ZigbeeNode::PowerLevel ZigbeeNode::powerLevel() const
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()
//{
@ -246,6 +296,11 @@ void ZigbeeNode::setManufacturerCode(quint16 manufacturerCode)
m_manufacturerCode = manufacturerCode;
}
void ZigbeeNode::setDeviceId(quint16 deviceId)
{
m_deviceId = deviceId;
}
void ZigbeeNode::setMaximumRxSize(quint16 size)
{
m_maximumRxSize = size;
@ -303,6 +358,57 @@ void ZigbeeNode::setDescriptorFlag(quint8 descriptorFlag)
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()
//{
// ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());

View File

@ -4,6 +4,7 @@
#include <QObject>
#include "zigbee.h"
#include "zigbeecluster.h"
#include "zigbeeaddress.h"
class ZigbeeNode : public QObject
@ -14,6 +15,13 @@ class ZigbeeNode : public QObject
friend class ZigbeeNetworkManager;
public:
enum State {
StateUninitialized,
StateInitializing,
StateInitialized
};
Q_ENUM(State)
enum NodeType {
NodeTypeCoordinator = 0,
NodeTypeRouter = 1,
@ -63,7 +71,7 @@ public:
};
Q_ENUM(PowerLevel)
ZigbeeNode(QObject *parent = nullptr);
State state() const;
quint16 shortAddress() const;
ZigbeeAddress extendedAddress() const;
@ -75,6 +83,7 @@ public:
Relationship relationship() const;
Zigbee::ZigbeeProfile profile() const;
quint16 manufacturerCode() const;
quint16 deviceId() const;
bool complexDescriptorAvailable() const;
bool userDescriptorAvailable() const;
@ -83,6 +92,14 @@ public:
quint16 maximumTxSize() 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
bool isPrimaryTrustCenter() const;
bool isBackupTrustCenter() const;
@ -111,6 +128,12 @@ public:
PowerLevel powerLevel() const;
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;
ZigbeeAddress m_extendedAddress;
quint8 m_endPoint = 1;
@ -120,6 +143,7 @@ private:
Relationship m_relationship = Parent;
Zigbee::ZigbeeProfile m_profile;
quint16 m_manufacturerCode = 0;
quint16 m_deviceId = 0;
bool m_complexDescriptorAvailable = false;
bool m_userDescriptorAvailable = false;
@ -156,6 +180,8 @@ private:
bool m_extendedSimpleDescriptorListAvailable = false;
protected:
void setState(State state);
void setShortAddress(const quint16 &shortAddress);
void setExtendedAddress(const ZigbeeAddress &extendedAddress);
void setEndPoint(quint8 endPoint);
@ -165,6 +191,7 @@ protected:
void setRelationship(Relationship relationship);
void setZigbeeProfile(Zigbee::ZigbeeProfile profile);
void setManufacturerCode(quint16 manufacturerCode);
void setDeviceId(quint16 deviceType);
void setMaximumRxSize(quint16 size);
void setMaximumTxSize(quint16 size);
@ -176,6 +203,22 @@ protected:
void setMacCapabilitiesFlag(quint16 macFlag);
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);

View File

@ -11,6 +11,16 @@ ZigbeeSecurityConfiguration::ZigbeeSecurityConfiguration(const ZigbeeSecurityCon
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
{
return m_networkKey;
@ -33,12 +43,14 @@ void ZigbeeSecurityConfiguration::setGlobalTrustCenterlinkKey(const QString &glo
void ZigbeeSecurityConfiguration::clear()
{
m_zigbeeSecurityMode = ZigbeeSecurityModeNone;
m_networkKey.clear();
m_globalTrustCenterLinkKey = "5A6967426565416C6C69616E63653039";
}
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

View File

@ -6,9 +6,18 @@
class ZigbeeSecurityConfiguration
{
public:
enum ZigbeeSecurityMode {
ZigbeeSecurityModeNone,
ZigbeeSecurityModeNetworkLayer,
ZigbeeSecurityModeApplicationLayer
};
explicit ZigbeeSecurityConfiguration();
ZigbeeSecurityConfiguration(const ZigbeeSecurityConfiguration &other);
ZigbeeSecurityMode zigbeeSecurityMode() const;
void setZigbeeSecurityMode(ZigbeeSecurityMode zigbeeSecurityMode);
QString networkKey() const;
void setNetworkKey(const QString &networkKey);
@ -21,6 +30,8 @@ public:
bool operator!=(const ZigbeeSecurityConfiguration &other) const;
private:
ZigbeeSecurityMode m_zigbeeSecurityMode = ZigbeeSecurityModeNone;
// This is the local network key
QString m_networkKey;

View File

@ -133,7 +133,6 @@ QString ZigbeeUtils::profileIdToString(const Zigbee::ZigbeeProfile &profileId)
quint64 ZigbeeUtils::generateRandomPanId()
{
srand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch() / 1000));
srand(static_cast<uint>(qrand()));
qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch() / 1000));
return static_cast<quint64>((ULLONG_MAX - 0) * (qrand()/static_cast<double>(RAND_MAX)));
}