mirror of
https://github.com/Laxilef/OTGateway.git
synced 2025-12-14 12:14:28 +05:00
feat: added OT option alwaysSendIndoorTemp, rename nativeHeatingControl to nativeOTC (#204)
* added option to always send the current and target indoor temp, even if the current heating mode doesnt officially need it. This is a direct fix for WeHeat heatpumps which seem to require it. * add option to AlwaysSendIndoorTemp and rename NativeHeatingControl to NativeOTC. Updated locals and settings page. * change minor order
This commit is contained in:
@@ -319,7 +319,7 @@ protected:
|
||||
emergencyFlags |= 0b00000010;
|
||||
}
|
||||
|
||||
if (settings.opentherm.options.nativeHeatingControl) {
|
||||
if (settings.opentherm.options.nativeOTC) {
|
||||
emergencyFlags |= 0b00000100;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
|
||||
30
src/utils.h
30
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<JsonObject>();
|
||||
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>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_NATIVE_HEATING_CONTROL)].as<bool>();
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_ALWAYS_SEND_INDOOR_TEMP)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_ALWAYS_SEND_INDOOR_TEMP)].as<bool>();
|
||||
|
||||
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>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_NATIVE_OTC)].as<bool>();
|
||||
|
||||
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>()) {
|
||||
bool value = src[FPSTR(S_MQTT)][FPSTR(S_ENABLED)].as<bool>();
|
||||
@@ -1118,7 +1128,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
||||
if (src[FPSTR(S_EQUITHERM)][FPSTR(S_ENABLED)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_EQUITHERM)][FPSTR(S_ENABLED)].as<bool>();
|
||||
|
||||
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>()) {
|
||||
bool value = src[FPSTR(S_PID)][FPSTR(S_ENABLED)].as<bool>();
|
||||
|
||||
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<float>() : 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;
|
||||
|
||||
|
||||
@@ -457,12 +457,13 @@
|
||||
"autoFaultReset": "自动报警复位 <small>(不推荐!)</small>",
|
||||
"autoDiagReset": "自动诊断复位 <small>(不推荐!)</small>",
|
||||
"setDateAndTime": "同步设置锅炉日期与时间",
|
||||
"immergasFix": "针对Immergas锅炉的兼容性修复"
|
||||
"immergasFix": "针对Immergas锅炉的兼容性修复",
|
||||
"alwaysSendIndoorTemp": "一定要给锅炉输送电流和目标温度"
|
||||
},
|
||||
|
||||
"nativeHeating": {
|
||||
"title": "原生锅炉供暖控制",
|
||||
"note": "<u>注意:</u> 仅适用于锅炉需接收目标室温并自主调节载热介质温度的场景,与固件中的PID及Equithermq气候补偿功能不兼容。"
|
||||
"nativeOTC": {
|
||||
"title": "本地(由锅炉处理)外部温度补偿",
|
||||
"note": "只有 锅炉能调节冷却液温度时才有效。未经测试。固件中不兼容PID和Equitherm的调压器。"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -457,12 +457,13 @@
|
||||
"autoFaultReset": "Auto fault reset <small>(not recommended!)</small>",
|
||||
"autoDiagReset": "Auto diag reset <small>(not recommended!)</small>",
|
||||
"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 <u>ONLY</u> 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 <u>ONLY</u> if the boiler regulates the temperature of the coolant itself. Untested. Not compatible with PID and Equitherm regulators in firmware."
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -457,12 +457,13 @@
|
||||
"autoFaultReset": "Ripristino automatico degli errori <small>(sconsigliato!)</small>",
|
||||
"autoDiagReset": "Ripristino diagnostico automatica <small>(sconsigliato!)</small>",
|
||||
"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 <u>SOLO</u> 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 <u>SOLO</u> se la caldaia regola la temperatura del liquido refrigerante stesso. Testate. Non compatibile con i regolatori PID ed Equitherm nel firmware."
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -422,11 +422,12 @@
|
||||
"autoFaultReset": "Automatische storingsreset <small>(niet aanbevolen!)</small>",
|
||||
"autoDiagReset": "Automatische diagnosereset <small>(niet aanbevolen!)</small>",
|
||||
"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 <u>ALLEEN</u> 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 <u>ALLEEN</u> als de ketel de temperatuur van de koelvloeistof zelf regelt. Geteste. Niet compatibel met PID- en Equitherm-regelaars in firmware"
|
||||
}
|
||||
},
|
||||
"mqtt": {
|
||||
|
||||
@@ -457,12 +457,13 @@
|
||||
"autoFaultReset": "Автоматический сброс ошибок <small>(не рекомендуется!)</small>",
|
||||
"autoDiagReset": "Автоматический сброс диагностики <small>(не рекомендуется!)</small>",
|
||||
"setDateAndTime": "Устанавливать время и дату на котле",
|
||||
"immergasFix": "Фикс для котлов Immergas"
|
||||
"immergasFix": "Фикс для котлов Immergas",
|
||||
"alwaysSendIndoorTemp": "Всегда отправляйте ток и целевую температуру в помещении в котёл"
|
||||
},
|
||||
|
||||
"nativeHeating": {
|
||||
"title": "Передать управление отоплением котлу",
|
||||
"note": "Работает <u>ТОЛЬКО</u> если котел требует и принимает целевую температуру в помещении и сам регулирует температуру теплоносителя на основе встроенного режима кривых. Несовместимо с ПИД и ПЗА."
|
||||
"nativeOTC": {
|
||||
"title": "Нативная (обрабатывается котлом) Внешняя компенсация температуры",
|
||||
"note": "Работает <u>ТОЛЬКО</u> если котёл регулирует температуру самого охлаждающей жидкости. Непроверенных. Несовместимо с регуляторами PID и Equitherm в прошивке."
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -692,12 +692,17 @@
|
||||
<span data-i18n>settings.ot.options.immergasFix</span>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<input type="checkbox" name="opentherm[options][alwaysSendIndoorTemp]" value="true">
|
||||
<span data-i18n>settings.ot.options.alwaysSendIndoorTemp</span>
|
||||
</label>
|
||||
|
||||
<hr />
|
||||
|
||||
<label>
|
||||
<input type="checkbox" name="opentherm[options][nativeHeatingControl]" value="true">
|
||||
<span data-i18n>settings.ot.nativeHeating.title</span><br />
|
||||
<small data-i18n>settings.ot.nativeHeating.note</small>
|
||||
<input type="checkbox" name="opentherm[options][nativeOTC]" value="true">
|
||||
<span data-i18n>settings.ot.nativeOTC.title</span><br />
|
||||
<small data-i18n>settings.ot.nativeOTC.note</small>
|
||||
</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user