From 5686094151a0aa228dd4738388e7bb9d77b8cf5f Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 20 Sep 2021 08:49:57 +0200 Subject: [PATCH 1/3] factor for charge duration --- src/devices/thermostat.cpp | 11 +++--- src/emsdevice.cpp | 77 +++++++++++++++++++++++++------------- src/helpers.cpp | 2 +- src/locale_EN.h | 4 +- 4 files changed, 62 insertions(+), 32 deletions(-) diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index f3b1e4df9..8326e545a 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -1383,11 +1383,12 @@ bool Thermostat::set_wwcharge(const char * value, const int8_t id) { // Set ww charge duration in steps of 15 min, ems+ bool Thermostat::set_wwchargeduration(const char * value, const int8_t id) { - uint8_t t = 0xFF; - if (!Helpers::value2enum(value, t, FL_(enum_wwChargeDuration))) { + int t = 0xFF; + if (!Helpers::value2number(value, t)) { LOG_WARNING(F("Set warm water charge duration: Invalid value")); return false; } + t = (t + 8) / 15; LOG_INFO(F("Setting warm water charge duration to %d min"), t * 15); write_command(0x2F5, 10, t, 0x02F5); return true; @@ -2420,10 +2421,10 @@ void Thermostat::register_device_values() { TAG_THERMOSTAT_DATA, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::LIST, MAKE_CF_CB(set_wwcircmode)); register_device_value(TAG_THERMOSTAT_DATA, &wwChargeDuration_, - DeviceValueType::ENUM, - FL_(enum_wwChargeDuration), + DeviceValueType::UINT, + FL_(mul15), FL_(wwChargeDuration), - DeviceValueUOM::LIST, + DeviceValueUOM::MINUTES, MAKE_CF_CB(set_wwchargeduration)); register_device_value(TAG_THERMOSTAT_DATA, &wwCharge_, DeviceValueType::BOOL, nullptr, FL_(wwCharge), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_wwcharge)); register_device_value(TAG_THERMOSTAT_DATA, &wwExtra1_, DeviceValueType::UINT, nullptr, FL_(wwExtra1), DeviceValueUOM::DEGREES); diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index c1eb97c4c..41e9b3dae 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -603,27 +603,36 @@ void EMSdevice::generate_values_json_web(JsonObject & json) { // If a divider is specified, do the division to 2 decimals places and send back as double/float // otherwise force as an integer whole // the nested if's is necessary due to the way the ArduinoJson templates are pre-processed by the compiler - uint8_t divider = (dv.options_size == 1) ? Helpers::atoint(uuid::read_flash_string(dv.options[0]).c_str()) : 0; + uint8_t divider = 0; + uint8_t factor = 1; + if (dv.options_size == 1) { + const char * s = uuid::read_flash_string(dv.options[0]).c_str(); + if (s[0] == '*') { + factor = Helpers::atoint(&s[1]); + } else { + divider = Helpers::atoint(s); + } + } if ((dv.type == DeviceValueType::INT) && Helpers::hasValue(*(int8_t *)(dv.value_p))) { obj = data.createNestedObject(); - obj["v"] = (divider) ? Helpers::round2(*(int8_t *)(dv.value_p), divider) : *(int8_t *)(dv.value_p); + obj["v"] = (divider) ? Helpers::round2(*(int8_t *)(dv.value_p), divider) : *(int8_t *)(dv.value_p) * factor; } else if ((dv.type == DeviceValueType::UINT) && Helpers::hasValue(*(uint8_t *)(dv.value_p))) { obj = data.createNestedObject(); - obj["v"] = (divider) ? Helpers::round2(*(uint8_t *)(dv.value_p), divider) : *(uint8_t *)(dv.value_p); + obj["v"] = (divider) ? Helpers::round2(*(uint8_t *)(dv.value_p), divider) : *(uint8_t *)(dv.value_p) * factor; } else if ((dv.type == DeviceValueType::SHORT) && Helpers::hasValue(*(int16_t *)(dv.value_p))) { obj = data.createNestedObject(); - obj["v"] = (divider) ? Helpers::round2(*(int16_t *)(dv.value_p), divider) : *(int16_t *)(dv.value_p); + obj["v"] = (divider) ? Helpers::round2(*(int16_t *)(dv.value_p), divider) : *(int16_t *)(dv.value_p) * factor; } else if ((dv.type == DeviceValueType::USHORT) && Helpers::hasValue(*(uint16_t *)(dv.value_p))) { obj = data.createNestedObject(); - obj["v"] = (divider) ? Helpers::round2(*(uint16_t *)(dv.value_p), divider) : *(uint16_t *)(dv.value_p); + obj["v"] = (divider) ? Helpers::round2(*(uint16_t *)(dv.value_p), divider) : *(uint16_t *)(dv.value_p) * factor; } else if ((dv.type == DeviceValueType::ULONG) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) { obj = data.createNestedObject(); - obj["v"] = (divider) ? Helpers::round2(*(uint32_t *)(dv.value_p), divider) : *(uint32_t *)(dv.value_p); + obj["v"] = divider ? Helpers::round2(*(uint32_t *)(dv.value_p), divider) : *(uint32_t *)(dv.value_p) * factor; } else if ((dv.type == DeviceValueType::TIME) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) { uint32_t time_value = *(uint32_t *)(dv.value_p); obj = data.createNestedObject(); - obj["v"] = (divider) ? time_value / divider : time_value; // sometimes we need to divide by 60 + obj["v"] = (divider > 0) ? time_value / divider : time_value * factor; // sometimes we need to divide by 60 } } @@ -684,11 +693,20 @@ bool EMSdevice::get_value_info(JsonObject & root, const char * cmd, const int8_t // search device value with this tag for (auto & dv : devicevalues_) { if (strcmp(cmd, Helpers::toLower(uuid::read_flash_string(dv.short_name)).c_str()) == 0 && (tag <= 0 || tag == dv.tag)) { - uint8_t divider = (dv.options_size == 1) ? Helpers::atoint(uuid::read_flash_string(dv.options[0]).c_str()) : 0; - const char * type = "type"; - const char * min = "min"; - const char * max = "max"; - const char * value = "value"; + uint8_t divider = 0; + uint8_t factor = 1; + if (dv.options_size == 1) { + const char * s = uuid::read_flash_string(dv.options[0]).c_str(); + if (s[0] == '*') { + factor = Helpers::atoint(&s[1]); + } else { + divider = Helpers::atoint(s); + } + } + const char * type = "type"; + const char * min = "min"; + const char * max = "max"; + const char * value = "value"; json["name"] = dv.short_name; // prefix tag if it's included @@ -726,7 +744,7 @@ bool EMSdevice::get_value_info(JsonObject & root, const char * cmd, const int8_t case DeviceValueType::USHORT: if (Helpers::hasValue(*(uint16_t *)(dv.value_p))) { - json[value] = Helpers::round2(*(uint16_t *)(dv.value_p), divider); + json[value] = divider ? Helpers::round2(*(uint16_t *)(dv.value_p), divider) : *(uint16_t *)(dv.value_p) * factor; } json[type] = F_(number); json[min] = 0; @@ -735,7 +753,7 @@ bool EMSdevice::get_value_info(JsonObject & root, const char * cmd, const int8_t case DeviceValueType::UINT: if (Helpers::hasValue(*(uint8_t *)(dv.value_p))) { - json[value] = Helpers::round2(*(uint8_t *)(dv.value_p), divider); + json[value] = divider ? Helpers::round2(*(uint8_t *)(dv.value_p), divider) : *(uint8_t *)(dv.value_p) * factor; } json[type] = F_(number); json[min] = 0; @@ -748,7 +766,7 @@ bool EMSdevice::get_value_info(JsonObject & root, const char * cmd, const int8_t case DeviceValueType::SHORT: if (Helpers::hasValue(*(int16_t *)(dv.value_p))) { - json[value] = Helpers::round2(*(int16_t *)(dv.value_p), divider); + json[value] = divider ? Helpers::round2(*(int16_t *)(dv.value_p), divider) : *(int16_t *)(dv.value_p) * factor; } json[type] = F_(number); json[min] = divider ? -EMS_VALUE_SHORT_NOTSET / divider : -EMS_VALUE_SHORT_NOTSET; @@ -757,7 +775,7 @@ bool EMSdevice::get_value_info(JsonObject & root, const char * cmd, const int8_t case DeviceValueType::INT: if (Helpers::hasValue(*(int8_t *)(dv.value_p))) { - json[value] = Helpers::round2(*(int8_t *)(dv.value_p), divider); + json[value] = divider ? Helpers::round2(*(int8_t *)(dv.value_p), divider) : *(int8_t *)(dv.value_p) * factor; } json[type] = F_(number); if (dv.uom == DeviceValueUOM::PERCENT) { @@ -771,7 +789,7 @@ bool EMSdevice::get_value_info(JsonObject & root, const char * cmd, const int8_t case DeviceValueType::ULONG: if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) { - json[value] = Helpers::round2(*(uint32_t *)(dv.value_p), divider); + json[value] = divider ? Helpers::round2(*(uint32_t *)(dv.value_p), divider) : *(uint32_t *)(dv.value_p) * factor; } json[type] = F_(number); json[min] = 0; @@ -797,7 +815,7 @@ bool EMSdevice::get_value_info(JsonObject & root, const char * cmd, const int8_t case DeviceValueType::TIME: if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) { - json[value] = (divider) ? *(uint32_t *)(dv.value_p) / divider : *(uint32_t *)(dv.value_p); + json[value] = (divider) ? *(uint32_t *)(dv.value_p) / divider : *(uint32_t *)(dv.value_p) * factor; } json[type] = F_(number); json[min] = 0; @@ -918,47 +936,56 @@ bool EMSdevice::generate_values_json(JsonObject & root, const uint8_t tag_filter // If a divider is specified, do the division to 2 decimals places and send back as double/float // otherwise force as an integer whole // the nested if's is necessary due to the way the ArduinoJson templates are pre-processed by the compiler - uint8_t divider = (dv.options_size == 1) ? Helpers::atoint(uuid::read_flash_string(dv.options[0]).c_str()) : 0; + uint8_t divider = 0; + uint8_t factor = 1; + if (dv.options_size == 1) { + const char * s = uuid::read_flash_string(dv.options[0]).c_str(); + if (s[0] == '*') { + factor = Helpers::atoint(&s[1]); + } else { + divider = Helpers::atoint(s); + } + } // INT if ((dv.type == DeviceValueType::INT) && Helpers::hasValue(*(int8_t *)(dv.value_p))) { if (divider) { json[name] = Helpers::round2(*(int8_t *)(dv.value_p), divider); } else { - json[name] = *(int8_t *)(dv.value_p); + json[name] = *(int8_t *)(dv.value_p) * factor; } has_value = true; } else if ((dv.type == DeviceValueType::UINT) && Helpers::hasValue(*(uint8_t *)(dv.value_p))) { if (divider) { json[name] = Helpers::round2(*(uint8_t *)(dv.value_p), divider); } else { - json[name] = *(uint8_t *)(dv.value_p); + json[name] = *(uint8_t *)(dv.value_p) * factor; } has_value = true; } else if ((dv.type == DeviceValueType::SHORT) && Helpers::hasValue(*(int16_t *)(dv.value_p))) { if (divider) { json[name] = Helpers::round2(*(int16_t *)(dv.value_p), divider); } else { - json[name] = *(int16_t *)(dv.value_p); + json[name] = *(int16_t *)(dv.value_p) * factor; } has_value = true; } else if ((dv.type == DeviceValueType::USHORT) && Helpers::hasValue(*(uint16_t *)(dv.value_p))) { if (divider) { json[name] = Helpers::round2(*(uint16_t *)(dv.value_p), divider); } else { - json[name] = *(uint16_t *)(dv.value_p); + json[name] = *(uint16_t *)(dv.value_p) * factor; } has_value = true; } else if ((dv.type == DeviceValueType::ULONG) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) { if (divider) { json[name] = Helpers::round2(*(uint32_t *)(dv.value_p), divider); } else { - json[name] = *(uint32_t *)(dv.value_p); + json[name] = *(uint32_t *)(dv.value_p) * factor; } has_value = true; } else if ((dv.type == DeviceValueType::TIME) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) { uint32_t time_value = *(uint32_t *)(dv.value_p); - time_value = (divider) ? time_value / divider : time_value; // sometimes we need to divide by 60 + time_value = (divider) ? time_value / divider : time_value * factor; // sometimes we need to divide by 60 if (console) { char time_s[40]; snprintf_P(time_s, sizeof(time_s), "%d days %d hours %d minutes", (time_value / 1440), ((time_value % 1440) / 60), (time_value % 60)); diff --git a/src/helpers.cpp b/src/helpers.cpp index 949326686..bc1f41d88 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -350,7 +350,7 @@ uint32_t Helpers::hextoint(const char * hex) { // quick char to long uint16_t Helpers::atoint(const char * value) { unsigned int x = 0; - while (*value != '\0') { + while (*value >= '0' && *value <= '9') { x = (x * 10) + (*value - '0'); ++value; } diff --git a/src/locale_EN.h b/src/locale_EN.h index a3837591f..a32081665 100644 --- a/src/locale_EN.h +++ b/src/locale_EN.h @@ -162,6 +162,8 @@ MAKE_PSTR_LIST(div2, F_(2)) MAKE_PSTR_LIST(div10, F_(10)) MAKE_PSTR_LIST(div100, F_(100)) MAKE_PSTR_LIST(div60, F_(60)) +MAKE_PSTR_LIST(mul10, F("*10")) +MAKE_PSTR_LIST(mul15, F("*15")) // Unit Of Measurement mapping - maps to DeviceValueUOM_s in emsdevice.cpp // uom - also used with HA see https://github.com/home-assistant/core/blob/d7ac4bd65379e11461c7ce0893d3533d8d8b8cbf/homeassistant/const.py#L384 @@ -352,7 +354,7 @@ MAKE_PSTR_LIST(enum_control, F_(off), F_(rc20), F_(rc3x)) MAKE_PSTR_LIST(enum_wwProgMode, F("std prog"), F_(own_prog)) MAKE_PSTR_LIST(enum_dayOfWeek, F("mo"), F("tu"), F("we"), F("th"), F("fr"), F("sa"), F("so"), F("all")) -MAKE_PSTR_LIST(enum_wwChargeDuration, F_(off), F("15min"), F("30min"), F("45min"), F("60min"), F("75min"), F("90min"), F("105min"), F("120min")) +// MAKE_PSTR_LIST(enum_wwChargeDuration, F_(off), F("15min"), F("30min"), F("45min"), F("60min"), F("75min"), F("90min"), F("105min"), F("120min")) // solar list MAKE_PSTR_LIST(enum_solarmode, F_(constant), F("pwm"), F("analog")) From e92a3ad0253ea6178633be83ef9c1091b970946d Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 20 Sep 2021 08:51:16 +0200 Subject: [PATCH 2/3] add MM10 valvetime --- src/devices/mixer.cpp | 39 ++++++++++++++++++++++++++++++++++----- src/devices/mixer.h | 4 ++++ src/locale_EN.h | 1 + 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/devices/mixer.cpp b/src/devices/mixer.cpp index 76ab005f3..0a7d5ca9b 100644 --- a/src/devices/mixer.cpp +++ b/src/devices/mixer.cpp @@ -78,6 +78,8 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s register_device_value(tag, &status_, DeviceValueType::INT, nullptr, FL_(mixerStatus), DeviceValueUOM::PERCENT); register_device_value(tag, &flowSetTemp_, DeviceValueType::UINT, nullptr, FL_(flowSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flowSetTemp)); register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_pump)); + register_device_value(tag, &activated_, DeviceValueType::BOOL, nullptr, FL_(activated), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_activated)); + register_device_value(tag, &setValveTime_, DeviceValueType::UINT, FL_(mul10), FL_(mixerSetTime), DeviceValueUOM::SECONDS, MAKE_CF_CB(set_setValveTime), 1, 12); } // HT3 @@ -231,16 +233,16 @@ void Mixer::process_HpPoolStatus(std::shared_ptr telegram) { poolShuntStatus_ = poolShunt_ == 100 ? 3 : (poolShunt_ == 0 ? 4 : poolShuntStatus__); } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" - // Mixer on a MM10 - 0xAA // e.g. Thermostat -> Mixer Module, type 0xAA, telegram: 10 21 AA 00 FF 0C 0A 11 0A 32 xx void Mixer::process_MMConfigMessage(std::shared_ptr telegram) { - // pos 0: active FF = on - // pos 1: valve runtime 0C = 120 sec in units of 10 sec + has_update(telegram->read_value(activated_, 0)); // on = 0xFF + has_update(telegram->read_value(setValveTime_, 1)); // valve runtime in 10 sec, max 120 s } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" + // Mixer on a MM10 - 0xAC // e.g. Thermostat -> Mixer Module, type 0xAC, telegram: 10 21 AC 00 1E 64 01 AB void Mixer::process_MMSetMessage(std::shared_ptr telegram) { @@ -300,4 +302,31 @@ bool Mixer::set_pump(const char * value, const int8_t id) { return false; } +bool Mixer::set_activated(const char * value, const int8_t id) { + bool b; + if (!Helpers::value2bool(value, b)) { + return false; + } + if (flags() == EMSdevice::EMS_DEVICE_FLAG_MM10) { + LOG_INFO(F("Setting mixer %s"), value); + write_command(0xAA, 0, b ? 0xFF : 0, 0xAA); + return true; + } + return false; +} + +bool Mixer::set_setValveTime(const char * value, const int8_t id) { + int v; + if (!Helpers::value2number(value, v)) { + return false; + } + if (flags() == EMSdevice::EMS_DEVICE_FLAG_MM10) { + v = (v + 5) / 10; + LOG_INFO(F("Setting mixer valve time to %ds"), v * 10); + write_command(0xAA, 1, v, 0xAA); + return true; + } + return false; +} + } // namespace emsesp diff --git a/src/devices/mixer.h b/src/devices/mixer.h index 556b00146..ff9a200bd 100644 --- a/src/devices/mixer.h +++ b/src/devices/mixer.h @@ -44,6 +44,8 @@ class Mixer : public EMSdevice { bool set_flowSetTemp(const char * value, const int8_t id); bool set_pump(const char * value, const int8_t id); + bool set_activated(const char * value, const int8_t id); + bool set_setValveTime(const char * value, const int8_t id); enum class Type { NONE, @@ -59,6 +61,8 @@ class Mixer : public EMSdevice { uint8_t pumpStatus_; int8_t status_; uint8_t flowSetTemp_; + uint8_t activated_; + uint8_t setValveTime_; int16_t poolTemp_; int8_t poolShuntStatus__; diff --git a/src/locale_EN.h b/src/locale_EN.h index a32081665..48fb642b1 100644 --- a/src/locale_EN.h +++ b/src/locale_EN.h @@ -597,6 +597,7 @@ MAKE_PSTR_LIST(flowTempHc, F("flowtemphc"), F("flow temperature in assigned hc ( MAKE_PSTR_LIST(pumpStatus, F("pumpstatus"), F("pump status in assigned hc (PC1)")) MAKE_PSTR_LIST(mixerStatus, F("valvestatus"), F("mixing valve actuator in assigned hc (VC1)")) MAKE_PSTR_LIST(flowTempVf, F("flowtempvf"), F("flow temperature in header (T0/Vf)")) +MAKE_PSTR_LIST(mixerSetTime, F("valvesettime"), F("time to set valve")) MAKE_PSTR_LIST(wwPumpStatus, F("pumpstatus"), F("pump status in assigned wwc (PC1)")) MAKE_PSTR_LIST(wwTempStatus, F("wwtempstatus"), F("temperature switch in assigned wwc (MC1)")) MAKE_PSTR_LIST(wwTemp, F("wwtemp"), F("current temperature")) From 2516d2d6ded25b433f697394f2ba63e813510034 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 20 Sep 2021 08:53:03 +0200 Subject: [PATCH 3/3] add boiler disinfect command --- src/devices/boiler.cpp | 24 +++++++++++++++++++++--- src/devices/boiler.h | 3 ++- src/locale_EN.h | 4 ++-- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index 503df6fa1..a7d243deb 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -261,7 +261,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const register_device_value( TAG_BOILER_DATA_WW, &wwActivated_, DeviceValueType::BOOL, nullptr, FL_(wwActivated), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_warmwater_activated)); register_device_value(TAG_BOILER_DATA_WW, &wwOneTime_, DeviceValueType::BOOL, nullptr, FL_(wwOneTime), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_warmwater_onetime)); - register_device_value(TAG_BOILER_DATA_WW, &wwDisinfecting_, DeviceValueType::BOOL, nullptr, FL_(wwDisinfecting), DeviceValueUOM::BOOLEAN); + register_device_value(TAG_BOILER_DATA_WW, &wwDisinfect_, DeviceValueType::BOOL, nullptr, FL_(wwDisinfect), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_warmwater_disinfect)); register_device_value(TAG_BOILER_DATA_WW, &wwCharging_, DeviceValueType::BOOL, nullptr, FL_(wwCharging), DeviceValueUOM::BOOLEAN); register_device_value(TAG_BOILER_DATA_WW, &wwRecharging_, DeviceValueType::BOOL, nullptr, FL_(wwRecharging), DeviceValueUOM::BOOLEAN); register_device_value(TAG_BOILER_DATA_WW, &wwTempOK_, DeviceValueType::BOOL, nullptr, FL_(wwTempOK), DeviceValueUOM::BOOLEAN); @@ -471,7 +471,7 @@ void Boiler::process_UBAMonitorWW(std::shared_ptr telegram) { has_update(telegram->read_value(wWStarts_, 13, 3)); // force to 3 bytes has_update(telegram->read_bitvalue(wwOneTime_, 5, 1)); - has_update(telegram->read_bitvalue(wwDisinfecting_, 5, 2)); + has_update(telegram->read_bitvalue(wwDisinfect_, 5, 2)); has_update(telegram->read_bitvalue(wwCharging_, 5, 3)); has_update(telegram->read_bitvalue(wwRecharging_, 5, 4)); has_update(telegram->read_bitvalue(wwTempOK_, 5, 5)); @@ -611,7 +611,7 @@ void Boiler::process_UBAMonitorWWPlus(std::shared_ptr telegram) has_update(telegram->read_value(wWStarts_, 17, 3)); // force to 3 bytes has_update(telegram->read_bitvalue(wwOneTime_, 12, 2)); - has_update(telegram->read_bitvalue(wwDisinfecting_, 12, 3)); + has_update(telegram->read_bitvalue(wwDisinfect_, 12, 3)); has_update(telegram->read_bitvalue(wwCharging_, 12, 4)); has_update(telegram->read_bitvalue(wwRecharging_, 13, 4)); has_update(telegram->read_bitvalue(wwTempOK_, 13, 5)); @@ -1310,6 +1310,24 @@ bool Boiler::set_warmwater_circulation(const char * value, const int8_t id) { return true; } +// starting warm water disinfect, set to off seems not working +bool Boiler::set_warmwater_disinfect(const char * value, const int8_t id) { + bool v = false; + if (!Helpers::value2bool(value, v)) { + LOG_WARNING(F("Set warm water disinfect: Invalid value")); + return false; + } + + LOG_INFO(F("Setting warm water disinfect %s"), v ? "on" : "off"); + if (is_fetch(EMS_TYPE_UBAParameterWWPlus)) { + write_command(EMS_TYPE_UBAFlags, 0, (v ? 0x44 : 0x04), 0xE9); // not sure if this is in flags + } else { + write_command(EMS_TYPE_UBAFlags, 0, (v ? 0x44 : 0x04), 0x34); + } + + return true; +} + // configuration of warm water circulation pump bool Boiler::set_warmwater_circulation_pump(const char * value, const int8_t id) { bool v = false; diff --git a/src/devices/boiler.h b/src/devices/boiler.h index cbafb5ec4..264015b01 100644 --- a/src/devices/boiler.h +++ b/src/devices/boiler.h @@ -74,7 +74,7 @@ class Boiler : public EMSdevice { uint16_t wwStorageTemp2_; // warm water storage temp 2 uint8_t wwActivated_; // Warm Water activated uint8_t wwOneTime_; // Warm Water one time function on/off - uint8_t wwDisinfecting_; // Warm Water disinfection on/off + uint8_t wwDisinfect_; // Warm Water disinfection on/off uint8_t wwCharging_; // Warm Water charging on/off uint8_t wwRecharging_; // Warm Water recharge on/off uint8_t wwTempOK_; // Warm Water temperature ok on/off @@ -229,6 +229,7 @@ class Boiler : public EMSdevice { bool set_warmwater_activated(const char * value, const int8_t id); bool set_tapwarmwater_activated(const char * value, const int8_t id); bool set_warmwater_onetime(const char * value, const int8_t id); + bool set_warmwater_disinfect(const char * value, const int8_t id); bool set_warmwater_circulation(const char * value, const int8_t id); bool set_warmwater_circulation_pump(const char * value, const int8_t id); bool set_warmwater_circulation_mode(const char * value, const int8_t id); diff --git a/src/locale_EN.h b/src/locale_EN.h index 48fb642b1..083a59716 100644 --- a/src/locale_EN.h +++ b/src/locale_EN.h @@ -499,7 +499,7 @@ MAKE_PSTR_LIST(wwStorageTemp1, F("wwstoragetemp1"), F("storage intern temperatur MAKE_PSTR_LIST(wwStorageTemp2, F("wwstoragetemp2"), F("storage extern temperature")) MAKE_PSTR_LIST(wwActivated, F("wwactivated"), F("activated")) MAKE_PSTR_LIST(wwOneTime, F("wwonetime"), F("one time charging")) -MAKE_PSTR_LIST(wwDisinfecting, F("wwdisinfecting"), F("disinfecting")) +MAKE_PSTR_LIST(wwDisinfect, F("wwdisinfect"), F("disinfection")) MAKE_PSTR_LIST(wwCharging, F("wwcharging"), F("charging")) MAKE_PSTR_LIST(wwRecharging, F("wwrecharging"), F("recharging")) MAKE_PSTR_LIST(wwTempOK, F("wwtempok"), F("temperature ok")) @@ -514,7 +514,7 @@ MAKE_PSTR_LIST(wwHystOn, F("wwhyston"), F("hysteresis on temperature")) MAKE_PSTR_LIST(wwHystOff, F("wwhystoff"), F("hysteresis off temperature")) MAKE_PSTR_LIST(wwProgMode, F("wwprogmode"), F("program mode")) MAKE_PSTR_LIST(wwCircProg, F("wwcircprog"), F("circulation program mode")) -MAKE_PSTR_LIST(wwDisinfect, F("wwdisinfect"), F("disinfection")) +// MAKE_PSTR_LIST(wwDisinfect, F("wwdisinfect"), F("disinfection")) // same as in boiler MAKE_PSTR_LIST(wwDisinfectDay, F("wwdisinfectday"), F("disinfection day")) MAKE_PSTR_LIST(wwDisinfectHour, F("wwdisinfecthour"), F("disinfection hour")) MAKE_PSTR_LIST(wwMaxTemp, F("wwmaxtemp"), F("maximum temperature"))