diff --git a/AquaMQTT/include/message/IEnergyMessage.h b/AquaMQTT/include/message/IEnergyMessage.h index 1b668a5..9d3e391 100644 --- a/AquaMQTT/include/message/IEnergyMessage.h +++ b/AquaMQTT/include/message/IEnergyMessage.h @@ -6,6 +6,20 @@ namespace aquamqtt::message { +enum class ENERGY_ATTR_I8 +{ + DIAG_AIR_TEMP_MAX, + DIAG_AIR_TEMP_MIN, + DIAG_EVA_UPPER_AIR_TEMP_MAX, + DIAG_EVA_UPPER_AIR_TEMP_MIN, + DIAG_EVA_LOWER_AIR_TEMP_MAX, + DIAG_EVA_LOWER_AIR_TEMP_MIN, + DIAG_COMPRESSOR_TEMP_MAX, + DIAG_COMPRESSOR_TEMP_MIN, + DIAG_WATER_TEMP_MAX, + DIAG_WATER_TEMP_MIN +}; + enum class ENERGY_ATTR_U16 { POWER_HEATPUMP, @@ -36,14 +50,17 @@ class IEnergyMessage virtual uint64_t getAttr(ENERGY_ATTR_U64 attr) = 0; virtual uint32_t getAttr(ENERGY_ATTR_U32 attr) = 0; virtual uint16_t getAttr(ENERGY_ATTR_U16 attr) = 0; + virtual int8_t getAttr(ENERGY_ATTR_I8 attr) = 0; virtual bool hasAttr(ENERGY_ATTR_U64 attr) const = 0; virtual bool hasAttr(ENERGY_ATTR_U32 attr) const = 0; virtual bool hasAttr(ENERGY_ATTR_U16 attr) const = 0; + virtual bool hasAttr(ENERGY_ATTR_I8 attr) const = 0; virtual bool hasChanged(ENERGY_ATTR_U64 attr) const = 0; virtual bool hasChanged(ENERGY_ATTR_U32 attr) const = 0; virtual bool hasChanged(ENERGY_ATTR_U16 attr) const = 0; + virtual bool hasChanged(ENERGY_ATTR_I8 attr) const = 0; }; } // namespace aquamqtt::message diff --git a/AquaMQTT/include/message/legacy/MainEnergyMessage.h b/AquaMQTT/include/message/legacy/MainEnergyMessage.h index cbaeb60..2abe370 100644 --- a/AquaMQTT/include/message/legacy/MainEnergyMessage.h +++ b/AquaMQTT/include/message/legacy/MainEnergyMessage.h @@ -20,14 +20,17 @@ class MainEnergyMessage : public IEnergyMessage uint64_t getAttr(ENERGY_ATTR_U64 attr) override; uint32_t getAttr(ENERGY_ATTR_U32 attr) override; uint16_t getAttr(ENERGY_ATTR_U16 attr) override; + int8_t getAttr(ENERGY_ATTR_I8 attr) override; bool hasAttr(ENERGY_ATTR_U64 attr) const override; bool hasAttr(ENERGY_ATTR_U32 attr) const override; bool hasAttr(ENERGY_ATTR_U16 attr) const override; + bool hasAttr(ENERGY_ATTR_I8 attr) const override; bool hasChanged(ENERGY_ATTR_U64 attr) const override; bool hasChanged(ENERGY_ATTR_U32 attr) const override; bool hasChanged(ENERGY_ATTR_U16 attr) const override; + bool hasChanged(ENERGY_ATTR_I8 attr) const override; private: void compareWith(uint8_t* data); diff --git a/AquaMQTT/include/message/next/MainEnergyMessage.h b/AquaMQTT/include/message/next/MainEnergyMessage.h index 528b123..e3d1157 100644 --- a/AquaMQTT/include/message/next/MainEnergyMessage.h +++ b/AquaMQTT/include/message/next/MainEnergyMessage.h @@ -20,14 +20,17 @@ class MainEnergyMessage : public IEnergyMessage uint64_t getAttr(ENERGY_ATTR_U64 attr) override; uint32_t getAttr(ENERGY_ATTR_U32 attr) override; uint16_t getAttr(ENERGY_ATTR_U16 attr) override; + int8_t getAttr(ENERGY_ATTR_I8 attr) override; bool hasAttr(ENERGY_ATTR_U64 attr) const override; bool hasAttr(ENERGY_ATTR_U32 attr) const override; bool hasAttr(ENERGY_ATTR_U16 attr) const override; + bool hasAttr(ENERGY_ATTR_I8 attr) const override; bool hasChanged(ENERGY_ATTR_U64 attr) const override; bool hasChanged(ENERGY_ATTR_U32 attr) const override; bool hasChanged(ENERGY_ATTR_U16 attr) const override; + bool hasChanged(ENERGY_ATTR_I8 attr) const override; private: void compareWith(uint8_t* data); @@ -38,6 +41,8 @@ class MainEnergyMessage : public IEnergyMessage std::set mHasChangedU16; std::set mHasChangedU32; std::set mHasChangedU64; + std::set mHasChangedI8; + }; } // namespace aquamqtt::message::next diff --git a/AquaMQTT/include/mqtt/MQTTDefinitions.h b/AquaMQTT/include/mqtt/MQTTDefinitions.h index 980c7a6..0713aee 100644 --- a/AquaMQTT/include/mqtt/MQTTDefinitions.h +++ b/AquaMQTT/include/mqtt/MQTTDefinitions.h @@ -131,6 +131,17 @@ constexpr char ENERGY_POWER_HEAT_ELEMENT[] = { "powerHeatingElem" }; constexpr char ENERGY_POWER_HEATPUMP[] = { "powerHeatpump" }; constexpr char ENERGY_TOTAL_WATER_PRODUCTION[] = { "totalWaterProduction" }; +constexpr char ENERGY_DIAG_AIR_TEMP_MAX[] = { "diagAirTempMax" }; +constexpr char ENERGY_DIAG_AIR_TEMP_MIN[] = { "diagAirTempMin" }; +constexpr char ENERGY_DIAG_EVA_UPPER_AIR_TEMP_MAX[] = { "diagEvaUpperMax" }; +constexpr char ENERGY_DIAG_EVA_UPPER_AIR_TEMP_MIN[] = { "diagEvaUpperMin" }; +constexpr char ENERGY_DIAG_EVA_LOWER_AIR_TEMP_MAX[] = { "diagEvaLowerMax" }; +constexpr char ENERGY_DIAG_EVA_LOWER_AIR_TEMP_MIN[] = { "diagEvaLowerMin" }; +constexpr char ENERGY_DIAG_COMPRESSOR_TEMP_MAX[] = { "diagCompressorMax" }; +constexpr char ENERGY_DIAG_COMPRESSOR_TEMP_MIN[] = { "diagCompressorMin" }; +constexpr char ENERGY_DIAG_WATER_TEMP_MAX[] = { "diagWaterTempMax" }; +constexpr char ENERGY_DIAG_WATER_TEMP_MIN[] = { "diagWaterTempMin" }; + constexpr char ERROR_ERROR_NUMBER[] = { "errorNumber" }; constexpr char STATS_AQUAMQTT_ADDR[] = { "ipAddress" }; diff --git a/AquaMQTT/include/mqtt/MQTTDiscovery.h b/AquaMQTT/include/mqtt/MQTTDiscovery.h index 35d7de0..8c41dde 100644 --- a/AquaMQTT/include/mqtt/MQTTDiscovery.h +++ b/AquaMQTT/include/mqtt/MQTTDiscovery.h @@ -64,6 +64,16 @@ enum class MQTT_ITEM_SENSOR STATS_MAIN_MSG_CRC_NOK, STATS_MAIN_DROPPED_BYTES, MAIN_COMPRESSOR_OUTLET_TEMP, + ENERGY_DIAG_AIR_TEMP_MAX, + ENERGY_DIAG_AIR_TEMP_MIN, + ENERGY_DIAG_EVA_UPPER_AIR_TEMP_MAX, + ENERGY_DIAG_EVA_UPPER_AIR_TEMP_MIN, + ENERGY_DIAG_EVA_LOWER_AIR_TEMP_MAX, + ENERGY_DIAG_EVA_LOWER_AIR_TEMP_MIN, + ENERGY_DIAG_COMPRESSOR_TEMP_MAX, + ENERGY_DIAG_COMPRESSOR_TEMP_MIN, + ENERGY_DIAG_WATER_TEMP_MAX, + ENERGY_DIAG_WATER_TEMP_MIN, RESERVED_COUNT }; @@ -256,10 +266,6 @@ static bool buildConfiguration( doc["uniq_id"] = make_unique(temp, identifier, "main_error_code"); break; case MQTT_ITEM_SENSOR::ENERGY_TOTAL_HEATING_ELEM_HOURS: - if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_NEXT) - { - return false; - } doc["name"] = "Total Heating Element Hours"; doc["stat_t"] = "~/energy/totalHeatingElemHours"; doc["unit_of_meas"] = "h"; @@ -276,6 +282,10 @@ static bool buildConfiguration( doc["uniq_id"] = make_unique(temp, identifier, "energy_total_hp_h"); break; case MQTT_ITEM_SENSOR::ENERGY_TOTAL_HOURS: + if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_NEXT) + { + return false; + } doc["name"] = "Total Hours"; doc["stat_t"] = "~/energy/totalHours"; doc["unit_of_meas"] = "h"; @@ -284,23 +294,15 @@ static bool buildConfiguration( doc["uniq_id"] = make_unique(temp, identifier, "energy_total_h"); break; case MQTT_ITEM_SENSOR::ENERGY_TOTAL_ENERGY_WH: - if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_NEXT) - { - return false; - } doc["name"] = "Total Energy"; doc["stat_t"] = "~/energy/totalEnergyWh"; doc["unit_of_meas"] = "Wh"; - doc["stat_cla"] = "total"; + doc["stat_cla"] = "total_increasing"; doc["ic"] = "mdi:lightning-bolt-circle"; doc["uniq_id"] = make_unique(temp, identifier, "energy_total_energy"); doc["dev_cla"] = "energy"; break; case MQTT_ITEM_SENSOR::ENERGY_POWER_TOTAL: - if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_NEXT) - { - return false; - } doc["name"] = "Power Consumed Total"; doc["stat_t"] = "~/energy/powerTotal"; doc["unit_of_meas"] = "W"; @@ -323,6 +325,10 @@ static bool buildConfiguration( doc["dev_cla"] = "power"; break; case MQTT_ITEM_SENSOR::ENERGY_POWER_HEATPUMP: + if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_NEXT) + { + return false; + } doc["name"] = "Power Consumed Heatpump"; doc["stat_t"] = "~/energy/powerHeatpump"; doc["unit_of_meas"] = "W"; @@ -665,10 +671,120 @@ static bool buildConfiguration( doc["stat_t"] = "~/hmi/pvInputActivated"; doc["uniq_id"] = make_unique(temp, identifier, "hmi_pv_allowed"); doc["ic"] = "mdi:solar-power-variant"; + break; + case MQTT_ITEM_SENSOR::ENERGY_DIAG_AIR_TEMP_MAX: + if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_LEGACY) + { + return false; + } + doc["name"] = "Air Temperature Observed Max"; + doc["stat_t"] = "~/energy/diagAirTempMax"; + doc["ent_cat"] = "diagnostic"; + doc["uniq_id"] = make_unique(temp, identifier, "energy_d_at_max"); + doc["unit_of_meas"] = "°C"; + break; + case MQTT_ITEM_SENSOR::ENERGY_DIAG_AIR_TEMP_MIN: + if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_LEGACY) + { + return false; + } + doc["name"] = "Air Temperature Observed Min"; + doc["stat_t"] = "~/energy/diagAirTempMin"; + doc["ent_cat"] = "diagnostic"; + doc["uniq_id"] = make_unique(temp, identifier, "energy_d_at_min"); + doc["unit_of_meas"] = "°C"; + break; + case MQTT_ITEM_SENSOR::ENERGY_DIAG_EVA_UPPER_AIR_TEMP_MAX: + if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_LEGACY) + { + return false; + } + doc["name"] = "Upper Evaporator Temperature Observed Max"; + doc["stat_t"] = "~/energy/diagEvaUpperMax"; + doc["ent_cat"] = "diagnostic"; + doc["uniq_id"] = make_unique(temp, identifier, "energy_d_ue_max"); + doc["unit_of_meas"] = "°C"; + break; + case MQTT_ITEM_SENSOR::ENERGY_DIAG_EVA_UPPER_AIR_TEMP_MIN: + if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_LEGACY) + { + return false; + } + doc["name"] = "Upper Evaporator Temperature Observed Min"; + doc["stat_t"] = "~/energy/diagEvaUpperMin"; + doc["ent_cat"] = "diagnostic"; + doc["uniq_id"] = make_unique(temp, identifier, "energy_d_ue_min"); + doc["unit_of_meas"] = "°C"; + break; + case MQTT_ITEM_SENSOR::ENERGY_DIAG_EVA_LOWER_AIR_TEMP_MAX: + if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_LEGACY) + { + return false; + } + doc["name"] = "Lower Evaporator Temperature Observed Max"; + doc["stat_t"] = "~/energy/diagEvaLowerMax"; + doc["ent_cat"] = "diagnostic"; + doc["uniq_id"] = make_unique(temp, identifier, "energy_d_le_max"); + doc["unit_of_meas"] = "°C"; + break; + case MQTT_ITEM_SENSOR::ENERGY_DIAG_EVA_LOWER_AIR_TEMP_MIN: + if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_LEGACY) + { + return false; + } + doc["name"] = "Lower Evaporator Temperature Observed Min"; + doc["stat_t"] = "~/energy/diagEvaLowerMin"; + doc["ent_cat"] = "diagnostic"; + doc["uniq_id"] = make_unique(temp, identifier, "energy_d_le_min"); + doc["unit_of_meas"] = "°C"; + break; + case MQTT_ITEM_SENSOR::ENERGY_DIAG_COMPRESSOR_TEMP_MAX: + if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_LEGACY) + { + return false; + } + doc["name"] = "Compressor Temperature Observed Max"; + doc["stat_t"] = "~/energy/diagCompressorMax"; + doc["ent_cat"] = "diagnostic"; + doc["uniq_id"] = make_unique(temp, identifier, "energy_d_c_max"); + doc["unit_of_meas"] = "°C"; + break; + case MQTT_ITEM_SENSOR::ENERGY_DIAG_COMPRESSOR_TEMP_MIN: + if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_LEGACY) + { + return false; + } + doc["name"] = "Compressor Temperature Observed Min"; + doc["stat_t"] = "~/energy/diagCompressorMin"; + doc["ent_cat"] = "diagnostic"; + doc["uniq_id"] = make_unique(temp, identifier, "energy_d_c_min"); + doc["unit_of_meas"] = "°C"; + break; + case MQTT_ITEM_SENSOR::ENERGY_DIAG_WATER_TEMP_MAX: + if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_LEGACY) + { + return false; + } + doc["name"] = "Water Temperature Observed Max"; + doc["stat_t"] = "~/energy/diagWaterTempMax"; + doc["ent_cat"] = "diagnostic"; + doc["uniq_id"] = make_unique(temp, identifier, "energy_d_w_max"); + doc["unit_of_meas"] = "°C"; + break; + case MQTT_ITEM_SENSOR::ENERGY_DIAG_WATER_TEMP_MIN: + if (protocolVersion == aquamqtt::message::ProtocolVersion::PROTOCOL_LEGACY) + { + return false; + } + doc["name"] = "Water Temperature Observed Min"; + doc["stat_t"] = "~/energy/diagWaterTempMin"; + doc["ent_cat"] = "diagnostic"; + doc["uniq_id"] = make_unique(temp, identifier, "energy_d_w_min"); + doc["unit_of_meas"] = "°C"; + break; case MQTT_ITEM_SENSOR::RESERVED_COUNT: default: return false; - } serializeJson(doc, buffer, config::MQTT_MAX_PAYLOAD_SIZE); diff --git a/AquaMQTT/src/message/legacy/MainEnergyMessage.cpp b/AquaMQTT/src/message/legacy/MainEnergyMessage.cpp index 8bf4ed9..289c2d0 100644 --- a/AquaMQTT/src/message/legacy/MainEnergyMessage.cpp +++ b/AquaMQTT/src/message/legacy/MainEnergyMessage.cpp @@ -130,6 +130,13 @@ uint16_t MainEnergyMessage::getAttr(ENERGY_ATTR_U16 attr) return 0; } +int8_t MainEnergyMessage::getAttr(ENERGY_ATTR_I8 attr) +{ + return 0; +} + + + bool MainEnergyMessage::hasAttr(ENERGY_ATTR_U64 attr) const { switch (attr) @@ -168,6 +175,11 @@ bool MainEnergyMessage::hasAttr(ENERGY_ATTR_U16 attr) const } } +bool MainEnergyMessage::hasAttr(ENERGY_ATTR_I8 attr) const +{ + return false; +} + bool MainEnergyMessage::hasChanged(ENERGY_ATTR_U64 attr) const { return mCreatedWithoutPrevious || mHasChangedU64.find(attr) != mHasChangedU64.end(); @@ -182,4 +194,10 @@ bool MainEnergyMessage::hasChanged(ENERGY_ATTR_U16 attr) const { return mCreatedWithoutPrevious || mHasChangedU16.find(attr) != mHasChangedU16.end(); } + +bool MainEnergyMessage::hasChanged(ENERGY_ATTR_I8 attr) const +{ + return false; +} + } // namespace aquamqtt::message::legacy diff --git a/AquaMQTT/src/message/next/MainEnergyMessage.cpp b/AquaMQTT/src/message/next/MainEnergyMessage.cpp index 9973354..ed697ac 100644 --- a/AquaMQTT/src/message/next/MainEnergyMessage.cpp +++ b/AquaMQTT/src/message/next/MainEnergyMessage.cpp @@ -10,8 +10,9 @@ MainEnergyMessage::MainEnergyMessage(uint8_t* data, uint8_t* previous) , mHasChangedU16() , mHasChangedU32() , mHasChangedU64() + , mHasChangedI8() { - mCreatedWithoutPrevious = previous == nullptr; + mCreatedWithoutPrevious = (previous == nullptr); compareWith(previous); } @@ -32,11 +33,11 @@ void MainEnergyMessage::compareWith(uint8_t* data) switch (indiceChanged) { - case 3: - case 4: - case 5: - case 6: - mHasChangedU32.insert(ENERGY_ATTR_U32::TOTAL_HOURS); + case 9: + case 10: + case 11: + case 12: + mHasChangedU32.insert(ENERGY_ATTR_U32::TOTAL_HEATING_ELEMENT_HOURS); break; case 13: case 14: @@ -44,10 +45,46 @@ void MainEnergyMessage::compareWith(uint8_t* data) case 16: mHasChangedU32.insert(ENERGY_ATTR_U32::TOTAL_HEATPUMP_HOURS); break; + case 17: + case 18: + case 19: + case 20: + mHasChangedU64.insert(ENERGY_ATTR_U64::TOTAL_ENERGY); + break; case 21: case 22: mHasChangedU16.insert(ENERGY_ATTR_U16::POWER_HEATPUMP); break; + case 38: + mHasChangedI8.insert(ENERGY_ATTR_I8::DIAG_AIR_TEMP_MAX); + break; + case 37: + mHasChangedI8.insert(ENERGY_ATTR_I8::DIAG_AIR_TEMP_MIN); + break; + case 36: + mHasChangedI8.insert(ENERGY_ATTR_I8::DIAG_EVA_UPPER_AIR_TEMP_MAX); + break; + case 35: + mHasChangedI8.insert(ENERGY_ATTR_I8::DIAG_EVA_UPPER_AIR_TEMP_MIN); + break; + case 34: + mHasChangedI8.insert(ENERGY_ATTR_I8::DIAG_EVA_LOWER_AIR_TEMP_MAX); + break; + case 33: + mHasChangedI8.insert(ENERGY_ATTR_I8::DIAG_EVA_LOWER_AIR_TEMP_MIN); + break; + case 32: + mHasChangedI8.insert(ENERGY_ATTR_I8::DIAG_COMPRESSOR_TEMP_MAX); + break; + case 31: + mHasChangedI8.insert(ENERGY_ATTR_I8::DIAG_COMPRESSOR_TEMP_MIN); + break; + case 30: + mHasChangedI8.insert(ENERGY_ATTR_I8::DIAG_WATER_TEMP_MAX); + break; + case 29: + mHasChangedI8.insert(ENERGY_ATTR_I8::DIAG_WATER_TEMP_MIN); + break; default: break; } @@ -64,7 +101,9 @@ uint64_t MainEnergyMessage::getAttr(ENERGY_ATTR_U64 attr) switch (attr) { case ENERGY_ATTR_U64::TOTAL_ENERGY: - break; + // NEXT protocol has this attribute stored as u32 + return ((uint32_t) mData[20] << 24) | ((uint32_t) mData[19] << 16) | ((uint32_t) mData[18] << 8) + | (uint32_t) mData[17]; } return 0; } @@ -76,10 +115,10 @@ uint32_t MainEnergyMessage::getAttr(ENERGY_ATTR_U32 attr) case ENERGY_ATTR_U32::TOTAL_HEATPUMP_HOURS: return ((uint32_t) mData[16] << 24) | ((uint32_t) mData[15] << 16) | ((uint32_t) mData[14] << 8) | (uint32_t) mData[13]; - case ENERGY_ATTR_U32::TOTAL_HOURS: - return ((uint32_t) mData[6] << 24) | ((uint32_t) mData[5] << 16) | ((uint32_t) mData[4] << 8) - | (uint32_t) mData[3]; case ENERGY_ATTR_U32::TOTAL_HEATING_ELEMENT_HOURS: + return ((uint32_t) mData[12] << 24) | ((uint32_t) mData[11] << 16) | ((uint32_t) mData[10] << 8) + | (uint32_t) mData[9]; + case ENERGY_ATTR_U32::TOTAL_HOURS: break; } return 0; @@ -99,12 +138,40 @@ uint16_t MainEnergyMessage::getAttr(ENERGY_ATTR_U16 attr) return 0; } +int8_t MainEnergyMessage::getAttr(ENERGY_ATTR_I8 attr) +{ + switch (attr) + { + case ENERGY_ATTR_I8::DIAG_AIR_TEMP_MAX: + return static_cast(mData[38]); + case ENERGY_ATTR_I8::DIAG_AIR_TEMP_MIN: + return static_cast(mData[37]); + case ENERGY_ATTR_I8::DIAG_EVA_UPPER_AIR_TEMP_MAX: + return static_cast(mData[36]); + case ENERGY_ATTR_I8::DIAG_EVA_UPPER_AIR_TEMP_MIN: + return static_cast(mData[35]); + case ENERGY_ATTR_I8::DIAG_EVA_LOWER_AIR_TEMP_MAX: + return static_cast(mData[34]); + case ENERGY_ATTR_I8::DIAG_EVA_LOWER_AIR_TEMP_MIN: + return static_cast(mData[33]); + case ENERGY_ATTR_I8::DIAG_COMPRESSOR_TEMP_MAX: + return static_cast(mData[32]); + case ENERGY_ATTR_I8::DIAG_COMPRESSOR_TEMP_MIN: + return static_cast(mData[31]); + case ENERGY_ATTR_I8::DIAG_WATER_TEMP_MAX: + return static_cast(mData[30]); + case ENERGY_ATTR_I8::DIAG_WATER_TEMP_MIN: + return static_cast(mData[29]); + } + return 0; +} + bool MainEnergyMessage::hasAttr(ENERGY_ATTR_U64 attr) const { switch (attr) { case ENERGY_ATTR_U64::TOTAL_ENERGY: - break; + return true; } return false; } @@ -114,9 +181,9 @@ bool MainEnergyMessage::hasAttr(ENERGY_ATTR_U32 attr) const switch (attr) { case ENERGY_ATTR_U32::TOTAL_HEATPUMP_HOURS: - case ENERGY_ATTR_U32::TOTAL_HOURS: - return true; case ENERGY_ATTR_U32::TOTAL_HEATING_ELEMENT_HOURS: + return true; + case ENERGY_ATTR_U32::TOTAL_HOURS: break; } return false; @@ -126,16 +193,35 @@ bool MainEnergyMessage::hasAttr(ENERGY_ATTR_U16 attr) const { switch (attr) { - case ENERGY_ATTR_U16::POWER_HEATPUMP: + case ENERGY_ATTR_U16::POWER_TOTAL: return true; + case ENERGY_ATTR_U16::POWER_HEATPUMP: case ENERGY_ATTR_U16::POWER_HEATELEMENT: - case ENERGY_ATTR_U16::POWER_TOTAL: case ENERGY_ATTR_U16::WATER_TOTAL: break; } return false; } +bool MainEnergyMessage::hasAttr(ENERGY_ATTR_I8 attr) const +{ + switch (attr) + { + case ENERGY_ATTR_I8::DIAG_AIR_TEMP_MAX: + case ENERGY_ATTR_I8::DIAG_AIR_TEMP_MIN: + case ENERGY_ATTR_I8::DIAG_EVA_UPPER_AIR_TEMP_MAX: + case ENERGY_ATTR_I8::DIAG_EVA_UPPER_AIR_TEMP_MIN: + case ENERGY_ATTR_I8::DIAG_EVA_LOWER_AIR_TEMP_MAX: + case ENERGY_ATTR_I8::DIAG_EVA_LOWER_AIR_TEMP_MIN: + case ENERGY_ATTR_I8::DIAG_COMPRESSOR_TEMP_MAX: + case ENERGY_ATTR_I8::DIAG_COMPRESSOR_TEMP_MIN: + case ENERGY_ATTR_I8::DIAG_WATER_TEMP_MAX: + case ENERGY_ATTR_I8::DIAG_WATER_TEMP_MIN: + return true; + } + return false; +} + bool MainEnergyMessage::hasChanged(ENERGY_ATTR_U64 attr) const { return mCreatedWithoutPrevious || mHasChangedU64.find(attr) != mHasChangedU64.end(); @@ -151,4 +237,9 @@ bool MainEnergyMessage::hasChanged(ENERGY_ATTR_U16 attr) const return mCreatedWithoutPrevious || mHasChangedU16.find(attr) != mHasChangedU16.end(); } +bool MainEnergyMessage::hasChanged(ENERGY_ATTR_I8 attr) const +{ + return mCreatedWithoutPrevious || mHasChangedI8.find(attr) != mHasChangedI8.end(); +} + } // namespace aquamqtt::message::next diff --git a/AquaMQTT/src/message/next/MainStatusMessage.cpp b/AquaMQTT/src/message/next/MainStatusMessage.cpp index 2ad4bc6..d885207 100644 --- a/AquaMQTT/src/message/next/MainStatusMessage.cpp +++ b/AquaMQTT/src/message/next/MainStatusMessage.cpp @@ -70,15 +70,15 @@ float MainStatusMessage::getAttr(MAIN_ATTR_FLOAT attr) switch (attr) { case MAIN_ATTR_FLOAT::WATER_TEMPERATURE: - return mData[1]; + return static_cast(mData[1]); case MAIN_ATTR_FLOAT::AIR_TEMPERATURE: - return mData[9]; + return static_cast(mData[9]); case MAIN_ATTR_FLOAT::EVAPORATOR_UPPER_TEMPERATURE: - return mData[5]; + return static_cast(mData[5]); case MAIN_ATTR_FLOAT::EVAPORATOR_LOWER_TEMPERATURE: - return mData[7]; + return static_cast(mData[7]); case MAIN_ATTR_FLOAT::COMPRESSOR_OUTLET_TEMPERATURE: - return mData[3]; + return static_cast(mData[3]); case MAIN_ATTR_FLOAT::FAN_SPEED_PWM: return mData[18]; } diff --git a/AquaMQTT/src/task/MQTTTask.cpp b/AquaMQTT/src/task/MQTTTask.cpp index d6e1ef2..8cdab45 100644 --- a/AquaMQTT/src/task/MQTTTask.cpp +++ b/AquaMQTT/src/task/MQTTTask.cpp @@ -1066,13 +1066,13 @@ void MQTTTask::updateEnergyStats(bool fullUpdate, message::ProtocolVersion& vers { message = std::make_unique( mTransferBuffer, - fullUpdate ? nullptr : mLastProcessedHMIMessage); + fullUpdate ? nullptr : mLastProcessedEnergyMessage); } else { message = std::make_unique( mTransferBuffer, - fullUpdate ? nullptr : mLastProcessedHMIMessage); + fullUpdate ? nullptr : mLastProcessedEnergyMessage); } if (message->hasAttr(ENERGY_ATTR_U32::TOTAL_HEATPUMP_HOURS)) @@ -1154,6 +1154,101 @@ void MQTTTask::updateEnergyStats(bool fullUpdate, message::ProtocolVersion& vers } } + if (message->hasAttr(ENERGY_ATTR_I8::DIAG_AIR_TEMP_MAX)) + { + if (fullUpdate || message->hasChanged(ENERGY_ATTR_I8::DIAG_AIR_TEMP_MAX)) + { + publishi(ENERGY_SUBTOPIC, ENERGY_DIAG_AIR_TEMP_MAX, message->getAttr(ENERGY_ATTR_I8::DIAG_AIR_TEMP_MAX)); + } + } + if (message->hasAttr(ENERGY_ATTR_I8::DIAG_AIR_TEMP_MIN)) + { + if (fullUpdate || message->hasChanged(ENERGY_ATTR_I8::DIAG_AIR_TEMP_MIN)) + { + publishi(ENERGY_SUBTOPIC, ENERGY_DIAG_AIR_TEMP_MIN, message->getAttr(ENERGY_ATTR_I8::DIAG_AIR_TEMP_MIN)); + } + } + if (message->hasAttr(ENERGY_ATTR_I8::DIAG_EVA_UPPER_AIR_TEMP_MAX)) + { + if (fullUpdate || message->hasChanged(ENERGY_ATTR_I8::DIAG_EVA_UPPER_AIR_TEMP_MAX)) + { + publishi( + ENERGY_SUBTOPIC, + ENERGY_DIAG_EVA_UPPER_AIR_TEMP_MAX, + message->getAttr(ENERGY_ATTR_I8::DIAG_EVA_UPPER_AIR_TEMP_MAX)); + } + } + if (message->hasAttr(ENERGY_ATTR_I8::DIAG_EVA_UPPER_AIR_TEMP_MIN)) + { + if (fullUpdate || message->hasChanged(ENERGY_ATTR_I8::DIAG_EVA_UPPER_AIR_TEMP_MIN)) + { + publishi( + ENERGY_SUBTOPIC, + ENERGY_DIAG_EVA_UPPER_AIR_TEMP_MIN, + message->getAttr(ENERGY_ATTR_I8::DIAG_EVA_UPPER_AIR_TEMP_MIN)); + } + } + if (message->hasAttr(ENERGY_ATTR_I8::DIAG_EVA_LOWER_AIR_TEMP_MAX)) + { + if (fullUpdate || message->hasChanged(ENERGY_ATTR_I8::DIAG_EVA_LOWER_AIR_TEMP_MAX)) + { + publishi( + ENERGY_SUBTOPIC, + ENERGY_DIAG_EVA_LOWER_AIR_TEMP_MAX, + message->getAttr(ENERGY_ATTR_I8::DIAG_EVA_LOWER_AIR_TEMP_MAX)); + } + } + if (message->hasAttr(ENERGY_ATTR_I8::DIAG_EVA_LOWER_AIR_TEMP_MIN)) + { + if (fullUpdate || message->hasChanged(ENERGY_ATTR_I8::DIAG_EVA_LOWER_AIR_TEMP_MIN)) + { + publishi( + ENERGY_SUBTOPIC, + ENERGY_DIAG_EVA_LOWER_AIR_TEMP_MIN, + message->getAttr(ENERGY_ATTR_I8::DIAG_EVA_LOWER_AIR_TEMP_MIN)); + } + } + if (message->hasAttr(ENERGY_ATTR_I8::DIAG_COMPRESSOR_TEMP_MAX)) + { + if (fullUpdate || message->hasChanged(ENERGY_ATTR_I8::DIAG_COMPRESSOR_TEMP_MAX)) + { + publishi( + ENERGY_SUBTOPIC, + ENERGY_DIAG_COMPRESSOR_TEMP_MAX, + message->getAttr(ENERGY_ATTR_I8::DIAG_COMPRESSOR_TEMP_MAX)); + } + } + if (message->hasAttr(ENERGY_ATTR_I8::DIAG_COMPRESSOR_TEMP_MIN)) + { + if (fullUpdate || message->hasChanged(ENERGY_ATTR_I8::DIAG_COMPRESSOR_TEMP_MIN)) + { + publishi( + ENERGY_SUBTOPIC, + ENERGY_DIAG_COMPRESSOR_TEMP_MIN, + message->getAttr(ENERGY_ATTR_I8::DIAG_COMPRESSOR_TEMP_MIN)); + } + } + if (message->hasAttr(ENERGY_ATTR_I8::DIAG_WATER_TEMP_MAX)) + { + if (fullUpdate || message->hasChanged(ENERGY_ATTR_I8::DIAG_WATER_TEMP_MAX)) + { + publishi( + ENERGY_SUBTOPIC, + ENERGY_DIAG_WATER_TEMP_MAX, + message->getAttr(ENERGY_ATTR_I8::DIAG_WATER_TEMP_MAX)); + } + } + if (message->hasAttr(ENERGY_ATTR_I8::DIAG_WATER_TEMP_MIN)) + { + if (fullUpdate || message->hasChanged(ENERGY_ATTR_I8::DIAG_WATER_TEMP_MIN)) + { + publishi( + ENERGY_SUBTOPIC, + ENERGY_DIAG_WATER_TEMP_MIN, + message->getAttr(ENERGY_ATTR_I8::DIAG_WATER_TEMP_MIN)); + } + } + if (config::DEBUG_RAW_SERIAL_MESSAGES) { sprintf(reinterpret_cast(mTopicBuffer), @@ -1474,13 +1569,9 @@ void MQTTTask::publishFiltered( auto previousFilteredValue = mFilteredValue; mFilteredValue = std::round(filter.updateEstimate(rawValue) * 10.0f) / 10.0f; - if (fullUpdate) { - publishFloat( - MAIN_SUBTOPIC, - topic, - config::MQTT_FILTER_TEMPERATURE_NOISE ? mFilteredValue : rawValue); + publishFloat(MAIN_SUBTOPIC, topic, config::MQTT_FILTER_TEMPERATURE_NOISE ? mFilteredValue : rawValue); } else if (!config::MQTT_FILTER_TEMPERATURE_NOISE && message->hasChanged(attribute)) { diff --git a/DEVICES.md b/DEVICES.md index 0bf479a..96ba5c0 100644 --- a/DEVICES.md +++ b/DEVICES.md @@ -4,21 +4,16 @@ These devices have been tested succesfully by the community. Currently there are no insights if the software version indicitates compatibilty to the AquaMQTT implementation. -| Name | HMI Software Version | Controller Software Version | Observed Protocol Version | Other Information | -|--------------------------|----------------------|-----------------------------|------------------|-------------------| -| Windhager Aquawin Air 3 | B | B | [LEGACY](PROTOCOL.md) | | -| [Atlantic Explorer V4](https://github.com/tspopp/AquaMQTT/issues/14) | B | B | [LEGACY](PROTOCOL.md) | | -| [Austria Email Explorer Evo 2](https://github.com/tspopp/AquaMQTT/issues/22) | ? | ? | [LEGACY](PROTOCOL.md) | [PCB adapter is recommended](./pcb) | -| [Thermor Aeromax 5](https://github.com/tspopp/AquaMQTT/issues/18) | ? | ? | [LEGACY](PROTOCOL.md) | [PCB adapter is recommended](./pcb) -| [Thermor Aeromax 5](https://github.com/tspopp/AquaMQTT/issues/51) | E |G | [LEGACY](PROTOCOL.md) | - - -## Incompatible Devices - -| Name | HMI Software Version | Controller Software Version | Observed Protocol Version | Other Information | -|--------------------------|----------------------|-----------------------------|------------------|-------------------| -| [Austria Email BWWP 200 WT SMART COZY](https://github.com/tspopp/AquaMQTT/issues/45) | E | E | NEXT | [In Development](https://github.com/tspopp/AquaMQTT/pull/52) - +| Name | HMI Software Version | Controller Software Version | Observed Protocol Version | Other Information | +|----------------------------------------------------------------------------------------------------|----------------------|-----------------------------|---------------------------|-------------------------------------| +| Windhager Aquawin Air 3 | B | B | [LEGACY](PROTOCOL.md) | | +| [Atlantic Explorer V4](https://github.com/tspopp/AquaMQTT/issues/14) | B | B | [LEGACY](PROTOCOL.md) | | +| [Austria Email Explorer Evo 2](https://github.com/tspopp/AquaMQTT/issues/22) | ? | ? | [LEGACY](PROTOCOL.md) | | +| [Thermor Aeromax 5](https://github.com/tspopp/AquaMQTT/issues/18) | ? | ? | [LEGACY](PROTOCOL.md) | [PCB adapter is recommended](./pcb) | +| [Thermor Aeromax 5](https://github.com/tspopp/AquaMQTT/issues/51) | E | G | [LEGACY](PROTOCOL.md) | [PCB adapter is recommended](./pcb) | +| [Austria Email BWWP 200 WT SMART COZY (taloriko)](https://github.com/tspopp/AquaMQTT/issues/45) | E | E | [NEXT](PROTOCOL_NEXT.md) | | +| [Atlantic Explorer 270/V3 (Silmo)](https://github.com/tspopp/AquaMQTT/pull/52) | E | E | [NEXT](PROTOCOL_NEXT.md) | | +| [Atlantic Explorer (ALENOC)](https://github.com/tspopp/AquaMQTT/issues/14#issuecomment-2501636900) | E | E | [NEXT](PROTOCOL_NEXT.md) | | ## Potential compatible devices diff --git a/MQTT.md b/MQTT.md index c1fc3c6..b20c530 100644 --- a/MQTT.md +++ b/MQTT.md @@ -89,17 +89,28 @@ Using the prefix, the `$root` topic is created, which is `$prefix/aquamqtt/` and ### Energy Message -| Value | MQTT Topic | Format | Unit | Other Information | [LEGACY](./PROTOCOL.md) | [NEXT](./PROTOCOL_NEXT.md) | -|-------------------------------|--------------------------------------|--------|------|------------------------------------------------------------------------------------------------------------|--------------------------|----------------------------| -| Total Heatpump Hours | `$root/energy/totalHeatpumpHours` | uint32 | h | retained | :heavy_check_mark: | :heavy_check_mark: | -| Total Heating Element Hours | `$root/energy/totalHeatingElemHours` | uint32 | h | retained | :heavy_check_mark: | :x: | -| Total Hours | `$root/energy/totalHours` | uint32 | h | retained | :heavy_check_mark: | :heavy_check_mark: | -| Total Energy | `$root/energy/totalEnergyWh` | uint64 | Wh | | :heavy_check_mark: | :x: | -| Total Water Production | `$root/energy/totalWaterProduction` | uint16 | l | Note: Expected to wrap-around at UINT16_MAX | :heavy_check_mark: | :x: | -| Current Power Heatpump | `$root/energy/powerHeatpump` | uint16 | W | Note: It is possible to define an additional custom mqtt topic for this attribute within `Configuration.h` | :heavy_check_mark: | :heavy_check_mark: | -| Current Power Heating Element | `$root/energy/powerHeatingElem` | uint16 | W | Note: It is possible to define an additional custom mqtt topic for this attribute within `Configuration.h` | :heavy_check_mark: | :x: | -| Current Power Total | `$root/energy/powerTotal` | uint16 | W | | :heavy_check_mark: | :x: | -| Raw Message (Debug Mode Only) | `$root/energy/debug` | string | | | :heavy_check_mark: | :heavy_check_mark: | +| Value | MQTT Topic | Format | Unit | Other Information | [LEGACY](./PROTOCOL.md) | [NEXT](./PROTOCOL_NEXT.md) | +|------------------------------------------------|--------------------------------------|--------|------|------------------------------------------------------------------------------------------------------------|-------------------------|----------------------------| +| Total Heatpump Hours | `$root/energy/totalHeatpumpHours` | uint32 | h | retained | :heavy_check_mark: | :heavy_check_mark: | +| Total Heating Element Hours | `$root/energy/totalHeatingElemHours` | uint32 | h | retained | :heavy_check_mark: | :heavy_check_mark: | +| Total Hours | `$root/energy/totalHours` | uint32 | h | retained | :heavy_check_mark: | :x: | +| Total Energy | `$root/energy/totalEnergyWh` | uint64 | Wh | | :heavy_check_mark: | :heavy_check_mark: | +| Total Water Production | `$root/energy/totalWaterProduction` | uint16 | l | Note: Expected to wrap-around at UINT16_MAX | :heavy_check_mark: | :x: | +| Current Power Heatpump | `$root/energy/powerHeatpump` | uint16 | W | Note: It is possible to define an additional custom mqtt topic for this attribute within `Configuration.h` | :heavy_check_mark: | :x: | +| Current Power Heating Element | `$root/energy/powerHeatingElem` | uint16 | W | Note: It is possible to define an additional custom mqtt topic for this attribute within `Configuration.h` | :heavy_check_mark: | :x: | +| Current Power Total | `$root/energy/powerTotal` | uint16 | W | | :heavy_check_mark: | :heavy_check_mark: | +| Observed Maximum Air Temperature | `$root/energy/diagAirTempMax` | int8 | °C | | :x: | :heavy_check_mark: | +| Observed Minimum Air Temperature | `$root/energy/diagAirTempMin` | int8 | °C | | :x: | :heavy_check_mark: | +| Observed Maximum Evaporator Upper Temperature | `$root/energy/diagEvaUpperMax` | int8 | °C | | :x: | :heavy_check_mark: | +| Observed Minimum Evaporator Upper Temperature | `$root/energy/diagEvaUpperMin` | int8 | °C | | :x: | :heavy_check_mark: | +| Observed Maximum Evaporator Lower Temperature | `$root/energy/diagEvaLowerMax` | int8 | °C | | :x: | :heavy_check_mark: | +| Observed Minimum Evaporator Lower Temperature | `$root/energy/diagEvaLowerMin` | int8 | °C | | :x: | :heavy_check_mark: | +| Observed Maximum Compressor Outlet Temperature | `$root/energy/diagCompressorMax` | int8 | °C | | :x: | :heavy_check_mark: | +| Observed Minimum Compressor Outlet Temperature | `$root/energy/diagCompressorMin` | int8 | °C | | :x: | :heavy_check_mark: | +| Observed Maximum Water Temperature | `$root/energy/diagWaterTempMax` | int8 | °C | | :x: | :heavy_check_mark: | +| Observed Minimum Water Temperature | `$root/energy/diagWaterTempMin` | int8 | °C | | :x: | :heavy_check_mark: | +| Raw Message (Debug Mode Only) | `$root/energy/debug` | string | | | :x: | :heavy_check_mark: | + ### Error Messages diff --git a/PROTOCOL_NEXT.md b/PROTOCOL_NEXT.md index 5a73388..4d920a3 100644 --- a/PROTOCOL_NEXT.md +++ b/PROTOCOL_NEXT.md @@ -1,14 +1,17 @@ # Protocol (NEXT) -Another heat pump protocol observed in https://github.com/tspopp/AquaMQTT/issues/45 with an _Austria Email BWWP 200 WT SMART COZY_ heat pump. +Another heat pump protocol observed in https://github.com/tspopp/AquaMQTT/issues/45 with an _Austria Email BWWP 200 WT SMART COZY_ and _Atlantic Explorer v3_ heat pump. Further information in https://github.com/tspopp/AquaMQTT/pull/52. + +For distinction with the original (LEGACY) implementation we refer to this Protocol as **Protocol NEXT**. ## Message Format ``` -ID LEN PAYLOAD CHECKSUM -C1 23 2E00230018001800150000000000000000000000008200000000454528CB000E0111 44 -C2 22 32120000001000062C01D0020000003A211E0C0C000000004E450000060422013E FA -43 2D 0000071D0000000000000000071D0000EEB2390000000000000000000B4C105AFB27FB250B1B000000000000 57 +ID LEN PAYLOAD CHECKSUM +C1 23 2E00230018001800150000000000000000000000008200000000454528CB000E0111 44 +C2 22 32120000001000062C01D0020000003A211E0C0C000000004E450000060422013E FA +43 2D 0000071D0000000000000000071D0000EEB2390000000000000000000B4C105AFB27FB250B1B000000000000 57 +4A 41 0D0F2D00270015001800130000000000000000020000000000671D00000200000045110000581100007A2200000800000002000000211E000C00320000000008 6B ``` ## Identifier @@ -39,42 +42,42 @@ static uint8_t generateNextChecksum(const uint8_t* buffer, uint8_t length){ ### HMI Message (194) -| Byte Number | Example (dec) | Purpose/Function | Other Information | -|-------------|---------------|--------------------------------|-------------------| -| 0 | 34 | Length Field | | -| 1 | 50 | Water Target Temperature | | -| 2 | 18 | Operation Mode, Operation Type | See table below | -| 3 | 0 | ? | | -| 4 | 0 | Anti-Legionella Mode / AirDuct Mode | See table below | -| 5 | 0 | Emergency-Mode | 0 == inactive, 1 == active | -| 6 | 0 | InstallationConfig | WP-Only == 0, WP+ExtBoiler-Prio-WP == 1, Wp+ExtBoiler-Opt-WP == 17, Wp+ExtBoiler-Opt-ExtBoiler == 33 , Wp+ExtBoiler-Prio-ExtBoiler == 49 , WP + Solar == 50| -| 7 | 0 | ExhaustFanConfig | Only AirDuct EXT/INT 0 == off, 1 == slow, 2 == fast | -| 8 | 6 | Heating-Element | 0 == Automatic, 4 == locked, 6 == PV System "Smart-Grid" Yes | -| 9 | 44 | Timer Mode: Window 1 Start | Byte 1/2 --> See table below | -| 10 | 1 | Timer Mode: Window 1 Start | Byte 2/2 --> 44 + 256 = 300 / 60 = 5 --> 05:00 | -| 11 | 240 | Timer Mode: Window 1 Length | Byte 1/2 --> See table below | -| 12 | 0 | Timer Mode: Window 1 Length | Byte 2/2 --> 240 + 0 = 240 / 60 = 4 --> 4h | -| 13 | 14 | Absence Days | If the start is in the future, the value will only become visible then | -| 14 | 7 | Boost Days | 7 Days max | -| 15 | 0 | ? | | -| 16 | 59 | Time Seconds | | -| 17 | 33 | Date Day, Month | | -| 18 | 30 | Date Year, Month | | -| 19 | 12 | Time Minutes | | -| 20 | 12 | Time Hours | | -| 21 | 8 | TestMode Status | 1 == Heating-Element, 2 == Compressor, 8 == Fan, 32 == Defrost-Valve | -| 22 | 50 | TestMode Fanspeed | 0 == standstill, 50 == slow, 100 == fast | -| 23 | 0 | ? | | -| 24 | 0 | ? | | -| 25 | 78 | ? | | -| 26 | 69 | ? | | -| 27 | 0 | Error Number Requested | | -| 28 | 0 | Error Request Id | | -| 29 | 60 | Timer Mode: Window 2 Start | Byte 1/2 --> See table below | -| 30 | 0 | Timer Mode: Window 2 Start | Byte 2/2 --> 60 + 0 = 60 / 60 = 1 == 01:00 | -| 31 | 240 | Timer Mode: Window 2 Length | Byte 1/2 --> See table below | -| 32 | 0 | Timer Mode: Window 2 Length | Byte 2/2 --> 240 + 0 = 240 / 60 = 4 == 4h | -| 33 | 62 | ? | | +| Byte Number | Example (dec) | Purpose/Function | Other Information | +|-------------|---------------|-------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0 | 34 | Length Field | | +| 1 | 50 | Water Target Temperature | | +| 2 | 18 | Operation Mode, Operation Type | See table below | +| 3 | 0 | ? | | +| 4 | 0 | Anti-Legionella Mode / AirDuct Mode | See table below | +| 5 | 0 | Emergency-Mode | 0 == inactive, 1 == active | +| 6 | 0 | InstallationConfig | WP-Only == 0, WP+ExtBoiler-Prio-WP == 1, Wp+ExtBoiler-Opt-WP == 17, Wp+ExtBoiler-Opt-ExtBoiler == 33 , Wp+ExtBoiler-Prio-ExtBoiler == 49 , WP + Solar == 50 | +| 7 | 0 | ExhaustFanConfig | Only AirDuct EXT/INT 0 == off, 1 == slow, 2 == fast | +| 8 | 6 | Heating-Element | 0 == Automatic, 4 == locked, 6 == PV System "Smart-Grid" Yes | +| 9 | 44 | Timer Mode: Window 1 Start | Byte 1/2 --> See table below | +| 10 | 1 | Timer Mode: Window 1 Start | Byte 2/2 --> 44 + 256 = 300 / 60 = 5 --> 05:00 | +| 11 | 240 | Timer Mode: Window 1 Length | Byte 1/2 --> See table below | +| 12 | 0 | Timer Mode: Window 1 Length | Byte 2/2 --> 240 + 0 = 240 / 60 = 4 --> 4h | +| 13 | 14 | Absence Days | If the start is in the future, the value will only become visible then | +| 14 | 7 | Boost Days | 7 Days max | +| 15 | 0 | Command | 0x02 -> Reset statistics | +| 16 | 59 | Time Seconds | | +| 17 | 33 | Date Day, Month | | +| 18 | 30 | Date Year, Month | | +| 19 | 12 | Time Minutes | | +| 20 | 12 | Time Hours | | +| 21 | 8 | TestMode Status | 1 == Heating-Element, 2 == Compressor, 8 == Fan, 32 == Defrost-Valve | +| 22 | 50 | TestMode Fanspeed | 0 == standstill, 50 == slow, 100 == fast | +| 23 | 0 | ? | | +| 24 | 0 | ? | | +| 25 | 78 | ? | | +| 26 | 69 | ? | | +| 27 | 0 | Error Number Requested | | +| 28 | 0 | Error Request Id | | +| 29 | 60 | Timer Mode: Window 2 Start | Byte 1/2 --> See table below | +| 30 | 0 | Timer Mode: Window 2 Start | Byte 2/2 --> 60 + 0 = 60 / 60 = 1 == 01:00 | +| 31 | 240 | Timer Mode: Window 2 Length | Byte 1/2 --> See table below | +| 32 | 0 | Timer Mode: Window 2 Length | Byte 2/2 --> 240 + 0 = 240 / 60 = 4 == 4h | +| 33 | 62 | ? | | ##### Byte No. 2: Operation Mode @@ -82,78 +85,66 @@ static uint8_t generateNextChecksum(const uint8_t* buffer, uint8_t length){ | Bit Number | Purpose/Function | Other Information | |------------|------------------|----------------------------------------------------------------------------------------| | 0 - 3 | Operation Mode | Interpreted as integer, 0 == Auto, 1 == ECO ON, 2 == ECO OFF, 5 == Absence, 9 == BOOST | -| 4 - 7 | Operation Type | Interpreted as integer, 1 == Timer, 4 == Continious | +| 4 - 7 | Operation Type | Interpreted as integer, 1 == Timer, 4 == Continuous | ##### Byte No. 4: Anti-Legionella Mode / AirDuct Mode -| Bit Number | Purpose/Function | Other Information | -|------------|------------------|----------------------------------------------------------------------------------------| -| 0 - 3 | Anti-Legionella Mode | Interpreted as integer, 0 == Off, 1 == 1perMonth, 2 == 2perMonth, 3 == 3perMonth, 4 == 4/perMonth | -| 4 - 7 | AirDuct Mode | Interpreted as integer, 0 == AirDuct INT/INT, 1 == AirDuct EXT/INT, 2 == AirDuct EXT/EXT | +| Bit Number | Purpose/Function | Other Information | +|------------|----------------------|---------------------------------------------------------------------------------------------------| +| 0 - 3 | Anti-Legionella Mode | Interpreted as integer, 0 == Off, 1 == 1perMonth, 2 == 2perMonth, 3 == 3perMonth, 4 == 4/perMonth | +| 4 - 7 | AirDuct Mode | Interpreted as integer, 0 == AirDuct INT/INT, 1 == AirDuct EXT/INT, 2 == AirDuct EXT/EXT | ##### Byte No. 9-12 + 29-32: Time Window: Setting limitations: -| | Information| -|-------------|---------------| -| One Time Window | Minimum duration of 8 hours, maximum duration of 12 hours | -| Two Time Windows | Each at least 4 hours, combined maximum of 20 hours | -| Disable the second Time Window | Set the end time to less than 4 hours | - - -## Help Required: - -- *TODO: OperationMode: ~~Boost, Eco On, Eco Off, Auto, Absence~~* -- *TODO: TimerWindow ~~A/B~~* -- *TODO: Anti-Legionalla ~~Setting~~* -- *TODO: AirDuct Config: ~~INT/INT, EXT/INT, EXT/EXT~~* -- *TODO: Installation Config: ~~IWP-Only, WP+ExtBoiler-Prio-WP,...~~* -- *TODO: Exhaust Fan Config:~~(Only in EXT/INT): STOP, LOW-SPEED, HIGH-SPEED~~* -- *TODO: Heating Element ~~Enabled On/Off/PV~~* -- *TODO: PV Mode allowed ~~On/Off~~* +| | Information | +|--------------------------------|-----------------------------------------------------------| +| One Time Window | Minimum duration of 8 hours, maximum duration of 12 hours | +| Two Time Windows | Each at least 4 hours, combined maximum of 20 hours | +| Disable the second Time Window | Set the end time to less than 4 hours | ### Main Message (193) -| Byte Number | Example (dec) | Purpose/Function | Other Information | -|-------------|---------------|------------------|-------------------| -| 0 | 35 | Length Field | | -| 1 | 46 | Hot Water Temp | | -| 2 | 0 | ? | | -| 3 | 35 | Compressor Outlet Temp | | -| 4 | 0 | ? | | -| 5 | 24 | Upper Evaporator Temp | | -| 6 | 0 | ? | | -| 7 | 24 | Lower Evaporator Temp | | -| 8 | 0 | ? | | -| 9 | 21 | Input Air Temp | | -| 10 | 0 | ? | | -| 11 | 0 | ? | | -| 12 | 0 | ? | | -| 13 | 0 | ? | | -| 14 | 0 | ? | | -| 15 | 0 | ? | | -| 16 | 0 | ? | | -| 17 | 0 | Picture Bitmask | See table below | -| 18 | 50 | Fan-Speed | 50 == low, 100 == high | -| 19 | 0 | ? | | -| 20 | 0 | ? | | -| 21 | 0 | ? | | +| Byte Number | Example (dec) | Purpose/Function | Other Information | +|-------------|---------------|---------------------------|----------------------------------------------------------| +| 0 | 35 | Length Field | | +| 1 | 46 | Hot Water Temp | | +| 2 | 0 | ? | | +| 3 | 35 | Compressor Outlet Temp | | +| 4 | 0 | ? | | +| 5 | 24 | Upper Evaporator Temp | | +| 6 | 0 | ? | | +| 7 | 24 | Lower Evaporator Temp | | +| 8 | 0 | ? | | +| 9 | 21 | Input Air Temp | | +| 10 | 0 | ? | | +| 11 | 0 | ? | | +| 12 | 0 | ? | | +| 13 | 0 | ? | | +| 14 | 0 | ? | | +| 15 | 0 | ? | | +| 16 | 0 | ? | | +| 17 | 0 | Picture Bitmask | See table below | +| 18 | 50 | Fan-Speed | 50 == low, 100 == high | +| 19 | 0 | ? | | +| 20 | 0 | ? | | +| 21 | 0 | ? | | | 22 | 20 | State: PV and Solar Input | 20 == PV Enabled and Active, ?? == Solar Input Triggered | -| 23 | 0 | ? | | -| 24 | 0 | ? | | -| 25 | 0 | ? | | -| 26 | 0 | ? | | -| 27 | 69 | ? | | -| 28 | 69 | ? | | -| 29 | 40 | ? | | -| 30 | 203 | ? | | -| 31 | 0 | ? | | -| 32 | 14 | ? | | -| 33 | 1 | ? | | -| 34 | 17 | ? | | +| 23 | 0 | ? | | +| 24 | 0 | ? | | +| 25 | 0 | ? | | +| 26 | 0 | ? | | +| 27 | 69 | ? | | +| 28 | 69 | ? | | +| 29 | 40 | ? | | +| 30 | 203 | ? | | +| 31 | 0 | ? | | +| 32 | 14 | ? | | +| 33 | 1 | ? | | +| 34 | 17 | ? | | ##### Byte No 17: Picture Bitmask @@ -179,9 +170,9 @@ Findings... |------------|------------------------|-------------------| | 0 | Heating Element On/Off | | | 1 | Heatpump On/Off | | -| 2 | ? Boiler Backup On/Off | | +| 2 | ? Boiler Backup On/Off | | | 3 | Fan On/Off. | | -| 4 | ? Aktiv | | +| 4 | ? Aktiv | | | 5 | Defrost On/Off | | | 6 | ? | | | 7 | ? | | @@ -189,89 +180,57 @@ Findings... ## Help Required: -_To identify this attributes within the message, try to locate the information within the HMI controller, -and provide a photo of the HMI controller together with a dump of the *main* message. We should find the values shown in the HMI controller within the message. -For determining the values from super secret menu, you change a setting in the super secret menu of the hmi controller and watch the change of main message._ - -- *TODO: ~~Hot Water Temp~~* -- *TODO: ~~Input Air Temp~~* -- *TODO: ~~Lower Evaporator Temp~~* -- *TODO: ~~Upper Evaporator Temp~~* -- *TODO: PWM Level Settings (Super Secret Menu)* --> Option not available -- *TODO: Status Bitmask (Fan On/Off, Defrost On/Off, PV On/Off, Solar On/Off, HeatElement On/Off, HeatPump On/Off, Boiler Backup On/Off)* -- *TODO: Current Fan PWM Level* --> Only two levels possible: low and high -- *TODO: Min T Target (Super Secret Menu)* --> Option not available -- *TODO: Anti-Legionella T Target (Super Secret Menu)* --> Option not available - *TODO: Error Codes* -- *TODO: Wattage Heat Element (Super Secret Menu)* --> Option not available -- *TODO: Boiler Capacity (Super Secret Menu)* --> Option not available -- *TODO: Brand (Super Secret Menu)* --> Option not available -- *TODO: Setting Bitflags (Super Secret Menu)* --> Option not available ### Energy Message (67) -| Byte Number | Example (dec) | Purpose/Function | Other Information | -|-------------|---------------|------------------|-------------------| -| 0 | 45 | Length Field | | -| 1 | 0 | ? | | -| 2 | 0 | ? | | -| 3 | 7 | Total Operation Hours (Heatpump) | Byte 1/2 | -| 4 | 29 | Total Operation Hours (Heatpump) | Byte 2/2 --> (29x256) + 7 = 7431h | -| 5 | 0 | ? | | -| 6 | 0 | ? | | -| 7 | 0 | ? | | -| 8 | 0 | ? | | -| 9 | 0 | ? | | -| 10 | 0 | ? | | -| 11 | 0 | ? | | -| 12 | 0 | ? | | -| 13 | 7 | Total Operation Hours (Heatpump) | The same as Byte 3+4 or for a reset? | -| 14 | 29 | Total Operation Hours (Heatpump) | The same as Byte 3+4 or for a reset? | -| 15 | 0 | ? | | -| 16 | 0 | ? | | -| 17 | 238 | ? | | -| 18 | 178 | ? | | -| 19 | 57 | ? | | -| 20 | 0 | ? | | -| 21 | 251 | Power Consumption Heatpump | Byte 1/2 | -| 22 | 1 | Power Consumption Heatpump | Byte 2/2 --> (1x256) + 151 = 507W ???? | -| 23 | 0 | ? | | -| 24 | 0 | ? | | -| 25 | 0 | ? | | -| 26 | 0 | ? | | -| 27 | 0 | ? | | -| 28 | 0 | ? | | -| 29 | 11 | ? | | -| 30 | 76 | ? | | -| 31 | 16 | ? | | -| 32 | 90 | ? | | -| 33 | 251 | ? | | -| 34 | 39 | ? | | -| 35 | 251 | ? | | -| 36 | 37 | ? | | -| 37 | 11 | ? | | -| 38 | 27 | ? | | -| 39 | 0 | ? | | -| 40 | 0 | ? | | -| 41 | 0 | ? | | -| 42 | 0 | ? | | -| 43 | 0 | ? | | -| 44 | 0 | ? | | - - -## Help Required: - -_To identify this attributes within the message, try to locate the information within the HMI controller, -and provide a photo of the HMI controller together with a dump of the *energy* message. We should find the values shown in the HMI controller within the message._ - -- *TODO: Power Consumption Heatpump* --> Cannot be displayed on the HMI -- *TODO: Power Consumption Heating Element* --> Cannot be displayed on the HMI -- *TODO: Power Consumption Total (Both)* --> Cannot be displayed on the HMI -- *TODO: Total Water Production (l)* --> Cannot be displayed on the HMI -- *TODO: ~~Total Operation Hours (Heatpump)~~* -- *TODO: ~~Total Operation Hours (Heating Element)~~* -- *TODO: Total Operation Hours (Both)* --> Cannot be displayed on the HMI -- *TODO: Total Energy Counter (Wh)* --> Cannot be displayed on the HMI +| Byte Number | Example (dec) | Purpose/Function | Other Information | +|-------------|---------------|---------------------------------------------------|---------------------------------------------| +| 0 | 45 | Length Field | | +| 1 | 0 | Total Operation Hours (Heat-Element) Resetable(?) | | +| 2 | 0 | Total Operation Hours (Heat-Element) Resetable(?) | | +| 3 | 7 | Total Operation Hours (Heatpump) Resetable(?) | Byte 1/2 | +| 4 | 29 | Total Operation Hours (Heatpump) Resetable(?) | Byte 2/2 --> (29x256) + 7 = 7431h | +| 5 | 0 | ? | Unknown Downcounting Value C during warm-up | +| 6 | 0 | ? | Unknown Downcounting Value C during warm-up | +| 7 | 0 | ? | Unknown Downcounting Value C during warm-up | +| 8 | 0 | ? | Unknown Downcounting Value C during warm-up | +| 9 | 0 | Total Operation Hours (Heat-Element) Permanent(?) | | +| 10 | 0 | Total Operation Hours (Heat-Element) Permanent(?) | | +| 11 | 0 | Total Operation Hours (Heat-Element) Permanent(?) | | +| 12 | 0 | Total Operation Hours (Heat-Element) Permanent(?) | | +| 13 | 7 | Total Operation Hours (Heatpump) Permanent(?) | The same as Byte 3+4 or for a reset? | +| 14 | 29 | Total Operation Hours (Heatpump) Permanent(?) | The same as Byte 3+4 or for a reset? | +| 15 | 0 | Total Operation Hours (Heatpump) Permanent(?) | | +| 16 | 0 | Total Operation Hours (Heatpump) Permanent(?) | | +| 17 | 238 | Total Energy (Wh) | | +| 18 | 178 | Total Energy (Wh) | | +| 19 | 57 | Total Energy (Wh) | | +| 20 | 0 | Total Energy (Wh) | | +| 21 | 251 | Power Consumption Total (Heatpump + Heat-Element) | Byte 1/2 | +| 22 | 1 | Power Consumption Total (Heatpump + Heat-Element) | Byte 2/2 --> (1x256) + 151 = 507W ???? | +| 23 | 0 | ? | | +| 24 | 0 | ? | | +| 25 | 0 | ? | | +| 26 | 0 | ? | | +| 27 | 0 | ? | | +| 28 | 0 | ? | | +| 29 | 11 | Water Temp Min | | +| 30 | 76 | Water Temp Max | | +| 31 | 16 | CompressorOutlet Temp Min | | +| 32 | 90 | CompressorOutlet Temp Max | | +| 33 | 251 | EvaporatorLower Air Temp Min | | +| 34 | 39 | EvaporatorLower Air Temp Max | | +| 35 | 251 | Evaporator Air Temp Min | | +| 36 | 37 | Evaporator Air Temp Max | | +| 37 | 11 | Air Temp Min | | +| 38 | 27 | Air Temp Max | | +| 39 | 0 | ? | | +| 40 | 0 | ? | | +| 41 | 0 | ? | | +| 42 | 0 | ? | | +| 43 | 0 | ? | | +| 44 | 0 | ? | | ### Error Message (74) @@ -343,8 +302,6 @@ and provide a photo of the HMI controller together with a dump of the *energy* m | 63 | | ? | | | 64 | | ? | | -*TODO: ~~Requires a running AquaDebug raw trace while opening the [super secret menu](https://github.com/tspopp/AquaMQTT/issues/17) in the hmi controller.~~* - ### Not yet assignable - *TODO: Number of restarts* diff --git a/README.md b/README.md index e6e7d1b..14cd49e 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,11 @@ Unfortunately, I had no success pairing those solutions with my Windhager brande - [Troubleshooting / F.A.Q](./TROUBLESHOOTING.md) -- [Heat pump serial protocol](./PROTOCOL.md) +- [Compatible Devices](./DEVICES.md) + +- [Heat pump serial protocol (LEGACY)](./PROTOCOL.md) + +- [Heat pump serial protocol (NEXT)](./PROTOCOL_NEXT.md) - [Available MQTT Topics and Payloads](./MQTT.md)