11 Commits

Author SHA1 Message Date
Proddy
34a2b20be8 Merge pull request #2978 from MichaelDvP/dev
add basflowtemp #2969, add pumpkick #2965, add reset HP #2933, fix custom brand
2026-03-13 19:58:03 +01:00
MichaelDvP
f1fc8d9aae update testdata 2026-03-13 16:52:48 +01:00
MichaelDvP
b04355e3e1 update asyncwebserver 2026-03-13 10:32:33 +01:00
MichaelDvP
cd3ae5cdf2 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2026-03-13 10:22:24 +01:00
MichaelDvP
a261ca23af add baseflowtemp #2969 2026-03-13 10:15:51 +01:00
MichaelDvP
cb96904a5c fix custom brand use after free of c_str() in json. 2026-03-13 10:15:00 +01:00
MichaelDvP
4a2d78f8e1 minflowtemp taken from offset 13 or 8 2026-03-11 18:43:25 +01:00
MichaelDvP
2037bc3a10 add reset of HP errors #2933, dev9 2026-03-07 12:02:09 +01:00
MichaelDvP
64d17d7c65 Test for minflowtemp 2026-03-07 11:43:12 +01:00
MichaelDvP
92e2633342 typo 2026-03-07 11:42:27 +01:00
MichaelDvP
5c4aaa4510 add pumpkick #2965, dev.8 2026-02-20 09:56:08 +01:00
14 changed files with 1223 additions and 631 deletions

View File

