diff --git a/src/HaHelper.h b/src/HaHelper.h index d7c9161..ae15d6e 100644 --- a/src/HaHelper.h +++ b/src/HaHelper.h @@ -872,38 +872,15 @@ public: return this->publish(this->getTopic(FPSTR(HA_ENTITY_BINARY_SENSOR), F("diagnostic")).c_str(), doc); } - bool publishSensorMaxPower(bool enabledByDefault = true) { + bool publishSensorPower(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("max_power")); - doc[FPSTR(HA_OBJECT_ID)] = this->getObjectId(F("max_power")); - doc[FPSTR(HA_ENTITY_CATEGORY)] = F("diagnostic"); - doc[FPSTR(HA_DEVICE_CLASS)] = F("power"); - doc[FPSTR(HA_STATE_CLASS)] = F("measurement"); - doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = F("kW"); - doc[FPSTR(HA_NAME)] = F("Max power"); - doc[FPSTR(HA_ICON)] = F("mdi:chart-bar"); - doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state")); - doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.sensors.maxPower|float(0)|round(2) }}"); - doc[FPSTR(HA_EXPIRE_AFTER)] = 120; - doc.shrinkToFit(); - - return this->publish(this->getTopic(FPSTR(HA_ENTITY_SENSOR), F("max_power")).c_str(), doc); - } - - bool publishSensorCurrentPower(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("current_power")); - doc[FPSTR(HA_OBJECT_ID)] = this->getObjectId(F("current_power")); + doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectId(F("power")); + doc[FPSTR(HA_OBJECT_ID)] = this->getObjectId(F("power")); doc[FPSTR(HA_ENTITY_CATEGORY)] = F("diagnostic"); doc[FPSTR(HA_DEVICE_CLASS)] = F("power"); doc[FPSTR(HA_STATE_CLASS)] = F("measurement"); @@ -911,11 +888,11 @@ public: doc[FPSTR(HA_NAME)] = F("Current power"); doc[FPSTR(HA_ICON)] = F("mdi:chart-bar"); doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state")); - doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.sensors.currentPower|float(0)|round(2) }}"); + doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.sensors.power|float(0)|round(2) }}"); doc[FPSTR(HA_EXPIRE_AFTER)] = 120; doc.shrinkToFit(); - return this->publish(this->getTopic(FPSTR(HA_ENTITY_SENSOR), F("current_power")).c_str(), doc); + return this->publish(this->getTopic(FPSTR(HA_ENTITY_SENSOR), F("power")).c_str(), doc); } bool publishSensorFaultCode(bool enabledByDefault = true) { diff --git a/src/MqttTask.h b/src/MqttTask.h index 795b4d8..3025d14 100644 --- a/src/MqttTask.h +++ b/src/MqttTask.h @@ -357,8 +357,7 @@ protected: // sensors this->haHelper->publishSensorModulation(false); this->haHelper->publishSensorPressure(settings.system.unitSystem, false); - this->haHelper->publishSensorMaxPower(false); - this->haHelper->publishSensorCurrentPower(); + this->haHelper->publishSensorPower(); this->haHelper->publishSensorFaultCode(); this->haHelper->publishSensorDiagnosticCode(); this->haHelper->publishSensorRssi(false); diff --git a/src/OpenThermTask.h b/src/OpenThermTask.h index 4b4dbf1..f59e364 100644 --- a/src/OpenThermTask.h +++ b/src/OpenThermTask.h @@ -254,32 +254,43 @@ protected: // These parameters will be updated every minute if (millis() - this->prevUpdateNonEssentialVars > 60000) { if (this->updateMinModulationLevel()) { - Log.straceln(FPSTR(L_OT), F("Min modulation: %u%%, boiler max power: %u kW"), vars.parameters.minModulation, vars.sensors.maxPower); + Log.snoticeln( + FPSTR(L_OT), + F("Received min modulation: %hhu%%, max power: %hhu kW"), + vars.parameters.minModulation, + vars.parameters.maxPower + ); - if (vars.parameters.minModulation > settings.heating.maxModulation) { + if (settings.heating.maxModulation < vars.parameters.minModulation) { settings.heating.maxModulation = vars.parameters.minModulation; fsSettings.update(); - Log.snoticeln(FPSTR(L_OT_DHW), F("Updated min modulation: %hhu"), settings.heating.maxModulation); + Log.swarningln(FPSTR(L_SETTINGS_OT), F("Updated min modulation: %hhu%%"), settings.heating.maxModulation); + } + + if (fabsf(settings.opentherm.maxPower) < 0.1f && vars.parameters.maxPower > 0) { + settings.opentherm.maxPower = vars.parameters.maxPower; + fsSettings.update(); + Log.swarningln(FPSTR(L_SETTINGS_OT), F("Updated max power: %.2f kW"), settings.opentherm.maxPower); } } else { - Log.swarningln(FPSTR(L_OT), F("Failed get min modulation & max power")); + Log.swarningln(FPSTR(L_OT), F("Failed receive min modulation and max power")); } if (!heatingEnabled && settings.opentherm.modulationSyncWithHeating) { if (this->setMaxModulationLevel(0)) { - Log.snoticeln(FPSTR(L_OT_HEATING), F("Set max modulation 0% (off)")); + Log.snoticeln(FPSTR(L_OT_HEATING), F("Set max modulation: 0% (off)")); } else { - Log.swarningln(FPSTR(L_OT_HEATING), F("Failed set max modulation 0% (off)")); + Log.swarningln(FPSTR(L_OT_HEATING), F("Failed set max modulation: 0% (off)")); } } else { if (this->setMaxModulationLevel(settings.heating.maxModulation)) { - Log.snoticeln(FPSTR(L_OT_HEATING), F("Set max modulation %hhu%%"), settings.heating.maxModulation); + Log.snoticeln(FPSTR(L_OT_HEATING), F("Set max modulation: %hhu%%"), settings.heating.maxModulation); } else { - Log.swarningln(FPSTR(L_OT_HEATING), F("Failed set max modulation %hhu%%"), settings.heating.maxModulation); + Log.swarningln(FPSTR(L_OT_HEATING), F("Failed set max modulation: %hhu%%"), settings.heating.maxModulation); } } @@ -287,23 +298,30 @@ protected: // Get DHW min/max temp (if necessary) if (settings.opentherm.dhwPresent && settings.opentherm.getMinMaxTemp) { if (this->updateMinMaxDhwTemp()) { + Log.snoticeln( + FPSTR(L_OT_DHW), + F("Received min temp: %hhu, max temp: %hhu"), + vars.parameters.dhwMinTemp, + vars.parameters.dhwMaxTemp + ); + if (settings.dhw.minTemp < vars.parameters.dhwMinTemp) { settings.dhw.minTemp = vars.parameters.dhwMinTemp; fsSettings.update(); - Log.snoticeln(FPSTR(L_OT_DHW), F("Updated min temp: %hhu"), settings.dhw.minTemp); + Log.swarningln(FPSTR(L_SETTINGS_DHW), F("Updated min temp: %hhu"), settings.dhw.minTemp); } if (settings.dhw.maxTemp > vars.parameters.dhwMaxTemp) { settings.dhw.maxTemp = vars.parameters.dhwMaxTemp; fsSettings.update(); - Log.snoticeln(FPSTR(L_OT_DHW), F("Updated max temp: %hhu"), settings.dhw.maxTemp); + Log.swarningln(FPSTR(L_SETTINGS_DHW), F("Updated max temp: %hhu"), settings.dhw.maxTemp); } } else { vars.parameters.dhwMinTemp = convertTemp(DEFAULT_DHW_MIN_TEMP, UnitSystem::METRIC, settings.system.unitSystem); vars.parameters.dhwMaxTemp = convertTemp(DEFAULT_DHW_MAX_TEMP, UnitSystem::METRIC, settings.system.unitSystem); - Log.swarningln(FPSTR(L_OT_DHW), F("Failed get min/max temp")); + Log.swarningln(FPSTR(L_OT_DHW), F("Failed receive min/max temp")); } if (settings.dhw.minTemp >= settings.dhw.maxTemp) { @@ -317,23 +335,30 @@ protected: // Get heating min/max temp if (settings.opentherm.getMinMaxTemp) { if (this->updateMinMaxHeatingTemp()) { + Log.snoticeln( + FPSTR(L_OT_HEATING), + F("Received min temp: %hhu, max temp: %hhu"), + vars.parameters.heatingMinTemp, + vars.parameters.heatingMaxTemp + ); + if (settings.heating.minTemp < vars.parameters.heatingMinTemp) { settings.heating.minTemp = vars.parameters.heatingMinTemp; fsSettings.update(); - Log.snoticeln(FPSTR(L_OT_HEATING), F("Updated min temp: %hhu"), settings.heating.minTemp); + Log.swarningln(FPSTR(L_SETTINGS_HEATING), F("Updated min temp: %hhu"), settings.heating.minTemp); } if (settings.heating.maxTemp > vars.parameters.heatingMaxTemp) { settings.heating.maxTemp = vars.parameters.heatingMaxTemp; fsSettings.update(); - Log.snoticeln(FPSTR(L_OT_HEATING), F("Updated max temp: %hhu"), settings.heating.maxTemp); + Log.swarningln(FPSTR(L_SETTINGS_HEATING), F("Updated max temp: %hhu"), settings.heating.maxTemp); } } else { vars.parameters.heatingMinTemp = convertTemp(DEFAULT_HEATING_MIN_TEMP, UnitSystem::METRIC, settings.system.unitSystem); vars.parameters.heatingMaxTemp = convertTemp(DEFAULT_HEATING_MAX_TEMP, UnitSystem::METRIC, settings.system.unitSystem); - Log.swarningln(FPSTR(L_OT_HEATING), F("Failed get min/max temp")); + Log.swarningln(FPSTR(L_OT_HEATING), F("Failed receive min/max temp")); } } @@ -345,7 +370,19 @@ protected: // Get fault code (if necessary) if (vars.states.fault) { - this->updateFaultCode(); + if (this->updateFaultCode()) { + Log.snoticeln( + FPSTR(L_OT), + F("Received fault code: %hhu%% (0x%02X)"), + vars.sensors.faultCode, + vars.sensors.faultCode + ); + + } else { + vars.sensors.faultCode = 0; + + Log.swarningln(FPSTR(L_OT), F("Failed receive fault code")); + } } else if (vars.sensors.faultCode != 0) { vars.sensors.faultCode = 0; @@ -353,7 +390,19 @@ protected: // Get diagnostic code (if necessary) if (vars.states.fault || vars.states.diagnostic) { - this->updateDiagCode(); + if (this->updateDiagCode()) { + Log.snoticeln( + FPSTR(L_OT), + F("Received diag code: %hhu%% (0x%02X)"), + vars.sensors.diagnosticCode, + vars.sensors.diagnosticCode + ); + + } else { + vars.sensors.diagnosticCode = 0; + + Log.swarningln(FPSTR(L_OT), F("Failed receive diag code")); + } } else if (vars.sensors.diagnosticCode != 0) { vars.sensors.diagnosticCode = 0; @@ -364,11 +413,21 @@ protected: if (!settings.opentherm.filterNumValues.enable) { // Get outdoor temp (if necessary) if (settings.sensors.outdoor.type == SensorType::BOILER) { - this->updateOutdoorTemp(); + if (this->updateOutdoorTemp()) { + Log.snoticeln(FPSTR(L_OT), F("Received outdoor temp: %.2f"), vars.temperatures.outdoor); + + } else { + Log.swarningln(FPSTR(L_OT), F("Failed receive outdoor temp")); + } } // Get pressure - this->updatePressure(); + if (this->updatePressure()) { + Log.snoticeln(FPSTR(L_OT), F("Received pressure: %.2f"), vars.sensors.pressure); + + } else { + Log.swarningln(FPSTR(L_OT), F("Failed receive pressure")); + } } this->prevUpdateNonEssentialVars = millis(); @@ -376,28 +435,52 @@ protected: // Get current modulation level (if necessary) - if (vars.states.flame && this->updateModulationLevel()) { - vars.sensors.currentPower = vars.sensors.maxPower > 0 - ? vars.sensors.maxPower * (vars.sensors.modulation / 100) - : 0; - - Log.sverboseln( - FPSTR(L_OT_DHW), - F("Current modulation level: %.2f%%, power: %.2f of %hhu kW"), - vars.sensors.modulation, - vars.sensors.currentPower, - vars.sensors.maxPower - ); + if (vars.states.flame) { + if (this->updateModulationLevel()) { + if (settings.opentherm.maxPower > 0.1f) { + float modulatedPower = settings.opentherm.maxPower - settings.opentherm.minPower; + vars.sensors.power = settings.opentherm.minPower + (modulatedPower / 100.0f * vars.sensors.modulation); + + } else { + vars.sensors.power = 0.0f; + } + + Log.snoticeln( + FPSTR(L_OT), + F("Received modulation level: %.2f%%, power: %.2f of %.2f kW (min: %.2f kW)"), + vars.sensors.modulation, + vars.sensors.power, + settings.opentherm.maxPower, + settings.opentherm.minPower + ); + + } else { + vars.sensors.modulation = 0; + vars.sensors.power = 0; + + Log.swarningln(FPSTR(L_OT), F("Failed receive modulation level")); + } } else { vars.sensors.modulation = 0; - vars.sensors.currentPower = 0; + vars.sensors.power = 0; } // Update DHW sensors (if necessary) if (settings.opentherm.dhwPresent) { - this->updateDhwTemp(); - this->updateDhwFlowRate(); + if (this->updateDhwTemp()) { + Log.snoticeln(FPSTR(L_OT_DHW), F("Received temp: %.2f"), vars.temperatures.dhw); + + } else { + Log.swarningln(FPSTR(L_OT_DHW), F("Failed receive temp")); + } + + if (this->updateDhwFlowRate()) { + Log.snoticeln(FPSTR(L_OT_DHW), F("Received flow rate: %.2f"), vars.sensors.dhwFlowRate); + + } else { + Log.swarningln(FPSTR(L_OT_DHW), F("Failed receive flow rate")); + } } else { vars.temperatures.dhw = 0.0f; @@ -405,24 +488,49 @@ protected: } // Get current heating temp - this->updateHeatingTemp(); + if (this->updateHeatingTemp()) { + Log.snoticeln(FPSTR(L_OT_HEATING), F("Received temp: %.2f"), vars.temperatures.heating); + + } else { + Log.swarningln(FPSTR(L_OT_HEATING), F("Failed receive temp")); + } // Get heating return temp - this->updateHeatingReturnTemp(); + if (this->updateHeatingReturnTemp()) { + Log.snoticeln(FPSTR(L_OT_HEATING), F("Received return temp: %.2f"), vars.temperatures.heatingReturn); + + } else { + Log.swarningln(FPSTR(L_OT_HEATING), F("Failed receive return temp")); + } // Get exhaust temp - this->updateExhaustTemp(); + if (this->updateExhaustTemp()) { + Log.snoticeln(FPSTR(L_OT), F("Received exhaust temp: %.2f"), vars.temperatures.exhaust); + + } else { + Log.swarningln(FPSTR(L_OT), F("Failed receive exhaust temp")); + } // If filtering is enabled, these parameters // must be updated every time. if (settings.opentherm.filterNumValues.enable) { // Get outdoor temp (if necessary) if (settings.sensors.outdoor.type == SensorType::BOILER) { - this->updateOutdoorTemp(); + if (this->updateOutdoorTemp()) { + Log.snoticeln(FPSTR(L_OT), F("Received outdoor temp: %.2f"), vars.temperatures.outdoor); + + } else { + Log.swarningln(FPSTR(L_OT), F("Failed receive outdoor temp")); + } } // Get pressure - this->updatePressure(); + if (this->updatePressure()) { + Log.snoticeln(FPSTR(L_OT), F("Received pressure: %.2f"), vars.sensors.pressure); + + } else { + Log.swarningln(FPSTR(L_OT), F("Failed receive pressure")); + } } @@ -573,46 +681,46 @@ protected: void initialize() { // Not all boilers support these, only try once when the boiler becomes connected if (this->updateSlaveVersion()) { - Log.straceln(FPSTR(L_OT), F("Slave version: %u, type: %u"), vars.parameters.slaveVersion, vars.parameters.slaveType); + Log.snoticeln(FPSTR(L_OT), F("Received slave version: %u, type: %u"), vars.parameters.slaveVersion, vars.parameters.slaveType); } else { - Log.swarningln(FPSTR(L_OT), F("Get slave version failed")); + Log.swarningln(FPSTR(L_OT), F("Failed receive slave version")); } // 0x013F if (this->setMasterVersion(0x3F, 0x01)) { - Log.straceln(FPSTR(L_OT), F("Master version: %u, type: %u"), vars.parameters.masterVersion, vars.parameters.masterType); + Log.snoticeln(FPSTR(L_OT), F("Set master version: %u, type: %u"), vars.parameters.masterVersion, vars.parameters.masterType); } else { - Log.swarningln(FPSTR(L_OT), F("Set master version failed")); + Log.swarningln(FPSTR(L_OT), F("Failed set master version")); } if (this->updateSlaveOtVersion()) { - Log.straceln(FPSTR(L_OT), F("Slave OT version: %f"), vars.parameters.slaveOtVersion); + Log.snoticeln(FPSTR(L_OT), F("Received slave OT version: %f"), vars.parameters.slaveOtVersion); } else { - Log.swarningln(FPSTR(L_OT), F("Get slave OT version failed")); + Log.swarningln(FPSTR(L_OT), F("Failed receive slave OT version")); } if (this->setMasterOtVersion(2.2f)) { - Log.straceln(FPSTR(L_OT), F("Master OT version: %f"), vars.parameters.masterOtVersion); + Log.snoticeln(FPSTR(L_OT), F("Set master OT version: %f"), vars.parameters.masterOtVersion); } else { - Log.swarningln(FPSTR(L_OT), F("Set master OT version failed")); + Log.swarningln(FPSTR(L_OT), F("Failed set master OT version")); } if (this->updateSlaveConfig()) { - Log.straceln(FPSTR(L_OT), F("Slave member id: %u, flags: %u"), vars.parameters.slaveMemberId, vars.parameters.slaveFlags); + Log.snoticeln(FPSTR(L_OT), F("Received slave member id: %u, flags: %u"), vars.parameters.slaveMemberId, vars.parameters.slaveFlags); } else { - Log.swarningln(FPSTR(L_OT), F("Get slave config failed")); + Log.swarningln(FPSTR(L_OT), F("Failed receive slave config")); } if (this->setMasterConfig(settings.opentherm.memberIdCode & 0xFF, (settings.opentherm.memberIdCode & 0xFFFF) >> 8)) { - Log.straceln(FPSTR(L_OT), F("Master member id: %u, flags: %u"), vars.parameters.masterMemberId, vars.parameters.masterFlags); + Log.snoticeln(FPSTR(L_OT), F("Set master member id: %u, flags: %u"), vars.parameters.masterMemberId, vars.parameters.masterFlags); } else { - Log.swarningln(FPSTR(L_OT), F("Set master config failed")); + Log.swarningln(FPSTR(L_OT), F("Failed set master config")); } } @@ -1023,7 +1131,6 @@ protected: )); if (!CustomOpenTherm::isValidResponse(response)) { - vars.sensors.faultCode = 0; return false; } @@ -1039,7 +1146,6 @@ protected: )); if (!CustomOpenTherm::isValidResponse(response)) { - vars.sensors.diagnosticCode = 0; return false; } @@ -1059,6 +1165,10 @@ protected: } float value = CustomOpenTherm::getFloat(response); + if (value < 0) { + return false; + } + if (settings.opentherm.filterNumValues.enable && fabs(vars.sensors.modulation) >= 0.1f) { vars.sensors.modulation += (value - vars.sensors.modulation) * settings.opentherm.filterNumValues.factor; @@ -1080,11 +1190,8 @@ protected: return false; } - byte minModulation = response & 0xFF; - byte maxPower = (response & 0xFFFF) >> 8; - - vars.parameters.minModulation = minModulation; - vars.sensors.maxPower = maxPower; + vars.parameters.minModulation = response & 0xFF; + vars.parameters.maxPower = (response & 0xFFFF) >> 8; return true; } diff --git a/src/Settings.h b/src/Settings.h index 9f95d85..f51d22d 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -56,6 +56,8 @@ struct Settings { unsigned int memberIdCode = 0; float pressureFactor = 1.0f; float dhwFlowRateFactor = 1.0f; + float minPower = 0.0f; + float maxPower = 0.0f; bool dhwPresent = true; bool summerWinterMode = false; bool heatingCh2Enabled = true; @@ -174,8 +176,7 @@ struct Variables { float modulation = 0.0f; float pressure = 0.0f; float dhwFlowRate = 0.0f; - byte maxPower = 0; - float currentPower = 0.0f; + float power = 0.0f; byte faultCode = 0; unsigned short diagnosticCode = 0; int8_t rssi = 0; @@ -214,6 +215,7 @@ struct Variables { byte dhwMaxTemp = DEFAULT_DHW_MAX_TEMP; byte minModulation = 0; byte maxModulation = 0; + uint8_t maxPower = 0; uint8_t slaveMemberId = 0; uint8_t slaveFlags = 0; uint8_t slaveType = 0; diff --git a/src/strings.h b/src/strings.h index 2278050..e688878 100644 --- a/src/strings.h +++ b/src/strings.h @@ -4,6 +4,9 @@ #endif const char L_SETTINGS[] PROGMEM = "SETTINGS"; +const char L_SETTINGS_OT[] PROGMEM = "SETTINGS.OT"; +const char L_SETTINGS_DHW[] PROGMEM = "SETTINGS.DHW"; +const char L_SETTINGS_HEATING[] PROGMEM = "SETTINGS.HEATING"; const char L_NETWORK[] PROGMEM = "NETWORK"; const char L_NETWORK_SETTINGS[] PROGMEM = "NETWORK.SETTINGS"; const char L_PORTAL_WEBSERVER[] PROGMEM = "PORTAL.WEBSERVER"; diff --git a/src/utils.h b/src/utils.h index e7915b9..742ac28 100644 --- a/src/utils.h +++ b/src/utils.h @@ -347,6 +347,8 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) { dst["opentherm"]["memberIdCode"] = src.opentherm.memberIdCode; dst["opentherm"]["pressureFactor"] = roundd(src.opentherm.pressureFactor, 2); dst["opentherm"]["dhwFlowRateFactor"] = roundd(src.opentherm.dhwFlowRateFactor, 2); + dst["opentherm"]["minPower"] = roundd(src.opentherm.minPower, 2); + dst["opentherm"]["maxPower"] = roundd(src.opentherm.maxPower, 2); dst["opentherm"]["dhwPresent"] = src.opentherm.dhwPresent; dst["opentherm"]["summerWinterMode"] = src.opentherm.summerWinterMode; dst["opentherm"]["heatingCh2Enabled"] = src.opentherm.heatingCh2Enabled; @@ -716,6 +718,24 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false } } + if (!src["opentherm"]["minPower"].isNull()) { + float value = src["opentherm"]["minPower"].as(); + + if (value >= 0 && value <= 1000 && fabs(value - dst.opentherm.minPower) > 0.0001f) { + dst.opentherm.minPower = roundd(value, 2); + changed = true; + } + } + + if (!src["opentherm"]["maxPower"].isNull()) { + float value = src["opentherm"]["maxPower"].as(); + + if (value >= 0 && value <= 1000 && fabs(value - dst.opentherm.maxPower) > 0.0001f) { + dst.opentherm.maxPower = roundd(value, 2); + changed = true; + } + } + if (src["opentherm"]["filterNumValues"]["enable"].is()) { bool value = src["opentherm"]["filterNumValues"]["enable"].as(); @@ -1546,8 +1566,7 @@ void varsToJson(const Variables& src, JsonVariant dst) { dst["sensors"]["modulation"] = roundd(src.sensors.modulation, 2); dst["sensors"]["pressure"] = roundd(src.sensors.pressure, 2); dst["sensors"]["dhwFlowRate"] = roundd(src.sensors.dhwFlowRate, 2); - dst["sensors"]["maxPower"] = src.sensors.maxPower; - dst["sensors"]["currentPower"] = roundd(src.sensors.currentPower, 2); + dst["sensors"]["power"] = roundd(src.sensors.power, 2); dst["sensors"]["faultCode"] = src.sensors.faultCode; dst["sensors"]["diagnosticCode"] = src.sensors.diagnosticCode; dst["sensors"]["rssi"] = src.sensors.rssi; diff --git a/src_data/locales/en.json b/src_data/locales/en.json index 512e839..3ac0b97 100644 --- a/src_data/locales/en.json +++ b/src_data/locales/en.json @@ -100,8 +100,7 @@ "modulation": "Modulation", "pressure": "Pressure", "dhwFlowRate": "DHW flow rate", - "maxPower": "Max power", - "currentPower": "Current power", + "power": "Current power", "faultCode": "Fault code", "diagCode": "Diagnostic code", "indoorTemp": "Indoor temp", @@ -272,6 +271,14 @@ "title": "Coeff. DHW flow rate correction", "note": "If the DHW flow rate displayed is X10 from the real one, set the 0.1." }, + "minPower": { + "title": "Min boiler power (kW)", + "note": "This value is at 0-1% boiler modulation level. Typically found in the boiler specification as \"minimum useful heat output\"." + }, + "maxPower": { + "title": "Max boiler power (kW)", + "note": "0 - try detect automatically. Typically found in the boiler specification as \"maximum useful heat output\"." + }, "fnv": { "title": "Filtering numeric values", "enable": { diff --git a/src_data/locales/ru.json b/src_data/locales/ru.json index 99a470a..7037bbb 100644 --- a/src_data/locales/ru.json +++ b/src_data/locales/ru.json @@ -100,8 +100,7 @@ "modulation": "Уровень модуляции", "pressure": "Давление", "dhwFlowRate": "Расход ГВС", - "maxPower": "Макс. мощность", - "currentPower": "Текущая мощность", + "power": "Текущая мощность", "faultCode": "Код ошибки", "diagCode": "Диагностический код", "indoorTemp": "Внутренняя темп.", @@ -272,6 +271,14 @@ "title": "Коэфф. коррекции потока ГВС", "note": "Если поток ГВС отображается Х10 от реального, установите значение 0.1." }, + "minPower": { + "title": "Мин. мощность котла (кВ)", + "note": "Это значение соответствует уровню модуляции котла 0–1%. Обычно можно найти в спецификации котла как \"минимальная полезная тепловая мощность\"." + }, + "maxPower": { + "title": "Макс. мощность котла (кВ)", + "note": "0 - попробовать определить автоматически. Обычно можно найти в спецификации котла как \"максимальная полезная тепловая мощность\"." + }, "fnv": { "title": "Фильтрация числовых значений", "enable": { diff --git a/src_data/pages/dashboard.html b/src_data/pages/dashboard.html index 450fef9..1ef633e 100644 --- a/src_data/pages/dashboard.html +++ b/src_data/pages/dashboard.html @@ -159,12 +159,8 @@ /min - dashboard.state.maxPower - kw - - - dashboard.state.currentPower - kw + dashboard.state.power + kw dashboard.state.faultCode @@ -442,8 +438,7 @@ setValue('#ot-modulation', result.sensors.modulation); setValue('#ot-pressure', result.sensors.pressure); setValue('#ot-dhw-flow-rate', result.sensors.dhwFlowRate); - setValue('#ot-max-power', result.sensors.maxPower); - setValue('#ot-current-power', result.sensors.currentPower); + setValue('#ot-power', result.sensors.power); setValue( '#ot-fault-code', result.sensors.faultCode diff --git a/src_data/pages/settings.html b/src_data/pages/settings.html index d228a7b..cd684ca 100644 --- a/src_data/pages/settings.html +++ b/src_data/pages/settings.html @@ -415,6 +415,20 @@ +
+ + + +
+
settings.section.ot.options