From 7cdf772b1ad2931cf089bd3d3c3ccc74a4534504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Wed, 6 May 2020 12:33:26 +0200 Subject: [PATCH] Start implementing clusters --- README.md | 14 ++ config.pri | 2 +- .../deconz/zigbeebridgecontrollerdeconz.cpp | 2 +- .../deconz/zigbeenetworkdeconz.cpp | 44 ++-- libnymea-zigbee/deconz/zigbeenetworkdeconz.h | 6 +- libnymea-zigbee/deconz/zigbeenodedeconz.cpp | 52 ++++- libnymea-zigbee/deconz/zigbeenodedeconz.h | 2 + .../deconz/zigbeenodeendpointdeconz.cpp | 14 -- .../deconz/zigbeenodeendpointdeconz.h | 4 +- libnymea-zigbee/libnymea-zigbee.pro | 50 +++-- libnymea-zigbee/loggingcategory.cpp | 1 + libnymea-zigbee/loggingcategory.h | 1 + libnymea-zigbee/zcl/zigbeeclusterbasic.cpp | 7 + libnymea-zigbee/zcl/zigbeeclusterbasic.h | 51 +++++ libnymea-zigbee/zdo/zigbeedeviceobject.cpp | 9 + libnymea-zigbee/zdo/zigbeedeviceobject.h | 21 ++ .../zdo/zigbeedeviceobjectreply.cpp | 6 + libnymea-zigbee/zdo/zigbeedeviceobjectreply.h | 16 ++ .../{ => zdo}/zigbeedeviceprofile.cpp | 0 .../{ => zdo}/zigbeedeviceprofile.h | 7 + .../zdo/zigbeedeviceprofilehandler.cpp | 6 + .../zdo/zigbeedeviceprofilehandler.h | 16 ++ libnymea-zigbee/zigbeecluster.cpp | 55 ++++- libnymea-zigbee/zigbeecluster.h | 20 +- libnymea-zigbee/zigbeeclusterlibrary.cpp | 8 +- libnymea-zigbee/zigbeeclusterlibrary.h | 6 +- libnymea-zigbee/zigbeeclusterlibraryreply.cpp | 24 +++ libnymea-zigbee/zigbeeclusterlibraryreply.h | 35 ++++ libnymea-zigbee/zigbeenetwork.cpp | 21 +- libnymea-zigbee/zigbeenetwork.h | 17 +- libnymea-zigbee/zigbeenetworkdatabase.cpp | 42 ++++ libnymea-zigbee/zigbeenetworkdatabase.h | 49 +++++ libnymea-zigbee/zigbeenetworkrequest.cpp | 2 +- libnymea-zigbee/zigbeenode.cpp | 188 +++++++++--------- libnymea-zigbee/zigbeenode.h | 13 +- libnymea-zigbee/zigbeenodeendpoint.h | 31 +-- 36 files changed, 627 insertions(+), 215 deletions(-) create mode 100644 libnymea-zigbee/zcl/zigbeeclusterbasic.cpp create mode 100644 libnymea-zigbee/zcl/zigbeeclusterbasic.h create mode 100644 libnymea-zigbee/zdo/zigbeedeviceobject.cpp create mode 100644 libnymea-zigbee/zdo/zigbeedeviceobject.h create mode 100644 libnymea-zigbee/zdo/zigbeedeviceobjectreply.cpp create mode 100644 libnymea-zigbee/zdo/zigbeedeviceobjectreply.h rename libnymea-zigbee/{ => zdo}/zigbeedeviceprofile.cpp (100%) rename libnymea-zigbee/{ => zdo}/zigbeedeviceprofile.h (97%) create mode 100644 libnymea-zigbee/zdo/zigbeedeviceprofilehandler.cpp create mode 100644 libnymea-zigbee/zdo/zigbeedeviceprofilehandler.h create mode 100644 libnymea-zigbee/zigbeeclusterlibraryreply.cpp create mode 100644 libnymea-zigbee/zigbeeclusterlibraryreply.h create mode 100644 libnymea-zigbee/zigbeenetworkdatabase.cpp create mode 100644 libnymea-zigbee/zigbeenetworkdatabase.h diff --git a/README.md b/README.md index f8bb9cc..03ccd23 100644 --- a/README.md +++ b/README.md @@ -18,3 +18,17 @@ Depending on your available hardware following gateway modules are supported * RaspBee * ConBee II * RaspBee II + + +## Structure + +ZigbeeNetwork + - ZDO handler + - ZCL handler + - ZHA handler + - ZLL handler + - GP handler + + - [ZigbeeNode] + - [ZigbeeNodeEndpoints] + - Profile diff --git a/config.pri b/config.pri index 525583c..8c2f05a 100644 --- a/config.pri +++ b/config.pri @@ -1,4 +1,4 @@ -QT += gui serialport +QT += gui serialport sql QMAKE_CXXFLAGS += -Werror -std=c++11 QMAKE_LFLAGS += -std=c++11 diff --git a/libnymea-zigbee/deconz/zigbeebridgecontrollerdeconz.cpp b/libnymea-zigbee/deconz/zigbeebridgecontrollerdeconz.cpp index a9a34f4..fa66231 100644 --- a/libnymea-zigbee/deconz/zigbeebridgecontrollerdeconz.cpp +++ b/libnymea-zigbee/deconz/zigbeebridgecontrollerdeconz.cpp @@ -28,7 +28,7 @@ #include "zigbeeutils.h" #include "loggingcategory.h" #include "zigbeechannelmask.h" -#include "zigbeedeviceprofile.h" +#include "zdo/zigbeedeviceprofile.h" #include "zigbeebridgecontrollerdeconz.h" #include diff --git a/libnymea-zigbee/deconz/zigbeenetworkdeconz.cpp b/libnymea-zigbee/deconz/zigbeenetworkdeconz.cpp index 547bf7a..22d1ceb 100644 --- a/libnymea-zigbee/deconz/zigbeenetworkdeconz.cpp +++ b/libnymea-zigbee/deconz/zigbeenetworkdeconz.cpp @@ -25,8 +25,8 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#include "zdo/zigbeedeviceprofile.h" #include "zigbeenetworkdeconz.h" -#include "zigbeedeviceprofile.h" #include "loggingcategory.h" #include "zigbeeutils.h" @@ -109,11 +109,6 @@ ZigbeeNetworkReply *ZigbeeNetworkDeconz::setPermitJoin(quint16 shortAddress, qui return sendRequest(request); } -quint8 ZigbeeNetworkDeconz::generateSequenceNumber() -{ - return m_sequenceNumber++; -} - void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetworkState state) { if (m_createState == state) @@ -322,8 +317,8 @@ void ZigbeeNetworkDeconz::handleZigbeeDeviceProfileIndication(const DeconzApsDat return; } - // Check if this is a response for a ZDO request foreach (ZigbeeNetworkReply *reply, m_pendingReplies.values()) { + // Check if this is a response for a ZDO request if (reply->request().profileId() == Zigbee::ZigbeeProfileDevice) { // We have a reply which is waiting for a ZDO response, lets check if they match // Check if this is the response to the sent request command @@ -347,6 +342,16 @@ void ZigbeeNetworkDeconz::handleZigbeeDeviceProfileIndication(const DeconzApsDat } qCWarning(dcZigbeeNetwork()) << "FIXME: Unhandled ZDO indication" << indication; +} + +void ZigbeeNetworkDeconz::handleZigbeeHomeAutomationIndication(const DeconzApsDataIndication &indication) +{ + ZigbeeClusterLibrary::Frame frame = ZigbeeClusterLibrary::parseFrameData(static_cast(indication.clusterId), indication.asdu); + qCDebug(dcZigbeeNetwork()) << "ZCL HA" << indication << frame; + + + + } ZigbeeNode *ZigbeeNetworkDeconz::createNode(QObject *parent) @@ -412,22 +417,8 @@ void ZigbeeNetworkDeconz::startNetworkInternally() // Check if we have to create a pan ID and select the channel if (panId() == 0) { m_createNewNetwork = true; - //setExtendedPanId(ZigbeeUtils::generateRandomPanId()); - //qCDebug(dcZigbeeNetwork()) << "Created new PAN ID:" << extendedPanId(); } - // Note: we cannot read or write the network key here. - - // if (securityConfiguration().networkKey().isNull()) { - // m_createNewNetwork = true; - // qCDebug(dcZigbeeNetwork()) << "Create a new network key"; - // ZigbeeNetworkKey key = ZigbeeNetworkKey::generateKey(); - // m_securityConfiguration.setNetworkKey(key); - // } - - //qCDebug(dcZigbeeNetwork()) << "Using" << securityConfiguration().networkKey() << "network link key"; - //qCDebug(dcZigbeeNetwork()) << "Using" << securityConfiguration().globalTrustCenterLinkKey() << "global trust center link key"; - // - Read the firmware version // - Read the network configuration parameters // - Read the network state @@ -630,6 +621,15 @@ void ZigbeeNetworkDeconz::onAspDataIndicationReceived(const DeconzApsDataIndicat return; } + if (indication.profileId == Zigbee::ZigbeeProfileLightLink) { + + } + + if (indication.profileId == Zigbee::ZigbeeProfileHomeAutomation) { + handleZigbeeHomeAutomationIndication(indication); + return; + } + // FIXME: handle it qCDebug(dcZigbeeNetwork()) << "Unhandled indication" << indication; @@ -660,7 +660,7 @@ void ZigbeeNetworkDeconz::startNetwork() m_permitJoining = false; emit permitJoiningChanged(m_permitJoining); setState(StateOffline); - //setStartingState(StartingStateNone); + setCreateNetworkState(CreateNetworkStateIdle); setError(ErrorHardwareUnavailable); return; } diff --git a/libnymea-zigbee/deconz/zigbeenetworkdeconz.h b/libnymea-zigbee/deconz/zigbeenetworkdeconz.h index a3ae5a5..1cbae37 100644 --- a/libnymea-zigbee/deconz/zigbeenetworkdeconz.h +++ b/libnymea-zigbee/deconz/zigbeenetworkdeconz.h @@ -33,6 +33,7 @@ #include "zigbeenetwork.h" #include "zigbeenodedeconz.h" #include "zigbeechannelmask.h" +#include "zigbeeclusterlibrary.h" #include "zigbeebridgecontrollerdeconz.h" class ZigbeeNetworkDeconz : public ZigbeeNetwork @@ -57,8 +58,6 @@ public: ZigbeeNetworkReply *setPermitJoin(quint16 shortAddress, quint8 duration); - quint8 generateSequenceNumber(); - private: ZigbeeBridgeControllerDeconz *m_controller = nullptr; bool m_networkRunning = false; @@ -69,8 +68,6 @@ private: QHash m_pendingReplies; - quint8 m_sequenceNumber = 0; - QTimer *m_pollNetworkStateTimer = nullptr; void setCreateNetworkState(CreateNetworkState state); @@ -80,6 +77,7 @@ private: // ZZL // HA + void handleZigbeeHomeAutomationIndication(const DeconzApsDataIndication &indication); // GP diff --git a/libnymea-zigbee/deconz/zigbeenodedeconz.cpp b/libnymea-zigbee/deconz/zigbeenodedeconz.cpp index 609748d..c9b7558 100644 --- a/libnymea-zigbee/deconz/zigbeenodedeconz.cpp +++ b/libnymea-zigbee/deconz/zigbeenodedeconz.cpp @@ -27,7 +27,7 @@ #include "zigbeeutils.h" #include "zigbeenodedeconz.h" -#include "zigbeedeviceprofile.h" +#include "zdo/zigbeedeviceprofile.h" #include "zigbeenetworkdeconz.h" #include "zigbeenodeendpointdeconz.h" @@ -36,7 +36,7 @@ #include ZigbeeNodeDeconz::ZigbeeNodeDeconz(ZigbeeNetworkDeconz *network, QObject *parent) : - ZigbeeNode(parent), + ZigbeeNode(network, parent), m_network(network) { @@ -138,10 +138,45 @@ ZigbeeNetworkReply *ZigbeeNodeDeconz::requestSimpleDescriptor(quint8 endpoint) return m_network->sendRequest(request); } +ZigbeeNetworkReply *ZigbeeNodeDeconz::requestLeaveNetwork(bool rejoin, bool removeChildren) +{ + ZigbeeNetworkRequest request; + request.setRequestId(m_network->generateSequenceNumber()); + request.setDestinationAddressMode(Zigbee::DestinationAddressModeShortAddress); + request.setDestinationShortAddress(shortAddress()); + request.setDestinationEndpoint(0); // ZDO + request.setProfileId(Zigbee::ZigbeeProfileDevice); // ZDP + request.setClusterId(ZigbeeDeviceProfile::MgmtLeaveRequest); + request.setSourceEndpoint(0); // ZDO + + // Build ASDU + QByteArray asdu; + quint8 leaveFlag = 0; + if (rejoin) { + leaveFlag |= 0x01; + } + + if (removeChildren) { + leaveFlag |= 0x02; + } + + QDataStream stream(&asdu, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << request.requestId() << extendedAddress().toUInt64() << leaveFlag; + request.setAsdu(asdu); + + // We expect an indication with the response and the confirmation + request.setExpectIndication(true); + return m_network->sendRequest(request); +} + void ZigbeeNodeDeconz::leaveNetworkRequest(bool rejoin, bool removeChildren) { - Q_UNUSED(rejoin) - Q_UNUSED(removeChildren) + ZigbeeNetworkReply *reply = requestLeaveNetwork(rejoin, removeChildren); + connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply](){ + // TODO: check reply error + + }); } void ZigbeeNodeDeconz::initNodeDescriptor() @@ -309,7 +344,7 @@ void ZigbeeNodeDeconz::initEndpoints() // Create endpoint ZigbeeNodeEndpointDeconz *endpoint = nullptr; if (!hasEndpoint(endpointId)) { - ZigbeeNodeEndpointDeconz *endpoint = qobject_cast(createNodeEndpoint(endpointId, this)); + endpoint = qobject_cast(createNodeEndpoint(endpointId, this)); m_endpoints.append(endpoint); } else { endpoint = qobject_cast(getEndpoint(endpointId)); @@ -323,7 +358,7 @@ void ZigbeeNodeDeconz::initEndpoints() quint16 clusterId = 0; stream >> clusterId; if (!endpoint->hasInputCluster(static_cast(clusterId))) { - endpoint->addInputCluster(new ZigbeeCluster(static_cast(clusterId), ZigbeeCluster::Input, endpoint)); + endpoint->addInputCluster(new ZigbeeCluster(m_network, this, endpoint, static_cast(clusterId), ZigbeeCluster::Input, endpoint)); } qCDebug(dcZigbeeNode()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast(clusterId)); @@ -335,7 +370,7 @@ void ZigbeeNodeDeconz::initEndpoints() quint16 clusterId = 0; stream >> clusterId; if (!endpoint->hasOutputCluster(static_cast(clusterId))) { - endpoint->addOutputCluster(new ZigbeeCluster(static_cast(clusterId), ZigbeeCluster::Output, endpoint)); + endpoint->addOutputCluster(new ZigbeeCluster(m_network, this, endpoint, static_cast(clusterId), ZigbeeCluster::Output, endpoint)); } qCDebug(dcZigbeeNode()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast(clusterId)); } @@ -354,10 +389,9 @@ void ZigbeeNodeDeconz::initEndpoints() void ZigbeeNodeDeconz::initBasicCluster() { - + // TODO setState(StateInitialized); - } void ZigbeeNodeDeconz::setClusterAttributeReport(const ZigbeeClusterAttributeReport &report) diff --git a/libnymea-zigbee/deconz/zigbeenodedeconz.h b/libnymea-zigbee/deconz/zigbeenodedeconz.h index ce6692d..f53a08f 100644 --- a/libnymea-zigbee/deconz/zigbeenodedeconz.h +++ b/libnymea-zigbee/deconz/zigbeenodedeconz.h @@ -50,6 +50,8 @@ public: ZigbeeNetworkReply *requestActiveEndpoints(); ZigbeeNetworkReply *requestSimpleDescriptor(quint8 endpoint); + ZigbeeNetworkReply *requestLeaveNetwork(bool rejoin = false, bool removeChildren = false); + void leaveNetworkRequest(bool rejoin = false, bool removeChildren = false) override; private: diff --git a/libnymea-zigbee/deconz/zigbeenodeendpointdeconz.cpp b/libnymea-zigbee/deconz/zigbeenodeendpointdeconz.cpp index 98b3675..3956aac 100644 --- a/libnymea-zigbee/deconz/zigbeenodeendpointdeconz.cpp +++ b/libnymea-zigbee/deconz/zigbeenodeendpointdeconz.cpp @@ -36,20 +36,6 @@ ZigbeeNodeEndpointDeconz::ZigbeeNodeEndpointDeconz(ZigbeeNetworkDeconz *network, } -ZigbeeNetworkReply *ZigbeeNodeEndpointDeconz::readAttribute(ZigbeeCluster *cluster, QList attributes) -{ - Q_UNUSED(cluster) - Q_UNUSED(attributes) - return nullptr; -} - -ZigbeeNetworkReply *ZigbeeNodeEndpointDeconz::configureReporting(ZigbeeCluster *cluster, QList reportConfigurations) -{ - Q_UNUSED(cluster) - Q_UNUSED(reportConfigurations) - return nullptr; -} - void ZigbeeNodeEndpointDeconz::setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute) { Q_UNUSED(clusterId) diff --git a/libnymea-zigbee/deconz/zigbeenodeendpointdeconz.h b/libnymea-zigbee/deconz/zigbeenodeendpointdeconz.h index fde0f21..78f8879 100644 --- a/libnymea-zigbee/deconz/zigbeenodeendpointdeconz.h +++ b/libnymea-zigbee/deconz/zigbeenodeendpointdeconz.h @@ -30,6 +30,7 @@ #include #include "zigbeenodeendpoint.h" +#include "zigbeeclusterlibrary.h" class ZigbeeNodeDeconz; class ZigbeeNetworkDeconz; @@ -43,9 +44,6 @@ class ZigbeeNodeEndpointDeconz : public ZigbeeNodeEndpoint public: explicit ZigbeeNodeEndpointDeconz(ZigbeeNetworkDeconz *network, ZigbeeNode *node, quint8 endpointId, QObject *parent = nullptr); - ZigbeeNetworkReply *readAttribute(ZigbeeCluster *cluster, QList attributes) override; - ZigbeeNetworkReply *configureReporting(ZigbeeCluster *cluster, QList reportConfigurations) override; - protected: // Cluster commands void setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute = ZigbeeClusterAttribute()) override; diff --git a/libnymea-zigbee/libnymea-zigbee.pro b/libnymea-zigbee/libnymea-zigbee.pro index b04e37d..98ac205 100644 --- a/libnymea-zigbee/libnymea-zigbee.pro +++ b/libnymea-zigbee/libnymea-zigbee.pro @@ -10,23 +10,29 @@ SOURCES += \ deconz/zigbeenetworkdeconz.cpp \ deconz/zigbeenodedeconz.cpp \ deconz/zigbeenodeendpointdeconz.cpp \ - nxp/interface/zigbeeinterface.cpp \ - nxp/interface/zigbeeinterfacemessage.cpp \ - nxp/interface/zigbeeinterfacerequest.cpp \ - nxp/interface/zigbeeinterfacereply.cpp \ - nxp/zigbeenetworknxp.cpp \ - nxp/zigbeebridgecontrollernxp.cpp \ - nxp/zigbeenodeendpointnxp.cpp \ - nxp/zigbeenodenxp.cpp \ +# nxp/interface/zigbeeinterface.cpp \ +# nxp/interface/zigbeeinterfacemessage.cpp \ +# nxp/interface/zigbeeinterfacerequest.cpp \ +# nxp/interface/zigbeeinterfacereply.cpp \ +# nxp/zigbeenetworknxp.cpp \ +# nxp/zigbeebridgecontrollernxp.cpp \ +# nxp/zigbeenodeendpointnxp.cpp \ +# nxp/zigbeenodenxp.cpp \ + zcl/zigbeeclusterbasic.cpp \ + zdo/zigbeedeviceobject.cpp \ + zdo/zigbeedeviceobjectreply.cpp \ + zdo/zigbeedeviceprofilehandler.cpp \ + zdo/zigbeedeviceprofile.cpp \ zigbeeadpu.cpp \ zigbeebridgecontroller.cpp \ zigbeechannelmask.cpp \ zigbeecluster.cpp \ zigbeeclusterattribute.cpp \ zigbeeclusterlibrary.cpp \ - zigbeedeviceprofile.cpp \ + zigbeeclusterlibraryreply.cpp \ zigbeemanufacturer.cpp \ zigbeenetwork.cpp \ + zigbeenetworkdatabase.cpp \ zigbeenetworkkey.cpp \ zigbeenetworkmanager.cpp \ zigbee.cpp \ @@ -39,6 +45,7 @@ SOURCES += \ zigbeenode.cpp \ zigbeeaddress.cpp \ + HEADERS += \ deconz/interface/deconz.h \ deconz/interface/zigbeeinterfacedeconz.h \ @@ -47,23 +54,29 @@ HEADERS += \ deconz/zigbeenetworkdeconz.h \ deconz/zigbeenodedeconz.h \ deconz/zigbeenodeendpointdeconz.h \ - nxp/interface/zigbeeinterface.h \ - nxp/interface/zigbeeinterfacemessage.h \ - nxp/interface/zigbeeinterfacerequest.h \ - nxp/interface/zigbeeinterfacereply.h \ - nxp/zigbeenetworknxp.h \ - nxp/zigbeebridgecontrollernxp.h \ - nxp/zigbeenodeendpointnxp.h \ - nxp/zigbeenodenxp.h \ +# nxp/interface/zigbeeinterface.h \ +# nxp/interface/zigbeeinterfacemessage.h \ +# nxp/interface/zigbeeinterfacerequest.h \ +# nxp/interface/zigbeeinterfacereply.h \ +# nxp/zigbeenetworknxp.h \ +# nxp/zigbeebridgecontrollernxp.h \ +# nxp/zigbeenodeendpointnxp.h \ +# nxp/zigbeenodenxp.h \ + zcl/zigbeeclusterbasic.h \ + zdo/zigbeedeviceobject.h \ + zdo/zigbeedeviceobjectreply.h \ + zdo/zigbeedeviceprofilehandler.h \ + zdo/zigbeedeviceprofile.h \ zigbeeadpu.h \ zigbeebridgecontroller.h \ zigbeechannelmask.h \ zigbeecluster.h \ zigbeeclusterattribute.h \ zigbeeclusterlibrary.h \ - zigbeedeviceprofile.h \ + zigbeeclusterlibraryreply.h \ zigbeemanufacturer.h \ zigbeenetwork.h \ + zigbeenetworkdatabase.h \ zigbeenetworkkey.h \ zigbeenetworkmanager.h \ zigbee.h \ @@ -76,6 +89,7 @@ HEADERS += \ zigbeenode.h \ zigbeeaddress.h \ + # install header file with relative subdirectory for (header, HEADERS) { path = $$[QT_INSTALL_PREFIX]/include/nymea-zigbee/$${dirname(header)} diff --git a/libnymea-zigbee/loggingcategory.cpp b/libnymea-zigbee/loggingcategory.cpp index 188adcb..98d6842 100644 --- a/libnymea-zigbee/loggingcategory.cpp +++ b/libnymea-zigbee/loggingcategory.cpp @@ -32,4 +32,5 @@ Q_LOGGING_CATEGORY(dcZigbeeNode, "ZigbeeNode") Q_LOGGING_CATEGORY(dcZigbeeCluster, "ZigbeeCluster") Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface") Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController") +Q_LOGGING_CATEGORY(dcZigbeeNetworkDatabase, "ZigbeeNetworkDatabase") Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic") diff --git a/libnymea-zigbee/loggingcategory.h b/libnymea-zigbee/loggingcategory.h index 0245617..5cae2fe 100644 --- a/libnymea-zigbee/loggingcategory.h +++ b/libnymea-zigbee/loggingcategory.h @@ -36,6 +36,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNode) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeCluster) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController) +Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetworkDatabase) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic) #endif // LOGGINGCATEGORY_H diff --git a/libnymea-zigbee/zcl/zigbeeclusterbasic.cpp b/libnymea-zigbee/zcl/zigbeeclusterbasic.cpp new file mode 100644 index 0000000..ff5cf1f --- /dev/null +++ b/libnymea-zigbee/zcl/zigbeeclusterbasic.cpp @@ -0,0 +1,7 @@ +#include "zigbeeclusterbasic.h" + +ZigbeeClusterBasic::ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent) : + ZigbeeCluster(network, node, endpoint, Zigbee::ClusterIdBasic, direction, parent) +{ + +} diff --git a/libnymea-zigbee/zcl/zigbeeclusterbasic.h b/libnymea-zigbee/zcl/zigbeeclusterbasic.h new file mode 100644 index 0000000..1ed3849 --- /dev/null +++ b/libnymea-zigbee/zcl/zigbeeclusterbasic.h @@ -0,0 +1,51 @@ +#ifndef ZIGBEECLUSTERBASIC_H +#define ZIGBEECLUSTERBASIC_H + +#include + +#include "zigbeecluster.h" + +class ZigbeeClusterBasic : public ZigbeeCluster +{ + Q_OBJECT +public: + + enum Attribute { + AttributeZclVersion = 0x0000, // Mandatory + AttributeAppVersion = 0x0001, + AttributeStackVersion = 0x0002, + AttributeHardwareVersion = 0x0003, + AttributeManufacturerName = 0x0004, + AttributeModelIdentifier = 0x0005, + AttributeDateCode = 0x0006, // ISO 8601 YYYYMMDD + AttributePowerSource = 0x0007, // Mandatory + AttributeLocationDescription = 0x0010, + AttributePhysicalEnvironment = 0x0011, + AttributeDeviceEnabled = 0x0012, // 0: disabled, 1: enabled + AttributeAlarmMask = 0x0013, + AttributeDisableLocalConfig = 0x0014, + AttributeSwBuildId = 0x4000 + }; + Q_ENUM(Attribute) + + // From attribute 0x0007 power source + enum AttributePowerSourceValue { + AttributePowerSourceValueUnknown = 0x00, + AttributePowerSourceValueMainsSinglePhase = 0x01, + AttributePowerSourceValueMainsThreePhase = 0x02, + AttributePowerSourceValueBattery = 0x03, + AttributePowerSourceValueDcSource = 0x04, + AttributePowerSourceValueEmergencyMainsConstantlyPowered = 0x05, + AttributePowerSourceValueEmergencyMainsTransferSwitch = 0x06 + }; + Q_ENUM(AttributePowerSourceValue) + + + explicit ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr); + + +signals: + +}; + +#endif // ZIGBEECLUSTERBASIC_H diff --git a/libnymea-zigbee/zdo/zigbeedeviceobject.cpp b/libnymea-zigbee/zdo/zigbeedeviceobject.cpp new file mode 100644 index 0000000..77dafb6 --- /dev/null +++ b/libnymea-zigbee/zdo/zigbeedeviceobject.cpp @@ -0,0 +1,9 @@ +#include "zigbeedeviceobject.h" +#include "zigbeenetwork.h" + +ZigbeeDeviceObject::ZigbeeDeviceObject(ZigbeeNetwork *network, QObject *parent) : + QObject(parent), + m_network(network) +{ + +} diff --git a/libnymea-zigbee/zdo/zigbeedeviceobject.h b/libnymea-zigbee/zdo/zigbeedeviceobject.h new file mode 100644 index 0000000..0fcbcc3 --- /dev/null +++ b/libnymea-zigbee/zdo/zigbeedeviceobject.h @@ -0,0 +1,21 @@ +#ifndef ZIGBEEDEVICEOBJECT_H +#define ZIGBEEDEVICEOBJECT_H + +#include + +class ZigbeeNetwork; + +class ZigbeeDeviceObject : public QObject +{ + Q_OBJECT +public: + explicit ZigbeeDeviceObject(ZigbeeNetwork *network, QObject *parent = nullptr); + +private: + ZigbeeNetwork *m_network = nullptr; + +signals: + +}; + +#endif // ZIGBEEDEVICEOBJECT_H diff --git a/libnymea-zigbee/zdo/zigbeedeviceobjectreply.cpp b/libnymea-zigbee/zdo/zigbeedeviceobjectreply.cpp new file mode 100644 index 0000000..f870ca6 --- /dev/null +++ b/libnymea-zigbee/zdo/zigbeedeviceobjectreply.cpp @@ -0,0 +1,6 @@ +#include "zigbeedeviceobjectreply.h" + +ZigbeeDeviceObjectReply::ZigbeeDeviceObjectReply(QObject *parent) : QObject(parent) +{ + +} diff --git a/libnymea-zigbee/zdo/zigbeedeviceobjectreply.h b/libnymea-zigbee/zdo/zigbeedeviceobjectreply.h new file mode 100644 index 0000000..9faeaf1 --- /dev/null +++ b/libnymea-zigbee/zdo/zigbeedeviceobjectreply.h @@ -0,0 +1,16 @@ +#ifndef ZIGBEEDEVICEOBJECTREPLY_H +#define ZIGBEEDEVICEOBJECTREPLY_H + +#include + +class ZigbeeDeviceObjectReply : public QObject +{ + Q_OBJECT +public: + explicit ZigbeeDeviceObjectReply(QObject *parent = nullptr); + +signals: + +}; + +#endif // ZIGBEEDEVICEOBJECTREPLY_H diff --git a/libnymea-zigbee/zigbeedeviceprofile.cpp b/libnymea-zigbee/zdo/zigbeedeviceprofile.cpp similarity index 100% rename from libnymea-zigbee/zigbeedeviceprofile.cpp rename to libnymea-zigbee/zdo/zigbeedeviceprofile.cpp diff --git a/libnymea-zigbee/zigbeedeviceprofile.h b/libnymea-zigbee/zdo/zigbeedeviceprofile.h similarity index 97% rename from libnymea-zigbee/zigbeedeviceprofile.h rename to libnymea-zigbee/zdo/zigbeedeviceprofile.h index c2c4cf7..feb2812 100644 --- a/libnymea-zigbee/zigbeedeviceprofile.h +++ b/libnymea-zigbee/zdo/zigbeedeviceprofile.h @@ -45,6 +45,13 @@ class ZigbeeDeviceProfile Q_GADGET public: + enum Status { + StatusSuccess = 0x00, + StatusInvalidRequestType = 0x01, + StatusDeviceNotFound = 0x02 + }; + Q_ENUM(Status) + enum ZdoCommand { /* Requests */ /*Device and service discovery */ diff --git a/libnymea-zigbee/zdo/zigbeedeviceprofilehandler.cpp b/libnymea-zigbee/zdo/zigbeedeviceprofilehandler.cpp new file mode 100644 index 0000000..bc8f4ee --- /dev/null +++ b/libnymea-zigbee/zdo/zigbeedeviceprofilehandler.cpp @@ -0,0 +1,6 @@ +#include "zigbeedeviceprofilehandler.h" + +ZigbeeDeviceProfileHandler::ZigbeeDeviceProfileHandler(QObject *parent) : QObject(parent) +{ + +} diff --git a/libnymea-zigbee/zdo/zigbeedeviceprofilehandler.h b/libnymea-zigbee/zdo/zigbeedeviceprofilehandler.h new file mode 100644 index 0000000..1aa324c --- /dev/null +++ b/libnymea-zigbee/zdo/zigbeedeviceprofilehandler.h @@ -0,0 +1,16 @@ +#ifndef ZIGBEEDEVICEPROFILEHANDLER_H +#define ZIGBEEDEVICEPROFILEHANDLER_H + +#include + +class ZigbeeDeviceProfileHandler : public QObject +{ + Q_OBJECT +public: + explicit ZigbeeDeviceProfileHandler(QObject *parent = nullptr); + +signals: + +}; + +#endif // ZIGBEEDEVICEPROFILEHANDLER_H diff --git a/libnymea-zigbee/zigbeecluster.cpp b/libnymea-zigbee/zigbeecluster.cpp index 54db161..586eaac 100644 --- a/libnymea-zigbee/zigbeecluster.cpp +++ b/libnymea-zigbee/zigbeecluster.cpp @@ -26,11 +26,20 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "zigbeeutils.h" +#include "zigbeenetwork.h" #include "zigbeecluster.h" #include "loggingcategory.h" +#include "zigbeenetworkreply.h" +#include "zigbeeclusterlibrary.h" +#include "zigbeenetworkrequest.h" -ZigbeeCluster::ZigbeeCluster(Zigbee::ClusterId clusterId, Direction direction, QObject *parent) : +#include + +ZigbeeCluster::ZigbeeCluster(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Zigbee::ClusterId clusterId, Direction direction, QObject *parent) : QObject(parent), + m_network(network), + m_node(node), + m_endpoint(endpoint), m_clusterId(clusterId), m_direction(direction) { @@ -83,6 +92,50 @@ void ZigbeeCluster::setAttribute(const ZigbeeClusterAttribute &attribute) } } +ZigbeeNetworkReply *ZigbeeCluster::readAttributes(QList attributes) +{ + // Build the request + ZigbeeNetworkRequest request; + request.setRequestId(m_network->generateSequenceNumber()); + request.setDestinationAddressMode(Zigbee::DestinationAddressModeShortAddress); + request.setDestinationShortAddress(static_cast(m_node->shortAddress())); + request.setProfileId(m_endpoint->profile()); + request.setClusterId(m_clusterId); + request.setSourceEndpoint(m_endpoint->endpointId()); + request.setRadius(10); + + // Build ZCL frame + ZigbeeClusterLibrary::FrameControl frameControl; + frameControl.frameType = ZigbeeClusterLibrary::FrameTypeGlobal; // Note: for general commands always use global + frameControl.disableDefaultResponse = true; + + // ZCL header + ZigbeeClusterLibrary::Header header; + header.frameControl = frameControl; + header.command = ZigbeeClusterLibrary::CommandReadAttributes; + header.transactionSequenceNumber = m_network->generateTranactionSequenceNumber(); + + // ZCL payload + QByteArray payload; + QDataStream stream(&payload, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + foreach (quint16 attribute, attributes) { + stream << attribute; + } + + // Put them together + ZigbeeClusterLibrary::Frame frame; + frame.clusterId = m_clusterId; + frame.header = header; + frame.payload = payload; + + request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission)); + request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame)); + + qCDebug(dcZigbeeCluster()) << "Send read attributes request" << m_node << m_endpoint << this << attributes; + return m_network->sendRequest(request); +} + QDebug operator<<(QDebug debug, ZigbeeCluster *cluster) { debug.nospace().noquote() << "ZigbeeCluster(" diff --git a/libnymea-zigbee/zigbeecluster.h b/libnymea-zigbee/zigbeecluster.h index 518e484..d18c308 100644 --- a/libnymea-zigbee/zigbeecluster.h +++ b/libnymea-zigbee/zigbeecluster.h @@ -31,6 +31,7 @@ #include #include "zigbee.h" +#include "zigbeeclusterlibrary.h" #include "zigbeeclusterattribute.h" struct ZigbeeClusterReportConfigurationRecord { @@ -53,6 +54,12 @@ typedef struct ZigbeeClusterAttributeReport { QByteArray data; } ZigbeeClusterAttributeReport; + +class ZigbeeNode; +class ZigbeeNetwork; +class ZigbeeNodeEndpoint; +class ZigbeeNetworkReply; + class ZigbeeCluster : public QObject { Q_OBJECT @@ -189,7 +196,7 @@ public: Q_ENUM(ColorControlClusterColorMode) - explicit ZigbeeCluster(Zigbee::ClusterId clusterId, Direction direction, QObject *parent = nullptr); + explicit ZigbeeCluster(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Zigbee::ClusterId clusterId, Direction direction, QObject *parent = nullptr); Direction direction() const; @@ -204,13 +211,18 @@ public: // FIXME: this should not be public void setAttribute(const ZigbeeClusterAttribute &attribute); -private: + // ZCL global commands + ZigbeeNetworkReply *readAttributes(QList attributes); + +protected: + ZigbeeNetwork *m_network = nullptr; + ZigbeeNode *m_node = nullptr; + ZigbeeNodeEndpoint *m_endpoint= nullptr; + Zigbee::ClusterId m_clusterId = Zigbee::ClusterIdUnknown; Direction m_direction = Input; QHash m_attributes; -protected: - signals: void attributeChanged(const ZigbeeClusterAttribute &attribute); diff --git a/libnymea-zigbee/zigbeeclusterlibrary.cpp b/libnymea-zigbee/zigbeeclusterlibrary.cpp index e0fb7b2..9ae2b5a 100644 --- a/libnymea-zigbee/zigbeeclusterlibrary.cpp +++ b/libnymea-zigbee/zigbeeclusterlibrary.cpp @@ -93,7 +93,7 @@ QByteArray ZigbeeClusterLibrary::buildHeader(const ZigbeeClusterLibrary::Header return headerData; } -ZigbeeClusterLibrary::Frame ZigbeeClusterLibrary::parseFrameData(const QByteArray &frameData) +ZigbeeClusterLibrary::Frame ZigbeeClusterLibrary::parseFrameData(Zigbee::ClusterId clusterId, const QByteArray &frameData) { QDataStream stream(frameData); stream.setByteOrder(QDataStream::LittleEndian); @@ -116,7 +116,6 @@ ZigbeeClusterLibrary::Frame ZigbeeClusterLibrary::parseFrameData(const QByteArra stream >> header.transactionSequenceNumber; offset += 1; - stream >> commandByte; offset += 1; @@ -124,8 +123,9 @@ ZigbeeClusterLibrary::Frame ZigbeeClusterLibrary::parseFrameData(const QByteArra offset += 1; Frame frame; + frame.clusterId = clusterId; frame.header = header; - frame.payload = frameData.right(frameData.length() - offset); + frame.payload = frameData.right(frameData.length() - offset - 1); return frame; } @@ -169,7 +169,7 @@ QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Header &header) QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Frame &frame) { - debug.nospace() << "Zigbee Cluster Library Frame("; + debug.nospace() << "Zigbee Cluster Library Frame(" << frame.clusterId << ", "; debug.nospace() << frame.header; debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(frame.payload) << ")"; return debug.space(); diff --git a/libnymea-zigbee/zigbeeclusterlibrary.h b/libnymea-zigbee/zigbeeclusterlibrary.h index 792426b..37a9707 100644 --- a/libnymea-zigbee/zigbeeclusterlibrary.h +++ b/libnymea-zigbee/zigbeeclusterlibrary.h @@ -31,10 +31,13 @@ #include #include +#include "zigbee.h" + class ZigbeeClusterLibrary { Q_GADGET public: + /* General ZCL commans */ enum Command { CommandReadAttributes = 0x00, CommandReadAttributesResponse = 0x01, @@ -90,6 +93,7 @@ public: } ZclHeader; typedef struct Frame { + Zigbee::ClusterId clusterId; Header header; QByteArray payload; } Frame; @@ -100,7 +104,7 @@ public: static QByteArray buildHeader(const Header &header); - static Frame parseFrameData(const QByteArray &frameData); + static Frame parseFrameData(Zigbee::ClusterId clusterId, const QByteArray &frameData); static QByteArray buildFrame(const Frame &frame); }; diff --git a/libnymea-zigbee/zigbeeclusterlibraryreply.cpp b/libnymea-zigbee/zigbeeclusterlibraryreply.cpp new file mode 100644 index 0000000..e2fbdf6 --- /dev/null +++ b/libnymea-zigbee/zigbeeclusterlibraryreply.cpp @@ -0,0 +1,24 @@ +#include "zigbeeclusterlibraryreply.h" + +ZigbeeNetworkRequest ZigbeeClusterLibraryReply::request() const +{ + return m_request; +} + +ZigbeeClusterLibrary::Frame ZigbeeClusterLibraryReply::requestFrame() const +{ + return m_requestFrame; +} + +quint8 ZigbeeClusterLibraryReply::transactionSequenceNumber() const +{ + return m_requestFrame.header.transactionSequenceNumber; +} + +ZigbeeClusterLibraryReply::ZigbeeClusterLibraryReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame requestFrame, QObject *parent) : + QObject(parent), + m_request(request), + m_requestFrame(requestFrame) +{ + +} diff --git a/libnymea-zigbee/zigbeeclusterlibraryreply.h b/libnymea-zigbee/zigbeeclusterlibraryreply.h new file mode 100644 index 0000000..cbbac7c --- /dev/null +++ b/libnymea-zigbee/zigbeeclusterlibraryreply.h @@ -0,0 +1,35 @@ +#ifndef ZIGBEECLUSTERLIBRARYREPLY_H +#define ZIGBEECLUSTERLIBRARYREPLY_H + +#include + +#include "zigbeenetworkrequest.h" +#include "zigbeeclusterlibrary.h" + +class ZigbeeClusterLibraryReply : public QObject +{ + Q_OBJECT + + friend class ZigbeeCluster; + +public: + ZigbeeNetworkRequest request() const; + ZigbeeClusterLibrary::Frame requestFrame() const; + + quint8 transactionSequenceNumber() const; + +private: + explicit ZigbeeClusterLibraryReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame requestFrame, QObject *parent = nullptr); + + ZigbeeNetworkRequest m_request; + ZigbeeClusterLibrary::Frame m_requestFrame; + ZigbeeClusterLibrary::Command m_expectedResponse; + + ZigbeeClusterLibrary::Frame m_responseFrame; + +signals: + void finished(); + +}; + +#endif // ZIGBEECLUSTERLIBRARYREPLY_H diff --git a/libnymea-zigbee/zigbeenetwork.cpp b/libnymea-zigbee/zigbeenetwork.cpp index 7aad462..e9aa06e 100644 --- a/libnymea-zigbee/zigbeenetwork.cpp +++ b/libnymea-zigbee/zigbeenetwork.cpp @@ -29,9 +29,16 @@ #include "zigbeenetwork.h" #include "loggingcategory.h" +#include + ZigbeeNetwork::ZigbeeNetwork(QObject *parent) : QObject(parent) { + m_db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), "zigbee"); + m_db.setDatabaseName(""); + qCDebug(dcZigbeeNetwork()) << "Opening zigbee network database" << m_db.databaseName(); + + } @@ -167,6 +174,16 @@ void ZigbeeNetwork::setPermitJoining(bool permitJoining) setPermitJoiningInternal(permitJoining); } +quint8 ZigbeeNetwork::generateSequenceNumber() +{ + return m_sequenceNumber++; +} + +quint8 ZigbeeNetwork::generateTranactionSequenceNumber() +{ + return m_transactionSequenceNumber++; +} + QList ZigbeeNetwork::nodes() const { return m_nodes; @@ -329,7 +346,7 @@ void ZigbeeNetwork::loadNetwork() for (int n = 0; n < inputClustersCount; n ++) { settings.setArrayIndex(n); Zigbee::ClusterId clusterId = static_cast(settings.value("clusterId", 0).toUInt()); - ZigbeeCluster *cluster = new ZigbeeCluster(clusterId, ZigbeeCluster::Input, endpoint); + ZigbeeCluster *cluster = new ZigbeeCluster(this, node, endpoint, clusterId, ZigbeeCluster::Input, endpoint); //qCDebug(dcZigbeeNetwork()) << "Created" << cluster; endpoint->m_inputClusters.insert(clusterId, cluster); } @@ -339,7 +356,7 @@ void ZigbeeNetwork::loadNetwork() for (int n = 0; n < outputClustersCount; n ++) { settings.setArrayIndex(n); Zigbee::ClusterId clusterId = static_cast(settings.value("clusterId", 0).toUInt()); - ZigbeeCluster *cluster = new ZigbeeCluster(clusterId, ZigbeeCluster::Output, endpoint); + ZigbeeCluster *cluster = new ZigbeeCluster(this, node, endpoint, clusterId, ZigbeeCluster::Output, endpoint); //qCDebug(dcZigbeeNetwork()) << "Created" << cluster; endpoint->m_outputClusters.insert(clusterId, cluster); } diff --git a/libnymea-zigbee/zigbeenetwork.h b/libnymea-zigbee/zigbeenetwork.h index 0da1bdd..160207c 100644 --- a/libnymea-zigbee/zigbeenetwork.h +++ b/libnymea-zigbee/zigbeenetwork.h @@ -31,6 +31,8 @@ #include #include +#include + #include "zigbeenode.h" #include "zigbeechannelmask.h" #include "zigbeebridgecontroller.h" @@ -94,6 +96,8 @@ public: bool permitJoining() const; void setPermitJoining(bool permitJoining); + quint8 generateSequenceNumber(); + quint8 generateTranactionSequenceNumber(); // Network nodes QList nodes() const; @@ -106,6 +110,8 @@ public: bool hasNode(quint16 shortAddress) const; bool hasNode(const ZigbeeAddress &address) const; + virtual ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) = 0; + private: State m_state = StateUninitialized; @@ -113,6 +119,9 @@ private: QString m_serialPortName = "/dev/ttyUSB0"; qint32 m_serialBaudrate = 115200; + quint8 m_sequenceNumber = 0; + quint8 m_transactionSequenceNumber = 0; + // Network configurations quint16 m_panId = 0; quint64 m_extendedPanId = 0; @@ -120,10 +129,16 @@ private: ZigbeeChannelMask m_channelMask = ZigbeeChannelMask(ZigbeeChannelMask::ChannelConfigurationAllChannels); ZigbeeNode::NodeType m_nodeType = ZigbeeNode::NodeTypeCoordinator; + // Network storage QString m_settingsFileName = "/etc/nymea/nymea-zigbee.conf"; QList m_nodes; QList m_uninitializedNodes; + QSqlDatabase m_db; + +private: + bool initDB(); + void addNodeInternally(ZigbeeNode *node); void removeNodeInternally(ZigbeeNode *node); @@ -152,8 +167,6 @@ protected: bool networkConfigurationAvailable() const; - virtual ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) = 0; - // Network reply methods ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest()); void setReplyResponseData(ZigbeeNetworkReply *reply, const QByteArray &responseData); diff --git a/libnymea-zigbee/zigbeenetworkdatabase.cpp b/libnymea-zigbee/zigbeenetworkdatabase.cpp new file mode 100644 index 0000000..e60a851 --- /dev/null +++ b/libnymea-zigbee/zigbeenetworkdatabase.cpp @@ -0,0 +1,42 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea-zigbee. +* This project including source code and documentation is protected by copyright law, and +* remains the property of nymea GmbH. All rights, including reproduction, publication, +* editing and translation, are reserved. The use of this project is subject to the terms of a +* license agreement to be concluded with nymea GmbH in accordance with the terms +* of use of nymea GmbH, available under https://nymea.io/license +* +* GNU Lesser General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the terms of the GNU +* Lesser General Public License as published by the Free Software Foundation; version 3. +* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License along with this project. +* If not, see . +* +* 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 "zigbeenetworkdatabase.h" +#include "loggingcategory.h" + +ZigbeeNetworkDatabase::ZigbeeNetworkDatabase(const QString &databaseName, QObject *parent) : QObject(parent) +{ + m_db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), "zigbee"); + m_db.setDatabaseName(databaseName); + qCDebug(dcZigbeeNetworkDatabase()) << "Opening zigbee network database" << m_db.databaseName(); + + if (!m_db.isValid()) { + qCWarning(dcZigbeeNetworkDatabase()) << "The zigbee network database is not valid" << m_db.databaseName(); + // FIXME: create a new one + return; + } +} diff --git a/libnymea-zigbee/zigbeenetworkdatabase.h b/libnymea-zigbee/zigbeenetworkdatabase.h new file mode 100644 index 0000000..0abbfee --- /dev/null +++ b/libnymea-zigbee/zigbeenetworkdatabase.h @@ -0,0 +1,49 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea-zigbee. +* This project including source code and documentation is protected by copyright law, and +* remains the property of nymea GmbH. All rights, including reproduction, publication, +* editing and translation, are reserved. The use of this project is subject to the terms of a +* license agreement to be concluded with nymea GmbH in accordance with the terms +* of use of nymea GmbH, available under https://nymea.io/license +* +* GNU Lesser General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the terms of the GNU +* Lesser General Public License as published by the Free Software Foundation; version 3. +* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License along with this project. +* If not, see . +* +* 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 ZIGBEENETWORKDATABASE_H +#define ZIGBEENETWORKDATABASE_H + +#include +#include + + +class ZigbeeNetworkDatabase : public QObject +{ + Q_OBJECT +public: + explicit ZigbeeNetworkDatabase(const QString &databaseName, QObject *parent = nullptr); + +private: + QSqlDatabase m_db; + + +signals: + +}; + +#endif // ZIGBEENETWORKDATABASE_H diff --git a/libnymea-zigbee/zigbeenetworkrequest.cpp b/libnymea-zigbee/zigbeenetworkrequest.cpp index 9ddd9dd..ed7f730 100644 --- a/libnymea-zigbee/zigbeenetworkrequest.cpp +++ b/libnymea-zigbee/zigbeenetworkrequest.cpp @@ -26,7 +26,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "zigbeenetworkrequest.h" -#include "zigbeedeviceprofile.h" +#include "zdo/zigbeedeviceprofile.h" #include "zigbeeutils.h" ZigbeeNetworkRequest::ZigbeeNetworkRequest() diff --git a/libnymea-zigbee/zigbeenode.cpp b/libnymea-zigbee/zigbeenode.cpp index 3e99bb0..00ded90 100644 --- a/libnymea-zigbee/zigbeenode.cpp +++ b/libnymea-zigbee/zigbeenode.cpp @@ -27,14 +27,16 @@ #include "zigbeenode.h" #include "zigbeeutils.h" +#include "zigbeenetwork.h" #include "loggingcategory.h" #include -ZigbeeNode::ZigbeeNode(QObject *parent) : - QObject(parent) +ZigbeeNode::ZigbeeNode(ZigbeeNetwork *network, QObject *parent) : + QObject(parent), + m_network(network) { - + m_deviceObject = new ZigbeeDeviceObject(m_network, this); } ZigbeeNode::State ZigbeeNode::state() const @@ -47,6 +49,11 @@ bool ZigbeeNode::connected() const return m_connected; } +ZigbeeDeviceObject *ZigbeeNode::deviceObject() const +{ + return m_deviceObject; +} + quint16 ZigbeeNode::shortAddress() const { return m_shortAddress; @@ -248,95 +255,90 @@ void ZigbeeNode::setExtendedAddress(const ZigbeeAddress &extendedAddress) m_extendedAddress = extendedAddress; } -QByteArray ZigbeeNode::nodeDescriptorRawData() const -{ - return m_nodeDescriptorRawData; -} +//void ZigbeeNode::setNodeDescriptorRawData(const QByteArray nodeDescriptorRawData) +//{ +// m_nodeDescriptorRawData = nodeDescriptorRawData; -void ZigbeeNode::setNodeDescriptorRawData(const QByteArray nodeDescriptorRawData) -{ - m_nodeDescriptorRawData = nodeDescriptorRawData; +// // Parse the raw data +// quint8 sequenceNumber = 0; +// quint8 status = 0; +// quint16 shortAddress = 0; +// quint16 manufacturerCode = 0; +// quint16 maximalRxSize = 0; +// quint16 maximalTxSize = 0; +// quint16 serverMask = 0; +// quint8 descriptorFlag = 0; +// quint8 macFlags = 0; +// quint8 maxBufferSize = 0; +// quint16 bitField = 0; - // Parse the raw data - quint8 sequenceNumber = 0; - quint8 status = 0; - quint16 shortAddress = 0; - quint16 manufacturerCode = 0; - quint16 maximalRxSize = 0; - quint16 maximalTxSize = 0; - quint16 serverMask = 0; - quint8 descriptorFlag = 0; - quint8 macFlags = 0; - quint8 maxBufferSize = 0; - quint16 bitField = 0; +// QDataStream stream(&m_nodeDescriptorRawData, QIODevice::ReadOnly); +// stream >> sequenceNumber; +// stream >> status; +// stream >> shortAddress; +// stream >> manufacturerCode; +// stream >> maximalRxSize; +// stream >> maximalTxSize; +// stream >> serverMask; +// stream >> descriptorFlag; +// stream >> macFlags; +// stream >> maxBufferSize; +// stream >> bitField; - QDataStream stream(&m_nodeDescriptorRawData, QIODevice::ReadOnly); - stream >> sequenceNumber; - stream >> status; - stream >> shortAddress; - stream >> manufacturerCode; - stream >> maximalRxSize; - stream >> maximalTxSize; - stream >> serverMask; - stream >> descriptorFlag; - stream >> macFlags; - stream >> maxBufferSize; - stream >> bitField; +// // Set node data +// m_manufacturerCode = manufacturerCode; +// m_maximumRxSize = maximalRxSize; +// m_maximumTxSize = maximalTxSize; +// m_maximumBufferSize = maxBufferSize; - // Set node data - m_manufacturerCode = manufacturerCode; - m_maximumRxSize = maximalRxSize; - m_maximumTxSize = maximalTxSize; - m_maximumBufferSize = maxBufferSize; +// setServerMask(serverMask); +// setMacCapabilitiesFlag(macFlags); +// setDescriptorFlag(descriptorFlag); - 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; +// } - // 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; - m_complexDescriptorAvailable = (bitField >> 3) & 0x0001; - m_userDescriptorAvailable = (bitField >> 4) & 0x0001; - - qCDebug(dcZigbeeNode()) << "Node descriptor:"; - qCDebug(dcZigbeeNode()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber); - qCDebug(dcZigbeeNode()) << " Status:" << ZigbeeUtils::convertByteToHexString(status); - qCDebug(dcZigbeeNode()) << " Node type:" << nodeType(); - qCDebug(dcZigbeeNode()) << " Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); - qCDebug(dcZigbeeNode()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode); - qCDebug(dcZigbeeNode()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(maximumRxSize()); - qCDebug(dcZigbeeNode()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(maximumTxSize()); - qCDebug(dcZigbeeNode()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(maximumBufferSize()); - qCDebug(dcZigbeeNode()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask); - qCDebug(dcZigbeeNode()) << " Primary Trust center:" << isPrimaryTrustCenter(); - qCDebug(dcZigbeeNode()) << " Backup Trust center:" << isBackupTrustCenter(); - qCDebug(dcZigbeeNode()) << " Primary Binding cache:" << isPrimaryBindingCache(); - qCDebug(dcZigbeeNode()) << " Backup Binding cache:" << isBackupBindingCache(); - qCDebug(dcZigbeeNode()) << " Primary Discovery cache:" << isPrimaryDiscoveryCache(); - qCDebug(dcZigbeeNode()) << " Backup Discovery cache:" << isBackupDiscoveryCache(); - qCDebug(dcZigbeeNode()) << " Network Manager:" << isNetworkManager(); - qCDebug(dcZigbeeNode()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorFlag); - qCDebug(dcZigbeeNode()) << " Extended active endpoint list available:" << extendedActiveEndpointListAvailable(); - qCDebug(dcZigbeeNode()) << " Extended simple descriptor list available:" << extendedSimpleDescriptorListAvailable(); - qCDebug(dcZigbeeNode()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macFlags); - qCDebug(dcZigbeeNode()) << " Alternate PAN coordinator:" << alternatePanCoordinator(); - qCDebug(dcZigbeeNode()) << " Device type:" << deviceType(); - qCDebug(dcZigbeeNode()) << " Power source flag main power:" << powerSourceFlagMainPower(); - qCDebug(dcZigbeeNode()) << " Receiver on when idle:" << receiverOnWhenIdle(); - qCDebug(dcZigbeeNode()) << " Security capability:" << securityCapability(); - qCDebug(dcZigbeeNode()) << " Allocate address:" << allocateAddress(); - qCDebug(dcZigbeeNode()) << " Bit field:" << ZigbeeUtils::convertUint16ToHexString(bitField); - qCDebug(dcZigbeeNode()) << " Complex desciptor available:" << complexDescriptorAvailable(); - qCDebug(dcZigbeeNode()) << " User desciptor available:" << userDescriptorAvailable(); -} +// qCDebug(dcZigbeeNode()) << "Node descriptor:"; +// qCDebug(dcZigbeeNode()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber); +// qCDebug(dcZigbeeNode()) << " Status:" << ZigbeeUtils::convertByteToHexString(status); +// qCDebug(dcZigbeeNode()) << " Node type:" << nodeType(); +// qCDebug(dcZigbeeNode()) << " Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); +// qCDebug(dcZigbeeNode()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode); +// qCDebug(dcZigbeeNode()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(maximumRxSize()); +// qCDebug(dcZigbeeNode()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(maximumTxSize()); +// qCDebug(dcZigbeeNode()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(maximumBufferSize()); +// qCDebug(dcZigbeeNode()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask); +// qCDebug(dcZigbeeNode()) << " Primary Trust center:" << isPrimaryTrustCenter(); +// qCDebug(dcZigbeeNode()) << " Backup Trust center:" << isBackupTrustCenter(); +// qCDebug(dcZigbeeNode()) << " Primary Binding cache:" << isPrimaryBindingCache(); +// qCDebug(dcZigbeeNode()) << " Backup Binding cache:" << isBackupBindingCache(); +// qCDebug(dcZigbeeNode()) << " Primary Discovery cache:" << isPrimaryDiscoveryCache(); +// qCDebug(dcZigbeeNode()) << " Backup Discovery cache:" << isBackupDiscoveryCache(); +// qCDebug(dcZigbeeNode()) << " Network Manager:" << isNetworkManager(); +// qCDebug(dcZigbeeNode()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorFlag); +// qCDebug(dcZigbeeNode()) << " Extended active endpoint list available:" << extendedActiveEndpointListAvailable(); +// qCDebug(dcZigbeeNode()) << " Extended simple descriptor list available:" << extendedSimpleDescriptorListAvailable(); +// qCDebug(dcZigbeeNode()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macFlags); +// qCDebug(dcZigbeeNode()) << " Alternate PAN coordinator:" << alternatePanCoordinator(); +// qCDebug(dcZigbeeNode()) << " Device type:" << deviceType(); +// qCDebug(dcZigbeeNode()) << " Power source flag main power:" << powerSourceFlagMainPower(); +// qCDebug(dcZigbeeNode()) << " Receiver on when idle:" << receiverOnWhenIdle(); +// qCDebug(dcZigbeeNode()) << " Security capability:" << securityCapability(); +// qCDebug(dcZigbeeNode()) << " Allocate address:" << allocateAddress(); +// qCDebug(dcZigbeeNode()) << " Bit field:" << ZigbeeUtils::convertUint16ToHexString(bitField); +// qCDebug(dcZigbeeNode()) << " Complex desciptor available:" << complexDescriptorAvailable(); +// qCDebug(dcZigbeeNode()) << " User desciptor available:" << userDescriptorAvailable(); +//} quint16 ZigbeeNode::serverMask() const { @@ -448,14 +450,14 @@ void ZigbeeNode::setPowerDescriptorFlag(quint16 powerDescriptorFlag) 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; +// 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::startInitialization() diff --git a/libnymea-zigbee/zigbeenode.h b/libnymea-zigbee/zigbeenode.h index 8924af3..400d6af 100644 --- a/libnymea-zigbee/zigbeenode.h +++ b/libnymea-zigbee/zigbeenode.h @@ -33,6 +33,9 @@ #include "zigbee.h" #include "zigbeeaddress.h" #include "zigbeenodeendpoint.h" +#include "zdo/zigbeedeviceobject.h" + +class ZigbeeNetwork; class ZigbeeNode : public QObject { @@ -100,6 +103,8 @@ public: State state() const; bool connected() const; + ZigbeeDeviceObject *deviceObject() const; + quint16 shortAddress() const; ZigbeeAddress extendedAddress() const; @@ -190,8 +195,10 @@ private: virtual void setClusterAttributeReport(const ZigbeeClusterAttributeReport &report) = 0; protected: - ZigbeeNode(QObject *parent = nullptr); + ZigbeeNode(ZigbeeNetwork *network, QObject *parent = nullptr); + ZigbeeNetwork *m_network; + ZigbeeDeviceObject *m_deviceObject = nullptr; QList m_endpoints; // Node descriptor information @@ -214,10 +221,6 @@ protected: void setShortAddress(const quint16 &shortAddress); void setExtendedAddress(const ZigbeeAddress &extendedAddress); - // Note: node descriptor properties (raw data for settings) - QByteArray nodeDescriptorRawData() const; - void setNodeDescriptorRawData(const QByteArray nodeDescriptorRawData); - quint16 serverMask() const; void setServerMask(quint16 serverMask); diff --git a/libnymea-zigbee/zigbeenodeendpoint.h b/libnymea-zigbee/zigbeenodeendpoint.h index 4b1a0b2..065cf54 100644 --- a/libnymea-zigbee/zigbeenodeendpoint.h +++ b/libnymea-zigbee/zigbeenodeendpoint.h @@ -73,36 +73,6 @@ public: ZigbeeCluster *getOutputCluster(Zigbee::ClusterId clusterId) const; bool hasOutputCluster(Zigbee::ClusterId clusterId) const; - // Attribute methods - virtual ZigbeeNetworkReply *readAttribute(ZigbeeCluster *cluster, QList attributes) = 0; - virtual ZigbeeNetworkReply *configureReporting(ZigbeeCluster *cluster, QList reportConfigurations) = 0; - - // Identify - virtual ZigbeeNetworkReply *identify(quint16 seconds); - - // Reset - virtual ZigbeeNetworkReply *factoryReset(); - - // Binding - virtual ZigbeeNetworkReply *bindGroup(Zigbee::ClusterId clusterId, quint16 destinationAddress, quint8 destinationEndpoint); - virtual ZigbeeNetworkReply *bindUnicast(Zigbee::ClusterId clusterId, const ZigbeeAddress &destinationAddress, quint8 destinationEndpoint); - - // Cluster commands - virtual ZigbeeNetworkReply *sendOnOffClusterCommand(ZigbeeCluster::OnOffClusterCommand command); - - // Group commands - virtual ZigbeeNetworkReply *addGroup(quint8 destinationEndpoint, quint16 groupAddress); - - // Level commands - virtual ZigbeeNetworkReply *sendLevelCommand(ZigbeeCluster::LevelClusterCommand command, quint8 level, bool triggersOnOff, quint16 transitionTime); - - // Color commands - virtual ZigbeeNetworkReply *sendMoveToColorTemperature(quint16 colourTemperature, quint16 transitionTime); - virtual ZigbeeNetworkReply *sendMoveToColor(double x, double y, quint16 transitionTime); - virtual ZigbeeNetworkReply *sendMoveToHueSaturation(quint8 hue, quint8 saturation, quint16 transitionTime); - virtual ZigbeeNetworkReply *sendMoveToHue(quint8 hue, quint16 transitionTime); - virtual ZigbeeNetworkReply *sendMoveToSaturation(quint8 saturation, quint16 transitionTime); - private: ZigbeeNode *m_node = nullptr; quint8 m_endpointId = 0; @@ -139,6 +109,7 @@ signals: void manufacturerNameChanged(const QString &manufacturerName); void modelIdentifierChanged(const QString &modelIdentifier); void softwareBuildIdChanged(const QString &softwareBuildId); + }; QDebug operator<<(QDebug debug, ZigbeeNodeEndpoint *endpoint);