From e63a0dc7eb6f4341be4738e791f4ec6bd7c80e4f Mon Sep 17 00:00:00 2001 From: Yurii Date: Mon, 30 Jun 2025 02:41:44 +0300 Subject: [PATCH] refactor: improved freeze protection & overheat protection; added desc for OT options --- src/MainTask.h | 75 +++++++---- src/OpenThermTask.h | 20 +-- src/Settings.h | 20 ++- src/strings.h | 7 +- src/utils.h | 76 ++++++----- src_data/locales/en.json | 17 ++- src_data/locales/it.json | 17 ++- src_data/locales/ru.json | 17 ++- src_data/pages/settings.html | 243 ++++++++++++++++++++--------------- 9 files changed, 299 insertions(+), 193 deletions(-) diff --git a/src/MainTask.h b/src/MainTask.h index c60c7b3..af02b60 100644 --- a/src/MainTask.h +++ b/src/MainTask.h @@ -29,6 +29,7 @@ protected: enum class PumpStartReason {NONE, HEATING, ANTISTUCK}; Blinker* blinker = nullptr; + unsigned long miscRunned = 0; unsigned long lastHeapInfo = 0; unsigned int minFreeHeap = 0; unsigned int minMaxFreeBlockHeap = 0; @@ -42,6 +43,8 @@ protected: bool telnetStarted = false; bool emergencyDetected = false; unsigned long emergencyFlipTime = 0; + bool freezeDetected = false; + unsigned long freezeDetectedTime = 0; #if defined(ARDUINO_ARCH_ESP32) const char* getTaskName() override { @@ -150,18 +153,16 @@ protected: Sensors::setConnectionStatusByType(Sensors::Type::MANUAL, false, false); } - this->yield(); - this->heating(); - this->emergency(); + this->yield(); + if (this->misc()) { + this->yield(); + } this->ledStatus(); - this->cascadeControl(); - this->externalPump(); - this->yield(); - // telnet if (this->telnetStarted) { + this->yield(); telnetStream->loop(); this->yield(); } @@ -180,14 +181,27 @@ protected: // heap info this->heap(); + } + bool misc() { + if (millis() - this->miscRunned < 1000) { + return false; + } - // restart + // restart if required if (this->restartSignalReceived && millis() - this->restartSignalReceivedTime > 15000) { this->restartSignalReceived = false; ESP.restart(); } + + this->heating(); + this->emergency(); + this->cascadeControl(); + this->externalPump(); + this->miscRunned = millis(); + + return true; } void heap() { @@ -230,15 +244,15 @@ protected: } void heating() { - // anti freeze protection + // freeze protection if (!settings.heating.enabled) { - float minTemp = 255.0f; + float lowTemp = 255.0f; uint8_t availableSensors = 0; if (Sensors::existsConnectedSensorsByPurpose(Sensors::Purpose::INDOOR_TEMP)) { auto value = Sensors::getMeanValueByPurpose(Sensors::Purpose::INDOOR_TEMP, Sensors::ValueType::PRIMARY); - if (value < minTemp) { - minTemp = value; + if (value < lowTemp) { + lowTemp = value; } availableSensors++; @@ -246,8 +260,8 @@ protected: if (Sensors::existsConnectedSensorsByPurpose(Sensors::Purpose::HEATING_TEMP)) { auto value = Sensors::getMeanValueByPurpose(Sensors::Purpose::HEATING_TEMP, Sensors::ValueType::PRIMARY); - if (value < minTemp) { - minTemp = value; + if (value < lowTemp) { + lowTemp = value; } availableSensors++; @@ -255,23 +269,36 @@ protected: if (Sensors::existsConnectedSensorsByPurpose(Sensors::Purpose::HEATING_RETURN_TEMP)) { auto value = Sensors::getMeanValueByPurpose(Sensors::Purpose::HEATING_RETURN_TEMP, Sensors::ValueType::PRIMARY); - if (value < minTemp) { - minTemp = value; + if (value < lowTemp) { + lowTemp = value; } availableSensors++; } - if (availableSensors && minTemp <= settings.heating.antiFreezeTemp) { - settings.heating.enabled = true; - fsSettings.update(); + if (availableSensors && lowTemp <= settings.heating.freezeProtection.lowTemp) { + if (!this->freezeDetected) { + this->freezeDetected = true; + this->freezeDetectedTime = millis(); - Log.sinfoln( - FPSTR(L_MAIN), - F("Heating turned on by anti freeze protection, current min temp: %.2f, threshold: %hhu"), - minTemp, settings.heating.antiFreezeTemp - ); + } else if (millis() - this->freezeDetectedTime > (settings.heating.freezeProtection.thresholdTime * 1000)) { + this->freezeDetected = false; + settings.heating.enabled = true; + fsSettings.update(); + + Log.sinfoln( + FPSTR(L_MAIN), + F("Heating turned on by freeze protection, current low temp: %.2f, threshold: %hhu"), + lowTemp, settings.heating.freezeProtection.lowTemp + ); + } + + } else if (this->freezeDetected) { + this->freezeDetected = false; } + + } else if (this->freezeDetected) { + this->freezeDetected = false; } } diff --git a/src/OpenThermTask.h b/src/OpenThermTask.h index 21d9084..4b7543b 100644 --- a/src/OpenThermTask.h +++ b/src/OpenThermTask.h @@ -1320,7 +1320,7 @@ protected: // Heating overheat control - if (settings.heating.overheatHighTemp > 0 && settings.heating.overheatLowTemp > 0) { + if (settings.heating.overheatProtection.highTemp > 0 && settings.heating.overheatProtection.lowTemp > 0) { float highTemp = convertTemp( max({ vars.slave.heating.currentTemp, @@ -1332,22 +1332,22 @@ protected: ); if (vars.master.heating.overheat) { - if ((float) settings.heating.overheatLowTemp - highTemp + 0.0001f >= 0.0f) { + if ((float) settings.heating.overheatProtection.lowTemp - highTemp + 0.0001f >= 0.0f) { vars.master.heating.overheat = false; Log.sinfoln( FPSTR(L_OT_HEATING), F("Overheating not detected. Current high temp: %.2f, threshold (low): %hhu"), - highTemp, settings.heating.overheatLowTemp + highTemp, settings.heating.overheatProtection.lowTemp ); } } else if (vars.slave.heating.active) { - if (highTemp - (float) settings.heating.overheatHighTemp + 0.0001f >= 0.0f) { + if (highTemp - (float) settings.heating.overheatProtection.highTemp + 0.0001f >= 0.0f) { vars.master.heating.overheat = true; Log.swarningln( FPSTR(L_OT_HEATING), F("Overheating detected! Current high temp: %.2f, threshold (high): %hhu"), - highTemp, settings.heating.overheatHighTemp + highTemp, settings.heating.overheatProtection.highTemp ); } } @@ -1357,7 +1357,7 @@ protected: } // DHW overheat control - if (settings.dhw.overheatHighTemp > 0 && settings.dhw.overheatLowTemp > 0) { + if (settings.dhw.overheatProtection.highTemp > 0 && settings.dhw.overheatProtection.lowTemp > 0) { float highTemp = convertTemp( max({ vars.slave.heating.currentTemp, @@ -1372,22 +1372,22 @@ protected: ); if (vars.master.dhw.overheat) { - if ((float) settings.dhw.overheatLowTemp - highTemp + 0.0001f >= 0.0f) { + if ((float) settings.dhw.overheatProtection.lowTemp - highTemp + 0.0001f >= 0.0f) { vars.master.dhw.overheat = false; Log.sinfoln( FPSTR(L_OT_DHW), F("Overheating not detected. Current high temp: %.2f, threshold (low): %hhu"), - highTemp, settings.dhw.overheatLowTemp + highTemp, settings.dhw.overheatProtection.lowTemp ); } } else if (vars.slave.dhw.active) { - if (highTemp - (float) settings.dhw.overheatHighTemp + 0.0001f >= 0.0f) { + if (highTemp - (float) settings.dhw.overheatProtection.highTemp + 0.0001f >= 0.0f) { vars.master.dhw.overheat = true; Log.swarningln( FPSTR(L_OT_DHW), F("Overheating detected! Current high temp: %.2f, threshold (high): %hhu"), - highTemp, settings.dhw.overheatHighTemp + highTemp, settings.dhw.overheatProtection.highTemp ); } } diff --git a/src/Settings.h b/src/Settings.h index 731e4e4..af71a46 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -108,9 +108,16 @@ struct Settings { byte minTemp = DEFAULT_HEATING_MIN_TEMP; byte maxTemp = DEFAULT_HEATING_MAX_TEMP; uint8_t maxModulation = 100; - uint8_t overheatHighTemp = 95; - uint8_t overheatLowTemp = 90; - uint8_t antiFreezeTemp = 10; + + struct { + uint8_t highTemp = 95; + uint8_t lowTemp = 90; + } overheatProtection; + + struct { + uint8_t lowTemp = 10; + unsigned short thresholdTime = 600; + } freezeProtection; } heating; struct { @@ -119,8 +126,11 @@ struct Settings { byte minTemp = DEFAULT_DHW_MIN_TEMP; byte maxTemp = DEFAULT_DHW_MAX_TEMP; uint8_t maxModulation = 100; - uint8_t overheatHighTemp = 95; - uint8_t overheatLowTemp = 90; + + struct { + uint8_t highTemp = 95; + uint8_t lowTemp = 90; + } overheatProtection; } dhw; struct { diff --git a/src/strings.h b/src/strings.h index 6876f9b..74e2eaf 100644 --- a/src/strings.h +++ b/src/strings.h @@ -44,7 +44,6 @@ const char S_APP_VERSION[] PROGMEM = "appVersion"; const char S_AUTH[] PROGMEM = "auth"; const char S_AUTO_DIAG_RESET[] PROGMEM = "autoDiagReset"; const char S_AUTO_FAULT_RESET[] PROGMEM = "autoFaultReset"; -const char S_ANTI_FREEZE_TEMP[] PROGMEM = "antiFreezeTemp"; const char S_BACKTRACE[] PROGMEM = "backtrace"; const char S_BATTERY[] PROGMEM = "battery"; const char S_BAUDRATE[] PROGMEM = "baudrate"; @@ -85,6 +84,7 @@ const char S_EQUITHERM[] PROGMEM = "equitherm"; const char S_EXTERNAL_PUMP[] PROGMEM = "externalPump"; const char S_FACTOR[] PROGMEM = "factor"; const char S_FAULT[] PROGMEM = "fault"; +const char S_FREEZE_PROTECTION[] PROGMEM = "freezeProtection"; const char S_FILTERING[] PROGMEM = "filtering"; const char S_FILTERING_FACTOR[] PROGMEM = "filteringFactor"; const char S_FLAGS[] PROGMEM = "flags"; @@ -100,6 +100,7 @@ const char S_HEATING[] PROGMEM = "heating"; const char S_HEATING_TO_CH2[] PROGMEM = "heatingToCh2"; const char S_HEATING_STATE_TO_SUMMER_WINTER_MODE[] PROGMEM = "heatingStateToSummerWinterMode"; const char S_HIDDEN[] PROGMEM = "hidden"; +const char S_HIGH_TEMP[] PROGMEM = "highTemp"; const char S_HOME_ASSISTANT_DISCOVERY[] PROGMEM = "homeAssistantDiscovery"; const char S_HOSTNAME[] PROGMEM = "hostname"; const char S_HUMIDITY[] PROGMEM = "humidity"; @@ -119,6 +120,7 @@ const char S_I_MULTIPLIER[] PROGMEM = "i_multiplier"; const char S_K_FACTOR[] PROGMEM = "k_factor"; const char S_LOGIN[] PROGMEM = "login"; const char S_LOG_LEVEL[] PROGMEM = "logLevel"; +const char S_LOW_TEMP[] PROGMEM = "lowTemp"; const char S_MAC[] PROGMEM = "mac"; const char S_MASTER[] PROGMEM = "master"; const char S_MAX[] PROGMEM = "max"; @@ -152,8 +154,7 @@ const char S_OUTDOOR_TEMP[] PROGMEM = "outdoorTemp"; const char S_OUT_GPIO[] PROGMEM = "outGpio"; const char S_OUTPUT[] PROGMEM = "output"; const char S_OVERHEAT[] PROGMEM = "overheat"; -const char S_OVERHEAT_HIGH_TEMP[] PROGMEM = "overheatHighTemp"; -const char S_OVERHEAT_LOW_TEMP[] PROGMEM = "overheatLowTemp"; +const char S_OVERHEAT_PROTECTION[] PROGMEM = "overheatProtection"; const char S_PASSWORD[] PROGMEM = "password"; const char S_PID[] PROGMEM = "pid"; const char S_PORT[] PROGMEM = "port"; diff --git a/src/utils.h b/src/utils.h index 0835aba..4913357 100644 --- a/src/utils.h +++ b/src/utils.h @@ -495,9 +495,14 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) { heating[FPSTR(S_MIN_TEMP)] = src.heating.minTemp; heating[FPSTR(S_MAX_TEMP)] = src.heating.maxTemp; heating[FPSTR(S_MAX_MODULATION)] = src.heating.maxModulation; - heating[FPSTR(S_OVERHEAT_HIGH_TEMP)] = src.heating.overheatHighTemp; - heating[FPSTR(S_OVERHEAT_LOW_TEMP)] = src.heating.overheatLowTemp; - heating[FPSTR(S_ANTI_FREEZE_TEMP)] = src.heating.antiFreezeTemp; + + auto heatingOverheatProtection = heating[FPSTR(S_OVERHEAT_PROTECTION)].to(); + heatingOverheatProtection[FPSTR(S_HIGH_TEMP)] = src.heating.overheatProtection.highTemp; + heatingOverheatProtection[FPSTR(S_LOW_TEMP)] = src.heating.overheatProtection.lowTemp; + + auto freezeProtection = heating[FPSTR(S_FREEZE_PROTECTION)].to(); + freezeProtection[FPSTR(S_LOW_TEMP)] = src.heating.freezeProtection.lowTemp; + freezeProtection[FPSTR(S_THRESHOLD_TIME)] = src.heating.freezeProtection.thresholdTime; auto dhw = dst[FPSTR(S_DHW)].to(); dhw[FPSTR(S_ENABLED)] = src.dhw.enabled; @@ -505,8 +510,10 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) { dhw[FPSTR(S_MIN_TEMP)] = src.dhw.minTemp; dhw[FPSTR(S_MAX_TEMP)] = src.dhw.maxTemp; dhw[FPSTR(S_MAX_MODULATION)] = src.dhw.maxModulation; - dhw[FPSTR(S_OVERHEAT_HIGH_TEMP)] = src.dhw.overheatHighTemp; - dhw[FPSTR(S_OVERHEAT_LOW_TEMP)] = src.dhw.overheatLowTemp; + + auto dhwOverheatProtection = dhw[FPSTR(S_OVERHEAT_PROTECTION)].to(); + dhwOverheatProtection[FPSTR(S_HIGH_TEMP)] = src.dhw.overheatProtection.highTemp; + dhwOverheatProtection[FPSTR(S_LOW_TEMP)] = src.dhw.overheatProtection.lowTemp; auto equitherm = dst[FPSTR(S_EQUITHERM)].to(); equitherm[FPSTR(S_ENABLED)] = src.equitherm.enabled; @@ -1347,38 +1354,49 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false } } - if (!src[FPSTR(S_HEATING)][FPSTR(S_OVERHEAT_HIGH_TEMP)].isNull()) { - unsigned char value = src[FPSTR(S_HEATING)][FPSTR(S_OVERHEAT_HIGH_TEMP)].as(); + if (!src[FPSTR(S_HEATING)][FPSTR(S_OVERHEAT_PROTECTION)][FPSTR(S_HIGH_TEMP)].isNull()) { + unsigned char value = src[FPSTR(S_HEATING)][FPSTR(S_OVERHEAT_PROTECTION)][FPSTR(S_HIGH_TEMP)].as(); - if (isValidTemp(value, dst.system.unitSystem, 0.0f, 100.0f) && value != dst.heating.overheatHighTemp) { - dst.heating.overheatHighTemp = value; + if (isValidTemp(value, dst.system.unitSystem, 0.0f, 100.0f) && value != dst.heating.overheatProtection.highTemp) { + dst.heating.overheatProtection.highTemp = value; changed = true; } } - if (!src[FPSTR(S_HEATING)][FPSTR(S_OVERHEAT_LOW_TEMP)].isNull()) { - unsigned char value = src[FPSTR(S_HEATING)][FPSTR(S_OVERHEAT_LOW_TEMP)].as(); + if (!src[FPSTR(S_HEATING)][FPSTR(S_OVERHEAT_PROTECTION)][FPSTR(S_LOW_TEMP)].isNull()) { + unsigned char value = src[FPSTR(S_HEATING)][FPSTR(S_OVERHEAT_PROTECTION)][FPSTR(S_LOW_TEMP)].as(); - if (isValidTemp(value, dst.system.unitSystem, 0.0f, 99.0f) && value != dst.heating.overheatLowTemp) { - dst.heating.overheatLowTemp = value; + if (isValidTemp(value, dst.system.unitSystem, 0.0f, 99.0f) && value != dst.heating.overheatProtection.lowTemp) { + dst.heating.overheatProtection.lowTemp = value; changed = true; } } - if (dst.heating.overheatHighTemp < dst.heating.overheatLowTemp) { - dst.heating.overheatHighTemp = dst.heating.overheatLowTemp; + if (dst.heating.overheatProtection.highTemp < dst.heating.overheatProtection.lowTemp) { + dst.heating.overheatProtection.highTemp = dst.heating.overheatProtection.lowTemp; changed = true; } - if (!src[FPSTR(S_HEATING)][FPSTR(S_ANTI_FREEZE_TEMP)].isNull()) { - unsigned short value = src[FPSTR(S_HEATING)][FPSTR(S_ANTI_FREEZE_TEMP)].as(); + if (!src[FPSTR(S_HEATING)][FPSTR(S_FREEZE_PROTECTION)][FPSTR(S_LOW_TEMP)].isNull()) { + unsigned short value = src[FPSTR(S_HEATING)][FPSTR(S_FREEZE_PROTECTION)][FPSTR(S_LOW_TEMP)].as(); - if (isValidTemp(value, dst.system.unitSystem, 1, 30) && value != dst.heating.antiFreezeTemp) { - dst.heating.antiFreezeTemp = value; + if (isValidTemp(value, dst.system.unitSystem, 1, 30) && value != dst.heating.freezeProtection.lowTemp) { + dst.heating.freezeProtection.lowTemp = value; changed = true; } } + if (!src[FPSTR(S_HEATING)][FPSTR(S_FREEZE_PROTECTION)][FPSTR(S_THRESHOLD_TIME)].isNull()) { + unsigned short value = src[FPSTR(S_HEATING)][FPSTR(S_FREEZE_PROTECTION)][FPSTR(S_THRESHOLD_TIME)].as(); + + if (value >= 30 && value <= 1800) { + if (value != dst.heating.freezeProtection.thresholdTime) { + dst.heating.freezeProtection.thresholdTime = value; + changed = true; + } + } + } + // dhw if (src[FPSTR(S_DHW)][FPSTR(S_ENABLED)].is()) { @@ -1422,26 +1440,26 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false } } - if (!src[FPSTR(S_DHW)][FPSTR(S_OVERHEAT_HIGH_TEMP)].isNull()) { - unsigned char value = src[FPSTR(S_DHW)][FPSTR(S_OVERHEAT_HIGH_TEMP)].as(); + if (!src[FPSTR(S_DHW)][FPSTR(S_OVERHEAT_PROTECTION)][FPSTR(S_HIGH_TEMP)].isNull()) { + unsigned char value = src[FPSTR(S_DHW)][FPSTR(S_OVERHEAT_PROTECTION)][FPSTR(S_HIGH_TEMP)].as(); - if (isValidTemp(value, dst.system.unitSystem, 0.0f, 100.0f) && value != dst.dhw.overheatHighTemp) { - dst.dhw.overheatHighTemp = value; + if (isValidTemp(value, dst.system.unitSystem, 0.0f, 100.0f) && value != dst.dhw.overheatProtection.highTemp) { + dst.dhw.overheatProtection.highTemp = value; changed = true; } } - if (!src[FPSTR(S_DHW)][FPSTR(S_OVERHEAT_LOW_TEMP)].isNull()) { - unsigned char value = src[FPSTR(S_DHW)][FPSTR(S_OVERHEAT_LOW_TEMP)].as(); + if (!src[FPSTR(S_DHW)][FPSTR(S_OVERHEAT_PROTECTION)][FPSTR(S_LOW_TEMP)].isNull()) { + unsigned char value = src[FPSTR(S_DHW)][FPSTR(S_OVERHEAT_PROTECTION)][FPSTR(S_LOW_TEMP)].as(); - if (isValidTemp(value, dst.system.unitSystem, 0.0f, 99.0f) && value != dst.dhw.overheatLowTemp) { - dst.dhw.overheatLowTemp = value; + if (isValidTemp(value, dst.system.unitSystem, 0.0f, 99.0f) && value != dst.dhw.overheatProtection.lowTemp) { + dst.dhw.overheatProtection.lowTemp = value; changed = true; } } - if (dst.dhw.overheatHighTemp < dst.dhw.overheatLowTemp) { - dst.dhw.overheatHighTemp = dst.dhw.overheatLowTemp; + if (dst.dhw.overheatProtection.highTemp < dst.dhw.overheatProtection.lowTemp) { + dst.dhw.overheatProtection.highTemp = dst.dhw.overheatProtection.lowTemp; changed = true; } diff --git a/src_data/locales/en.json b/src_data/locales/en.json index b539321..c801561 100644 --- a/src_data/locales/en.json +++ b/src_data/locales/en.json @@ -304,7 +304,7 @@ "max": "Maximum temperature" }, "maxModulation": "Max modulation level", - "overheat": { + "ohProtection": { "title": "Overheating protection", "desc": "Note: This feature can be useful if the built-in boiler overheating protection does not work or does not work correctly and the heat carrier boils. To disable, set 0 as high and low temperature.", "highTemp": { @@ -316,6 +316,12 @@ "note": "Threshold at which the burner can be turned on again" } }, + "freezeProtection": { + "title": "Freeze protection", + "desc": "Heating will be forced to turn on if the heat carrier or indoor temperature drops below Low temperature during Waiting time.", + "lowTemp": "Low temperature threshold", + "thresholdTime": "Waiting time (sec)" + }, "portal": { "login": "Login", @@ -350,11 +356,7 @@ "heating": { "hyst": "Hysteresis (in degrees)", - "turboFactor": "Turbo mode coeff.", - "antiFreezeTemp": { - "title": "Freeze protection temperature", - "note": "If the heat carrier or indoor temperature drops below this value, the heating will be forced to turn on" - } + "turboFactor": "Turbo mode coeff." }, "emergency": { @@ -413,7 +415,8 @@ }, "options": { - "desc": "Options", + "title": "Options (additional settings)", + "desc": "Options can change the logic of the boiler. Not all options are documented in the protocol, so the same option can have different effects on different boilers.
Note: There is no need to change anything if everything works well.", "dhwSupport": "DHW support", "coolingSupport": "Cooling support", "summerWinterMode": "Summer/winter mode", diff --git a/src_data/locales/it.json b/src_data/locales/it.json index 5a33e07..9a13be8 100644 --- a/src_data/locales/it.json +++ b/src_data/locales/it.json @@ -304,7 +304,7 @@ "max": "Temperatura massima" }, "maxModulation": "Max livello modulazione", - "overheat": { + "ohProtection": { "title": "Protezione contro il surriscaldamento", "desc": "Nota: questa funzione può essere utile se la protezione contro il surriscaldamento integrata nella caldaia non funziona o non funziona correttamente e il fluido termovettore bolle. Per disattivarla, impostare 0 come temperatura alta e bassa.", "highTemp": { @@ -316,6 +316,12 @@ "note": "Soglia alla quale il bruciatore può essere riacceso" } }, + "freezeProtection": { + "title": "Protezione antigelo", + "desc": "Il riscaldamento verrà attivato forzatamente se la temperatura del vettore di calore o interna scende al di sotto della temperatura minima durante il tempo di attesa.", + "lowTemp": "Soglia di temperatura minima", + "thresholdTime": "Tempo di attesa (sec)" + }, "portal": { "login": "Login", @@ -350,11 +356,7 @@ "heating": { "hyst": "Isteresi (in gradi)", - "turboFactor": "Turbo mode coeff.", - "antiFreezeTemp": { - "title": "Temperatura di protezione antigelo", - "note": "Se la temperatura del fluido termovettore o interna scende al di sotto di questo valore, il riscaldamento verrà forzato ad accendersi" - } + "turboFactor": "Turbo mode coeff." }, "emergency": { @@ -413,7 +415,8 @@ }, "options": { - "desc": "Opzioni", + "title": "Opzioni (impostazioni aggiuntive)", + "desc": "Le opzioni possono modificare la logica della caldaia. Non tutte le opzioni sono documentate nel protocollo, quindi la stessa opzione può avere effetti diversi su caldaie diverse.
Nota: Non è necessario modificare nulla se tutto funziona correttamente.", "dhwSupport": "Supporto ACS", "coolingSupport": "Supporto rafferscamento", "summerWinterMode": "Modalità Estate/inverno", diff --git a/src_data/locales/ru.json b/src_data/locales/ru.json index a7af639..28055f7 100644 --- a/src_data/locales/ru.json +++ b/src_data/locales/ru.json @@ -304,7 +304,7 @@ "max": "Макс. температура" }, "maxModulation": "Макс. уровень модуляции", - "overheat": { + "ohProtection": { "title": "Защита от перегрева", "desc": "Примечание: Эта функция может быть полезна, если встроенная защита от перегрева котла не срабатывает или срабатывает некорректно и теплоноситель закипает. Для отключения установите 0 в качестве верхнего и нижнего порога температуры.", "highTemp": { @@ -316,6 +316,12 @@ "note": "Порог, при котором горелка может быть включена снова" } }, + "freezeProtection": { + "title": "Защита от замерзания", + "desc": "Отопление будет принудительно включено, если темп. теплоносителя или внутренняя темп. опустится ниже нижнего порога в течение времени ожидания.", + "lowTemp": "Нижний порог температуры", + "thresholdTime": "Время ожидания (сек)" + }, "portal": { "login": "Логин", @@ -350,11 +356,7 @@ "heating": { "hyst": "Гистерезис (в градусах)", - "turboFactor": "Коэфф. турбо режима", - "antiFreezeTemp": { - "title": "Температура защиты от замерзания", - "note": "Отопление будет принудительно включено, если температура теплоносителя или внутренняя температура опустится ниже этого значения" - } + "turboFactor": "Коэфф. турбо режима" }, "emergency": { @@ -413,7 +415,8 @@ }, "options": { - "desc": "Опции", + "title": "Опции (дополнительные настройки)", + "desc": "Опции могут менять логику работы котла. Не все опции задокументированы в протоколе, поэтому одна и та же опция может иметь разный эффект на разных котлах.
Примечание: Нет необходимости что-то менять, если всё работает хорошо.", "dhwSupport": "Поддержка ГВС", "coolingSupport": "Поддержка охлаждения", "summerWinterMode": "Летний/зимний режим", diff --git a/src_data/pages/settings.html b/src_data/pages/settings.html index 37a596a..fe58d94 100644 --- a/src_data/pages/settings.html +++ b/src_data/pages/settings.html @@ -207,33 +207,49 @@ - +
- settings.overheat.title + settings.ohProtection.title
- settings.overheat.desc + settings.ohProtection.desc
-
+
+ +
+ settings.freezeProtection.title + +
+ + + +
+ + settings.freezeProtection.desc +
+ +
@@ -264,27 +280,29 @@ +
+
- settings.overheat.title + settings.ohProtection.title
- settings.overheat.desc + settings.ohProtection.desc
-
+
@@ -533,97 +551,107 @@ -
- settings.ot.options.desc +
+ settings.ot.options.title - +
+
+ settings.ot.options.desc +
- +
+ - + - + - + - + - + - + - + - + - + - + - + - + - + - + -
- -
+ +
+ + +
+ + + +
@@ -930,12 +958,19 @@ setInputValue("[name='heating[hysteresis]']", data.heating.hysteresis); setInputValue("[name='heating[turboFactor]']", data.heating.turboFactor); setInputValue("[name='heating[maxModulation]']", data.heating.maxModulation); - setInputValue("[name='heating[overheatHighTemp]']", data.heating.overheatHighTemp); - setInputValue("[name='heating[overheatLowTemp]']", data.heating.overheatLowTemp); - setInputValue("[name='heating[antiFreezeTemp]']", data.heating.antiFreezeTemp, { + setInputValue("[name='heating[overheatProtection][highTemp]']", data.heating.overheatProtection.highTemp, { + "min": 0, + "max": data.system.unitSystem == 0 ? 100 : 212 + }); + setInputValue("[name='heating[overheatProtection][lowTemp]']", data.heating.overheatProtection.lowTemp, { + "min": 0, + "max": data.system.unitSystem == 0 ? 99 : 211 + }); + setInputValue("[name='heating[freezeProtection][lowTemp]']", data.heating.freezeProtection.lowTemp, { "min": data.system.unitSystem == 0 ? 1 : 34, "max": data.system.unitSystem == 0 ? 30 : 86 }); + setInputValue("[name='heating[freezeProtection][thresholdTime]']", data.heating.freezeProtection.thresholdTime); setBusy('#heating-settings-busy', '#heating-settings', false); // DHW @@ -948,8 +983,14 @@ "max": data.system.unitSystem == 0 ? 100 : 212 }); setInputValue("[name='dhw[maxModulation]']", data.dhw.maxModulation); - setInputValue("[name='dhw[overheatHighTemp]']", data.dhw.overheatHighTemp); - setInputValue("[name='dhw[overheatLowTemp]']", data.dhw.overheatLowTemp); + setInputValue("[name='dhw[overheatProtection][highTemp]']", data.dhw.overheatProtection.highTemp, { + "min": 0, + "max": data.system.unitSystem == 0 ? 100 : 212 + }); + setInputValue("[name='dhw[overheatProtection][lowTemp]']", data.dhw.overheatProtection.lowTemp, { + "min": 0, + "max": data.system.unitSystem == 0 ? 99 : 211 + }); setBusy('#dhw-settings-busy', '#dhw-settings', false); // Emergency mode