diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index 6025ded43..cf68370e6 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -136,6 +136,8 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i summer_typeids = {0x02AF, 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6}; curve_typeids = {0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1, 0x02A2}; summer2_typeids = {0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0476, 0x0477, 0x0478}; + hp_typeids = {0x0467, 0x0468, 0x0469, 0x046A}; + hpmode_typeids = {0x0291, 0x0292, 0x0293, 0x0294}; for (uint8_t i = 0; i < monitor_typeids.size(); i++) { register_telegram_type(monitor_typeids[i], "RC300Monitor", false, MAKE_PF_CB(process_RC300Monitor)); register_telegram_type(set_typeids[i], "RC300Set", false, MAKE_PF_CB(process_RC300Set)); @@ -145,6 +147,8 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i } for (uint8_t i = 0; i < set2_typeids.size(); i++) { register_telegram_type(set2_typeids[i], "RC300Set2", false, MAKE_PF_CB(process_RC300Set2)); + register_telegram_type(hp_typeids[i], "HPSet", false, MAKE_PF_CB(process_HPSet)); + register_telegram_type(hpmode_typeids[i], "HPMode", true, MAKE_PF_CB(process_HPMode)); } register_telegram_type(0x2F5, "RC300WWmode", true, MAKE_PF_CB(process_RC300WWmode)); register_telegram_type(0x31B, "RC300WWtemp", true, MAKE_PF_CB(process_RC300WWtemp)); @@ -306,6 +310,25 @@ std::shared_ptr Thermostat::heating_circuit(std::sha } } + // not found, search heatpump message types + if (hc_num == 0) { + for (uint8_t i = 0; i < hp_typeids.size(); i++) { + if (hp_typeids[i] == telegram->type_id) { + hc_num = i + 1; + break; + } + } + } + + if (hc_num == 0) { + for (uint8_t i = 0; i < hpmode_typeids.size(); i++) { + if (hpmode_typeids[i] == telegram->type_id) { + hc_num = i + 1; + break; + } + } + } + // not found, search device-id types for remote thermostats if (hc_num == 0 && telegram->src >= 0x18 && telegram->src <= 0x1F) { hc_num = telegram->src - 0x17; @@ -383,6 +406,9 @@ std::shared_ptr Thermostat::heating_circuit(std::sha if (summer2_typeids.size()) { toggle_fetch(summer2_typeids[hc_num - 1], toggle_); } + if (hp_typeids.size()) { + toggle_fetch(hp_typeids[hc_num - 1], toggle_); + } return new_hc; // return back point to new HC object } @@ -1128,6 +1154,26 @@ void Thermostat::process_RC300Floordry(std::shared_ptr telegram) has_update(telegram, floordrytemp_, 1); } +// 0x291 ff. HP mode +void Thermostat::process_HPMode(std::shared_ptr telegram) { + std::shared_ptr hc = heating_circuit(telegram); + if (hc == nullptr) { + return; + } + has_update(telegram, hc->hpmode, 0); +} + +// 0x467 ff HP settings +void Thermostat::process_HPSet(std::shared_ptr telegram) { + std::shared_ptr hc = heating_circuit(telegram); + if (hc == nullptr) { + return; + } + has_update(telegram, hc->dewoffset, 0); // 7-35°C + has_update(telegram, hc->roomtempdiff, 3); // 1-10K + has_update(telegram, hc->hpminflowtemp, 4); // 2-10K +} + // type 0x41 - data from the RC30 thermostat(0x10) - 14 bytes long // RC30Monitor(0x41), data: 80 20 00 AC 00 00 00 02 00 05 09 00 AC 00 void Thermostat::process_RC30Monitor(std::shared_ptr telegram) { @@ -1447,6 +1493,62 @@ void Thermostat::process_RCErrorMessage(std::shared_ptr telegram * */ +// hp mode RC300 +bool Thermostat::set_roomtempdiff(const char * value, const int8_t id) { + uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id; + std::shared_ptr hc = heating_circuit(hc_num); + if (hc == nullptr) { + return false; + } + int v; + if (Helpers::value2number(value, v)) { + write_command(hp_typeids[hc->hc()], 3, v, hp_typeids[hc->hc()]); + return true; + } + return false; +} +bool Thermostat::set_dewoffset(const char * value, const int8_t id) { + uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id; + std::shared_ptr hc = heating_circuit(hc_num); + if (hc == nullptr) { + return false; + } + int v; + if (Helpers::value2number(value, v)) { + write_command(hp_typeids[hc->hc()], 4, v, hp_typeids[hc->hc()]); + return true; + } + return false; +} + +bool Thermostat::set_hpminflowtemp(const char * value, const int8_t id) { + uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id; + std::shared_ptr hc = heating_circuit(hc_num); + if (hc == nullptr) { + return false; + } + int v; + if (Helpers::value2temperature(value, v)) { + write_command(hp_typeids[hc->hc()], 0, v, hp_typeids[hc->hc()]); + return true; + } + return false; +} + +bool Thermostat::set_hpmode(const char * value, const int8_t id) { + uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id; + std::shared_ptr hc = heating_circuit(hc_num); + if (hc == nullptr) { + return false; + } + uint8_t v; + if (!Helpers::value2enum(value, v, FL_(enum_hpmode))) { + return false; + } + write_command(hpmode_typeids[hc->hc()], 0, v, hpmode_typeids[hc->hc()]); + return true; +} + // 0xBB Hybrid pump bool Thermostat::set_hybridStrategy(const char * value, const int8_t id) { uint8_t v; @@ -4076,6 +4178,12 @@ void Thermostat::register_device_values_hc(std::shared_ptrnoreducetemp, DeviceValueType::INT, FL_(noreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_noreducetemp)); register_device_value(tag, &hc->reducetemp, DeviceValueType::INT, FL_(reducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_reducetemp)); register_device_value(tag, &hc->wwprio, DeviceValueType::BOOL, FL_(wwprio), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwprio)); + + register_device_value(tag, &hc->hpmode, DeviceValueType::ENUM, FL_(enum_hpmode), FL_(hpmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_hpmode)); + register_device_value(tag, &hc->dewoffset, DeviceValueType::UINT, FL_(dewoffset), DeviceValueUOM::K, MAKE_CF_CB(set_dewoffset)); + register_device_value(tag, &hc->roomtempdiff, DeviceValueType::UINT, FL_(roomtempdiff), DeviceValueUOM::K, MAKE_CF_CB(set_roomtempdiff)); + register_device_value(tag, &hc->hpminflowtemp, DeviceValueType::UINT, FL_(hpminflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_hpminflowtemp)); + break; case EMS_DEVICE_FLAG_CRF: register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode5), FL_(mode), DeviceValueUOM::NONE); diff --git a/src/devices/thermostat.h b/src/devices/thermostat.h index a73abd26b..b347ac411 100644 --- a/src/devices/thermostat.h +++ b/src/devices/thermostat.h @@ -89,6 +89,11 @@ class Thermostat : public EMSdevice { uint16_t reduceminutes; // remaining minutes to night->day // FW100 temperature uint8_t roomsensor; // 1-intern, 2-extern, 3-autoselect the lower value + // hp + uint8_t dewoffset; + uint8_t roomtempdiff; + uint8_t hpminflowtemp; + uint8_t hpmode; uint8_t hc_num() const { return hc_num_; @@ -170,6 +175,8 @@ class Thermostat : public EMSdevice { std::vector summer_typeids; std::vector summer2_typeids; std::vector curve_typeids; + std::vector hp_typeids; + std::vector hpmode_typeids; // standard for all thermostats char status_[20]; // online or offline @@ -392,6 +399,8 @@ class Thermostat : public EMSdevice { void process_RemoteTemp(std::shared_ptr telegram); void process_RemoteHumidity(std::shared_ptr telegram); void process_RemoteCorrection(std::shared_ptr telegram); + void process_HPSet(std::shared_ptr telegram); + void process_HPMode(std::shared_ptr telegram); // internal helper functions bool set_mode_n(const uint8_t mode, const uint8_t hc_num); @@ -551,6 +560,11 @@ class Thermostat : public EMSdevice { bool set_pvEnableWw(const char * value, const int8_t id); bool set_pvRaiseHeat(const char * value, const int8_t id); bool set_pvLowerCool(const char * value, const int8_t id); + + bool set_roomtempdiff(const char * value, const int8_t id); + bool set_dewoffset(const char * value, const int8_t id); + bool set_hpminflowtemp(const char * value, const int8_t id); + bool set_hpmode(const char * value, const int8_t id); }; } // namespace emsesp diff --git a/src/locale_common.h b/src/locale_common.h index afab14406..3e373dab1 100644 --- a/src/locale_common.h +++ b/src/locale_common.h @@ -292,6 +292,7 @@ MAKE_ENUM(enum_summermode, FL_(summer), FL_(auto), FL_(winter)) MAKE_ENUM(enum_hpoperatingmode, FL_(off), FL_(auto), FL_(heating), FL_(cooling)) MAKE_ENUM(enum_summer, FL_(winter), FL_(summer)) MAKE_ENUM(enum_operatingstate, FL_(heating), FL_(off), FL_(cooling)) +MAKE_ENUM(enum_hpmode, FL_(heating), FL_(cooling), FL_(heatandcool)) MAKE_ENUM(enum_mode, FL_(manual), FL_(auto)) // RC100, RC300, RC310 MAKE_ENUM(enum_mode2, FL_(off), FL_(manual), FL_(auto)) // RC20, RC30 diff --git a/src/locale_translations.h b/src/locale_translations.h index baa571cdd..c8b8e0c48 100644 --- a/src/locale_translations.h +++ b/src/locale_translations.h @@ -178,6 +178,7 @@ MAKE_WORD_TRANSLATION(layeredbuffer, "layered buffer", "Schichtspeicher", "Gelaa MAKE_WORD_TRANSLATION(maintenance, "maintenance", "Wartung", "Onderhoud", "Underhåll", "przegląd", "vedlikehold", "maintenance", "bakım") MAKE_WORD_TRANSLATION(heating, "heating", "Heizen", "Verwarmen", "Uppvärmning", "ogrzewanie", "oppvarming", "chauffage", "ısıtma") MAKE_WORD_TRANSLATION(cooling, "cooling", "Kühlen", "Koelen", "Kyler", "chłodzenie", "kjøling", "refroidissement", "soğuma") +MAKE_WORD_TRANSLATION(heatandcool, "heating&cooling", "Heizen&Kühlen", "Verwarmen&Koelen", "Uppvärmning&Kyler") // TODO translate MAKE_WORD_TRANSLATION(disinfecting, "disinfecting", "Desinfizieren", "Desinfecteren", "Desinficerar", "dezynfekcja termiczna", "desinfisering", "désinfection", "dezenfeksiyon") MAKE_WORD_TRANSLATION(no_heat, "no heat", "keine Wärme", "Geen warmte", "Ingen värme", "brak ciepła", "ingen varme", "pas de chauffage", "ısınma yok") MAKE_WORD_TRANSLATION(heatrequest, "heat request", "Wärmeanforderung", "Verwarmignsverzoek", "Värmeförfrågan", "zapotrzebowanie na ciepło", "varmeforespørsel", "demande de chauffage", "ısınma ihtiyacı") @@ -574,7 +575,6 @@ MAKE_TRANSLATION(mixingvalves, "mixingvalves", "mixing valves", "Mischventile", MAKE_TRANSLATION(pvEnableWw, "pvenableww", "enable raise dhw", "aktiviere Anhebung WW", "", "", "podwyższenie c.w.u. z PV", "aktivere hevet temperatur bereder", "", "") // TODO translate MAKE_TRANSLATION(pvRaiseHeat, "pvraiseheat", "raise heating with PV", "Anhebung Heizen mit PV", "", "", "podwyższenie grzania z PV", "heve varmen med solpanel", "", "") // TODO translate MAKE_TRANSLATION(pvLowerCool, "pvlowercool", "lower cooling with PV", "Kühlabsenkung mit PV", "", "", "obniżenie chłodzenia z PV", "nedre kjøling solpanel", "", "") // TODO translate - // thermostat ww MAKE_TRANSLATION(wwMode, "wwmode", "mode", "Modus", "Modus", "Läge", "tryb pracy", "modus", "mode", "") MAKE_TRANSLATION(wwSetTempLow, "wwsettemplow", "set low temperature", "untere Solltemperatur", "Onderste streeftemperatuur", "Nedre Börvärde", "zadana temperatura obniżona", "nedre settverdi", "réglage température basse", "") @@ -649,6 +649,11 @@ MAKE_TRANSLATION(reducehours, "reducehours", "duration for nighttemp", "Dauer Na MAKE_TRANSLATION(reduceminutes, "reduceminutes", "remaining time for nightmode", "Restzeit Nachttemp.", "Resterende tijd nachtverlaging", "Återstående Tid Nattläge", "czas do końca trybu nocnego", "gjenværende tid i nattstilling", "temps restant mode nuit", "") MAKE_TRANSLATION(switchonoptimization, "switchonoptimization", "switch-on optimization", "Einschaltoptimierung", "Inschakeloptimalisering", "Växlingsoptimering", "optymalizacja załączania", "slå på optimalisering", "optimisation mise en marche", "") +MAKE_TRANSLATION(hpmode, "hpmode", "HP Mode", "WP Modus") +MAKE_TRANSLATION(dewoffset, "dewoffset", "dew point offset", "Taupunkt Differenz") +MAKE_TRANSLATION(roomtempdiff, "roomtempdiff", "room temp difference", "Raumtemperatur Differenz") +MAKE_TRANSLATION(hpminflowtemp, "hpminflowtemp", "HP min. flow temp.", "WP minimale Vorlauftemperatur") + // heatpump MAKE_TRANSLATION(airHumidity, "airhumidity", "relative air humidity", "relative Luftfeuchte", "Relatieve luchtvochtigheid", "Relativ Luftfuktighet", "wilgotność względna w pomieszczeniu", "luftfuktighet", "humidité relative air", "") MAKE_TRANSLATION(dewTemperature, "dewtemperature", "dew point temperature", "Taupunkttemperatur", "Dauwpunttemperatuur", "Daggpunkt", "punkt rosy w pomieszczeniu", "duggtemperatur", "température point rosée", "")