From 6d6cb755e2c208579e4f6b1f5997c22342724c99 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 10 Apr 2022 10:03:36 +0200 Subject: [PATCH 1/9] update hybrid heatpump #459 --- src/device_library.h | 2 +- src/devices/boiler.cpp | 132 ++++++++++++++++++++++++++++++++++++++++- src/devices/boiler.h | 18 ++++++ src/emsdevice.h | 1 + src/locale_EN.h | 10 ++++ 5 files changed, 161 insertions(+), 2 deletions(-) diff --git a/src/device_library.h b/src/device_library.h index 32b5be398..bd1a7d40f 100644 --- a/src/device_library.h +++ b/src/device_library.h @@ -36,7 +36,7 @@ {132, DeviceType::BOILER, F("GC7000F"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, {133, DeviceType::BOILER, F("Logano GB125/KB195i/Logamatic MC110"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, {167, DeviceType::BOILER, F("Cerapur Aero"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, -{168, DeviceType::BOILER, F("Hybrid Heatpump"), DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP}, +{168, DeviceType::BOILER, F("Hybrid Heatpump"), DeviceFlags::EMS_DEVICE_FLAG_HYBRID}, {170, DeviceType::BOILER, F("Logano GB212"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, {172, DeviceType::BOILER, F("Enviline/Compress 6000AW/Hybrid 7000iAW/SupraEco/Geo 5xx"), DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP}, {173, DeviceType::BOILER, F("Geo 5xx"), DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP}, diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index 996146840..811cffa7a 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -71,7 +71,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const } // only EMS+ - if (model() != EMSdevice::EMS_DEVICE_FLAG_EMS && model() != EMSdevice::EMS_DEVICE_FLAG_HT3) { + if (model() != EMSdevice::EMS_DEVICE_FLAG_EMS && model() != EMSdevice::EMS_DEVICE_FLAG_HT3 && model() != EMSdevice::EMS_DEVICE_FLAG_HYBRID) { register_telegram_type(0xD1, F("UBAOutdoorTemp"), false, MAKE_PF_CB(process_UBAOutdoorTemp)); register_telegram_type(0xE3, F("UBAMonitorSlowPlus2"), false, MAKE_PF_CB(process_UBAMonitorSlowPlus2)); register_telegram_type(0xE4, F("UBAMonitorFastPlus"), false, MAKE_PF_CB(process_UBAMonitorFastPlus)); @@ -89,6 +89,10 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const register_telegram_type(0x48A, F("HpPool"), true, MAKE_PF_CB(process_HpPool)); } + if (model() == EMSdevice::EMS_DEVICE_FLAG_HYBRID) { + register_telegram_type(0xBB, F("HybridHp"), true, MAKE_PF_CB(process_HybridHp)); + } + // reset is a command uses a dummy variable which is always zero, shown as blank, but provides command enum options register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &reset_, DeviceValueType::CMD, FL_(enum_reset), FL_(reset), DeviceValueUOM::NONE, MAKE_CF_CB(set_reset)); has_update(reset_, 0); @@ -198,6 +202,58 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const DeviceValueUOM::NONE, MAKE_CF_CB(set_maintenancedate)); + // Hybrid Heatpump + if (model() == EMSdevice::EMS_DEVICE_FLAG_HYBRID) { + register_device_value(DeviceValueTAG::TAG_BOILER_DATA, + &gasPriceMode_, + DeviceValueType::ENUM, + FL_(enum_gasPriceMode), + FL_(gasPriceMode), + DeviceValueUOM::NONE, + MAKE_CF_CB(set_gasPriceMode)); + register_device_value(DeviceValueTAG::TAG_BOILER_DATA, + &switchOverTemp_, + DeviceValueType::UINT, + nullptr, + FL_(switchOverTemp), + DeviceValueUOM::DEGREES, + MAKE_CF_CB(set_switchOverTemp)); + register_device_value(DeviceValueTAG::TAG_BOILER_DATA, + &gasPriceRatio_, + DeviceValueType::UINT, + FL_(div10), + FL_(gasPriceRatio), + DeviceValueUOM::NONE, + MAKE_CF_CB(set_gasPriceRatio)); + register_device_value(DeviceValueTAG::TAG_BOILER_DATA, + &fossileFactor_, + DeviceValueType::UINT, + FL_(div10), + FL_(fossileFactor), + DeviceValueUOM::NONE, + MAKE_CF_CB(set_fossileFactor)); + register_device_value(DeviceValueTAG::TAG_BOILER_DATA, + &electricFactor_, + DeviceValueType::UINT, + FL_(div10), + FL_(electricFactor), + DeviceValueUOM::NONE, + MAKE_CF_CB(set_electricFactor)); + register_device_value(DeviceValueTAG::TAG_BOILER_DATA, + &waitBoiler_, + DeviceValueType::UINT, + nullptr, + FL_(waitBoiler), + DeviceValueUOM::MINUTES, + MAKE_CF_CB(set_waitBoiler)); + register_device_value(DeviceValueTAG::TAG_BOILER_DATA, + &tempDiffBoiler_, + DeviceValueType::UINT, + nullptr, + FL_(tempDiffBoiler), + DeviceValueUOM::DEGREES_R, + MAKE_CF_CB(set_tempDiffBoiler)); + } // heatpump info if (model() == EMS_DEVICE_FLAG_HEATPUMP) { register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &upTimeControl_, DeviceValueType::TIME, FL_(div60), FL_(upTimeControl), DeviceValueUOM::MINUTES); @@ -994,6 +1050,80 @@ void Boiler::process_UBAMaintenanceData(std::shared_ptr telegram } } + +// 0xBB Heatpump optimization +// Boiler(0x08) -> Me(0x0B), ?(0xBB), data: 00 00 00 00 00 00 00 00 00 00 00 FF 02 0F 1E 0B 1A 00 14 03 +void Boiler::process_HybridHp(std::shared_ptr telegram) { + has_enumupdate(telegram, gasPriceMode_, 12, 1); // cost = 2, temperature = 3, mix = 4 + has_update(telegram, switchOverTemp_, 13); // full degrees + has_update(telegram, gasPriceRatio_, 14); // is *10 + has_update(telegram, fossileFactor_, 15); // is * 10 + has_update(telegram, electricFactor_, 16); // is * 10 + has_update(telegram, waitBoiler_, 18); // minutes + has_update(telegram, tempDiffBoiler_, 19); // relative degrees +} + +/* + * Settings + */ + +bool Boiler::set_gasPriceMode(const char * value, const int8_t id) { + uint8_t v; + if (!Helpers::value2enum(value, v, FL_(enum_gasPriceMode))) { + return false; + } + write_command(0xBB, 12, v + 1, 0xBB); + return true; +} +bool Boiler::set_switchOverTemp(const char * value, const int8_t id) { + int v; + if (!Helpers::value2temperature(value, v)) { + return false; + } + write_command(0xBB, 13, v, 0xBB); + return true; +} +bool Boiler::set_gasPriceRatio(const char * value, const int8_t id) { + float v; + if (!Helpers::value2float(value, v)) { + return false; + } + write_command(0xBB, 14, (uint8_t)(v * 10), 0xBB); + return true; +} +bool Boiler::set_fossileFactor(const char * value, const int8_t id) { + float v; + if (!Helpers::value2float(value, v)) { + return false; + } + write_command(0xBB, 15, (uint8_t)(v * 10), 0xBB); + return true; +} +bool Boiler::set_electricFactor(const char * value, const int8_t id) { + float v; + if (!Helpers::value2float(value, v)) { + return false; + } + write_command(0xBB, 16, (uint8_t)(v * 10), 0xBB); + return true; +} +bool Boiler::set_waitBoiler(const char * value, const int8_t id) { + int v; + if (!Helpers::value2number(value, v)) { + return false; + } + write_command(0xBB, 18, v, 0xBB); + return true; +} +bool Boiler::set_tempDiffBoiler(const char * value, const int8_t id) { + int v; + if (!Helpers::value2temperature(value, v, true)) { + return false; + } + write_command(0xBB, 19, v, 0xBB); + return true; +} + // Set the dhw temperature 0x33/0x35 or 0xEA bool Boiler::set_ww_temp(const char * value, const int8_t id) { int v = 0; diff --git a/src/devices/boiler.h b/src/devices/boiler.h index d83821457..9be5110fd 100644 --- a/src/devices/boiler.h +++ b/src/devices/boiler.h @@ -193,6 +193,15 @@ class Boiler : public EMSdevice { // Pool unit int8_t poolSetTemp_; + // HybridHP + uint8_t gasPriceMode_; // cost = 2, temperature = 3, mix = 4 + uint8_t switchOverTemp_; // degrees + uint8_t gasPriceRatio_; // is *10 + uint8_t fossileFactor_; // is * 10 + uint8_t electricFactor_; // is * 10 + uint8_t waitBoiler_; // minutes + uint8_t tempDiffBoiler_; // relative temperature degrees + void process_UBAParameterWW(std::shared_ptr telegram); void process_UBAMonitorFast(std::shared_ptr telegram); void process_UBATotalUptime(std::shared_ptr telegram); @@ -221,6 +230,7 @@ class Boiler : public EMSdevice { void process_HpPower(std::shared_ptr telegram); void process_HpOutdoor(std::shared_ptr telegram); void process_HpPool(std::shared_ptr telegram); + void process_HybridHp(std::shared_ptr telegram); // commands - none of these use the additional id parameter bool set_ww_mode(const char * value, const int8_t id); @@ -256,6 +266,14 @@ class Boiler : public EMSdevice { bool set_ww_hyst_on(const char * value, const int8_t id); bool set_ww_hyst_off(const char * value, const int8_t id); bool set_pool_temp(const char * value, const int8_t id); + + bool set_gasPriceMode(const char * value, const int8_t id); + bool set_switchOverTemp(const char * value, const int8_t id); + bool set_gasPriceRatio(const char * value, const int8_t id); + bool set_fossileFactor(const char * value, const int8_t id); + bool set_electricFactor(const char * value, const int8_t id); + bool set_waitBoiler(const char * value, const int8_t id); + bool set_tempDiffBoiler(const char * value, const int8_t id); }; } // namespace emsesp diff --git a/src/emsdevice.h b/src/emsdevice.h index 99cadae76..2f03afd2c 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -319,6 +319,7 @@ class EMSdevice { static constexpr uint8_t EMS_DEVICE_FLAG_EMSPLUS = 2; static constexpr uint8_t EMS_DEVICE_FLAG_HT3 = 3; static constexpr uint8_t EMS_DEVICE_FLAG_HEATPUMP = 4; + static constexpr uint8_t EMS_DEVICE_FLAG_HYBRID = 5; // Solar Module static constexpr uint8_t EMS_DEVICE_FLAG_SM10 = 1; diff --git a/src/locale_EN.h b/src/locale_EN.h index c1b14c3a2..c00b65014 100644 --- a/src/locale_EN.h +++ b/src/locale_EN.h @@ -509,6 +509,16 @@ MAKE_PSTR_LIST(hpTl2, F("hptl2"), F("air inlet temperature (TL2)")) MAKE_PSTR_LIST(hpPl1, F("hppl1"), F("low pressure side temperature (PL1)")) MAKE_PSTR_LIST(hpPh1, F("hpph1"), F("high pressure side temperature (PH1)")) +// hybrid heatpump +MAKE_PSTR_LIST(enum_gasPriceMode, F("co2"), F("cost"), F("temperature"), F("mix")) +MAKE_PSTR_LIST(gasPriceMode, F("gaspricemode"), F("gas price mode")) +MAKE_PSTR_LIST(switchOverTemp, F("switchovertemp"), F("switch over temperature")) +MAKE_PSTR_LIST(gasPriceRatio, F("gaspriceratio"), F("gas price ratio")) +MAKE_PSTR_LIST(fossileFactor, F("fossilefactor"), F("fossile factor")) +MAKE_PSTR_LIST(electricFactor, F("electricfactor"), F("electric factor")) +MAKE_PSTR_LIST(waitBoiler, F("waitboiler"), F("wait boiler")) +MAKE_PSTR_LIST(tempDiffBoiler, F("tempdiffboiler"), F("temperature difference boiler")) + // the following are dhw for the boiler and automatically tagged with 'ww' MAKE_PSTR_LIST(wwSelTemp, F("wwseltemp"), F("selected temperature")) MAKE_PSTR_LIST(wwSelTempLow, F("wwseltemplow"), F("selected lower temperature")) From cf876acc5d750470b2def58c544ea8f52c6f0b96 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 10 Apr 2022 14:34:10 +0200 Subject: [PATCH 2/9] rename hybrid entities --- src/devices/boiler.cpp | 41 +++++++++++++++++++++++------------------ src/devices/boiler.h | 12 ++++++------ src/locale_EN.h | 23 +++++++++++++++-------- 3 files changed, 44 insertions(+), 32 deletions(-) diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index 811cffa7a..3fd61ad88 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -205,12 +205,12 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const // Hybrid Heatpump if (model() == EMSdevice::EMS_DEVICE_FLAG_HYBRID) { register_device_value(DeviceValueTAG::TAG_BOILER_DATA, - &gasPriceMode_, + &hybridStrategy_, DeviceValueType::ENUM, - FL_(enum_gasPriceMode), - FL_(gasPriceMode), + FL_(enum_hybridStrategy), + FL_(hybridStrategy), DeviceValueUOM::NONE, - MAKE_CF_CB(set_gasPriceMode)); + MAKE_CF_CB(set_hybridStrategy)); register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &switchOverTemp_, DeviceValueType::UINT, @@ -219,12 +219,12 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const DeviceValueUOM::DEGREES, MAKE_CF_CB(set_switchOverTemp)); register_device_value(DeviceValueTAG::TAG_BOILER_DATA, - &gasPriceRatio_, + &energyCostRatio_, DeviceValueType::UINT, FL_(div10), - FL_(gasPriceRatio), + FL_(energyCostRatio), DeviceValueUOM::NONE, - MAKE_CF_CB(set_gasPriceRatio)); + MAKE_CF_CB(set_energyCostRatio)); register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &fossileFactor_, DeviceValueType::UINT, @@ -240,12 +240,12 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const DeviceValueUOM::NONE, MAKE_CF_CB(set_electricFactor)); register_device_value(DeviceValueTAG::TAG_BOILER_DATA, - &waitBoiler_, + &delayBoiler_, DeviceValueType::UINT, nullptr, - FL_(waitBoiler), + FL_(delayBoiler), DeviceValueUOM::MINUTES, - MAKE_CF_CB(set_waitBoiler)); + MAKE_CF_CB(set_delayBoiler)); register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &tempDiffBoiler_, DeviceValueType::UINT, @@ -1050,16 +1050,15 @@ void Boiler::process_UBAMaintenanceData(std::shared_ptr telegram } } - // 0xBB Heatpump optimization // Boiler(0x08) -> Me(0x0B), ?(0xBB), data: 00 00 00 00 00 00 00 00 00 00 00 FF 02 0F 1E 0B 1A 00 14 03 void Boiler::process_HybridHp(std::shared_ptr telegram) { - has_enumupdate(telegram, gasPriceMode_, 12, 1); // cost = 2, temperature = 3, mix = 4 + has_enumupdate(telegram, hybridStrategy_, 12, 1); // cost = 2, temperature = 3, mix = 4 has_update(telegram, switchOverTemp_, 13); // full degrees - has_update(telegram, gasPriceRatio_, 14); // is *10 + has_update(telegram, energyCostRatio_, 14); // is *10 has_update(telegram, fossileFactor_, 15); // is * 10 has_update(telegram, electricFactor_, 16); // is * 10 - has_update(telegram, waitBoiler_, 18); // minutes + has_update(telegram, delayBoiler_, 18); // minutes has_update(telegram, tempDiffBoiler_, 19); // relative degrees } @@ -1067,14 +1066,15 @@ void Boiler::process_HybridHp(std::shared_ptr telegram) { * Settings */ -bool Boiler::set_gasPriceMode(const char * value, const int8_t id) { +bool Boiler::set_hybridStrategy(const char * value, const int8_t id) { uint8_t v; - if (!Helpers::value2enum(value, v, FL_(enum_gasPriceMode))) { + if (!Helpers::value2enum(value, v, FL_(enum_hybridStrategy))) { return false; } write_command(0xBB, 12, v + 1, 0xBB); return true; } + bool Boiler::set_switchOverTemp(const char * value, const int8_t id) { int v; if (!Helpers::value2temperature(value, v)) { @@ -1083,7 +1083,8 @@ bool Boiler::set_switchOverTemp(const char * value, const int8_t id) { write_command(0xBB, 13, v, 0xBB); return true; } -bool Boiler::set_gasPriceRatio(const char * value, const int8_t id) { + +bool Boiler::set_energyCostRatio(const char * value, const int8_t id) { float v; if (!Helpers::value2float(value, v)) { return false; @@ -1091,6 +1092,7 @@ bool Boiler::set_gasPriceRatio(const char * value, const int8_t id) { write_command(0xBB, 14, (uint8_t)(v * 10), 0xBB); return true; } + bool Boiler::set_fossileFactor(const char * value, const int8_t id) { float v; if (!Helpers::value2float(value, v)) { @@ -1099,6 +1101,7 @@ bool Boiler::set_fossileFactor(const char * value, const int8_t id) { write_command(0xBB, 15, (uint8_t)(v * 10), 0xBB); return true; } + bool Boiler::set_electricFactor(const char * value, const int8_t id) { float v; if (!Helpers::value2float(value, v)) { @@ -1107,7 +1110,8 @@ bool Boiler::set_electricFactor(const char * value, const int8_t id) { write_command(0xBB, 16, (uint8_t)(v * 10), 0xBB); return true; } -bool Boiler::set_waitBoiler(const char * value, const int8_t id) { + +bool Boiler::set_delayBoiler(const char * value, const int8_t id) { int v; if (!Helpers::value2number(value, v)) { return false; @@ -1115,6 +1119,7 @@ bool Boiler::set_waitBoiler(const char * value, const int8_t id) { write_command(0xBB, 18, v, 0xBB); return true; } + bool Boiler::set_tempDiffBoiler(const char * value, const int8_t id) { int v; if (!Helpers::value2temperature(value, v, true)) { diff --git a/src/devices/boiler.h b/src/devices/boiler.h index 9be5110fd..1641a49a7 100644 --- a/src/devices/boiler.h +++ b/src/devices/boiler.h @@ -194,12 +194,12 @@ class Boiler : public EMSdevice { int8_t poolSetTemp_; // HybridHP - uint8_t gasPriceMode_; // cost = 2, temperature = 3, mix = 4 + uint8_t hybridStrategy_; // cost = 2, temperature = 3, mix = 4 uint8_t switchOverTemp_; // degrees - uint8_t gasPriceRatio_; // is *10 + uint8_t energyCostRatio_; // is *10 uint8_t fossileFactor_; // is * 10 uint8_t electricFactor_; // is * 10 - uint8_t waitBoiler_; // minutes + uint8_t delayBoiler_; // minutes uint8_t tempDiffBoiler_; // relative temperature degrees void process_UBAParameterWW(std::shared_ptr telegram); @@ -267,12 +267,12 @@ class Boiler : public EMSdevice { bool set_ww_hyst_off(const char * value, const int8_t id); bool set_pool_temp(const char * value, const int8_t id); - bool set_gasPriceMode(const char * value, const int8_t id); + bool set_hybridStrategy(const char * value, const int8_t id); bool set_switchOverTemp(const char * value, const int8_t id); - bool set_gasPriceRatio(const char * value, const int8_t id); + bool set_energyCostRatio(const char * value, const int8_t id); bool set_fossileFactor(const char * value, const int8_t id); bool set_electricFactor(const char * value, const int8_t id); - bool set_waitBoiler(const char * value, const int8_t id); + bool set_delayBoiler(const char * value, const int8_t id); bool set_tempDiffBoiler(const char * value, const int8_t id); }; diff --git a/src/locale_EN.h b/src/locale_EN.h index c00b65014..ff0d8be51 100644 --- a/src/locale_EN.h +++ b/src/locale_EN.h @@ -221,6 +221,12 @@ MAKE_PSTR(tag_wwc1, "wwc1") MAKE_PSTR(tag_wwc2, "wwc2") MAKE_PSTR(tag_wwc3, "wwc3") MAKE_PSTR(tag_wwc4, "wwc4") +MAKE_PSTR(tag_wwc5, "wwc5") +MAKE_PSTR(tag_wwc6, "wwc6") +MAKE_PSTR(tag_wwc7, "wwc7") +MAKE_PSTR(tag_wwc8, "wwc8") +MAKE_PSTR(tag_wwc9, "wwc9") +MAKE_PSTR(tag_wwc10, "wwc10") MAKE_PSTR(tag_hs1, "hs1") MAKE_PSTR(tag_hs2, "hs2") MAKE_PSTR(tag_hs3, "hs3") @@ -510,14 +516,14 @@ MAKE_PSTR_LIST(hpPl1, F("hppl1"), F("low pressure side temperature (PL1)")) MAKE_PSTR_LIST(hpPh1, F("hpph1"), F("high pressure side temperature (PH1)")) // hybrid heatpump -MAKE_PSTR_LIST(enum_gasPriceMode, F("co2"), F("cost"), F("temperature"), F("mix")) -MAKE_PSTR_LIST(gasPriceMode, F("gaspricemode"), F("gas price mode")) -MAKE_PSTR_LIST(switchOverTemp, F("switchovertemp"), F("switch over temperature")) -MAKE_PSTR_LIST(gasPriceRatio, F("gaspriceratio"), F("gas price ratio")) -MAKE_PSTR_LIST(fossileFactor, F("fossilefactor"), F("fossile factor")) -MAKE_PSTR_LIST(electricFactor, F("electricfactor"), F("electric factor")) -MAKE_PSTR_LIST(waitBoiler, F("waitboiler"), F("wait boiler")) -MAKE_PSTR_LIST(tempDiffBoiler, F("tempdiffboiler"), F("temperature difference boiler")) +MAKE_PSTR_LIST(enum_hybridStrategy, F("co2-optimized"), F("cost-optimized"), F("outside-temp-switched"), F("co2-cost-mix")) +MAKE_PSTR_LIST(hybridStrategy, F("hybridstrategy"), F("hybrid control strategy")) +MAKE_PSTR_LIST(switchOverTemp, F("switchovertemp"), F("outside switchover temperature")) +MAKE_PSTR_LIST(energyCostRatio, F("energycostratio"), F("energy cost ratio")) +MAKE_PSTR_LIST(fossileFactor, F("fossilefactor"), F("fossile energy factor")) +MAKE_PSTR_LIST(electricFactor, F("electricfactor"), F("electric energy factor")) +MAKE_PSTR_LIST(delayBoiler, F("delayboiler"), F("delay boiler support")) +MAKE_PSTR_LIST(tempDiffBoiler, F("tempdiffboiler"), F("tempediff boiler support")) // the following are dhw for the boiler and automatically tagged with 'ww' MAKE_PSTR_LIST(wwSelTemp, F("wwseltemp"), F("selected temperature")) @@ -671,6 +677,7 @@ MAKE_PSTR_LIST(poolSetTemp, F("poolsettemp"), F("pool set temperature")) MAKE_PSTR_LIST(poolTemp, F("pooltemp"), F("pool temperature")) MAKE_PSTR_LIST(poolShuntStatus, F("poolshuntstatus"), F("pool shunt status opening/closing")) MAKE_PSTR_LIST(poolShunt, F("poolshunt"), F("pool shunt open/close (0% = pool / 100% = heat)")) +MAKE_PSTR_LIST(hydrTemp, F("hydrTemp"), F("hydraulic header temperature")) // solar MAKE_PSTR_LIST(collectorTemp, F("collectortemp"), F("collector temperature (TS1)")) From 75914da36a27446a0aedde53494e34313a9ede0d Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 10 Apr 2022 14:35:55 +0200 Subject: [PATCH 3/9] thermostat switchpoints allow T1-T4 --- src/devices/thermostat.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index 48253bb2b..23bce8656 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -1148,12 +1148,14 @@ void Thermostat::process_RC35Timer(std::shared_ptr telegram) { char data[sizeof(hc->switchtime1)]; uint8_t no = telegram->offset / 2; uint8_t day = telegram->message_data[0] >> 5; - uint8_t on = telegram->message_data[0] & 1; + uint8_t on = telegram->message_data[0] & 0x07; uint8_t time = telegram->message_data[1]; std::string sday = read_flash_string(FL_(enum_dayOfWeek)[day]); if (day == 7) { snprintf(data, sizeof(data), "%02d not_set", no); + } else if (model() == EMS_DEVICE_FLAG_RC30_N) { + snprintf(data, sizeof(data), "%02d %s %02d:%02d T%d", no, sday.c_str(), time / 6, 10 * (time % 6), on); } else { snprintf(data, sizeof(data), "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), on ? "on" : "off"); } @@ -1306,6 +1308,12 @@ void Thermostat::process_RCErrorMessage(std::shared_ptr telegram } } +/* + * + * *** settings *** + * + */ + // 0xA5 - Set minimum external temperature bool Thermostat::set_minexttemp(const char * value, const int8_t id) { int mt = 0; @@ -2352,6 +2360,8 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char } if (strlen(value) > 13 && value[12] == 'o') { on = value[13] == 'n' ? 1 : 0; + } else if (strlen(value) > 13 && value[12] == 'T') { + on = value[13] - '0'; } else if (strlen(value) == 13) { on = value[12] - '0'; } @@ -2369,7 +2379,7 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char } uint8_t max_on = 3; - if ((model() == EMS_DEVICE_FLAG_RC35) || (model() == EMS_DEVICE_FLAG_RC30_N)) { + if (model() == EMS_DEVICE_FLAG_RC35) { max_on = 1; } if (no > 41 || time > 0x90 || (on > max_on && on != 7)) { @@ -2379,8 +2389,10 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char } if (data[0] != 0xE7) { std::string sday = read_flash_string(FL_(enum_dayOfWeek)[day]); - if ((model() == EMS_DEVICE_FLAG_RC35) || (model() == EMS_DEVICE_FLAG_RC30_N)) { + if (model() == EMS_DEVICE_FLAG_RC35) { snprintf(out, len, "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), on ? "on" : "off"); + } else if (model() == EMS_DEVICE_FLAG_RC30_N) { + snprintf(out, len, "%02d %s %02d:%02d T%d", no, sday.c_str(), time / 6, 10 * (time % 6), on + 1); } else if (model() == EMS_DEVICE_FLAG_RC20) { snprintf(out, len, "%02d %s %02d:%02d T%d", no, sday.c_str(), time / 6, 10 * (time % 6), on); } else { From 0d79138e0b47b43d93a87832ac937441462fda58 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 10 Apr 2022 14:37:43 +0200 Subject: [PATCH 4/9] product-id 100 is mixer with max wwc10, add handlers_ignored --- src/device_library.h | 2 +- src/devices/mixer.cpp | 57 ++++++++++++++++++++++++++++++++++-------- src/devices/mixer.h | 10 ++++++++ src/devices/solar.cpp | 40 +++-------------------------- src/devices/solar.h | 1 - src/emsdevice.cpp | 30 +++++++++++++++++++--- src/emsdevice.h | 5 +++- src/emsdevicevalue.cpp | 12 +++++++++ src/emsdevicevalue.h | 6 +++++ src/emsesp.cpp | 7 ++++-- src/system.cpp | 4 +++ 11 files changed, 118 insertions(+), 56 deletions(-) diff --git a/src/device_library.h b/src/device_library.h index bd1a7d40f..726972c5f 100644 --- a/src/device_library.h +++ b/src/device_library.h @@ -113,7 +113,6 @@ // Solar Modules - 0x30 (for solar), 0x2A, 0x41 (for ww) { 73, DeviceType::SOLAR, F("SM10"), DeviceFlags::EMS_DEVICE_FLAG_SM10}, -{100, DeviceType::SOLAR, F("ISM DHW"), DeviceFlags::EMS_DEVICE_FLAG_ISM}, {101, DeviceType::SOLAR, F("ISM1"), DeviceFlags::EMS_DEVICE_FLAG_ISM}, {103, DeviceType::SOLAR, F("ISM2"), DeviceFlags::EMS_DEVICE_FLAG_ISM}, {162, DeviceType::SOLAR, F("SM50"), DeviceFlags::EMS_DEVICE_FLAG_SM100}, @@ -122,6 +121,7 @@ // Mixer Modules - 0x20-0x27 for HC, 0x28-0x29 for WWC and 0x11 for the MP100 { 69, DeviceType::MIXER, F("MM10"), DeviceFlags::EMS_DEVICE_FLAG_MM10}, +{100, DeviceType::MIXER, F("IPM"), DeviceFlags::EMS_DEVICE_FLAG_IPM}, {102, DeviceType::MIXER, F("IPM"), DeviceFlags::EMS_DEVICE_FLAG_IPM}, {159, DeviceType::MIXER, F("MM50"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS}, {160, DeviceType::MIXER, F("MM100"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS}, diff --git a/src/devices/mixer.cpp b/src/devices/mixer.cpp index daeb29840..c1cacf0b1 100644 --- a/src/devices/mixer.cpp +++ b/src/devices/mixer.cpp @@ -99,17 +99,29 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c // HT3 if (flags == EMSdevice::EMS_DEVICE_FLAG_IPM) { - register_telegram_type(0x010C, F("IPMStatusMessage"), false, MAKE_PF_CB(process_IPMStatusMessage)); - register_telegram_type(0x011E, F("IPMTempMessage"), false, MAKE_PF_CB(process_IPMTempMessage)); - // register_telegram_type(0x0123, F("IPMSetMessage"), false, MAKE_PF_CB(process_IPMSetMessage)); - type_ = Type::HC; - hc_ = device_id - 0x20 + 1; - uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1; - register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES); - 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::NONE, MAKE_CF_CB(set_pump)); - register_device_value(tag, &flowTempVf_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempVf), DeviceValueUOM::DEGREES); + if (device_id >= 0x40) { // special DHW pos 10 + register_telegram_type(0x34, F("UBAMonitorWW"), false, MAKE_PF_CB(process_MonitorWW)); + register_telegram_type(0x1E, F("HydrTemp"), false, MAKE_PF_CB(process_HydrTemp)); + type_ = Type::WWC; + hc_ = device_id - 0x40 + 1; + uint8_t tag = DeviceValueTAG::TAG_WWC9 + hc_ - 1; + register_device_value(tag, &wwSelTemp_, DeviceValueType::UINT, nullptr, FL_(wwSelTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwSelTemp)); + register_device_value(tag, &wwCurTemp_1_, DeviceValueType::USHORT, FL_(div10), FL_(wwCurTemp), DeviceValueUOM::DEGREES); + register_device_value(tag, &wwCurTemp_2_, DeviceValueType::USHORT, FL_(div10), FL_(wwCurTemp2), DeviceValueUOM::DEGREES); + register_device_value(tag, &HydrTemp_, DeviceValueType::USHORT, FL_(div10), FL_(hydrTemp), DeviceValueUOM::DEGREES); + } else { + register_telegram_type(0x010C, F("IPMStatusMessage"), false, MAKE_PF_CB(process_IPMStatusMessage)); + register_telegram_type(0x011E, F("IPMTempMessage"), false, MAKE_PF_CB(process_IPMTempMessage)); + // register_telegram_type(0x0123, F("IPMSetMessage"), false, MAKE_PF_CB(process_IPMSetMessage)); + type_ = Type::HC; + hc_ = device_id - 0x20 + 1; + uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1; + register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES); + 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::NONE, MAKE_CF_CB(set_pump)); + register_device_value(tag, &flowTempVf_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempVf), DeviceValueUOM::DEGREES); + } } } @@ -203,6 +215,19 @@ void Mixer::process_MMPLUSConfigMessage_WWC(std::shared_ptr tele has_update(telegram, wwMaxTemp_, 10); } +// 0x34 +void Mixer::process_MonitorWW(std::shared_ptr telegram) { + has_update(telegram, wwSelTemp_, 0); + has_update(telegram, wwCurTemp_1_, 1); + has_update(telegram, wwCurTemp_2_, 3); +} +// 0x1E +void Mixer::process_HydrTemp(std::shared_ptr telegram) { + has_update(telegram, HydrTemp_, 0); +} + + + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" @@ -241,6 +266,16 @@ void Mixer::process_IPMSetMessage(std::shared_ptr telegram) { #pragma GCC diagnostic pop +bool Mixer::set_wwSelTemp(const char * value, const int8_t id) { + int temperature; + if (!Helpers::value2temperature(value, temperature)) { + return false; + } + write_command(0x35, 3, (uint8_t)temperature, 0x34); + return true; +} + + bool Mixer::set_flowSetTemp(const char * value, const int8_t id) { int v; if (!Helpers::value2number(value, v)) { diff --git a/src/devices/mixer.h b/src/devices/mixer.h index 1547598bd..8c8cf72ea 100644 --- a/src/devices/mixer.h +++ b/src/devices/mixer.h @@ -43,6 +43,9 @@ class Mixer : public EMSdevice { void process_MMSetMessage(std::shared_ptr telegram); void process_HpPoolStatus(std::shared_ptr telegram); + void process_MonitorWW(std::shared_ptr telegram); + void process_HydrTemp(std::shared_ptr telegram); + 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); @@ -56,6 +59,8 @@ class Mixer : public EMSdevice { bool set_wwCircPump(const char * value, const int8_t id); bool set_wwCircMode(const char * value, const int8_t id); + bool set_wwSelTemp(const char * value, const int8_t id); + enum class Type { NONE, @@ -90,6 +95,11 @@ class Mixer : public EMSdevice { Type type_ = Type::NONE; uint16_t hc_ = EMS_VALUE_USHORT_NOTSET; uint8_t poolShuntStatus__ = EMS_VALUE_UINT_NOTSET; // temp value + + uint8_t wwSelTemp_; + uint16_t wwCurTemp_1_; + uint16_t wwCurTemp_2_; + uint16_t HydrTemp_; }; } // namespace emsesp diff --git a/src/devices/solar.cpp b/src/devices/solar.cpp index 919b9a135..55c2a5bd6 100644 --- a/src/devices/solar.cpp +++ b/src/devices/solar.cpp @@ -63,30 +63,12 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c } if (flags == EMSdevice::EMS_DEVICE_FLAG_ISM) { - if (device_id == 0x41) { // ISM DHW module - register_telegram_type(0x34, F("UBAMonitorWW"), false, MAKE_PF_CB(process_MonitorWW)); - } else { - register_telegram_type(0x0103, F("ISM1StatusMessage"), true, MAKE_PF_CB(process_ISM1StatusMessage)); - register_telegram_type(0x0101, F("ISM1Set"), true, MAKE_PF_CB(process_ISM1Set)); - register_telegram_type(0x0104, F("ISM2StatusMessage"), false, MAKE_PF_CB(process_ISM2StatusMessage)); - } + register_telegram_type(0x0103, F("ISM1StatusMessage"), true, MAKE_PF_CB(process_ISM1StatusMessage)); + register_telegram_type(0x0101, F("ISM1Set"), true, MAKE_PF_CB(process_ISM1Set)); + register_telegram_type(0x0104, F("ISM2StatusMessage"), false, MAKE_PF_CB(process_ISM2StatusMessage)); } // device values... - - // special case ISM DHW module - if (device_id == 0x41) { // ISM DHW module - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwSelTemp_, - DeviceValueType::UINT, - nullptr, - FL_(wwSelTemp), - DeviceValueUOM::DEGREES, - MAKE_CF_CB(set_wwSelTemp)); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwTemp_1_, DeviceValueType::USHORT, FL_(div10), FL_(wwCurTemp), DeviceValueUOM::DEGREES); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwTemp_3_, DeviceValueType::USHORT, FL_(div10), FL_(wwCurTemp2), DeviceValueUOM::DEGREES); - return; - } // special case for a SM100 DHW device_id with 0x2A where it's not actual a solar module if (device_id == 0x2A) { register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwTemp_1_, DeviceValueType::USHORT, FL_(div10), FL_(wwTemp1), DeviceValueUOM::DEGREES); @@ -809,16 +791,6 @@ void Solar::process_ISM1Set(std::shared_ptr telegram) { has_update(telegram, cylMaxTemp_, 6); } -/* - * Junkers ISM1 Solar DHW Module - type 0x34 ww - */ -void Solar::process_MonitorWW(std::shared_ptr telegram) { - has_update(telegram, wwSelTemp_, 0); - has_update(telegram, wwTemp_1_, 1); - has_update(telegram, wwTemp_3_, 3); -} - - /* * Settings */ @@ -1163,11 +1135,7 @@ bool Solar::set_wwSelTemp(const char * value, const int8_t id) { if (!Helpers::value2temperature(value, temperature)) { return false; } - if (flags() == EMSdevice::EMS_DEVICE_FLAG_ISM) { - write_command(0x35, 3, (uint8_t)temperature, 0x34); - } else { // SM100 - write_command(0x7A6, 9, (uint8_t)temperature, 0x7A6); - } + write_command(0x7A6, 9, (uint8_t)temperature, 0x7A6); return true; } diff --git a/src/devices/solar.h b/src/devices/solar.h index 68c98e478..363462cb6 100644 --- a/src/devices/solar.h +++ b/src/devices/solar.h @@ -188,7 +188,6 @@ class Solar : public EMSdevice { void process_ISM1StatusMessage(std::shared_ptr telegram); void process_ISM1Set(std::shared_ptr telegram); void process_ISM2StatusMessage(std::shared_ptr telegram); - void process_MonitorWW(std::shared_ptr telegram); // settings bool set_CollectorMaxTemp(const char * value, const int8_t id); diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index b579aa6a2..625c9e497 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -311,6 +311,11 @@ void EMSdevice::show_telegram_handlers(uuid::console::Shell & shell) const { } } shell.println(); + shell.printf(F(" Ignored telegram type IDs: ")); + for (auto handlers : handlers_ignored_) { + shell.printf(F("0x%02X "), handlers); + } + shell.println(); } // list all the telegram type IDs for this device, outputting to a string (max size 200) @@ -333,10 +338,27 @@ char * EMSdevice::show_telegram_handlers(char * result, const size_t len, const strlcat(result, Helpers::hextoa(tf.telegram_type_id_, true).c_str(), len); } } - + if (handlers == Handlers::ALL || handlers == Handlers::IGNORED) { + i = 0; + for (auto handlers : handlers_ignored_) { + if (i++ > 0) { + strlcat(result, " ", len); + } + strlcat(result, Helpers::hextoa(handlers).c_str(), len); + } + } return result; } +void EMSdevice::add_handlers_ignored(const uint16_t handler) { + for (auto handlers : handlers_ignored_) { + if (handler == handlers) { + return; + } + } + handlers_ignored_.push_back(handler); +} + // list all the mqtt handlers for this device void EMSdevice::show_mqtt_handlers(uuid::console::Shell & shell) const { Mqtt::show_topic_handlers(shell, device_type_); @@ -443,7 +465,7 @@ void EMSdevice::register_device_value(uint8_t tag, if (tag >= DeviceValueTAG::TAG_HC1 && tag <= DeviceValueTAG::TAG_HC8) { flags |= CommandFlag::MQTT_SUB_FLAG_HC; - } else if (tag >= DeviceValueTAG::TAG_WWC1 && tag <= DeviceValueTAG::TAG_WWC4) { + } else if (tag >= DeviceValueTAG::TAG_WWC1 && tag <= DeviceValueTAG::TAG_WWC10) { flags |= CommandFlag::MQTT_SUB_FLAG_WWC; } else if (tag == DeviceValueTAG::TAG_DEVICE_DATA_WW) { flags |= CommandFlag::MQTT_SUB_FLAG_WW; @@ -517,7 +539,7 @@ void EMSdevice::publish_value(void * value_p) const { if (dv.value_p == value_p && !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE)) { char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; if (Mqtt::publish_single2cmd()) { - if (dv.tag >= DeviceValueTAG::TAG_HC1 && dv.tag <= DeviceValueTAG::TAG_WWC4) { + if (dv.tag >= DeviceValueTAG::TAG_HC1 && dv.tag <= DeviceValueTAG::TAG_WWC10) { snprintf(topic, sizeof(topic), "%s/%s/%s", @@ -887,7 +909,7 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8 // check if we have hc or wwc if (id >= 1 && id <= 8) { tag = DeviceValueTAG::TAG_HC1 + id - 1; - } else if (id >= 9 && id <= 12) { + } else if (id >= 9 && id <= 19) { tag = DeviceValueTAG::TAG_WWC1 + id - 9; } else if (id != -1) { return false; // error diff --git a/src/emsdevice.h b/src/emsdevice.h index 2f03afd2c..3da12a4e3 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -177,12 +177,13 @@ class EMSdevice { std::string to_string() const; std::string to_string_short() const; - enum Handlers : uint8_t { ALL, RECEIVED, FETCHED, PENDING }; + enum Handlers : uint8_t { ALL, RECEIVED, FETCHED, PENDING, IGNORED }; void show_telegram_handlers(uuid::console::Shell & shell) const; char * show_telegram_handlers(char * result, const size_t len, const uint8_t handlers); void show_mqtt_handlers(uuid::console::Shell & shell) const; void list_device_entries(JsonObject & output) const; + void add_handlers_ignored(const uint16_t handler); void mask_entity(const std::string & entity_id); void getMaskedEntities(std::vector & entity_ids); @@ -385,6 +386,8 @@ class EMSdevice { // device values std::vector devicevalues_; + + std::vector handlers_ignored_; }; } // namespace emsesp diff --git a/src/emsdevicevalue.cpp b/src/emsdevicevalue.cpp index 450f53aff..d1a2ffe41 100644 --- a/src/emsdevicevalue.cpp +++ b/src/emsdevicevalue.cpp @@ -70,6 +70,12 @@ const __FlashStringHelper * const DeviceValue::DeviceValueTAG_s[] PROGMEM = { F_(tag_wwc2), // "Wwc2" F_(tag_wwc3), // "wwc3" F_(tag_wwc4), // "wwc4" + F_(tag_wwc5), // "wwc5" + F_(tag_wwc6), // "wwc6" + F_(tag_wwc7), // "wwc7" + F_(tag_wwc8), // "wwc8" + F_(tag_wwc9), // "wwc9" + F_(tag_wwc10), // "wwc10" F_(tag_hs1), // "hs1" F_(tag_hs2), // "hs2" F_(tag_hs3), // "hs3" @@ -109,6 +115,12 @@ const __FlashStringHelper * const DeviceValue::DeviceValueTAG_mqtt[] PROGMEM = { F_(tag_wwc2), // "Wwc2" F_(tag_wwc3), // "wwc3" F_(tag_wwc4), // "wwc4" + F_(tag_wwc5), // "wwc5" + F_(tag_wwc6), // "wwc6" + F_(tag_wwc7), // "wwc7" + F_(tag_wwc8), // "wwc8" + F_(tag_wwc9), // "wwc9" + F_(tag_wwc10), // "wwc10" F_(tag_hs1), // "hs1" F_(tag_hs2), // "hs2" F_(tag_hs3), // "hs3" diff --git a/src/emsdevicevalue.h b/src/emsdevicevalue.h index 5d6ac776e..5f88b9de5 100644 --- a/src/emsdevicevalue.h +++ b/src/emsdevicevalue.h @@ -90,6 +90,12 @@ class DeviceValue { TAG_WWC2, TAG_WWC3, TAG_WWC4, + TAG_WWC5, + TAG_WWC6, + TAG_WWC7, + TAG_WWC8, + TAG_WWC9, + TAG_WWC10, TAG_HS1, TAG_HS2, TAG_HS3, diff --git a/src/emsesp.cpp b/src/emsesp.cpp index aef1cb0e3..f2e8e93b8 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -619,7 +619,7 @@ void EMSESP::publish_device_values(uint8_t device_type) { if (nested) { need_publish |= emsdevice->generate_values(json, DeviceValueTAG::TAG_NONE, true, EMSdevice::OUTPUT_TARGET::MQTT); // nested } else { - for (uint8_t hc_tag = DeviceValueTAG::TAG_HC1; hc_tag <= DeviceValueTAG::TAG_WWC4; hc_tag++) { + for (uint8_t hc_tag = DeviceValueTAG::TAG_HC1; hc_tag <= DeviceValueTAG::TAG_WWC10; hc_tag++) { json = doc.to(); if (emsdevice->generate_values(json, hc_tag, false, EMSdevice::OUTPUT_TARGET::MQTT)) { // not nested Mqtt::publish(Mqtt::tag_to_topic(device_type, hc_tag), json); @@ -951,6 +951,9 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { if (wait_validate_ == telegram->type_id) { wait_validate_ = 0; } + if (!found && emsdevice->is_device_id(telegram->src) && telegram->message_length > 0) { + emsdevice->add_handlers_ignored(telegram->type_id); + } break; } } @@ -1202,7 +1205,7 @@ bool EMSESP::command_info(uint8_t device_type, JsonObject & output, const int8_t uint8_t tag; if (id >= 1 && id <= 8) { tag = DeviceValueTAG::TAG_HC1 + id - 1; - } else if (id >= 9 && id <= 12) { + } else if (id >= 9 && id <= 19) { tag = DeviceValueTAG::TAG_WWC1 + id - 9; } else if (id == -1 || id == 0) { tag = DeviceValueTAG::TAG_NONE; diff --git a/src/system.cpp b/src/system.cpp index edb65a7f2..f2063415f 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -1219,6 +1219,10 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp if (result[0] != '\0') { obj["handlers pending"] = result; } + (void)emsdevice->show_telegram_handlers(result, sizeof(result), EMSdevice::Handlers::IGNORED); + if (result[0] != '\0') { + obj["handlers ignored"] = result; + } } } } From eec4d7863dccba06509a25f620cf20221d4e687e Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 10 Apr 2022 18:25:11 +0200 Subject: [PATCH 5/9] move Hybrid settings to thermostat --- src/devices/boiler.cpp | 12 ++-- src/devices/boiler.h | 5 +- src/devices/mixer.cpp | 1 + src/devices/thermostat.cpp | 142 +++++++++++++++++++++++++++++++++++++ src/devices/thermostat.h | 19 +++++ 5 files changed, 174 insertions(+), 5 deletions(-) diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index 3fd61ad88..8d2a8d226 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -89,10 +89,11 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const register_telegram_type(0x48A, F("HpPool"), true, MAKE_PF_CB(process_HpPool)); } + /* if (model() == EMSdevice::EMS_DEVICE_FLAG_HYBRID) { register_telegram_type(0xBB, F("HybridHp"), true, MAKE_PF_CB(process_HybridHp)); } - + */ // reset is a command uses a dummy variable which is always zero, shown as blank, but provides command enum options register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &reset_, DeviceValueType::CMD, FL_(enum_reset), FL_(reset), DeviceValueUOM::NONE, MAKE_CF_CB(set_reset)); has_update(reset_, 0); @@ -202,6 +203,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const DeviceValueUOM::NONE, MAKE_CF_CB(set_maintenancedate)); + /* // Hybrid Heatpump if (model() == EMSdevice::EMS_DEVICE_FLAG_HYBRID) { register_device_value(DeviceValueTAG::TAG_BOILER_DATA, @@ -254,6 +256,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_tempDiffBoiler)); } + */ // heatpump info if (model() == EMS_DEVICE_FLAG_HEATPUMP) { register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &upTimeControl_, DeviceValueType::TIME, FL_(div60), FL_(upTimeControl), DeviceValueUOM::MINUTES); @@ -1049,7 +1052,7 @@ void Boiler::process_UBAMaintenanceData(std::shared_ptr telegram has_update(maintenanceDate_, date, sizeof(maintenanceDate_)); } } - +/* // 0xBB Heatpump optimization // Boiler(0x08) -> Me(0x0B), ?(0xBB), data: 00 00 00 00 00 00 00 00 00 00 00 FF 02 0F 1E 0B 1A 00 14 03 void Boiler::process_HybridHp(std::shared_ptr telegram) { @@ -1061,11 +1064,11 @@ void Boiler::process_HybridHp(std::shared_ptr telegram) { has_update(telegram, delayBoiler_, 18); // minutes has_update(telegram, tempDiffBoiler_, 19); // relative degrees } - +*/ /* * Settings */ - +/* bool Boiler::set_hybridStrategy(const char * value, const int8_t id) { uint8_t v; if (!Helpers::value2enum(value, v, FL_(enum_hybridStrategy))) { @@ -1128,6 +1131,7 @@ bool Boiler::set_tempDiffBoiler(const char * value, const int8_t id) { write_command(0xBB, 19, v, 0xBB); return true; } +*/ // Set the dhw temperature 0x33/0x35 or 0xEA bool Boiler::set_ww_temp(const char * value, const int8_t id) { diff --git a/src/devices/boiler.h b/src/devices/boiler.h index 1641a49a7..7247f273b 100644 --- a/src/devices/boiler.h +++ b/src/devices/boiler.h @@ -193,6 +193,7 @@ class Boiler : public EMSdevice { // Pool unit int8_t poolSetTemp_; + /* // HybridHP uint8_t hybridStrategy_; // cost = 2, temperature = 3, mix = 4 uint8_t switchOverTemp_; // degrees @@ -201,6 +202,7 @@ class Boiler : public EMSdevice { uint8_t electricFactor_; // is * 10 uint8_t delayBoiler_; // minutes uint8_t tempDiffBoiler_; // relative temperature degrees + */ void process_UBAParameterWW(std::shared_ptr telegram); void process_UBAMonitorFast(std::shared_ptr telegram); @@ -266,7 +268,7 @@ class Boiler : public EMSdevice { bool set_ww_hyst_on(const char * value, const int8_t id); bool set_ww_hyst_off(const char * value, const int8_t id); bool set_pool_temp(const char * value, const int8_t id); - + /* bool set_hybridStrategy(const char * value, const int8_t id); bool set_switchOverTemp(const char * value, const int8_t id); bool set_energyCostRatio(const char * value, const int8_t id); @@ -274,6 +276,7 @@ class Boiler : public EMSdevice { bool set_electricFactor(const char * value, const int8_t id); bool set_delayBoiler(const char * value, const int8_t id); bool set_tempDiffBoiler(const char * value, const int8_t id); + */ }; } // namespace emsesp diff --git a/src/devices/mixer.cpp b/src/devices/mixer.cpp index c1cacf0b1..8a8f0e614 100644 --- a/src/devices/mixer.cpp +++ b/src/devices/mixer.cpp @@ -102,6 +102,7 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c if (device_id >= 0x40) { // special DHW pos 10 register_telegram_type(0x34, F("UBAMonitorWW"), false, MAKE_PF_CB(process_MonitorWW)); register_telegram_type(0x1E, F("HydrTemp"), false, MAKE_PF_CB(process_HydrTemp)); + // register_telegram_type(0x10D, F("wwNTCStatus"), false, MAKE_PF_CB(process_wwNTCStatus)); type_ = Type::WWC; hc_ = device_id - 0x40 + 1; uint8_t tag = DeviceValueTAG::TAG_WWC9 + hc_ - 1; diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index 23bce8656..99ea0129c 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -169,6 +169,8 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i } } } + register_telegram_type(0xBB, F("HybridSettings"), true, MAKE_PF_CB(process_JunkersHybridSettings)); + register_telegram_type(0x23, F("JunkersSetMixer"), true, MAKE_PF_CB(process_JunkersSetMixer)); register_telegram_type(0x123, F("JunkersRemote"), false, MAKE_PF_CB(process_JunkersRemoteMonitor)); } @@ -302,6 +304,11 @@ std::shared_ptr Thermostat::heating_circuit(std::sha toggle_ = true; } + // not found, search device-id types for remote thermostats + if (telegram->dest >= 0x20 && telegram->dest <= 0x27) { + hc_num = telegram->dest - 0x20; + } + // still didn't recognize it, ignore it if (hc_num == 0) { return nullptr; @@ -842,6 +849,27 @@ void Thermostat::process_JunkersMonitor(std::shared_ptr telegram add_ha_climate(hc); } +// 0xBB Heatpump optimization +// ?(0xBB), data: 00 00 00 00 00 00 00 00 00 00 00 FF 02 0F 1E 0B 1A 00 14 03 +void Thermostat::process_JunkersHybridSettings(std::shared_ptr telegram) { + has_enumupdate(telegram, hybridStrategy_, 12, 1); // cost = 2, temperature = 3, mix = 4 + has_update(telegram, switchOverTemp_, 13); // full degrees + has_update(telegram, energyCostRatio_, 14); // is *10 + has_update(telegram, fossileFactor_, 15); // is * 10 + has_update(telegram, electricFactor_, 16); // is * 10 + has_update(telegram, delayBoiler_, 18); // minutes + has_update(telegram, tempDiffBoiler_, 19); // relative degrees +} + +void Thermostat::process_JunkersSetMixer(std::shared_ptr telegram) { + std::shared_ptr hc = heating_circuit(telegram); + if (hc == nullptr) { + return; + } + has_update(telegram, hc->targetflowtemp, 0); +} + + // type 0x02A5 - data from Worchester CRF200 void Thermostat::process_CRFMonitor(std::shared_ptr telegram) { std::shared_ptr hc = heating_circuit(telegram); @@ -1314,6 +1342,70 @@ void Thermostat::process_RCErrorMessage(std::shared_ptr telegram * */ +// 0xBB Hybrid pump +bool Thermostat::set_hybridStrategy(const char * value, const int8_t id) { + uint8_t v; + if (!Helpers::value2enum(value, v, FL_(enum_hybridStrategy))) { + return false; + } + write_command(0xBB, 12, v + 1, 0xBB); + return true; +} + +bool Thermostat::set_switchOverTemp(const char * value, const int8_t id) { + int v; + if (!Helpers::value2temperature(value, v)) { + return false; + } + write_command(0xBB, 13, v, 0xBB); + return true; +} + +bool Thermostat::set_energyCostRatio(const char * value, const int8_t id) { + float v; + if (!Helpers::value2float(value, v)) { + return false; + } + write_command(0xBB, 14, (uint8_t)(v * 10), 0xBB); + return true; +} + +bool Thermostat::set_fossileFactor(const char * value, const int8_t id) { + float v; + if (!Helpers::value2float(value, v)) { + return false; + } + write_command(0xBB, 15, (uint8_t)(v * 10), 0xBB); + return true; +} + +bool Thermostat::set_electricFactor(const char * value, const int8_t id) { + float v; + if (!Helpers::value2float(value, v)) { + return false; + } + write_command(0xBB, 16, (uint8_t)(v * 10), 0xBB); + return true; +} + +bool Thermostat::set_delayBoiler(const char * value, const int8_t id) { + int v; + if (!Helpers::value2number(value, v)) { + return false; + } + write_command(0xBB, 18, v, 0xBB); + return true; +} + +bool Thermostat::set_tempDiffBoiler(const char * value, const int8_t id) { + int v; + if (!Helpers::value2temperature(value, v, true)) { + return false; + } + write_command(0xBB, 19, v, 0xBB); + return true; +} + // 0xA5 - Set minimum external temperature bool Thermostat::set_minexttemp(const char * value, const int8_t id) { int mt = 0; @@ -3423,6 +3515,55 @@ void Thermostat::register_device_values() { FL_(dateTime), DeviceValueUOM::NONE, MAKE_CF_CB(set_datetime)); + register_device_value(DeviceValueTAG::TAG_THERMOSTAT_DATA, + &hybridStrategy_, + DeviceValueType::ENUM, + FL_(enum_hybridStrategy), + FL_(hybridStrategy), + DeviceValueUOM::NONE, + MAKE_CF_CB(set_hybridStrategy)); + register_device_value(DeviceValueTAG::TAG_THERMOSTAT_DATA, + &switchOverTemp_, + DeviceValueType::UINT, + nullptr, + FL_(switchOverTemp), + DeviceValueUOM::DEGREES, + MAKE_CF_CB(set_switchOverTemp)); + register_device_value(DeviceValueTAG::TAG_THERMOSTAT_DATA, + &energyCostRatio_, + DeviceValueType::UINT, + FL_(div10), + FL_(energyCostRatio), + DeviceValueUOM::NONE, + MAKE_CF_CB(set_energyCostRatio)); + register_device_value(DeviceValueTAG::TAG_THERMOSTAT_DATA, + &fossileFactor_, + DeviceValueType::UINT, + FL_(div10), + FL_(fossileFactor), + DeviceValueUOM::NONE, + MAKE_CF_CB(set_fossileFactor)); + register_device_value(DeviceValueTAG::TAG_THERMOSTAT_DATA, + &electricFactor_, + DeviceValueType::UINT, + FL_(div10), + FL_(electricFactor), + DeviceValueUOM::NONE, + MAKE_CF_CB(set_electricFactor)); + register_device_value(DeviceValueTAG::TAG_THERMOSTAT_DATA, + &delayBoiler_, + DeviceValueType::UINT, + nullptr, + FL_(delayBoiler), + DeviceValueUOM::MINUTES, + MAKE_CF_CB(set_delayBoiler)); + register_device_value(DeviceValueTAG::TAG_THERMOSTAT_DATA, + &tempDiffBoiler_, + DeviceValueType::UINT, + nullptr, + FL_(tempDiffBoiler), + DeviceValueUOM::DEGREES_R, + MAKE_CF_CB(set_tempDiffBoiler)); break; case EMS_DEVICE_FLAG_EASY: // Easy TC100 have no date/time, see issue #100, not sure about CT200, so leave it. @@ -3606,6 +3747,7 @@ void Thermostat::register_device_values_hc(std::shared_ptrcontrol, DeviceValueType::ENUM, FL_(enum_j_control), FL_(control), DeviceValueUOM::NONE, MAKE_CF_CB(set_control)); register_device_value(tag, &hc->program, DeviceValueType::ENUM, FL_(enum_progMode4), FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program)); register_device_value(tag, &hc->remotetemp, DeviceValueType::SHORT, FL_(div10), FL_(remotetemp), DeviceValueUOM::DEGREES); + register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, nullptr, FL_(targetflowtemp), DeviceValueUOM::DEGREES); break; default: break; diff --git a/src/devices/thermostat.h b/src/devices/thermostat.h index 4c0a42b6c..70ef91abd 100644 --- a/src/devices/thermostat.h +++ b/src/devices/thermostat.h @@ -216,6 +216,15 @@ class Thermostat : public EMSdevice { uint8_t wwDailyHeating_; uint8_t wwDailyHeatTime_; + // HybridHP + uint8_t hybridStrategy_; // cost = 2, temperature = 3, mix = 4 + uint8_t switchOverTemp_; // degrees + uint8_t energyCostRatio_; // is *10 + uint8_t fossileFactor_; // is * 10 + uint8_t electricFactor_; // is * 10 + uint8_t delayBoiler_; // minutes + uint8_t tempDiffBoiler_; // relative temperature degrees + std::vector> heating_circuits_; // each thermostat can have multiple heating circuits uint8_t zero_value_ = 0; // for fixing current room temperature to 0 for HA @@ -351,6 +360,8 @@ class Thermostat : public EMSdevice { void process_JunkersSet2(std::shared_ptr telegram); void process_EasyMonitor(std::shared_ptr telegram); void process_JunkersRemoteMonitor(std::shared_ptr telegram); + void process_JunkersHybridSettings(std::shared_ptr telegram); + void process_JunkersSetMixer(std::shared_ptr telegram); // internal helper functions bool set_mode_n(const uint8_t mode, const uint8_t hc_num); @@ -441,6 +452,14 @@ class Thermostat : public EMSdevice { bool set_preheating(const char * value, const int8_t id); bool set_mixingvalves(const char * value, const int8_t id); bool set_offtemp(const char * value, const int8_t id); + + bool set_hybridStrategy(const char * value, const int8_t id); + bool set_switchOverTemp(const char * value, const int8_t id); + bool set_energyCostRatio(const char * value, const int8_t id); + bool set_fossileFactor(const char * value, const int8_t id); + bool set_electricFactor(const char * value, const int8_t id); + bool set_delayBoiler(const char * value, const int8_t id); + bool set_tempDiffBoiler(const char * value, const int8_t id); }; } // namespace emsesp From 4009a1a25c18f1d211465e320fb1c09c7ac3ce80 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 11 Apr 2022 10:20:40 +0200 Subject: [PATCH 6/9] b12, cleanup, formatting, small fixes --- CHANGELOG_LATEST.md | 3 ++- src/devices/boiler.cpp | 26 +++++++++++++++++++------- src/devices/boiler.h | 14 +++++++------- src/devices/mixer.cpp | 9 +++++++-- src/devices/thermostat.cpp | 28 ++++++++++++++++++++-------- src/devices/thermostat.h | 30 +++++++++++++++--------------- src/emsdevice.cpp | 2 +- src/mqtt.cpp | 4 ++++ src/version.h | 2 +- 9 files changed, 76 insertions(+), 42 deletions(-) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 88faa8b08..bd71d324d 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -33,7 +33,8 @@ - Extend customization to select if an entity is to be shown in the WebUI or forced as read-only [#317](https://github.com/emsesp/EMS-ESP32/issues/317) - Added Moduline 400 installation parameters [PR #449 by @kwertie01](https://github.com/emsesp/EMS-ESP32/pull/449) - Read time from IVT-controller [#439](https://github.com/emsesp/EMS-ESP32/issues/439) -- Hybrid Heatpump product-id 168 [#459](https://github.com/emsesp/EMS-ESP32/issues/459) +- Hybrid Heatpump product-id 168 [#459](https://github.com/emsesp/EMS-ESP32/issues/459), thermostat settings +- Junkers ISM2 and IPM in warm water mode [#437](https://github.com/emsesp/EMS-ESP32/issues/437) ### Fixed diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index 8d2a8d226..ccfa5a507 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -215,46 +215,58 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const MAKE_CF_CB(set_hybridStrategy)); register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &switchOverTemp_, - DeviceValueType::UINT, + DeviceValueType::INT, nullptr, FL_(switchOverTemp), DeviceValueUOM::DEGREES, - MAKE_CF_CB(set_switchOverTemp)); + MAKE_CF_CB(set_switchOverTemp), + -20, + 20); register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &energyCostRatio_, DeviceValueType::UINT, FL_(div10), FL_(energyCostRatio), DeviceValueUOM::NONE, - MAKE_CF_CB(set_energyCostRatio)); + MAKE_CF_CB(set_energyCostRatio), + 0, + 19.9); register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &fossileFactor_, DeviceValueType::UINT, FL_(div10), FL_(fossileFactor), DeviceValueUOM::NONE, - MAKE_CF_CB(set_fossileFactor)); + MAKE_CF_CB(set_fossileFactor), + 0, + 5); register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &electricFactor_, DeviceValueType::UINT, FL_(div10), FL_(electricFactor), DeviceValueUOM::NONE, - MAKE_CF_CB(set_electricFactor)); + MAKE_CF_CB(set_electricFactor), + 0, + 5); register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &delayBoiler_, DeviceValueType::UINT, nullptr, FL_(delayBoiler), DeviceValueUOM::MINUTES, - MAKE_CF_CB(set_delayBoiler)); + MAKE_CF_CB(set_delayBoiler), + 5, + 120); register_device_value(DeviceValueTAG::TAG_BOILER_DATA, &tempDiffBoiler_, DeviceValueType::UINT, nullptr, FL_(tempDiffBoiler), DeviceValueUOM::DEGREES_R, - MAKE_CF_CB(set_tempDiffBoiler)); + MAKE_CF_CB(set_tempDiffBoiler), + 1, + 99); } */ // heatpump info diff --git a/src/devices/boiler.h b/src/devices/boiler.h index 7247f273b..d1365f1f7 100644 --- a/src/devices/boiler.h +++ b/src/devices/boiler.h @@ -128,7 +128,7 @@ class Boiler : public EMSdevice { uint32_t burn2WorkMin_; // burner stage 2 operating time uint32_t heatWorkMin_; // Total heat operating time uint32_t UBAuptime_; // Total UBA working hours - char lastCode_[75]; // last error code + char lastCode_[50]; // last error code char serviceCode_[4]; // 3 character status/service code uint16_t serviceCodeNumber_; // error/service code @@ -195,13 +195,13 @@ class Boiler : public EMSdevice { /* // HybridHP - uint8_t hybridStrategy_; // cost = 2, temperature = 3, mix = 4 - uint8_t switchOverTemp_; // degrees - uint8_t energyCostRatio_; // is *10 - uint8_t fossileFactor_; // is * 10 - uint8_t electricFactor_; // is * 10 + uint8_t hybridStrategy_; // cost = 2, temperature = 3, mix = 4 + int8_t switchOverTemp_; // degrees + uint8_t energyCostRatio_; // is *10 + uint8_t fossileFactor_; // is * 10 + uint8_t electricFactor_; // is * 10 uint8_t delayBoiler_; // minutes - uint8_t tempDiffBoiler_; // relative temperature degrees + uint8_t tempDiffBoiler_; // relative temperature degrees */ void process_UBAParameterWW(std::shared_ptr telegram); diff --git a/src/devices/mixer.cpp b/src/devices/mixer.cpp index 8a8f0e614..3db9cdfb7 100644 --- a/src/devices/mixer.cpp +++ b/src/devices/mixer.cpp @@ -110,6 +110,7 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c register_device_value(tag, &wwCurTemp_1_, DeviceValueType::USHORT, FL_(div10), FL_(wwCurTemp), DeviceValueUOM::DEGREES); register_device_value(tag, &wwCurTemp_2_, DeviceValueType::USHORT, FL_(div10), FL_(wwCurTemp2), DeviceValueUOM::DEGREES); register_device_value(tag, &HydrTemp_, DeviceValueType::USHORT, FL_(div10), FL_(hydrTemp), DeviceValueUOM::DEGREES); + register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::NONE, MAKE_CF_CB(set_pump)); } else { register_telegram_type(0x010C, F("IPMStatusMessage"), false, MAKE_PF_CB(process_IPMStatusMessage)); register_telegram_type(0x011E, F("IPMTempMessage"), false, MAKE_PF_CB(process_IPMTempMessage)); @@ -216,13 +217,17 @@ void Mixer::process_MMPLUSConfigMessage_WWC(std::shared_ptr tele has_update(telegram, wwMaxTemp_, 10); } -// 0x34 +// 0x34 only8 bytes long +// Mixer(0x41) -> All(0x00), UBAMonitorWW(0x34), data: 37 02 1E 02 1E 00 00 00 00 void Mixer::process_MonitorWW(std::shared_ptr telegram) { has_update(telegram, wwSelTemp_, 0); has_update(telegram, wwCurTemp_1_, 1); has_update(telegram, wwCurTemp_2_, 3); + has_bitupdate(telegram, pumpStatus_, 5, 0); // not sure thisisthe right value } -// 0x1E + +// 0x1E, only16 bit temperature +// Mixer(0x41) -> Boiler(0x08), HydrTemp(0x1E), data: 01 D8 void Mixer::process_HydrTemp(std::shared_ptr telegram) { has_update(telegram, HydrTemp_, 0); } diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index 99ea0129c..61d7a776c 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -306,7 +306,7 @@ std::shared_ptr Thermostat::heating_circuit(std::sha // not found, search device-id types for remote thermostats if (telegram->dest >= 0x20 && telegram->dest <= 0x27) { - hc_num = telegram->dest - 0x20; + hc_num = telegram->dest - 0x20; } // still didn't recognize it, ignore it @@ -3524,46 +3524,58 @@ void Thermostat::register_device_values() { MAKE_CF_CB(set_hybridStrategy)); register_device_value(DeviceValueTAG::TAG_THERMOSTAT_DATA, &switchOverTemp_, - DeviceValueType::UINT, + DeviceValueType::INT, nullptr, FL_(switchOverTemp), DeviceValueUOM::DEGREES, - MAKE_CF_CB(set_switchOverTemp)); + MAKE_CF_CB(set_switchOverTemp), + -20, + 20); register_device_value(DeviceValueTAG::TAG_THERMOSTAT_DATA, &energyCostRatio_, DeviceValueType::UINT, FL_(div10), FL_(energyCostRatio), DeviceValueUOM::NONE, - MAKE_CF_CB(set_energyCostRatio)); + MAKE_CF_CB(set_energyCostRatio), + 0, + 19.9); register_device_value(DeviceValueTAG::TAG_THERMOSTAT_DATA, &fossileFactor_, DeviceValueType::UINT, FL_(div10), FL_(fossileFactor), DeviceValueUOM::NONE, - MAKE_CF_CB(set_fossileFactor)); + MAKE_CF_CB(set_fossileFactor), + 0, + 5); register_device_value(DeviceValueTAG::TAG_THERMOSTAT_DATA, &electricFactor_, DeviceValueType::UINT, FL_(div10), FL_(electricFactor), DeviceValueUOM::NONE, - MAKE_CF_CB(set_electricFactor)); + MAKE_CF_CB(set_electricFactor), + 0, + 5); register_device_value(DeviceValueTAG::TAG_THERMOSTAT_DATA, &delayBoiler_, DeviceValueType::UINT, nullptr, FL_(delayBoiler), DeviceValueUOM::MINUTES, - MAKE_CF_CB(set_delayBoiler)); + MAKE_CF_CB(set_delayBoiler), + 5, + 120); register_device_value(DeviceValueTAG::TAG_THERMOSTAT_DATA, &tempDiffBoiler_, DeviceValueType::UINT, nullptr, FL_(tempDiffBoiler), DeviceValueUOM::DEGREES_R, - MAKE_CF_CB(set_tempDiffBoiler)); + MAKE_CF_CB(set_tempDiffBoiler), + 1, + 99); break; case EMS_DEVICE_FLAG_EASY: // Easy TC100 have no date/time, see issue #100, not sure about CT200, so leave it. diff --git a/src/devices/thermostat.h b/src/devices/thermostat.h index 70ef91abd..c2faafb85 100644 --- a/src/devices/thermostat.h +++ b/src/devices/thermostat.h @@ -182,11 +182,11 @@ class Thermostat : public EMSdevice { uint8_t ibaDamping_; // damping 0-off, 0xff-on uint8_t backlight_; uint8_t heatingpid_; - int8_t brightness_; // Screen brightness 0F=dark F1=light - uint8_t preheating_; // Preheating in the clock program: (0x00 = off, 0xFF = on) - uint8_t autodst_; // Automatic change Daylight Saving time: (0x00 = off, 0xFF = on) - uint8_t offtemp_; // Set Temperature when mode is Off / 10 (e.g.: 0x0F = 7.5 degrees Celsius) - uint8_t mixingvalves_; // Number of Mixing Valves: (0x00=0, 0x01=1, 0x02=2) + int8_t brightness_; // Screen brightness 0F=dark F1=light + uint8_t preheating_; // Preheating in the clock program: (0x00 = off, 0xFF = on) + uint8_t autodst_; // Automatic change Daylight Saving time: (0x00 = off, 0xFF = on) + uint8_t offtemp_; // Set Temperature when mode is Off / 10 (e.g.: 0x0F = 7.5 degrees Celsius) + uint8_t mixingvalves_; // Number of Mixing Valves: (0x00=0, 0x01=1, 0x02=2) int8_t dampedoutdoortemp_; uint16_t tempsensor1_; @@ -217,13 +217,13 @@ class Thermostat : public EMSdevice { uint8_t wwDailyHeatTime_; // HybridHP - uint8_t hybridStrategy_; // cost = 2, temperature = 3, mix = 4 - uint8_t switchOverTemp_; // degrees - uint8_t energyCostRatio_; // is *10 - uint8_t fossileFactor_; // is * 10 - uint8_t electricFactor_; // is * 10 + uint8_t hybridStrategy_; // co2 = 1, cost = 2, temperature = 3, mix = 4 + int8_t switchOverTemp_; // degrees + uint8_t energyCostRatio_; // is *10 + uint8_t fossileFactor_; // is * 10 + uint8_t electricFactor_; // is * 10 uint8_t delayBoiler_; // minutes - uint8_t tempDiffBoiler_; // relative temperature degrees + uint8_t tempDiffBoiler_; // relative temperature degrees std::vector> heating_circuits_; // each thermostat can have multiple heating circuits @@ -309,10 +309,10 @@ class Thermostat : public EMSdevice { static constexpr uint8_t AUTO_HEATING_CIRCUIT = 0; // Installation settings - static constexpr uint8_t EMS_TYPE_IBASettings = 0xA5; // installation settings + static constexpr uint8_t EMS_TYPE_IBASettings = 0xA5; // installation settings static constexpr uint8_t EMS_TYPE_RC30Settings = 0xA7; // RC30 settings - static constexpr uint8_t EMS_TYPE_wwSettings = 0x37; // ww settings - static constexpr uint8_t EMS_TYPE_time = 0x06; // time + static constexpr uint8_t EMS_TYPE_wwSettings = 0x37; // ww settings + static constexpr uint8_t EMS_TYPE_time = 0x06; // time std::shared_ptr heating_circuit(std::shared_ptr telegram); std::shared_ptr heating_circuit(const uint8_t hc_num); @@ -451,7 +451,7 @@ class Thermostat : public EMSdevice { bool set_autodst(const char * value, const int8_t id); bool set_preheating(const char * value, const int8_t id); bool set_mixingvalves(const char * value, const int8_t id); - bool set_offtemp(const char * value, const int8_t id); + bool set_offtemp(const char * value, const int8_t id); bool set_hybridStrategy(const char * value, const int8_t id); bool set_switchOverTemp(const char * value, const int8_t id); diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 625c9e497..4711ddcbf 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -561,7 +561,7 @@ void EMSdevice::publish_value(void * value_p) const { } int8_t divider = (dv.options_size == 1) ? Helpers::atoint(read_flash_string(dv.options[0]).c_str()) : 0; - char payload[30] = {'\0'}; + char payload[50] = {'\0'}; uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : 0; switch (dv.type) { diff --git a/src/mqtt.cpp b/src/mqtt.cpp index abc0af963..8096285f9 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -386,6 +386,10 @@ void Mqtt::on_publish(uint16_t packetId) const { // called when MQTT settings have changed via the Web forms void Mqtt::reset_mqtt() { + if (!mqtt_enabled_) { + mqtt_messages_.clear(); + } + if (!mqttClient_) { return; } diff --git a/src/version.h b/src/version.h index b64112942..16885163f 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.4.0b11" +#define EMSESP_APP_VERSION "3.4.0b12" From ec1b0b364189ac3d545f382d77a4487e2d7b88e9 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 11 Apr 2022 15:03:07 +0200 Subject: [PATCH 7/9] add IPM ww-parameters to mixer --- src/devices/mixer.cpp | 105 ++++++++++++++++++++++++++++++++++-------- src/devices/mixer.h | 12 +++-- src/locale_DE.h | 18 ++++++++ 3 files changed, 114 insertions(+), 21 deletions(-) diff --git a/src/devices/mixer.cpp b/src/devices/mixer.cpp index 3db9cdfb7..794fac20a 100644 --- a/src/devices/mixer.cpp +++ b/src/devices/mixer.cpp @@ -100,8 +100,9 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c // HT3 if (flags == EMSdevice::EMS_DEVICE_FLAG_IPM) { if (device_id >= 0x40) { // special DHW pos 10 - register_telegram_type(0x34, F("UBAMonitorWW"), false, MAKE_PF_CB(process_MonitorWW)); - register_telegram_type(0x1E, F("HydrTemp"), false, MAKE_PF_CB(process_HydrTemp)); + register_telegram_type(0x34, F("UBAMonitorWW"), false, MAKE_PF_CB(process_IPMMonitorWW)); + register_telegram_type(0x1E, F("HydrTemp"), false, MAKE_PF_CB(process_IPMHydrTemp)); + register_telegram_type(0x33, F("UBAParameterWW"), true, MAKE_PF_CB(process_IPMParameterWW)); // register_telegram_type(0x10D, F("wwNTCStatus"), false, MAKE_PF_CB(process_wwNTCStatus)); type_ = Type::WWC; hc_ = device_id - 0x40 + 1; @@ -110,7 +111,26 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c register_device_value(tag, &wwCurTemp_1_, DeviceValueType::USHORT, FL_(div10), FL_(wwCurTemp), DeviceValueUOM::DEGREES); register_device_value(tag, &wwCurTemp_2_, DeviceValueType::USHORT, FL_(div10), FL_(wwCurTemp2), DeviceValueUOM::DEGREES); register_device_value(tag, &HydrTemp_, DeviceValueType::USHORT, FL_(div10), FL_(hydrTemp), DeviceValueUOM::DEGREES); - register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::NONE, MAKE_CF_CB(set_pump)); + register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::NONE); + register_device_value( + tag, &wwFlowTempOffset_, DeviceValueType::UINT, nullptr, FL_(wwFlowTempOffset), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwFlowTempOffset)); + register_device_value(tag, &wwHystOn_, DeviceValueType::INT, nullptr, FL_(wwHystOn), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwHystOn)); + register_device_value(tag, &wwHystOff_, DeviceValueType::INT, nullptr, FL_(wwHystOff), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwHystOff)); + register_device_value(tag, + &wwDisinfectionTemp_, + DeviceValueType::UINT, + nullptr, + FL_(wwDisinfectionTemp), + DeviceValueUOM::DEGREES, + MAKE_CF_CB(set_wwDisinfectionTemp)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, + &wwCircPump_, + DeviceValueType::BOOL, + nullptr, + FL_(wwCircPump), + DeviceValueUOM::NONE, + MAKE_CF_CB(set_wwCircPump)); + register_device_value(tag, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCircMode)); } else { register_telegram_type(0x010C, F("IPMStatusMessage"), false, MAKE_PF_CB(process_IPMStatusMessage)); register_telegram_type(0x011E, F("IPMTempMessage"), false, MAKE_PF_CB(process_IPMTempMessage)); @@ -217,23 +237,35 @@ void Mixer::process_MMPLUSConfigMessage_WWC(std::shared_ptr tele has_update(telegram, wwMaxTemp_, 10); } -// 0x34 only8 bytes long +// 0x34 only 8 bytes long // Mixer(0x41) -> All(0x00), UBAMonitorWW(0x34), data: 37 02 1E 02 1E 00 00 00 00 -void Mixer::process_MonitorWW(std::shared_ptr telegram) { +void Mixer::process_IPMMonitorWW(std::shared_ptr telegram) { has_update(telegram, wwSelTemp_, 0); has_update(telegram, wwCurTemp_1_, 1); has_update(telegram, wwCurTemp_2_, 3); - has_bitupdate(telegram, pumpStatus_, 5, 0); // not sure thisisthe right value + has_bitupdate(telegram, pumpStatus_, 5, 3); } +// Mixer(0x41) -> Me(0x0B), UBAParameterWW(0x33), data: 08 FF 46 FB FF 28 FF 07 46 00 FF 00 +void Mixer::process_IPMParameterWW(std::shared_ptr telegram) { + // has_update(telegram, wwActivated_, 1); // 0xFF means on + // has_update(telegram, wwSelTemp_, 2); + has_update(telegram, wwHystOn_, 3); // Hyst on (default -5) + has_update(telegram, wwHystOff_, 4); // Hyst off (default -1) + has_update(telegram, wwFlowTempOffset_, 5); // default 40 + has_update(telegram, wwCircPump_, 6); // 0xFF means on + has_update(telegram, wwCircMode_, 7); // 1=1x3min 6=6x3min 7=continuous + has_update(telegram, wwDisinfectionTemp_, 8); + // has_bitupdate(telegram, wwChargeType_, 10, 0); // 0 = charge pump, 0xff = 3-way valve +} + + // 0x1E, only16 bit temperature // Mixer(0x41) -> Boiler(0x08), HydrTemp(0x1E), data: 01 D8 -void Mixer::process_HydrTemp(std::shared_ptr telegram) { +void Mixer::process_IPMHydrTemp(std::shared_ptr telegram) { has_update(telegram, HydrTemp_, 0); } - - #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" @@ -281,7 +313,6 @@ bool Mixer::set_wwSelTemp(const char * value, const int8_t id) { return true; } - bool Mixer::set_flowSetTemp(const char * value, const int8_t id) { int v; if (!Helpers::value2number(value, v)) { @@ -390,34 +421,72 @@ bool Mixer::set_wwRequiredTemp(const char * value, const int8_t id) { } bool Mixer::set_wwDisinfectionTemp(const char * value, const int8_t id) { - uint8_t wwc = device_id() - 0x28; - float v = 0; + float v = 0; if (!Helpers::value2temperature(value, v)) { return false; } - write_command(0x313 + wwc, 9, (uint8_t)v, 0x313 + wwc); + if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) { + write_command(0x33, 8, (uint8_t)v, 0x33); + } else { + uint8_t wwc = device_id() - 0x28; + write_command(0x313 + wwc, 9, (uint8_t)v, 0x313 + wwc); + } return true; } bool Mixer::set_wwCircPump(const char * value, const int8_t id) { - uint8_t wwc = device_id() - 0x28; - bool v = false; + bool v = false; if (!Helpers::value2bool(value, v)) { return false; } - write_command(0x33B + wwc, 0, v ? 0x01 : 0x00, 0x33B + wwc); + if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) { + write_command(0x33, 6, v ? 0xFF : 0x00, 0x33); + } else { + uint8_t wwc = device_id() - 0x28; + write_command(0x33B + wwc, 0, v ? 0x01 : 0x00, 0x33B + wwc); + } return true; } bool Mixer::set_wwCircMode(const char * value, const int8_t id) { - uint8_t wwc = device_id() - 0x28; uint8_t n; if (!Helpers::value2enum(value, n, FL_(enum_wwCircMode))) { return false; } - write_command(0x313 + wwc, 0, n, 0x313 + wwc); + if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) { + write_command(0x33, 7, n, 0x33); + } else { + uint8_t wwc = device_id() - 0x28; + write_command(0x313 + wwc, 0, n, 0x313 + wwc); + } return true; } +bool Mixer::set_wwFlowTempOffset(const char * value, const int8_t id) { + int n; + if (!Helpers::value2number(value, n)) { + return false; + } + write_command(0x33, 5, n, 0x33); + return true; +} + +bool Mixer::set_wwHystOn(const char * value, const int8_t id) { + int n; + if (!Helpers::value2number(value, n)) { + return false; + } + write_command(0x33, 3, n, 0x33); + return true; +} + +bool Mixer::set_wwHystOff(const char * value, const int8_t id) { + int n; + if (!Helpers::value2number(value, n)) { + return false; + } + write_command(0x33, 4, n, 0x33); + return true; +} } // namespace emsesp diff --git a/src/devices/mixer.h b/src/devices/mixer.h index 8c8cf72ea..0a2c12039 100644 --- a/src/devices/mixer.h +++ b/src/devices/mixer.h @@ -43,8 +43,9 @@ class Mixer : public EMSdevice { void process_MMSetMessage(std::shared_ptr telegram); void process_HpPoolStatus(std::shared_ptr telegram); - void process_MonitorWW(std::shared_ptr telegram); - void process_HydrTemp(std::shared_ptr telegram); + void process_IPMMonitorWW(std::shared_ptr telegram); + void process_IPMHydrTemp(std::shared_ptr telegram); + void process_IPMParameterWW(std::shared_ptr telegram); bool set_flowSetTemp(const char * value, const int8_t id); bool set_pump(const char * value, const int8_t id); @@ -60,7 +61,9 @@ class Mixer : public EMSdevice { bool set_wwCircMode(const char * value, const int8_t id); bool set_wwSelTemp(const char * value, const int8_t id); - + bool set_wwFlowTempOffset(const char * value, const int8_t id); + bool set_wwHystOn(const char * value, const int8_t id); + bool set_wwHystOff(const char * value, const int8_t id); enum class Type { NONE, @@ -100,6 +103,9 @@ class Mixer : public EMSdevice { uint16_t wwCurTemp_1_; uint16_t wwCurTemp_2_; uint16_t HydrTemp_; + int8_t wwHystOn_; // Hyst on (default -5) + int8_t wwHystOff_; // Hyst off (default -1) + uint8_t wwFlowTempOffset_; // default 40 }; } // namespace emsesp diff --git a/src/locale_DE.h b/src/locale_DE.h index 894d55274..02c25e4e3 100644 --- a/src/locale_DE.h +++ b/src/locale_DE.h @@ -221,6 +221,12 @@ MAKE_PSTR(tag_wwc1, "wwc1") MAKE_PSTR(tag_wwc2, "wwc2") MAKE_PSTR(tag_wwc3, "wwc3") MAKE_PSTR(tag_wwc4, "wwc4") +MAKE_PSTR(tag_wwc5, "wwc5") +MAKE_PSTR(tag_wwc6, "wwc6") +MAKE_PSTR(tag_wwc7, "wwc7") +MAKE_PSTR(tag_wwc8, "wwc8") +MAKE_PSTR(tag_wwc9, "wwc9") +MAKE_PSTR(tag_wwc10, "wwc10") MAKE_PSTR(tag_hs1, "hs1") MAKE_PSTR(tag_hs2, "hs2") MAKE_PSTR(tag_hs3, "hs3") @@ -520,6 +526,16 @@ MAKE_PSTR_LIST(hpTl2, F("hptl2"), F("Außenlufttemperaturfühler (TL2)")) MAKE_PSTR_LIST(hpPl1, F("hppl1"), F("Niedrigdruckfühler (PL1)")) MAKE_PSTR_LIST(hpPh1, F("hpph1"), F("Hochdruckfühler (PH1)")) +// hybrid heatpump +MAKE_PSTR_LIST(enum_hybridStrategy, F("co2-optimized"), F("cost-optimized"), F("outside-temp-switched"), F("co2-cost-mix")) +MAKE_PSTR_LIST(hybridStrategy, F("hybridstrategy"), F("hybrid control strategy")) +MAKE_PSTR_LIST(switchOverTemp, F("switchovertemp"), F("outside switchover temperature")) +MAKE_PSTR_LIST(energyCostRatio, F("energycostratio"), F("energy cost ratio")) +MAKE_PSTR_LIST(fossileFactor, F("fossilefactor"), F("fossile energy factor")) +MAKE_PSTR_LIST(electricFactor, F("electricfactor"), F("electric energy factor")) +MAKE_PSTR_LIST(delayBoiler, F("delayboiler"), F("delay boiler support")) +MAKE_PSTR_LIST(tempDiffBoiler, F("tempdiffboiler"), F("tempediff boiler support")) + // the following are dhw for the boiler and automatically tagged with 'ww' MAKE_PSTR_LIST(wWSelTemp, F("wwseltemp"), F("gewählte Temperatur")) MAKE_PSTR_LIST(wwSelTempLow, F("wwseltemplow"), F("selected lower temperature")) @@ -562,6 +578,7 @@ MAKE_PSTR_LIST(wwMaxTemp, F("wwmaxtemp"), F("Maximale Temperatur")) MAKE_PSTR_LIST(wwOneTimeKey, F("wwonetimekey"), F("Einmalladungstaste")) // mqtt values / commands +MAKE_PSTR_LIST(switchtime, F("switchtime"), F("program switchtime")) MAKE_PSTR_LIST(switchtime1, F("switchtime1"), F("own1 program switchtime")) MAKE_PSTR_LIST(switchtime2, F("switchtime2"), F("own2 program switchtime")) MAKE_PSTR_LIST(wwswitchtime, F("wwswitchtime"), F("program switchtime")) @@ -671,6 +688,7 @@ MAKE_PSTR_LIST(poolSetTemp, F("poolsettemp"), F("pool set temperature")) MAKE_PSTR_LIST(poolTemp, F("pooltemp"), F("pool temperature")) MAKE_PSTR_LIST(poolShuntStatus, F("poolshuntstatus"), F("pool shunt status opening/closing")) MAKE_PSTR_LIST(poolShunt, F("poolshunt"), F("pool shunt open/close (0% = pool / 100% = heat)")) +MAKE_PSTR_LIST(hydrTemp, F("hydrTemp"), F("hydraulic header temperature")) // solar MAKE_PSTR_LIST(collectorTemp, F("collectortemp"), F("Kollektortemperatur (TS1)")) From 94f5d4d50322d4eb878327c8708048e037f70daa Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Tue, 12 Apr 2022 18:56:23 +0200 Subject: [PATCH 8/9] fix set_switchtime --- src/devices/thermostat.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index 61d7a776c..0e28ece89 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -631,7 +631,7 @@ void Thermostat::process_RC20Timer(std::shared_ptr telegram) { char data[sizeof(hc->switchtime1)]; uint8_t no = telegram->offset / 2; uint8_t day = telegram->message_data[0] >> 5; - uint8_t temp = telegram->message_data[0] & 1; + uint8_t temp = telegram->message_data[0] & 7; uint8_t time = telegram->message_data[1]; std::string sday = read_flash_string(FL_(enum_dayOfWeek)[day]); @@ -1176,14 +1176,12 @@ void Thermostat::process_RC35Timer(std::shared_ptr telegram) { char data[sizeof(hc->switchtime1)]; uint8_t no = telegram->offset / 2; uint8_t day = telegram->message_data[0] >> 5; - uint8_t on = telegram->message_data[0] & 0x07; + uint8_t on = telegram->message_data[0] & 1; uint8_t time = telegram->message_data[1]; std::string sday = read_flash_string(FL_(enum_dayOfWeek)[day]); if (day == 7) { snprintf(data, sizeof(data), "%02d not_set", no); - } else if (model() == EMS_DEVICE_FLAG_RC30_N) { - snprintf(data, sizeof(data), "%02d %s %02d:%02d T%d", no, sday.c_str(), time / 6, 10 * (time % 6), on); } else { snprintf(data, sizeof(data), "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), on ? "on" : "off"); } @@ -2470,8 +2468,8 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char data[1] = time; } - uint8_t max_on = 3; - if (model() == EMS_DEVICE_FLAG_RC35) { + uint8_t max_on = 4; + if (model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_N) { max_on = 1; } if (no > 41 || time > 0x90 || (on > max_on && on != 7)) { @@ -2481,10 +2479,8 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char } if (data[0] != 0xE7) { std::string sday = read_flash_string(FL_(enum_dayOfWeek)[day]); - if (model() == EMS_DEVICE_FLAG_RC35) { + if (model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_N) { snprintf(out, len, "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), on ? "on" : "off"); - } else if (model() == EMS_DEVICE_FLAG_RC30_N) { - snprintf(out, len, "%02d %s %02d:%02d T%d", no, sday.c_str(), time / 6, 10 * (time % 6), on + 1); } else if (model() == EMS_DEVICE_FLAG_RC20) { snprintf(out, len, "%02d %s %02d:%02d T%d", no, sday.c_str(), time / 6, 10 * (time % 6), on); } else { From a9a11f464b2359fd4dbca3f92a8f5b8967509ee4 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Thu, 14 Apr 2022 11:59:44 +0200 Subject: [PATCH 9/9] add comment to boiler: hybrid heatpump --- src/devices/boiler.cpp | 12 ++++++++++++ src/devices/boiler.h | 8 ++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index ccfa5a507..1b2d89588 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -90,6 +90,10 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const } /* + * Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat + * thermostat always overwrites settings in boiler + * enable settings here if no thermostat is used in system + * if (model() == EMSdevice::EMS_DEVICE_FLAG_HYBRID) { register_telegram_type(0xBB, F("HybridHp"), true, MAKE_PF_CB(process_HybridHp)); } @@ -204,6 +208,10 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const MAKE_CF_CB(set_maintenancedate)); /* + * Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat + * thermostat always overwrites settings in boiler + * enable settings here if no thermostat is used in system + * // Hybrid Heatpump if (model() == EMSdevice::EMS_DEVICE_FLAG_HYBRID) { register_device_value(DeviceValueTAG::TAG_BOILER_DATA, @@ -1065,6 +1073,10 @@ void Boiler::process_UBAMaintenanceData(std::shared_ptr telegram } } /* + * Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat + * thermostat always overwrites settings in boiler + * enable settings here if no thermostat is used in system + * // 0xBB Heatpump optimization // Boiler(0x08) -> Me(0x0B), ?(0xBB), data: 00 00 00 00 00 00 00 00 00 00 00 FF 02 0F 1E 0B 1A 00 14 03 void Boiler::process_HybridHp(std::shared_ptr telegram) { diff --git a/src/devices/boiler.h b/src/devices/boiler.h index d1365f1f7..00d019898 100644 --- a/src/devices/boiler.h +++ b/src/devices/boiler.h @@ -193,8 +193,12 @@ class Boiler : public EMSdevice { // Pool unit int8_t poolSetTemp_; - /* - // HybridHP +/* + * Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat + * thermostat always overwrites settings in boiler + * enable settings here if no thermostat is used in system + * +// HybridHP uint8_t hybridStrategy_; // cost = 2, temperature = 3, mix = 4 int8_t switchOverTemp_; // degrees uint8_t energyCostRatio_; // is *10