From f544f01caac22bb9ba6f10a326db9eb651e006b8 Mon Sep 17 00:00:00 2001 From: Yurii Date: Sat, 30 Mar 2024 00:04:51 +0300 Subject: [PATCH] feat: polling of exhaust gas temperature (#42) and heating return temperature; added new sensors to HA --- src/HaHelper.h | 46 +++++++++++++++++++++++++++++++++++++++++++++ src/MqttTask.h | 2 ++ src/OpenThermTask.h | 36 +++++++++++++++++++++++++++++++++++ src/Settings.h | 2 ++ src/utils.h | 2 ++ 5 files changed, 88 insertions(+) diff --git a/src/HaHelper.h b/src/HaHelper.h index 4a54d38..1d105ef 100644 --- a/src/HaHelper.h +++ b/src/HaHelper.h @@ -1136,6 +1136,29 @@ public: return this->publish(this->getTopic(FPSTR(HA_ENTITY_SENSOR), F("heating_temp")).c_str(), doc); } + bool publishSensorHeatingReturnTemp(bool enabledByDefault = true) { + JsonDocument doc; + doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status")); + doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("state")); + doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.states.otStatus, 'online', 'offline') }}"); + doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all"); + doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; + doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectId(F("heating_return_temp")); + doc[FPSTR(HA_OBJECT_ID)] = this->getObjectId(F("heating_return_temp")); + doc[FPSTR(HA_ENTITY_CATEGORY)] = F("diagnostic"); + doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature"); + doc[FPSTR(HA_STATE_CLASS)] = F("measurement"); + doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = F("°C"); + doc[FPSTR(HA_NAME)] = F("Heating return temperature"); + doc[FPSTR(HA_ICON)] = F("mdi:radiator"); + doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state")); + doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.temperatures.heatingReturn|float(0)|round(2) }}"); + doc[FPSTR(HA_EXPIRE_AFTER)] = 120; + doc.shrinkToFit(); + + return this->publish(this->getTopic(FPSTR(HA_ENTITY_SENSOR), F("heating_return_temp")).c_str(), doc); + } + bool publishSensorDhwTemp(bool enabledByDefault = true) { JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status")); @@ -1159,6 +1182,29 @@ public: return this->publish(this->getTopic(FPSTR(HA_ENTITY_SENSOR), F("dhw_temp")).c_str(), doc); } + bool publishSensorExhaustTemp(bool enabledByDefault = true) { + JsonDocument doc; + doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status")); + doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("state")); + doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.states.otStatus, 'online', 'offline') }}"); + doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all"); + doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; + doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectId(F("exhaust_temp")); + doc[FPSTR(HA_OBJECT_ID)] = this->getObjectId(F("exhaust_temp")); + doc[FPSTR(HA_ENTITY_CATEGORY)] = F("diagnostic"); + doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature"); + doc[FPSTR(HA_STATE_CLASS)] = F("measurement"); + doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = F("°C"); + doc[FPSTR(HA_NAME)] = F("Exhaust temperature"); + doc[FPSTR(HA_ICON)] = F("mdi:smoke"); + doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state")); + doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.temperatures.exhaust|float(0)|round(2) }}"); + doc[FPSTR(HA_EXPIRE_AFTER)] = 120; + doc.shrinkToFit(); + + return this->publish(this->getTopic(FPSTR(HA_ENTITY_SENSOR), F("exhaust_temp")).c_str(), doc); + } + bool publishClimateHeating(byte minTemp = 20, byte maxTemp = 90, byte currentTempSource = HaHelper::TEMP_SOURCE_HEATING, bool enabledByDefault = true) { JsonDocument doc; diff --git a/src/MqttTask.h b/src/MqttTask.h index 0b7f5d9..4e4f954 100644 --- a/src/MqttTask.h +++ b/src/MqttTask.h @@ -370,6 +370,8 @@ protected: // temperatures this->haHelper->publishNumberIndoorTemp(); this->haHelper->publishSensorHeatingTemp(); + this->haHelper->publishSensorHeatingReturnTemp(false); + this->haHelper->publishSensorExhaustTemp(false); // buttons this->haHelper->publishButtonRestart(false); diff --git a/src/OpenThermTask.h b/src/OpenThermTask.h index f24a19e..84e8287 100644 --- a/src/OpenThermTask.h +++ b/src/OpenThermTask.h @@ -293,6 +293,12 @@ protected: // Get current heating temp updateHeatingTemp(); + // Get heating return temp + updateHeatingReturnTemp(); + + // Get exhaust temp + updateExhaustTemp(); + // Fault reset action if (vars.actions.resetFault) { @@ -655,6 +661,21 @@ protected: return true; } + bool updateExhaustTemp() { + unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest( + OpenThermRequestType::READ_DATA, + OpenThermMessageID::Texhaust, + 0 + )); + + if (!CustomOpenTherm::isValidResponse(response)) { + return false; + } + + vars.temperatures.exhaust = CustomOpenTherm::getFloat(response); + return true; + } + bool updateHeatingTemp() { unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest( OpenThermMessageType::READ_DATA, @@ -675,6 +696,21 @@ protected: return true; } + bool updateHeatingReturnTemp() { + unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest( + OpenThermMessageType::READ_DATA, + OpenThermMessageID::Tret, + 0 + )); + + if (!CustomOpenTherm::isValidResponse(response)) { + return false; + } + + vars.temperatures.heatingReturn = CustomOpenTherm::getFloat(response); + return true; + } + bool updateDhwTemp() { unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest( diff --git a/src/Settings.h b/src/Settings.h index 6576040..e24b1db 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -153,7 +153,9 @@ struct Variables { float indoor = 0.0f; float outdoor = 0.0f; float heating = 0.0f; + float heatingReturn = 0.0f; float dhw = 0.0f; + float exhaust = 0.0f; } temperatures; struct { diff --git a/src/utils.h b/src/utils.h index c17c6ed..c72c90b 100644 --- a/src/utils.h +++ b/src/utils.h @@ -998,7 +998,9 @@ void varsToJson(const Variables& src, JsonVariant dst) { dst["temperatures"]["indoor"] = roundd(src.temperatures.indoor, 2); dst["temperatures"]["outdoor"] = roundd(src.temperatures.outdoor, 2); dst["temperatures"]["heating"] = roundd(src.temperatures.heating, 2); + dst["temperatures"]["heatingReturn"] = roundd(src.temperatures.heatingReturn, 2); dst["temperatures"]["dhw"] = roundd(src.temperatures.dhw, 2); + dst["temperatures"]["exhaust"] = roundd(src.temperatures.exhaust, 2); dst["parameters"]["heatingEnabled"] = src.parameters.heatingEnabled; dst["parameters"]["heatingMinTemp"] = src.parameters.heatingMinTemp;