diff --git a/src/MainTask.h b/src/MainTask.h index 8d746e0..fcd0c28 100644 --- a/src/MainTask.h +++ b/src/MainTask.h @@ -319,7 +319,7 @@ protected: emergencyFlags |= 0b00000010; } - if (settings.opentherm.options.nativeHeatingControl) { + if (settings.opentherm.options.nativeOTC) { emergencyFlags |= 0b00000100; } } diff --git a/src/OpenThermTask.h b/src/OpenThermTask.h index c609597..53eed3b 100644 --- a/src/OpenThermTask.h +++ b/src/OpenThermTask.h @@ -218,7 +218,7 @@ protected: vars.master.heating.enabled, vars.master.dhw.enabled, settings.opentherm.options.coolingSupport, - settings.opentherm.options.nativeHeatingControl, + settings.opentherm.options.nativeOTC, vars.master.ch2.enabled, summerWinterMode, dhwBlocking, @@ -911,7 +911,7 @@ protected: // Update CH2 temp if (Sensors::getAmountByType(Sensors::Type::OT_CH2_TEMP, true)) { - if (vars.master.ch2.enabled && !settings.opentherm.options.nativeHeatingControl) { + if (vars.master.ch2.enabled && !settings.opentherm.options.nativeOTC) { if (this->updateCh2Temp()) { float convertedCh2Temp = convertTemp( vars.slave.ch2.currentTemp, @@ -1209,8 +1209,8 @@ protected: } } - // Native heating control - if (settings.opentherm.options.nativeHeatingControl) { + // NativeOTC or if the AlwaysSendIndoorTemp option is enabled. + if ((settings.opentherm.options.nativeOTC) || (settings.opentherm.options.alwaysSendIndoorTemp)) { // Converted current indoor temp float convertedTemp = convertTemp(vars.master.heating.indoorTemp, settings.system.unitSystem, settings.opentherm.unitSystem); @@ -1238,7 +1238,6 @@ protected: } } - // Converted target indoor temp convertedTemp = convertTemp(vars.master.heating.targetTemp, settings.system.unitSystem, settings.opentherm.unitSystem); @@ -1274,7 +1273,7 @@ protected: } // Normal heating control - if (!settings.opentherm.options.nativeHeatingControl && vars.master.heating.enabled) { + if (!settings.opentherm.options.nativeOTC && vars.master.heating.enabled) { // Converted target heating temp float convertedTemp = convertTemp(vars.master.heating.setpointTemp, settings.system.unitSystem, settings.opentherm.unitSystem); @@ -1311,7 +1310,7 @@ protected: } // Set CH2 temp - if (!settings.opentherm.options.nativeHeatingControl && vars.master.ch2.enabled) { + if (!settings.opentherm.options.nativeOTC && vars.master.ch2.enabled) { if (settings.opentherm.options.heatingToCh2 || settings.opentherm.options.dhwToCh2) { // Converted target CH2 temp float convertedTemp = convertTemp( diff --git a/src/RegulatorTask.h b/src/RegulatorTask.h index 43df116..30fbb6d 100644 --- a/src/RegulatorTask.h +++ b/src/RegulatorTask.h @@ -37,7 +37,7 @@ protected: this->indoorSensorsConnected = Sensors::existsConnectedSensorsByPurpose(Sensors::Purpose::INDOOR_TEMP); //this->outdoorSensorsConnected = Sensors::existsConnectedSensorsByPurpose(Sensors::Purpose::OUTDOOR_TEMP); - if (settings.equitherm.enabled || settings.pid.enabled || settings.opentherm.options.nativeHeatingControl) { + if (settings.equitherm.enabled || settings.pid.enabled || settings.opentherm.options.nativeOTC) { vars.master.heating.indoorTempControl = true; vars.master.heating.minTemp = THERMOSTAT_INDOOR_MIN_TEMP; vars.master.heating.maxTemp = THERMOSTAT_INDOOR_MAX_TEMP; @@ -102,7 +102,7 @@ protected: void hysteresis() { bool useHyst = false; if (settings.heating.hysteresis.enabled && this->indoorSensorsConnected) { - useHyst = settings.equitherm.enabled || settings.pid.enabled || settings.opentherm.options.nativeHeatingControl; + useHyst = settings.equitherm.enabled || settings.pid.enabled || settings.opentherm.options.nativeOTC; } if (useHyst) { @@ -119,13 +119,13 @@ protected: } inline float getHeatingMinSetpointTemp() { - return settings.opentherm.options.nativeHeatingControl + return settings.opentherm.options.nativeOTC ? vars.master.heating.minTemp : settings.heating.minTemp; } inline float getHeatingMaxSetpointTemp() { - return settings.opentherm.options.nativeHeatingControl + return settings.opentherm.options.nativeOTC ? vars.master.heating.maxTemp : settings.heating.maxTemp; } @@ -146,7 +146,7 @@ protected: if (vars.emergency.state) { return settings.emergency.target; - } else if (settings.opentherm.options.nativeHeatingControl) { + } else if (settings.opentherm.options.nativeOTC) { return settings.heating.target; } else if (!settings.equitherm.enabled && !settings.pid.enabled) { diff --git a/src/Settings.h b/src/Settings.h index 43c3871..13da7c2 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -78,7 +78,8 @@ struct Settings { bool autoFaultReset = false; bool autoDiagReset = false; bool setDateAndTime = false; - bool nativeHeatingControl = false; + bool alwaysSendIndoorTemp = true; + bool nativeOTC = false; bool immergasFix = false; } options; } opentherm; diff --git a/src/strings.h b/src/strings.h index 510c392..d438a6e 100644 --- a/src/strings.h +++ b/src/strings.h @@ -110,6 +110,7 @@ const char S_HYSTERESIS[] PROGMEM = "hysteresis"; const char S_ID[] PROGMEM = "id"; const char S_IGNORE_DIAG_STATE[] PROGMEM = "ignoreDiagState"; const char S_IMMERGAS_FIX[] PROGMEM = "immergasFix"; +const char S_ALWAYS_SEND_INDOOR_TEMP[] PROGMEM = "alwaysSendIndoorTemp"; const char S_INDOOR_TEMP[] PROGMEM = "indoorTemp"; const char S_INDOOR_TEMP_CONTROL[] PROGMEM = "indoorTempControl"; const char S_IN_GPIO[] PROGMEM = "inGpio"; @@ -141,7 +142,7 @@ const char S_MODEL[] PROGMEM = "model"; const char S_MODULATION[] PROGMEM = "modulation"; const char S_MQTT[] PROGMEM = "mqtt"; const char S_NAME[] PROGMEM = "name"; -const char S_NATIVE_HEATING_CONTROL[] PROGMEM = "nativeHeatingControl"; +const char S_NATIVE_OTC[] PROGMEM = "nativeOTC"; const char S_NETWORK[] PROGMEM = "network"; const char S_NTP[] PROGMEM = "ntp"; const char S_OFFSET[] PROGMEM = "offset"; diff --git a/src/utils.h b/src/utils.h index c3d5dfc..f3db18d 100644 --- a/src/utils.h +++ b/src/utils.h @@ -468,8 +468,10 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) { otOptions[FPSTR(S_AUTO_FAULT_RESET)] = src.opentherm.options.autoFaultReset; otOptions[FPSTR(S_AUTO_DIAG_RESET)] = src.opentherm.options.autoDiagReset; otOptions[FPSTR(S_SET_DATE_AND_TIME)] = src.opentherm.options.setDateAndTime; - otOptions[FPSTR(S_NATIVE_HEATING_CONTROL)] = src.opentherm.options.nativeHeatingControl; + otOptions[FPSTR(S_ALWAYS_SEND_INDOOR_TEMP)] = src.opentherm.options.alwaysSendIndoorTemp; + otOptions[FPSTR(S_NATIVE_OTC)] = src.opentherm.options.nativeOTC; otOptions[FPSTR(S_IMMERGAS_FIX)] = src.opentherm.options.immergasFix; + auto mqtt = dst[FPSTR(S_MQTT)].to(); mqtt[FPSTR(S_ENABLED)] = src.mqtt.enabled; @@ -1003,11 +1005,20 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false } } - if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_NATIVE_HEATING_CONTROL)].is()) { - bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_NATIVE_HEATING_CONTROL)].as(); + if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_ALWAYS_SEND_INDOOR_TEMP)].is()) { + bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_ALWAYS_SEND_INDOOR_TEMP)].as(); - if (value != dst.opentherm.options.nativeHeatingControl) { - dst.opentherm.options.nativeHeatingControl = value; + if (value != dst.opentherm.options.alwaysSendIndoorTemp) { + dst.opentherm.options.alwaysSendIndoorTemp = value; + changed = true; + } + } + + if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_NATIVE_OTC)].is()) { + bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_NATIVE_OTC)].as(); + + if (value != dst.opentherm.options.nativeOTC) { + dst.opentherm.options.nativeOTC = value; if (value) { dst.equitherm.enabled = false; @@ -1027,7 +1038,6 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false } } - // mqtt if (src[FPSTR(S_MQTT)][FPSTR(S_ENABLED)].is()) { bool value = src[FPSTR(S_MQTT)][FPSTR(S_ENABLED)].as(); @@ -1118,7 +1128,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false if (src[FPSTR(S_EQUITHERM)][FPSTR(S_ENABLED)].is()) { bool value = src[FPSTR(S_EQUITHERM)][FPSTR(S_ENABLED)].as(); - if (!dst.opentherm.options.nativeHeatingControl) { + if (!dst.opentherm.options.nativeOTC) { if (value != dst.equitherm.enabled) { dst.equitherm.enabled = value; changed = true; @@ -1171,7 +1181,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false if (src[FPSTR(S_PID)][FPSTR(S_ENABLED)].is()) { bool value = src[FPSTR(S_PID)][FPSTR(S_ENABLED)].as(); - if (!dst.opentherm.options.nativeHeatingControl) { + if (!dst.opentherm.options.nativeOTC) { if (value != dst.pid.enabled) { dst.pid.enabled = value; changed = true; @@ -1704,7 +1714,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false // force check emergency target { float value = !src[FPSTR(S_EMERGENCY)][FPSTR(S_TARGET)].isNull() ? src[FPSTR(S_EMERGENCY)][FPSTR(S_TARGET)].as() : dst.emergency.target; - bool noRegulators = !dst.opentherm.options.nativeHeatingControl; + bool noRegulators = !dst.opentherm.options.nativeOTC; bool valid = isValidTemp( value, dst.system.unitSystem, @@ -1729,7 +1739,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false // force check heating target { - bool indoorTempControl = dst.equitherm.enabled || dst.pid.enabled || dst.opentherm.options.nativeHeatingControl; + bool indoorTempControl = dst.equitherm.enabled || dst.pid.enabled || dst.opentherm.options.nativeOTC; float minTemp = indoorTempControl ? THERMOSTAT_INDOOR_MIN_TEMP : dst.heating.minTemp; float maxTemp = indoorTempControl ? THERMOSTAT_INDOOR_MAX_TEMP : dst.heating.maxTemp; diff --git a/src_data/locales/cn.json b/src_data/locales/cn.json index 9910c0f..4d60218 100644 --- a/src_data/locales/cn.json +++ b/src_data/locales/cn.json @@ -457,12 +457,13 @@ "autoFaultReset": "自动报警复位 (不推荐!)", "autoDiagReset": "自动诊断复位 (不推荐!)", "setDateAndTime": "同步设置锅炉日期与时间", - "immergasFix": "针对Immergas锅炉的兼容性修复" + "immergasFix": "针对Immergas锅炉的兼容性修复", + "alwaysSendIndoorTemp": "一定要给锅炉输送电流和目标温度" }, - "nativeHeating": { - "title": "原生锅炉供暖控制", - "note": "注意: 仅适用于锅炉需接收目标室温并自主调节载热介质温度的场景,与固件中的PID及Equithermq气候补偿功能不兼容。" + "nativeOTC": { + "title": "本地(由锅炉处理)外部温度补偿", + "note": "只有 锅炉能调节冷却液温度时才有效。未经测试。固件中不兼容PID和Equitherm的调压器。" } }, diff --git a/src_data/locales/en.json b/src_data/locales/en.json index 732a5f7..6bc0152 100644 --- a/src_data/locales/en.json +++ b/src_data/locales/en.json @@ -457,12 +457,13 @@ "autoFaultReset": "Auto fault reset (not recommended!)", "autoDiagReset": "Auto diag reset (not recommended!)", "setDateAndTime": "Set date & time on boiler", - "immergasFix": "Fix for Immergas boilers" + "immergasFix": "Fix for Immergas boilers", + "alwaysSendIndoorTemp": "Always send current and target indoor temp to boiler" }, - "nativeHeating": { - "title": "Native heating control (boiler)", - "note": "Works ONLY if the boiler requires the desired room temperature and regulates the temperature of the coolant itself. Not compatible with PID and Equitherm regulators in firmware." + "nativeOTC": { + "title": "Native (handled by boiler) Outside Temp Compensation", + "note": "Works ONLY if the boiler regulates the temperature of the coolant itself. Untested. Not compatible with PID and Equitherm regulators in firmware." } }, diff --git a/src_data/locales/it.json b/src_data/locales/it.json index 2a5ca65..7792efb 100644 --- a/src_data/locales/it.json +++ b/src_data/locales/it.json @@ -457,12 +457,13 @@ "autoFaultReset": "Ripristino automatico degli errori (sconsigliato!)", "autoDiagReset": "Ripristino diagnostico automatica (sconsigliato!)", "setDateAndTime": "Imposta data e ora sulla caldaia", - "immergasFix": "Fix per caldiaie Immergas" + "immergasFix": "Fix per caldiaie Immergas", + "alwaysSendIndoorTemp": "Invia sempre corrente e la temperatura interna target alla caldaia" }, - "nativeHeating": { - "title": "Controllo del riscaldamento nativo (caldaia)", - "note": "Lavora SOLO se la caldaia richiede la temperatura ambiente desiderata e regola autonomamente la temperatura del fluido. Non compatiblile con regolazioni PID e Equitherm del sistema." + "nativeOTC": { + "title": "Compensazione della temperatura esterna nativa (gestita dalla caldaia)", + "note": "Lavora SOLO se la caldaia regola la temperatura del liquido refrigerante stesso. Testate. Non compatibile con i regolatori PID ed Equitherm nel firmware." } }, diff --git a/src_data/locales/nl.json b/src_data/locales/nl.json index 0f8970b..af4e063 100644 --- a/src_data/locales/nl.json +++ b/src_data/locales/nl.json @@ -422,11 +422,12 @@ "autoFaultReset": "Automatische storingsreset (niet aanbevolen!)", "autoDiagReset": "Automatische diagnosereset (niet aanbevolen!)", "setDateAndTime": "Stel datum & tijd in op ketel", - "immergasFix": "Fix voor Immergas-ketels" + "immergasFix": "Fix voor Immergas-ketels", + "alwaysSendIndoorTemp": "Stuur altijd de stroom- en streeftemperatuur binnen naar de ketel" }, - "nativeHeating": { - "title": "Natuurlijke verwarmingsregeling (ketel)", - "note": "Werkt ALLEEN als de ketel de gewenste kamertemperatuur vereist en zelf de temperatuur van de warmtedrager regelt. Niet compatibel met PID- en Equitherm-regelaars in de firmware." + "nativeOTC": { + "title": "Native (afgehandeld door de ketel) Buitentemperatuurcompensatie", + "note": "Werkt ALLEEN als de ketel de temperatuur van de koelvloeistof zelf regelt. Geteste. Niet compatibel met PID- en Equitherm-regelaars in firmware" } }, "mqtt": { diff --git a/src_data/locales/ru.json b/src_data/locales/ru.json index 707ca30..6bce482 100644 --- a/src_data/locales/ru.json +++ b/src_data/locales/ru.json @@ -457,12 +457,13 @@ "autoFaultReset": "Автоматический сброс ошибок (не рекомендуется!)", "autoDiagReset": "Автоматический сброс диагностики (не рекомендуется!)", "setDateAndTime": "Устанавливать время и дату на котле", - "immergasFix": "Фикс для котлов Immergas" + "immergasFix": "Фикс для котлов Immergas", + "alwaysSendIndoorTemp": "Всегда отправляйте ток и целевую температуру в помещении в котёл" }, - "nativeHeating": { - "title": "Передать управление отоплением котлу", - "note": "Работает ТОЛЬКО если котел требует и принимает целевую температуру в помещении и сам регулирует температуру теплоносителя на основе встроенного режима кривых. Несовместимо с ПИД и ПЗА." + "nativeOTC": { + "title": "Нативная (обрабатывается котлом) Внешняя компенсация температуры", + "note": "Работает ТОЛЬКО если котёл регулирует температуру самого охлаждающей жидкости. Непроверенных. Несовместимо с регуляторами PID и Equitherm в прошивке." } }, diff --git a/src_data/pages/settings.html b/src_data/pages/settings.html index 8630dbc..aca7079 100644 --- a/src_data/pages/settings.html +++ b/src_data/pages/settings.html @@ -692,12 +692,17 @@ settings.ot.options.immergasFix + +
@@ -1117,8 +1122,9 @@ setCheckboxValue("[name='opentherm[options][autoFaultReset]']", data.opentherm.options.autoFaultReset); setCheckboxValue("[name='opentherm[options][autoDiagReset]']", data.opentherm.options.autoDiagReset); setCheckboxValue("[name='opentherm[options][setDateAndTime]']", data.opentherm.options.setDateAndTime); - setCheckboxValue("[name='opentherm[options][nativeHeatingControl]']", data.opentherm.options.nativeHeatingControl); + setCheckboxValue("[name='opentherm[options][nativeOTC]']", data.opentherm.options.nativeOTC); setCheckboxValue("[name='opentherm[options][immergasFix]']", data.opentherm.options.immergasFix); + setCheckboxValue("[name='opentherm[options][alwaysSendIndoorTemp]']", data.opentherm.options.alwaysSendIndoorTemp); setBusy('#ot-settings-busy', '#ot-settings', false); // MQTT @@ -1206,7 +1212,7 @@ setBusy('#dhw-settings-busy', '#dhw-settings', false); // Emergency mode - if (data.opentherm.options.nativeHeatingControl) { + if (data.opentherm.options.nativeOTC) { setInputValue("[name='emergency[target]']", data.emergency.target, { "min": data.system.unitSystem == 0 ? 5 : 41, "max": data.system.unitSystem == 0 ? 40 : 104