feat: configure OpenTherm channel disabling actions

This commit is contained in:
Yurii committed 2026-10-20 05:26:31 +03:00
1 parent 4581ca49cb
commit c63b8d44a1
11 files changed
+229 -94

No files matched your search

+47 -32
View File
@@ -182,7 +182,8 @@ protected:
&& !vars.master.heating.overheat;
// DHW settings
vars.master.dhw.enabled = settings.opentherm.options.dhwSupport
vars.master.dhw.enabled = this->isReady()
&& settings.opentherm.options.dhwSupport
&& settings.dhw.enabled
&& !vars.master.dhw.overheat;
vars.master.dhw.targetTemp = settings.dhw.target;
@@ -190,7 +191,7 @@ protected:
// CH2 settings
vars.master.ch2.enabled = settings.opentherm.options.ch2AlwaysEnabled
|| (settings.opentherm.options.heatingToCh2 && vars.master.heating.enabled)
|| (settings.opentherm.options.dhwToCh2 && settings.opentherm.options.dhwSupport && settings.dhw.enabled);
|| (settings.opentherm.options.dhwToCh2 && vars.master.dhw.enabled);
if (settings.opentherm.options.heatingToCh2) {
vars.master.ch2.targetTemp = !settings.opentherm.options.nativeOTC
@@ -211,6 +212,7 @@ protected:
statusLb = 0xCA;
}
// Mode flags follow the channel request, before applying its disabling action.
// Summer/winter mode
bool summerWinterMode = settings.opentherm.options.summerWinterMode;
if (settings.opentherm.options.heatingStateToSummerWinterMode) {
@@ -224,11 +226,11 @@ protected:
}
unsigned long response = this->instance->setBoilerStatus(
vars.master.heating.enabled,
vars.master.dhw.enabled,
this->getSlaveChannelEnabled(vars.master.heating.enabled, settings.opentherm.heatingDisablingAction),
settings.opentherm.options.dhwSupport && this->getSlaveChannelEnabled(vars.master.dhw.enabled, settings.opentherm.dhwDisablingAction),
settings.opentherm.options.coolingSupport,
settings.opentherm.options.nativeOTC,
vars.master.ch2.enabled,
this->getSlaveChannelEnabled(vars.master.ch2.enabled, settings.opentherm.ch2DisablingAction),
summerWinterMode,
dhwBlocking,
statusLb
@@ -1222,16 +1224,14 @@ protected:
// Update DHW temp
if (vars.master.dhw.enabled) {
if (settings.opentherm.options.dhwSupport) {
// Target dhw temp
const float& targetTemp = vars.master.dhw.targetTemp;
const float targetTemp = this->getSlaveChannelSetpoint(
vars.master.dhw.enabled, vars.master.dhw.targetTemp, settings.opentherm.dhwDisablingAction
);
// Converted target dhw temp
const float convertedTemp = convertTemp(
targetTemp,
settings.system.unitSystem,
settings.opentherm.unitSystem
);
const float convertedTemp = this->convertSetpointTemp(targetTemp);
// Set DHW temp
if (this->needSetDhwTemp(convertedTemp)) {
@@ -1328,19 +1328,16 @@ protected:
// Set heating temp
{
// Target heating temp
float targetTemp = 0.0f;
if (vars.master.heating.enabled) {
targetTemp = !settings.opentherm.options.nativeOTC
? vars.master.heating.setpointTemp
: vars.master.heating.targetTemp;
}
const float targetTemp = this->getSlaveChannelSetpoint(
vars.master.heating.enabled,
settings.opentherm.options.nativeOTC
? vars.master.heating.targetTemp
: vars.master.heating.setpointTemp,
settings.opentherm.heatingDisablingAction
);
// Converted target heating temp
const float convertedTemp = convertTemp(
targetTemp,
settings.system.unitSystem,
settings.opentherm.unitSystem
);
const float convertedTemp = this->convertSetpointTemp(targetTemp);
if (this->needSetHeatingTemp(convertedTemp)) {
// Set max heating temp
@@ -1375,18 +1372,15 @@ protected:
}
// Set CH2 temp
if (settings.opentherm.options.heatingToCh2 || settings.opentherm.options.dhwToCh2) {
if (settings.opentherm.options.heatingToCh2 || settings.opentherm.options.dhwToCh2
|| (!vars.master.ch2.enabled && settings.opentherm.ch2DisablingAction != ChannelDisablingAction::OFF)) {
// Target CH2 heating temp
const float targetTemp = vars.master.ch2.enabled
? vars.master.ch2.targetTemp
: 0.0f;
const float targetTemp = this->getSlaveChannelSetpoint(
vars.master.ch2.enabled, vars.master.ch2.targetTemp, settings.opentherm.ch2DisablingAction
);
// Converted target CH2 temp
const float convertedTemp = convertTemp(
targetTemp,
settings.system.unitSystem,
settings.opentherm.unitSystem
);
const float convertedTemp = this->convertSetpointTemp(targetTemp);
if (this->needSetCh2Temp(convertedTemp)) {
if (this->setCh2Temp(convertedTemp)) {
@@ -1556,6 +1550,27 @@ protected:
return millis() - this->instanceCreatedTime > this->readyTime;
}
bool getSlaveChannelEnabled(const bool enabled, const ChannelDisablingAction action) {
return enabled || action == ChannelDisablingAction::ZERO_SETPOINT;
}
float getSlaveChannelSetpoint(const bool enabled, const float temperature, const ChannelDisablingAction action) {
if (!enabled && action != ChannelDisablingAction::OFF) {
return 0.0f;
}
return temperature;
}
float convertSetpointTemp(const float temperature) {
// Preserve the no-demand zero for TSet/TsetCH2 when converting units.
if (temperature == 0.0f) {
return 0.0f;
}
return convertTemp(temperature, settings.system.unitSystem, settings.opentherm.unitSystem);
}
bool needSetRoomSetpoint(const float target) {
return !this->roomSetTempTime
|| millis() - this->roomSetTempTime > this->heatingSetTempInterval
+3 -1
View File
@@ -58,6 +58,9 @@ struct Settings {
uint8_t rxLedGpio = DEFAULT_OT_RX_LED_GPIO;
uint8_t memberId = 0;
uint8_t flags = 0;
ChannelDisablingAction heatingDisablingAction = ChannelDisablingAction::OFF_AND_ZERO_SETPOINT;
ChannelDisablingAction dhwDisablingAction = ChannelDisablingAction::OFF_AND_ZERO_SETPOINT;
ChannelDisablingAction ch2DisablingAction = ChannelDisablingAction::OFF_AND_ZERO_SETPOINT;
float minPower = 0.0f;
float maxPower = 0.0f;
@@ -113,7 +116,6 @@ struct Settings {
struct {
bool enabled = true;
float value = 0.5f;
HysteresisAction action = HysteresisAction::DISABLE_HEATING;
} hysteresis;
struct {
+4 -3
View File
@@ -163,9 +163,10 @@ enum class UnitSystem : uint8_t {
IMPERIAL = 1
};
enum class HysteresisAction : uint8_t {
DISABLE_HEATING = 0,
SET_ZERO_TARGET = 1
enum class ChannelDisablingAction : uint8_t {
OFF = 0,
ZERO_SETPOINT = 1,
OFF_AND_ZERO_SETPOINT = 2
};
char buffer[255];
+3 -1
View File
@@ -35,7 +35,6 @@ const char L_CASCADE_OUTPUT[] PROGMEM = "CASCADE.OUTPUT";
const char L_EXTPUMP[] PROGMEM = "EXTPUMP";
const char S_ACTION[] PROGMEM = "action";
const char S_ACTIONS[] PROGMEM = "actions";
const char S_ACTIVE[] PROGMEM = "active";
const char S_ADDRESS[] PROGMEM = "address";
@@ -55,6 +54,7 @@ const char S_BUILD[] PROGMEM = "build";
const char S_CASCADE_CONTROL[] PROGMEM = "cascadeControl";
const char S_CHANNEL[] PROGMEM = "channel";
const char S_CH2_ALWAYS_ENABLED[] PROGMEM = "ch2AlwaysEnabled";
const char S_CH2_DISABLING_ACTION[] PROGMEM = "ch2DisablingAction";
const char S_CHIP[] PROGMEM = "chip";
const char S_CODE[] PROGMEM = "code";
const char S_COMMIT[] PROGMEM = "commit";
@@ -71,6 +71,7 @@ const char S_DATE[] PROGMEM = "date";
const char S_DEADBAND[] PROGMEM = "deadband";
const char S_DHW[] PROGMEM = "dhw";
const char S_DHW_BLOCKING[] PROGMEM = "dhwBlocking";
const char S_DHW_DISABLING_ACTION[] PROGMEM = "dhwDisablingAction";
const char S_DHW_STATE_AS_DHW_BLOCKING[] PROGMEM = "dhwStateAsDhwBlocking";
const char S_DHW_SUPPORT[] PROGMEM = "dhwSupport";
const char S_DHW_TO_CH2[] PROGMEM = "dhwToCh2";
@@ -102,6 +103,7 @@ const char S_GET_MIN_MAX_TEMP[] PROGMEM = "getMinMaxTemp";
const char S_GPIO[] PROGMEM = "gpio";
const char S_HEAP[] PROGMEM = "heap";
const char S_HEATING[] PROGMEM = "heating";
const char S_HEATING_DISABLING_ACTION[] PROGMEM = "heatingDisablingAction";
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";
+38 -18
View File
@@ -444,6 +444,9 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) {
opentherm[FPSTR(S_RX_LED_GPIO)] = src.opentherm.rxLedGpio;
opentherm[FPSTR(S_MEMBER_ID)] = src.opentherm.memberId;
opentherm[FPSTR(S_FLAGS)] = src.opentherm.flags;
opentherm[FPSTR(S_HEATING_DISABLING_ACTION)] = static_cast<uint8_t>(src.opentherm.heatingDisablingAction);
opentherm[FPSTR(S_DHW_DISABLING_ACTION)] = static_cast<uint8_t>(src.opentherm.dhwDisablingAction);
opentherm[FPSTR(S_CH2_DISABLING_ACTION)] = static_cast<uint8_t>(src.opentherm.ch2DisablingAction);
opentherm[FPSTR(S_MIN_POWER)] = roundf(src.opentherm.minPower, 2);
opentherm[FPSTR(S_MAX_POWER)] = roundf(src.opentherm.maxPower, 2);
@@ -489,7 +492,6 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) {
heating[FPSTR(S_TARGET)] = roundf(src.heating.target, 2);
heating[FPSTR(S_HYSTERESIS)][FPSTR(S_ENABLED)] = src.heating.hysteresis.enabled;
heating[FPSTR(S_HYSTERESIS)][FPSTR(S_VALUE)] = roundf(src.heating.hysteresis.value, 3);
heating[FPSTR(S_HYSTERESIS)][FPSTR(S_ACTION)] = static_cast<uint8_t>(src.heating.hysteresis.action);
heating[FPSTR(S_TURBO_FACTOR)] = roundf(src.heating.turboFactor, 3);
heating[FPSTR(S_MIN_TEMP)] = src.heating.minTemp;
heating[FPSTR(S_MAX_TEMP)] = src.heating.maxTemp;
@@ -570,6 +572,29 @@ inline void safeSettingsToJson(const Settings& src, JsonVariant dst) {
settingsToJson(src, dst, true);
}
bool jsonToChannelDisablingAction(const JsonVariantConst src, ChannelDisablingAction& dst) {
if (!src.is<uint8_t>()) {
return false;
}
const uint8_t value = src.as<uint8_t>();
switch (value) {
case static_cast<uint8_t>(ChannelDisablingAction::OFF):
case static_cast<uint8_t>(ChannelDisablingAction::ZERO_SETPOINT):
case static_cast<uint8_t>(ChannelDisablingAction::OFF_AND_ZERO_SETPOINT):
if (static_cast<uint8_t>(dst) != value) {
dst = static_cast<ChannelDisablingAction>(value);
return true;
}
break;
default:
break;
}
return false;
}
bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false) {
bool changed = false;
@@ -822,6 +847,18 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
}
}
if (jsonToChannelDisablingAction(src[FPSTR(S_OPENTHERM)][FPSTR(S_HEATING_DISABLING_ACTION)], dst.opentherm.heatingDisablingAction)) {
changed = true;
}
if (jsonToChannelDisablingAction(src[FPSTR(S_OPENTHERM)][FPSTR(S_DHW_DISABLING_ACTION)], dst.opentherm.dhwDisablingAction)) {
changed = true;
}
if (jsonToChannelDisablingAction(src[FPSTR(S_OPENTHERM)][FPSTR(S_CH2_DISABLING_ACTION)], dst.opentherm.ch2DisablingAction)) {
changed = true;
}
if (!src[FPSTR(S_OPENTHERM)][FPSTR(S_MIN_POWER)].isNull()) {
float value = src[FPSTR(S_OPENTHERM)][FPSTR(S_MIN_POWER)].as<float>();
@@ -1332,23 +1369,6 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
}
}
if (!src[FPSTR(S_HEATING)][FPSTR(S_HYSTERESIS)][FPSTR(S_ACTION)].isNull()) {
uint8_t value = src[FPSTR(S_HEATING)][FPSTR(S_HYSTERESIS)][FPSTR(S_ACTION)].as<uint8_t>();
switch (value) {
case static_cast<uint8_t>(HysteresisAction::DISABLE_HEATING):
case static_cast<uint8_t>(HysteresisAction::SET_ZERO_TARGET):
if (static_cast<uint8_t>(dst.heating.hysteresis.action) != value) {
dst.heating.hysteresis.action = static_cast<HysteresisAction>(value);
changed = true;
}
break;
default:
break;
}
}
if (!src[FPSTR(S_HEATING)][FPSTR(S_TURBO_FACTOR)].isNull()) {
float value = src[FPSTR(S_HEATING)][FPSTR(S_TURBO_FACTOR)].as<float>();
+11 -6
View File
@@ -352,12 +352,7 @@
"hyst": {
"title": "滞回",
"desc": "滞回有助于维持设定的室内温度(在使用«Equitherm»和/或«PID»时)。强制禁用加热当<code>current indoor > target + value</code>,启用加热当<code>current indoor < (target - value)</code>。",
"value": "值 <small>(以度为单位)</small>",
"action": {
"title": "行动",
"disableHeating": "禁用加热",
"set0target": "设置空目标"
}
"value": "值 <small>(以度为单位)</small>"
},
"turboFactor": "Turbo 模式系数",
"indoorTempAvgType": {
@@ -420,6 +415,16 @@
}
},
"ot": {
"disablingAction": {
"title": "回路关闭方式",
"desc": "无论因何原因关闭回路,包括过热,均采用所选的关闭方式。<br />某些锅炉会在关闭回路时停止循环泵,此时可尝试将目标温度设为 <b>0</b>,以使循环泵的延时运转功能正常工作。",
"heating": "采暖回路",
"dhw": "生活热水回路",
"ch2": "回路 2",
"off": "仅关闭回路",
"zeroSetpoint": "将目标温度设为 <b>0</b>",
"offAndZeroSetpoint": "关闭回路并将目标温度设为 <b>0</b>"
},
"advanced": "高级设置",
"inGpio": "In GPIO",
"outGpio": "Out GPIO",
+11 -6
View File
@@ -352,12 +352,7 @@
"hyst": {
"title": "Hysteresis",
"desc": "Hysteresis is useful for maintaining a set indoor temp (when using «Equitherm» and/or «PID»). Forces disable heating when <code>current indoor > target + value</code> and enable heating when <code>current indoor < (target - value)</code>.",
"value": "Value <small>(in degrees)</small>",
"action": {
"title": "Action",
"disableHeating": "Disable heating",
"set0target": "Set null target"
}
"value": "Value <small>(in degrees)</small>"
},
"turboFactor": "Turbo mode coeff.",
"indoorTempAvgType": {
@@ -420,6 +415,16 @@
}
},
"ot": {
"disablingAction": {
"title": "Circuit disabling action",
"desc": "The selected action applies whenever the circuit is disabled, including overheating.<br />Some boilers stop the circulation pump when the circuit is disabled. In this case, you can try setting the target temperature to <b>0</b> so that the pump overrun works correctly.",
"heating": "Heating circuit",
"dhw": "DHW circuit",
"ch2": "Circuit 2",
"off": "Disable circuit only",
"zeroSetpoint": "Set the target temperature to <b>0</b>",
"offAndZeroSetpoint": "Disable circuit and set the target temperature to <b>0</b>"
},
"advanced": "Advanced Settings",
"inGpio": "In GPIO",
"outGpio": "Out GPIO",
+11 -6
View File
@@ -352,12 +352,7 @@
"hyst": {
"title": "Isteresi",
"desc": "L'isteresi è utile per mantenere una temperatura interna impostata (quando si utilizza «Equitherm» e/o «PID»). Forza la disabilitazione del riscaldamento quando <code>current indoor > target + value</code> e abilita il riscaldamento quando <code>current indoor < (target - value)</code>.",
"value": "Valore <small>(in gradi)</small>",
"action": {
"title": "Azione",
"disableHeating": "Disabilita riscaldamento",
"set0target": "Imposta target nullo"
}
"value": "Valore <small>(in gradi)</small>"
},
"turboFactor": "Turbo mode coeff.",
"indoorTempAvgType": {
@@ -420,6 +415,16 @@
}
},
"ot": {
"disablingAction": {
"title": "Azione di disattivazione dei circuiti",
"desc": "L'azione selezionata si applica a ogni disattivazione del circuito, anche in caso di surriscaldamento.<br />Alcune caldaie arrestano la pompa di circolazione quando il circuito viene disattivato; in questo caso si può provare a impostare la temperatura desiderata a <b>0</b>, affinché la post-circolazione della pompa funzioni correttamente.",
"heating": "Circuito di riscaldamento",
"dhw": "Circuito ACS",
"ch2": "Circuito 2",
"off": "Disattiva solo il circuito",
"zeroSetpoint": "Imposta la temperatura desiderata a <b>0</b>",
"offAndZeroSetpoint": "Disattiva il circuito e imposta la temperatura desiderata a <b>0</b>"
},
"advanced": "Impostazioni avanzate",
"inGpio": "In GPIO",
"outGpio": "Out GPIO",
+11 -6
View File
@@ -352,12 +352,7 @@
"hyst": {
"title": "Hysterese",
"desc": "Hysterese is nuttig voor het handhaven van een ingestelde binnentemperatuur (bij gebruik van «Equitherm» en/of «PID»). Forceert uitschakelen van verwarming wanneer <code>current indoor > target + value</code> en inschakelen van verwarming wanneer <code>current indoor < (target - value)</code>.",
"value": "Waarde <small>(in graden)</small>",
"action": {
"title": "Actie",
"disableHeating": "Verwarming uitschakelen",
"set0target": "Stel null target in"
}
"value": "Waarde <small>(in graden)</small>"
},
"turboFactor": "Turbomodus coëff.",
"indoorTempAvgType": {
@@ -420,6 +415,16 @@
}
},
"ot": {
"disablingAction": {
"title": "Actie bij uitschakelen van circuits",
"desc": "De gekozen actie geldt bij elke uitschakeling van het circuit, ook bij oververhitting.<br />Sommige ketels schakelen de circulatiepomp uit wanneer het circuit wordt uitgeschakeld. In dat geval kunt u proberen de doeltemperatuur op <b>0</b> in te stellen, zodat de pompnaloop correct werkt.",
"heating": "Verwarmingscircuit",
"dhw": "Warmtapwatercircuit",
"ch2": "Circuit 2",
"off": "Alleen het circuit uitschakelen",
"zeroSetpoint": "Doeltemperatuur op <b>0</b> instellen",
"offAndZeroSetpoint": "Circuit uitschakelen en doeltemperatuur op <b>0</b> instellen"
},
"advanced": "Geavanceerde instellingen",
"inGpio": "In GPIO",
"outGpio": "Uit GPIO",
+11 -6
View File
@@ -352,12 +352,7 @@
"hyst": {
"title": "Гистерезис",
"desc": "Гистерезис полезен для поддержания заданной внутр. темп. (при использовании «ПЗА» и/или «ПИД»). Принудительно откл. отопление, когда <code>current indoor > target + value</code>, и вкл. отопление, когда <code>current indoor < (target - value)</code>.",
"value": "Значение <small>(в градусах)</small>",
"action": {
"title": "Действие",
"disableHeating": "Отключить отопление",
"set0target": "Установить 0 в качестве целевой темп."
}
"value": "Значение <small>(в градусах)</small>"
},
"turboFactor": "Коэфф. турбо режима",
"indoorTempAvgType": {
@@ -420,6 +415,16 @@
}
},
"ot": {
"disablingAction": {
"title": "Действие отключения контуров",
"desc": "Выбранное действие применяется при любой причине отключения, включая перегрев.<br />Некоторые котлы отключают циркуляционный насос при отключении контура, в этом случае можно попробовать установить <b>0</b> в качестве целевой температуры, чтобы выбег насоса работал корректно.",
"heating": "Контур отопления",
"dhw": "Контур ГВС",
"ch2": "Контур 2",
"off": "Только отключить контур",
"zeroSetpoint": "Установить <b>0</b> в качестве целевой температуры",
"offAndZeroSetpoint": "Отключить контур и установить <b>0</b> в качестве целевой температуры"
},
"advanced": "Дополнительные настройки",
"inGpio": "Вход GPIO",
"outGpio": "Выход GPIO",
+79 -9
View File
@@ -239,13 +239,6 @@
<input type="number" inputmode="decimal" name="heating[hysteresis][value]" min="0" max="5" step="0.05" required>
</label>
<label>
<span data-i18n>settings.heating.hyst.action.title</span>
<select name="heating[hysteresis][action]">
<option value="0" data-i18n>settings.heating.hyst.action.disableHeating</option>
<option value="1" data-i18n>settings.heating.hyst.action.set0target</option>
</select>
</label>
</div>
</div>
@@ -621,6 +614,81 @@
</label>
</div>
<hr />
<details>
<summary><b data-i18n>settings.ot.disablingAction.title</b></summary>
<div>
<fieldset>
<small data-i18n>settings.ot.disablingAction.desc</small>
</fieldset>
<fieldset>
<legend><b data-i18n>settings.ot.disablingAction.heating</b></legend>
<label>
<input type="radio" name="opentherm[heatingDisablingAction]" value="0" />
<span data-i18n>settings.ot.disablingAction.off</span>
</label>
<label>
<input type="radio" name="opentherm[heatingDisablingAction]" value="1" />
<span data-i18n>settings.ot.disablingAction.zeroSetpoint</span>
</label>
<label>
<input type="radio" name="opentherm[heatingDisablingAction]" value="2" />
<span data-i18n>settings.ot.disablingAction.offAndZeroSetpoint</span>
</label>
</fieldset>
<hr />
<fieldset>
<legend><b data-i18n>settings.ot.disablingAction.dhw</b></legend>
<label>
<input type="radio" name="opentherm[dhwDisablingAction]" value="0" />
<span data-i18n>settings.ot.disablingAction.off</span>
</label>
<label>
<input type="radio" name="opentherm[dhwDisablingAction]" value="1" />
<span data-i18n>settings.ot.disablingAction.zeroSetpoint</span>
</label>
<label>
<input type="radio" name="opentherm[dhwDisablingAction]" value="2" />
<span data-i18n>settings.ot.disablingAction.offAndZeroSetpoint</span>
</label>
</fieldset>
<hr />
<fieldset>
<legend><b data-i18n>settings.ot.disablingAction.ch2</b></legend>
<label>
<input type="radio" name="opentherm[ch2DisablingAction]" value="0" />
<span data-i18n>settings.ot.disablingAction.off</span>
</label>
<label>
<input type="radio" name="opentherm[ch2DisablingAction]" value="1" />
<span data-i18n>settings.ot.disablingAction.zeroSetpoint</span>
</label>
<label>
<input type="radio" name="opentherm[ch2DisablingAction]" value="2" />
<span data-i18n>settings.ot.disablingAction.offAndZeroSetpoint</span>
</label>
</fieldset>
</div>
</details>
<hr />
<details>
<summary><b data-i18n>settings.ot.options.title</b></summary>
@@ -1124,6 +1192,9 @@
setInputValue("[name='opentherm[flags]']", data.opentherm.flags);
setInputValue("[name='opentherm[minPower]']", data.opentherm.minPower);
setInputValue("[name='opentherm[maxPower]']", data.opentherm.maxPower);
setRadioValue("[name='opentherm[heatingDisablingAction]']", data.opentherm.heatingDisablingAction);
setRadioValue("[name='opentherm[dhwDisablingAction]']", data.opentherm.dhwDisablingAction);
setRadioValue("[name='opentherm[ch2DisablingAction]']", data.opentherm.ch2DisablingAction);
setCheckboxValue("[name='opentherm[options][dhwSupport]']", data.opentherm.options.dhwSupport);
setCheckboxValue("[name='opentherm[options][coolingSupport]']", data.opentherm.options.coolingSupport);
setCheckboxValue("[name='opentherm[options][summerWinterMode]']", data.opentherm.options.summerWinterMode);
@@ -1190,7 +1261,6 @@
});
setCheckboxValue("[name='heating[hysteresis][enabled]']", data.heating.hysteresis.enabled);
setInputValue("[name='heating[hysteresis][value]']", data.heating.hysteresis.value);
setSelectValue("[name='heating[hysteresis][action]']", data.heating.hysteresis.action);
setInputValue("[name='heating[turboFactor]']", data.heating.turboFactor);
setInputValue("[name='heating[maxModulation]']", data.heating.maxModulation);
setSelectValue("[name='heating[indoorTempAvgType]']", data.heating.indoorTempAvgType);
@@ -1402,4 +1472,4 @@
});
</script>
</body>
</html>
</html>