diff --git a/lib/HomeAssistantHelper/strings.h b/lib/HomeAssistantHelper/strings.h index d0ad108c..bffff92 100644 --- a/lib/HomeAssistantHelper/strings.h +++ b/lib/HomeAssistantHelper/strings.h @@ -52,6 +52,7 @@ const char HA_TEMPERATURE_COMMAND_TOPIC[] PROGMEM = "temperature_command_t const char HA_TEMPERATURE_COMMAND_TEMPLATE[] PROGMEM = "temperature_command_template"; const char HA_TEMPERATURE_STATE_TOPIC[] PROGMEM = "temperature_state_topic"; const char HA_TEMPERATURE_STATE_TEMPLATE[] PROGMEM = "temperature_state_template"; +const char HA_TEMPERATURE_UNIT[] PROGMEM = " temperature_unit"; const char HA_MODE_COMMAND_TOPIC[] PROGMEM = "mode_command_topic"; const char HA_MODE_COMMAND_TEMPLATE[] PROGMEM = "mode_command_template"; const char HA_MODE_STATE_TOPIC[] PROGMEM = "mode_state_topic"; diff --git a/src/HaHelper.h b/src/HaHelper.h index 256653e..5b5cf98 100644 --- a/src/HaHelper.h +++ b/src/HaHelper.h @@ -37,9 +37,13 @@ public: if (unit == UnitSystem::METRIC) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C); + doc[FPSTR(HA_MIN)] = 5; + doc[FPSTR(HA_MAX)] = 50; } else if (unit == UnitSystem::IMPERIAL) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F); + doc[FPSTR(HA_MIN)] = 41; + doc[FPSTR(HA_MAX)] = 122; } doc[FPSTR(HA_NAME)] = F("Emergency target temp"); @@ -48,8 +52,6 @@ public: doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.emergency.target|float(0)|round(1) }}"); doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set")); doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"emergency\": {\"target\" : {{ value }}}}"); - doc[FPSTR(HA_MIN)] = 5; - doc[FPSTR(HA_MAX)] = 50; doc[FPSTR(HA_STEP)] = 0.5; doc[FPSTR(HA_MODE)] = "box"; doc[FPSTR(HA_EXPIRE_AFTER)] = 120; @@ -309,9 +311,13 @@ public: if (unit == UnitSystem::METRIC) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C); + doc[FPSTR(HA_MIN)] = 0; + doc[FPSTR(HA_MAX)] = 99; } else if (unit == UnitSystem::IMPERIAL) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F); + doc[FPSTR(HA_MIN)] = 32; + doc[FPSTR(HA_MAX)] = 211; } doc[FPSTR(HA_NAME)] = F("Heating min temp"); @@ -320,8 +326,6 @@ public: doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.heating.minTemp|float(0)|round(1) }}"); doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set")); doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"heating\": {\"minTemp\" : {{ value }}}}"); - doc[FPSTR(HA_MIN)] = 0; - doc[FPSTR(HA_MAX)] = 99; doc[FPSTR(HA_STEP)] = 1; doc[FPSTR(HA_MODE)] = "box"; doc[FPSTR(HA_EXPIRE_AFTER)] = 120; @@ -340,9 +344,13 @@ public: if (unit == UnitSystem::METRIC) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C); + doc[FPSTR(HA_MIN)] = 1; + doc[FPSTR(HA_MAX)] = 100; } else if (unit == UnitSystem::IMPERIAL) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F); + doc[FPSTR(HA_MIN)] = 33; + doc[FPSTR(HA_MAX)] = 212; } doc[FPSTR(HA_NAME)] = F("Heating max temp"); @@ -351,8 +359,6 @@ public: doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.heating.maxTemp|float(0)|round(1) }}"); doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set")); doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"heating\": {\"maxTemp\" : {{ value }}}}"); - doc[FPSTR(HA_MIN)] = 1; - doc[FPSTR(HA_MAX)] = 100; doc[FPSTR(HA_STEP)] = 1; doc[FPSTR(HA_MODE)] = "box"; doc[FPSTR(HA_EXPIRE_AFTER)] = 120; @@ -510,9 +516,13 @@ public: if (unit == UnitSystem::METRIC) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C); + doc[FPSTR(HA_MIN)] = 0; + doc[FPSTR(HA_MAX)] = 99; } else if (unit == UnitSystem::IMPERIAL) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F); + doc[FPSTR(HA_MIN)] = 32; + doc[FPSTR(HA_MAX)] = 211; } doc[FPSTR(HA_NAME)] = F("DHW min temp"); @@ -521,8 +531,6 @@ public: doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.dhw.minTemp|float(0)|round(1) }}"); doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set")); doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"dhw\": {\"minTemp\" : {{ value }}}}"); - doc[FPSTR(HA_MIN)] = 0; - doc[FPSTR(HA_MAX)] = 99; doc[FPSTR(HA_STEP)] = 1; doc[FPSTR(HA_MODE)] = "box"; doc[FPSTR(HA_EXPIRE_AFTER)] = 120; @@ -541,9 +549,13 @@ public: if (unit == UnitSystem::METRIC) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C); + doc[FPSTR(HA_MIN)] = 1; + doc[FPSTR(HA_MAX)] = 100; } else if (unit == UnitSystem::IMPERIAL) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F); + doc[FPSTR(HA_MIN)] = 33; + doc[FPSTR(HA_MAX)] = 212; } doc[FPSTR(HA_NAME)] = F("DHW max temp"); @@ -552,8 +564,6 @@ public: doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.dhw.maxTemp|float(0)|round(1) }}"); doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set")); doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"dhw\": {\"maxTemp\" : {{ value }}}}"); - doc[FPSTR(HA_MIN)] = 1; - doc[FPSTR(HA_MAX)] = 100; doc[FPSTR(HA_STEP)] = 1; doc[FPSTR(HA_MODE)] = "box"; doc[FPSTR(HA_EXPIRE_AFTER)] = 120; @@ -680,9 +690,13 @@ public: if (unit == UnitSystem::METRIC) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C); + doc[FPSTR(HA_MIN)] = 0; + doc[FPSTR(HA_MAX)] = 99; } else if (unit == UnitSystem::IMPERIAL) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F); + doc[FPSTR(HA_MIN)] = 0; + doc[FPSTR(HA_MAX)] = 211; } doc[FPSTR(HA_NAME)] = F("PID min temp"); @@ -691,8 +705,6 @@ public: doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.pid.minTemp|float(0)|round(1) }}"); doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set")); doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"pid\": {\"minTemp\" : {{ value }}}}"); - doc[FPSTR(HA_MIN)] = 0; - doc[FPSTR(HA_MAX)] = 99; doc[FPSTR(HA_STEP)] = 1; doc[FPSTR(HA_MODE)] = "box"; doc[FPSTR(HA_EXPIRE_AFTER)] = 120; @@ -711,9 +723,13 @@ public: if (unit == UnitSystem::METRIC) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C); + doc[FPSTR(HA_MIN)] = 1; + doc[FPSTR(HA_MAX)] = 100; } else if (unit == UnitSystem::IMPERIAL) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F); + doc[FPSTR(HA_MIN)] = 1; + doc[FPSTR(HA_MAX)] = 212; } doc[FPSTR(HA_NAME)] = F("PID max temp"); @@ -722,8 +738,6 @@ public: doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.pid.maxTemp|float(0)|round(1) }}"); doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set")); doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"pid\": {\"maxTemp\" : {{ value }}}}"); - doc[FPSTR(HA_MIN)] = 1; - doc[FPSTR(HA_MAX)] = 100; doc[FPSTR(HA_STEP)] = 1; doc[FPSTR(HA_MODE)] = "box"; doc[FPSTR(HA_EXPIRE_AFTER)] = 120; @@ -1141,9 +1155,13 @@ public: if (unit == UnitSystem::METRIC) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C); + doc[FPSTR(HA_MIN)] = -99; + doc[FPSTR(HA_MAX)] = 99; } else if (unit == UnitSystem::IMPERIAL) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F); + doc[FPSTR(HA_MIN)] = -147; + doc[FPSTR(HA_MAX)] = 211; } doc[FPSTR(HA_NAME)] = F("Indoor temperature"); @@ -1152,8 +1170,6 @@ public: doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.temperatures.indoor|float(0)|round(1) }}"); doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("state/set")); doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"temperatures\": {\"indoor\":{{ value }}}}"); - doc[FPSTR(HA_MIN)] = -99; - doc[FPSTR(HA_MAX)] = 99; doc[FPSTR(HA_STEP)] = 0.01; doc[FPSTR(HA_MODE)] = "box"; doc[FPSTR(HA_EXPIRE_AFTER)] = 120; @@ -1198,9 +1214,13 @@ public: if (unit == UnitSystem::METRIC) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C); + doc[FPSTR(HA_MIN)] = -99; + doc[FPSTR(HA_MAX)] = 99; } else if (unit == UnitSystem::IMPERIAL) { doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F); + doc[FPSTR(HA_MIN)] = -147; + doc[FPSTR(HA_MAX)] = 211; } doc[FPSTR(HA_NAME)] = F("Outdoor temperature"); @@ -1209,8 +1229,6 @@ public: doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.temperatures.outdoor|float(0)|round(1) }}"); doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("state/set")); doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"temperatures\": {\"outdoor\":{{ value }}}}"); - doc[FPSTR(HA_MIN)] = -99; - doc[FPSTR(HA_MAX)] = 99; doc[FPSTR(HA_STEP)] = 0.01; doc[FPSTR(HA_MODE)] = "box"; doc[FPSTR(HA_EXPIRE_AFTER)] = 120; @@ -1367,7 +1385,7 @@ public: } - bool publishClimateHeating(byte minTemp = 20, byte maxTemp = 90, byte currentTempSource = HaHelper::TEMP_SOURCE_HEATING, bool enabledByDefault = true) { + bool publishClimateHeating(UnitSystem unit = UnitSystem::METRIC, byte minTemp = 20, byte maxTemp = 90, byte currentTempSource = HaHelper::TEMP_SOURCE_HEATING, bool enabledByDefault = true) { JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status")); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; @@ -1393,6 +1411,13 @@ public: doc[FPSTR(HA_TEMPERATURE_STATE_TOPIC)] = this->getDeviceTopic(F("settings")); doc[FPSTR(HA_TEMPERATURE_STATE_TEMPLATE)] = F("{{ value_json.heating.target|float(0)|round(1) }}"); + if (unit == UnitSystem::METRIC) { + doc[FPSTR(HA_TEMPERATURE_UNIT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C); + + } else if (unit == UnitSystem::IMPERIAL) { + doc[FPSTR(HA_TEMPERATURE_UNIT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F); + } + doc[FPSTR(HA_MODE_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set")); doc[FPSTR(HA_MODE_COMMAND_TEMPLATE)] = F("{% if value == 'heat' %}{\"heating\": {\"enable\" : true}}" "{% elif value == 'off' %}{\"heating\": {\"enable\" : false}}{% endif %}"); @@ -1420,7 +1445,7 @@ public: return this->publish(this->getTopic(FPSTR(HA_ENTITY_CLIMATE), F("heating"), '_').c_str(), doc); } - bool publishClimateDhw(byte minTemp = 40, byte maxTemp = 60, bool enabledByDefault = true) { + bool publishClimateDhw(UnitSystem unit = UnitSystem::METRIC, byte minTemp = 40, byte maxTemp = 60, bool enabledByDefault = true) { JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status")); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; @@ -1438,6 +1463,13 @@ public: doc[FPSTR(HA_TEMPERATURE_STATE_TOPIC)] = this->getDeviceTopic(F("settings")); doc[FPSTR(HA_TEMPERATURE_STATE_TEMPLATE)] = F("{{ value_json.dhw.target|int(0) }}"); + if (unit == UnitSystem::METRIC) { + doc[FPSTR(HA_TEMPERATURE_UNIT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C); + + } else if (unit == UnitSystem::IMPERIAL) { + doc[FPSTR(HA_TEMPERATURE_UNIT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_F); + } + doc[FPSTR(HA_MODE_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set")); doc[FPSTR(HA_MODE_COMMAND_TEMPLATE)] = F("{% if value == 'heat' %}{\"dhw\": {\"enable\" : true}}" "{% elif value == 'off' %}{\"dhw\": {\"enable\" : false}}{% endif %}"); diff --git a/src/MqttTask.h b/src/MqttTask.h index d22685b..1496aa8 100644 --- a/src/MqttTask.h +++ b/src/MqttTask.h @@ -51,6 +51,7 @@ protected: MqttClient* client = nullptr; HaHelper* haHelper = nullptr; MqttWriter* writer = nullptr; + UnitSystem currentUnitSystem = UnitSystem::METRIC; unsigned short readyForSendTime = 15000; unsigned long lastReconnectTime = 0; unsigned long connectedTime = 0; @@ -213,10 +214,11 @@ protected: } // publish ha entities if not published - if (this->newConnection) { + if (this->newConnection || this->currentUnitSystem != settings.system.unitSystem) { this->publishHaEntities(); this->publishNonStaticHaEntities(true); this->newConnection = false; + this->currentUnitSystem = settings.system.unitSystem; } else { // publish non static ha entities @@ -318,14 +320,14 @@ protected: void publishHaEntities() { // emergency this->haHelper->publishSwitchEmergency(); - this->haHelper->publishNumberEmergencyTarget(); + this->haHelper->publishNumberEmergencyTarget(settings.system.unitSystem); this->haHelper->publishSwitchEmergencyUseEquitherm(); this->haHelper->publishSwitchEmergencyUsePid(); // heating this->haHelper->publishSwitchHeating(false); this->haHelper->publishSwitchHeatingTurbo(); - this->haHelper->publishNumberHeatingHysteresis(); + this->haHelper->publishNumberHeatingHysteresis(settings.system.unitSystem); this->haHelper->publishSensorHeatingSetpoint(settings.system.unitSystem, false); this->haHelper->publishSensorBoilerHeatingMinTemp(settings.system.unitSystem, false); this->haHelper->publishSensorBoilerHeatingMaxTemp(settings.system.unitSystem, false); @@ -368,8 +370,8 @@ protected: this->haHelper->publishSensorUptime(false); // temperatures - this->haHelper->publishNumberIndoorTemp(); - this->haHelper->publishSensorHeatingTemp(); + this->haHelper->publishNumberIndoorTemp(settings.system.unitSystem); + this->haHelper->publishSensorHeatingTemp(settings.system.unitSystem); this->haHelper->publishSensorHeatingReturnTemp(settings.system.unitSystem, false); this->haHelper->publishSensorExhaustTemp(settings.system.unitSystem, false); @@ -385,8 +387,7 @@ protected: bool published = false; bool isStupidMode = !settings.pid.enable && !settings.equitherm.enable; - byte heatingMinTemp = 0; - byte heatingMaxTemp = 90; + byte heatingMinTemp, heatingMaxTemp = 0; bool editableOutdoorTemp = settings.sensors.outdoor.type == SensorType::MANUAL; bool editableIndoorTemp = settings.sensors.indoor.type == SensorType::MANUAL; @@ -413,7 +414,7 @@ protected: this->haHelper->publishNumberDhwMinTemp(settings.system.unitSystem, false); this->haHelper->publishNumberDhwMaxTemp(settings.system.unitSystem, false); this->haHelper->publishBinSensorDhw(); - this->haHelper->publishSensorDhwTemp(); + this->haHelper->publishSensorDhwTemp(settings.system.unitSystem); this->haHelper->publishSensorDhwFlowRate(false); } else { @@ -443,6 +444,7 @@ protected: this->haHelper->publishNumberHeatingTarget(settings.system.unitSystem, heatingMinTemp, heatingMaxTemp, false); this->haHelper->publishClimateHeating( + settings.system.unitSystem, heatingMinTemp, heatingMaxTemp, isStupidMode ? HaHelper::TEMP_SOURCE_HEATING : HaHelper::TEMP_SOURCE_INDOOR @@ -453,6 +455,7 @@ protected: } else if (_isStupidMode != isStupidMode) { _isStupidMode = isStupidMode; this->haHelper->publishClimateHeating( + settings.system.unitSystem, heatingMinTemp, heatingMaxTemp, isStupidMode ? HaHelper::TEMP_SOURCE_HEATING : HaHelper::TEMP_SOURCE_INDOOR @@ -466,7 +469,7 @@ protected: _dhwMaxTemp = settings.dhw.maxTemp; this->haHelper->publishNumberDhwTarget(settings.system.unitSystem, settings.dhw.minTemp, settings.dhw.maxTemp, false); - this->haHelper->publishClimateDhw(settings.dhw.minTemp, settings.dhw.maxTemp); + this->haHelper->publishClimateDhw(settings.system.unitSystem, settings.dhw.minTemp, settings.dhw.maxTemp); published = true; } @@ -476,10 +479,10 @@ protected: if (editableOutdoorTemp) { this->haHelper->deleteSensorOutdoorTemp(); - this->haHelper->publishNumberOutdoorTemp(); + this->haHelper->publishNumberOutdoorTemp(settings.system.unitSystem); } else { this->haHelper->deleteNumberOutdoorTemp(); - this->haHelper->publishSensorOutdoorTemp(); + this->haHelper->publishSensorOutdoorTemp(settings.system.unitSystem); } published = true; @@ -490,10 +493,10 @@ protected: if (editableIndoorTemp) { this->haHelper->deleteSensorIndoorTemp(); - this->haHelper->publishNumberIndoorTemp(); + this->haHelper->publishNumberIndoorTemp(settings.system.unitSystem); } else { this->haHelper->deleteNumberIndoorTemp(); - this->haHelper->publishSensorIndoorTemp(); + this->haHelper->publishSensorIndoorTemp(settings.system.unitSystem); } published = true; diff --git a/src/OpenThermTask.h b/src/OpenThermTask.h index 4bb0cd8..1440222 100644 --- a/src/OpenThermTask.h +++ b/src/OpenThermTask.h @@ -333,10 +333,11 @@ protected: newDhwTemp = constrain(newDhwTemp, settings.dhw.minTemp, settings.dhw.maxTemp); } - Log.sinfoln(FPSTR(L_OT_DHW), F("Set temp = %u"), newDhwTemp); + float convertedTemp = convertTemp(newDhwTemp, settings.system.unitSystem, settings.opentherm.unitSystem); + Log.sinfoln(FPSTR(L_OT_DHW), F("Set temp: %u (converted: %.2f)"), newDhwTemp, convertedTemp); // Set DHW temp - if (this->instance->setDhwTemp(tempTo(newDhwTemp))) { + if (this->instance->setDhwTemp(convertedTemp)) { currentDhwTemp = newDhwTemp; this->dhwSetTempTime = millis(); @@ -346,7 +347,7 @@ protected: // Set DHW temp to CH2 if (settings.opentherm.dhwToCh2) { - if (!this->instance->setHeatingCh2Temp(tempTo(newDhwTemp))) { + if (!this->instance->setHeatingCh2Temp(convertedTemp)) { Log.swarningln(FPSTR(L_OT_DHW), F("Failed set ch2 temp")); } } @@ -355,10 +356,11 @@ protected: // Update heating temp if (heatingEnabled && (this->needSetHeatingTemp() || fabs(vars.parameters.heatingSetpoint - currentHeatingTemp) > 0.0001)) { - Log.sinfoln(FPSTR(L_OT_HEATING), F("Set temp = %u"), vars.parameters.heatingSetpoint); + float convertedTemp = convertTemp(vars.parameters.heatingSetpoint, settings.system.unitSystem, settings.opentherm.unitSystem); + Log.sinfoln(FPSTR(L_OT_HEATING), F("Set temp: %u (converted: %.2f)"), vars.parameters.heatingSetpoint, convertedTemp); // Set heating temp - if (this->instance->setHeatingCh1Temp(tempTo(vars.parameters.heatingSetpoint)) || this->setMaxHeatingTemp(tempTo(vars.parameters.heatingSetpoint))) { + if (this->instance->setHeatingCh1Temp(convertedTemp) || this->setMaxHeatingTemp(convertedTemp)) { currentHeatingTemp = vars.parameters.heatingSetpoint; this->heatingSetTempTime = millis(); @@ -368,7 +370,7 @@ protected: // Set heating temp to CH2 if (settings.opentherm.heatingCh1ToCh2) { - if (!this->instance->setHeatingCh2Temp(tempTo(vars.parameters.heatingSetpoint))) { + if (!this->instance->setHeatingCh2Temp(convertedTemp)) { Log.swarningln(FPSTR(L_OT_HEATING), F("Failed set ch2 temp")); } } @@ -601,8 +603,8 @@ protected: byte maxTemp = (response & 0xFFFF) >> 8; if (minTemp >= 0 && maxTemp > 0 && maxTemp > minTemp) { - vars.parameters.dhwMinTemp = tempFrom(minTemp); - vars.parameters.dhwMaxTemp = tempFrom(maxTemp); + vars.parameters.dhwMinTemp = convertTemp(minTemp, settings.opentherm.unitSystem, settings.system.unitSystem); + vars.parameters.dhwMaxTemp = convertTemp(maxTemp, settings.opentherm.unitSystem, settings.system.unitSystem); return true; } @@ -625,8 +627,8 @@ protected: byte maxTemp = (response & 0xFFFF) >> 8; if (minTemp >= 0 && maxTemp > 0 && maxTemp > minTemp) { - vars.parameters.heatingMinTemp = tempFrom(minTemp); - vars.parameters.heatingMaxTemp = tempFrom(maxTemp); + vars.parameters.heatingMinTemp = convertTemp(minTemp, settings.opentherm.unitSystem, settings.system.unitSystem); + vars.parameters.heatingMaxTemp = convertTemp(maxTemp, settings.opentherm.unitSystem, settings.system.unitSystem); return true; } @@ -637,7 +639,7 @@ protected: unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest( OpenThermMessageType::WRITE_DATA, OpenThermMessageID::MaxTSet, - CustomOpenTherm::temperatureToData(tempTo(value)) + CustomOpenTherm::temperatureToData(value) )); return CustomOpenTherm::isValidResponse(response); @@ -654,9 +656,12 @@ protected: return false; } - float value = CustomOpenTherm::getFloat(response); + vars.temperatures.outdoor = settings.sensors.outdoor.offset + convertTemp( + CustomOpenTherm::getFloat(response), + settings.opentherm.unitSystem, + settings.system.unitSystem + ); - vars.temperatures.outdoor = tempFrom(value) + settings.sensors.outdoor.offset; return true; } @@ -671,7 +676,12 @@ protected: return false; } - vars.temperatures.exhaust = tempFrom(CustomOpenTherm::getFloat(response)); + vars.temperatures.exhaust = convertTemp( + CustomOpenTherm::getFloat(response), + settings.opentherm.unitSystem, + settings.system.unitSystem + ); + return true; } @@ -691,7 +701,12 @@ protected: return false; } - vars.temperatures.heating = tempFrom(value); + vars.temperatures.heating = convertTemp( + value, + settings.opentherm.unitSystem, + settings.system.unitSystem + ); + return true; } @@ -706,7 +721,12 @@ protected: return false; } - vars.temperatures.heatingReturn = tempFrom(CustomOpenTherm::getFloat(response)); + vars.temperatures.heatingReturn = convertTemp( + CustomOpenTherm::getFloat(response), + settings.opentherm.unitSystem, + settings.system.unitSystem + ); + return true; } @@ -727,7 +747,12 @@ protected: return false; } - vars.temperatures.dhw = tempFrom(value); + vars.temperatures.dhw = convertTemp( + value, + settings.opentherm.unitSystem, + settings.system.unitSystem + ); + return true; } @@ -806,26 +831,4 @@ protected: return true; } - - static float tempTo(float value) { - if (settings.system.unitSystem == UnitSystem::METRIC && settings.opentherm.unitSystem == UnitSystem::IMPERIAL) { - value = c2f(value); - - } else if (settings.system.unitSystem == UnitSystem::IMPERIAL && settings.opentherm.unitSystem == UnitSystem::METRIC) { - value = f2c(value); - } - - return value; - } - - static float tempFrom(float value) { - if (settings.system.unitSystem == UnitSystem::METRIC && settings.opentherm.unitSystem == UnitSystem::IMPERIAL) { - value = f2c(value); - - } else if (settings.system.unitSystem == UnitSystem::IMPERIAL && settings.opentherm.unitSystem == UnitSystem::METRIC) { - value = c2f(value); - } - - return value; - } }; diff --git a/src/PortalTask.h b/src/PortalTask.h index 61c1357..74e4ef0 100644 --- a/src/PortalTask.h +++ b/src/PortalTask.h @@ -434,6 +434,7 @@ protected: JsonDocument doc; varsToJson(vars, doc); + doc["system"]["unitSystem"] = static_cast(settings.system.unitSystem); doc["system"]["version"] = PROJECT_VERSION; doc["system"]["buildDate"] = __DATE__ " " __TIME__; doc["system"]["uptime"] = millis() / 1000ul; diff --git a/src/utils.h b/src/utils.h index 1fce972..befb8d7 100644 --- a/src/utils.h +++ b/src/utils.h @@ -8,7 +8,18 @@ inline float f2c(float value) { return (value - 32.0f) * (5.0f / 9.0f); } -bool isValidTemp(float value, UnitSystem unit, float min = 0.1f, float max = 99.9f) { +float convertTemp(float value, const UnitSystem unitFrom, const UnitSystem unitTo) { + if (unitFrom == UnitSystem::METRIC && unitTo == UnitSystem::IMPERIAL) { + value = c2f(value); + + } else if (unitFrom == UnitSystem::IMPERIAL && unitTo == UnitSystem::METRIC) { + value = f2c(value); + } + + return value; +} + +bool isValidTemp(const float value, UnitSystem unit, const float min = 0.1f, const float max = 99.9f) { if (unit == UnitSystem::METRIC) { return value >= min && value <= max; @@ -401,6 +412,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false if (!src["system"]["unitSystem"].isNull()) { byte value = src["system"]["unitSystem"].as(); + UnitSystem prevUnitSystem = dst.system.unitSystem; switch (value) { case static_cast(UnitSystem::METRIC): @@ -416,6 +428,19 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false default: break; } + + // convert temps + if (dst.system.unitSystem != prevUnitSystem) { + dst.emergency.target = convertTemp(dst.emergency.target, prevUnitSystem, dst.system.unitSystem); + dst.heating.target = convertTemp(dst.heating.target, prevUnitSystem, dst.system.unitSystem); + dst.heating.minTemp = convertTemp(dst.heating.minTemp, prevUnitSystem, dst.system.unitSystem); + dst.heating.maxTemp = convertTemp(dst.heating.maxTemp, prevUnitSystem, dst.system.unitSystem); + dst.dhw.target = convertTemp(dst.dhw.target, prevUnitSystem, dst.system.unitSystem); + dst.dhw.minTemp = convertTemp(dst.dhw.minTemp, prevUnitSystem, dst.system.unitSystem); + dst.dhw.maxTemp = convertTemp(dst.dhw.maxTemp, prevUnitSystem, dst.system.unitSystem); + dst.pid.minTemp = convertTemp(dst.pid.minTemp, prevUnitSystem, dst.system.unitSystem); + dst.pid.maxTemp = convertTemp(dst.pid.maxTemp, prevUnitSystem, dst.system.unitSystem); + } }