From 9b3d43d27f48b268b3b7b09fa02630d152e0cafc Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 22 Dec 2024 15:58:46 +0100 Subject: [PATCH 1/4] add min/max for #2288, own flag for CR11 #2295 --- src/device_library.h | 2 +- src/devices/thermostat.cpp | 42 +++++++++++++++++++++++++++++++++----- src/devices/thermostat.h | 1 + src/emsdevice.h | 1 + 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/device_library.h b/src/device_library.h index 4d4ebb457..fd3e0d17b 100644 --- a/src/device_library.h +++ b/src/device_library.h @@ -82,7 +82,7 @@ // Thermostat - Buderus/Nefit/Bosch specific - 0x17 / 0x10 / 0x18 / 0x19-0x1B for hc2-4 / 0x38 { 4, DeviceType::THERMOSTAT, "UI800, BC400", DeviceFlags::EMS_DEVICE_FLAG_BC400}, // 0x10 -{ 10, DeviceType::THERMOSTAT, "CR11", DeviceFlags::EMS_DEVICE_FLAG_RC100}, // 0x18 +{ 10, DeviceType::THERMOSTAT, "CR11", DeviceFlags::EMS_DEVICE_FLAG_CR11}, // 0x18 { 65, DeviceType::THERMOSTAT, "RC10", DeviceFlags::EMS_DEVICE_FLAG_RC20_N},// 0x17 { 67, DeviceType::THERMOSTAT, "RC30", DeviceFlags::EMS_DEVICE_FLAG_RC30_N},// 0x10 - based on RC35 { 77, DeviceType::THERMOSTAT, "RC20, Moduline 300", DeviceFlags::EMS_DEVICE_FLAG_RC20},// 0x17 diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index e2fce386f..fc4901db3 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -143,6 +143,14 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i register_telegram_type(monitor_typeids[i], "CRFMonitor", false, MAKE_PF_CB(process_CRFMonitor)); } + } else if (model == EMSdevice::EMS_DEVICE_FLAG_CR11) { + monitor_typeids = {0x02A5}; + set_typeids = {0x2B9}; + curve_typeids = {0x029B}; + register_telegram_type(monitor_typeids[0], "RC300Monitor", true, MAKE_PF_CB(process_CR11Monitor)); + register_telegram_type(set_typeids[0], "RC300Set", false, MAKE_PF_CB(process_RC300Set)); + register_telegram_type(curve_typeids[0], "RC300Curves", true, MAKE_PF_CB(process_RC300Curve)); + // RC300/RC100 variants } else if (isRC300() || (model == EMSdevice::EMS_DEVICE_FLAG_RC100)) { monitor_typeids = {0x02A5, 0x02A6, 0x02A7, 0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC}; @@ -491,6 +499,8 @@ uint8_t Thermostat::HeatingCircuit::get_mode() const { } else if (mode == 1) { return HeatingCircuit::Mode::OFF; } + } else if (model == EMSdevice::EMS_DEVICE_FLAG_CR11) { + return HeatingCircuit::Mode::MANUAL; } else if (model == EMSdevice::EMS_DEVICE_FLAG_BC400 || model == EMSdevice::EMS_DEVICE_FLAG_CR120) { if (mode_new == 0) { return HeatingCircuit::Mode::OFF; @@ -1053,6 +1063,21 @@ void Thermostat::process_CRFMonitor(std::shared_ptr telegram) { add_ha_climate(hc); } +// type 0x02A5 - data from CR11 +void Thermostat::process_CR11Monitor(std::shared_ptr telegram) { + auto hc = heating_circuit(telegram); + if (hc == nullptr) { + return; + } + + has_update(telegram, hc->roomTemp, 0); // is * 10 + has_update(hc->mode, 0); // set manual for CR11 + has_update(telegram, hc->selTemp, 6, 1); // is * 2, force as single byte + has_update(telegram, hc->targetflowtemp, 4); + + add_ha_climate(hc); +} + // type 0x02A5 - data from the Nefit RC1010/3000 thermostat (0x18) and RC300/310s on 0x10 // Rx: 10 0B FF 00 01 A5 80 00 01 30 23 00 30 28 01 E7 03 03 01 01 E7 02 33 00 00 11 01 03 FF FF 00 04 void Thermostat::process_RC300Monitor(std::shared_ptr telegram) { @@ -1096,7 +1121,7 @@ void Thermostat::process_RC300Monitor(std::shared_ptr telegram) // Thermostat(0x10) -> Me(0x0B), RC300Set(0x2B9), data: FF 2E 2A 26 1E 02 4E FF FF 00 1C 01 E1 20 01 0F 05 00 00 02 1F void Thermostat::process_RC300Set(std::shared_ptr telegram) { auto hc = heating_circuit(telegram); - if (hc == nullptr) { + if (hc == nullptr || model() == EMSdevice::EMS_DEVICE_FLAG_CR11) { return; } @@ -1112,9 +1137,6 @@ void Thermostat::process_RC300Set(std::shared_ptr telegram) { // set mode for CR120, BC400, https://github.com/emsesp/EMS-ESP32/discussions/1779 has_update(telegram, hc->mode_new, 21); // for BC400, CR120 has_bitupdate(telegram, hc->mode, 0, 0); // RC300, RC100 - if (hc->mode == EMS_VALUE_UINT8_NOTSET) { - has_update(hc->mode, 0); // set manual for CR11 - } has_update(telegram, hc->daytemp, 2); // is * 2 has_update(telegram, hc->nighttemp, 4); // is * 2 @@ -4485,6 +4507,8 @@ void Thermostat::register_device_values() { // Easy TC100 have no date/time, see issue #100, not sure about CT200, so leave it. register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dateTime_, DeviceValueType::STRING, FL_(dateTime), DeviceValueUOM::NONE); // can't set datetime break; + case EMSdevice::EMS_DEVICE_FLAG_CR11: + break; case EMSdevice::EMS_DEVICE_FLAG_CRF: default: register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dateTime_, DeviceValueType::STRING, FL_(dateTime), DeviceValueUOM::NONE); // can't set datetime @@ -4680,13 +4704,21 @@ void Thermostat::register_device_values_hc(std::shared_ptrmode, DeviceValueType::ENUM, FL_(enum_mode5), FL_(mode), DeviceValueUOM::NONE); register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype5), FL_(modetype), DeviceValueUOM::NONE); register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT8, FL_(targetflowtemp), DeviceValueUOM::DEGREES); break; + case EMSdevice::EMS_DEVICE_FLAG_CR11: + register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode), FL_(mode), DeviceValueUOM::NONE); + register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT8, FL_(targetflowtemp), DeviceValueUOM::DEGREES); + register_device_value( + tag, &hc->heatingtype, DeviceValueType::ENUM, FL_(enum_heatingtype), FL_(heatingtype), DeviceValueUOM::NONE, MAKE_CF_CB(set_heatingtype)); + break; case EMSdevice::EMS_DEVICE_FLAG_RC20: register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode)); register_device_value(tag, diff --git a/src/devices/thermostat.h b/src/devices/thermostat.h index d12821da1..a2792fd57 100644 --- a/src/devices/thermostat.h +++ b/src/devices/thermostat.h @@ -429,6 +429,7 @@ class Thermostat : public EMSdevice { void process_RC10Set(std::shared_ptr telegram); void process_RC10Set_2(std::shared_ptr telegram); void process_CRFMonitor(std::shared_ptr telegram); + void process_CR11Monitor(std::shared_ptr telegram); void process_RC300Monitor(std::shared_ptr telegram); void process_RC300Set(std::shared_ptr telegram); void process_RC300Set2(std::shared_ptr telegram); diff --git a/src/emsdevice.h b/src/emsdevice.h index 99f1a90c9..0804228fb 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -467,6 +467,7 @@ class EMSdevice { static constexpr uint8_t EMS_DEVICE_FLAG_BC400 = 14; // mostly like RC300, but some changes static constexpr uint8_t EMS_DEVICE_FLAG_R3000 = 15; // Rego3000, same as RC300 with different wwmodes static constexpr uint8_t EMS_DEVICE_FLAG_CR120 = 16; // mostly like RC300, but some changes + static constexpr uint8_t EMS_DEVICE_FLAG_CR11 = 17; // CRF200 only monitor uint8_t count_entities(); uint8_t count_entities_fav(); From ad89fe15b1366e7cc866bc6b9821d06c84d8e49f Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 23 Dec 2024 09:09:36 +0100 Subject: [PATCH 2/4] fix seltep command for CR11 #2295 --- src/devices/thermostat.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index fc4901db3..0014b4929 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -3748,6 +3748,9 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co break; } + } else if (model == EMSdevice::EMS_DEVICE_FLAG_CR11) { + offset = 10; // just seltemp write to manualtemp + } else if (isRC300() || (model == EMSdevice::EMS_DEVICE_FLAG_RC100)) { validate_typeid = set_typeids[hc->hc()]; switch (mode) { From 97925c47fd8d4db5e19507b525db8a6ff05c7dac Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 23 Dec 2024 12:12:25 +0100 Subject: [PATCH 3/4] remove broken ntp_time --- interface/src/app/status/Status.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/app/status/Status.tsx b/interface/src/app/status/Status.tsx index a3ce5e18a..bc468fc62 100644 --- a/interface/src/app/status/Status.tsx +++ b/interface/src/app/status/Status.tsx @@ -38,7 +38,6 @@ import { AuthenticatedContext } from 'contexts/authentication'; import { useI18nContext } from 'i18n/i18n-react'; import { NTPSyncStatus, NetworkConnectionStatus } from 'types'; import { useInterval } from 'utils'; -import { formatDateTime } from 'utils/time'; import RestartMonitor from './RestartMonitor'; @@ -139,7 +138,7 @@ const SystemStatus = () => { case NTPSyncStatus.NTP_INACTIVE: return LL.INACTIVE(0); case NTPSyncStatus.NTP_ACTIVE: - return LL.ACTIVE() + ' (' + formatDateTime(data.ntp_time ?? '') + ')'; + return LL.ACTIVE(); default: return LL.UNKNOWN(); } From 4c69c9e445ef01168f70d5416afe04b8f1fe3a98 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 23 Dec 2024 13:03:59 +0100 Subject: [PATCH 4/4] fix show ntp_time (as local time) --- interface/src/app/status/Status.tsx | 3 ++- src/web/WebStatusService.cpp | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/interface/src/app/status/Status.tsx b/interface/src/app/status/Status.tsx index bc468fc62..7477d07d1 100644 --- a/interface/src/app/status/Status.tsx +++ b/interface/src/app/status/Status.tsx @@ -38,6 +38,7 @@ import { AuthenticatedContext } from 'contexts/authentication'; import { useI18nContext } from 'i18n/i18n-react'; import { NTPSyncStatus, NetworkConnectionStatus } from 'types'; import { useInterval } from 'utils'; +import { formatDateTime } from 'utils/time'; import RestartMonitor from './RestartMonitor'; @@ -138,7 +139,7 @@ const SystemStatus = () => { case NTPSyncStatus.NTP_INACTIVE: return LL.INACTIVE(0); case NTPSyncStatus.NTP_ACTIVE: - return LL.ACTIVE(); + return LL.ACTIVE() + (data.ntp_time !== undefined) ? ' (' + formatDateTime(data.ntp_time) + ')' : ''; default: return LL.UNKNOWN(); } diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp index 3710ab374..a93f39f5b 100644 --- a/src/web/WebStatusService.cpp +++ b/src/web/WebStatusService.cpp @@ -68,6 +68,12 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) { } return 0; }(); + time_t now = time(nullptr); + if (now > 1500000000L) { + char t[25]; + strftime(t, sizeof(t), "%FT%T", localtime(&now)); + root["ntp_time"] = t; + } #endif root["ap_status"] = EMSESP::esp8266React.apStatus();