4 Commits

10 changed files with 158 additions and 72 deletions

View File

@@ -395,7 +395,7 @@ public:
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("signal_strength"); //doc[FPSTR(HA_DEVICE_CLASS)] = F("signal_strength");
doc[FPSTR(HA_STATE_CLASS)] = FPSTR(HA_STATE_CLASS_MEASUREMENT); doc[FPSTR(HA_STATE_CLASS)] = FPSTR(HA_STATE_CLASS_MEASUREMENT);
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_PERCENT); doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_PERCENT);
doc[FPSTR(HA_ICON)] = F("mdi:signal"); doc[FPSTR(HA_ICON)] = F("mdi:signal");

View File

@@ -229,7 +229,13 @@ protected:
vars.slave.flame = CustomOpenTherm::isFlameOn(response); vars.slave.flame = CustomOpenTherm::isFlameOn(response);
vars.slave.cooling = CustomOpenTherm::isCoolingActive(response); vars.slave.cooling = CustomOpenTherm::isCoolingActive(response);
vars.slave.fault.active = CustomOpenTherm::isFault(response); vars.slave.fault.active = CustomOpenTherm::isFault(response);
vars.slave.diag.active = CustomOpenTherm::isDiagnostic(response);
if (!settings.opentherm.options.ignoreDiagState) {
vars.slave.diag.active = CustomOpenTherm::isDiagnostic(response);
} else if (vars.slave.diag.active) {
vars.slave.diag.active = false;
}
Log.snoticeln( Log.snoticeln(
FPSTR(L_OT), F("Received boiler status. Heating: %hhu; DHW: %hhu; flame: %hhu; cooling: %hhu; fault: %hhu; diag: %hhu"), FPSTR(L_OT), F("Received boiler status. Heating: %hhu; DHW: %hhu; flame: %hhu; cooling: %hhu; fault: %hhu; diag: %hhu"),
@@ -342,13 +348,23 @@ protected:
vars.slave.modulation.min, vars.slave.power.max vars.slave.modulation.min, vars.slave.power.max
); );
if (settings.opentherm.maxModulation < vars.slave.modulation.min) { if (settings.heating.maxModulation < vars.slave.modulation.min) {
settings.opentherm.maxModulation = vars.slave.modulation.min; settings.heating.maxModulation = vars.slave.modulation.min;
fsSettings.update(); fsSettings.update();
Log.swarningln( Log.swarningln(
FPSTR(L_SETTINGS_OT), F("Updated min modulation: %hhu%%"), FPSTR(L_SETTINGS_HEATING), F("Updated min modulation: %hhu%%"),
settings.opentherm.maxModulation settings.heating.maxModulation
);
}
if (settings.dhw.maxModulation < vars.slave.modulation.min) {
settings.dhw.maxModulation = vars.slave.modulation.min;
fsSettings.update();
Log.swarningln(
FPSTR(L_SETTINGS_DHW), F("Updated min modulation: %hhu%%"),
settings.dhw.maxModulation
); );
} }
@@ -367,29 +383,6 @@ protected:
Log.swarningln(FPSTR(L_OT), F("Failed receive min modulation and max power")); Log.swarningln(FPSTR(L_OT), F("Failed receive min modulation and max power"));
} }
if (!vars.master.heating.enabled && settings.opentherm.options.modulationSyncWithHeating) {
if (this->setMaxModulationLevel(0)) {
Log.snoticeln(FPSTR(L_OT), F("Set max modulation: 0% (response: %hhu%%)"), vars.slave.modulation.max);
} else {
Log.swarningln(FPSTR(L_OT), F("Failed set max modulation: 0% (response: %hhu%%)"), vars.slave.modulation.max);
}
} else {
if (this->setMaxModulationLevel(settings.opentherm.maxModulation)) {
Log.snoticeln(
FPSTR(L_OT), F("Set max modulation: %hhu%% (response: %hhu%%)"),
settings.opentherm.maxModulation, vars.slave.modulation.max
);
} else {
Log.swarningln(
FPSTR(L_OT), F("Failed set max modulation: %hhu%% (response: %hhu%%)"),
settings.opentherm.maxModulation, vars.slave.modulation.max
);
}
}
// Get DHW min/max temp (if necessary) // Get DHW min/max temp (if necessary)
if (settings.opentherm.options.dhwSupport && settings.opentherm.options.getMinMaxTemp) { if (settings.opentherm.options.dhwSupport && settings.opentherm.options.getMinMaxTemp) {
@@ -514,9 +507,42 @@ protected:
vars.slave.diag.code = 0; vars.slave.diag.code = 0;
} }
// Auto fault reset
if (settings.opentherm.options.autoFaultReset && vars.slave.fault.active && !vars.actions.resetFault) {
vars.actions.resetFault = true;
}
// Auto diag reset
if (settings.opentherm.options.autoDiagReset && vars.slave.diag.active && !vars.actions.resetDiagnostic) {
vars.actions.resetDiagnostic = true;
}
this->prevUpdateNonEssentialVars = millis(); this->prevUpdateNonEssentialVars = millis();
} }
// Set max modulation level
uint8_t targetMaxModulation = vars.slave.modulation.max;
if (vars.slave.heating.active) {
targetMaxModulation = settings.heating.maxModulation;
} else if (vars.slave.dhw.active) {
targetMaxModulation = settings.dhw.maxModulation;
}
if (vars.slave.modulation.max != targetMaxModulation) {
if (this->setMaxModulationLevel(targetMaxModulation)) {
Log.snoticeln(
FPSTR(L_OT), F("Set max modulation: %hhu%% (response: %hhu%%)"),
targetMaxModulation, vars.slave.modulation.max
);
} else {
Log.swarningln(
FPSTR(L_OT), F("Failed set max modulation: %hhu%% (response: %hhu%%)"),
targetMaxModulation, vars.slave.modulation.max
);
}
}
// Update modulation level // Update modulation level
if ( if (

View File

@@ -59,7 +59,6 @@ struct Settings {
byte rxLedGpio = DEFAULT_OT_RX_LED_GPIO; byte rxLedGpio = DEFAULT_OT_RX_LED_GPIO;
uint8_t memberId = 0; uint8_t memberId = 0;
uint8_t flags = 0; uint8_t flags = 0;
uint8_t maxModulation = 100;
float minPower = 0.0f; float minPower = 0.0f;
float maxPower = 0.0f; float maxPower = 0.0f;
@@ -72,9 +71,11 @@ struct Settings {
bool heatingToCh2 = false; bool heatingToCh2 = false;
bool dhwToCh2 = false; bool dhwToCh2 = false;
bool dhwBlocking = false; bool dhwBlocking = false;
bool modulationSyncWithHeating = false;
bool maxTempSyncWithTargetTemp = true; bool maxTempSyncWithTargetTemp = true;
bool getMinMaxTemp = true; bool getMinMaxTemp = true;
bool ignoreDiagState = false;
bool autoFaultReset = false;
bool autoDiagReset = false;
bool nativeHeatingControl = false; bool nativeHeatingControl = false;
bool immergasFix = false; bool immergasFix = false;
} options; } options;
@@ -104,6 +105,7 @@ struct Settings {
float turboFactor = 7.5f; float turboFactor = 7.5f;
byte minTemp = DEFAULT_HEATING_MIN_TEMP; byte minTemp = DEFAULT_HEATING_MIN_TEMP;
byte maxTemp = DEFAULT_HEATING_MAX_TEMP; byte maxTemp = DEFAULT_HEATING_MAX_TEMP;
uint8_t maxModulation = 100;
} heating; } heating;
struct { struct {
@@ -111,6 +113,7 @@ struct Settings {
float target = DEFAULT_DHW_TARGET_TEMP; float target = DEFAULT_DHW_TARGET_TEMP;
byte minTemp = DEFAULT_DHW_MIN_TEMP; byte minTemp = DEFAULT_DHW_MIN_TEMP;
byte maxTemp = DEFAULT_DHW_MAX_TEMP; byte maxTemp = DEFAULT_DHW_MAX_TEMP;
uint8_t maxModulation = 100;
} dhw; } dhw;
struct { struct {

View File

@@ -16,7 +16,7 @@
#define THERMOSTAT_INDOOR_DEFAULT_TEMP 20 #define THERMOSTAT_INDOOR_DEFAULT_TEMP 20
#define THERMOSTAT_INDOOR_MIN_TEMP 5 #define THERMOSTAT_INDOOR_MIN_TEMP 5
#define THERMOSTAT_INDOOR_MAX_TEMP 30 #define THERMOSTAT_INDOOR_MAX_TEMP 40
#define DEFAULT_NTC_NOMINAL_RESISTANCE 10000.0f #define DEFAULT_NTC_NOMINAL_RESISTANCE 10000.0f
#define DEFAULT_NTC_NOMINAL_TEMP 25.0f #define DEFAULT_NTC_NOMINAL_TEMP 25.0f

View File

@@ -42,6 +42,8 @@ const char S_ANTI_STUCK_TIME[] PROGMEM = "antiStuckTime";
const char S_AP[] PROGMEM = "ap"; const char S_AP[] PROGMEM = "ap";
const char S_APP_VERSION[] PROGMEM = "appVersion"; const char S_APP_VERSION[] PROGMEM = "appVersion";
const char S_AUTH[] PROGMEM = "auth"; 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_BACKTRACE[] PROGMEM = "backtrace"; const char S_BACKTRACE[] PROGMEM = "backtrace";
const char S_BATTERY[] PROGMEM = "battery"; const char S_BATTERY[] PROGMEM = "battery";
const char S_BAUDRATE[] PROGMEM = "baudrate"; const char S_BAUDRATE[] PROGMEM = "baudrate";
@@ -101,6 +103,7 @@ const char S_HOSTNAME[] PROGMEM = "hostname";
const char S_HUMIDITY[] PROGMEM = "humidity"; const char S_HUMIDITY[] PROGMEM = "humidity";
const char S_HYSTERESIS[] PROGMEM = "hysteresis"; const char S_HYSTERESIS[] PROGMEM = "hysteresis";
const char S_ID[] PROGMEM = "id"; const char S_ID[] PROGMEM = "id";
const char S_IGNORE_DIAG_STATE[] PROGMEM = "ignoreDiagState";
const char S_IMMERGAS_FIX[] PROGMEM = "immergasFix"; const char S_IMMERGAS_FIX[] PROGMEM = "immergasFix";
const char S_INDOOR_TEMP[] PROGMEM = "indoorTemp"; const char S_INDOOR_TEMP[] PROGMEM = "indoorTemp";
const char S_INDOOR_TEMP_CONTROL[] PROGMEM = "indoorTempControl"; const char S_INDOOR_TEMP_CONTROL[] PROGMEM = "indoorTempControl";
@@ -131,7 +134,6 @@ const char S_MIN_POWER[] PROGMEM = "minPower";
const char S_MIN_TEMP[] PROGMEM = "minTemp"; const char S_MIN_TEMP[] PROGMEM = "minTemp";
const char S_MODEL[] PROGMEM = "model"; const char S_MODEL[] PROGMEM = "model";
const char S_MODULATION[] PROGMEM = "modulation"; const char S_MODULATION[] PROGMEM = "modulation";
const char S_MODULATION_SYNC_WITH_HEATING[] PROGMEM = "modulationSyncWithHeating";
const char S_MQTT[] PROGMEM = "mqtt"; const char S_MQTT[] PROGMEM = "mqtt";
const char S_NAME[] PROGMEM = "name"; const char S_NAME[] PROGMEM = "name";
const char S_NATIVE_HEATING_CONTROL[] PROGMEM = "nativeHeatingControl"; const char S_NATIVE_HEATING_CONTROL[] PROGMEM = "nativeHeatingControl";

View File

@@ -449,7 +449,6 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) {
opentherm[FPSTR(S_RX_LED_GPIO)] = src.opentherm.rxLedGpio; opentherm[FPSTR(S_RX_LED_GPIO)] = src.opentherm.rxLedGpio;
opentherm[FPSTR(S_MEMBER_ID)] = src.opentherm.memberId; opentherm[FPSTR(S_MEMBER_ID)] = src.opentherm.memberId;
opentherm[FPSTR(S_FLAGS)] = src.opentherm.flags; opentherm[FPSTR(S_FLAGS)] = src.opentherm.flags;
opentherm[FPSTR(S_MAX_MODULATION)] = src.opentherm.maxModulation;
opentherm[FPSTR(S_MIN_POWER)] = roundf(src.opentherm.minPower, 2); opentherm[FPSTR(S_MIN_POWER)] = roundf(src.opentherm.minPower, 2);
opentherm[FPSTR(S_MAX_POWER)] = roundf(src.opentherm.maxPower, 2); opentherm[FPSTR(S_MAX_POWER)] = roundf(src.opentherm.maxPower, 2);
@@ -462,9 +461,11 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) {
otOptions[FPSTR(S_HEATING_TO_CH2)] = src.opentherm.options.heatingToCh2; otOptions[FPSTR(S_HEATING_TO_CH2)] = src.opentherm.options.heatingToCh2;
otOptions[FPSTR(S_DHW_TO_CH2)] = src.opentherm.options.dhwToCh2; otOptions[FPSTR(S_DHW_TO_CH2)] = src.opentherm.options.dhwToCh2;
otOptions[FPSTR(S_DHW_BLOCKING)] = src.opentherm.options.dhwBlocking; otOptions[FPSTR(S_DHW_BLOCKING)] = src.opentherm.options.dhwBlocking;
otOptions[FPSTR(S_MODULATION_SYNC_WITH_HEATING)] = src.opentherm.options.modulationSyncWithHeating;
otOptions[FPSTR(S_MAX_TEMP_SYNC_WITH_TARGET_TEMP)] = src.opentherm.options.maxTempSyncWithTargetTemp; otOptions[FPSTR(S_MAX_TEMP_SYNC_WITH_TARGET_TEMP)] = src.opentherm.options.maxTempSyncWithTargetTemp;
otOptions[FPSTR(S_GET_MIN_MAX_TEMP)] = src.opentherm.options.getMinMaxTemp; otOptions[FPSTR(S_GET_MIN_MAX_TEMP)] = src.opentherm.options.getMinMaxTemp;
otOptions[FPSTR(S_IGNORE_DIAG_STATE)] = src.opentherm.options.ignoreDiagState;
otOptions[FPSTR(S_AUTO_FAULT_RESET)] = src.opentherm.options.autoFaultReset;
otOptions[FPSTR(S_AUTO_DIAG_RESET)] = src.opentherm.options.autoDiagReset;
otOptions[FPSTR(S_NATIVE_HEATING_CONTROL)] = src.opentherm.options.nativeHeatingControl; otOptions[FPSTR(S_NATIVE_HEATING_CONTROL)] = src.opentherm.options.nativeHeatingControl;
otOptions[FPSTR(S_IMMERGAS_FIX)] = src.opentherm.options.immergasFix; otOptions[FPSTR(S_IMMERGAS_FIX)] = src.opentherm.options.immergasFix;
@@ -491,12 +492,14 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) {
heating[FPSTR(S_TURBO_FACTOR)] = roundf(src.heating.turboFactor, 3); heating[FPSTR(S_TURBO_FACTOR)] = roundf(src.heating.turboFactor, 3);
heating[FPSTR(S_MIN_TEMP)] = src.heating.minTemp; heating[FPSTR(S_MIN_TEMP)] = src.heating.minTemp;
heating[FPSTR(S_MAX_TEMP)] = src.heating.maxTemp; heating[FPSTR(S_MAX_TEMP)] = src.heating.maxTemp;
heating[FPSTR(S_MAX_MODULATION)] = src.heating.maxModulation;
auto dhw = dst[FPSTR(S_DHW)].to<JsonObject>(); auto dhw = dst[FPSTR(S_DHW)].to<JsonObject>();
dhw[FPSTR(S_ENABLED)] = src.dhw.enabled; dhw[FPSTR(S_ENABLED)] = src.dhw.enabled;
dhw[FPSTR(S_TARGET)] = roundf(src.dhw.target, 1); dhw[FPSTR(S_TARGET)] = roundf(src.dhw.target, 1);
dhw[FPSTR(S_MIN_TEMP)] = src.dhw.minTemp; dhw[FPSTR(S_MIN_TEMP)] = src.dhw.minTemp;
dhw[FPSTR(S_MAX_TEMP)] = src.dhw.maxTemp; dhw[FPSTR(S_MAX_TEMP)] = src.dhw.maxTemp;
dhw[FPSTR(S_MAX_MODULATION)] = src.dhw.maxModulation;
auto equitherm = dst[FPSTR(S_EQUITHERM)].to<JsonObject>(); auto equitherm = dst[FPSTR(S_EQUITHERM)].to<JsonObject>();
equitherm[FPSTR(S_ENABLED)] = src.equitherm.enabled; equitherm[FPSTR(S_ENABLED)] = src.equitherm.enabled;
@@ -811,15 +814,6 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
} }
} }
if (!src[FPSTR(S_OPENTHERM)][FPSTR(S_MAX_MODULATION)].isNull()) {
unsigned char value = src[FPSTR(S_OPENTHERM)][FPSTR(S_MAX_MODULATION)].as<unsigned char>();
if (value > 0 && value <= 100 && value != dst.opentherm.maxModulation) {
dst.opentherm.maxModulation = value;
changed = true;
}
}
if (!src[FPSTR(S_OPENTHERM)][FPSTR(S_MIN_POWER)].isNull()) { if (!src[FPSTR(S_OPENTHERM)][FPSTR(S_MIN_POWER)].isNull()) {
float value = src[FPSTR(S_OPENTHERM)][FPSTR(S_MIN_POWER)].as<float>(); float value = src[FPSTR(S_OPENTHERM)][FPSTR(S_MIN_POWER)].as<float>();
@@ -928,15 +922,6 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
} }
} }
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_MODULATION_SYNC_WITH_HEATING)].is<bool>()) {
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_MODULATION_SYNC_WITH_HEATING)].as<bool>();
if (value != dst.opentherm.options.modulationSyncWithHeating) {
dst.opentherm.options.modulationSyncWithHeating = value;
changed = true;
}
}
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_MAX_TEMP_SYNC_WITH_TARGET_TEMP)].is<bool>()) { if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_MAX_TEMP_SYNC_WITH_TARGET_TEMP)].is<bool>()) {
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_MAX_TEMP_SYNC_WITH_TARGET_TEMP)].as<bool>(); bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_MAX_TEMP_SYNC_WITH_TARGET_TEMP)].as<bool>();
@@ -955,6 +940,33 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
} }
} }
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_IGNORE_DIAG_STATE)].is<bool>()) {
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_IGNORE_DIAG_STATE)].as<bool>();
if (value != dst.opentherm.options.ignoreDiagState) {
dst.opentherm.options.ignoreDiagState = value;
changed = true;
}
}
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_AUTO_FAULT_RESET)].is<bool>()) {
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_AUTO_FAULT_RESET)].as<bool>();
if (value != dst.opentherm.options.autoFaultReset) {
dst.opentherm.options.autoFaultReset = value;
changed = true;
}
}
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_AUTO_DIAG_RESET)].is<bool>()) {
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_AUTO_DIAG_RESET)].as<bool>();
if (value != dst.opentherm.options.autoDiagReset) {
dst.opentherm.options.autoDiagReset = value;
changed = true;
}
}
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_NATIVE_HEATING_CONTROL)].is<bool>()) { 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>(); bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_NATIVE_HEATING_CONTROL)].as<bool>();
@@ -1301,6 +1313,16 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
} }
if (!src[FPSTR(S_HEATING)][FPSTR(S_MAX_MODULATION)].isNull()) {
unsigned char value = src[FPSTR(S_HEATING)][FPSTR(S_MAX_MODULATION)].as<unsigned char>();
if (value > 0 && value <= 100 && value != dst.heating.maxModulation) {
dst.heating.maxModulation = value;
changed = true;
}
}
// dhw // dhw
if (src[FPSTR(S_DHW)][FPSTR(S_ENABLED)].is<bool>()) { if (src[FPSTR(S_DHW)][FPSTR(S_ENABLED)].is<bool>()) {
bool value = src[FPSTR(S_DHW)][FPSTR(S_ENABLED)].as<bool>(); bool value = src[FPSTR(S_DHW)][FPSTR(S_ENABLED)].as<bool>();
@@ -1334,6 +1356,15 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
changed = true; changed = true;
} }
if (!src[FPSTR(S_DHW)][FPSTR(S_MAX_MODULATION)].isNull()) {
unsigned char value = src[FPSTR(S_DHW)][FPSTR(S_MAX_MODULATION)].as<unsigned char>();
if (value > 0 && value <= 100 && value != dst.dhw.maxModulation) {
dst.dhw.maxModulation = value;
changed = true;
}
}
if (!safe) { if (!safe) {
// external pump // external pump

View File

@@ -292,6 +292,7 @@
"min": "Minimum temperature", "min": "Minimum temperature",
"max": "Maximum temperature" "max": "Maximum temperature"
}, },
"maxModulation": "Max modulation level",
"portal": { "portal": {
"login": "Login", "login": "Login",
@@ -375,7 +376,6 @@
"ledGpio": "RX LED GPIO", "ledGpio": "RX LED GPIO",
"memberId": "Master member ID", "memberId": "Master member ID",
"flags": "Master flags", "flags": "Master flags",
"maxMod": "Max modulation level",
"minPower": { "minPower": {
"title": "Min boiler power <small>(kW)</small>", "title": "Min boiler power <small>(kW)</small>",
"note": "This value is at 0-1% boiler modulation level. Typically found in the boiler specification as \"minimum useful heat output\"." "note": "This value is at 0-1% boiler modulation level. Typically found in the boiler specification as \"minimum useful heat output\"."
@@ -395,9 +395,11 @@
"heatingToCh2": "Duplicate heating to CH2", "heatingToCh2": "Duplicate heating to CH2",
"dhwToCh2": "Duplicate DHW to CH2", "dhwToCh2": "Duplicate DHW to CH2",
"dhwBlocking": "DHW blocking", "dhwBlocking": "DHW blocking",
"modulationSyncWithHeating": "Sync modulation with heating",
"maxTempSyncWithTargetTemp": "Sync max heating temp with target temp", "maxTempSyncWithTargetTemp": "Sync max heating temp with target temp",
"getMinMaxTemp": "Get min/max temp from boiler", "getMinMaxTemp": "Get min/max temp from boiler",
"ignoreDiagState": "Ignore diag state",
"autoFaultReset": "Auto fault reset <small>(not recommended!)</small>",
"autoDiagReset": "Auto diag reset <small>(not recommended!)</small>",
"immergasFix": "Fix for Immergas boilers" "immergasFix": "Fix for Immergas boilers"
}, },

View File

@@ -292,6 +292,7 @@
"min": "Temperatura minima", "min": "Temperatura minima",
"max": "Temperatura massima" "max": "Temperatura massima"
}, },
"maxModulation": "Max livello modulazione",
"portal": { "portal": {
"login": "Login", "login": "Login",
@@ -375,7 +376,6 @@
"ledGpio": "RX LED GPIO", "ledGpio": "RX LED GPIO",
"memberId": "Master member ID", "memberId": "Master member ID",
"flags": "Master flags", "flags": "Master flags",
"maxMod": "Max livello modulazione",
"minPower": { "minPower": {
"title": "Potenza minima caldaia <small>(kW)</small>", "title": "Potenza minima caldaia <small>(kW)</small>",
"note": "Questo valore corrisponde allo livello 0-1% di modulazione della caldaia. Di solito si trova nelle specifiche delle caldaia come \"potenza minima disponibile\"." "note": "Questo valore corrisponde allo livello 0-1% di modulazione della caldaia. Di solito si trova nelle specifiche delle caldaia come \"potenza minima disponibile\"."
@@ -395,9 +395,11 @@
"heatingToCh2": "Riproduci riscaldamento su CH2", "heatingToCh2": "Riproduci riscaldamento su CH2",
"dhwToCh2": "Riproduci ACS su CH2", "dhwToCh2": "Riproduci ACS su CH2",
"dhwBlocking": "Bloccare ACS", "dhwBlocking": "Bloccare ACS",
"modulationSyncWithHeating": "Sincronizzare modulazione con caldaia",
"maxTempSyncWithTargetTemp": "Sincronizza la temperatura massima di riscaldamento con la temperatura target", "maxTempSyncWithTargetTemp": "Sincronizza la temperatura massima di riscaldamento con la temperatura target",
"getMinMaxTemp": "Prendi temp min/max dalla caldaia", "getMinMaxTemp": "Prendi temp min/max dalla caldaia",
"ignoreDiagState": "Ignora lo stato diagnostico",
"autoFaultReset": "Ripristino automatico degli errori <small>(sconsigliato!)</small>",
"autoDiagReset": "Ripristino diagnostico automatica <small>(sconsigliato!)</small>",
"immergasFix": "Fix per caldiaie Immergas" "immergasFix": "Fix per caldiaie Immergas"
}, },

View File

@@ -292,6 +292,7 @@
"min": "Мин. температура", "min": "Мин. температура",
"max": "Макс. температура" "max": "Макс. температура"
}, },
"maxModulation": "Макс. уровень модуляции",
"portal": { "portal": {
"login": "Логин", "login": "Логин",
@@ -375,7 +376,6 @@
"ledGpio": "RX LED GPIO", "ledGpio": "RX LED GPIO",
"memberId": "Master member ID", "memberId": "Master member ID",
"flags": "Master flags", "flags": "Master flags",
"maxMod": "Макс. уровень модуляции",
"minPower": { "minPower": {
"title": "Мин. мощность котла <small>(кВт)</small>", "title": "Мин. мощность котла <small>(кВт)</small>",
"note": "Это значение соответствует уровню модуляции котла 01%. Обычно можно найти в спецификации котла как \"минимальная полезная тепловая мощность\"." "note": "Это значение соответствует уровню модуляции котла 01%. Обычно можно найти в спецификации котла как \"минимальная полезная тепловая мощность\"."
@@ -395,9 +395,11 @@
"heatingToCh2": "Дублировать параметры отопления в канал 2", "heatingToCh2": "Дублировать параметры отопления в канал 2",
"dhwToCh2": "Дублировать параметры ГВС в канал 2", "dhwToCh2": "Дублировать параметры ГВС в канал 2",
"dhwBlocking": "DHW blocking", "dhwBlocking": "DHW blocking",
"modulationSyncWithHeating": "Синхронизировать модуляцию с отоплением",
"maxTempSyncWithTargetTemp": "Синхронизировать макс. темп. отопления с целевой темп.", "maxTempSyncWithTargetTemp": "Синхронизировать макс. темп. отопления с целевой темп.",
"getMinMaxTemp": "Получать мин. и макс. температуру от котла", "getMinMaxTemp": "Получать мин. и макс. температуру от котла",
"ignoreDiagState": "Игнорировать состояние диагностики",
"autoFaultReset": "Автоматический сброс ошибок <small>(не рекомендуется!)</small>",
"autoDiagReset": "Автоматический сброс диагностики <small>(не рекомендуется!)</small>",
"immergasFix": "Фикс для котлов Immergas" "immergasFix": "Фикс для котлов Immergas"
}, },

View File

@@ -202,6 +202,11 @@
</label> </label>
</div> </div>
<label>
<span data-i18n>settings.maxModulation</span>
<input type="number" inputmode="numeric" name="heating[maxModulation]" min="1" max="100" step="1" required>
</label>
<button type="submit" data-i18n>button.save</button> <button type="submit" data-i18n>button.save</button>
</form> </form>
</div> </div>
@@ -226,6 +231,11 @@
</label> </label>
</div> </div>
<label>
<span data-i18n>settings.maxModulation</span>
<input type="number" inputmode="numeric" name="dhw[maxModulation]" min="1" max="100" step="1" required>
</label>
<button type="submit" data-i18n>button.save</button> <button type="submit" data-i18n>button.save</button>
</form> </form>
</div> </div>
@@ -457,11 +467,6 @@
<span data-i18n>settings.ot.flags</span> <span data-i18n>settings.ot.flags</span>
<input type="number" inputmode="numeric" name="opentherm[flags]" min="0" max="255" step="1" required> <input type="number" inputmode="numeric" name="opentherm[flags]" min="0" max="255" step="1" required>
</label> </label>
<label>
<span data-i18n>settings.ot.maxMod</span>
<input type="number" inputmode="numeric" name="opentherm[maxModulation]" min="1" max="100" step="1" required>
</label>
</div> </div>
<div class="grid"> <div class="grid">
@@ -521,11 +526,6 @@
<span data-i18n>settings.ot.options.dhwBlocking</span> <span data-i18n>settings.ot.options.dhwBlocking</span>
</label> </label>
<label>
<input type="checkbox" name="opentherm[options][modulationSyncWithHeating]" value="true">
<span data-i18n>settings.ot.options.modulationSyncWithHeating</span>
</label>
<label> <label>
<input type="checkbox" name="opentherm[options][maxTempSyncWithTargetTemp]" value="true"> <input type="checkbox" name="opentherm[options][maxTempSyncWithTargetTemp]" value="true">
<span data-i18n>settings.ot.options.maxTempSyncWithTargetTemp</span> <span data-i18n>settings.ot.options.maxTempSyncWithTargetTemp</span>
@@ -536,6 +536,21 @@
<span data-i18n>settings.ot.options.getMinMaxTemp</span> <span data-i18n>settings.ot.options.getMinMaxTemp</span>
</label> </label>
<label>
<input type="checkbox" name="opentherm[options][ignoreDiagState]" value="true">
<span data-i18n>settings.ot.options.ignoreDiagState</span>
</label>
<label>
<input type="checkbox" name="opentherm[options][autoFaultReset]" value="true">
<span data-i18n>settings.ot.options.autoFaultReset</span>
</label>
<label>
<input type="checkbox" name="opentherm[options][autoDiagReset]" value="true">
<span data-i18n>settings.ot.options.autoDiagReset</span>
</label>
<label> <label>
<input type="checkbox" name="opentherm[options][immergasFix]" value="true"> <input type="checkbox" name="opentherm[options][immergasFix]" value="true">
<span data-i18n>settings.ot.options.immergasFix</span> <span data-i18n>settings.ot.options.immergasFix</span>
@@ -788,7 +803,6 @@
setInputValue("[name='opentherm[rxLedGpio]']", data.opentherm.rxLedGpio < 255 ? data.opentherm.rxLedGpio : ''); setInputValue("[name='opentherm[rxLedGpio]']", data.opentherm.rxLedGpio < 255 ? data.opentherm.rxLedGpio : '');
setInputValue("[name='opentherm[memberId]']", data.opentherm.memberId); setInputValue("[name='opentherm[memberId]']", data.opentherm.memberId);
setInputValue("[name='opentherm[flags]']", data.opentherm.flags); setInputValue("[name='opentherm[flags]']", data.opentherm.flags);
setInputValue("[name='opentherm[maxModulation]']", data.opentherm.maxModulation);
setInputValue("[name='opentherm[minPower]']", data.opentherm.minPower); setInputValue("[name='opentherm[minPower]']", data.opentherm.minPower);
setInputValue("[name='opentherm[maxPower]']", data.opentherm.maxPower); setInputValue("[name='opentherm[maxPower]']", data.opentherm.maxPower);
setCheckboxValue("[name='opentherm[options][dhwSupport]']", data.opentherm.options.dhwSupport); setCheckboxValue("[name='opentherm[options][dhwSupport]']", data.opentherm.options.dhwSupport);
@@ -799,9 +813,11 @@
setCheckboxValue("[name='opentherm[options][heatingToCh2]']", data.opentherm.options.heatingToCh2); setCheckboxValue("[name='opentherm[options][heatingToCh2]']", data.opentherm.options.heatingToCh2);
setCheckboxValue("[name='opentherm[options][dhwToCh2]']", data.opentherm.options.dhwToCh2); setCheckboxValue("[name='opentherm[options][dhwToCh2]']", data.opentherm.options.dhwToCh2);
setCheckboxValue("[name='opentherm[options][dhwBlocking]']", data.opentherm.options.dhwBlocking); setCheckboxValue("[name='opentherm[options][dhwBlocking]']", data.opentherm.options.dhwBlocking);
setCheckboxValue("[name='opentherm[options][modulationSyncWithHeating]']", data.opentherm.options.modulationSyncWithHeating);
setCheckboxValue("[name='opentherm[options][maxTempSyncWithTargetTemp]']", data.opentherm.options.maxTempSyncWithTargetTemp); setCheckboxValue("[name='opentherm[options][maxTempSyncWithTargetTemp]']", data.opentherm.options.maxTempSyncWithTargetTemp);
setCheckboxValue("[name='opentherm[options][getMinMaxTemp]']", data.opentherm.options.getMinMaxTemp); setCheckboxValue("[name='opentherm[options][getMinMaxTemp]']", data.opentherm.options.getMinMaxTemp);
setCheckboxValue("[name='opentherm[options][ignoreDiagState]']", data.opentherm.options.ignoreDiagState);
setCheckboxValue("[name='opentherm[options][autoFaultReset]']", data.opentherm.options.autoFaultReset);
setCheckboxValue("[name='opentherm[options][autoDiagReset]']", data.opentherm.options.autoDiagReset);
setCheckboxValue("[name='opentherm[options][nativeHeatingControl]']", data.opentherm.options.nativeHeatingControl); setCheckboxValue("[name='opentherm[options][nativeHeatingControl]']", data.opentherm.options.nativeHeatingControl);
setCheckboxValue("[name='opentherm[options][immergasFix]']", data.opentherm.options.immergasFix); setCheckboxValue("[name='opentherm[options][immergasFix]']", data.opentherm.options.immergasFix);
setBusy('#ot-settings-busy', '#ot-settings', false); setBusy('#ot-settings-busy', '#ot-settings', false);
@@ -851,6 +867,7 @@
}); });
setInputValue("[name='heating[hysteresis]']", data.heating.hysteresis); setInputValue("[name='heating[hysteresis]']", data.heating.hysteresis);
setInputValue("[name='heating[turboFactor]']", data.heating.turboFactor); setInputValue("[name='heating[turboFactor]']", data.heating.turboFactor);
setInputValue("[name='heating[maxModulation]']", data.heating.maxModulation);
setBusy('#heating-settings-busy', '#heating-settings', false); setBusy('#heating-settings-busy', '#heating-settings', false);
// DHW // DHW
@@ -862,6 +879,7 @@
"min": data.system.unitSystem == 0 ? 1 : 33, "min": data.system.unitSystem == 0 ? 1 : 33,
"max": data.system.unitSystem == 0 ? 100 : 212 "max": data.system.unitSystem == 0 ? 100 : 212
}); });
setInputValue("[name='dhw[maxModulation]']", data.dhw.maxModulation);
setBusy('#dhw-settings-busy', '#dhw-settings', false); setBusy('#dhw-settings-busy', '#dhw-settings', false);
// Emergency mode // Emergency mode
@@ -869,7 +887,7 @@
if (data.opentherm.options.nativeHeatingControl) { if (data.opentherm.options.nativeHeatingControl) {
setInputValue("[name='emergency[target]']", data.emergency.target, { setInputValue("[name='emergency[target]']", data.emergency.target, {
"min": data.system.unitSystem == 0 ? 5 : 41, "min": data.system.unitSystem == 0 ? 5 : 41,
"max": data.system.unitSystem == 0 ? 30 : 86 "max": data.system.unitSystem == 0 ? 40 : 86
}); });
} else { } else {