@@ -10,6 +10,8 @@ For more details go to [emsesp.org](https://emsesp.org/).
- customize device brand [#2784](https://github.com/emsesp/EMS-ESP32/issues/2784)
- set model for ems-esp devices temperature, analog, etc. [#2958](https://github.com/emsesp/EMS-ESP32/discussions/2958)
- prometheus metrics for temperature/analog/scheduler/custom [#2962](https://github.com/emsesp/EMS-ESP32/issues/2962)
- boiler pumpkick [#2965](https://github.com/emsesp/EMS-ESP32/discussions/2965)
- heatpump reset [#2933](https://github.com/emsesp/EMS-ESP32/issues/2933)
## Fixed
@@ -22,3 +24,4 @@ For more details go to [emsesp.org](https://emsesp.org/).
- remove wrong burnMinPower [#2918](https://github.com/emsesp/EMS-ESP32/issues/2918)
- store scheduler active state to nvs [#2946](https://github.com/emsesp/EMS-ESP32/discussions/2946)
- translated modes `heat` and `eco` for HA-climate mode-str-tpl
- support `minflowtemp` and `baseflowtemp` [#2969](https://github.com/emsesp/EMS-ESP32/discussions/2969)

View File

@@ -26,22 +26,22 @@
"@alova/adapter-xhr": "2.3.1",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@mui/icons-material": "^7.3.8",
"@mui/material": "^7.3.8",
"@preact/compat": "^18.3.1",
"@mui/icons-material": "^7.3.9",
"@mui/material": "^7.3.9",
"@preact/compat": "^18.3.2",
"@table-library/react-table-library": "4.1.15",
"alova": "3.5.0",
"alova": "3.5.1",
"async-validator": "^4.2.5",
"etag": "^1.8.1",
"formidable": "^3.5.4",
"jwt-decode": "^4.0.0",
"magic-string": "^0.30.21",
"mime-types": "^3.0.2",
"preact": "^10.28.3",
"preact": "^10.29.0",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-icons": "^5.5.0",
"react-router": "^7.13.0",
"react-icons": "^5.6.0",
"react-router": "^7.13.1",
"react-toastify": "^11.0.5",
"typesafe-i18n": "^5.27.1",
"typescript": "^5.9.3"
@@ -49,23 +49,23 @@
"devDependencies": {
"@babel/core": "^7.29.0",
"@eslint/js": "^10.0.1",
"@preact/compat": "^18.3.1",
"@preact/compat": "^18.3.2",
"@preact/preset-vite": "^2.10.3",
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
"@types/node": "^25.2.3",
"@types/node": "^25.5.0",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"axe-core": "^4.11.1",
"concurrently": "^9.2.1",
"eslint": "^10.0.0",
"eslint": "^10.0.3",
"eslint-config-prettier": "^10.1.8",
"prettier": "^3.8.1",
"rollup-plugin-visualizer": "^6.0.5",
"rollup-plugin-visualizer": "^7.0.1",
"terser": "^5.46.0",
"typescript-eslint": "^8.55.0",
"typescript-eslint": "^8.57.0",
"vite": "^7.3.1",
"vite-plugin-imagemin": "^0.6.1",
"vite-tsconfig-paths": "^6.1.1"
},
"packageManager": "pnpm@10.29.3"
"packageManager": "pnpm@10.32.1"
}

1654
interface/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -106,7 +106,7 @@ board_build.filesystem = littlefs
lib_deps =
bblanchon/ArduinoJson @ 7.4.2
ESP32Async/AsyncTCP @ 3.4.10
ESP32Async/ESPAsyncWebServer @ 3.10.0
ESP32Async/ESPAsyncWebServer @ 3.10.1
https://github.com/emsesp/EMS-ESP-Modules.git @ 1.0.8

View File

@@ -104,9 +104,9 @@ const char * EMSdevice::uom_to_string(uint8_t uom) {
}
}
const char * EMSdevice::brand_to_char() {
std::string EMSdevice::brand_to_char() {
if (!custom_brand().empty()) {
return custom_brand().c_str();
return custom_brand();
}
switch (brand_) {
case EMSdevice::Brand::BOSCH:
@@ -331,15 +331,15 @@ uint8_t EMSdevice::decode_brand(uint8_t value) {
std::string EMSdevice::to_string() {
// for devices that haven't been lookup yet, don't show all details
if (product_id_ == 0) {
return std::string(name()) + " (DeviceID:" + Helpers::hextoa(device_id_) + ")";
return name() + " (DeviceID:" + Helpers::hextoa(device_id_) + ")";
}
if (brand_ == Brand::NO_BRAND && custom_brand().empty()) {
return std::string(name()) + " (DeviceID:" + Helpers::hextoa(device_id_) + ", ProductID:" + Helpers::itoa(product_id_) + ", Version:" + version_ + ")";
return name() + " (DeviceID:" + Helpers::hextoa(device_id_) + ", ProductID:" + Helpers::itoa(product_id_) + ", Version:" + version_ + ")";
}
return std::string(brand_to_char()) + " " + name() + " (DeviceID:" + Helpers::hextoa(device_id_) + ", ProductID:" + Helpers::itoa(product_id_)
+ ", Version:" + version_ + ")";
return brand_to_char() + " " + name() + " (DeviceID:" + Helpers::hextoa(device_id_) + ", ProductID:" + Helpers::itoa(product_id_) + ", Version:" + version_
+ ")";
}
// returns string of EMS device version and productID
@@ -2160,7 +2160,7 @@ void EMSdevice::mqtt_ha_entity_config_create() {
if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && dv.has_state(DeviceValueState::DV_ACTIVE)
&& !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE)) {
// create_device_config is only done once for the EMS device. It can added to any entity, so we take the first
if (Mqtt::publish_ha_sensor_config_dv(dv, name().c_str(), std::string(brand_to_char()).c_str(), to_string_version().c_str(), false, create_device_config)) {
if (Mqtt::publish_ha_sensor_config_dv(dv, name().c_str(), brand_to_char().c_str(), to_string_version().c_str(), false, create_device_config)) {
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
create_device_config = false; // only create the main config once
count++;

View File

@@ -63,7 +63,7 @@ class EMSdevice {
const char * device_type_2_device_name_translated(); // returns translated device type name
bool has_tags(const int8_t tag) const;
bool has_cmd(const char * cmd, const int8_t id) const;
const char * brand_to_char();
std::string brand_to_char();
std::string to_string();
std::string to_string_short();
std::string to_string_version();

View File

@@ -303,7 +303,7 @@ MAKE_ENUM(enum_comfort, FL_(hot), FL_(eco), FL_(intelligent))
MAKE_ENUM(enum_comfort1, FL_(high_comfort), FL_(eco))
MAKE_ENUM(enum_comfort2, FL_(eco), FL_(high_comfort))
MAKE_ENUM(enum_flow, FL_(off), FL_(flow), FL_(bufferedflow), FL_(buffer), FL_(layeredbuffer))
MAKE_ENUM(enum_reset, FL_(dash), FL_(maintenance), FL_(error), FL_(history), FL_(message))
MAKE_ENUM(enum_reset, FL_(dash), FL_(maintenance), FL_(error), FL_(history), FL_(message), FL_(hp_error), FL_(burn_starts), FL_(factory))
MAKE_ENUM(enum_maxHeat, FL_(0kW), FL_(2kW), FL_(3kW), FL_(4kW), FL_(6kW), FL_(9kW))
MAKE_ENUM(enum_maxHeat1, FL_(0kW), FL_(3kW), FL_(6kW), FL_(9kW))
MAKE_ENUM(enum_maxHeat2, FL_(3kW), FL_(6kW), FL_(9kW))

View File

@@ -197,6 +197,9 @@ MAKE_WORD_TRANSLATION(lower, "lower", "niedriger", "lager", "lägre", "mniejszy"
MAKE_WORD_TRANSLATION(error, "error", "Fehler", "error", "Fel", "błąd", "feil", "erreur", "Hata", "errore", "error", "chyba")
MAKE_WORD_TRANSLATION(history, "history", "Fehlerspeicher", "geschiedenis", "historik", "historia", "historikk", "historique", "geçmiş", "storico", "história", "historie")
MAKE_WORD_TRANSLATION(message, "message", "Meldung", "melding", "meddelande", "komunikat", "melding", "message", "mesajı", "messaggio", "správa", "zpráva")
MAKE_WORD_TRANSLATION(hp_error, "hp error", "WP Fehler", "hp error", "hp Fel", "hp błąd", "hp feil", "hp erreur", "hp Hata", "hp errore", "hp error", "hp chyba")
MAKE_WORD_TRANSLATION(factory, "factory", "werkseinst.", "", "", "", "", "", "", "", "", "")
MAKE_WORD_TRANSLATION(burn_starts, "burner starts", "Brennerstarts", "", "", "", "", "", "", "", "", "")
MAKE_WORD_TRANSLATION(na, "n/a", "n/a", "n/a", "n/a", "nd.", "n/a", "n/c", "mevcut değil", "n/a", "n/a", "n/a")
MAKE_WORD_TRANSLATION(inverted, "inverted", "invertiert", "omgekeerd", "inverterad", "odwrócony", "invertert", "inversé", "ters", "invertito", "invertovaný", "invertovaný")
@@ -424,6 +427,10 @@ MAKE_TRANSLATION(pumpOnTemp, "pumpontemp", "pump logic temperature", "Pumpenlogi
MAKE_TRANSLATION(headertemp, "headertemp", "low loss header", "Hydr. Weiche", "open verdeler", "Fördelare", "sprzęgło hydrauliczne", "lav tap header", "bouteille de déc. hydr.", "isı bloğu gidiş suyu sıc.", "comp. idr.", "nízkostratová hlavica", "hydraulický oddělovač")
MAKE_TRANSLATION(heatblock, "heatblock", "heating block", "Wärmezelle", "Aanvoertemp. warmtecel", "Värmeblock", "blok grzewczy", "varmeblokk", "départ corps de chauffe", "Hid.denge kabı sıcaklığı", "mandata scamb. pr.", "vykurovací blok", "blok topení")
MAKE_TRANSLATION(pumpKickHour, "pumpkickhour", "pump kick hour", "Stunde Pumpkick")
MAKE_TRANSLATION(pumpKickDay, "pumpkickday", "pump kick day", "Tag Pumpkick")
MAKE_TRANSLATION(pumpKickDelay, "pumpkickdelay", "pump kick delay", "Pause vor Pumpkick")
MAKE_TRANSLATION(curveOn, "curveon", "heatingcurve on", "Heizkurve an", "stookkromme aan", "Värmekurva På", "krzywa grzewcza włączona", "varmekurve på", "courbe de chauffage activée", "ısıtma eğrisi açık", "curva di riscaldamento attiva", "vykurovacia krivka zapnutá", "topná křivka zapnutá")
MAKE_TRANSLATION(curveBase, "curvebase", "heatingcurve base", "Heizkurve Basis", "stookkromme basis", "Värmekurva Bas", "podstawa krzywej grzewczej", "varmekurve basis", "base de courbe de chauffage", "ısıtma eğrisi tabanı", "base curva di riscaldamento", "základňa vykurovacej krivky", "základ topné křivky")
MAKE_TRANSLATION(curveEnd, "curveend", "heatingcurve end", "Heizkurve Ende", "stookkromme einde", "Värmekurva Slut", "koniec krzywej grzewczej", "varmekurve slutt", "fin de courbe de chauffage", "ısıtma eğrisi sonu", "fine curva di riscaldamento", "koniec vykurovacej krivky", "konec topné křivky")
@@ -773,6 +780,7 @@ MAKE_TRANSLATION(comforttemp, "comforttemp", "comfort temperature", "Komforttemp
MAKE_TRANSLATION(summertemp, "summertemp", "summer temperature", "Sommertemperatur", "Zomertemperatuur", "Sommartemperatur", "temperatura przełączania lato/zima", "Sommertemperatur", "température été", "yaz sıcaklığı", "temperatura estiva", "letná teplota", "letní teplota")
MAKE_TRANSLATION(designtemp, "designtemp", "design temperature", "Auslegungstemperatur", "Ontwerptemperatuur", "Design-temperatur", "temperatura projektowa", "designtemperatur", "température conception", "özel sıcaklık", "temperatura predefinita", "návrhová teplota", "dimenzovaná teplota")
MAKE_TRANSLATION(offsettemp, "offsettemp", "offset temperature", "Temperaturanhebung", "Temperatuur offset", "Temperaturkorrigering", "korekta temperatury", "temperaturkorrigering", "température offset", "artış sıcaklığı", "aumento della temperatura", "offsetová teplota", "offset teploty")
MAKE_TRANSLATION(baseflowtemp, "baseflowtemp", "base flow temperature", "Basis Vorlauftemperatur") // ToDo translate
MAKE_TRANSLATION(minflowtemp, "minflowtemp", "min flow temperature", "min. Vorlauftemperatur", "Minimale aanvoertemperatuur", "Min. Flödestemperatur", "minimalna temperatura zasilania", "min. turtemperatur", "température min. flux", "minimun akış sıcaklığı", "temperatura minima di mandata", "min. výstupná teplota", "vytápění minimální teplota")
MAKE_TRANSLATION(maxflowtemp, "maxflowtemp", "max flow temperature", "max. Vorlauftemperatur", "Maximale aanvoertemperatuur", "Max. Flödestemperatur", "maksymalna temperatura zasilania", "maks turtemperatur", "température max flux", "maksimum akış sıcaklığı", "temperatura massima di mandata", "maximálna teplota prívodu", "vytápění maximální teplota")
MAKE_TRANSLATION(roominfluence, "roominfluence", "room influence", "Raumeinfluss", "Ruimteinvloed", "Rumspåverkan", "wpływ pomieszczenia", "rominnflytelse", "influence pièce", "oda etkisi", "influenza della camera", "vplyv miestnosti", "vliv prostoru")

View File

@@ -65,6 +65,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_telegram_type(0xE6, "UBAParametersPlus", true, MAKE_PF_CB(process_UBAParametersPlus));
register_telegram_type(0xE9, "UBAMonitorWWPlus", false, MAKE_PF_CB(process_UBAMonitorWWPlus));
register_telegram_type(0xEA, "UBAParameterWWPlus", true, MAKE_PF_CB(process_UBAParameterWWPlus));
register_telegram_type(0xEB, "PumpKick", true, MAKE_PF_CB(process_PumpKick));
register_telegram_type(0x28, "WeatherComp", true, MAKE_PF_CB(process_WeatherComp));
register_telegram_type(0x2E0, "UBASetPoints", false, MAKE_PF_CB(process_UBASetPoints2));
register_telegram_type(0x2CC, "HPPressure", true, MAKE_PF_CB(process_HpPressure));
@@ -355,6 +356,24 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &pc1On_, DeviceValueType::BOOL, FL_(pc1On), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &pc1Rate_, DeviceValueType::UINT8, FL_(pc1Rate), DeviceValueUOM::PERCENT);
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &pumpKickHour_, DeviceValueType::UINT8, FL_(pumpKickHour), DeviceValueUOM::HOURS, MAKE_CF_CB(set_pumpKickHour), 0, 23);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&pumpKickDay_,
DeviceValueType::ENUM,
FL_(enum_dayOfWeek),
FL_(pumpKickDay),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_pumpKickDay));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&pumpKickDelay_,
DeviceValueType::UINT16,
FL_(pumpKickDelay),
DeviceValueUOM::MINUTES,
MAKE_CF_CB(set_pumpKickDelay),
0,
32767);
/*
* Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat
* thermostat always overwrites settings in boiler
@@ -2246,6 +2265,13 @@ void Boiler::process_HpPowerLimit(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, hpPowerLimit_, 0);
}
// 0x0EB
void Boiler::process_PumpKick(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, pumpKickHour_, 0);
has_enumupdate(telegram, pumpKickDay_, 1, 1); // 1-mo, ...
has_update(telegram, pumpKickDelay_, 2);
}
// Boiler(0x08) -B-> All(0x00), ?(0x2E), data: 00 00 1C CE 00 00 05 E8 00 00 00 18 00 00 00 02
void Boiler::process_Meters(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, gasMeterHeat_, 0);
@@ -2979,25 +3005,26 @@ bool Boiler::set_reset(const char * value, const int8_t id) {
}
if (num == 0) {
return true; // dash
} else if (num == 1) {
// LOG_INFO("Reset boiler maintenance message");
return true; // dash
} else if (num == 1) { // Reset boiler maintenance message;
write_command(0x05, 8, 0xFF, 0x1C);
return true;
} else if (num == 2) {
// LOG_INFO("Reset boiler error message");
write_command(0x05, 0, 0x5A); // error reset
} else if (num == 2) { // Reset boiler error message;
write_command(0x05, 0, 0x5A);
return true;
} else if (num == 3) {
// LOG_INFO("Reset boiler history");
write_command(0x05, 42, 0x01); // clear history
} else if (num == 3) { // Reset boiler history
write_command(0x05, 42, 0x01);
return true;
} else if (num == 4) {
// LOG_INFO("Reset boiler message");
write_command(0x05, 8, 0xFF); // same as maintenance
write_command(0x05, 8, 0xFF); // reset messages, same as maintenance reset (1)
return true;
} else if (num == 5) {
// LOG_INFO("Factory Reset");
} else if (num == 5) { // reset Heatpump errors
write_command(0x05, 50, 0xFF);
return true;
} else if (num == 6) { // reset burner starts
write_command(0x05, 2, 165);
return true;
} else if (num == 7) { // factory reset
write_command(0x05, 6, 154);
return true;
}
@@ -3628,4 +3655,32 @@ bool Boiler::set_shutdown(const char * value, const int8_t id) {
return false;
}
bool Boiler::set_pumpKickHour(const char * value, const int8_t id) {
int v;
if (Helpers::value2number(value, v, 0, 23)) {
write_command(0xEB, 0, v, 0xEB);
return true;
}
return false;
}
bool Boiler::set_pumpKickDay(const char * value, const int8_t id) {
uint8_t v;
if (Helpers::value2enum(value, v, FL_(enum_dayOfWeek))) {
write_command(0xEB, 1, v + 1, 0xEB);
return true;
}
return false;
}
bool Boiler::set_pumpKickDelay(const char * value, const int8_t id) {
int v;
if (Helpers::value2number(value, v, 0, 32767)) {
uint8_t data[2] = {(uint8_t)(v >> 8), (uint8_t)v};
write_command(0xEB, 2, data, 2, 0xEB);
return true;
}
return false;
}
} // namespace emsesp

View File

@@ -319,6 +319,9 @@ class Boiler : public EMSdevice {
int16_t pc1Flow_;
uint8_t pc1Rate_;
uint8_t pc1On_;
uint8_t pumpKickHour_; // hour
uint8_t pumpKickDay_; // day 1=mo
uint16_t pumpKickDelay_; // delay minutes after pump running
// HIU
// uint16_t cwFlowRate_; // cold water flow rate *10
@@ -397,6 +400,7 @@ class Boiler : public EMSdevice {
void process_HpFan(std::shared_ptr<const Telegram> telegram);
void process_HpPower2(std::shared_ptr<const Telegram> telegram);
void process_HpPowerLimit(std::shared_ptr<const Telegram> telegram);
void process_PumpKick(std::shared_ptr<const Telegram> telegram);
void process_Meters(std::shared_ptr<const Telegram> telegram);
void process_Energy(std::shared_ptr<const Telegram> telegram);
@@ -602,6 +606,10 @@ class Boiler : public EMSdevice {
bool set_nrgHeat(const char * value, const int8_t id);
bool set_nrgWw(const char * value, const int8_t id);
bool set_nomPower(const char * value, const int8_t id);
bool set_pumpKickHour(const char * value, const int8_t id);
bool set_pumpKickDay(const char * value, const int8_t id);
bool set_pumpKickDelay(const char * value, const int8_t id);
};
} // namespace emsesp

View File

@@ -1101,6 +1101,8 @@ void Thermostat::process_JunkersWW(std::shared_ptr<const Telegram> telegram) {
void Thermostat::process_JunkersDisp(std::shared_ptr<const Telegram> telegram) {
has_enumupdate(telegram, ibaMainDisplay_, 1, 1);
has_update(telegram, ibaLanguage_, 3);
has_update(telegram, ibaMinExtTemperature_, 16);
has_update(telegram, ibaBuildingType_, 17); // percent /10
}
// type 0x02A5 - data from Worchester CRF200
@@ -1250,12 +1252,12 @@ void Thermostat::process_RC300Summer(std::shared_ptr<const Telegram> telegram) {
if (hc->heatingtype != 3) {
has_update(telegram, hc->designtemp, 4);
has_update(telegram, hc->minflowtemp, model() == EMSdevice::EMS_DEVICE_FLAG_BC400 ? 13 : 8);
} else {
has_update(telegram, hc->designtemp, 5);
has_update(telegram, hc->minflowtemp, 8);
}
// minflowtemp could be in 8 or 13 #2969
has_update(telegram, hc->minflowtemp, 13);
has_update(telegram, hc->baseflowtemp, 8);
has_update(telegram, hc->fastHeatup, 10);
has_update(telegram, hc->comfortPointOffset, 11);
has_update(telegram, hc->comfortPointTemp, 12);
@@ -2025,6 +2027,8 @@ bool Thermostat::set_minexttemp(const char * value, const int8_t id) {
write_command(0x241, 10, mt, 0x241);
} else if (isRC300()) {
write_command(0x240, 10, mt, 0x240);
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
write_command(0x110, 16, mt, 0x110);
} else {
write_command(EMS_TYPE_IBASettings, 5, mt, EMS_TYPE_IBASettings);
}
@@ -2181,6 +2185,14 @@ bool Thermostat::set_remotehum(const char * value, const int8_t id) {
// 0xA5/0xA7 - Set the building settings
bool Thermostat::set_building(const char * value, const int8_t id) {
if (model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
int i;
if (Helpers::value2number(value, i, 0, 100)) {
write_command(0x110, 17, i / 10, 0x110);
return true;
}
return false;
}
uint8_t bd;
if (!Helpers::value2enum(value, bd, FL_(enum_ibaBuildingType))) {
return false;
@@ -2326,6 +2338,7 @@ bool Thermostat::set_control(const char * value, const int8_t id) {
// 1-FB10, 2-FB100
if (model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS && !has_flags(EMSdevice::EMS_DEVICE_FLAG_JUNKERS_OLD)) {
if (Helpers::value2enum(value, ctrl, FL_(enum_j_control))) {
hc->control = ctrl; // set in advance, dont wait for verify
write_command(set_typeids[hc->hc()], 1, ctrl);
return true;
}
@@ -2374,6 +2387,7 @@ bool Thermostat::set_control(const char * value, const int8_t id) {
}
} else if (Helpers::value2enum(value, ctrl, FL_(enum_control))) {
write_command(set_typeids[hc->hc()], EMS_OFFSET_RC35Set_control, ctrl);
hc->control = ctrl; // set in advance, dont wait for verify
return true;
}
@@ -4074,10 +4088,16 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
}
factor = 1;
break;
case HeatingCircuit::Mode::BASEFLOW:
set_typeid = summer_typeids[hc->hc()];
validate_typeid = set_typeid;
offset = 8;
factor = 1;
break;
case HeatingCircuit::Mode::MINFLOW:
set_typeid = summer_typeids[hc->hc()];
validate_typeid = set_typeid;
offset = hc->heatingtype != 3 && model == EMS_DEVICE_FLAG_BC400 ? 13 : 8;
offset = 13;
factor = 1;
break;
case HeatingCircuit::Mode::MAXFLOW:
@@ -4730,6 +4750,19 @@ void Thermostat::register_device_values() {
DeviceValueUOM::NONE,
MAKE_CF_CB(set_language));
}
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&ibaBuildingType_,
DeviceValueType::UINT8,
DeviceValueNumOp::DV_NUMOP_MUL10,
FL_(ibaBuildingType),
DeviceValueUOM::PERCENT,
MAKE_CF_CB(set_building));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&ibaMinExtTemperature_,
DeviceValueType::INT8,
FL_(ibaMinExtTemperature),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_minexttemp));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&hybridStrategy_,
DeviceValueType::ENUM,
@@ -4880,6 +4913,7 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
register_device_value(tag, &hc->summertemp, DeviceValueType::UINT8, FL_(summertemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_summertemp), 10, 30);
register_device_value(tag, &hc->designtemp, DeviceValueType::UINT8, FL_(designtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_designtemp));
register_device_value(tag, &hc->offsettemp, DeviceValueType::INT8, FL_(offsettemp), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_offsettemp));
register_device_value(tag, &hc->baseflowtemp, DeviceValueType::UINT8, FL_(baseflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_baseflowtemp));
register_device_value(tag, &hc->minflowtemp, DeviceValueType::UINT8, FL_(minflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_minflowtemp));
register_device_value(tag, &hc->maxflowtemp, DeviceValueType::UINT8, FL_(maxflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_maxflowtemp));
register_device_value(tag, &hc->roominfluence, DeviceValueType::UINT8, FL_(roominfluence), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_roominfluence));

View File

@@ -50,7 +50,7 @@ class Thermostat : public EMSdevice {
uint8_t daymidtemp;
uint8_t nighttemp;
uint8_t holidaytemp;
uint8_t heatingtype; // type of heating: 1 radiator, 2 convectors, 3 floors, 4 room supply
uint8_t heatingtype; // type of heating: 1 radiator, 2 convectors, 3 floor, 4 room supply
uint8_t targetflowtemp;
uint8_t summertemp;
int8_t nofrosttemp; // signed -20°C to +10°C
@@ -65,6 +65,7 @@ class Thermostat : public EMSdevice {
int16_t curroominfl;
uint8_t flowtempoffset;
uint8_t minflowtemp;
uint8_t baseflowtemp;
uint8_t maxflowtemp;
uint8_t reducemode;
uint8_t nofrostmode;
@@ -169,6 +170,7 @@ class Thermostat : public EMSdevice {
DAYMID,
COOLTEMP,
COOLSTART,
BASEFLOW,
UNKNOWN
};
@@ -583,6 +585,9 @@ class Thermostat : public EMSdevice {
inline bool set_minflowtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::MINFLOW);
}
inline bool set_baseflowtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::BASEFLOW);
}
inline bool set_roominfluence(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::ROOMINFLUENCE, true);
}

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.8.2-dev.7"
#define EMSESP_APP_VERSION "3.8.2-dev.9"

View File

@@ -31,7 +31,8 @@ void test_2() {
"off\",\"heatingtemp\":\"heating temperature\",\"maintenance\":\"maintenance scheduled\",\"maintenancedate\":\"next maintenance "
"date\",\"maintenancetime\":\"time to next maintenance\",\"nofrostmode\":\"nofrost mode\",\"nofrosttemp\":\"nofrost "
"temperature\",\"nompower\":\"nominal Power\",\"nrgheat\":\"energy heating\",\"pumpcharacter\":\"boiler pump characteristic\",\"pumpdelay\":\"pump "
"delay\",\"pumpmode\":\"boiler pump mode\",\"pumpmodmax\":\"boiler pump max power\",\"pumpmodmin\":\"boiler pump min power\",\"pumpontemp\":\"pump "
"delay\",\"pumpkickday\":\"pump kick day\",\"pumpkickdelay\":\"pump kick delay\",\"pumpkickhour\":\"pump kick hour\",\"pumpmode\":\"boiler pump "
"mode\",\"pumpmodmax\":\"boiler pump max power\",\"pumpmodmin\":\"boiler pump min power\",\"pumpontemp\":\"pump "
"logic temperature\",\"reset\":\"reset\",\"selburnpow\":\"burner selected max power\",\"selflowtemp\":\"selected flow "
"temperature\",\"summertemp\":\"summer temperature\"}]";
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/boiler/commands"));