From e430ecf85c18aa006d03ab9c01415769a64e1a1c Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Thu, 31 Oct 2024 16:29:36 +0100 Subject: [PATCH 1/5] don't count echos as errors also for remote thermostat emulation --- src/telegram.cpp | 2 +- src/uart/emsuart_esp32.cpp | 3 +++ src/uart/emsuart_esp32.h | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/telegram.cpp b/src/telegram.cpp index 46d510567..29d078af1 100644 --- a/src/telegram.cpp +++ b/src/telegram.cpp @@ -148,7 +148,7 @@ void RxService::add(uint8_t * data, uint8_t length) { // validate the CRC. if it fails then increment the number of corrupt/incomplete telegrams and only report to console/syslog uint8_t crc = calculate_crc(data, length - 1); if (data[length - 1] != crc) { - if ((data[0] & 0x7F) != ems_bus_id()) { // do not count echos as errors + if (data[0] != EMSuart::last_tx_src()) { // do not count echos as errors telegram_error_count_++; LOG_WARNING("Incomplete Rx: %s", Helpers::data_to_hex(data, length).c_str()); // include CRC } else { diff --git a/src/uart/emsuart_esp32.cpp b/src/uart/emsuart_esp32.cpp index 89b55de45..0b9f2fccc 100644 --- a/src/uart/emsuart_esp32.cpp +++ b/src/uart/emsuart_esp32.cpp @@ -31,6 +31,7 @@ #include "emsesp.h" namespace emsesp { +uint8_t EMSuart::last_tx_src_ = 0; static QueueHandle_t uart_queue; uint8_t tx_mode_ = 0xFF; @@ -144,6 +145,8 @@ uint16_t EMSuart::transmit(const uint8_t * buf, const uint8_t len) { return EMS_TX_STATUS_OK; } + last_tx_src_ = len < 4 ? 0 : buf[0]; + if (tx_mode_ == EMS_TXMODE_HW) { // hardware controlled mode uart_write_bytes_with_break(EMSUART_NUM, buf, len, 10); return EMS_TX_STATUS_OK; diff --git a/src/uart/emsuart_esp32.h b/src/uart/emsuart_esp32.h index dcb31c49e..e2b5cd643 100644 --- a/src/uart/emsuart_esp32.h +++ b/src/uart/emsuart_esp32.h @@ -65,10 +65,14 @@ class EMSuart { static void send_poll(const uint8_t data); static void stop(); static uint16_t transmit(const uint8_t * buf, const uint8_t len); + static uint8_t last_tx_src() { + return last_tx_src_; + } private: static void IRAM_ATTR uart_gen_break(uint32_t length_us); static void uart_event_task(void * pvParameters); + static uint8_t last_tx_src_; }; } // namespace emsesp From 000a73156a65f55bf6e47b4716c32726a2c7d2d2 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Tue, 5 Nov 2024 07:44:12 +0100 Subject: [PATCH 2/5] formatting --- src/emsdevice.cpp | 70 +++++++++++++++++++++++++++++++++++---------- src/locale_common.h | 2 +- 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 9f9bc28b9..a1efd137e 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -135,11 +135,27 @@ const char * EMSdevice::device_type_2_device_name(const uint8_t device_type) { case DeviceType::GATEWAY: return F_(gateway); case DeviceType::SWITCH: - return F_(switch); - case DeviceType::CONTROLLER : return F_(controller); case DeviceType::CONNECT : return F_(connect); case DeviceType::ALERT : return F_(alert); - case DeviceType::EXTENSION : return F_(extension); case DeviceType::GENERIC : return F_(generic); - case DeviceType::HEATSOURCE : return F_(heatsource); case DeviceType::VENTILATION : return F_(ventilation); - case DeviceType::WATER : return F_(water); case DeviceType::POOL : return F_(pool); default : return Helpers::translated_word(FL_(unknown), true); + return F_(switcher); + case DeviceType::CONTROLLER: + return F_(controller); + case DeviceType::CONNECT: + return F_(connect); + case DeviceType::ALERT: + return F_(alert); + case DeviceType::EXTENSION: + return F_(extension); + case DeviceType::GENERIC: + return F_(generic); + case DeviceType::HEATSOURCE: + return F_(heatsource); + case DeviceType::VENTILATION: + return F_(ventilation); + case DeviceType::WATER: + return F_(water); + case DeviceType::POOL: + return F_(pool); + default: + return Helpers::translated_word(FL_(unknown), true); } } @@ -217,23 +233,47 @@ uint8_t EMSdevice::device_name_2_device_type(const char * topic) { if (!strcmp(lowtopic, F_(mixer))) { return DeviceType::MIXER; } - if (!strcmp(lowtopic, F_(switch))) { - return DeviceType::SWITCH; - } - if (!strcmp(lowtopic, F_(gateway))) { return DeviceType::GATEWAY; } if (!strcmp(lowtopic, F_(alert))) { + if (!strcmp(lowtopic, F_(switcher))) { + return DeviceType::SWITCH; + } + if (!strcmp(lowtopic, F_(gateway))) { + return DeviceType::GATEWAY; + } + if (!strcmp(lowtopic, F_(alert))) { return DeviceType::ALERT; - } if (!strcmp(lowtopic, F_(extension))) { return DeviceType::EXTENSION; } if (!strcmp(lowtopic, F_(heatsource))) { + } + if (!strcmp(lowtopic, F_(extension))) { + return DeviceType::EXTENSION; + } + if (!strcmp(lowtopic, F_(heatsource))) { return DeviceType::HEATSOURCE; - } if (!strcmp(lowtopic, F_(ventilation))) { return DeviceType::VENTILATION; } if (!strcmp(lowtopic, F_(water))) { + } + if (!strcmp(lowtopic, F_(ventilation))) { + return DeviceType::VENTILATION; + } + if (!strcmp(lowtopic, F_(water))) { return DeviceType::WATER; - } if (!strcmp(lowtopic, F_(pool))) { return DeviceType::POOL; } + } + if (!strcmp(lowtopic, F_(pool))) { + return DeviceType::POOL; + } // non EMS - if (!strcmp(lowtopic, F_(custom))) { return DeviceType::CUSTOM; } if (!strcmp(lowtopic, F_(temperaturesensor))) { + if (!strcmp(lowtopic, F_(custom))) { + return DeviceType::CUSTOM; + } + if (!strcmp(lowtopic, F_(temperaturesensor))) { return DeviceType::TEMPERATURESENSOR; - } if (!strcmp(lowtopic, F_(analogsensor))) { return DeviceType::ANALOGSENSOR; } if (!strcmp(lowtopic, F_(scheduler))) { + } + if (!strcmp(lowtopic, F_(analogsensor))) { + return DeviceType::ANALOGSENSOR; + } + if (!strcmp(lowtopic, F_(scheduler))) { return DeviceType::SCHEDULER; - } if (!strcmp(lowtopic, F_(system))) { return DeviceType::SYSTEM; } + } + if (!strcmp(lowtopic, F_(system))) { + return DeviceType::SYSTEM; + } return DeviceType::UNKNOWN; } diff --git a/src/locale_common.h b/src/locale_common.h index 08a65d68c..92330b9de 100644 --- a/src/locale_common.h +++ b/src/locale_common.h @@ -88,7 +88,7 @@ MAKE_WORD(coldshot) // device types - lowercase, used in MQTT MAKE_WORD(boiler) MAKE_WORD(thermostat) -MAKE_WORD(switch) +MAKE_WORD_CUSTOM(switcher, "switch") MAKE_WORD(solar) MAKE_WORD(mixer) MAKE_WORD(gateway) From 761ee9e7d0f6aec7a372ccb991bffb4c96751f48 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Tue, 5 Nov 2024 08:42:28 +0100 Subject: [PATCH 3/5] fix topic for HA config default case --- src/mqtt.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mqtt.cpp b/src/mqtt.cpp index f4e3e443c..86c8db03d 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -984,6 +984,7 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev break; default: // plain old sensor + snprintf(topic, sizeof(topic), "sensor/%s", config_topic); break; } } else { From fa630b9e64b4cdb6e61ce372c0251b0a3c0b9794 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Tue, 5 Nov 2024 08:54:05 +0100 Subject: [PATCH 4/5] add system commands `showertimer`, ` showeralert` #2168 --- src/locale_common.h | 2 ++ src/locale_translations.h | 2 ++ src/system.cpp | 33 +++++++++++++++++++++++++++++++++ src/system.h | 2 ++ 4 files changed, 39 insertions(+) diff --git a/src/locale_common.h b/src/locale_common.h index 92330b9de..09ccde737 100644 --- a/src/locale_common.h +++ b/src/locale_common.h @@ -48,6 +48,8 @@ MAKE_WORD(send) MAKE_WORD(telegram) MAKE_WORD(bus_id) MAKE_WORD(tx_mode) +MAKE_WORD(showertimer) +MAKE_WORD(showeralert) MAKE_WORD(ems) MAKE_WORD(devices) MAKE_WORD(shower) diff --git a/src/locale_translations.h b/src/locale_translations.h index b78e4c60c..fc0133e37 100644 --- a/src/locale_translations.h +++ b/src/locale_translations.h @@ -79,6 +79,8 @@ MAKE_WORD_TRANSLATION(commands_response, "get response", "Hole Antwort", "Verzoe MAKE_WORD_TRANSLATION(coldshot_cmd, "send a cold shot of water", "Zugabe einer Menge kalten Wassers", "", "", "uruchom tryśnięcie zimnej wody", "", "", "soğuk su gönder", "", "pošlite studenú dávku vody", "poslat studenou vodu") // TODO translate MAKE_WORD_TRANSLATION(message_cmd, "send a message", "Eine Nachricht senden", "", "", "", "", "", "", "", "poslať správu", "odeslat zprávu") // TODO translate MAKE_WORD_TRANSLATION(values_cmd, "list all values", "Liste alle Werte auf", "", "", "", "", "", "", "", "vypísať všetky hodnoty", "vypsat všechny hodnoty") // TODO translate +MAKE_WORD_TRANSLATION(showertimer_cmd, "enable shower timer", "aktiviere Duschzeitmessung", "", "", "", "", "", "", "", "", "") // TODO translate +MAKE_WORD_TRANSLATION(showeralert_cmd, "enable shower alert", "aktiviere Duschzeitwarnung", "", "", "", "", "", "", "", "", "") // TODO translate // tags MAKE_WORD_TRANSLATION(tag_hc1, "hc1", "HK1", "hc1", "VK1", "OG1", "hc1", "hc1", "ID1", "hc1", "hc1", "hc1") diff --git a/src/system.cpp b/src/system.cpp index 7738caf43..e990e8a1e 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -196,6 +196,37 @@ bool System::command_syslog_level(const char * value, const int8_t id) { return false; } */ +// shower timer +bool System::command_showertimer(const char * value, const int8_t id) { + bool b; + if (Helpers::value2bool(value, b)) { + EMSESP::webSettingsService.update([&](WebSettings & settings) { + if (settings.shower_timer != b) { + settings.shower_timer = b; + return StateUpdateResult::CHANGED; + } + return StateUpdateResult::UNCHANGED; + }); + return true; + } + return false; +} + +// shower alert +bool System::command_showeralert(const char * value, const int8_t id) { + bool b; + if (Helpers::value2bool(value, b)) { + EMSESP::webSettingsService.update([&](WebSettings & settings) { + if (settings.shower_alert != b) { + settings.shower_alert = b; + return StateUpdateResult::CHANGED; + } + return StateUpdateResult::UNCHANGED; + }); + return true; + } + return false; +} // send message - to log and MQTT bool System::command_message(const char * value, const int8_t id) { @@ -860,6 +891,8 @@ void System::commands_init() { Command::add(EMSdevice::DeviceType::SYSTEM, F_(format), System::command_format, FL_(format_cmd), CommandFlag::ADMIN_ONLY); Command::add(EMSdevice::DeviceType::SYSTEM, F_(watch), System::command_watch, FL_(watch_cmd)); Command::add(EMSdevice::DeviceType::SYSTEM, F_(message), System::command_message, FL_(message_cmd)); + Command::add(EMSdevice::DeviceType::SYSTEM, F_(showertimer), System::command_showertimer, FL_(showertimer_cmd), CommandFlag::ADMIN_ONLY); + Command::add(EMSdevice::DeviceType::SYSTEM, F_(showeralert), System::command_showeralert, FL_(showeralert_cmd), CommandFlag::ADMIN_ONLY); #if defined(EMSESP_TEST) Command::add(EMSdevice::DeviceType::SYSTEM, ("test"), System::command_test, FL_(test_cmd)); #endif diff --git a/src/system.h b/src/system.h index ffc620a3f..36604732e 100644 --- a/src/system.h +++ b/src/system.h @@ -69,6 +69,8 @@ class System { static bool command_fetch(const char * value, const int8_t id); static bool command_restart(const char * value, const int8_t id); static bool command_format(const char * value, const int8_t id); + static bool command_showertimer(const char * value, const int8_t id); + static bool command_showeralert(const char * value, const int8_t id); static bool command_watch(const char * value, const int8_t id); static bool command_message(const char * value, const int8_t id); static bool command_info(const char * value, const int8_t id, JsonObject output); From 64a1e005015eb621a866f750667ba19acaef32e6 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Tue, 5 Nov 2024 15:01:00 +0100 Subject: [PATCH 5/5] commands showertimer, showeralert work instant and permanent, move to shower.cpp --- src/shower.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ src/system.cpp | 33 --------------------------------- src/system.h | 2 -- 3 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/shower.cpp b/src/shower.cpp index 88226cd79..b88f86266 100644 --- a/src/shower.cpp +++ b/src/shower.cpp @@ -51,6 +51,48 @@ void Shower::start() { FL_(coldshot_cmd), CommandFlag::ADMIN_ONLY); + Command::add( + EMSdevice::DeviceType::SYSTEM, + F_(showertimer), + [&](const char * value, const int8_t id, JsonObject output) { + bool b; + if (!Helpers::value2bool(value, b)) { + return false; + } + shower_timer_ = b; + EMSESP::webSettingsService.update([&](WebSettings & settings) { + if (settings.shower_timer != b) { + settings.shower_timer = b; + return StateUpdateResult::CHANGED; + } + return StateUpdateResult::UNCHANGED; + }); + return true; + }, + FL_(showertimer_cmd), + CommandFlag::ADMIN_ONLY); + + Command::add( + EMSdevice::DeviceType::SYSTEM, + F_(showeralert), + [&](const char * value, const int8_t id, JsonObject output) { + bool b; + if (!Helpers::value2bool(value, b)) { + return false; + } + shower_alert_ = b; + EMSESP::webSettingsService.update([&](WebSettings & settings) { + if (settings.shower_alert != b) { + settings.shower_alert = b; + return StateUpdateResult::CHANGED; + } + return StateUpdateResult::UNCHANGED; + }); + return true; + }, + FL_(showeralert_cmd), + CommandFlag::ADMIN_ONLY); + if (shower_timer_) { set_shower_state(false, true); // turns shower to off and creates HA topic if not already done } diff --git a/src/system.cpp b/src/system.cpp index e990e8a1e..7738caf43 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -196,37 +196,6 @@ bool System::command_syslog_level(const char * value, const int8_t id) { return false; } */ -// shower timer -bool System::command_showertimer(const char * value, const int8_t id) { - bool b; - if (Helpers::value2bool(value, b)) { - EMSESP::webSettingsService.update([&](WebSettings & settings) { - if (settings.shower_timer != b) { - settings.shower_timer = b; - return StateUpdateResult::CHANGED; - } - return StateUpdateResult::UNCHANGED; - }); - return true; - } - return false; -} - -// shower alert -bool System::command_showeralert(const char * value, const int8_t id) { - bool b; - if (Helpers::value2bool(value, b)) { - EMSESP::webSettingsService.update([&](WebSettings & settings) { - if (settings.shower_alert != b) { - settings.shower_alert = b; - return StateUpdateResult::CHANGED; - } - return StateUpdateResult::UNCHANGED; - }); - return true; - } - return false; -} // send message - to log and MQTT bool System::command_message(const char * value, const int8_t id) { @@ -891,8 +860,6 @@ void System::commands_init() { Command::add(EMSdevice::DeviceType::SYSTEM, F_(format), System::command_format, FL_(format_cmd), CommandFlag::ADMIN_ONLY); Command::add(EMSdevice::DeviceType::SYSTEM, F_(watch), System::command_watch, FL_(watch_cmd)); Command::add(EMSdevice::DeviceType::SYSTEM, F_(message), System::command_message, FL_(message_cmd)); - Command::add(EMSdevice::DeviceType::SYSTEM, F_(showertimer), System::command_showertimer, FL_(showertimer_cmd), CommandFlag::ADMIN_ONLY); - Command::add(EMSdevice::DeviceType::SYSTEM, F_(showeralert), System::command_showeralert, FL_(showeralert_cmd), CommandFlag::ADMIN_ONLY); #if defined(EMSESP_TEST) Command::add(EMSdevice::DeviceType::SYSTEM, ("test"), System::command_test, FL_(test_cmd)); #endif diff --git a/src/system.h b/src/system.h index 36604732e..ffc620a3f 100644 --- a/src/system.h +++ b/src/system.h @@ -69,8 +69,6 @@ class System { static bool command_fetch(const char * value, const int8_t id); static bool command_restart(const char * value, const int8_t id); static bool command_format(const char * value, const int8_t id); - static bool command_showertimer(const char * value, const int8_t id); - static bool command_showeralert(const char * value, const int8_t id); static bool command_watch(const char * value, const int8_t id); static bool command_message(const char * value, const int8_t id); static bool command_info(const char * value, const int8_t id, JsonObject output);