diff --git a/libnymea-zigbee/zcl/measurement/zigbeeclusterelectricalmeasurement.cpp b/libnymea-zigbee/zcl/measurement/zigbeeclusterelectricalmeasurement.cpp index 80a5f45..34eca00 100644 --- a/libnymea-zigbee/zcl/measurement/zigbeeclusterelectricalmeasurement.cpp +++ b/libnymea-zigbee/zcl/measurement/zigbeeclusterelectricalmeasurement.cpp @@ -1,5 +1,7 @@ #include "zigbeeclusterelectricalmeasurement.h" +#include +#include #include Q_DECLARE_LOGGING_CATEGORY(dcZigbeeCluster) @@ -26,3 +28,48 @@ void ZigbeeClusterElectricalMeasurement::setAttribute(const ZigbeeClusterAttribu break; } } + +void ZigbeeClusterElectricalMeasurement::processDataIndication(ZigbeeClusterLibrary::Frame frame) +{ + switch (m_direction) { + case Client: + qCWarning(dcZigbeeCluster()) << "ElectricalMeasurement: Unhandled ZCL indication in" << m_node << m_endpoint << this << frame; + break; + case Server: + ServerCommand command = static_cast(frame.header.command); + switch (command) { + case CommandGetProfileInfoResponse: { + QDataStream stream(frame.payload); + stream.setByteOrder(QDataStream::LittleEndian); + quint8 profileCount, profileIntervalPeriod, maxNumberOfIntervals; + QList attributes; + stream >> profileCount >> profileIntervalPeriod >> maxNumberOfIntervals; + while (!stream.atEnd()) { + stream >> attributes; + } + qCDebug(dcZigbeeCluster()) << "ElectricalMeasurement: GetProfileInfoResponse received:" << profileCount << static_cast(profileIntervalPeriod) << maxNumberOfIntervals << attributes; + emit getProfileInfoResponse(profileCount, static_cast(profileIntervalPeriod), maxNumberOfIntervals, attributes); + break; + } + case CommandGetMeasurementProfileResponse: { + QDataStream stream(frame.payload); + stream.setByteOrder(QDataStream::LittleEndian); + quint32 startTime; + // According to the spec, attributeId is 1 octet, however, normally an attributeId is 2 octets... + quint8 status, profileIntervalPeriod, numberOfIntevalsDelivered, attributeId; + QList values; + stream >> startTime >> status >> profileIntervalPeriod >> numberOfIntevalsDelivered >> attributeId; + while (!stream.atEnd()) { + stream >> values; + } + qCDebug(dcZigbeeCluster()) << "ElectricalMeasurement: GetMeasurementProfileInfoResponse:" << QDateTime::fromMSecsSinceEpoch((qulonglong)startTime * 1000) << static_cast(status) << static_cast(profileIntervalPeriod) << numberOfIntevalsDelivered << attributeId << values; + emit getMeasurementProfileInfoResponse(QDateTime::fromMSecsSinceEpoch((qulonglong)startTime * 1000), static_cast(status), static_cast(profileIntervalPeriod), numberOfIntevalsDelivered, attributeId, values); + break; + } + default: + qCInfo(dcZigbeeCluster()) << "ElectricalMeasurement: Ignoring out of spec command:" << m_node << m_endpoint << this << frame << m_direction; + } + + break; + } +} diff --git a/libnymea-zigbee/zcl/measurement/zigbeeclusterelectricalmeasurement.h b/libnymea-zigbee/zcl/measurement/zigbeeclusterelectricalmeasurement.h index 793b690..a02d559 100644 --- a/libnymea-zigbee/zcl/measurement/zigbeeclusterelectricalmeasurement.h +++ b/libnymea-zigbee/zcl/measurement/zigbeeclusterelectricalmeasurement.h @@ -225,6 +225,39 @@ public: Q_DECLARE_FLAGS(ACAlarmsMask, ACAlarm) Q_FLAG(ACAlarmsMask) + enum ProfileIntervalPeriod { + ProfileIntervalPeriodDaily = 0x00, + ProfileIntervalPeriod60Minutes = 0x01, + ProfileIntervalPeriod30Minutes = 0x02, + ProfileIntervalPeriod15Minutes = 0x03, + ProfileIntervalPeriod10Minutes = 0x04, + ProfileIntervalPeriod7p5Minutes = 0x05, + ProfileIntervalPeriod5Minutes = 0x06, + ProfileIntervalPeriod2p5Minutes = 0x07 + }; + Q_ENUM(ProfileIntervalPeriod) + + enum MeasurementStatus { + MeasurementStatusSuccess = 0x00, + MeasurementTypeAttributeProfileNotSupported = 0x01, + MeasurementStatusInvalidStartTime = 0x02, + MeasurementStatusMoreIntervalsRequestedThanCanBeReturned = 0x03, + MeasurementTypeNoIntervalsAvailableForRequestedTime = 0x04 + }; + Q_ENUM(MeasurementStatus) + + enum ClientCommand { + CommandGetProfileInfo = 0x00, + CommandGetMeasurementProfileInfo = 0x01 + }; + Q_ENUM(ClientCommand) + + enum ServerCommand { + CommandGetProfileInfoResponse = 0x00, + CommandGetMeasurementProfileResponse = 0x01 + }; + Q_ENUM(ServerCommand) + explicit ZigbeeClusterElectricalMeasurement(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr); quint16 activePowerPhaseA() const; @@ -232,6 +265,12 @@ public: signals: void activePowerPhaseAChanged(qint16 activePowerPhaseA); + void getProfileInfoResponse(quint8 profileCount, ProfileIntervalPeriod profileIntervalPeriod, quint8 maxNumberOfIntervals, const QList &attributes); + void getMeasurementProfileInfoResponse(const QDateTime &startTime, MeasurementStatus status, ProfileIntervalPeriod profileIntervalPeriod, quint8 numberOfIntervals, quint8 attributeId, const QList &values); + +protected: + void processDataIndication(ZigbeeClusterLibrary::Frame frame) override; + private: void setAttribute(const ZigbeeClusterAttribute &attribute) override;