From 899ad4e3b9eedb660a65fd3bd6aedc3a0ddd14f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Thu, 27 Feb 2020 21:53:53 +0100 Subject: [PATCH] Continue restructuring and reach compilable state --- libnymea-zigbee/libnymea-zigbee.pro | 16 +- .../{ => nxp}/interface/zigbeeinterface.cpp | 0 .../{ => nxp}/interface/zigbeeinterface.h | 2 +- .../interface/zigbeeinterfacemessage.cpp | 0 .../interface/zigbeeinterfacemessage.h | 2 +- .../interface/zigbeeinterfacereply.cpp | 0 .../interface/zigbeeinterfacereply.h | 6 +- .../interface/zigbeeinterfacerequest.cpp | 0 .../interface/zigbeeinterfacerequest.h | 0 .../nxp/zigbeebridgecontrollernxp.cpp | 72 +- .../nxp/zigbeebridgecontrollernxp.h | 6 +- libnymea-zigbee/nxp/zigbeenetworknxp.cpp | 929 +++++++++++ libnymea-zigbee/nxp/zigbeenetworknxp.h | 67 +- libnymea-zigbee/zigbeenetwork.cpp | 21 +- libnymea-zigbee/zigbeenetwork.h | 8 +- libnymea-zigbee/zigbeenetworkmanager.cpp | 1393 +---------------- libnymea-zigbee/zigbeenetworkmanager.h | 105 +- 17 files changed, 1113 insertions(+), 1514 deletions(-) rename libnymea-zigbee/{ => nxp}/interface/zigbeeinterface.cpp (100%) rename libnymea-zigbee/{ => nxp}/interface/zigbeeinterface.h (99%) rename libnymea-zigbee/{ => nxp}/interface/zigbeeinterfacemessage.cpp (100%) rename libnymea-zigbee/{ => nxp}/interface/zigbeeinterfacemessage.h (98%) rename libnymea-zigbee/{ => nxp}/interface/zigbeeinterfacereply.cpp (100%) rename libnymea-zigbee/{ => nxp}/interface/zigbeeinterfacereply.h (96%) rename libnymea-zigbee/{ => nxp}/interface/zigbeeinterfacerequest.cpp (100%) rename libnymea-zigbee/{ => nxp}/interface/zigbeeinterfacerequest.h (100%) diff --git a/libnymea-zigbee/libnymea-zigbee.pro b/libnymea-zigbee/libnymea-zigbee.pro index 39c48a8..0472cbe 100644 --- a/libnymea-zigbee/libnymea-zigbee.pro +++ b/libnymea-zigbee/libnymea-zigbee.pro @@ -4,10 +4,10 @@ TARGET = nymea-zigbee1 TEMPLATE = lib SOURCES += \ - interface/zigbeeinterface.cpp \ - interface/zigbeeinterfacemessage.cpp \ - interface/zigbeeinterfacerequest.cpp \ - interface/zigbeeinterfacereply.cpp \ + nxp/interface/zigbeeinterface.cpp \ + nxp/interface/zigbeeinterfacemessage.cpp \ + nxp/interface/zigbeeinterfacerequest.cpp \ + nxp/interface/zigbeeinterfacereply.cpp \ nxp/zigbeenetworknxp.cpp \ nxp/zigbeebridgecontrollernxp.cpp \ zigbeecluster.cpp \ @@ -23,10 +23,10 @@ SOURCES += \ zigbeeaddress.cpp \ HEADERS += \ - interface/zigbeeinterface.h \ - interface/zigbeeinterfacemessage.h \ - interface/zigbeeinterfacerequest.h \ - interface/zigbeeinterfacereply.h \ + nxp/interface/zigbeeinterface.h \ + nxp/interface/zigbeeinterfacemessage.h \ + nxp/interface/zigbeeinterfacerequest.h \ + nxp/interface/zigbeeinterfacereply.h \ nxp/zigbeenetworknxp.h \ nxp/zigbeebridgecontrollernxp.h \ zigbeecluster.h \ diff --git a/libnymea-zigbee/interface/zigbeeinterface.cpp b/libnymea-zigbee/nxp/interface/zigbeeinterface.cpp similarity index 100% rename from libnymea-zigbee/interface/zigbeeinterface.cpp rename to libnymea-zigbee/nxp/interface/zigbeeinterface.cpp diff --git a/libnymea-zigbee/interface/zigbeeinterface.h b/libnymea-zigbee/nxp/interface/zigbeeinterface.h similarity index 99% rename from libnymea-zigbee/interface/zigbeeinterface.h rename to libnymea-zigbee/nxp/interface/zigbeeinterface.h index 58638ac..b6d184c 100644 --- a/libnymea-zigbee/interface/zigbeeinterface.h +++ b/libnymea-zigbee/nxp/interface/zigbeeinterface.h @@ -32,7 +32,7 @@ #include #include -#include "../zigbee.h" +#include "../../zigbee.h" #include "zigbeeinterfacemessage.h" class ZigbeeInterface : public QObject diff --git a/libnymea-zigbee/interface/zigbeeinterfacemessage.cpp b/libnymea-zigbee/nxp/interface/zigbeeinterfacemessage.cpp similarity index 100% rename from libnymea-zigbee/interface/zigbeeinterfacemessage.cpp rename to libnymea-zigbee/nxp/interface/zigbeeinterfacemessage.cpp diff --git a/libnymea-zigbee/interface/zigbeeinterfacemessage.h b/libnymea-zigbee/nxp/interface/zigbeeinterfacemessage.h similarity index 98% rename from libnymea-zigbee/interface/zigbeeinterfacemessage.h rename to libnymea-zigbee/nxp/interface/zigbeeinterfacemessage.h index 8f8a418..e5bfea0 100644 --- a/libnymea-zigbee/interface/zigbeeinterfacemessage.h +++ b/libnymea-zigbee/nxp/interface/zigbeeinterfacemessage.h @@ -31,7 +31,7 @@ #include #include -#include "../zigbee.h" +#include "../../zigbee.h" class ZigbeeInterfaceMessage { diff --git a/libnymea-zigbee/interface/zigbeeinterfacereply.cpp b/libnymea-zigbee/nxp/interface/zigbeeinterfacereply.cpp similarity index 100% rename from libnymea-zigbee/interface/zigbeeinterfacereply.cpp rename to libnymea-zigbee/nxp/interface/zigbeeinterfacereply.cpp diff --git a/libnymea-zigbee/interface/zigbeeinterfacereply.h b/libnymea-zigbee/nxp/interface/zigbeeinterfacereply.h similarity index 96% rename from libnymea-zigbee/interface/zigbeeinterfacereply.h rename to libnymea-zigbee/nxp/interface/zigbeeinterfacereply.h index a30589c..e1dc9c4 100644 --- a/libnymea-zigbee/interface/zigbeeinterfacereply.h +++ b/libnymea-zigbee/nxp/interface/zigbeeinterfacereply.h @@ -33,12 +33,12 @@ #include "zigbeeinterfacerequest.h" -class ZigbeeBridgeController; +class ZigbeeBridgeControllerNxp; class ZigbeeInterfaceReply : public QObject { Q_OBJECT - friend class ZigbeeBridgeController; + friend class ZigbeeBridgeControllerNxp; public: enum Status { @@ -80,7 +80,7 @@ private: quint8 m_sequenceNumber; QString m_statusErrorMessage; - // Called by ZigbeeBridgeController + // Called by ZigbeeBridgeControllerNxp void setStatusMessage(const ZigbeeInterfaceMessage &statusMessage); void setAdditionalMessage(const ZigbeeInterfaceMessage &additionalMessage); diff --git a/libnymea-zigbee/interface/zigbeeinterfacerequest.cpp b/libnymea-zigbee/nxp/interface/zigbeeinterfacerequest.cpp similarity index 100% rename from libnymea-zigbee/interface/zigbeeinterfacerequest.cpp rename to libnymea-zigbee/nxp/interface/zigbeeinterfacerequest.cpp diff --git a/libnymea-zigbee/interface/zigbeeinterfacerequest.h b/libnymea-zigbee/nxp/interface/zigbeeinterfacerequest.h similarity index 100% rename from libnymea-zigbee/interface/zigbeeinterfacerequest.h rename to libnymea-zigbee/nxp/interface/zigbeeinterfacerequest.h diff --git a/libnymea-zigbee/nxp/zigbeebridgecontrollernxp.cpp b/libnymea-zigbee/nxp/zigbeebridgecontrollernxp.cpp index 3ece135..0eccc7e 100644 --- a/libnymea-zigbee/nxp/zigbeebridgecontrollernxp.cpp +++ b/libnymea-zigbee/nxp/zigbeebridgecontrollernxp.cpp @@ -25,31 +25,31 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include "zigbeebridgecontroller.h" +#include "zigbeebridgecontrollernxp.h" #include "loggingcategory.h" #include "zigbeeutils.h" #include -ZigbeeBridgeController::ZigbeeBridgeController(QObject *parent) : +ZigbeeBridgeControllerNxp::ZigbeeBridgeControllerNxp(QObject *parent) : QObject(parent) { m_interface = new ZigbeeInterface(this); - connect(m_interface, &ZigbeeInterface::availableChanged, this, &ZigbeeBridgeController::availableChanged); - connect(m_interface, &ZigbeeInterface::messageReceived, this, &ZigbeeBridgeController::onMessageReceived); + connect(m_interface, &ZigbeeInterface::availableChanged, this, &ZigbeeBridgeControllerNxp::availableChanged); + connect(m_interface, &ZigbeeInterface::messageReceived, this, &ZigbeeBridgeControllerNxp::onMessageReceived); } -ZigbeeBridgeController::~ZigbeeBridgeController() +ZigbeeBridgeControllerNxp::~ZigbeeBridgeControllerNxp() { qCDebug(dcZigbeeController()) << "Destroy controller"; } -bool ZigbeeBridgeController::available() const +bool ZigbeeBridgeControllerNxp::available() const { return m_interface->available(); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandResetController() +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandResetController() { ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeReset, QByteArray())); request.setDescription("Reset controller"); @@ -58,7 +58,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandResetController() return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandSoftResetController() +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandSoftResetController() { ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeZllFactoryNew, QByteArray())); request.setDescription("Soft reset controller"); @@ -67,7 +67,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandSoftResetController() return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandErasePersistantData() +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandErasePersistantData() { ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeErasePersistentData, QByteArray())); request.setDescription("Erase persistent data"); @@ -75,7 +75,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandErasePersistantData() return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandGetVersion() +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandGetVersion() { ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeGetVersion, QByteArray())); request.setDescription("Get version"); @@ -84,7 +84,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandGetVersion() return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandSetExtendedPanId(quint64 extendedPanId) +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandSetExtendedPanId(quint64 extendedPanId) { QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); @@ -96,7 +96,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandSetExtendedPanId(quint64 ex return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandSetChannelMask(quint32 channelMask) +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandSetChannelMask(quint32 channelMask) { // Note: 10 < value < 27 -> using sinle channel value // 0x07fff800 select from all channels 11 - 26 @@ -116,7 +116,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandSetChannelMask(quint32 chan return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandSetNodeType(ZigbeeNode::NodeType nodeType) +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandSetNodeType(ZigbeeNode::NodeType nodeType) { quint8 deviceTypeValue = 0; if (nodeType == ZigbeeNode::NodeTypeEndDevice) { @@ -146,7 +146,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandSetNodeType(ZigbeeNode::Nod return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandStartNetwork() +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandStartNetwork() { ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeStartNetwork, QByteArray())); request.setDescription("Start network"); @@ -156,7 +156,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandStartNetwork() return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandStartScan() +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandStartScan() { ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeStartScan, QByteArray())); request.setDescription("Start scan"); @@ -166,7 +166,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandStartScan() return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandPermitJoin(quint16 targetAddress, const quint8 advertisingIntervall, bool tcSignificance) +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandPermitJoin(quint16 targetAddress, const quint8 advertisingIntervall, bool tcSignificance) { QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); @@ -180,7 +180,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandPermitJoin(quint16 targetAd return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandGetPermitJoinStatus() +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandGetPermitJoinStatus() { ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeGetPermitJoining, QByteArray())); request.setDescription("Get permit joining status"); @@ -190,7 +190,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandGetPermitJoinStatus() return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandRequestActiveEndpoints(quint16 shortAddress) +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandRequestActiveEndpoints(quint16 shortAddress) { QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); @@ -204,7 +204,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandRequestActiveEndpoints(quin return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandRequestLinkQuality(quint16 shortAddress) +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandRequestLinkQuality(quint16 shortAddress) { QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); @@ -219,7 +219,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandRequestLinkQuality(quint16 return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandEnableWhiteList() +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandEnableWhiteList() { ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeNetworkWhitelistEnable, QByteArray())); request.setDescription("Enable whitelist"); @@ -227,7 +227,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandEnableWhiteList() return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandInitiateTouchLink() +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandInitiateTouchLink() { ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeInitiateTouchlink, QByteArray())); request.setDescription("Initiate touch link"); @@ -235,7 +235,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandInitiateTouchLink() return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandTouchLinkFactoryReset() +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandTouchLinkFactoryReset() { ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeTouchlinkFactoryReset, QByteArray())); request.setDescription("Touch link factory reset"); @@ -243,7 +243,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandTouchLinkFactoryReset() return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandNetworkAddressRequest(quint16 targetAddress, quint64 extendedAddress) +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandNetworkAddressRequest(quint16 targetAddress, quint64 extendedAddress) { QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); @@ -260,7 +260,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandNetworkAddressRequest(quint return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandSetSecurityStateAndKey(quint8 keyState, quint8 keySequence, quint8 keyType, const QString &key) +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandSetSecurityStateAndKey(quint8 keyState, quint8 keySequence, quint8 keyType, const QString &key) { // Note: calls ZPS_vAplSecSetInitialSecurityState @@ -287,7 +287,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandSetSecurityStateAndKey(quin return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandAuthenticateDevice(const ZigbeeAddress &ieeeAddress, const QString &key) +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandAuthenticateDevice(const ZigbeeAddress &ieeeAddress, const QString &key) { QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); @@ -302,7 +302,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandAuthenticateDevice(const Zi return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandNodeDescriptorRequest(quint16 shortAddress) +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandNodeDescriptorRequest(quint16 shortAddress) { QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); @@ -316,7 +316,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandNodeDescriptorRequest(quint return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandSimpleDescriptorRequest(quint16 shortAddress, quint8 endpoint) +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandSimpleDescriptorRequest(quint16 shortAddress, quint8 endpoint) { QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); @@ -331,7 +331,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandSimpleDescriptorRequest(qui return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandPowerDescriptorRequest(quint16 shortAddress) +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandPowerDescriptorRequest(quint16 shortAddress) { QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); @@ -345,7 +345,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandPowerDescriptorRequest(quin return sendRequest(request); } -ZigbeeInterfaceReply *ZigbeeBridgeController::commandUserDescriptorRequest(quint16 shortAddress, quint16 address) +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandUserDescriptorRequest(quint16 shortAddress, quint16 address) { QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); @@ -360,7 +360,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandUserDescriptorRequest(quint return sendRequest(request); } -void ZigbeeBridgeController::sendMessage(ZigbeeInterfaceReply *reply) +void ZigbeeBridgeControllerNxp::sendMessage(ZigbeeInterfaceReply *reply) { if (!reply) return; @@ -372,7 +372,7 @@ void ZigbeeBridgeController::sendMessage(ZigbeeInterfaceReply *reply) reply->startTimer(reply->request().timeoutIntervall()); } -void ZigbeeBridgeController::onMessageReceived(const ZigbeeInterfaceMessage &message) +void ZigbeeBridgeControllerNxp::onMessageReceived(const ZigbeeInterfaceMessage &message) { // Check if we have a current reply if (m_currentReply) { @@ -412,7 +412,7 @@ void ZigbeeBridgeController::onMessageReceived(const ZigbeeInterfaceMessage &mes } -void ZigbeeBridgeController::onReplyTimeout() +void ZigbeeBridgeControllerNxp::onReplyTimeout() { m_currentReply->setFinished(); m_currentReply = nullptr; @@ -422,21 +422,21 @@ void ZigbeeBridgeController::onReplyTimeout() } -bool ZigbeeBridgeController::enable(const QString &serialPort, qint32 baudrate) +bool ZigbeeBridgeControllerNxp::enable(const QString &serialPort, qint32 baudrate) { return m_interface->enable(serialPort, baudrate); } -void ZigbeeBridgeController::disable() +void ZigbeeBridgeControllerNxp::disable() { m_interface->disable(); } -ZigbeeInterfaceReply *ZigbeeBridgeController::sendRequest(const ZigbeeInterfaceRequest &request) +ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::sendRequest(const ZigbeeInterfaceRequest &request) { // Create Reply ZigbeeInterfaceReply *reply = new ZigbeeInterfaceReply(request); - connect(reply, &ZigbeeInterfaceReply::timeout, this, &ZigbeeBridgeController::onReplyTimeout); + connect(reply, &ZigbeeInterfaceReply::timeout, this, &ZigbeeBridgeControllerNxp::onReplyTimeout); // If reply running, enqueue, else send request if (m_currentReply) { diff --git a/libnymea-zigbee/nxp/zigbeebridgecontrollernxp.h b/libnymea-zigbee/nxp/zigbeebridgecontrollernxp.h index 5939828..debf665 100644 --- a/libnymea-zigbee/nxp/zigbeebridgecontrollernxp.h +++ b/libnymea-zigbee/nxp/zigbeebridgecontrollernxp.h @@ -38,12 +38,12 @@ #include "interface/zigbeeinterfacerequest.h" #include "interface/zigbeeinterfacemessage.h" -class ZigbeeBridgeController : public QObject +class ZigbeeBridgeControllerNxp : public QObject { Q_OBJECT public: - explicit ZigbeeBridgeController(QObject *parent = nullptr); - ~ZigbeeBridgeController(); + explicit ZigbeeBridgeControllerNxp(QObject *parent = nullptr); + ~ZigbeeBridgeControllerNxp(); bool available() const; diff --git a/libnymea-zigbee/nxp/zigbeenetworknxp.cpp b/libnymea-zigbee/nxp/zigbeenetworknxp.cpp index b86cb82..53f4186 100644 --- a/libnymea-zigbee/nxp/zigbeenetworknxp.cpp +++ b/libnymea-zigbee/nxp/zigbeenetworknxp.cpp @@ -1,7 +1,936 @@ #include "zigbeenetworknxp.h" +#include "../loggingcategory.h" +#include "../zigbeeutils.h" + +#include ZigbeeNetworkNxp::ZigbeeNetworkNxp(QObject *parent) : ZigbeeNetwork(parent) { } + +void ZigbeeNetworkNxp::setStartingState(ZigbeeNetworkNxp::StartingState state) +{ + if (m_startingState == state) + return; + + m_startingState = state; + + switch (m_startingState) { + case StartingStateNone: + break; + case StartingStateErase: { + m_networkRunning = false; + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Erase persistant data"; + ZigbeeInterfaceReply *reply = m_controller->commandErasePersistantData(); + connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandErasePersistentDataFinished); + break; + } + case StartingStateReset: { + m_networkRunning = false; + + // qCDebug(dcZigbeeNetwork()) << ""; + // ZigbeeInterfaceReply *reply = m_controller->commandSoftResetController(); + // connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply](){ + // reply->deleteLater(); + + // }); + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Reset controller"; + ZigbeeInterfaceReply *reply = m_controller->commandResetController(); + connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandResetControllerFinished); + break; + } + case StartingStateGetVersion: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Get controller version"; + readControllerVersion(); + break; + } + case StartingStateSetPanId: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Set PAN ID"; + if (extendedPanId() == 0) { + setExtendedPanId(ZigbeeUtils::generateRandomPanId()); + } + ZigbeeInterfaceReply *reply = m_controller->commandSetExtendedPanId(extendedPanId()); + connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandSetExtendedPanIdFinished); + break; + } + case StartingStateSetChannel: { + // Create channel mask + // Note: normal number passed, that specific channel will be used || Bitfield: all channels would be 0x07FFF800 + // 0x07fff800 select from all channels 11 - 26 + // 0x02108800 primary zigbee light link channels 11, 15, 20, 25 + + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Set channel mask"; + ZigbeeInterfaceReply *reply = nullptr; + if (channel() == 0) { + qCDebug(dcZigbeeNetwork()) << "Autoselect quitest channel for the zigbee network. FIXME: currently hardcoded to 13 due to firmware error."; + quint32 channelMask = 0; + channelMask |= 1 << (13); + reply = m_controller->commandSetChannelMask(channelMask); + } else { + quint32 channelMask = 0; + channelMask |= 1 << (channel()); + qCDebug(dcZigbeeNetwork()) << "Using channel" << channel() << "for the zigbee network."; + reply = m_controller->commandSetChannelMask(channelMask); + } + connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandSetChannelMaskFinished); + break; + } + case StartingStateSetSecurity: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Set security configuration"; + ZigbeeInterfaceReply *reply = m_controller->commandSetSecurityStateAndKey(4, 0, 1, "5A6967426565416C6C69616E63653039"); + connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandSetSecurityFinished); + break; + } + case StartingStateSetNodeType: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Set node type"; + ZigbeeInterfaceReply *reply = m_controller->commandSetNodeType(ZigbeeNode::NodeTypeCoordinator); + connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandSetNodeTypeFinished); + break; + } + case StartingStateStartNetwork: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Starting network"; + ZigbeeInterfaceReply *reply = m_controller->commandStartNetwork(); + connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandStartNetworkFinished); + break; + } + case StartingStateGetPermitJoinStatus: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Get permit join status"; + readPermitJoinStatus(); + break; + } + case StartingStateReadeNodeDescriptor: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Read coordinator node descriptor"; + //ZigbeeInterfaceReply *reply = m_controller->commandNodeDescriptorRequest(0x0000); + //connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandNodeDescriptorRequestFinished); + break; + } + case StartingStateReadPowerDescriptor: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Read coordinator power descriptor"; + //ZigbeeInterfaceReply *reply = m_controller->commandPowerDescriptorRequest(0x0000); + //connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandPowerDescriptorRequestFinished); + break; + } + } +} + +void ZigbeeNetworkNxp::readControllerVersion() +{ + ZigbeeInterfaceReply *reply = m_controller->commandGetVersion(); + connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply](){ + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + if (reply->additionalMessage().data().count() != 4) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << ":" << "Invalid payload size"; + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + + // Parse version + quint16 majorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(0, 2)); + quint16 minorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(2, 2)); + + //m_controllerFirmwareVersion = QString("%1.%2").arg(majorVersion).arg(minorVersion); + qCDebug(dcZigbeeNetwork()) << "Controller version:" << QString("%1.%2").arg(majorVersion).arg(minorVersion); + + if (m_startingState == StartingStateGetVersion) setStartingState(StartingStateSetPanId); + }); +} + +void ZigbeeNetworkNxp::readPermitJoinStatus() +{ + ZigbeeInterfaceReply *reply = m_controller->commandGetPermitJoinStatus(); + connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply](){ + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + qCDebug(dcZigbeeController()) << reply->additionalMessage(); + + setPermitJoining(static_cast(reply->additionalMessage().data().at(0))); + if (m_startingState == StartingStateGetPermitJoinStatus) setStartingState(StartingStateReadeNodeDescriptor); + }); +} + +void ZigbeeNetworkNxp::onCommandInitiateTouchLinkFinished() +{ + ZigbeeInterfaceReply *reply = static_cast(sender()); + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; +} + +void ZigbeeNetworkNxp::onCommandTouchLinkFactoryResetFinished() +{ + ZigbeeInterfaceReply *reply = static_cast(sender()); + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; +} + +void ZigbeeNetworkNxp::onCommandRequestLinkQualityFinished() +{ + ZigbeeInterfaceReply *reply = static_cast(sender()); + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + qCDebug(dcZigbeeController()) << reply->additionalMessage(); + + // FIXME: parsing + + quint8 sequenceNumber = static_cast(reply->additionalMessage().data().at(0)); + quint8 statusCode = static_cast(reply->additionalMessage().data().at(1)); + quint8 neighborTableEntries = static_cast(reply->additionalMessage().data().at(2)); + quint8 neighborTableListCount = static_cast(reply->additionalMessage().data().at(3)); + quint8 startIndex = static_cast(reply->additionalMessage().data().at(4)); + + qCDebug(dcZigbeeNetwork()) << "LQI response:"; + qCDebug(dcZigbeeNetwork()) << " SQN:" << ZigbeeUtils::convertByteToHexString(sequenceNumber); + qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(statusCode); + qCDebug(dcZigbeeNetwork()) << " Neighbor table entries:" << neighborTableEntries; + qCDebug(dcZigbeeNetwork()) << " Neighbor table list count:" << neighborTableListCount; + qCDebug(dcZigbeeNetwork()) << " Start index:" << startIndex; + + int offset = 5; + + // Note: according to docs, if the table has no neigbors the list will be empty + if (neighborTableEntries == 0) { + qCDebug(dcZigbeeNetwork()) << " There are no neigbors"; + return; + } + + for (int i = startIndex; i < neighborTableListCount; i++) { + + quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(offset, 2)); + quint64 panId = ZigbeeUtils::convertByteArrayToUint64(reply->additionalMessage().data().mid(offset + 2, 8)); + quint64 ieeeAddress = ZigbeeUtils::convertByteArrayToUint64(reply->additionalMessage().data().mid(offset + 10, 8)); + quint8 depth = static_cast(reply->additionalMessage().data().at(offset + 18)); + quint8 linkQuality = static_cast(reply->additionalMessage().data().at(offset + 19)); + quint8 bitMap = static_cast(reply->additionalMessage().data().at(offset + 20)); + + offset += 21; + + qCDebug(dcZigbeeNetwork()) << " Neighbor:" << i; + qCDebug(dcZigbeeNetwork()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); + qCDebug(dcZigbeeNetwork()) << " PAN id:" << panId; + qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(ieeeAddress); + qCDebug(dcZigbeeNetwork()) << " Depth:" << depth; + qCDebug(dcZigbeeNetwork()) << " Link quality:" << linkQuality; + qCDebug(dcZigbeeNetwork()) << " BitMap:" << ZigbeeUtils::convertByteToHexString(bitMap); + + // foreach (ZigbeeNode *node, nodes()) { + // if (node->extendedAddress() == ZigbeeAddress(ieeeAddress)) { + // node->setShortAddress(shortAddress); + // } + // } + } +} + +void ZigbeeNetworkNxp::processLoggingMessage(const ZigbeeInterfaceMessage &message) +{ + quint8 logLevel = static_cast(message.data().at(0)); + QString logMessage = QString::fromUtf8(message.data().right(message.data().count() - 1)); + + QString logLevelString; + switch (logLevel) { + case 0: + logLevelString = "Emergency:"; + break; + case 1: + logLevelString = "Alert:"; + break; + case 2: + logLevelString = "Critical:"; + break; + case 3: + logLevelString = "Error:"; + break; + case 4: + logLevelString = "Warning:"; + break; + case 5: + logLevelString = "Notice:"; + break; + case 6: + logLevelString = "Information:"; + break; + case 7: + logLevelString = "Debug:"; + break; + default: + logLevelString = "Unknown:"; + break; + } + + if (logLevel < 5) { + qCWarning(dcZigbeeController()).noquote() << "ControllerLog:" << logLevelString << logMessage; + } else { + qCDebug(dcZigbeeController()).noquote() << "ControllerLog:" << logLevelString << logMessage; + } +} + +void ZigbeeNetworkNxp::processFactoryNewRestart(const ZigbeeInterfaceMessage &message) +{ + quint8 controllerStatus = static_cast(message.data().at(0)); + QString controllerStatusString; + switch (controllerStatus) { + case 0: + controllerStatusString = "startup"; + break; + case 1: + controllerStatusString = "wait start"; + break; + case 2: + controllerStatusString = "NRF start"; + break; + case 3: + controllerStatusString = "discovery"; + break; + case 4: + controllerStatusString = "network init"; + break; + case 5: + controllerStatusString = "rescan"; + break; + case 6: + controllerStatusString = "running"; + break; + default: + qCWarning(dcZigbeeNetwork()) << "Unhandled controller status" << controllerStatus; + break; + } + + qCDebug(dcZigbeeNetwork()) << "Restart finished. Current controller state:" << controllerStatusString; + if (m_startingState == StartingStateReset) setStartingState(StartingStateGetVersion); +} + +void ZigbeeNetworkNxp::processNodeClusterList(const ZigbeeInterfaceMessage &message) +{ + quint8 sourceEndpoint = static_cast(message.data().at(0)); + + quint16 profileId = static_cast(message.data().at(1)); + profileId <<= 8; + profileId |= static_cast(message.data().at(2)); + + qCDebug(dcZigbeeController()) << "Node cluster list received:"; + qCDebug(dcZigbeeController()) << " Souce endpoint:" << sourceEndpoint; + qCDebug(dcZigbeeController()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast(profileId)); + + + QByteArray clusterListData = message.data().right(message.data().count() - 3); + + for (int i = 0; i < clusterListData.count(); i += 2) { + quint16 clusterId = static_cast(clusterListData.at(i)); + clusterId <<= 8; + clusterId |= clusterListData .at(i + 1); + + qCDebug(dcZigbeeController()) << " Cluster ID:" << ZigbeeUtils::clusterIdToString(static_cast(clusterId)); + } +} + +void ZigbeeNetworkNxp::processNodeAttributeList(const ZigbeeInterfaceMessage &message) +{ + quint8 sourceEndpoint = static_cast(message.data().at(0)); + + quint16 profileId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(1, 2)); + quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(3, 2)); + + qCDebug(dcZigbeeController()) << "Node attribute list received:"; + qCDebug(dcZigbeeController()) << " Souce endpoint:" << sourceEndpoint; + qCDebug(dcZigbeeController()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast(profileId)); + qCDebug(dcZigbeeController()) << " Cluster ID:" << ZigbeeUtils::clusterIdToString(static_cast(clusterId)); + + QByteArray attributeListData = message.data().right(message.data().count() - 5); + if (attributeListData.count() % 2 != 0) { + qCWarning(dcZigbeeController()) << "Attribute list is incomplete. Truncate last byte"; + attributeListData = attributeListData.left(attributeListData.count() - 1); + } + + qCWarning(dcZigbeeController()) << "Attributes" << ZigbeeUtils::convertByteArrayToHexString(attributeListData); + for (int i = 0; i < attributeListData.count(); i += 2) { + quint16 attribute = ZigbeeUtils::convertByteArrayToUint16(attributeListData.mid(i, 2)); + qCDebug(dcZigbeeController()) << " Attribute:" << ZigbeeUtils::convertUint16ToHexString(attribute); + } +} + +void ZigbeeNetworkNxp::processNodeCommandIdList(const ZigbeeInterfaceMessage &message) +{ + quint8 sourceEndpoint = static_cast(message.data().at(0)); + quint16 profileId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(1, 2)); + quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(3, 2)); + + qCDebug(dcZigbeeController()) << "Node command list received:"; + qCDebug(dcZigbeeController()) << " Souce endpoint:" << sourceEndpoint; + qCDebug(dcZigbeeController()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast(profileId)); + qCDebug(dcZigbeeController()) << " Cluster ID:" << ZigbeeUtils::clusterIdToString(static_cast(clusterId)); + + QByteArray commandListData = message.data().right(message.data().count() - 5); + + for (int i = 0; i < commandListData.count(); i++) { + quint8 attribute = static_cast(commandListData.at(i)); + qCDebug(dcZigbeeController()) << " Command:" << ZigbeeUtils::convertByteToHexString(attribute); + } +} + +void ZigbeeNetworkNxp::processDeviceAnnounce(const ZigbeeInterfaceMessage &message) +{ + QByteArray data = message.data(); + + quint16 shortAddress = 0; + quint64 ieeeAddress = 0; + quint8 macCapabilitiesFlag = 0; + + QDataStream stream(&data, QIODevice::ReadOnly); + stream >> shortAddress >> ieeeAddress >> macCapabilitiesFlag; + + qCDebug(dcZigbeeNetwork()) << "Device announced:"; + qCDebug(dcZigbeeNetwork()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); + qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(ieeeAddress); + qCDebug(dcZigbeeNetwork()) << " Mac capabilities:" << ZigbeeUtils::convertByteToHexString(macCapabilitiesFlag); + + // Check if we already have a node with this + + + // ZigbeeNode *node = createNode(); + // node->setShortAddress(shortAddress); + // node->setExtendedAddress(ZigbeeAddress(ieeeAddress)); + // node->setMacCapabilitiesFlag(macCapabilitiesFlag); + + // qCDebug(dcZigbeeNetwork()) << " Node:" << node; + + + + // // FIXME: check if node already added, and if we have to update it + // addUnitializedNode(node); + // node->setState(StateInitializing); + + // ZigbeeInterfaceReply *reply = nullptr; + // reply = m_controller->commandAuthenticateDevice(node->extendedAddress(), securityConfiguration().globalTrustCenterLinkKey()); + // connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandAuthenticateDeviceFinished); + + // reply = m_controller->commandNodeDescriptorRequest(node->shortAddress()); + // connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandNodeDescriptorRequestFinished); + + // reply = m_controller->commandSimpleDescriptorRequest(node->shortAddress(), endPoint()); + // connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandSimpleDescriptorRequestFinished); + + // reply = m_controller->commandPowerDescriptorRequest(node->shortAddress()); + // connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandPowerDescriptorRequestFinished); +} + +void ZigbeeNetworkNxp::processAttributeReport(const ZigbeeInterfaceMessage &message) +{ + QByteArray data = message.data(); + quint8 sequenceNumber = 0; + quint16 sourceAddress = 0; + quint8 endPoint = 0; + quint16 clusterId = 0; + quint16 attributeId = 0; + quint8 attributeStatus = 0; + quint8 attributDataType = 0; + quint16 dataSize = 0; + + QDataStream stream(&data, QIODevice::ReadOnly); + stream >> sequenceNumber >> sourceAddress >> endPoint >> clusterId >> attributeId >> attributeStatus >> attributDataType >> dataSize; + + Zigbee::DataType dataType = static_cast(attributDataType); + QByteArray attributeData = data.right(dataSize); + + if (attributeData.length() != dataSize) { + qCCritical(dcZigbeeNetwork()) << "HACK" << attributeData.length() << "!=" << dataSize; + // Note: the NXP firmware for JN5169 has a bug here and does not send the attributeStatus. + // Repars data without attribute status + sequenceNumber = 0; + sourceAddress = 0; + endPoint = 0; + clusterId = 0; + attributeId = 0; + attributeStatus = 0; + attributDataType = 0; + dataSize = 0; + + QDataStream alternativeStream(&data, QIODevice::ReadOnly); + alternativeStream >> sequenceNumber >> sourceAddress >> endPoint >> clusterId >> attributeId >> attributDataType >> dataSize; + + dataType = static_cast(attributDataType); + attributeData = data.right(dataSize); + } + + qCDebug(dcZigbeeNetwork()) << "Attribute report:"; + qCDebug(dcZigbeeNetwork()) << " SQN:" << ZigbeeUtils::convertByteToHexString(sequenceNumber); + qCDebug(dcZigbeeNetwork()) << " Source address:" << ZigbeeUtils::convertUint16ToHexString(sourceAddress); + qCDebug(dcZigbeeNetwork()) << " End point:" << ZigbeeUtils::convertByteToHexString(endPoint); + qCDebug(dcZigbeeNetwork()) << " Cluster:" << ZigbeeUtils::clusterIdToString(static_cast(clusterId)); + qCDebug(dcZigbeeNetwork()) << " Attribut id:" << ZigbeeUtils::convertUint16ToHexString(attributeId); + qCDebug(dcZigbeeNetwork()) << " Attribut data type:" << dataType; + qCDebug(dcZigbeeNetwork()) << " Attribut size:" << dataSize; + qCDebug(dcZigbeeNetwork()) << " Data:" << ZigbeeUtils::convertByteArrayToHexString(attributeData); + + switch (dataType) { + case Zigbee::CharString: + qCDebug(dcZigbeeNetwork()) << " Data(converted)" << QString::fromUtf8(attributeData); + break; + case Zigbee::Bool: + qCDebug(dcZigbeeNetwork()) << " Data(converted)" << static_cast(attributeData.at(0)); + break; + default: + break; + } + + // FIXME +// ZigbeeNode *node = getZigbeeNode(sourceAddress); +// if (!node) { +// qCWarning(dcZigbeeNode()) << "Received an attribute report from an unknown node. Ignoring data."; +// return; +// } + +// node->setClusterAttribute(static_cast(clusterId), ZigbeeClusterAttribute(attributeId, dataType, attributeData)); +} + +void ZigbeeNetworkNxp::processLeaveIndication(const ZigbeeInterfaceMessage &message) +{ + QByteArray data = message.data(); + quint64 extendedAddress = 0; + bool rejoining = 0; + + QDataStream stream(&data, QIODevice::ReadOnly); + stream >> extendedAddress; + stream >> rejoining; + + ZigbeeAddress address(extendedAddress); + qCDebug(dcZigbeeNetwork()) << "Node leaving indication:" << address.toString() << "rejoining:" << rejoining; + + ZigbeeNode *node = getZigbeeNode(address); + if (node) removeNode(node); +} + +void ZigbeeNetworkNxp::processRestartProvisioned(const ZigbeeInterfaceMessage &message) +{ + if (message.data().isEmpty()) + return; + + quint8 status = static_cast(message.data().at(0)); + switch (status) { + case 0: + qCDebug(dcZigbeeNetwork()) << "Restart provisioned: start up"; + break; + case 1: + qCDebug(dcZigbeeNetwork()) << "Restart provisioned: wait start"; + break; + case 2: + qCDebug(dcZigbeeNetwork()) << "Restart provisioned: NFN start"; + break; + case 3: + qCDebug(dcZigbeeNetwork()) << "Restart provisioned: discovery"; + break; + case 4: + qCDebug(dcZigbeeNetwork()) << "Restart provisioned: network init"; + break; + case 5: + qCDebug(dcZigbeeNetwork()) << "Restart provisioned: rescan"; + break; + case 6: + qCDebug(dcZigbeeNetwork()) << "Restart provisioned: running"; + break; + default: + qCDebug(dcZigbeeNetwork()) << "Restart provisioned: unknown"; + break; + } + + if (m_startingState == StartingStateReset) { + if (m_networkRunning) { + qCDebug(dcZigbeeNetwork()) << "Reset finished. Network already running. No need to set it up"; + setStartingState(StartingStateGetPermitJoinStatus); + } else { + qCDebug(dcZigbeeNetwork()) << "Reset finished. Set up network"; + setStartingState(StartingStateGetVersion); + } + } +} + +void ZigbeeNetworkNxp::processRouterDiscoveryConfirm(const ZigbeeInterfaceMessage &message) +{ + if (message.data().isEmpty()) + return; + + quint8 status = static_cast(message.data().at(0)); + Zigbee::ZigbeeNwkLayerStatus networkStatus = static_cast(message.data().at(0)); + qCDebug(dcZigbeeNetwork()) << "Router discovery confirm received" << status << networkStatus; +} + +void ZigbeeNetworkNxp::onMessageReceived(const ZigbeeInterfaceMessage &message) +{ + switch (message.messageType()) { + case Zigbee::MessageTypeLogging: + processLoggingMessage(message); + break; + case Zigbee::MessageTypeFactoryNewRestart: + processFactoryNewRestart(message); + break; + case Zigbee::MessageTypeNodeClusterList: + processNodeClusterList(message); + break; + case Zigbee::MessageTypeNodeAttributeList: + processNodeAttributeList(message); + break; + case Zigbee::MessageTypeNodeCommandIdList: + processNodeCommandIdList(message); + break; + case Zigbee::MessageTypeDeviceAnnounce: + processDeviceAnnounce(message); + break; + case Zigbee::MessageTypeAttributeReport: + processAttributeReport(message); + break; + case Zigbee::MessageTypeLeaveIndication: + processLeaveIndication(message); + break; + case Zigbee::MessageTypeNetworkJoinedFormed: + processNetworkFormed(message); + break; + case Zigbee::MessageTypeRestartProvisioned: + processRestartProvisioned(message); + break; + case Zigbee::MessageTypeRouterDiscoveryConfirm: + processRouterDiscoveryConfirm(message); + break; + default: + qCWarning(dcZigbeeController()) << "Unhandled message received:" << message; + break; + } +} + +void ZigbeeNetworkNxp::onControllerAvailableChanged(bool available) +{ + qCDebug(dcZigbeeNetwork()) << "Hardware controller is" << (available ? "now available" : "not available"); + + if (m_factoryResetting && !available) { + setStartingState(StartingStateReset); + return; + } + + if (!available) { + // FIXME +// foreach (ZigbeeNode *node, nodes()) { +// node->setConnected(false); +// } + + setError(ErrorHardwareUnavailable); + setPermitJoining(false); + setState(StateOffline); + setStartingState(StartingStateNone); + } else { + setError(ErrorNoError); + setState(StateStarting); + setStartingState(StartingStateReset); + } +} + + +//void ZigbeeNetworkNxp::requestMatchDescriptor(const quint16 &shortAddress, const Zigbee::ZigbeeProfile &profile) +//{ + +// // TargetAddress profile InputClusterCount InputClusterList OutputClusterCount OutputClusterList + +// Q_UNUSED(profile) + +// QByteArray data; +// QDataStream stream(&data, QIODevice::WriteOnly); +// stream << shortAddress; +// stream << static_cast(0xFFFF); +// stream << static_cast(0); +// stream << static_cast(0); +// stream << static_cast(0); +// stream << static_cast(0); + +// ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeMatchDescriptorRequest, data)); +// request.setExpectedAdditionalMessageType(Zigbee::MessageTypeMatchDescriptorResponse); +// request.setDescription("Request match descriptors " + ZigbeeUtils::convertUint16ToHexString(shortAddress)); +// request.setTimoutIntervall(5000); + +// ZigbeeInterfaceReply *reply = controller()->sendRequest(request); +// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onRequestMatchDescriptorFinished); +//} + +void ZigbeeNetworkNxp::onCommandResetControllerFinished() +{ + ZigbeeInterfaceReply *reply = static_cast(sender()); + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; +} + +void ZigbeeNetworkNxp::onCommandSoftResetControllerFinished() +{ + ZigbeeInterfaceReply *reply = static_cast(sender()); + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; +} + +void ZigbeeNetworkNxp::onCommandErasePersistentDataFinished() +{ + ZigbeeInterfaceReply *reply = static_cast(sender()); + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + m_factoryResetting = false; + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + if (m_startingState == StartingStateErase) { + setStartingState(StartingStateReset); + } +} + +void ZigbeeNetworkNxp::onCommandSetExtendedPanIdFinished() +{ + ZigbeeInterfaceReply *reply = static_cast(sender()); + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + if (m_startingState == StartingStateSetPanId) setStartingState(StartingStateSetChannel); +} + +void ZigbeeNetworkNxp::onCommandSetChannelMaskFinished() +{ + ZigbeeInterfaceReply *reply = static_cast(sender()); + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeNetwork()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + if (m_startingState == StartingStateSetChannel) setStartingState(StartingStateSetSecurity); +} + +void ZigbeeNetworkNxp::onCommandSetNodeTypeFinished() +{ + ZigbeeInterfaceReply *reply = static_cast(sender()); + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + if (m_startingState == StartingStateSetNodeType) setStartingState(StartingStateStartNetwork); +} + +void ZigbeeNetworkNxp::onCommandStartNetworkFinished() +{ + ZigbeeInterfaceReply *reply = static_cast(sender()); + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeNetwork()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + qCDebug(dcZigbeeController()) << reply->additionalMessage(); + processNetworkFormed(reply->additionalMessage()); + if (m_startingState == StartingStateStartNetwork) setStartingState(StartingStateGetPermitJoinStatus); +} + +void ZigbeeNetworkNxp::onCommandStartScanFinished() +{ + ZigbeeInterfaceReply *reply = static_cast(sender()); + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + qCDebug(dcZigbeeController()) << reply->additionalMessage(); + processNetworkFormed(reply->additionalMessage()); +} + +void ZigbeeNetworkNxp::onCommandRequestMatchDescriptorFinished() +{ + ZigbeeInterfaceReply *reply = static_cast(sender()); + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + qCDebug(dcZigbeeController()) << reply->additionalMessage(); +} + +void ZigbeeNetworkNxp::onCommandSetSecurityFinished() +{ + ZigbeeInterfaceReply *reply = static_cast(sender()); + reply->deleteLater(); + + if (reply->status() != ZigbeeInterfaceReply::Success) { + qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); + return; + } + + qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + if (m_startingState == StartingStateSetSecurity) setStartingState(StartingStateSetNodeType); +} + +void ZigbeeNetworkNxp::processNetworkFormed(const ZigbeeInterfaceMessage &message) +{ + // Parse network status + QByteArray data = message.data(); + quint8 networkStatus = static_cast(data.at(0)); + QString networkStatusString; + + bool success = false; + + if (networkStatus == 0) { + networkStatusString = "joined"; + success = true; + } else if (networkStatus == 1) { + networkStatusString = "created"; + success = true; + } else if (networkStatus >= 128 && networkStatus <= 244) { + networkStatusString = "failed: Zigbee event code: " + QString::number(networkStatus); + } else { + networkStatusString = "unknown"; + } + + if (!success) { + qCWarning(dcZigbeeNetwork()) << "Forming network failed" << networkStatusString; + setPermitJoining(false); + setStartingState(StartingStateNone); + setState(StateOffline); + setError(ErrorZigbeeError); + m_networkRunning = false; + return; + } + + quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(data.mid(1, 2)); + quint64 extendedAddress = ZigbeeUtils::convertByteArrayToUint64(data.mid(3, 8)); + + // Parse network channel + quint8 channel = static_cast(data.at(11)); + + qCDebug(dcZigbeeNetwork()).noquote() << "Network" << networkStatusString; + qCDebug(dcZigbeeNetwork()) << " Extended PAN ID:" << extendedPanId(); + qCDebug(dcZigbeeNetwork()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); + qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(extendedAddress); + qCDebug(dcZigbeeNetwork()) << " Channel:" << channel; + qCDebug(dcZigbeeNetwork()) << " Permit joining:" << permitJoining(); + + m_networkRunning = true; + + // FIXME: create coordinator node + +// // Set the node information +// setShortAddress(shortAddress); +// setExtendedAddress(ZigbeeAddress(extendedAddress)); +// setChannel(channel); + +// if (!hasNode(this->shortAddress())) +// addUnitializedNode(this); + +} + +void ZigbeeNetworkNxp::startNetwork() +{ + qCDebug(dcZigbeeNetwork()) << "Start network..."; + if (m_controller) { + qCDebug(dcZigbeeNetwork()) << "Clean up old controller..."; + delete m_controller; + m_controller = nullptr; + } + + qCDebug(dcZigbeeNetwork()) << "Create new controller..."; + m_controller = new ZigbeeBridgeControllerNxp(this); + connect(m_controller, &ZigbeeBridgeControllerNxp::messageReceived, this, &ZigbeeNetworkNxp::onMessageReceived); + connect(m_controller, &ZigbeeBridgeControllerNxp::availableChanged, this, &ZigbeeNetworkNxp::onControllerAvailableChanged); + + if (state() == StateUninitialized) + loadNetwork(); + + if (!m_controller->enable(serialPortName(), serialBaudrate())) { + setPermitJoining(false); + setState(StateOffline); + setStartingState(StartingStateNone); + setError(ErrorHardwareUnavailable); + } else { + // Reset + setStartingState(StartingStateReset); + setState(StateStarting); + } +} + +void ZigbeeNetworkNxp::stopNetwork() +{ + qCDebug(dcZigbeeNetwork()) << "Stopping network..."; + setState(StateStopping); + if (m_controller) { + delete m_controller; + m_controller = nullptr; + } + + setStartingState(StartingStateNone); + setPermitJoining(false); + setState(StateOffline); + setError(ErrorNoError); +} + +void ZigbeeNetworkNxp::factoryResetNetwork() +{ + qCDebug(dcZigbeeNetwork()) << "Factory reset network and forget all information. This cannot be undone."; + clearSettings(); + + setState(StateStarting); + setStartingState(StartingStateErase); +} + diff --git a/libnymea-zigbee/nxp/zigbeenetworknxp.h b/libnymea-zigbee/nxp/zigbeenetworknxp.h index 8252fb6..740e18f 100644 --- a/libnymea-zigbee/nxp/zigbeenetworknxp.h +++ b/libnymea-zigbee/nxp/zigbeenetworknxp.h @@ -3,6 +3,7 @@ #include #include "../zigbeenetwork.h" +#include "zigbeebridgecontrollernxp.h" class ZigbeeNetworkNxp : public ZigbeeNetwork { @@ -10,7 +11,71 @@ class ZigbeeNetworkNxp : public ZigbeeNetwork public: explicit ZigbeeNetworkNxp(QObject *parent = nullptr); -signals: +private: + enum StartingState { + StartingStateNone, + StartingStateErase, + StartingStateReset, + StartingStateGetVersion, + StartingStateSetPanId, + StartingStateSetChannel, + StartingStateSetSecurity, + StartingStateSetNodeType, + StartingStateStartNetwork, + StartingStateGetPermitJoinStatus, + StartingStateReadeNodeDescriptor, + StartingStateReadPowerDescriptor + }; + + ZigbeeBridgeControllerNxp *m_controller = nullptr; + bool m_networkRunning = false; + bool m_factoryResetting = false; + StartingState m_startingState = StartingStateNone; + + void setStartingState(StartingState state); + void readControllerVersion(); + void readPermitJoinStatus(); + +private slots: + void onMessageReceived(const ZigbeeInterfaceMessage &message); + void onControllerAvailableChanged(bool available); + + // Controller command finished slots + void onCommandResetControllerFinished(); + void onCommandSoftResetControllerFinished(); + void onCommandErasePersistentDataFinished(); + void onCommandSetExtendedPanIdFinished(); + void onCommandSetChannelMaskFinished(); + void onCommandSetNodeTypeFinished(); + void onCommandStartNetworkFinished(); + void onCommandStartScanFinished(); + void onCommandEnableWhitelistFinished(); + +// void onCommandNodeDescriptorRequestFinished(); +// void onCommandSimpleDescriptorRequestFinished(); +// void onCommandPowerDescriptorRequestFinished(); + + void onCommandInitiateTouchLinkFinished(); + void onCommandTouchLinkFactoryResetFinished(); + void onCommandRequestLinkQualityFinished(); + + void onCommandRequestMatchDescriptorFinished(); + void onCommandSetSecurityFinished(); + void onCommandNetworkAddressRequestFinished(); + void onCommandAuthenticateDeviceFinished(); + + // Process controller notifications/messages + void processNetworkFormed(const ZigbeeInterfaceMessage &message); + void processLoggingMessage(const ZigbeeInterfaceMessage &message); + void processFactoryNewRestart(const ZigbeeInterfaceMessage &message); + void processNodeClusterList(const ZigbeeInterfaceMessage &message); + void processNodeAttributeList(const ZigbeeInterfaceMessage &message); + void processNodeCommandIdList(const ZigbeeInterfaceMessage &message); + void processDeviceAnnounce(const ZigbeeInterfaceMessage &message); + void processAttributeReport(const ZigbeeInterfaceMessage &message); + void processLeaveIndication(const ZigbeeInterfaceMessage &message); + void processRestartProvisioned(const ZigbeeInterfaceMessage &message); + void processRouterDiscoveryConfirm(const ZigbeeInterfaceMessage &message); public slots: void startNetwork() override; diff --git a/libnymea-zigbee/zigbeenetwork.cpp b/libnymea-zigbee/zigbeenetwork.cpp index 528aa50..6bf9bc2 100644 --- a/libnymea-zigbee/zigbeenetwork.cpp +++ b/libnymea-zigbee/zigbeenetwork.cpp @@ -129,6 +129,21 @@ void ZigbeeNetwork::setSecurityConfiguration(const ZigbeeSecurityConfiguration & emit securityConfigurationChanged(m_securityConfiguration); } +bool ZigbeeNetwork::permitJoining() const +{ + return m_permitJoining; +} + +void ZigbeeNetwork::setPermitJoining(bool permitJoining) +{ + if (m_permitJoining == permitJoining) + return; + + qCDebug(dcZigbeeNetwork()) << "Permit joining changed to" << permitJoining; + m_permitJoining = permitJoining; + emit permitJoiningChanged(m_permitJoining); +} + QList ZigbeeNetwork::nodes() const { return m_nodes; @@ -242,7 +257,7 @@ void ZigbeeNetwork::loadNetwork() foreach (const QString ieeeAddressString, settings.childGroups()) { settings.beginGroup(ieeeAddressString); - ZigbeeNode *node = createNode(); + ZigbeeNode *node = new ZigbeeNode(this); node->setExtendedAddress(ZigbeeAddress(ieeeAddressString)); node->setShortAddress(static_cast(settings.value("nwkAddress", 0).toUInt())); node->setMacCapabilitiesFlag(static_cast(settings.value("macCapabilitiesFlag", 0).toUInt())); @@ -285,8 +300,8 @@ void ZigbeeNetwork::loadNetwork() // settings.endGroup(); // clusterId // } // settings.endGroup(); // outputCluster - - node->setState(StateInitialized); + //FIXME + //node->setState(StateInitialized); addNodeInternally(node); settings.endGroup(); // ieeeAddress diff --git a/libnymea-zigbee/zigbeenetwork.h b/libnymea-zigbee/zigbeenetwork.h index fb661d2..c38f78d 100644 --- a/libnymea-zigbee/zigbeenetwork.h +++ b/libnymea-zigbee/zigbeenetwork.h @@ -41,7 +41,7 @@ class ZigbeeNetwork : public QObject public: enum State { StateUninitialized, - StateDisconnected, + StateOffline, StateStarting, StateRunning, StateStopping @@ -81,6 +81,9 @@ public: ZigbeeSecurityConfiguration securityConfiguration() const; void setSecurityConfiguration(const ZigbeeSecurityConfiguration &securityConfiguration); + bool permitJoining() const; + void setPermitJoining(bool permitJoining); + QList nodes() const; ZigbeeNode *coordinatorNode() const; @@ -105,6 +108,7 @@ private: uint m_channel = 0; ZigbeeSecurityConfiguration m_securityConfiguration; ZigbeeNode::NodeType m_nodeType = ZigbeeNode::NodeTypeCoordinator; + bool m_permitJoining = false; QString m_settingsFileName = "/etc/nymea/nymea-zigbee.conf"; QList m_nodes; @@ -125,8 +129,6 @@ protected: void addUnitializedNode(ZigbeeNode *node); void removeNode(ZigbeeNode *node); - ZigbeeNode *createNode(); - void setState(State state); void setError(Error error); diff --git a/libnymea-zigbee/zigbeenetworkmanager.cpp b/libnymea-zigbee/zigbeenetworkmanager.cpp index 5ea7717..33b8477 100644 --- a/libnymea-zigbee/zigbeenetworkmanager.cpp +++ b/libnymea-zigbee/zigbeenetworkmanager.cpp @@ -29,1384 +29,43 @@ #include "loggingcategory.h" #include "zigbeeutils.h" +#include "nxp/zigbeenetworknxp.h" + #include #include #include -ZigbeeNetworkManager::ZigbeeNetworkManager(QObject *parent) : - QObject(parent) +ZigbeeNetworkManager::ZigbeeNetworkManager(const QSerialPortInfo &serialPortInfo, QSerialPort::BaudRate baudrate, BackendType backendType, QObject *parent) : + QObject(parent), + m_serialPortInfo(serialPortInfo), + m_baudrate(baudrate), + m_backendType(backendType) { - -} - -QString ZigbeeNetworkManager::controllerFirmwareVersion() const -{ - return m_controllerFirmwareVersion; -} - -ZigbeeBridgeController *ZigbeeNetworkManager::controller() const -{ - return m_controller; -} - -bool ZigbeeNetworkManager::networkRunning() const -{ - return state() == ZigbeeNetwork::StateRunning; -} - -bool ZigbeeNetworkManager::permitJoining() const -{ - return m_permitJoining; -} - -void ZigbeeNetworkManager::setPermitJoining(bool permitJoining) -{ - if (m_permitJoining == permitJoining) - return; - - ZigbeeInterfaceReply *reply = m_controller->commandPermitJoin(0, (permitJoining ? 255 : 0)); - connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply, permitJoining](){ - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully." << permitJoining; - - // Read the permit joining status back in order to update the state - readPermitJoinStatus(); - }); -} - -void ZigbeeNetworkManager::resetController() -{ - ZigbeeInterfaceReply *reply = m_controller->commandResetController(); - connect(reply, &ZigbeeInterfaceReply::finished, this, [reply](){ - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - }); -} - -void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState state) -{ - if (m_startingState == state) - return; - - m_startingState = state; - - switch (m_startingState) { - case StartingStateNone: - break; - case StartingStateErase: { - m_networkRunning = false; - qCDebug(dcZigbeeNetwork()) << "Starting state changed: Erase persistant data"; - ZigbeeInterfaceReply *reply = m_controller->commandErasePersistantData(); - connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandErasePersistentDataFinished); - break; - } - case StartingStateReset: { - m_networkRunning = false; - - // qCDebug(dcZigbeeNetwork()) << ""; - // ZigbeeInterfaceReply *reply = m_controller->commandSoftResetController(); - // connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply](){ - // reply->deleteLater(); - - // }); - qCDebug(dcZigbeeNetwork()) << "Starting state changed: Reset controller"; - ZigbeeInterfaceReply *reply = m_controller->commandResetController(); - connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandResetControllerFinished); - break; - } - case StartingStateGetVersion: { - qCDebug(dcZigbeeNetwork()) << "Starting state changed: Get controller version"; - readControllerVersion(); - break; - } - case StartingStateSetPanId: { - qCDebug(dcZigbeeNetwork()) << "Starting state changed: Set PAN ID"; - if (extendedPanId() == 0) { - setExtendedPanId(ZigbeeUtils::generateRandomPanId()); - } - ZigbeeInterfaceReply *reply = m_controller->commandSetExtendedPanId(extendedPanId()); - connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSetExtendedPanIdFinished); - break; - } - case StartingStateSetChannel: { - // Create channel mask - // Note: normal number passed, that specific channel will be used || Bitfield: all channels would be 0x07FFF800 - // 0x07fff800 select from all channels 11 - 26 - // 0x02108800 primary zigbee light link channels 11, 15, 20, 25 - - qCDebug(dcZigbeeNetwork()) << "Starting state changed: Set channel mask"; - ZigbeeInterfaceReply *reply = nullptr; - if (channel() == 0) { - qCDebug(dcZigbeeNetwork()) << "Autoselect quitest channel for the zigbee network. FIXME: currently hardcoded to 13 due to firmware error."; - quint32 channelMask = 0; - channelMask |= 1 << (13); - reply = m_controller->commandSetChannelMask(channelMask); - } else { - quint32 channelMask = 0; - channelMask |= 1 << (channel()); - qCDebug(dcZigbeeNetwork()) << "Using channel" << channel() << "for the zigbee network."; - reply = m_controller->commandSetChannelMask(channelMask); - } - connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSetChannelMaskFinished); - break; - } - case StartingStateSetSecurity: { - qCDebug(dcZigbeeNetwork()) << "Starting state changed: Set security configuration"; - ZigbeeInterfaceReply *reply = m_controller->commandSetSecurityStateAndKey(4, 0, 1, "5A6967426565416C6C69616E63653039"); - connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSetSecurityFinished); - break; - } - case StartingStateSetNodeType: { - qCDebug(dcZigbeeNetwork()) << "Starting state changed: Set node type"; - ZigbeeInterfaceReply *reply = m_controller->commandSetNodeType(ZigbeeNode::NodeTypeCoordinator); - connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSetNodeTypeFinished); - break; - } - case StartingStateStartNetwork: { - qCDebug(dcZigbeeNetwork()) << "Starting state changed: Starting network"; - ZigbeeInterfaceReply *reply = m_controller->commandStartNetwork(); - connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandStartNetworkFinished); - break; - } - case StartingStateGetPermitJoinStatus: { - qCDebug(dcZigbeeNetwork()) << "Starting state changed: Get permit join status"; - readPermitJoinStatus(); - break; - } - case StartingStateReadeNodeDescriptor: { - qCDebug(dcZigbeeNetwork()) << "Starting state changed: Read coordinator node descriptor"; - ZigbeeInterfaceReply *reply = m_controller->commandNodeDescriptorRequest(shortAddress()); - connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished); - break; - } - case StartingStateReadPowerDescriptor: { - qCDebug(dcZigbeeNetwork()) << "Starting state changed: Read coordinator power descriptor"; - ZigbeeInterfaceReply *reply = m_controller->commandPowerDescriptorRequest(shortAddress()); - connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished); - break; - } - } -} - -void ZigbeeNetworkManager::readControllerVersion() -{ - ZigbeeInterfaceReply *reply = m_controller->commandGetVersion(); - connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply](){ - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - if (reply->additionalMessage().data().count() != 4) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << ":" << "Invalid payload size"; - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - - // Parse version - quint16 majorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(0, 2)); - quint16 minorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(2, 2)); - - m_controllerFirmwareVersion = QString("%1.%2").arg(majorVersion).arg(minorVersion); - qCDebug(dcZigbeeNetwork()) << "Controller version:" << m_controllerFirmwareVersion; - - if (m_startingState == StartingStateGetVersion) setStartingState(StartingStateSetPanId); - }); -} - -void ZigbeeNetworkManager::readPermitJoinStatus() -{ - ZigbeeInterfaceReply *reply = m_controller->commandGetPermitJoinStatus(); - connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply](){ - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - qCDebug(dcZigbeeController()) << reply->additionalMessage(); - - m_permitJoining = static_cast(reply->additionalMessage().data().at(0)); - emit permitJoiningChanged(m_permitJoining); - - if (m_startingState == StartingStateGetPermitJoinStatus) setStartingState(StartingStateReadeNodeDescriptor); - }); -} - -//void ZigbeeNetworkManager::requestMatchDescriptor(const quint16 &shortAddress, const Zigbee::ZigbeeProfile &profile) -//{ - -// // TargetAddress profile InputClusterCount InputClusterList OutputClusterCount OutputClusterList - -// Q_UNUSED(profile) - -// QByteArray data; -// QDataStream stream(&data, QIODevice::WriteOnly); -// stream << shortAddress; -// stream << static_cast(0xFFFF); -// stream << static_cast(0); -// stream << static_cast(0); -// stream << static_cast(0); -// stream << static_cast(0); - -// ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeMatchDescriptorRequest, data)); -// request.setExpectedAdditionalMessageType(Zigbee::MessageTypeMatchDescriptorResponse); -// request.setDescription("Request match descriptors " + ZigbeeUtils::convertUint16ToHexString(shortAddress)); -// request.setTimoutIntervall(5000); - -// ZigbeeInterfaceReply *reply = controller()->sendRequest(request); -// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onRequestMatchDescriptorFinished); -//} - -void ZigbeeNetworkManager::onCommandResetControllerFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; -} - -void ZigbeeNetworkManager::onCommandSoftResetControllerFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; -} - -void ZigbeeNetworkManager::onCommandErasePersistentDataFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - m_factoryResetting = false; - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - if (m_startingState == StartingStateErase) { - setStartingState(StartingStateReset); - } -} - -void ZigbeeNetworkManager::onCommandSetExtendedPanIdFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - if (m_startingState == StartingStateSetPanId) setStartingState(StartingStateSetChannel); -} - -void ZigbeeNetworkManager::onCommandSetChannelMaskFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeNetwork()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - if (m_startingState == StartingStateSetChannel) setStartingState(StartingStateSetSecurity); -} - -void ZigbeeNetworkManager::onCommandSetNodeTypeFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - if (m_startingState == StartingStateSetNodeType) setStartingState(StartingStateStartNetwork); -} - -void ZigbeeNetworkManager::onCommandStartNetworkFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeNetwork()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - qCDebug(dcZigbeeController()) << reply->additionalMessage(); - processNetworkFormed(reply->additionalMessage()); - if (m_startingState == StartingStateStartNetwork) setStartingState(StartingStateGetPermitJoinStatus); -} - -void ZigbeeNetworkManager::onCommandStartScanFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - qCDebug(dcZigbeeController()) << reply->additionalMessage(); - processNetworkFormed(reply->additionalMessage()); -} - -void ZigbeeNetworkManager::onCommandRequestMatchDescriptorFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - qCDebug(dcZigbeeController()) << reply->additionalMessage(); -} - -void ZigbeeNetworkManager::onCommandSetSecurityFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - if (m_startingState == StartingStateSetSecurity) setStartingState(StartingStateSetNodeType); -} - -void ZigbeeNetworkManager::onCommandNetworkAddressRequestFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - qCDebug(dcZigbeeController()) << reply->additionalMessage(); - - quint8 sequenceNumber = static_cast(reply->additionalMessage().data().at(0)); - quint8 statusCode = static_cast(reply->additionalMessage().data().at(1)); - quint64 ieeeAddress = ZigbeeUtils::convertByteArrayToUint64(reply->additionalMessage().data().mid(2, 8)); - quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(10, 2)); - quint8 deviceCount = static_cast(reply->additionalMessage().data().at(12)); - quint8 startIndex = static_cast(reply->additionalMessage().data().at(13)); - - qCDebug(dcZigbeeNetwork()) << "Network address response:"; - qCDebug(dcZigbeeNetwork()) << " SQN:" << sequenceNumber; - qCDebug(dcZigbeeNetwork()) << " Status:" << statusCode; - qCDebug(dcZigbeeNetwork()) << " Address:" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress); - qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(ieeeAddress); - qCDebug(dcZigbeeNetwork()) << " Deice count:" << deviceCount; - qCDebug(dcZigbeeNetwork()) << " Start index:" << startIndex; - -} - -void ZigbeeNetworkManager::onCommandAuthenticateDeviceFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - qCDebug(dcZigbeeController()) << reply->additionalMessage(); - - quint64 gatewayIeeeAddress = ZigbeeUtils::convertByteArrayToUint64(reply->additionalMessage().data().mid(0, 8)); - QString encryptedKey = reply->additionalMessage().data().mid(8, 16).toHex(); - QByteArray mic = reply->additionalMessage().data().mid(24, 4); - quint64 initiatorIeeeAddress = ZigbeeUtils::convertByteArrayToUint64(reply->additionalMessage().data().mid(28, 8)); - quint8 activeKeySequenceNumber = static_cast(reply->additionalMessage().data().at(36)); - quint8 channel = static_cast(reply->additionalMessage().data().at(37)); - quint16 shortPan = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(38, 2)); - quint64 extendedPanId = ZigbeeUtils::convertByteArrayToUint64(reply->additionalMessage().data().mid(40, 8)); - - qCDebug(dcZigbeeNetwork()) << "Authentication response:"; - qCDebug(dcZigbeeNetwork()) << " Gateways address:" << ZigbeeAddress(gatewayIeeeAddress); - qCDebug(dcZigbeeNetwork()) << " Key:" << encryptedKey; - qCDebug(dcZigbeeNetwork()) << " MIC:" << mic.toHex(); - qCDebug(dcZigbeeNetwork()) << " Initiator address:" << ZigbeeAddress(initiatorIeeeAddress); - qCDebug(dcZigbeeNetwork()) << " Active key sequence number:" << activeKeySequenceNumber; - qCDebug(dcZigbeeNetwork()) << " Channel:" << channel; - qCDebug(dcZigbeeNetwork()) << " Short PAN ID:" << ZigbeeUtils::convertUint16ToHexString(shortPan); - qCDebug(dcZigbeeNetwork()) << " Extended PAN ID:" << extendedPanId << ZigbeeUtils::convertUint64ToHexString(extendedPanId); -} - -void ZigbeeNetworkManager::processNetworkFormed(const ZigbeeInterfaceMessage &message) -{ - // Parse network status - QByteArray data = message.data(); - quint8 networkStatus = static_cast(data.at(0)); - QString networkStatusString; - - bool success = false; - - if (networkStatus == 0) { - networkStatusString = "joined"; - success = true; - } else if (networkStatus == 1) { - networkStatusString = "created"; - success = true; - } - - if (!success) { - qCWarning(dcZigbeeNetwork()) << "Forming network failed" << networkStatus << static_cast(networkStatus); - setError(ErrorZigbeeError); - setStartingState(StartingStateNone); - setState(StateDisconnected); - m_networkRunning = false; - return; - } - - quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(data.mid(1, 2)); - quint64 extendedAddress = ZigbeeUtils::convertByteArrayToUint64(data.mid(3, 8)); - - // Parse network channel - quint8 channel = static_cast(data.at(11)); - - qCDebug(dcZigbeeNetwork()).noquote() << "Network" << networkStatusString; - qCDebug(dcZigbeeNetwork()) << " Extended PAN ID:" << extendedPanId(); - qCDebug(dcZigbeeNetwork()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); - qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(extendedAddress); - qCDebug(dcZigbeeNetwork()) << " Channel:" << channel; - qCDebug(dcZigbeeNetwork()) << " Permit joining:" << permitJoining(); - - m_networkRunning = true; - - // Set the node information - setShortAddress(shortAddress); - setExtendedAddress(ZigbeeAddress(extendedAddress)); - setChannel(channel); - - if (!hasNode(this->shortAddress())) - addUnitializedNode(this); - -} - -void ZigbeeNetworkManager::onCommandEnableWhitelistFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; -} - -void ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished() -{ -// ZigbeeInterfaceReply *reply = static_cast(sender()); -// reply->deleteLater(); - -// if (reply->status() != ZigbeeInterfaceReply::Success) { -// qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); -// return; -// } - -// qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; -// qCDebug(dcZigbeeController()) << reply->additionalMessage(); - - -// QByteArray data = reply->additionalMessage().data(); - -// quint8 sequenceNumber = 0; -// quint8 status = 0; -// quint16 shortAddress = 0; -// quint16 manufacturerCode = 0; -// quint16 maximalRxSize = 0; -// quint16 maximalTxSize = 0; -// quint16 serverMask = 0; -// quint8 descriptorFlag = 0; -// quint8 macFlags = 0; -// quint8 maxBufferSize = 0; -// quint16 bitField = 0; - -// QDataStream stream(&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); -// node->setMaximumRxSize(maximalRxSize); -// node->setMaximumTxSize(maximalTxSize); -// node->setMaximumBufferSize(maxBufferSize); -// node->setServerMask(serverMask); -// node->setMacCapabilitiesFlag(macFlags); -// node->setDescriptorFlag(descriptorFlag); - -// // Parse bit field -// // 0-2 Bit = logical type, 0 = coordinator, 1 = router, 2 = end device -// if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) { -// node->setNodeType(NodeTypeCoordinator); -// } else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) { -// node->setNodeType(NodeTypeRouter); -// } else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) { -// node->setNodeType(NodeTypeEndDevice); -// } - -// node->setComplexDescriptorAvailable((bitField >> 3) & 0x0001); -// node->setUserDescriptorAvailable((bitField >> 4) & 0x0001); - -// qCDebug(dcZigbeeNetwork()) << "Node descriptor:"; -// qCDebug(dcZigbeeNetwork()) << " Node type:" << node->nodeType(); -// qCDebug(dcZigbeeNetwork()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber); -// qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(status); -// qCDebug(dcZigbeeNetwork()) << " Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); -// qCDebug(dcZigbeeNetwork()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode); -// qCDebug(dcZigbeeNetwork()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(node->maximumRxSize()); -// qCDebug(dcZigbeeNetwork()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(node->maximumTxSize()); -// qCDebug(dcZigbeeNetwork()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(node->maximumBufferSize()); -// qCDebug(dcZigbeeNetwork()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask); -// qCDebug(dcZigbeeNetwork()) << " Primary Trust center:" << node->isPrimaryTrustCenter(); -// qCDebug(dcZigbeeNetwork()) << " Backup Trust center:" << node->isBackupTrustCenter(); -// qCDebug(dcZigbeeNetwork()) << " Primary Binding cache:" << node->isPrimaryBindingCache(); -// qCDebug(dcZigbeeNetwork()) << " Backup Binding cache:" << node->isBackupBindingCache(); -// qCDebug(dcZigbeeNetwork()) << " Primary Discovery cache:" << node->isPrimaryDiscoveryCache(); -// qCDebug(dcZigbeeNetwork()) << " Backup Discovery cache:" << node->isBackupDiscoveryCache(); -// qCDebug(dcZigbeeNetwork()) << " Network Manager:" << node->isNetworkManager(); -// qCDebug(dcZigbeeNetwork()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorFlag); -// qCDebug(dcZigbeeNetwork()) << " Extended active endpoint list available:" << node->extendedActiveEndpointListAvailable(); -// qCDebug(dcZigbeeNetwork()) << " Extended simple descriptor list available:" << node->extendedSimpleDescriptorListAvailable(); -// qCDebug(dcZigbeeNetwork()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macFlags); -// qCDebug(dcZigbeeNetwork()) << " Alternate PAN coordinator:" << node->alternatePanCoordinator(); -// qCDebug(dcZigbeeNetwork()) << " Device type:" << node->deviceType(); -// qCDebug(dcZigbeeNetwork()) << " Power source flag main power:" << node->powerSourceFlagMainPower(); -// qCDebug(dcZigbeeNetwork()) << " Receiver on when idle:" << node->receiverOnWhenIdle(); -// qCDebug(dcZigbeeNetwork()) << " Security capability:" << node->securityCapability(); -// qCDebug(dcZigbeeNetwork()) << " Allocate address:" << node->allocateAddress(); -// qCDebug(dcZigbeeNetwork()) << " Bit field:" << ZigbeeUtils::convertUint16ToHexString(bitField); -// qCDebug(dcZigbeeNetwork()) << " Complex desciptor available:" << node->complexDescriptorAvailable(); -// qCDebug(dcZigbeeNetwork()) << " User desciptor available:" << node->userDescriptorAvailable(); - -// if (m_startingState == StartingStateReadeNodeDescriptor) setStartingState(StartingStateReadPowerDescriptor); -} - -void ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - qCDebug(dcZigbeeController()) << reply->additionalMessage(); - - QByteArray data = reply->additionalMessage().data(); - - 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; - - QDataStream stream(&data, QIODevice::ReadOnly); - stream >> sequenceNumber; - stream >> status; - stream >> shortAddress; - stream >> length; - - if (length == 0) { - qCWarning(dcZigbeeNetwork()) << "Simple node descriptior has a length of 0."; - return; - } - - 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(shortAddress); - qCDebug(dcZigbeeNetwork()) << " Lenght:" << ZigbeeUtils::convertByteToHexString(length); - qCDebug(dcZigbeeNetwork()) << " End Point:" << ZigbeeUtils::convertByteToHexString(endPoint); - qCDebug(dcZigbeeNetwork()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast(profileId)); - - if (profileId == Zigbee::ZigbeeProfileLightLink) { - qCDebug(dcZigbeeNetwork()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast(deviceId); - } else { - qCDebug(dcZigbeeNetwork()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast(deviceId); - } - - qCDebug(dcZigbeeNetwork()) << " Bit field:" << ZigbeeUtils::convertByteToHexString(bitField); - - 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(clusterId)); - } - - 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(clusterId)); - } - - // 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->setEndPoint(endPoint); -// node->setZigbeeProfile(static_cast(profileId)); -// node->setDeviceId(deviceId); -} - -void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished() -{ -// ZigbeeInterfaceReply *reply = static_cast(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); -// return; -// } -// if (node->state() != ZigbeeNode::StateInitialized) { -// node->setState(ZigbeeNode::StateInitialized); -// } -// return; -// } - -// qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; -// qCDebug(dcZigbeeController()) << reply->additionalMessage(); - -// quint8 sequenceNumber = static_cast(reply->additionalMessage().data().at(0)); -// quint8 status = static_cast(reply->additionalMessage().data().at(1)); - -// quint16 bitField = static_cast(reply->additionalMessage().data().at(2)); -// bitField <<= 8; -// bitField |= static_cast(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)) { -// powerMode = PowerModeAlwaysOn; -// } else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) { -// powerMode = PowerModeOnPeriodically; -// } else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) { -// powerMode = PowerModeOnWhenStimulated; -// } - -// // Bit 4 - 7 Available power sources -// // Bit 0: Permanent mains supply -// // Bit 1: Rechargeable battery -// // Bit 2: Disposable battery -// // Bit 4: Reserved - -// QList availablePowerSources; -// if (ZigbeeUtils::checkBitUint16(bitField, 4)) { -// availablePowerSources.append(PowerSourcePermanentMainSupply); -// } else if (ZigbeeUtils::checkBitUint16(bitField, 5)) { -// availablePowerSources.append(PowerSourceRecharchableBattery); -// } else if (ZigbeeUtils::checkBitUint16(bitField, 6)) { -// 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)) { -// powerSource = PowerSourcePermanentMainSupply; -// } else if (ZigbeeUtils::checkBitUint16(bitField, 9)) { -// powerSource = PowerSourceRecharchableBattery; -// } else if (ZigbeeUtils::checkBitUint16(bitField, 10)) { -// powerSource = PowerSourceDisposableBattery; -// } - -// // Bit 12 - 15: Battery level if available -// // 0000: Critically low -// // 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)) { -// powerLevel = PowerLevelCriticalLow; -// } else if (ZigbeeUtils::checkBitUint16(bitField, 14) && !ZigbeeUtils::checkBitUint16(bitField, 15)) { -// powerLevel = PowerLevelLow; -// } else if (!ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) { -// powerLevel = PowerLevelOk; -// } else if (ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) { -// powerLevel = PowerLevelFull; -// } - -// qCDebug(dcZigbeeNetwork()) << "Node power descriptor:"; -// qCDebug(dcZigbeeNetwork()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber); -// qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(status); -// qCDebug(dcZigbeeNetwork()) << " Bitfiled:" << ZigbeeUtils::convertUint16ToHexString(bitField); -// qCDebug(dcZigbeeNetwork()) << " Power mode:" << m_powerMode; -// qCDebug(dcZigbeeNetwork()) << " Available power sources:"; -// foreach (const PowerSource &source, availablePowerSources) { -// qCDebug(dcZigbeeNetwork()) << " " << source; -// } -// 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); -// 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); -// readControllerVersion(); -// foreach (ZigbeeNode *node, nodes()) { -// node->setConnected(true); -// } -// } -} - -void ZigbeeNetworkManager::onCommandInitiateTouchLinkFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; -} - -void ZigbeeNetworkManager::onCommandTouchLinkFactoryResetFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; -} - -void ZigbeeNetworkManager::onCommandRequestLinkQualityFinished() -{ - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); - - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } - - qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - qCDebug(dcZigbeeController()) << reply->additionalMessage(); - - quint8 sequenceNumber = static_cast(reply->additionalMessage().data().at(0)); - quint8 statusCode = static_cast(reply->additionalMessage().data().at(1)); - quint8 neighborTableEntries = static_cast(reply->additionalMessage().data().at(2)); - quint8 neighborTableListCount = static_cast(reply->additionalMessage().data().at(3)); - quint8 startIndex = static_cast(reply->additionalMessage().data().at(4)); - - qCDebug(dcZigbeeNetwork()) << "LQI response:"; - qCDebug(dcZigbeeNetwork()) << " SQN:" << ZigbeeUtils::convertByteToHexString(sequenceNumber); - qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(statusCode); - qCDebug(dcZigbeeNetwork()) << " Neighbor table entries:" << neighborTableEntries; - qCDebug(dcZigbeeNetwork()) << " Neighbor table list count:" << neighborTableListCount; - qCDebug(dcZigbeeNetwork()) << " Start index:" << startIndex; - - int offset = 5; - - // Note: according to docs, if the table has no neigbors the list will be empty - if (neighborTableEntries == 0) { - qCDebug(dcZigbeeNetwork()) << " There are no neigbors"; - return; - } - - for (int i = startIndex; i < neighborTableListCount; i++) { - - quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(offset, 2)); - quint64 panId = ZigbeeUtils::convertByteArrayToUint64(reply->additionalMessage().data().mid(offset + 2, 8)); - quint64 ieeeAddress = ZigbeeUtils::convertByteArrayToUint64(reply->additionalMessage().data().mid(offset + 10, 8)); - quint8 depth = static_cast(reply->additionalMessage().data().at(offset + 18)); - quint8 linkQuality = static_cast(reply->additionalMessage().data().at(offset + 19)); - quint8 bitMap = static_cast(reply->additionalMessage().data().at(offset + 20)); - - offset += 21; - - qCDebug(dcZigbeeNetwork()) << " Neighbor:" << i; - qCDebug(dcZigbeeNetwork()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); - qCDebug(dcZigbeeNetwork()) << " PAN id:" << panId; - qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(ieeeAddress); - qCDebug(dcZigbeeNetwork()) << " Depth:" << depth; - qCDebug(dcZigbeeNetwork()) << " Link quality:" << linkQuality; - qCDebug(dcZigbeeNetwork()) << " BitMap:" << ZigbeeUtils::convertByteToHexString(bitMap); - - foreach (ZigbeeNode *node, nodes()) { - if (node->extendedAddress() == ZigbeeAddress(ieeeAddress)) { - node->setShortAddress(shortAddress); - } - } - - } -} - -void ZigbeeNetworkManager::processLoggingMessage(const ZigbeeInterfaceMessage &message) -{ - quint8 logLevel = static_cast(message.data().at(0)); - QString logMessage = QString::fromUtf8(message.data().right(message.data().count() - 1)); - - QString logLevelString; - switch (logLevel) { - case 0: - logLevelString = "Emergency:"; - break; - case 1: - logLevelString = "Alert:"; - break; - case 2: - logLevelString = "Critical:"; - break; - case 3: - logLevelString = "Error:"; - break; - case 4: - logLevelString = "Warning:"; - break; - case 5: - logLevelString = "Notice:"; - break; - case 6: - logLevelString = "Information:"; - break; - case 7: - logLevelString = "Debug:"; - break; - default: - logLevelString = "Unknown:"; - break; - } - - if (logLevel < 5) { - qCWarning(dcZigbeeController()).noquote() << "ControllerLog:" << logLevelString << logMessage; - } else { - qCDebug(dcZigbeeController()).noquote() << "ControllerLog:" << logLevelString << logMessage; - } -} - -void ZigbeeNetworkManager::processFactoryNewRestart(const ZigbeeInterfaceMessage &message) -{ - quint8 controllerStatus = static_cast(message.data().at(0)); - QString controllerStatusString; - switch (controllerStatus) { - case 0: - controllerStatusString = "startup"; - break; - case 1: - controllerStatusString = "wait start"; - break; - case 2: - controllerStatusString = "NRF start"; - break; - case 3: - controllerStatusString = "discovery"; - break; - case 4: - controllerStatusString = "network init"; - break; - case 5: - controllerStatusString = "rescan"; - break; - case 6: - controllerStatusString = "running"; - break; - default: - qCWarning(dcZigbeeNetwork()) << "Unhandled controller status" << controllerStatus; - break; - } - - qCDebug(dcZigbeeNetwork()) << "Restart finished. Current controller state:" << controllerStatusString; - if (m_startingState == StartingStateReset) setStartingState(StartingStateGetVersion); -} - -void ZigbeeNetworkManager::processNodeClusterList(const ZigbeeInterfaceMessage &message) -{ - quint8 sourceEndpoint = static_cast(message.data().at(0)); - - quint16 profileId = static_cast(message.data().at(1)); - profileId <<= 8; - profileId |= static_cast(message.data().at(2)); - - qCDebug(dcZigbeeController()) << "Node cluster list received:"; - qCDebug(dcZigbeeController()) << " Souce endpoint:" << sourceEndpoint; - qCDebug(dcZigbeeController()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast(profileId)); - - - QByteArray clusterListData = message.data().right(message.data().count() - 3); - - for (int i = 0; i < clusterListData.count(); i += 2) { - quint16 clusterId = static_cast(clusterListData.at(i)); - clusterId <<= 8; - clusterId |= clusterListData .at(i + 1); - - qCDebug(dcZigbeeController()) << " Cluster ID:" << ZigbeeUtils::clusterIdToString(static_cast(clusterId)); - } -} - -void ZigbeeNetworkManager::processNodeAttributeList(const ZigbeeInterfaceMessage &message) -{ - quint8 sourceEndpoint = static_cast(message.data().at(0)); - - quint16 profileId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(1, 2)); - quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(3, 2)); - - qCDebug(dcZigbeeController()) << "Node attribute list received:"; - qCDebug(dcZigbeeController()) << " Souce endpoint:" << sourceEndpoint; - qCDebug(dcZigbeeController()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast(profileId)); - qCDebug(dcZigbeeController()) << " Cluster ID:" << ZigbeeUtils::clusterIdToString(static_cast(clusterId)); - - QByteArray attributeListData = message.data().right(message.data().count() - 5); - if (attributeListData.count() % 2 != 0) { - qCWarning(dcZigbeeController()) << "Attribute list is incomplete. Truncate last byte"; - attributeListData = attributeListData.left(attributeListData.count() - 1); - } - - qCWarning(dcZigbeeController()) << "Attributes" << ZigbeeUtils::convertByteArrayToHexString(attributeListData); - for (int i = 0; i < attributeListData.count(); i += 2) { - quint16 attribute = ZigbeeUtils::convertByteArrayToUint16(attributeListData.mid(i, 2)); - qCDebug(dcZigbeeController()) << " Attribute:" << ZigbeeUtils::convertUint16ToHexString(attribute); - } -} - -void ZigbeeNetworkManager::processNodeCommandIdList(const ZigbeeInterfaceMessage &message) -{ - quint8 sourceEndpoint = static_cast(message.data().at(0)); - quint16 profileId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(1, 2)); - quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(3, 2)); - - qCDebug(dcZigbeeController()) << "Node command list received:"; - qCDebug(dcZigbeeController()) << " Souce endpoint:" << sourceEndpoint; - qCDebug(dcZigbeeController()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast(profileId)); - qCDebug(dcZigbeeController()) << " Cluster ID:" << ZigbeeUtils::clusterIdToString(static_cast(clusterId)); - - QByteArray commandListData = message.data().right(message.data().count() - 5); - - for (int i = 0; i < commandListData.count(); i++) { - quint8 attribute = static_cast(commandListData.at(i)); - qCDebug(dcZigbeeController()) << " Command:" << ZigbeeUtils::convertByteToHexString(attribute); - } -} - -void ZigbeeNetworkManager::processDeviceAnnounce(const ZigbeeInterfaceMessage &message) -{ - QByteArray data = message.data(); - - quint16 shortAddress = 0; - quint64 ieeeAddress = 0; - quint8 macCapabilitiesFlag = 0; - - QDataStream stream(&data, QIODevice::ReadOnly); - stream >> shortAddress >> ieeeAddress >> macCapabilitiesFlag; - - qCDebug(dcZigbeeNetwork()) << "Device announced:"; - qCDebug(dcZigbeeNetwork()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); - qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(ieeeAddress); - qCDebug(dcZigbeeNetwork()) << " Mac capabilities:" << ZigbeeUtils::convertByteToHexString(macCapabilitiesFlag); - - // Check if we already have a node with this - - -// ZigbeeNode *node = createNode(); -// node->setShortAddress(shortAddress); -// node->setExtendedAddress(ZigbeeAddress(ieeeAddress)); -// node->setMacCapabilitiesFlag(macCapabilitiesFlag); - -// qCDebug(dcZigbeeNetwork()) << " Node:" << node; - - - -// // FIXME: check if node already added, and if we have to update it -// addUnitializedNode(node); -// node->setState(StateInitializing); - -// ZigbeeInterfaceReply *reply = nullptr; -// reply = m_controller->commandAuthenticateDevice(node->extendedAddress(), securityConfiguration().globalTrustCenterLinkKey()); -// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandAuthenticateDeviceFinished); - -// reply = m_controller->commandNodeDescriptorRequest(node->shortAddress()); -// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished); - -// reply = m_controller->commandSimpleDescriptorRequest(node->shortAddress(), endPoint()); -// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished); - -// reply = m_controller->commandPowerDescriptorRequest(node->shortAddress()); -// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished); -} - -void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &message) -{ - QByteArray data = message.data(); - quint8 sequenceNumber = 0; - quint16 sourceAddress = 0; - quint8 endPoint = 0; - quint16 clusterId = 0; - quint16 attributeId = 0; - quint8 attributeStatus = 0; - quint8 attributDataType = 0; - quint16 dataSize = 0; - - QDataStream stream(&data, QIODevice::ReadOnly); - stream >> sequenceNumber >> sourceAddress >> endPoint >> clusterId >> attributeId >> attributeStatus >> attributDataType >> dataSize; - - Zigbee::DataType dataType = static_cast(attributDataType); - QByteArray attributeData = data.right(dataSize); - - if (attributeData.length() != dataSize) { - qCCritical(dcZigbeeNetwork()) << "HACK" << attributeData.length() << "!=" << dataSize; - // Note: the NXP firmware for JN5169 has a bug here and does not send the attributeStatus. - // Repars data without attribute status - sequenceNumber = 0; - sourceAddress = 0; - endPoint = 0; - clusterId = 0; - attributeId = 0; - attributeStatus = 0; - attributDataType = 0; - dataSize = 0; - - QDataStream alternativeStream(&data, QIODevice::ReadOnly); - alternativeStream >> sequenceNumber >> sourceAddress >> endPoint >> clusterId >> attributeId >> attributDataType >> dataSize; - - dataType = static_cast(attributDataType); - attributeData = data.right(dataSize); - } - - qCDebug(dcZigbeeNetwork()) << "Attribute report:"; - qCDebug(dcZigbeeNetwork()) << " SQN:" << ZigbeeUtils::convertByteToHexString(sequenceNumber); - qCDebug(dcZigbeeNetwork()) << " Source address:" << ZigbeeUtils::convertUint16ToHexString(sourceAddress); - qCDebug(dcZigbeeNetwork()) << " End point:" << ZigbeeUtils::convertByteToHexString(endPoint); - qCDebug(dcZigbeeNetwork()) << " Cluster:" << ZigbeeUtils::clusterIdToString(static_cast(clusterId)); - qCDebug(dcZigbeeNetwork()) << " Attribut id:" << ZigbeeUtils::convertUint16ToHexString(attributeId); - qCDebug(dcZigbeeNetwork()) << " Attribut data type:" << dataType; - qCDebug(dcZigbeeNetwork()) << " Attribut size:" << dataSize; - qCDebug(dcZigbeeNetwork()) << " Data:" << ZigbeeUtils::convertByteArrayToHexString(attributeData); - - switch (dataType) { - case Zigbee::CharString: - qCDebug(dcZigbeeNetwork()) << " Data(converted)" << QString::fromUtf8(attributeData); - break; - case Zigbee::Bool: - qCDebug(dcZigbeeNetwork()) << " Data(converted)" << static_cast(attributeData.at(0)); - break; - default: - break; - } - - ZigbeeNode *node = getZigbeeNode(sourceAddress); - if (!node) { - qCWarning(dcZigbeeNode()) << "Received an attribute report from an unknown node. Ignoring data."; - return; - } - - node->setClusterAttribute(static_cast(clusterId), ZigbeeClusterAttribute(attributeId, dataType, attributeData)); -} - -void ZigbeeNetworkManager::processLeaveIndication(const ZigbeeInterfaceMessage &message) -{ - QByteArray data = message.data(); - quint64 extendedAddress = 0; - bool rejoining = 0; - - QDataStream stream(&data, QIODevice::ReadOnly); - stream >> extendedAddress; - stream >> rejoining; - - ZigbeeAddress address(extendedAddress); - qCDebug(dcZigbeeNetwork()) << "Node leaving indication:" << address.toString() << "rejoining:" << rejoining; - - ZigbeeNode *node = getZigbeeNode(address); - if (node) removeNode(node); -} - -void ZigbeeNetworkManager::processRestartProvisioned(const ZigbeeInterfaceMessage &message) -{ - if (message.data().isEmpty()) - return; - - quint8 status = static_cast(message.data().at(0)); - switch (status) { - case 0: - qCDebug(dcZigbeeNetwork()) << "Restart provisioned: start up"; - break; - case 1: - qCDebug(dcZigbeeNetwork()) << "Restart provisioned: wait start"; - break; - case 2: - qCDebug(dcZigbeeNetwork()) << "Restart provisioned: NFN start"; - break; - case 3: - qCDebug(dcZigbeeNetwork()) << "Restart provisioned: discovery"; - break; - case 4: - qCDebug(dcZigbeeNetwork()) << "Restart provisioned: network init"; - break; - case 5: - qCDebug(dcZigbeeNetwork()) << "Restart provisioned: rescan"; - break; - case 6: - qCDebug(dcZigbeeNetwork()) << "Restart provisioned: running"; - break; - default: - qCDebug(dcZigbeeNetwork()) << "Restart provisioned: unknown"; - break; - } - - if (m_startingState == StartingStateReset) { - if (m_networkRunning) { - qCDebug(dcZigbeeNetwork()) << "Reset finished. Network already running. No need to set it up"; - setStartingState(StartingStateGetPermitJoinStatus); - } else { - qCDebug(dcZigbeeNetwork()) << "Reset finished. Set up network"; - setStartingState(StartingStateGetVersion); - } - } -} - -void ZigbeeNetworkManager::processRouterDiscoveryConfirm(const ZigbeeInterfaceMessage &message) -{ - if (message.data().isEmpty()) - return; - - quint8 status = static_cast(message.data().at(0)); - Zigbee::ZigbeeNwkLayerStatus networkStatus = static_cast(message.data().at(0)); - qCDebug(dcZigbeeNetwork()) << "Router discovery confirm received" << status << networkStatus; -} - -void ZigbeeNetworkManager::startNetwork() -{ - qCDebug(dcZigbeeNetwork()) << "Start network..."; - if (m_controller) { - qCDebug(dcZigbeeNetwork()) << "Clean up old controller..."; - delete m_controller; - m_controller = nullptr; - } - - qCDebug(dcZigbeeNetwork()) << "Create new controller..."; - m_controller = new ZigbeeBridgeController(this); - connect(m_controller, &ZigbeeBridgeController::messageReceived, this, &ZigbeeNetworkManager::onMessageReceived); - connect(m_controller, &ZigbeeBridgeController::availableChanged, this, &ZigbeeNetworkManager::onControllerAvailableChanged); - - if (state() == StateUninitialized) - loadNetwork(); - - if (!m_controller->enable(serialPortName(), serialBaudrate())) { - setState(StateDisconnected); - setStartingState(StartingStateNone); - setError(ErrorHardwareUnavailable); - } else { - // Reset - setStartingState(StartingStateReset); - setState(StateStarting); - } -} - -void ZigbeeNetworkManager::stopNetwork() -{ - qCDebug(dcZigbeeNetwork()) << "Stopping network..."; - setState(StateStopping); - if (m_controller) { - delete m_controller; - m_controller = nullptr; - } - - setStartingState(StartingStateNone); - setState(StateDisconnected); - setError(ErrorNoError); -} - -void ZigbeeNetworkManager::onMessageReceived(const ZigbeeInterfaceMessage &message) -{ - switch (message.messageType()) { - case Zigbee::MessageTypeLogging: - processLoggingMessage(message); - break; - case Zigbee::MessageTypeFactoryNewRestart: - processFactoryNewRestart(message); - break; - case Zigbee::MessageTypeNodeClusterList: - processNodeClusterList(message); - break; - case Zigbee::MessageTypeNodeAttributeList: - processNodeAttributeList(message); - break; - case Zigbee::MessageTypeNodeCommandIdList: - processNodeCommandIdList(message); - break; - case Zigbee::MessageTypeDeviceAnnounce: - processDeviceAnnounce(message); - break; - case Zigbee::MessageTypeAttributeReport: - processAttributeReport(message); - break; - case Zigbee::MessageTypeLeaveIndication: - processLeaveIndication(message); - break; - case Zigbee::MessageTypeNetworkJoinedFormed: - processNetworkFormed(message); - break; - case Zigbee::MessageTypeRestartProvisioned: - processRestartProvisioned(message); - break; - case Zigbee::MessageTypeRouterDiscoveryConfirm: - processRouterDiscoveryConfirm(message); - break; - default: - qCWarning(dcZigbeeController()) << "Unhandled message received:" << message; + switch (backendType) { + case BackendTypeNxp: + m_network = new ZigbeeNetworkNxp(this); + m_network->setSerialPortName(m_serialPortInfo.systemLocation()); + m_network->setSerialBaudrate(static_cast(baudrate)); break; } } -void ZigbeeNetworkManager::onControllerAvailableChanged(bool available) +QSerialPortInfo ZigbeeNetworkManager::serialPortInfo() const { - qCDebug(dcZigbeeNetwork()) << "Hardware controller is" << (available ? "now available" : "not available"); - - if (m_factoryResetting && !available) { - setStartingState(StartingStateReset); - return; - } - - if (!available) { - foreach (ZigbeeNode *node, nodes()) { - node->setConnected(false); - } - - setError(ErrorHardwareUnavailable); - setState(StateDisconnected); - setStartingState(StartingStateNone); - } else { - setError(ErrorNoError); - setState(StateStarting); - setStartingState(StartingStateReset); - } + return m_serialPortInfo; } - -void ZigbeeNetworkManager::factoryResetNetwork() +QSerialPort::BaudRate ZigbeeNetworkManager::baudrate() const { - qCDebug(dcZigbeeNetwork()) << "Factory reset network and forget all information. This cannot be undone."; - clearSettings(); - - setState(StateStarting); - setStartingState(StartingStateErase); + return m_baudrate; +} + +ZigbeeNetworkManager::BackendType ZigbeeNetworkManager::backendType() const +{ + return m_backendType; +} + +ZigbeeNetwork *ZigbeeNetworkManager::network() const +{ + return m_network; } diff --git a/libnymea-zigbee/zigbeenetworkmanager.h b/libnymea-zigbee/zigbeenetworkmanager.h index ca0e7b6..dafa648 100644 --- a/libnymea-zigbee/zigbeenetworkmanager.h +++ b/libnymea-zigbee/zigbeenetworkmanager.h @@ -29,109 +29,38 @@ #define ZIGBEEMANAGER_H #include +#include +#include #include "zigbeenetwork.h" -#include "zigbeeaddress.h" -#include "zigbeebridgecontroller.h" -#include "zigbeesecurityconfiguration.h" + class ZigbeeNetworkManager : public QObject { Q_OBJECT + public: - explicit ZigbeeNetworkManager(QObject *parent = nullptr); + enum BackendType { + BackendTypeNxp + }; + Q_ENUM(BackendType) - QString controllerFirmwareVersion() const; + explicit ZigbeeNetworkManager(const QSerialPortInfo &serialPortInfo, QSerialPort::BaudRate baudrate, BackendType backendType, QObject *parent = nullptr); - // Note: temporary public available for debugging - ZigbeeBridgeController *controller() const; + QSerialPortInfo serialPortInfo() const; + QSerialPort::BaudRate baudrate() const; + BackendType backendType() const; - bool networkRunning() const; + ZigbeeNetwork *network() const; - // Note: Follwoing methods should be abstract - bool permitJoining() const; - void setPermitJoining(bool permitJoining); - void resetController(); private: - enum StartingState { - StartingStateNone, - StartingStateErase, - StartingStateReset, - StartingStateGetVersion, - StartingStateSetPanId, - StartingStateSetChannel, - StartingStateSetSecurity, - StartingStateSetNodeType, - StartingStateStartNetwork, - StartingStateGetPermitJoinStatus, - StartingStateReadeNodeDescriptor, - StartingStateReadPowerDescriptor - }; - - ZigbeeBridgeController *m_controller = nullptr; - QString m_controllerFirmwareVersion; - - StartingState m_startingState = StartingStateNone; - void setStartingState(StartingState state); - - QList m_uninitializedNodes; - - bool m_permitJoining = false; - bool m_networkRunning = false; - bool m_factoryResetting = false; - - void readControllerVersion(); - void readPermitJoinStatus(); - -signals: - void permitJoiningChanged(bool permitJoining); + QSerialPortInfo m_serialPortInfo; + QSerialPort::BaudRate m_baudrate; + BackendType m_backendType = BackendTypeNxp; + ZigbeeNetwork *m_network = nullptr; private slots: - void onMessageReceived(const ZigbeeInterfaceMessage &message); - void onControllerAvailableChanged(bool available); - - // Controller command finished slots - void onCommandResetControllerFinished(); - void onCommandSoftResetControllerFinished(); - void onCommandErasePersistentDataFinished(); - void onCommandSetExtendedPanIdFinished(); - void onCommandSetChannelMaskFinished(); - void onCommandSetNodeTypeFinished(); - void onCommandStartNetworkFinished(); - void onCommandStartScanFinished(); - void onCommandEnableWhitelistFinished(); - - void onCommandNodeDescriptorRequestFinished(); - void onCommandSimpleDescriptorRequestFinished(); - void onCommandPowerDescriptorRequestFinished(); - - void onCommandInitiateTouchLinkFinished(); - void onCommandTouchLinkFactoryResetFinished(); - void onCommandRequestLinkQualityFinished(); - - void onCommandRequestMatchDescriptorFinished(); - void onCommandSetSecurityFinished(); - void onCommandNetworkAddressRequestFinished(); - void onCommandAuthenticateDeviceFinished(); - - // Process controller notifications/messages - void processNetworkFormed(const ZigbeeInterfaceMessage &message); - void processLoggingMessage(const ZigbeeInterfaceMessage &message); - void processFactoryNewRestart(const ZigbeeInterfaceMessage &message); - void processNodeClusterList(const ZigbeeInterfaceMessage &message); - void processNodeAttributeList(const ZigbeeInterfaceMessage &message); - void processNodeCommandIdList(const ZigbeeInterfaceMessage &message); - void processDeviceAnnounce(const ZigbeeInterfaceMessage &message); - void processAttributeReport(const ZigbeeInterfaceMessage &message); - void processLeaveIndication(const ZigbeeInterfaceMessage &message); - void processRestartProvisioned(const ZigbeeInterfaceMessage &message); - void processRouterDiscoveryConfirm(const ZigbeeInterfaceMessage &message); - -public slots: - void startNetwork() override; - void stopNetwork() override; - void factoryResetNetwork() override; };