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