diff --git a/libnymea-zigbee/interface/zigbeeinterface.h b/libnymea-zigbee/interface/zigbeeinterface.h index db8b345..58638ac 100644 --- a/libnymea-zigbee/interface/zigbeeinterface.h +++ b/libnymea-zigbee/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.h b/libnymea-zigbee/interface/zigbeeinterfacemessage.h index d4173b2..8f8a418 100644 --- a/libnymea-zigbee/interface/zigbeeinterfacemessage.h +++ b/libnymea-zigbee/interface/zigbeeinterfacemessage.h @@ -31,7 +31,7 @@ #include #include -#include "zigbee.h" +#include "../zigbee.h" class ZigbeeInterfaceMessage { diff --git a/libnymea-zigbee/libnymea-zigbee.pro b/libnymea-zigbee/libnymea-zigbee.pro index 3728608..39c48a8 100644 --- a/libnymea-zigbee/libnymea-zigbee.pro +++ b/libnymea-zigbee/libnymea-zigbee.pro @@ -8,14 +8,15 @@ SOURCES += \ interface/zigbeeinterfacemessage.cpp \ interface/zigbeeinterfacerequest.cpp \ interface/zigbeeinterfacereply.cpp \ - nxp/nxpzigbeenetworkmanager.cpp \ + nxp/zigbeenetworknxp.cpp \ + nxp/zigbeebridgecontrollernxp.cpp \ zigbeecluster.cpp \ zigbeeclusterattribute.cpp \ zigbeenetwork.cpp \ zigbeenetworkmanager.cpp \ zigbee.cpp \ loggingcategory.cpp \ - zigbeebridgecontroller.cpp \ + zigbeenodeendpoint.cpp \ zigbeesecurityconfiguration.cpp \ zigbeeutils.cpp \ zigbeenode.cpp \ @@ -26,14 +27,15 @@ HEADERS += \ interface/zigbeeinterfacemessage.h \ interface/zigbeeinterfacerequest.h \ interface/zigbeeinterfacereply.h \ - nxp/nxpzigbeenetworkmanager.h \ + nxp/zigbeenetworknxp.h \ + nxp/zigbeebridgecontrollernxp.h \ zigbeecluster.h \ zigbeeclusterattribute.h \ zigbeenetwork.h \ zigbeenetworkmanager.h \ zigbee.h \ loggingcategory.h \ - zigbeebridgecontroller.h \ + zigbeenodeendpoint.h \ zigbeesecurityconfiguration.h \ zigbeeutils.h \ zigbeenode.h \ diff --git a/libnymea-zigbee/nxp/nxpzigbeenetworkmanager.cpp b/libnymea-zigbee/nxp/nxpzigbeenetworkmanager.cpp deleted file mode 100644 index 7dac15f..0000000 --- a/libnymea-zigbee/nxp/nxpzigbeenetworkmanager.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* -* Copyright 2013 - 2020, nymea GmbH -* Contact: contact@nymea.io -* -* This file is part of nymea. -* This project including source code and documentation is protected by copyright law, and -* remains the property of nymea GmbH. All rights, including reproduction, publication, -* editing and translation, are reserved. The use of this project is subject to the terms of a -* license agreement to be concluded with nymea GmbH in accordance with the terms -* of use of nymea GmbH, available under https://nymea.io/license -* -* GNU Lesser General Public License Usage -* Alternatively, this project may be redistributed and/or modified under the terms of the GNU -* Lesser General Public License as published by the Free Software Foundation; version 3. -* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -* See the GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License along with this project. -* If not, see . -* -* For any further details and any questions please contact us under contact@nymea.io -* or see our FAQ/Licensing Information on https://nymea.io/license/faq -* -* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#include "nxpzigbeenetworkmanager.h" - -NxpZigbeeNetworkManager::NxpZigbeeNetworkManager(QObject *parent) : QObject(parent) -{ - -} diff --git a/libnymea-zigbee/nxp/nxpzigbeenetworkmanager.h b/libnymea-zigbee/nxp/nxpzigbeenetworkmanager.h deleted file mode 100644 index 6fc540e..0000000 --- a/libnymea-zigbee/nxp/nxpzigbeenetworkmanager.h +++ /dev/null @@ -1,44 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* -* Copyright 2013 - 2020, nymea GmbH -* Contact: contact@nymea.io -* -* This file is part of nymea. -* This project including source code and documentation is protected by copyright law, and -* remains the property of nymea GmbH. All rights, including reproduction, publication, -* editing and translation, are reserved. The use of this project is subject to the terms of a -* license agreement to be concluded with nymea GmbH in accordance with the terms -* of use of nymea GmbH, available under https://nymea.io/license -* -* GNU Lesser General Public License Usage -* Alternatively, this project may be redistributed and/or modified under the terms of the GNU -* Lesser General Public License as published by the Free Software Foundation; version 3. -* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -* See the GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License along with this project. -* If not, see . -* -* For any further details and any questions please contact us under contact@nymea.io -* or see our FAQ/Licensing Information on https://nymea.io/license/faq -* -* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifndef NXPZIGBEENETWORKMANAGER_H -#define NXPZIGBEENETWORKMANAGER_H - -#include - -class NxpZigbeeNetworkManager : public QObject -{ - Q_OBJECT -public: - explicit NxpZigbeeNetworkManager(QObject *parent = nullptr); - -signals: - -public slots: -}; - -#endif // NXPZIGBEENETWORKMANAGER_H diff --git a/libnymea-zigbee/zigbeebridgecontroller.cpp b/libnymea-zigbee/nxp/zigbeebridgecontrollernxp.cpp similarity index 94% rename from libnymea-zigbee/zigbeebridgecontroller.cpp rename to libnymea-zigbee/nxp/zigbeebridgecontrollernxp.cpp index 9facb3d..3ece135 100644 --- a/libnymea-zigbee/zigbeebridgecontroller.cpp +++ b/libnymea-zigbee/nxp/zigbeebridgecontrollernxp.cpp @@ -102,12 +102,16 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandSetChannelMask(quint32 chan // 0x07fff800 select from all channels 11 - 26 // 0x2108800 primary zigbee light link channels 11, 15, 20, 25 + //Zigbee::ZigbeeChannels channels = (Zigbee::ZigbeeChannel11 | Zigbee::ZigbeeChannel15 | Zigbee::ZigbeeChannel20 | Zigbee::ZigbeeChannel25); + + qCDebug(dcZigbeeController()) << "Set channel mask" << ZigbeeUtils::convertUint32ToHexString(channelMask); QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::BigEndian); stream << channelMask; ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSetChannelMask, data)); - request.setDescription("Set channel mask " + ZigbeeUtils::convertByteArrayToHexString(data)); + request.setDescription("Set channel mask" + ZigbeeUtils::convertByteArrayToHexString(data)); return sendRequest(request); } @@ -186,6 +190,20 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandGetPermitJoinStatus() return sendRequest(request); } +ZigbeeInterfaceReply *ZigbeeBridgeController::commandRequestActiveEndpoints(quint16 shortAddress) +{ + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + stream << shortAddress; + + ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeActiveEndpointRequest, data)); + request.setDescription("Get active endpoints"); + request.setExpectedAdditionalMessageType(Zigbee::MessageTypeActiveEndpointResponse); + request.setTimoutIntervall(3000); + + return sendRequest(request); +} + ZigbeeInterfaceReply *ZigbeeBridgeController::commandRequestLinkQuality(quint16 shortAddress) { QByteArray data; diff --git a/libnymea-zigbee/zigbeebridgecontroller.h b/libnymea-zigbee/nxp/zigbeebridgecontrollernxp.h similarity index 98% rename from libnymea-zigbee/zigbeebridgecontroller.h rename to libnymea-zigbee/nxp/zigbeebridgecontrollernxp.h index ce1ba4d..5939828 100644 --- a/libnymea-zigbee/zigbeebridgecontroller.h +++ b/libnymea-zigbee/nxp/zigbeebridgecontrollernxp.h @@ -59,6 +59,7 @@ public: ZigbeeInterfaceReply *commandStartScan(); ZigbeeInterfaceReply *commandPermitJoin(quint16 targetAddress = 0xfffc, const quint8 advertisingIntervall = 180, bool tcSignificance = false); ZigbeeInterfaceReply *commandGetPermitJoinStatus(); + ZigbeeInterfaceReply *commandRequestActiveEndpoints(quint16 shortAddress); ZigbeeInterfaceReply *commandRequestLinkQuality(quint16 shortAddress); ZigbeeInterfaceReply *commandEnableWhiteList(); ZigbeeInterfaceReply *commandInitiateTouchLink(); @@ -71,6 +72,7 @@ public: ZigbeeInterfaceReply *commandPowerDescriptorRequest(quint16 shortAddress); ZigbeeInterfaceReply *commandUserDescriptorRequest(quint16 shortAddress, quint16 address); + private: ZigbeeInterface *m_interface = nullptr; ZigbeeInterfaceReply *m_currentReply = nullptr; diff --git a/libnymea-zigbee/nxp/zigbeenetworknxp.cpp b/libnymea-zigbee/nxp/zigbeenetworknxp.cpp new file mode 100644 index 0000000..b86cb82 --- /dev/null +++ b/libnymea-zigbee/nxp/zigbeenetworknxp.cpp @@ -0,0 +1,7 @@ +#include "zigbeenetworknxp.h" + +ZigbeeNetworkNxp::ZigbeeNetworkNxp(QObject *parent) : + ZigbeeNetwork(parent) +{ + +} diff --git a/libnymea-zigbee/nxp/zigbeenetworknxp.h b/libnymea-zigbee/nxp/zigbeenetworknxp.h new file mode 100644 index 0000000..8252fb6 --- /dev/null +++ b/libnymea-zigbee/nxp/zigbeenetworknxp.h @@ -0,0 +1,23 @@ +#ifndef ZIGBEENETWORKNXP_H +#define ZIGBEENETWORKNXP_H + +#include +#include "../zigbeenetwork.h" + +class ZigbeeNetworkNxp : public ZigbeeNetwork +{ + Q_OBJECT +public: + explicit ZigbeeNetworkNxp(QObject *parent = nullptr); + +signals: + +public slots: + void startNetwork() override; + void stopNetwork() override; + + void factoryResetNetwork() override; + +}; + +#endif // ZIGBEENETWORKNXP_H diff --git a/libnymea-zigbee/zigbee.h b/libnymea-zigbee/zigbee.h index cac940e..4ec251d 100644 --- a/libnymea-zigbee/zigbee.h +++ b/libnymea-zigbee/zigbee.h @@ -44,6 +44,26 @@ public: }; Q_ENUM(ZigbeeProfile) + enum ZigbeeChannel { + ZigbeeChannel11, + ZigbeeChannel12, + ZigbeeChannel13, + ZigbeeChannel14, + ZigbeeChannel15, + ZigbeeChannel16, + ZigbeeChannel17, + ZigbeeChannel18, + ZigbeeChannel19, + ZigbeeChannel20, + ZigbeeChannel21, + ZigbeeChannel22, + ZigbeeChannel23, + ZigbeeChannel24, + ZigbeeChannel25 + }; + Q_ENUM(ZigbeeChannel) + Q_DECLARE_FLAGS(ZigbeeChannels, ZigbeeChannel) + enum InterfaceMessageType { // Common Commands MessageTypeNone = 0x0000, @@ -470,6 +490,25 @@ public: }; Q_ENUM(Manufacturer) + enum ZigbeeNwkLayerStatus { + ZigbeeNwkLayerStatusJointNetwork = 0x00, + ZigbeeNwkLayerStatusFormedNetwork = 0x01, + ZigbeeNwkLayerStatusInvalidParameter = 0xc1, + ZigbeeNwkLayerStatusInvalidRequest = 0xc2, + ZigbeeNwkLayerStatusNotPermitted = 0xc3, + ZigbeeNwkLayerStatusStartupFailure = 0xc4, + ZigbeeNwkLayerStatusAlreadyPresent = 0xc5, + ZigbeeNwkLayerStatusSynchFailure = 0xc6, + ZigbeeNwkLayerStatusTableFull = 0xc7, + ZigbeeNwkLayerStatusUnknownDevice = 0xc8, + ZigbeeNwkLayerStatusUnsupportedAttribute = 0xc9, + ZigbeeNwkLayerStatusNoNetworks = 0xca, + ZigbeeNwkLayerStatusLeaveUnconfirmed = 0xcb, + ZigbeeNwkLayerStatusMaxFrmCntr = 0xcc, + ZigbeeNwkLayerStatusNoKey = 0xcd, + ZigbeeNwkLayerStatusBadCcmOutput = 0xce + }; + Q_ENUM(ZigbeeNwkLayerStatus) ///* Manufacturer Codes */ ///* Codes less than 0x1000 were issued for RF4CE */ @@ -1165,4 +1204,6 @@ public: }; +Q_DECLARE_OPERATORS_FOR_FLAGS(Zigbee::ZigbeeChannels) + #endif // ZIGBEE_H diff --git a/libnymea-zigbee/zigbeenetwork.cpp b/libnymea-zigbee/zigbeenetwork.cpp index 83cd084..528aa50 100644 --- a/libnymea-zigbee/zigbeenetwork.cpp +++ b/libnymea-zigbee/zigbeenetwork.cpp @@ -29,9 +29,8 @@ #include "zigbeenetwork.h" #include "loggingcategory.h" -ZigbeeNetwork::ZigbeeNetwork(ControllerType controllerType, QObject *parent) : - ZigbeeNode(parent), - m_controllerType(controllerType) +ZigbeeNetwork::ZigbeeNetwork(QObject *parent) : + QObject(parent) { } @@ -41,11 +40,6 @@ ZigbeeNetwork::State ZigbeeNetwork::state() const return m_state; } -ZigbeeNetwork::ControllerType ZigbeeNetwork::controlerType() const -{ - return m_controllerType; -} - ZigbeeNetwork::Error ZigbeeNetwork::error() const { return m_error; @@ -232,6 +226,7 @@ void ZigbeeNetwork::loadNetwork() { qCDebug(dcZigbeeNetwork()) << "Load current network configuration from" << m_settingsFileName; QSettings settings(m_settingsFileName, QSettings::IniFormat, this); + settings.beginGroup("Network"); quint64 extendedPanId = static_cast(settings.value("panId", 0).toULongLong()); if (extendedPanId == 0) { @@ -240,7 +235,7 @@ void ZigbeeNetwork::loadNetwork() } setExtendedPanId(extendedPanId); setChannel(settings.value("channel", 0).toUInt()); - settings.endGroup(); + settings.endGroup(); // Network // Load nodes settings.beginGroup("Nodes"); @@ -250,42 +245,46 @@ void ZigbeeNetwork::loadNetwork() ZigbeeNode *node = createNode(); node->setExtendedAddress(ZigbeeAddress(ieeeAddressString)); node->setShortAddress(static_cast(settings.value("nwkAddress", 0).toUInt())); - // TODO: load the rest of the node + node->setMacCapabilitiesFlag(static_cast(settings.value("macCapabilitiesFlag", 0).toUInt())); + node->setNodeDescriptorRawData(settings.value("nodeDescriptorRawData", QByteArray()).toByteArray()); + node->setPowerDescriptorFlag(static_cast(settings.value("powerDescriptorFlag", 0).toUInt())); - settings.beginGroup("inputCluster"); - foreach (const QString &clusterIdString, settings.childGroups()) { - settings.beginGroup(clusterIdString); - Zigbee::ClusterId clusterId = static_cast(clusterIdString.toInt()); + // TODO: load endpoints - foreach (const QString &attributeIdString, settings.childGroups()) { - settings.beginGroup(attributeIdString); - quint16 id = static_cast(attributeIdString.toInt()); - Zigbee::DataType dataType = static_cast(settings.value("dataType", 0).toInt()); - QByteArray data = settings.value("data").toByteArray(); - node->setClusterAttribute(clusterId, ZigbeeClusterAttribute(id, dataType, data)); - settings.endGroup(); // attributeId - } - settings.endGroup(); // clusterId - } - settings.endGroup(); // inputCluster +// settings.beginGroup("inputCluster"); +// foreach (const QString &clusterIdString, settings.childGroups()) { +// settings.beginGroup(clusterIdString); +// Zigbee::ClusterId clusterId = static_cast(clusterIdString.toInt()); - // Output cluster - settings.beginGroup("outputCluster"); - foreach (const QString &clusterIdString, settings.childGroups()) { - settings.beginGroup(clusterIdString); - Zigbee::ClusterId clusterId = static_cast(clusterIdString.toInt()); +// foreach (const QString &attributeIdString, settings.childGroups()) { +// settings.beginGroup(attributeIdString); +// quint16 id = static_cast(attributeIdString.toInt()); +// Zigbee::DataType dataType = static_cast(settings.value("dataType", 0).toInt()); +// QByteArray data = settings.value("data").toByteArray(); +// node->setClusterAttribute(clusterId, ZigbeeClusterAttribute(id, dataType, data)); +// settings.endGroup(); // attributeId +// } +// settings.endGroup(); // clusterId +// } +// settings.endGroup(); // inputCluster - foreach (const QString &attributeIdString, settings.childGroups()) { - settings.beginGroup(attributeIdString); - quint16 id = static_cast(attributeIdString.toInt()); - Zigbee::DataType dataType = static_cast(settings.value("dataType", 0).toInt()); - QByteArray data = settings.value("data").toByteArray(); - node->setClusterAttribute(clusterId, ZigbeeClusterAttribute(id, dataType, data)); - settings.endGroup(); // attributeId - } - settings.endGroup(); // clusterId - } - settings.endGroup(); // inputCluster +// // Output cluster +// settings.beginGroup("outputCluster"); +// foreach (const QString &clusterIdString, settings.childGroups()) { +// settings.beginGroup(clusterIdString); +// Zigbee::ClusterId clusterId = static_cast(clusterIdString.toInt()); + +// foreach (const QString &attributeIdString, settings.childGroups()) { +// settings.beginGroup(attributeIdString); +// quint16 id = static_cast(attributeIdString.toInt()); +// Zigbee::DataType dataType = static_cast(settings.value("dataType", 0).toInt()); +// QByteArray data = settings.value("data").toByteArray(); +// node->setClusterAttribute(clusterId, ZigbeeClusterAttribute(id, dataType, data)); +// settings.endGroup(); // attributeId +// } +// settings.endGroup(); // clusterId +// } +// settings.endGroup(); // outputCluster node->setState(StateInitialized); addNodeInternally(node); @@ -299,21 +298,21 @@ void ZigbeeNetwork::loadNetwork() qCDebug(dcZigbeeNetwork()) << QStringLiteral("Nodes: (%1)").arg(m_nodes.count()); foreach (ZigbeeNode *node, nodes()) { qCDebug(dcZigbeeNetwork()) << " - " << node; - qCDebug(dcZigbeeNetwork()) << "Output cluster:"; - foreach (ZigbeeCluster *cluster, node->outputClusters()) { - qCDebug(dcZigbeeNetwork()) << " " << cluster; - foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) { - qCDebug(dcZigbeeNetwork()) << " " << attribute; - } - } +// qCDebug(dcZigbeeNetwork()) << "Output cluster:"; +// foreach (ZigbeeCluster *cluster, node->outputClusters()) { +// qCDebug(dcZigbeeNetwork()) << " " << cluster; +// foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) { +// qCDebug(dcZigbeeNetwork()) << " " << attribute; +// } +// } - qCDebug(dcZigbeeNetwork()) << "Input cluster:"; - foreach (ZigbeeCluster *cluster, node->inputClusters()) { - qCDebug(dcZigbeeNetwork()) << " " << cluster; - foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) { - qCDebug(dcZigbeeNetwork()) << " " << attribute; - } - } +// qCDebug(dcZigbeeNetwork()) << "Input cluster:"; +// foreach (ZigbeeCluster *cluster, node->inputClusters()) { +// qCDebug(dcZigbeeNetwork()) << " " << cluster; +// foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) { +// qCDebug(dcZigbeeNetwork()) << " " << attribute; +// } +// } } } @@ -350,36 +349,43 @@ void ZigbeeNetwork::saveNode(ZigbeeNode *node) // Save this node settings.beginGroup(node->extendedAddress().toString()); settings.setValue("nwkAddress", node->shortAddress()); + settings.setValue("macCapabilitiesFlag", node->m_macCapabilitiesFlag); + settings.setValue("nodeDescriptorRawData", node->m_nodeDescriptorRawData); + settings.setValue("powerDescriptorFlag", node->m_powerDescriptorFlag); + + // TODO: store endpoints + + // TODO: save the rest of the node - // Input clusters - settings.beginGroup("inputCluster"); - foreach (ZigbeeCluster *cluster, node->inputClusters()) { - settings.beginGroup(QString::number(static_cast(cluster->clusterId()))); - foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) { - settings.beginGroup(QString::number(static_cast(attribute.id()))); - settings.setValue("dataType", static_cast(attribute.dataType())); - settings.setValue("data", attribute.data()); - settings.endGroup(); // attributeId - } - settings.endGroup(); // clusterId - } - settings.endGroup(); // inputCluster +// // Input clusters +// settings.beginGroup("inputCluster"); +// foreach (ZigbeeCluster *cluster, node->inputClusters()) { +// settings.beginGroup(QString::number(static_cast(cluster->clusterId()))); +// foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) { +// settings.beginGroup(QString::number(static_cast(attribute.id()))); +// settings.setValue("dataType", static_cast(attribute.dataType())); +// settings.setValue("data", attribute.data()); +// settings.endGroup(); // attributeId +// } +// settings.endGroup(); // clusterId +// } +// settings.endGroup(); // inputCluster - // Output clusters - settings.beginGroup("outputCluster"); - foreach (ZigbeeCluster *cluster, node->outputClusters()) { - settings.beginGroup(QString::number(static_cast(cluster->clusterId()))); - foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) { - settings.beginGroup(QString::number(static_cast(attribute.id()))); - settings.setValue("dataType", static_cast(attribute.dataType())); - settings.setValue("data", attribute.data()); - settings.endGroup(); // attributeId - } - settings.endGroup(); // clusterId - } - settings.endGroup(); // inputCluster +// // Output clusters +// settings.beginGroup("outputCluster"); +// foreach (ZigbeeCluster *cluster, node->outputClusters()) { +// settings.beginGroup(QString::number(static_cast(cluster->clusterId()))); +// foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) { +// settings.beginGroup(QString::number(static_cast(attribute.id()))); +// settings.setValue("dataType", static_cast(attribute.dataType())); +// settings.setValue("data", attribute.data()); +// settings.endGroup(); // attributeId +// } +// settings.endGroup(); // clusterId +// } +// settings.endGroup(); // inputCluster settings.endGroup(); // Node ieee address @@ -400,7 +406,6 @@ void ZigbeeNetwork::removeNodeFromSettings(ZigbeeNode *node) settings.endGroup(); // Nodes } - void ZigbeeNetwork::addNode(ZigbeeNode *node) { qCDebug(dcZigbeeNetwork()) << "Add node" << node; @@ -425,12 +430,6 @@ void ZigbeeNetwork::removeNode(ZigbeeNode *node) removeNodeFromSettings(node); } -ZigbeeNode *ZigbeeNetwork::createNode() -{ - ZigbeeNode *node = new ZigbeeNode(this); - return node; -} - void ZigbeeNetwork::setState(ZigbeeNetwork::State state) { if (m_state == state) diff --git a/libnymea-zigbee/zigbeenetwork.h b/libnymea-zigbee/zigbeenetwork.h index 4d1783c..fb661d2 100644 --- a/libnymea-zigbee/zigbeenetwork.h +++ b/libnymea-zigbee/zigbeenetwork.h @@ -34,16 +34,11 @@ #include "zigbeenode.h" #include "zigbeesecurityconfiguration.h" -class ZigbeeNetwork : public ZigbeeNode +class ZigbeeNetwork : public QObject { Q_OBJECT public: - enum ControllerType { - ControlerTypeNxp - }; - Q_ENUM(ControllerType) - enum State { StateUninitialized, StateDisconnected, @@ -60,10 +55,9 @@ public: }; Q_ENUM(Error) - explicit ZigbeeNetwork(ControllerType controllerType, QObject *parent = nullptr); + explicit ZigbeeNetwork(QObject *parent = nullptr); State state() const; - ControllerType controlerType() const; Error error() const; @@ -99,7 +93,6 @@ public: private: - ControllerType m_controllerType = ControlerTypeNxp; State m_state = StateUninitialized; Error m_error = ErrorNoError; diff --git a/libnymea-zigbee/zigbeenetworkmanager.cpp b/libnymea-zigbee/zigbeenetworkmanager.cpp index ee611cd..5ea7717 100644 --- a/libnymea-zigbee/zigbeenetworkmanager.cpp +++ b/libnymea-zigbee/zigbeenetworkmanager.cpp @@ -34,7 +34,7 @@ #include ZigbeeNetworkManager::ZigbeeNetworkManager(QObject *parent) : - ZigbeeNetwork(ZigbeeNetwork::ControlerTypeNxp, parent) + QObject(parent) { } @@ -80,6 +80,21 @@ void ZigbeeNetworkManager::setPermitJoining(bool permitJoining) }); } +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) @@ -99,6 +114,13 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState } 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); @@ -121,15 +143,22 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState 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"; - quint32 channelMask = 0; + ZigbeeInterfaceReply *reply = nullptr; if (channel() == 0) { - qCDebug(dcZigbeeNetwork()) << "Autoselect quitest channel for the zigbee network."; + 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); } - ZigbeeInterfaceReply *reply = m_controller->commandSetChannelMask(channelMask); connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSetChannelMaskFinished); break; } @@ -162,12 +191,6 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished); break; } - case StartingStateReadSimpleDescriptor: { - qCDebug(dcZigbeeNetwork()) << "Starting state changed: Read coordinator simple descriptor"; - ZigbeeInterfaceReply *reply = m_controller->commandSimpleDescriptorRequest(shortAddress(), endPoint()); - connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished); - break; - } case StartingStateReadPowerDescriptor: { qCDebug(dcZigbeeNetwork()) << "Starting state changed: Read coordinator power descriptor"; ZigbeeInterfaceReply *reply = m_controller->commandPowerDescriptorRequest(shortAddress()); @@ -203,7 +226,6 @@ void ZigbeeNetworkManager::readControllerVersion() qCDebug(dcZigbeeNetwork()) << "Controller version:" << m_controllerFirmwareVersion; if (m_startingState == StartingStateGetVersion) setStartingState(StartingStateSetPanId); - }); } @@ -476,14 +498,10 @@ void ZigbeeNetworkManager::processNetworkFormed(const ZigbeeInterfaceMessage &me } 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; + qCWarning(dcZigbeeNetwork()) << "Forming network failed" << networkStatus << static_cast(networkStatus); setError(ErrorZigbeeError); setStartingState(StartingStateNone); setState(StateDisconnected); @@ -531,106 +549,106 @@ void ZigbeeNetworkManager::onCommandEnableWhitelistFinished() void ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished() { - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); +// ZigbeeInterfaceReply *reply = static_cast(sender()); +// reply->deleteLater(); - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - return; - } +// 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(); +// qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; +// qCDebug(dcZigbeeController()) << reply->additionalMessage(); - QByteArray data = reply->additionalMessage().data(); +// 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; +// 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; +// 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; - } +// // 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); +// // 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); - } +// // 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); +// 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(); +// 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(StartingStateReadSimpleDescriptor); +// if (m_startingState == StartingStateReadeNodeDescriptor) setStartingState(StartingStateReadPowerDescriptor); } void ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished() @@ -716,149 +734,144 @@ void ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished() ZigbeeNode *node = getZigbeeNode(shortAddress); if (!node) { qCWarning(dcZigbeeNetwork()) << "Could not find node for address" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress); - if (m_startingState == StartingStateReadSimpleDescriptor) setStartingState(StartingStateReadPowerDescriptor); return; } - // Set node data - node->setEndPoint(endPoint); - node->setZigbeeProfile(static_cast(profileId)); - node->setDeviceId(deviceId); - - if (m_startingState == StartingStateReadSimpleDescriptor) setStartingState(StartingStateReadPowerDescriptor); +// // Set node data +// node->setEndPoint(endPoint); +// node->setZigbeeProfile(static_cast(profileId)); +// node->setDeviceId(deviceId); } void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished() { - ZigbeeInterfaceReply *reply = static_cast(sender()); - reply->deleteLater(); +// 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; +// // Note: get the short address from the request data +// QByteArray requestData = reply->request().message().data(); +// quint16 shortAddress; +// QDataStream stream(&requestData, QIODevice::ReadOnly); +// stream >> shortAddress; - if (reply->status() != ZigbeeInterfaceReply::Success) { - qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); - // Note: the power descriptor is the last request from the initialization - ZigbeeNode *node = getZigbeeNode(shortAddress); - if (!node) { - qCWarning(dcZigbeeNetwork()) << "Could not find node for address" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress); - if (m_startingState == StartingStateReadSimpleDescriptor) setStartingState(StartingStateReadPowerDescriptor); - return; - } - if (node->state() != ZigbeeNode::StateInitialized) { - node->setState(ZigbeeNode::StateInitialized); - } - return; - } +// 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(); +// 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)); +// 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)); +// 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 +// // 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; - } +// 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 +// // 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); - } +// 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 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; - } +// // 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; +// 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); - if (m_startingState == StartingStateReadSimpleDescriptor) setStartingState(StartingStateReadPowerDescriptor); - return; - } +// // 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); +// // 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 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); - } - } +// // 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() @@ -1000,13 +1013,26 @@ void ZigbeeNetworkManager::processFactoryNewRestart(const ZigbeeInterfaceMessage 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; } @@ -1051,7 +1077,12 @@ void ZigbeeNetworkManager::processNodeAttributeList(const ZigbeeInterfaceMessage 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); @@ -1061,7 +1092,6 @@ void ZigbeeNetworkManager::processNodeAttributeList(const ZigbeeInterfaceMessage 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)); @@ -1080,39 +1110,48 @@ void ZigbeeNetworkManager::processNodeCommandIdList(const ZigbeeInterfaceMessage void ZigbeeNetworkManager::processDeviceAnnounce(const ZigbeeInterfaceMessage &message) { - quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(0, 2)); - quint64 ieeeAddress = ZigbeeUtils::convertByteArrayToUint64(message.data().mid(2, 8)); + QByteArray data = message.data(); - quint8 macCapabilitiesFlag = static_cast(message.data().at(10)); + 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); - ZigbeeNode *node = createNode(); - node->setShortAddress(shortAddress); - node->setExtendedAddress(ZigbeeAddress(ieeeAddress)); - node->setMacCapabilitiesFlag(macCapabilitiesFlag); + // Check if we already have a node with this - qCDebug(dcZigbeeNetwork()) << " Node:" << node; - // FIXME: check if node already added, and if we have to update it - addUnitializedNode(node); - node->setState(StateInitializing); +// ZigbeeNode *node = createNode(); +// node->setShortAddress(shortAddress); +// node->setExtendedAddress(ZigbeeAddress(ieeeAddress)); +// node->setMacCapabilitiesFlag(macCapabilitiesFlag); - ZigbeeInterfaceReply *reply = nullptr; - reply = m_controller->commandAuthenticateDevice(node->extendedAddress(), securityConfiguration().globalTrustCenterLinkKey()); - connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandAuthenticateDeviceFinished); +// qCDebug(dcZigbeeNetwork()) << " Node:" << node; - 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); +// // 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) @@ -1210,9 +1249,21 @@ void ZigbeeNetworkManager::processRestartProvisioned(const ZigbeeInterfaceMessag 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; @@ -1232,6 +1283,16 @@ void ZigbeeNetworkManager::processRestartProvisioned(const ZigbeeInterfaceMessag } } +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..."; @@ -1307,6 +1368,9 @@ void ZigbeeNetworkManager::onMessageReceived(const ZigbeeInterfaceMessage &messa case Zigbee::MessageTypeRestartProvisioned: processRestartProvisioned(message); break; + case Zigbee::MessageTypeRouterDiscoveryConfirm: + processRouterDiscoveryConfirm(message); + break; default: qCWarning(dcZigbeeController()) << "Unhandled message received:" << message; break; @@ -1338,7 +1402,6 @@ void ZigbeeNetworkManager::onControllerAvailableChanged(bool available) } - void ZigbeeNetworkManager::factoryResetNetwork() { qCDebug(dcZigbeeNetwork()) << "Factory reset network and forget all information. This cannot be undone."; diff --git a/libnymea-zigbee/zigbeenetworkmanager.h b/libnymea-zigbee/zigbeenetworkmanager.h index 1d72ae7..ca0e7b6 100644 --- a/libnymea-zigbee/zigbeenetworkmanager.h +++ b/libnymea-zigbee/zigbeenetworkmanager.h @@ -35,7 +35,7 @@ #include "zigbeebridgecontroller.h" #include "zigbeesecurityconfiguration.h" -class ZigbeeNetworkManager : public ZigbeeNetwork +class ZigbeeNetworkManager : public QObject { Q_OBJECT public: @@ -51,6 +51,7 @@ public: // Note: Follwoing methods should be abstract bool permitJoining() const; void setPermitJoining(bool permitJoining); + void resetController(); private: enum StartingState { @@ -65,7 +66,6 @@ private: StartingStateStartNetwork, StartingStateGetPermitJoinStatus, StartingStateReadeNodeDescriptor, - StartingStateReadSimpleDescriptor, StartingStateReadPowerDescriptor }; @@ -126,6 +126,7 @@ private slots: 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/zigbeenode.cpp b/libnymea-zigbee/zigbeenode.cpp index 7b5169b..9c96faa 100644 --- a/libnymea-zigbee/zigbeenode.cpp +++ b/libnymea-zigbee/zigbeenode.cpp @@ -31,6 +31,16 @@ #include +/* Node initialisation steps (sequentially) + * - Authenticate + * - Node descriptor + * - Power descriptor + * - Active endpoints + * - for each endpoint do: + * * Simple descriptor request + */ + + ZigbeeNode::ZigbeeNode(QObject *parent) : QObject(parent) { @@ -57,9 +67,9 @@ ZigbeeAddress ZigbeeNode::extendedAddress() const return m_extendedAddress; } -quint8 ZigbeeNode::endPoint() const +QList ZigbeeNode::endPoints() const { - return m_endPoint; + return m_endPoints; } ZigbeeNode::NodeType ZigbeeNode::nodeType() const @@ -77,21 +87,11 @@ ZigbeeNode::Relationship ZigbeeNode::relationship() const return m_relationship; } -Zigbee::ZigbeeProfile ZigbeeNode::profile() const -{ - return m_profile; -} - quint16 ZigbeeNode::manufacturerCode() const { return m_manufacturerCode; } -quint16 ZigbeeNode::deviceId() const -{ - return m_deviceId; -} - bool ZigbeeNode::complexDescriptorAvailable() const { return m_complexDescriptorAvailable; @@ -117,35 +117,6 @@ quint8 ZigbeeNode::maximumBufferSize() const return m_maximumBufferSize; } -QList ZigbeeNode::inputClusters() const -{ - return m_inputClusters.values(); -} - -ZigbeeCluster *ZigbeeNode::getInputCluster(Zigbee::ClusterId clusterId) const -{ - return m_inputClusters.value(clusterId); -} - -bool ZigbeeNode::hasInputCluster(Zigbee::ClusterId clusterId) const -{ - return m_inputClusters.keys().contains(clusterId); -} - -QList ZigbeeNode::outputClusters() const -{ - return m_outputClusters.values(); -} - -bool ZigbeeNode::hasOutputCluster(Zigbee::ClusterId clusterId) const -{ - return m_outputClusters.keys().contains(clusterId); -} - -ZigbeeCluster *ZigbeeNode::getOutputCluster(Zigbee::ClusterId clusterId) const -{ - return m_outputClusters.value(clusterId); -} bool ZigbeeNode::isPrimaryTrustCenter() const { @@ -308,139 +279,241 @@ void ZigbeeNode::setExtendedAddress(const ZigbeeAddress &extendedAddress) m_extendedAddress = extendedAddress; } -void ZigbeeNode::setEndPoint(quint8 endPoint) +void ZigbeeNode::setEndPoints(QList endPoints) { - m_endPoint = endPoint; + m_endPoints = endPoints; } -void ZigbeeNode::setNodeType(ZigbeeNode::NodeType nodeType) +QByteArray ZigbeeNode::nodeDescriptorRawData() const { - m_nodeType = nodeType; + return m_nodeDescriptorRawData; } -void ZigbeeNode::setFrequencyBand(ZigbeeNode::FrequencyBand frequencyBand) +void ZigbeeNode::setNodeDescriptorRawData(const QByteArray nodeDescriptorRawData) { - m_frequencyBand = frequencyBand; -} + m_nodeDescriptorRawData = nodeDescriptorRawData; -void ZigbeeNode::setRelationship(ZigbeeNode::Relationship relationship) -{ - m_relationship = relationship; -} + // Parse the raw data + quint8 sequenceNumber = 0; + quint8 status = 0; + quint16 shortAddress = 0; + quint16 manufacturerCode = 0; + quint16 maximalRxSize = 0; + quint16 maximalTxSize = 0; + quint16 serverMask = 0; + quint8 descriptorFlag = 0; + quint8 macFlags = 0; + quint8 maxBufferSize = 0; + quint16 bitField = 0; -void ZigbeeNode::setZigbeeProfile(Zigbee::ZigbeeProfile profile) -{ - m_profile = profile; -} + QDataStream stream(&m_nodeDescriptorRawData, QIODevice::ReadOnly); + stream >> sequenceNumber; + stream >> status; + stream >> shortAddress; + stream >> manufacturerCode; + stream >> maximalRxSize; + stream >> maximalTxSize; + stream >> serverMask; + stream >> descriptorFlag; + stream >> macFlags; + stream >> maxBufferSize; + stream >> bitField; -void ZigbeeNode::setManufacturerCode(quint16 manufacturerCode) -{ + // Set node data m_manufacturerCode = manufacturerCode; + m_maximumRxSize = maximalRxSize; + m_maximumTxSize = maximalTxSize; + m_maximumBufferSize = maxBufferSize; + + setServerMask(serverMask); + setMacCapabilitiesFlag(macFlags); + setDescriptorFlag(descriptorFlag); + + // Parse bit field + // 0-2 Bit = logical type, 0 = coordinator, 1 = router, 2 = end device + if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) { + m_nodeType = NodeTypeCoordinator; + } else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) { + m_nodeType = NodeTypeRouter; + } else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) { + m_nodeType = NodeTypeEndDevice; + } + + m_complexDescriptorAvailable = (bitField >> 3) & 0x0001; + m_userDescriptorAvailable = (bitField >> 4) & 0x0001; + + qCDebug(dcZigbeeNode()) << "Node descriptor:"; + qCDebug(dcZigbeeNode()) << " Node type:" << nodeType(); + qCDebug(dcZigbeeNode()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber); + qCDebug(dcZigbeeNode()) << " Status:" << ZigbeeUtils::convertByteToHexString(status); + qCDebug(dcZigbeeNode()) << " Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); + qCDebug(dcZigbeeNode()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode); + qCDebug(dcZigbeeNode()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(maximumRxSize()); + qCDebug(dcZigbeeNode()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(maximumTxSize()); + qCDebug(dcZigbeeNode()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(maximumBufferSize()); + qCDebug(dcZigbeeNode()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask); + qCDebug(dcZigbeeNode()) << " Primary Trust center:" << isPrimaryTrustCenter(); + qCDebug(dcZigbeeNode()) << " Backup Trust center:" << isBackupTrustCenter(); + qCDebug(dcZigbeeNode()) << " Primary Binding cache:" << isPrimaryBindingCache(); + qCDebug(dcZigbeeNode()) << " Backup Binding cache:" << isBackupBindingCache(); + qCDebug(dcZigbeeNode()) << " Primary Discovery cache:" << isPrimaryDiscoveryCache(); + qCDebug(dcZigbeeNode()) << " Backup Discovery cache:" << isBackupDiscoveryCache(); + qCDebug(dcZigbeeNode()) << " Network Manager:" << isNetworkManager(); + qCDebug(dcZigbeeNode()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorFlag); + qCDebug(dcZigbeeNode()) << " Extended active endpoint list available:" << extendedActiveEndpointListAvailable(); + qCDebug(dcZigbeeNode()) << " Extended simple descriptor list available:" << extendedSimpleDescriptorListAvailable(); + qCDebug(dcZigbeeNode()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macFlags); + qCDebug(dcZigbeeNode()) << " Alternate PAN coordinator:" << alternatePanCoordinator(); + qCDebug(dcZigbeeNode()) << " Device type:" << deviceType(); + qCDebug(dcZigbeeNode()) << " Power source flag main power:" << powerSourceFlagMainPower(); + qCDebug(dcZigbeeNode()) << " Receiver on when idle:" << receiverOnWhenIdle(); + qCDebug(dcZigbeeNode()) << " Security capability:" << securityCapability(); + qCDebug(dcZigbeeNode()) << " Allocate address:" << allocateAddress(); + qCDebug(dcZigbeeNode()) << " Bit field:" << ZigbeeUtils::convertUint16ToHexString(bitField); + qCDebug(dcZigbeeNode()) << " Complex desciptor available:" << complexDescriptorAvailable(); + qCDebug(dcZigbeeNode()) << " User desciptor available:" << userDescriptorAvailable(); } -void ZigbeeNode::setDeviceId(quint16 deviceId) +quint16 ZigbeeNode::serverMask() const { - m_deviceId = deviceId; -} - -void ZigbeeNode::setMaximumRxSize(quint16 size) -{ - m_maximumRxSize = size; -} - -void ZigbeeNode::setMaximumTxSize(quint16 size) -{ - m_maximumTxSize = size; -} - -void ZigbeeNode::setMaximumBufferSize(quint8 size) -{ - m_maximumBufferSize = size; + return m_serverMask; } void ZigbeeNode::setServerMask(quint16 serverMask) { - m_isPrimaryTrustCenter = ((serverMask >> 0) & 0x0001); - m_isBackupTrustCenter = ((serverMask >> 1) & 0x0001); - m_isPrimaryBindingCache = ((serverMask >> 2) & 0x0001); - m_isBackupBindingCache = ((serverMask >> 3) & 0x0001); - m_isPrimaryDiscoveryCache = ((serverMask >> 4) & 0x0001); - m_isBackupDiscoveryCache = ((serverMask >> 5) & 0x0001); - m_isNetworkManager = ((serverMask >> 6) & 0x0001); + m_serverMask = serverMask; + m_isPrimaryTrustCenter = ((m_serverMask >> 0) & 0x0001); + m_isBackupTrustCenter = ((m_serverMask >> 1) & 0x0001); + m_isPrimaryBindingCache = ((m_serverMask >> 2) & 0x0001); + m_isBackupBindingCache = ((m_serverMask >> 3) & 0x0001); + m_isPrimaryDiscoveryCache = ((m_serverMask >> 4) & 0x0001); + m_isBackupDiscoveryCache = ((m_serverMask >> 5) & 0x0001); + m_isNetworkManager = ((m_serverMask >> 6) & 0x0001); } -void ZigbeeNode::setComplexDescriptorAvailable(bool complexDescriptorAvailable) +quint8 ZigbeeNode::macCapabilitiesFlag() const { - m_complexDescriptorAvailable = complexDescriptorAvailable; + return m_macCapabilitiesFlag; } -void ZigbeeNode::setUserDescriptorAvailable(bool userDescriptorAvailable) +void ZigbeeNode::setMacCapabilitiesFlag(quint8 macFlag) { - m_userDescriptorAvailable = userDescriptorAvailable; -} - -void ZigbeeNode::setMacCapabilitiesFlag(quint16 macFlag) -{ - // Parse MAC capabilities - m_alternatePanCoordinator = ((macFlag >> 0) & 0x01); - if (((macFlag >> 1) & 0x01)) { + m_macCapabilitiesFlag = macFlag; + m_alternatePanCoordinator = ((m_macCapabilitiesFlag >> 0) & 0x01); + if (((m_macCapabilitiesFlag >> 1) & 0x01)) { m_deviceType = DeviceTypeFullFunction; } else { m_deviceType = DeviceTypeReducedFunction; } - m_powerSourceFlagMainPower = ((macFlag >> 2) & 0x01); - m_receiverOnWhenIdle = ((macFlag >> 3) & 0x01); - m_securityCapability = ((macFlag >> 6) & 0x01); - m_allocateAddress = ((macFlag >> 7) & 0x01); + m_powerSourceFlagMainPower = ((m_macCapabilitiesFlag >> 2) & 0x01); + m_receiverOnWhenIdle = ((m_macCapabilitiesFlag >> 3) & 0x01); + m_securityCapability = ((m_macCapabilitiesFlag >> 6) & 0x01); + m_allocateAddress = ((m_macCapabilitiesFlag >> 7) & 0x01); } void ZigbeeNode::setDescriptorFlag(quint8 descriptorFlag) { - m_extendedActiveEndpointListAvailable = ((descriptorFlag >> 0) & 0x01); - m_extendedSimpleDescriptorListAvailable = ((descriptorFlag >> 1) & 0x01); + m_descriptorFlag = descriptorFlag; + m_extendedActiveEndpointListAvailable = ((m_descriptorFlag >> 0) & 0x01); + m_extendedSimpleDescriptorListAvailable = ((m_descriptorFlag >> 1) & 0x01); } -void ZigbeeNode::setPowerMode(ZigbeeNode::PowerMode powerMode) +quint16 ZigbeeNode::powerDescriptorFlag() const { - m_powerMode = powerMode; + return m_powerDescriptorFlag; } -void ZigbeeNode::setPowerSource(ZigbeeNode::PowerSource powerSource) +void ZigbeeNode::setPowerDescriptorFlag(quint16 powerDescriptorFlag) { - m_powerSource = powerSource; -} + m_powerDescriptorFlag = powerDescriptorFlag; -void ZigbeeNode::setAvailablePowerSources(QList availablePowerSources) -{ - m_availablePowerSources = availablePowerSources; -} + // 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 + + m_powerMode = PowerModeAlwaysOn; + if (!ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 0) && !ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 1)) { + m_powerMode = PowerModeAlwaysOn; + } else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 0) && !ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 1)) { + m_powerMode = PowerModeOnPeriodically; + } else if (!ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 0) && ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 1)) { + m_powerMode = PowerModeOnWhenStimulated; + } + + // Bit 4 - 7 Available power sources + // Bit 0: Permanent mains supply + // Bit 1: Rechargeable battery + // Bit 2: Disposable battery + // Bit 4: Reserved + + m_availablePowerSources.clear(); + if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 4)) { + m_availablePowerSources.append(PowerSourcePermanentMainSupply); + } else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 5)) { + m_availablePowerSources.append(PowerSourceRecharchableBattery); + } else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 6)) { + m_availablePowerSources.append(PowerSourceDisposableBattery); + } + + // Bit 8 - 11 Active source: according to the same schema as available power sources + m_powerSource = PowerSourcePermanentMainSupply; + if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 8)) { + m_powerSource = PowerSourcePermanentMainSupply; + } else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 9)) { + m_powerSource = PowerSourceRecharchableBattery; + } else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 10)) { + m_powerSource = PowerSourceDisposableBattery; + } + + // Bit 12 - 15: Battery level if available + // 0000: Critically low + // 0100: Approximately 33% + // 1000: Approximately 66% + // 1100: Approximately 100% (near fully charged) + m_powerLevel = PowerLevelCriticalLow; + if (!ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 14) && !ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 15)) { + m_powerLevel = PowerLevelCriticalLow; + } else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 14) && !ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 15)) { + m_powerLevel = PowerLevelLow; + } else if (!ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 14) && ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 15)) { + m_powerLevel = PowerLevelOk; + } else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 14) && ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 15)) { + m_powerLevel = PowerLevelFull; + } + + qCDebug(dcZigbeeNode()) << "Node power descriptor (" << ZigbeeUtils::convertUint16ToHexString(m_powerDescriptorFlag) << "):"; + qCDebug(dcZigbeeNode()) << " Power mode:" << m_powerMode; + qCDebug(dcZigbeeNode()) << " Available power sources:"; + foreach (const PowerSource &source, m_availablePowerSources) { + qCDebug(dcZigbeeNode()) << " " << source; + } + qCDebug(dcZigbeeNode()) << " Power source:" << m_powerSource; + qCDebug(dcZigbeeNode()) << " Power level:" << m_powerLevel; -void ZigbeeNode::setPowerLevel(ZigbeeNode::PowerLevel powerLevel) -{ - m_powerLevel = powerLevel; } void ZigbeeNode::setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute) { qCDebug(dcZigbeeNode()) << this << "cluster attribute changed" << clusterId << attribute; - ZigbeeCluster *cluster = m_outputClusters.value(clusterId); +// ZigbeeCluster *cluster = m_outputClusters.value(clusterId); - // Note: create the cluster if not there yet - bool clusterCreated = false; - if (!cluster) { - cluster = new ZigbeeCluster(clusterId, this); - qCDebug(dcZigbeeNode()) << "Created cluster" << cluster; - connect(cluster, &ZigbeeCluster::attributeChanged, this, &ZigbeeNode::onClusterAttributeChanged); - m_outputClusters.insert(clusterId, cluster); - clusterCreated = true; - } +// // Note: create the cluster if not there yet +// bool clusterCreated = false; +// if (!cluster) { +// cluster = new ZigbeeCluster(clusterId, this); +// qCDebug(dcZigbeeNode()) << "Created cluster" << cluster; +// connect(cluster, &ZigbeeCluster::attributeChanged, this, &ZigbeeNode::onClusterAttributeChanged); +// m_outputClusters.insert(clusterId, cluster); +// clusterCreated = true; +// } - // Set the attribute if valid - if (attribute.isValid()) - cluster->setAttribute(attribute); +// // Set the attribute if valid +// if (attribute.isValid()) +// cluster->setAttribute(attribute); - if (clusterCreated) - emit clusterAdded(cluster); +// if (clusterCreated) +// emit clusterAdded(cluster); } @@ -478,12 +551,12 @@ void ZigbeeNode::onClusterAttributeChanged(const ZigbeeClusterAttribute &attribu // data = reply->additionalMessage().data().mid(5, length); // } -// qCDebug(dcZigbeeNetwork()) << "User descriptor:"; -// qCDebug(dcZigbeeNetwork()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber); -// qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(status); -// qCDebug(dcZigbeeNetwork()) << " Attribute address:" << ZigbeeUtils::convertUint16ToHexString(nwkAddress); -// qCDebug(dcZigbeeNetwork()) << " Lenght:" << ZigbeeUtils::convertByteToHexString(length); -// qCDebug(dcZigbeeNetwork()) << " Data:" << data; +// qCDebug(dcZigbeeNode()) << "User descriptor:"; +// qCDebug(dcZigbeeNode()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber); +// qCDebug(dcZigbeeNode()) << " Status:" << ZigbeeUtils::convertByteToHexString(status); +// qCDebug(dcZigbeeNode()) << " Attribute address:" << ZigbeeUtils::convertUint16ToHexString(nwkAddress); +// qCDebug(dcZigbeeNode()) << " Lenght:" << ZigbeeUtils::convertByteToHexString(length); +// qCDebug(dcZigbeeNode()) << " Data:" << data; //} //void ZigbeeNode::onToggleFinished() @@ -506,6 +579,17 @@ void ZigbeeNode::onClusterAttributeChanged(const ZigbeeClusterAttribute &attribu QDebug operator<<(QDebug debug, ZigbeeNode *node) { - debug.nospace().noquote() << "ZigbeeNode(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress()) << ", " << node->extendedAddress().toString() << ") "; + debug.nospace().noquote() << "ZigbeeNode(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress()); + debug.nospace().noquote() << ", " << node->extendedAddress().toString(); +// debug.nospace().noquote() << ", End points: "; + +// for (int i = 0; i < node->endPoints().count(); i++) { +// debug.nospace().noquote() << ZigbeeUtils::convertByteToHexString(node->endPoints().at(i)); +// if (i != node->endPoints().count() - 1 && node->endPoints().count() > 1) { +// debug.nospace().noquote() << ", "; +// } +// } + + debug.nospace().noquote() << ") "; return debug; } diff --git a/libnymea-zigbee/zigbeenode.h b/libnymea-zigbee/zigbeenode.h index d0e672f..6921d1d 100644 --- a/libnymea-zigbee/zigbeenode.h +++ b/libnymea-zigbee/zigbeenode.h @@ -103,15 +103,13 @@ public: quint16 shortAddress() const; ZigbeeAddress extendedAddress() const; - quint8 endPoint() const; + QList endPoints() const; // Information from node descriptor NodeType nodeType() const; FrequencyBand frequencyBand() const; Relationship relationship() const; - Zigbee::ZigbeeProfile profile() const; quint16 manufacturerCode() const; - quint16 deviceId() const; bool complexDescriptorAvailable() const; bool userDescriptorAvailable() const; @@ -120,14 +118,6 @@ public: quint16 maximumTxSize() const; quint8 maximumBufferSize() const; - QList inputClusters() const; - ZigbeeCluster *getInputCluster(Zigbee::ClusterId clusterId) const; - bool hasInputCluster(Zigbee::ClusterId clusterId) const; - - QList outputClusters() const; - ZigbeeCluster *getOutputCluster(Zigbee::ClusterId clusterId) const; - bool hasOutputCluster(Zigbee::ClusterId clusterId) const; - // Server Mask bool isPrimaryTrustCenter() const; bool isBackupTrustCenter() const; @@ -160,19 +150,16 @@ private: bool m_connected = false; State m_state = StateUninitialized; - QHash m_inputClusters; - QHash m_outputClusters; - quint16 m_shortAddress = 0; ZigbeeAddress m_extendedAddress; - quint8 m_endPoint = 1; + QList m_endPoints; + // Node descriptor information + QByteArray m_nodeDescriptorRawData; NodeType m_nodeType = NodeTypeRouter; FrequencyBand m_frequencyBand = FrequencyBand2400Mhz; Relationship m_relationship = Parent; - Zigbee::ZigbeeProfile m_profile; quint16 m_manufacturerCode = 0; - quint16 m_deviceId = 0; bool m_complexDescriptorAvailable = false; bool m_userDescriptorAvailable = false; @@ -182,6 +169,7 @@ private: quint8 m_maximumBufferSize = 0; // Server Mask + quint16 m_serverMask = 0; bool m_isPrimaryTrustCenter = false; bool m_isBackupTrustCenter = false; bool m_isPrimaryBindingCache = false; @@ -191,12 +179,14 @@ private: bool m_isNetworkManager = false; // Power information + quint16 m_powerDescriptorFlag = 0; PowerMode m_powerMode; PowerSource m_powerSource; QList m_availablePowerSources; PowerLevel m_powerLevel; // Mac capabilities flag + quint8 m_macCapabilitiesFlag = 0; bool m_alternatePanCoordinator = false; DeviceType m_deviceType = DeviceTypeFullFunction; bool m_powerSourceFlagMainPower = false; @@ -205,38 +195,35 @@ private: bool m_allocateAddress = false; // Descriptor capability + quint8 m_descriptorFlag = 0; bool m_extendedActiveEndpointListAvailable = false; bool m_extendedSimpleDescriptorListAvailable = false; -protected: +private: void setState(State state); void setConnected(bool connected); void setShortAddress(const quint16 &shortAddress); void setExtendedAddress(const ZigbeeAddress &extendedAddress); - void setEndPoint(quint8 endPoint); + void setEndPoints(QList endPoints); - void setNodeType(NodeType nodeType); - void setFrequencyBand(FrequencyBand frequencyBand); - void setRelationship(Relationship relationship); - void setZigbeeProfile(Zigbee::ZigbeeProfile profile); - void setManufacturerCode(quint16 manufacturerCode); - void setDeviceId(quint16 deviceType); - - void setMaximumRxSize(quint16 size); - void setMaximumTxSize(quint16 size); - void setMaximumBufferSize(quint8 size); + // Note: node descriptor properties (raw data for settings) + QByteArray nodeDescriptorRawData() const; + void setNodeDescriptorRawData(const QByteArray nodeDescriptorRawData); + quint16 serverMask() const; void setServerMask(quint16 serverMask); - void setComplexDescriptorAvailable(bool complexDescriptorAvailable); - void setUserDescriptorAvailable(bool userDescriptorAvailable); - void setMacCapabilitiesFlag(quint16 macFlag); + + // MAC capability raw data flag for settings + quint8 macCapabilitiesFlag() const; + void setMacCapabilitiesFlag(quint8 macFlag); + + quint8 descriptorFlag() const; void setDescriptorFlag(quint8 descriptorFlag); - void setPowerMode(PowerMode powerMode); - void setPowerSource(PowerSource powerSource); - void setAvailablePowerSources(QList availablePowerSources); - void setPowerLevel(PowerLevel powerLevel); + // Power decriptor data + quint16 powerDescriptorFlag() const; + void setPowerDescriptorFlag(quint16 powerDescriptorFlag); // Cluster commands void setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute = ZigbeeClusterAttribute()); diff --git a/libnymea-zigbee/zigbeenodeendpoint.cpp b/libnymea-zigbee/zigbeenodeendpoint.cpp new file mode 100644 index 0000000..4822b2d --- /dev/null +++ b/libnymea-zigbee/zigbeenodeendpoint.cpp @@ -0,0 +1,64 @@ +#include "zigbeenodeendpoint.h" + +ZigbeeNodeEndpoint::ZigbeeNodeEndpoint(quint8 endpoint, QObject *parent) : + QObject(parent), + m_endpoint(endpoint) +{ + +} + +quint8 ZigbeeNodeEndpoint::endpoint() const +{ + return m_endpoint; +} + +Zigbee::ZigbeeProfile ZigbeeNodeEndpoint::profile() const +{ + return m_profile; +} + +void ZigbeeNodeEndpoint::setProfile(Zigbee::ZigbeeProfile profile) +{ + m_profile = profile; +} + +quint16 ZigbeeNodeEndpoint::deviceId() const +{ + return m_deviceId; +} + +void ZigbeeNodeEndpoint::setDeviceId(quint16 deviceId) +{ + m_deviceId = deviceId; +} + + +QList ZigbeeNodeEndpoint::inputClusters() const +{ + return m_inputClusters.values(); +} + +ZigbeeCluster *ZigbeeNodeEndpoint::getInputCluster(Zigbee::ClusterId clusterId) const +{ + return m_inputClusters.value(clusterId); +} + +bool ZigbeeNodeEndpoint::hasInputCluster(Zigbee::ClusterId clusterId) const +{ + return m_inputClusters.keys().contains(clusterId); +} + +QList ZigbeeNodeEndpoint::outputClusters() const +{ + return m_outputClusters.values(); +} + +bool ZigbeeNodeEndpoint::hasOutputCluster(Zigbee::ClusterId clusterId) const +{ + return m_outputClusters.keys().contains(clusterId); +} + +ZigbeeCluster *ZigbeeNodeEndpoint::getOutputCluster(Zigbee::ClusterId clusterId) const +{ + return m_outputClusters.value(clusterId); +} diff --git a/libnymea-zigbee/zigbeenodeendpoint.h b/libnymea-zigbee/zigbeenodeendpoint.h new file mode 100644 index 0000000..770ac4b --- /dev/null +++ b/libnymea-zigbee/zigbeenodeendpoint.h @@ -0,0 +1,46 @@ +#ifndef ZIGBEENODEENDPOINT_H +#define ZIGBEENODEENDPOINT_H + +#include + +#include "zigbee.h" +#include "zigbeecluster.h" +class ZigbeeNodeEndpoint : public QObject +{ + Q_OBJECT +public: + explicit ZigbeeNodeEndpoint(quint8 endpoint, QObject *parent = nullptr); + + quint8 endpoint() const; + + Zigbee::ZigbeeProfile profile() const; + void setProfile(Zigbee::ZigbeeProfile profile); + + quint16 deviceId() const; + void setDeviceId(quint16 deviceId); + + quint8 deviceVersion() const; + void setDeviceVersion(quint8 deviceVersion); + + QList inputClusters() const; + ZigbeeCluster *getInputCluster(Zigbee::ClusterId clusterId) const; + bool hasInputCluster(Zigbee::ClusterId clusterId) const; + + QList outputClusters() const; + ZigbeeCluster *getOutputCluster(Zigbee::ClusterId clusterId) const; + bool hasOutputCluster(Zigbee::ClusterId clusterId) const; + +private: + quint8 m_endpoint = 0; + Zigbee::ZigbeeProfile m_profile = Zigbee::ZigbeeProfileLightLink; + quint16 m_deviceId = 0; + quint8 m_deviceVersion = 0; + + QHash m_inputClusters; + QHash m_outputClusters; + +signals: + +}; + +#endif // ZIGBEENODEENDPOINT_H diff --git a/libnymea-zigbee/zigbeeutils.cpp b/libnymea-zigbee/zigbeeutils.cpp index e4d1030..561f597 100644 --- a/libnymea-zigbee/zigbeeutils.cpp +++ b/libnymea-zigbee/zigbeeutils.cpp @@ -120,6 +120,15 @@ QString ZigbeeUtils::convertUint16ToHexString(const quint16 &value) return QString("0x%1").arg(convertByteArrayToHexString(data).remove(" ").remove("0x")); } +QString ZigbeeUtils::convertUint32ToHexString(const quint32 &value) +{ + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + stream << value; + + return QString("0x%1").arg(convertByteArrayToHexString(data).remove(" ").remove("0x")); +} + QString ZigbeeUtils::convertUint64ToHexString(const quint64 &value) { QByteArray data; @@ -160,6 +169,7 @@ QString ZigbeeUtils::profileIdToString(const Zigbee::ZigbeeProfile &profileId) quint64 ZigbeeUtils::generateRandomPanId() { + // Note: the PAN ID has to be between 0x0000 and 0x3fff qsrand(static_cast(QDateTime::currentMSecsSinceEpoch() / 1000)); - return static_cast((ULLONG_MAX - 0) * (qrand()/static_cast(RAND_MAX))); + return static_cast(rand() % (0x3fff - 1) + 1); } diff --git a/libnymea-zigbee/zigbeeutils.h b/libnymea-zigbee/zigbeeutils.h index 981e38d..7952b47 100644 --- a/libnymea-zigbee/zigbeeutils.h +++ b/libnymea-zigbee/zigbeeutils.h @@ -52,6 +52,7 @@ public: static QString convertByteToHexString(const quint8 &byte); static QString convertByteArrayToHexString(const QByteArray &byteArray); static QString convertUint16ToHexString(const quint16 &value); + static QString convertUint32ToHexString(const quint32 &value); static QString convertUint64ToHexString(const quint64 &value); // Enum prittify print methods