nymea-zigbee/libnymea-zigbee/zcl/zigbeeclusterlibrary.h

317 lines
11 KiB
C++

// SPDX-License-Identifier: LGPL-3.0-or-later
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* nymea-zigbee
* Zigbee integration module for nymea
*
* Copyright (C) 2013 - 2024, nymea GmbH
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
*
* This file is part of nymea-zigbee.
*
* nymea-zigbee 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.
*
* nymea-zigbee 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 nymea-zigbee. If not, see <https://www.gnu.org/licenses/>.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef ZIGBEECLUSTERLIBRARY_H
#define ZIGBEECLUSTERLIBRARY_H
#include <QObject>
#include <QDebug>
#include "zigbee.h"
#include "zigbeedatatype.h"
class ZigbeeClusterLibrary
{
Q_GADGET
public:
/* General ZCL commans */
enum Command {
CommandReadAttributes = 0x00,
CommandReadAttributesResponse = 0x01,
CommandWriteAttributes = 0x02,
CommandWriteAttributesUndivided = 0x03,
CommandWriteAttributesResponse = 0x04,
CommandWriteAttributesNoResponse = 0x05,
CommandConfigureReporting = 0x06,
CommandConfigureReportingResponse = 0x07,
CommandReadReportingConfiguration = 0x08,
CommandReadReportingConfigurationResponse = 0x09,
CommandReportAttributes = 0x0a,
CommandDefaultResponse = 0x0b,
CommandDiscoverAttributes = 0x0c,
CommandDiscoverAttributesResponse = 0x0d,
CommandReadAttributesStructured = 0x0e,
CommandWriteAttributesStructured = 0x0f,
CommandWriteAttributesStructuredResponse = 0x10,
CommandDiscoverCommandsReceived = 0x11,
CommandDiscoverCommandsReceivedResponse = 0x12,
CommandDiscoverCommandsGenerated = 0x13,
CommandDiscoverCommandsGeneratedResponse = 0x14,
CommandDiscoverAttributesExtended = 0x15,
CommandDiscoverAttributesExtendedResponse = 0x16
};
Q_ENUM(Command)
enum Status {
StatusSuccess = 0x00,
StatusFailure = 0x01,
StatusNotAuthorized = 0x7e,
StatusReservedFieldNotZero = 0x7f,
StatusMalformedCommand = 0x80,
StatusUnsupportedClusterCommand = 0x81,
StatusUnsupportedGeneralCommand = 0x82,
StatusUnsupportedManufacturerClusterCommand = 0x83,
StatusUnsupportedManufacturerGeneralCommand = 0x84,
StatusInvalidField = 0x85,
StatusUnsupportedAttribute = 0x86,
StatusInvalidValue = 0x87,
StatusReadOnly = 0x88,
StatusInsufficientSpace = 0x89,
StatusDuplicateExists = 0x8a,
StatusNotFound = 0x8b,
StatusUnreportableAttribute = 0x8c,
StatusInvalidDataType = 0x8d,
StatusInvalidSector = 0x8e,
StatusWriteOnly = 0x8f,
StatusInconsistentStartupState = 0x90,
StatusDefinedOutOfBand = 0x91,
StatusInconsistent = 0x92,
StatusActionDenied = 0x93,
StatusTimeout = 0x94,
StatusAbort = 0x95,
StatusInvalidImage = 0x96,
StatusWaitForData = 0x97,
StatusNoImageAvailable = 0x98,
StatusRequireMoreImage = 0x99,
StatusNotificationPending = 0x9a,
StatusHardwareFailure = 0xc0,
StatusSoftwareFailure = 0xc1,
StatusCalibrationError = 0xc2,
StatusUnsupportedCluster = 0xc3
};
Q_ENUM(Status)
enum ClusterId {
// Basics
ClusterIdUnknown = 0xffff,
ClusterIdBasic = 0x0000,
ClusterIdPowerConfiguration = 0x0001,
ClusterIdDeviceTemperature = 0x0002,
ClusterIdIdentify = 0x0003,
ClusterIdGroups = 0x0004,
ClusterIdScenes = 0x0005,
ClusterIdOnOff = 0x0006,
ClusterIdOnOffConfiguration = 0x0007,
ClusterIdLevelControl = 0x0008,
ClusterIdAlarms = 0x0009,
ClusterIdTime = 0x000A,
ClusterIdRssiLocation = 0x000B,
ClusterIdAnalogInput = 0x000C,
ClusterIdAnalogOutput = 0x000D,
ClusterIdAnalogValue = 0x000E,
ClusterIdBinaryInput = 0x000F,
ClusterIdBinaryOutput = 0x0010,
ClusterIdBinaryValue = 0x0011,
ClusterIdMultistateInput = 0x0012,
ClusterIdMultistateOutput = 0x0013,
ClusterIdMultistateValue = 0x0014,
ClusterIdCommissoning = 0x0015,
// Over the air uppgrade (OTA)
ClusterIdOtaUpgrade = 0x0019,
// Poll controll
ClusterIdPollControl = 0x0020,
// Closures
ClusterIdShadeConfiguration = 0x0100,
ClusterIdDoorLock = 0x0101,
ClusterIdWindowCovering = 0x0102,
// Heating, Ventilation and Air-Conditioning (HVAC)
ClusterIdPumpConfigurationControl = 0x0200,
ClusterIdThermostat = 0x0201,
ClusterIdFanControl = 0x0202,
ClusterIdDehumiditationControl = 0x0203,
ClusterIdThermostatUserControl = 0x0204,
// Lighting
ClusterIdColorControl = 0x0300,
ClusterIdBallastConfiguration = 0x0301,
// Sensing
ClusterIdIlluminanceMeasurement = 0x0400,
ClusterIdIlluminanceLevelSensing = 0x0401,
ClusterIdTemperatureMeasurement = 0x0402,
ClusterIdPressureMeasurement = 0x0403,
ClusterIdFlowMeasurement = 0x0404,
ClusterIdRelativeHumidityMeasurement = 0x0405,
ClusterIdOccupancySensing = 0x0406,
// Security and Safty
ClusterIdIasZone = 0x0500,
ClusterIdIasAce = 0x0501,
ClusterIdIasWd = 0x0502,
// Smart energy
ClusterIdPrice = 0x0700,
ClusterIdDemandResponseAndLoadControl = 0x0701,
ClusterIdMetering = 0x0702,
ClusterIdMessaging = 0x0703,
ClusterIdTunneling = 0x0704,
ClusterIdKeyEstablishment = 0x0800,
// ZLL
ClusterIdTouchlinkCommissioning = 0x1000,
// NXP Appliances
ClusterIdApplianceControl = 0x001B,
ClusterIdApplianceIdentification = 0x0B00,
ClusterIdApplianceEventsAlerts = 0x0B02,
ClusterIdApplianceStatistics = 0x0B03,
// Electrical Measurement
ClusterIdElectricalMeasurement = 0x0B04,
ClusterIdDiagnostics = 0x0B05,
// Zigbee green power
ClusterIdGreenPower = 0x0021,
// Manufacturer specific
ClusterIdManufacturerSpecificPhilips = 0xfc00,
};
Q_ENUM(ClusterId)
enum GlobalAttribute {
GlobalAttributeClusterRevision = 0xfffd,
GlobalAttributeAttributeReportingStatus = 0xfffe
};
Q_ENUM(GlobalAttribute)
enum AttributeReportingStatus {
AttributeReportingStatusPending = 0x00,
AttributeReportingStatusComplete = 0x01
};
Q_ENUM(AttributeReportingStatus)
// Frame control field
enum FrameType {
FrameTypeGlobal = 0x00,
FrameTypeClusterSpecific = 0x01
};
Q_ENUM(FrameType)
enum Direction {
DirectionClientToServer = 0x00,
DirectionServerToClient = 0x01
};
Q_ENUM(Direction)
enum ReportingDirection {
ReportingDirectionReporting = 0x00,
ReportingDirectionReceiving = 0x01
};
Q_ENUM(ReportingDirection)
typedef struct FrameControl {
FrameType frameType = FrameTypeGlobal;
bool manufacturerSpecific = false;
Direction direction = DirectionClientToServer;
bool disableDefaultResponse = false;
} FrameControl;
typedef struct Header {
FrameControl frameControl;
quint16 manufacturerCode = 0;
quint8 transactionSequenceNumber = 0;
quint8 command;
} ZclHeader;
typedef struct Frame {
Header header;
QByteArray payload;
} Frame;
// Read attribute
typedef struct ReadAttributeStatusRecord {
quint16 attributeId;
ZigbeeClusterLibrary::Status attributeStatus;
ZigbeeDataType dataType;
} ReadAttributeStatusRecord;
// Write attribute
typedef struct WriteAttributeRecord {
quint16 attributeId;
Zigbee::DataType dataType;
QByteArray data;
} WriteAttributeRecord;
// Reporting attributes
typedef struct AttributeReportingConfiguration {
ReportingDirection direction = ReportingDirectionReporting;
quint16 attributeId = 0x0000;
Zigbee::DataType dataType = Zigbee::NoData;
quint16 minReportingInterval = 0x0000; // seconds
quint16 maxReportingInterval = 0x0000; // seconds
QByteArray reportableChange; // Data depending on the dataType
quint16 timeoutPeriod = 0x0000; // seconds, only used for direction receiving
} AttributeReportingConfiguration;
// Response of reporting configuration
typedef struct AttributeReportingStatusRecord {
ZigbeeClusterLibrary::Status status;
ReportingDirection direction = ReportingDirectionReporting;
quint16 attributeId = 0x0000;
} AttributeReportingStatusRecord;
// General parse/build methods
static quint8 buildFrameControlByte(const FrameControl &frameControl);
static FrameControl parseFrameControlByte(quint8 frameControlByte);
static QByteArray buildHeader(const Header &header);
static QList<ReadAttributeStatusRecord> parseAttributeStatusRecords(const QByteArray &payload);
//static QByteArray readAttributeData(const QDataStream &stream, Zigbee::DataType dataType);
static ZigbeeDataType readDataType(QDataStream *stream, Zigbee::DataType dataType);
static Frame parseFrameData(const QByteArray &frameData);
static QByteArray buildFrame(const Frame &frame);
// AttributeReportingConfiguration
static QByteArray buildAttributeReportingConfiguration(const AttributeReportingConfiguration &reportingConfiguration);
static QByteArray buildWriteAttributeRecord(const WriteAttributeRecord &writeAttributeRecord);
// TODO: parseAttributeReportingConfiguration
static QList<AttributeReportingStatusRecord> parseAttributeReportingStatusRecords(const QByteArray &payload);
};
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::FrameControl &frameControl);
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Header &header);
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Frame &frame);
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::ReadAttributeStatusRecord &attributeStatusRecord);
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::AttributeReportingConfiguration &attributeReportingConfiguration);
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::AttributeReportingStatusRecord &attributeReportingStatusRecord);
#endif // ZIGBEECLUSTERLIBRARY_H