diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 11b8cd41d..c1b48dafa 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -22,6 +22,7 @@ - timeout for remote thermostat emulation [#1680](https://github.com/emsesp/EMS-ESP32/discussions/1680), [#1774](https://github.com/emsesp/EMS-ESP32/issues/1774) - CR120 thermostat as own model() [#1779](https://github.com/emsesp/EMS-ESP32/discussions/1779) - Modules - external linkable module library [#1778](https://github.com/emsesp/EMS-ESP32/issues/1778) +- make remote control timeout editable [#1774](https://github.com/emsesp/EMS-ESP32/issues/1774) ## Fixed diff --git a/interface/src/i18n/de/index.ts b/interface/src/i18n/de/index.ts index 3d9400fac..d59f7e195 100644 --- a/interface/src/i18n/de/index.ts +++ b/interface/src/i18n/de/index.ts @@ -120,7 +120,10 @@ const de: Translation = { BYPASS_TOKEN: 'Zugriffstoken-Autorisierung bei API-Aufrufen umgehen', READONLY: 'Nur-Lese-Modus aktivieren (blockiert alle ausgehenden EMS Tx Write-Befehle)', UNDERCLOCK_CPU: 'CPU-Geschwindigkeit untertakten', + REMOTE_TIMEOUT: 'Timeout', + REMOTE_TIMEOUT_EN: 'Deaktitiere Remote bei fehender Temperatur', HEATINGOFF: 'Heizen ausschalten beim EMS-ESP Start', + MIN_DURATION: 'Dauer bis die Dusche erkannt wrid', ENABLE_SHOWER_TIMER: 'Duschtimer aktivieren', ENABLE_SHOWER_ALERT: 'Duschalarm aktivieren', TRIGGER_TIME: 'Auslösezeit', diff --git a/interface/src/i18n/en/index.ts b/interface/src/i18n/en/index.ts index 8d75dc146..9fdd9977b 100644 --- a/interface/src/i18n/en/index.ts +++ b/interface/src/i18n/en/index.ts @@ -120,7 +120,10 @@ const en: Translation = { BYPASS_TOKEN: 'Bypass Access Token authorization on API calls', READONLY: 'Enable read-only mode (blocks all outgoing EMS Tx Write commands)', UNDERCLOCK_CPU: 'Underclock CPU speed', + REMOTE_TIMEOUT: 'Remote timeout', + REMOTE_TIMEOUT_EN: 'Disable remote on missing roomtemperature', HEATINGOFF: 'Start boiler with forced heating off', + MIN_DURATION: 'Time for detection shower', ENABLE_SHOWER_TIMER: 'Enable Shower Timer', ENABLE_SHOWER_ALERT: 'Enable Shower Alert', TRIGGER_TIME: 'Trigger Time', diff --git a/interface/src/i18n/fr/index.ts b/interface/src/i18n/fr/index.ts index 0d46fcbe9..1799cdfd1 100644 --- a/interface/src/i18n/fr/index.ts +++ b/interface/src/i18n/fr/index.ts @@ -121,6 +121,9 @@ const fr: Translation = { READONLY: 'Activer le mode lecture uniquement (bloque toutes les commandes EMS sortantes en écriture Tx)', UNDERCLOCK_CPU: 'Underclock du CPU', HEATINGOFF: 'Start boiler with forced heating off', // TODO translate + REMOTE_TIMEOUT: 'Remote timeout', + REMOTE_TIMEOUT_EN: 'Disable remote on missing roomtemperature', + MIN_DURATION: 'Time for detection shower', ENABLE_SHOWER_TIMER: 'Activer la minuterie de la douche', ENABLE_SHOWER_ALERT: 'Activer les alertes de durée de douche', TRIGGER_TIME: 'Durée avant déclenchement', diff --git a/interface/src/i18n/it/index.ts b/interface/src/i18n/it/index.ts index 280ec5f91..15b6c3bd0 100644 --- a/interface/src/i18n/it/index.ts +++ b/interface/src/i18n/it/index.ts @@ -120,7 +120,10 @@ const it: Translation = { BYPASS_TOKEN: 'Ignora autorizzazione del token di accesso sulle chiamate API', READONLY: 'Abilita modalità sola-lettura (blocca tutti i comandi di scrittura EMS Tx in uscita)', UNDERCLOCK_CPU: 'Abbassa velocità della CPU', + REMOTE_TIMEOUT: 'Remote timeout', + REMOTE_TIMEOUT_EN: 'Disable remote on missing roomtemperature', HEATINGOFF: 'Avviamento caldaia con riscaldamento forzato spento', + MIN_DURATION: 'Time for detection shower', ENABLE_SHOWER_TIMER: 'Abilita timer doccia', ENABLE_SHOWER_ALERT: 'Abilita avviso doccia', TRIGGER_TIME: 'Tempo di avvio', diff --git a/interface/src/i18n/nl/index.ts b/interface/src/i18n/nl/index.ts index 99d20a731..e8ece543d 100644 --- a/interface/src/i18n/nl/index.ts +++ b/interface/src/i18n/nl/index.ts @@ -120,7 +120,10 @@ const nl: Translation = { BYPASS_TOKEN: 'API Access Token authenticatie uitschakelen', READONLY: 'Activeer read-only modus (blokkeert alle outgaande EMS Tx schrijf commandos)', UNDERCLOCK_CPU: 'Underclock CPU snelheid', + REMOTE_TIMEOUT: 'Remote timeout', + REMOTE_TIMEOUT_EN: 'Disable remote on missing roomtemperature', HEATINGOFF: 'Start ketel met geforceerde verwarming uit', + MIN_DURATION: 'Time for detection shower', ENABLE_SHOWER_TIMER: 'Activeer Douche Timer (tijdmeting)', ENABLE_SHOWER_ALERT: 'Activeer Douchemelding', TRIGGER_TIME: 'Trigger tijd', diff --git a/interface/src/i18n/no/index.ts b/interface/src/i18n/no/index.ts index 33d548bce..025cb91a8 100644 --- a/interface/src/i18n/no/index.ts +++ b/interface/src/i18n/no/index.ts @@ -120,7 +120,10 @@ const no: Translation = { BYPASS_TOKEN: 'Utelat Aksess Token authorisering av API kall', READONLY: 'Aktiver read-only modus (blokker all EMS Tx Skriving)', UNDERCLOCK_CPU: 'Underklokking av prosessorhastighet', + REMOTE_TIMEOUT: 'Remote timeout', + REMOTE_TIMEOUT_EN: 'Disable remote control on missing roomtemperature', HEATINGOFF: 'Start boiler with forced heating off', // TODO translate + MIN_DURATION: 'Time for detection shower', ENABLE_SHOWER_TIMER: 'Aktiver Dusjtimer', ENABLE_SHOWER_ALERT: 'Aktiver Dusj-varsling', TRIGGER_TIME: 'Aktiveringstid', diff --git a/interface/src/i18n/pl/index.ts b/interface/src/i18n/pl/index.ts index e31b8ff60..b14fb564b 100644 --- a/interface/src/i18n/pl/index.ts +++ b/interface/src/i18n/pl/index.ts @@ -120,7 +120,10 @@ const pl: BaseTranslation = { BYPASS_TOKEN: 'Pomiń autoryzację tokenem w wywołaniach API', READONLY: 'Tryb pracy "tylko do odczytu" (blokuje wszystkie komendy zapisu na magistralę EMS)', UNDERCLOCK_CPU: 'Obniż taktowanie CPU', + REMOTE_TIMEOUT: 'Remote timeout', + REMOTE_TIMEOUT_EN: 'Disable remote control on missing roomtemperature', HEATINGOFF: 'Uruchom kocioł z wymuszonym wyłączonym grzaniem', + MIN_DURATION: 'Time for detection shower', ENABLE_SHOWER_TIMER: 'Aktywuj minutnik prysznica', ENABLE_SHOWER_ALERT: 'Aktywuj alarm prysznica', TRIGGER_TIME: 'Wyzwalaj po czasie', diff --git a/interface/src/i18n/sk/index.ts b/interface/src/i18n/sk/index.ts index c4c65ce65..5e3e599e9 100644 --- a/interface/src/i18n/sk/index.ts +++ b/interface/src/i18n/sk/index.ts @@ -120,7 +120,10 @@ const sk: Translation = { BYPASS_TOKEN: 'Vynechajte autorizáciu prístupového tokenu pri volaniach API', READONLY: 'Povoliť režim len na čítanie (blokuje všetky odchádzajúce príkazy EMS Tx Write)', UNDERCLOCK_CPU: 'Podtaktovanie rýchlosti procesora', + REMOTE_TIMEOUT: 'Remote timeout', + REMOTE_TIMEOUT_EN: 'Disable remote on missing roomtemperature', HEATINGOFF: 'Spustiť kotol s vynúteným vykurovaním', + MIN_DURATION: 'Time for detection shower', ENABLE_SHOWER_TIMER: 'Povoliť časovač sprchovania', ENABLE_SHOWER_ALERT: 'Povoliť upozornenie na sprchu', TRIGGER_TIME: 'Čas spustenia', diff --git a/interface/src/i18n/sv/index.ts b/interface/src/i18n/sv/index.ts index 5f06f30c8..523b45b35 100644 --- a/interface/src/i18n/sv/index.ts +++ b/interface/src/i18n/sv/index.ts @@ -120,7 +120,10 @@ const sv: Translation = { BYPASS_TOKEN: 'Inaktivera Token-autensiering för API-anrop', READONLY: 'Aktivera read-only (blockerar alla utgående skrivkommandon mot EMS-bussen)', UNDERCLOCK_CPU: 'Nedklocka Processorhastighet', + REMOTE_TIMEOUT: 'Remote timeout', + REMOTE_TIMEOUT_EN: 'Disable remote on missing roomtemperature', HEATINGOFF: 'Start boiler with forced heating off', // TODO translate + MIN_DURATION: 'Time for detection shower', ENABLE_SHOWER_TIMER: 'Aktivera Dusch-timer', ENABLE_SHOWER_ALERT: 'Aktivera Dusch-varning', TRIGGER_TIME: 'Aktiveringstid', diff --git a/interface/src/i18n/tr/index.ts b/interface/src/i18n/tr/index.ts index 15c2b1e33..f9656a1e5 100644 --- a/interface/src/i18n/tr/index.ts +++ b/interface/src/i18n/tr/index.ts @@ -120,7 +120,10 @@ const tr: Translation = { BYPASS_TOKEN: 'API bağlantılarında Erişim Jeton onaylamasını geç', READONLY: 'Salt okunur modu devreye al (bütün giden EMS Tx Yazma komutlarını engeller)', UNDERCLOCK_CPU: 'İşlemci hızını düşür', + REMOTE_TIMEOUT: 'Remote timeout', + REMOTE_TIMEOUT_EN: 'Disable remote on missing roomtemperature', HEATINGOFF: 'Start boiler with forced heating off', // TODO translate + MIN_DURATION: 'Time for detection shower', ENABLE_SHOWER_TIMER: 'Duş Sayacını Devreye Al', ENABLE_SHOWER_ALERT: 'Duş Alarmını Devreye Al', TRIGGER_TIME: 'Tetikleme Zamanı', diff --git a/interface/src/project/ApplicationSettings.tsx b/interface/src/project/ApplicationSettings.tsx index f28dfd6d9..9ed97d7f3 100644 --- a/interface/src/project/ApplicationSettings.tsx +++ b/interface/src/project/ApplicationSettings.tsx @@ -507,6 +507,45 @@ const ApplicationSettings: FC = () => { label={LL.HEATINGOFF()} disabled={saving} /> + + + + } + label={LL.REMOTE_TIMEOUT_EN()} + /> + + {data.remote_timeout_en && ( + + {LL.HOURS()} + ) + }} + fullWidth + variant="outlined" + value={numberValue(data.remote_timeout)} + type="number" + onChange={updateFormValue} + /> + + )} + { {LL.SECONDS()} diff --git a/interface/src/project/types.ts b/interface/src/project/types.ts index ed3519035..0fcf2da0f 100644 --- a/interface/src/project/types.ts +++ b/interface/src/project/types.ts @@ -8,6 +8,8 @@ export interface Settings { syslog_host: string; syslog_port: number; boiler_heatingoff: boolean; + remote_timeout_en: boolean; + remote_timeout: number; shower_timer: boolean; shower_alert: boolean; shower_alert_coldshot: number; diff --git a/interface/src/project/validators.ts b/interface/src/project/validators.ts index c60b0a2da..3118d18de 100644 --- a/interface/src/project/validators.ts +++ b/interface/src/project/validators.ts @@ -261,6 +261,16 @@ export const createSettingsValidator = (settings: Settings) => message: 'Time must be between 1 and 10 seconds' } ] + }), + ...(settings.remote_timeout_en && { + remote_timeout: [ + { + type: 'number', + min: 1, + max: 240, + message: 'Timeout must be between 1 and 240 hours' + } + ] }) }); diff --git a/platformio.ini b/platformio.ini index 6c7dca081..3262c6ed7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -195,7 +195,7 @@ build_flags = [env:espressi32_v3] platform = espressif32 platform_packages= - platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0-rc2 + platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.1 platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 framework = arduino board = esp32dev diff --git a/src/default_settings.h b/src/default_settings.h index 490123987..cfff9bf39 100644 --- a/src/default_settings.h +++ b/src/default_settings.h @@ -65,6 +65,14 @@ #define EMSESP_DEFAULT_BOILER_HEATINGOFF false #endif +#ifndef EMSESP_DEFAULT_REMOTE_TIMEOUT +#define EMSESP_DEFAULT_REMOTE_TIMEOUT 24 +#endif + +#ifndef EMSESP_DEFAULT_REMOTE_TIMEOUT_EN +#define EMSESP_DEFAULT_REMOTE_TIMEOUT_EN false +#endif + #ifndef EMSESP_DEFAULT_SHOWER_TIMER #define EMSESP_DEFAULT_SHOWER_TIMER false #endif diff --git a/src/roomcontrol.cpp b/src/roomcontrol.cpp index ecad897e2..f789b72c0 100644 --- a/src/roomcontrol.cpp +++ b/src/roomcontrol.cpp @@ -28,10 +28,14 @@ int16_t Roomctrl::remotetemp_[HCS] = {EMS_VALUE_INT16_NOTSET, EMS_VALUE_INT16 uint8_t Roomctrl::remotehum_[HCS] = {EMS_VALUE_UINT8_NOTSET, EMS_VALUE_UINT8_NOTSET, EMS_VALUE_UINT8_NOTSET, EMS_VALUE_UINT8_NOTSET}; uint8_t Roomctrl::sendtype_[HCS] = {SendType::TEMP, SendType::TEMP, SendType::TEMP, SendType::TEMP}; uint8_t Roomctrl::type_[HCS] = {RemoteType::NONE, RemoteType::NONE, RemoteType::NONE, RemoteType::NONE}; +uint32_t Roomctrl::timeout_ = 0; /** * set the temperature, */ +void Roomctrl::set_timeout(uint8_t t) { + timeout_ = t * 3600; +} void Roomctrl::set_remotetemp(const uint8_t type, const uint8_t hc, const int16_t temp) { if (!type_[hc] && !type) { return; @@ -96,7 +100,7 @@ void Roomctrl::send(uint8_t addr) { return; } - if (!switch_off_[hc] && (uuid::get_uptime() - receive_time_[hc]) > TIMEOUT) { + if (!switch_off_[hc] && timeout_ && (uuid::get_uptime() - receive_time_[hc]) > timeout_) { remotetemp_[hc] = EMS_VALUE_INT16_NOTSET; switch_off_[hc] = true; sendtype_[hc] = SendType::TEMP; @@ -366,6 +370,7 @@ void Roomctrl::ack_write() { data[0] = TxService::TX_WRITE_SUCCESS; EMSuart::transmit(data, 1); } + void Roomctrl::replyF7(uint8_t addr, uint8_t dst, uint8_t offset, uint8_t typehh, uint8_t typeh, uint8_t typel, uint8_t hc) { uint8_t data[12]; data[0] = addr | EMSbus::ems_mask(); diff --git a/src/roomcontrol.h b/src/roomcontrol.h index d2fa4b827..5d546e9ec 100644 --- a/src/roomcontrol.h +++ b/src/roomcontrol.h @@ -34,6 +34,7 @@ class Roomctrl { static bool is_remote(const uint8_t hc) { return (hc < 4 && remotetemp_[hc] != EMS_VALUE_INT16_NOTSET); } + static void set_timeout(uint8_t t); private: static constexpr uint32_t SEND_INTERVAL = 15000; // 15 sec @@ -59,6 +60,7 @@ class Roomctrl { static uint8_t remotehum_[HCS]; static uint8_t sendtype_[HCS]; static uint8_t type_[HCS]; // type is product-id 113 for RC20 or 109 for Junkers FB10 + static uint32_t timeout_; }; } // namespace emsesp diff --git a/src/version.h b/src/version.h index 00c9d1e6c..5d68e20f5 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.7.0-dev.15" +#define EMSESP_APP_VERSION "3.7.0-dev.16" diff --git a/src/web/WebSettingsService.cpp b/src/web/WebSettingsService.cpp index ee12c5f56..e95885777 100644 --- a/src/web/WebSettingsService.cpp +++ b/src/web/WebSettingsService.cpp @@ -43,6 +43,8 @@ void WebSettings::read(WebSettings & settings, JsonObject root) { root["syslog_host"] = settings.syslog_host; root["syslog_port"] = settings.syslog_port; root["boiler_heatingoff"] = settings.boiler_heatingoff; + root["remote_timeout"] = settings.remote_timeout; + root["remote_timeout_en"] = settings.remote_timeout_enabled; root["shower_timer"] = settings.shower_timer; root["shower_alert"] = settings.shower_alert; root["shower_alert_coldshot"] = settings.shower_alert_coldshot; @@ -238,7 +240,7 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { prev = settings.shower_alert_trigger; settings.shower_alert_trigger = root["shower_alert_trigger"] | EMSESP_DEFAULT_SHOWER_ALERT_TRIGGER; check_flag(prev, settings.shower_alert_trigger, ChangeFlags::SHOWER); - prev = settings.shower_min_duration; + prev = settings.shower_min_duration; settings.shower_min_duration = root["shower_min_duration"] | EMSESP_DEFAULT_SHOWER_MIN_DURATION; check_flag(prev, settings.shower_min_duration, ChangeFlags::SHOWER); prev = settings.shower_alert_coldshot; @@ -300,9 +302,12 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { settings.trace_raw = root["trace_raw"] | EMSESP_DEFAULT_TRACELOG_RAW; EMSESP::trace_raw(settings.trace_raw); - settings.notoken_api = root["notoken_api"] | EMSESP_DEFAULT_NOTOKEN_API; - settings.solar_maxflow = root["solar_maxflow"] | EMSESP_DEFAULT_SOLAR_MAXFLOW; - settings.boiler_heatingoff = root["boiler_heatingoff"] | EMSESP_DEFAULT_BOILER_HEATINGOFF; + settings.notoken_api = root["notoken_api"] | EMSESP_DEFAULT_NOTOKEN_API; + settings.solar_maxflow = root["solar_maxflow"] | EMSESP_DEFAULT_SOLAR_MAXFLOW; + settings.boiler_heatingoff = root["boiler_heatingoff"] | EMSESP_DEFAULT_BOILER_HEATINGOFF; + settings.remote_timeout = root["remote_timeout"] | EMSESP_DEFAULT_REMOTE_TIMEOUT; + settings.remote_timeout_enabled = root["remote_timeout_en"] | EMSESP_DEFAULT_REMOTE_TIMEOUT_EN; + emsesp::Roomctrl::set_timeout(settings.remote_timeout_enabled ? settings.remote_timeout : 0); settings.fahrenheit = root["fahrenheit"]; EMSESP::system_.fahrenheit(settings.fahrenheit); diff --git a/src/web/WebSettingsService.h b/src/web/WebSettingsService.h index 72e95c0ea..c645127ff 100644 --- a/src/web/WebSettingsService.h +++ b/src/web/WebSettingsService.h @@ -34,11 +34,13 @@ class WebSettings { uint8_t tx_mode; uint8_t ems_bus_id; bool boiler_heatingoff; + uint8_t remote_timeout; + bool remote_timeout_enabled; bool shower_timer; bool shower_alert; - uint8_t shower_alert_trigger; // minutes + uint8_t shower_alert_trigger; // minutes uint8_t shower_alert_coldshot; // seconds - uint32_t shower_min_duration; // seconds + uint32_t shower_min_duration; // seconds bool syslog_enabled; int8_t syslog_level; // uuid::log::Level uint32_t syslog_mark_interval;