diff --git a/libnymea-zigbee/zcl/hvac/zigbeeclusterthermostat.cpp b/libnymea-zigbee/zcl/hvac/zigbeeclusterthermostat.cpp index 0ea8157..649402e 100644 --- a/libnymea-zigbee/zcl/hvac/zigbeeclusterthermostat.cpp +++ b/libnymea-zigbee/zcl/hvac/zigbeeclusterthermostat.cpp @@ -34,62 +34,62 @@ ZigbeeClusterThermostat::ZigbeeClusterThermostat(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, ZigbeeCluster::Direction direction, QObject *parent): ZigbeeCluster(network, node, endpoint, ZigbeeClusterLibrary::ClusterIdThermostat, direction, parent) { - } -void ZigbeeClusterThermostat::processDataIndication(ZigbeeClusterLibrary::Frame frame) +qint16 ZigbeeClusterThermostat::localTemperature() const { - qCDebug(dcZigbeeCluster()) << "Processing cluster frame" << m_node << m_endpoint << this << frame; - -// switch (m_direction) { -// case Client: -// if (frame.header.frameControl.direction == ZigbeeClusterLibrary::DirectionClientToServer) { -// Command command = static_cast(frame.header.command); -// qCDebug(dcZigbeeCluster()) << "Received" << command << "from" << m_node << m_endpoint << this; -// switch (command) { -// case CommandQueryNextImageRequest: { -// // Print the image information -// quint8 fieldControl; -// quint16 manufacturerCode; -// quint16 imageType; -// quint32 currentVersion; -// quint16 hardwareVersion; - -// QDataStream requestStream(&frame.payload, QIODevice::ReadOnly); -// requestStream.setByteOrder(QDataStream::LittleEndian); -// requestStream >> fieldControl >> manufacturerCode >> imageType >> currentVersion >> hardwareVersion; -// qCDebug(dcZigbeeCluster()) << "OTA image request:" << (fieldControl == 0x0000 ? "Hardware version not present" : "Hardware version present"); -// qCDebug(dcZigbeeCluster()) << "OTA image request: Manufacturer code" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode); -// qCDebug(dcZigbeeCluster()) << "OTA image request: Image type" << ZigbeeUtils::convertUint16ToHexString(imageType); -// qCDebug(dcZigbeeCluster()) << "OTA image request: Current file version" << ZigbeeUtils::convertUint32ToHexString(currentVersion) << parseFileVersion(currentVersion); -// qCDebug(dcZigbeeCluster()) << "OTA image request: Hardware version" << hardwareVersion; - -// // Respond with no image available until we implement the entire cluster for OTA updates -// qCDebug(dcZigbeeCluster()) << "OTA mechanism not implemented yet. Tell the node there is no image available."; - -// QByteArray payload; -// QDataStream stream(&payload, QIODevice::WriteOnly); -// stream.setByteOrder(QDataStream::LittleEndian); -// stream << static_cast(StatuCodeNoImageAvailable); - -// // Note: if there would be an image available, the response would be success, followed by manufacturer code, image type, file version of image and file size - -// ZigbeeClusterReply *reply = sendClusterServerResponse(CommandQueryNextImageResponse, frame.header.transactionSequenceNumber, payload); -// connect(reply, &ZigbeeClusterReply::finished, this, [](){ -// qCDebug(dcZigbeeCluster()) << "OTA image request response for image query sent successfully to requested node."; -// }); - -// break; -// } -// default: -// qCWarning(dcZigbeeCluster()) << "Received command" << command << "which is not implemented yet from" << m_node << m_endpoint << this; -// break; -// } -// } -// break; -// case Server: -// qCWarning(dcZigbeeCluster()) << "Unhandled ZCL indication in" << m_node << m_endpoint << this << frame; -// break; -// } - + return m_attributes.value(AttributeLocalTemperature).dataType().toInt16(); +} + +qint16 ZigbeeClusterThermostat::occupiedCoolingSetpoint() const +{ + return m_attributes.value(AttributeOccupiedCoolingSetpoint).dataType().toInt16(); +} + +qint16 ZigbeeClusterThermostat::occupiedHeatingSetpoint() const +{ + return m_attributes.value(AttributeOccupiedHeatingSetpoint).dataType().toInt16(); +} + +ZigbeeClusterReply *ZigbeeClusterThermostat::setOccupiedHeatingSetpoint(qint16 occupiedHeatingSetpoint) +{ + ZigbeeDataType dataType(occupiedHeatingSetpoint); + QList attributes; + ZigbeeClusterLibrary::WriteAttributeRecord attribute; + attribute.attributeId = ZigbeeClusterThermostat::AttributeOccupiedHeatingSetpoint; + attribute.dataType = dataType.dataType(); + attribute.data = dataType.data(); + attributes.append(attribute); + + return this->writeAttributes(attributes); +} + +ZigbeeClusterReply *ZigbeeClusterThermostat::setOccupiedCoolingSetpoint(qint16 occupiedCoolingSetpoint) +{ + ZigbeeDataType dataType(occupiedCoolingSetpoint); + QList attributes; + ZigbeeClusterLibrary::WriteAttributeRecord attribute; + attribute.attributeId = ZigbeeClusterThermostat::AttributeOccupiedCoolingSetpoint; + attribute.dataType = dataType.dataType(); + attribute.data = dataType.data(); + attributes.append(attribute); + + return this->writeAttributes(attributes); +} + +void ZigbeeClusterThermostat::setAttribute(const ZigbeeClusterAttribute &attribute) +{ + ZigbeeCluster::setAttribute(attribute); + + switch (attribute.id()) { + case AttributeLocalTemperature: + emit localTemperatureChanged(localTemperature()); + break; + case AttributeOccupiedCoolingSetpoint: + emit occupiedCoolingSetpointChanged(occupiedCoolingSetpoint()); + break; + case AttributeOccupiedHeatingSetpoint: + emit occupiedHeatingSetpointChanged(occupiedHeatingSetpoint()); + break; + } } diff --git a/libnymea-zigbee/zcl/hvac/zigbeeclusterthermostat.h b/libnymea-zigbee/zcl/hvac/zigbeeclusterthermostat.h index 903076a..c7d45bb 100644 --- a/libnymea-zigbee/zcl/hvac/zigbeeclusterthermostat.h +++ b/libnymea-zigbee/zcl/hvac/zigbeeclusterthermostat.h @@ -51,7 +51,7 @@ public: AttributePIHeatingDemand = 0x0008, AttributeHVACSystemTypeConfiguration = 0x0009, - AttributeLocalTemperatureCalibratioon = 0x0010, + AttributeLocalTemperatureCalibration = 0x0010, AttributeOccupiedCoolingSetpoint = 0x0011, AttributeOccupiedHeatingSetpoint = 0x0012, AttributeUnoccupiedCoolingSetpoint = 0x0013, @@ -66,15 +66,39 @@ public: AttributeSystemMode = 0x001c, AttributeAlarmMask = 0x001d, AttributeThermostatRunningMode = 0x001e - }; Q_ENUM(Attribute) + enum SystemMode { + SystemModeOff = 0x00, + SystemModeAuto = 0x01, + SystemModeCool = 0x03, + SystemModeHeat = 0x04, + SystemModeEmergencyHeating = 0x05, + SystemModePrecooling = 0x06, + SystemModeFanOnly = 0x07, + SystemModeDry = 0x08, + SystemModeSleep = 0x09 + }; + Q_ENUM(SystemMode) + explicit ZigbeeClusterThermostat(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr); -protected: - void processDataIndication(ZigbeeClusterLibrary::Frame frame) override; + qint16 localTemperature() const; + qint16 occupiedCoolingSetpoint() const; + qint16 occupiedHeatingSetpoint() const; + // targetTemp is °C*100. e.g. 20.5°C -> 2050 + ZigbeeClusterReply *setOccupiedHeatingSetpoint(qint16 occupiedHeatingSetpoint); + ZigbeeClusterReply *setOccupiedCoolingSetpoint(qint16 occupiedCoolingSetpoint); + +signals: + void localTemperatureChanged(qint16 localTemp); + void occupiedCoolingSetpointChanged(qint16 occupiedCoolingSetpoint); + void occupiedHeatingSetpointChanged(qint16 occupiedHeatingSetpoint); + +private: + void setAttribute(const ZigbeeClusterAttribute &attribute) override; }; #endif // ZIGBEECLUSTERTHERMOSTAT_H