// SPDX-License-Identifier: LGPL-3.0-or-later /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 2013 - 2024, nymea GmbH * Copyright (C) 2024 - 2025, chargebyte austria GmbH * * This file is part of libnymea-app. * * libnymea-app is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * libnymea-app 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 libnymea-app. If not, see . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef ZIGBEENODE_H #define ZIGBEENODE_H #include #include #include #include class ZigbeeNodeNeighbor; class ZigbeeNodeRoute; class ZigbeeNodeBinding; class ZigbeeNodeEndpoint; class ZigbeeNode : public QObject { Q_OBJECT Q_PROPERTY(QUuid networkUuid READ networkUuid CONSTANT) Q_PROPERTY(QString ieeeAddress READ ieeeAddress CONSTANT) Q_PROPERTY(quint16 networkAddress READ networkAddress WRITE setNetworkAddress NOTIFY networkAddressChanged) Q_PROPERTY(ZigbeeNodeType type READ type WRITE setType NOTIFY typeChanged) Q_PROPERTY(ZigbeeNodeState state READ state WRITE setState NOTIFY stateChanged) Q_PROPERTY(QString manufacturer READ manufacturer WRITE setManufacturer NOTIFY manufacturerChanged) Q_PROPERTY(QString model READ model WRITE setModel NOTIFY modelChanged) Q_PROPERTY(QString version READ version WRITE setVersion NOTIFY versionChanged) Q_PROPERTY(bool rxOnWhenIdle READ rxOnWhenIdle WRITE setRxOnWhenIdle NOTIFY rxOnWhenIdleChanged) Q_PROPERTY(bool reachable READ reachable WRITE setReachable NOTIFY reachableChanged) Q_PROPERTY(uint lqi READ lqi WRITE setLqi NOTIFY lqiChanged) Q_PROPERTY(QDateTime lastSeen READ lastSeen WRITE setLastSeen NOTIFY lastSeenChanged) Q_PROPERTY(QList neighbors READ neighbors NOTIFY neighborsChanged) Q_PROPERTY(QList routes READ routes NOTIFY routesChanged) Q_PROPERTY(QList bindings READ bindings NOTIFY bindingsChanged) Q_PROPERTY(QList endpoints READ endpoints NOTIFY endpointsChanged) public: enum ZigbeeNodeType { ZigbeeNodeTypeCoordinator, ZigbeeNodeTypeRouter, ZigbeeNodeTypeEndDevice }; Q_ENUM(ZigbeeNodeType) enum ZigbeeNodeState { ZigbeeNodeStateUninitialized, ZigbeeNodeStateInitializing, ZigbeeNodeStateInitialized, ZigbeeNodeStateHandled }; Q_ENUM(ZigbeeNodeState) enum ZigbeeNodeRelationship { ZigbeeNodeRelationshipParent, ZigbeeNodeRelationshipChild, ZigbeeNodeRelationshipSibling, ZigbeeNodeRelationshipNone, ZigbeeNodeRelationshipPreviousChild }; Q_ENUM(ZigbeeNodeRelationship) enum ZigbeeNodeRouteStatus { ZigbeeNodeRouteStatusActive, ZigbeeNodeRouteStatusDiscoveryUnderway, ZigbeeNodeRouteStatusDiscoveryFailed, ZigbeeNodeRouteStatusInactive, ZigbeeNodeRouteStatusValidationUnderway }; Q_ENUM(ZigbeeNodeRouteStatus) enum ZigbeeNodeBindingType { ZigbeeNodeBindingTypeDevice, ZigbeeNodeBindingTypeGroup }; Q_ENUM(ZigbeeNodeBindingType) explicit ZigbeeNode(const QUuid &networkUuid, const QString &ieeeAddress, QObject *parent = nullptr); QUuid networkUuid() const; QString ieeeAddress() const; quint16 networkAddress() const; void setNetworkAddress(quint16 networkAddress); ZigbeeNodeType type() const; void setType(ZigbeeNodeType type); ZigbeeNodeState state() const; void setState(ZigbeeNodeState state); QString manufacturer() const; void setManufacturer(const QString &manufacturer); QString model() const; void setModel(const QString &model); QString version() const; void setVersion(const QString &version); bool rxOnWhenIdle() const; void setRxOnWhenIdle(bool rxOnWhenIdle); bool reachable() const; void setReachable(bool reachable); uint lqi() const; void setLqi(uint lqi); QDateTime lastSeen() const; void setLastSeen(const QDateTime &lastSeen); QList neighbors() const; void addOrUpdateNeighbor(quint16 networkAddress, ZigbeeNodeRelationship relationship, quint8 lqi, quint8 depth, bool permitJoining); void commitNeighbors(QList toBeKept); QList routes() const; void addOrUpdateRoute(quint16 destinationAddress, quint16 nextHopAddress, ZigbeeNodeRouteStatus status, bool memoryConstrained, bool manyToOne); void commitRoutes(QList toBeKept); QList bindings() const; void addBinding(const QString &sourceAddress, quint8 sourceEndpointId, quint16 clusterId, quint16 groupAddress); void addBinding(const QString &sourceAddress, quint8 sourceEndpointId, quint16 clusterId, const QString &destinationAddress, quint8 destinationEndpointId); void commitBindings(); QList endpoints() const; Q_INVOKABLE ZigbeeNodeEndpoint *getEndpoint(quint8 endpointId) const; void addEndpoint(ZigbeeNodeEndpoint *endpoint); static ZigbeeNodeState stringToNodeState(const QString &nodeState); static ZigbeeNodeType stringToNodeType(const QString &nodeType); signals: void networkAddressChanged(quint16 networkAddress); void typeChanged(ZigbeeNodeType type); void stateChanged(ZigbeeNodeState state); void manufacturerChanged(const QString &manufacturer); void modelChanged(const QString &model); void versionChanged(const QString &version); void rxOnWhenIdleChanged(bool rxOnWhenIdle); void reachableChanged(bool reachable); void lqiChanged(uint lqi); void lastSeenChanged(const QDateTime &lastSeen); void neighborsChanged(); void routesChanged(); void bindingsChanged(); void endpointsChanged(); private: QUuid m_networkUuid; QString m_ieeeAddress; quint16 m_networkAddress = 0; ZigbeeNodeType m_type = ZigbeeNodeTypeEndDevice; ZigbeeNodeState m_state = ZigbeeNodeStateUninitialized; QString m_manufacturer; QString m_model; QString m_version; bool m_rxOnWhenIdle = false; bool m_reachable = false; uint m_lqi = 0; QDateTime m_lastSeen; QList m_neighbors; bool m_neighborsDirty = false; QList m_routes; bool m_routesDirty = false; QList m_bindings; bool m_bindingsDirty = false; QList m_endpoints; }; class ZigbeeNodeNeighbor: public QObject { Q_OBJECT Q_PROPERTY(quint16 networkAddress READ networkAddress CONSTANT) Q_PROPERTY(ZigbeeNode::ZigbeeNodeRelationship relationship READ relationship NOTIFY relationshipChanged) Q_PROPERTY(quint8 lqi READ lqi NOTIFY lqiChanged) Q_PROPERTY(quint8 depth READ depth NOTIFY depthChanged) Q_PROPERTY(bool permitJoining READ permitJoining NOTIFY permitJoiningChanged) public: ZigbeeNodeNeighbor(quint16 networkAddress, QObject *parent); quint16 networkAddress() const; ZigbeeNode::ZigbeeNodeRelationship relationship() const; void setRelationship(ZigbeeNode::ZigbeeNodeRelationship relationship); quint8 lqi() const; void setLqi(quint8 lqi); quint8 depth() const; void setDepth(quint8 depth); bool permitJoining() const; void setPermitJoining(bool permitJoining); signals: void relationshipChanged(); void lqiChanged(); void depthChanged(); void permitJoiningChanged(); private: quint16 m_networkAddress; ZigbeeNode::ZigbeeNodeRelationship m_relationship; quint8 m_lqi = 0; quint8 m_depth = 0; bool m_permitJoining = false; }; class ZigbeeNodeRoute: public QObject { Q_OBJECT Q_PROPERTY(quint16 destinationAddress READ destinationAddress CONSTANT) Q_PROPERTY(quint16 nextHopAddress READ nextHopAddress NOTIFY nextHopAddressChanged) Q_PROPERTY(ZigbeeNode::ZigbeeNodeRouteStatus status READ status NOTIFY statusChanged) Q_PROPERTY(bool memoryConstrained READ memoryConstrained NOTIFY memoryConstrainedChanged) Q_PROPERTY(bool manyToOne READ manyToOne NOTIFY manyToOneChanged) public: ZigbeeNodeRoute(quint16 destinationAddress, QObject *parent); quint16 destinationAddress() const; quint16 nextHopAddress() const; void setNextHopAddress(quint16 nextHopAddress); ZigbeeNode::ZigbeeNodeRouteStatus status() const; void setStatus(ZigbeeNode::ZigbeeNodeRouteStatus status); bool memoryConstrained() const; void setMemoryConstrained(bool memoryConstrained); bool manyToOne() const; void setManyToOne(bool manyToOne); signals: void nextHopAddressChanged(); void statusChanged(); void memoryConstrainedChanged(); void manyToOneChanged(); private: quint16 m_destinationAddress; quint16 m_nextHopAddress; ZigbeeNode::ZigbeeNodeRouteStatus m_status = ZigbeeNode::ZigbeeNodeRouteStatusInactive; bool m_memoryConstrained = false; bool m_manyToOne = false; }; class ZigbeeNodeBinding: public QObject { Q_OBJECT Q_PROPERTY(QString sourceAddress READ sourceAddress CONSTANT) Q_PROPERTY(quint8 sourceEndpointId READ sourceEndpointId CONSTANT) Q_PROPERTY(quint16 clusterId READ clusterId CONSTANT) Q_PROPERTY(ZigbeeNode::ZigbeeNodeBindingType type READ type CONSTANT) Q_PROPERTY(quint16 groupAddress READ groupAddress CONSTANT) Q_PROPERTY(QString destinationAddress READ destinationAddress CONSTANT) Q_PROPERTY(quint8 destinationEndpointId READ destinationEndpointId CONSTANT) public: ZigbeeNodeBinding(const QString &sourceAddress, quint8 sourceEndointId, quint16 clusterId, quint16 groupAddress, QObject *parent); ZigbeeNodeBinding(const QString &sourceAddress, quint8 sourceEndointId, quint16 clusterId, const QString &destinationAddress, quint8 destinationEndpoint, QObject *parent); QString sourceAddress() const; quint8 sourceEndpointId() const; quint16 clusterId() const; ZigbeeNode::ZigbeeNodeBindingType type() const; quint16 groupAddress() const; QString destinationAddress() const; quint8 destinationEndpointId() const; private: QString m_sourceAddress; quint8 m_sourceEndpointId = 0; quint16 m_clusterId = 0; ZigbeeNode::ZigbeeNodeBindingType m_type = ZigbeeNode::ZigbeeNodeBindingTypeDevice; quint16 m_groupAddress = 0; QString m_destinationAddress; quint8 m_destinationEndpointId = 0; }; class ZigbeeCluster: public QObject { Q_OBJECT Q_PROPERTY(quint16 clusterId READ clusterId CONSTANT) Q_PROPERTY(ZigbeeClusterDirection direction READ direction CONSTANT) public: enum ZigbeeClusterDirection { ZigbeeClusterDirectionServer, ZigbeeClusterDirectionClient }; Q_ENUM(ZigbeeClusterDirection) enum ZigbeeClusterId { // Basics ZigbeeClusterIdUnknown = 0xffff, ZigbeeClusterIdBasic = 0x0000, ZigbeeClusterIdPowerConfiguration = 0x0001, ZigbeeClusterIdDeviceTemperature = 0x0002, ZigbeeClusterIdIdentify = 0x0003, ZigbeeClusterIdGroups = 0x0004, ZigbeeClusterIdScenes = 0x0005, ZigbeeClusterIdOnOff = 0x0006, ZigbeeClusterIdOnOffCOnfiguration = 0x0007, ZigbeeClusterIdLevelControl = 0x0008, ZigbeeClusterIdAlarms = 0x0009, ZigbeeClusterIdTime = 0x000A, ZigbeeClusterIdRssiLocation = 0x000B, ZigbeeClusterIdAnalogInput = 0x000C, ZigbeeClusterIdAnalogOutput = 0x000D, ZigbeeClusterIdAnalogValue = 0x000E, ZigbeeClusterIdBinaryInput = 0x000F, ZigbeeClusterIdBinaryOutput = 0x0010, ZigbeeClusterIdBinaryValue = 0x0011, ZigbeeClusterIdMultistateInput = 0x0012, ZigbeeClusterIdMultistateOutput = 0x0013, ZigbeeClusterIdMultistateValue = 0x0014, ZigbeeClusterIdCommissoning = 0x0015, // Over the air uppgrade (OTA) ZigbeeClusterIdOtaUpgrade = 0x0019, // Poll controll ZigbeeClusterIdPollControl = 0x0020, // Closures ZigbeeClusterIdShadeConfiguration = 0x0100, ZigbeeClusterIdDoorLock = 0x0101, ZigbeeClusterWindowCovering = 0x0102, // Heating, Ventilation and Air-Conditioning (HVAC) ZigbeeClusterIdPumpConfigurationControl = 0x0200, ZigbeeClusterIdThermostat = 0x0201, ZigbeeClusterIdFanControll = 0x0202, ZigbeeClusterIdDehumiditationControl = 0x0203, ZigbeeClusterIdThermostatUserControl = 0x0204, // Lighting ZigbeeClusterIdColorControl = 0x0300, ZigbeeClusterIdBallastConfiguration = 0x0301, // Sensing ZigbeeClusterIdIlluminanceMeasurement = 0x0400, ZigbeeClusterIdIlluminanceLevelSensing = 0x0401, ZigbeeClusterIdTemperatureMeasurement = 0x0402, ZigbeeClusterIdPressureMeasurement = 0x0403, ZigbeeClusterIdFlowMeasurement = 0x0404, ZigbeeClusterIdRelativeHumidityMeasurement = 0x0405, ZigbeeClusterIdOccupancySensing = 0x0406, // Security and Safty ZigbeeClusterIdIasZone = 0x0500, ZigbeeClusterIdIasAce = 0x0501, ZigbeeClusterIdIasWd = 0x0502, // Smart energy ZigbeeClusterIdPrice = 0x0700, ZigbeeClusterIdDemandResponseAndLoadControl = 0x0701, ZigbeeClusterIdMetering = 0x0702, ZigbeeClusterIdMessaging = 0x0703, ZigbeeClusterIdTunneling = 0x0704, ZigbeeClusterIdKeyEstablishment = 0x0800, // ZLL ZigbeeClusterIdTouchlinkCommissioning = 0x1000, // NXP Appliances ZigbeeClusterIdApplianceControl = 0x001B, ZigbeeClusterIdApplianceIdentification = 0x0B00, ZigbeeClusterIdApplianceEventsAlerts = 0x0B02, ZigbeeClusterIdApplianceStatistics = 0x0B03, // Electrical Measurement ZigbeeClusterIdElectricalMeasurement = 0x0B04, ZigbeeClusterIdDiagnostics = 0x0B05, // Zigbee green power ZigbeeClusterIdGreenPower = 0x0021, // Manufacturer specific ZigbeeClusterIdManufacturerSpecificPhilips = 0xfc00, }; Q_ENUM(ZigbeeClusterId) ZigbeeCluster(quint16 clusterId, ZigbeeClusterDirection direction, QObject *parent = nullptr); quint16 clusterId() const; ZigbeeClusterDirection direction() const; Q_INVOKABLE QString clusterName() const; private: quint16 m_clusterId = 0; ZigbeeClusterDirection m_direction; }; class ZigbeeNodeEndpoint: public QObject { Q_OBJECT Q_PROPERTY(quint8 endpointId READ endpointId CONSTANT) Q_PROPERTY(QList inputClusters READ inputClusters NOTIFY inputClustersChanged) Q_PROPERTY(QList outputClusters READ outputClusters NOTIFY outputClustersChanged) public: ZigbeeNodeEndpoint(quint8 endpointId, const QList &inputClusters = QList(), const QList &outputClusters = QList(), QObject *parent = nullptr); quint8 endpointId() const; QList inputClusters() const; Q_INVOKABLE ZigbeeCluster *getInputCluster(quint16 clusterId) const; void addInputCluster(ZigbeeCluster *cluster); QList outputClusters() const; Q_INVOKABLE ZigbeeCluster *getOutputCluster(quint16 clusterId) const; void addOutputCluster(ZigbeeCluster *cluster); signals: void inputClustersChanged(); void outputClustersChanged(); private: quint8 m_endpointId = 0; QList m_inputClusters; QList m_outputClusters; }; #endif // ZIGBEENODE_H