From b097e372e462afd5623083ea3d2e3b3ee76e187b Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sat, 22 Mar 2025 11:39:48 +0100 Subject: [PATCH 1/9] update pkg and libs --- interface/package.json | 6 ++--- interface/yarn.lock | 55 ++++++++++++++++++++++++------------------ platformio.ini | 4 +-- 3 files changed, 37 insertions(+), 28 deletions(-) diff --git a/interface/package.json b/interface/package.json index 472ba1067..768f03c74 100644 --- a/interface/package.json +++ b/interface/package.json @@ -42,16 +42,16 @@ }, "devDependencies": { "@babel/core": "^7.26.10", - "@eslint/js": "^9.22.0", + "@eslint/js": "^9.23.0", "@preact/compat": "^18.3.1", "@preact/preset-vite": "^2.10.1", "@trivago/prettier-plugin-sort-imports": "^5.2.2", "@types/formidable": "^3", - "@types/node": "^22.13.10", + "@types/node": "^22.13.11", "@types/react": "^19.0.12", "@types/react-dom": "^19.0.4", "concurrently": "^9.1.2", - "eslint": "^9.22.0", + "eslint": "^9.23.0", "eslint-config-prettier": "^10.1.1", "formidable": "^3.5.2", "prettier": "^3.5.3", diff --git a/interface/yarn.lock b/interface/yarn.lock index 59eec0d86..8ee3b5fce 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -620,10 +620,10 @@ __metadata: languageName: node linkType: hard -"@eslint/config-helpers@npm:^0.1.0": - version: 0.1.0 - resolution: "@eslint/config-helpers@npm:0.1.0" - checksum: 10c0/3562b5325f42740fc83b0b92b7d13a61b383f8db064915143eec36184f09a09fad73eca6c2955ab6c248b0d04fa03c140f9af2f2c4c06770781a6b79f300a01e +"@eslint/config-helpers@npm:^0.2.0": + version: 0.2.0 + resolution: "@eslint/config-helpers@npm:0.2.0" + checksum: 10c0/743a64653e13177029108f57ab47460ded08e3412c86216a14b7e8ab2dc79c2b64be45bf55c5ef29f83692a707dc34cf1e9217e4b8b4b272a0d9b691fdaf6a2a languageName: node linkType: hard @@ -636,9 +636,9 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^3.3.0": - version: 3.3.0 - resolution: "@eslint/eslintrc@npm:3.3.0" +"@eslint/eslintrc@npm:^3.3.1": + version: 3.3.1 + resolution: "@eslint/eslintrc@npm:3.3.1" dependencies: ajv: "npm:^6.12.4" debug: "npm:^4.3.2" @@ -649,14 +649,14 @@ __metadata: js-yaml: "npm:^4.1.0" minimatch: "npm:^3.1.2" strip-json-comments: "npm:^3.1.1" - checksum: 10c0/215de990231b31e2fe6458f225d8cea0f5c781d3ecb0b7920703501f8cd21b3101fc5ef2f0d4f9a38865d36647b983e0e8ce8bf12fd2bcdd227fc48a5b1a43be + checksum: 10c0/b0e63f3bc5cce4555f791a4e487bf999173fcf27c65e1ab6e7d63634d8a43b33c3693e79f192cbff486d7df1be8ebb2bd2edc6e70ddd486cbfa84a359a3e3b41 languageName: node linkType: hard -"@eslint/js@npm:9.22.0, @eslint/js@npm:^9.22.0": - version: 9.22.0 - resolution: "@eslint/js@npm:9.22.0" - checksum: 10c0/5bcd009bb579dc6c6ed760703bdd741e08a48cd9decd677aa2cf67fe66236658cb09a00185a0369f3904e5cffba9e6e0f2ff4d9ba4fdf598fcd81d34c49213a5 +"@eslint/js@npm:9.23.0, @eslint/js@npm:^9.23.0": + version: 9.23.0 + resolution: "@eslint/js@npm:9.23.0" + checksum: 10c0/4e70869372b6325389e0ab51cac6d3062689807d1cef2c3434857571422ce11dde3c62777af85c382b9f94d937127598d605d2086787f08611351bf99faded81 languageName: node linkType: hard @@ -1406,7 +1406,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^22.13.10": +"@types/node@npm:*": version: 22.13.10 resolution: "@types/node@npm:22.13.10" dependencies: @@ -1415,6 +1415,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^22.13.11": + version: 22.13.11 + resolution: "@types/node@npm:22.13.11" + dependencies: + undici-types: "npm:~6.20.0" + checksum: 10c0/f6ee33d36372242535c38640fe7550a6640d8a775ec19b55bfc11775b521cba072d892ca92a912332ce01b317293d645c1bf767f3f882ec719f2404a3d2a5b96 + languageName: node + linkType: hard + "@types/parse-json@npm:^4.0.0": version: 4.0.2 resolution: "@types/parse-json@npm:4.0.2" @@ -1594,7 +1603,7 @@ __metadata: "@babel/core": "npm:^7.26.10" "@emotion/react": "npm:^11.14.0" "@emotion/styled": "npm:^11.14.0" - "@eslint/js": "npm:^9.22.0" + "@eslint/js": "npm:^9.23.0" "@mui/icons-material": "npm:^6.4.8" "@mui/material": "npm:^6.4.8" "@preact/compat": "npm:^18.3.1" @@ -1602,13 +1611,13 @@ __metadata: "@table-library/react-table-library": "npm:4.1.12" "@trivago/prettier-plugin-sort-imports": "npm:^5.2.2" "@types/formidable": "npm:^3" - "@types/node": "npm:^22.13.10" + "@types/node": "npm:^22.13.11" "@types/react": "npm:^19.0.12" "@types/react-dom": "npm:^19.0.4" alova: "npm:3.2.10" async-validator: "npm:^4.2.5" concurrently: "npm:^9.1.2" - eslint: "npm:^9.22.0" + eslint: "npm:^9.23.0" eslint-config-prettier: "npm:^10.1.1" formidable: "npm:^3.5.2" jwt-decode: "npm:^4.0.0" @@ -3053,17 +3062,17 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^9.22.0": - version: 9.22.0 - resolution: "eslint@npm:9.22.0" +"eslint@npm:^9.23.0": + version: 9.23.0 + resolution: "eslint@npm:9.23.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.12.1" "@eslint/config-array": "npm:^0.19.2" - "@eslint/config-helpers": "npm:^0.1.0" + "@eslint/config-helpers": "npm:^0.2.0" "@eslint/core": "npm:^0.12.0" - "@eslint/eslintrc": "npm:^3.3.0" - "@eslint/js": "npm:9.22.0" + "@eslint/eslintrc": "npm:^3.3.1" + "@eslint/js": "npm:9.23.0" "@eslint/plugin-kit": "npm:^0.2.7" "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" @@ -3099,7 +3108,7 @@ __metadata: optional: true bin: eslint: bin/eslint.js - checksum: 10c0/7b5ab6f2365971c16efe97349565f75d8343347562fb23f12734c6ab2cd5e35301373a0d51e194789ddcfdfca21db7b62ff481b03d524b8169896c305b65ff48 + checksum: 10c0/9616c308dfa8d09db8ae51019c87d5d05933742214531b077bd6ab618baab3bec7938256c14dcad4dc47f5ba93feb0bc5e089f68799f076374ddea21b6a9be45 languageName: node linkType: hard diff --git a/platformio.ini b/platformio.ini index bab9c03a7..21667c4c3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -126,8 +126,8 @@ build_type = release board_build.filesystem = littlefs lib_deps = bblanchon/ArduinoJson @ 7.3.1 - ESP32Async/AsyncTCP @ 3.3.7 - ESP32Async/ESPAsyncWebServer @ 3.7.3 + ESP32Async/AsyncTCP @ 3.3.8 + ESP32Async/ESPAsyncWebServer @ 3.7.4 https://github.com/emsesp/EMS-ESP-Modules.git @ 1.0.5 ; From 1da08633ece0abcfd2a92514c2fab2e264ab3d7a Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sat, 22 Mar 2025 11:41:00 +0100 Subject: [PATCH 2/9] add scheduler random function (rnd(x) => random 0..x) --- src/core/shuntingYard.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/core/shuntingYard.hpp b/src/core/shuntingYard.hpp index 659978ba3..96e520636 100644 --- a/src/core/shuntingYard.hpp +++ b/src/core/shuntingYard.hpp @@ -102,6 +102,9 @@ std::deque exprToTokens(const std::string & expr) { } else if (strncmp(p, "hex", 3) == 0) { p += 2; tokens.emplace_back(Token::Type::Unary, "h", 5); + } else if (strncmp(p, "rnd", 3) == 0) { + p += 2; + tokens.emplace_back(Token::Type::Unary, "d", 5); } else if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p == '_') || (*p & 0x80)) { const auto * b = p; while ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p == '_') || (*p & 0x80)) { @@ -526,6 +529,9 @@ std::string calculate(const std::string & expr) { case 'x': stack.push_back(to_hex(static_cast(rhd))); break; + case 'd': + stack.push_back(to_string(rhd * esp_random() / UINT32_MAX)); + break; } } break; case Token::Type::Compare: { From 3796fb80271371e9d80957cb888f1c49b4ba156a Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sat, 22 Mar 2025 11:41:37 +0100 Subject: [PATCH 3/9] add analog sensor NTC and RGB-Led, dev29 --- CHANGELOG_LATEST.md | 1 + .../src/app/main/SensorsAnalogDialog.tsx | 34 +++++++ interface/src/app/main/types.ts | 10 ++- src/core/analogsensor.cpp | 90 ++++++++++++++++--- src/core/analogsensor.h | 13 ++- src/core/locale_common.h | 3 +- src/version.h | 2 +- src/web/WebDataService.cpp | 4 +- 8 files changed, 137 insertions(+), 20 deletions(-) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 48cb410d2..69c70d15e 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -20,6 +20,7 @@ For more details go to [docs.emsesp.org](https://docs.emsesp.org/). - support nested conditions in scheduler [#2451](https://github.com/emsesp/EMS-ESP32/issues/2451) - allow mixed case in scheduler expressions [#2457](https://github.com/emsesp/EMS-ESP32/issues/2457) - Suprapur-o [#2470](https://github.com/emsesp/EMS-ESP32/issues/2470) +- analogsensor types: NTC and RGB-Led ## Fixed diff --git a/interface/src/app/main/SensorsAnalogDialog.tsx b/interface/src/app/main/SensorsAnalogDialog.tsx index 274b4eb6a..d82601d5e 100644 --- a/interface/src/app/main/SensorsAnalogDialog.tsx +++ b/interface/src/app/main/SensorsAnalogDialog.tsx @@ -171,6 +171,27 @@ const SensorsAnalogDialog = ({ /> )} + {editItem.t === AnalogType.NTC && ( + + °C + ) + }, + htmlInput: { min: '-20', max: '20', step: '0.1' } + }} + /> + + )} {editItem.t === AnalogType.COUNTER && ( )} + {editItem.t === AnalogType.RGB && ( + + + + )} {editItem.t >= AnalogType.COUNTER && editItem.t <= AnalogType.RATE && ( ; diff --git a/src/core/analogsensor.cpp b/src/core/analogsensor.cpp index 49ff30d79..067f2b334 100644 --- a/src/core/analogsensor.cpp +++ b/src/core/analogsensor.cpp @@ -30,7 +30,7 @@ void AnalogSensor::start() { return; } - analogSetAttenuation(ADC_2_5db); // for all channels 1.5V + analogSetAttenuation(ADC_11db); // for all channels 3.3V LOG_INFO("Starting Analog Sensor service"); @@ -110,13 +110,15 @@ void AnalogSensor::reload(bool get_nvs) { sensors_.back().set_value(0); // reset value only for new sensors } } - if (sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT) { + if (sensor.type == AnalogType::COUNTER || (sensor.type >= AnalogType::DIGITAL_OUT && sensor.type <= AnalogType::PWM_2) + || sensor.type == AnalogType::RGB) { Command::add( EMSdevice::DeviceType::ANALOGSENSOR, sensor.name.c_str(), [&](const char * value, const int8_t id) { return command_setvalue(value, sensor.gpio); }, sensor.type == AnalogType::COUNTER ? FL_(counter) : sensor.type == AnalogType::DIGITAL_OUT ? FL_(digital_out) + : sensor.type == AnalogType::RGB ? FL_(RGB) : FL_(pwm), CommandFlag::ADMIN_ONLY); } @@ -157,6 +159,10 @@ void AnalogSensor::reload(bool get_nvs) { // analogSetPinAttenuation does not work with analogReadMilliVolts sensor.analog_ = 0; // initialize sensor.last_reading_ = 0; + } else if (sensor.type() == AnalogType::NTC) { + LOG_DEBUG("NTC Sensor on GPIO %02d", sensor.gpio()); + // analogSetPinAttenuation(sensor.gpio(), ADC_11db); //does not work with analogReadMilliVolts + sensor.set_uom(DeviceValueUOM::DEGREES); } else if (sensor.type() == AnalogType::COUNTER) { LOG_DEBUG("I/O Counter on GPIO %02d", sensor.gpio()); pinMode(sensor.gpio(), INPUT_PULLUP); @@ -183,6 +189,18 @@ void AnalogSensor::reload(bool get_nvs) { sensor.polltime_ = 0; sensor.poll_ = digitalRead(sensor.gpio()); publish_sensor(sensor); + } else if (sensor.type() == AnalogType::RGB) { + LOG_DEBUG("RGB on GPIO %02d", sensor.gpio()); + uint32_t v = sensor.value(); + uint8_t r = v / 10000; + uint8_t g = (v - r * 10000) / 100; + uint8_t b = v % 100; +#if ESP_ARDUINO_VERSION_MAJOR < 3 + neopixelWrite(sensor.gpio(), 2 * r, 2 * g, 2 * b); +#else + rgbLedWrite(sensor.gpio(), 2 * r, 2 * g, 2 * b); +#endif + LOG_DEBUG("RGB set to %d, %d, %d", r, g, b); } else if (sensor.type() == AnalogType::DIGITAL_OUT) { LOG_DEBUG("Digital Write on GPIO %02d", sensor.gpio()); pinMode(sensor.gpio(), OUTPUT); @@ -272,6 +290,23 @@ void AnalogSensor::measure() { changed_ = true; publish_sensor(sensor); } + } else if (sensor.type() == AnalogType::NTC) { + auto a = analogReadMilliVolts(sensor.gpio()); + if (!sensor.analog_) { // init first time + sensor.analog_ = a; + sensor.sum_ = a * 16; + } else { // simple moving average filter + sensor.sum_ = (sensor.sum_ * 15 + a * 16) / 16; + sensor.analog_ = sensor.sum_ / 16; + } + if (sensor.analog_ > 0 && sensor.analog_ < 3300 && (sensor.last_reading_ + 1 < sensor.analog_ || sensor.last_reading_ > sensor.analog_ + 1)) { + sensor.set_value(sensor.offset() + 1 / (1 / T25 + log((double)sensor.analog_ / (3300 - sensor.analog_) * (Rt / R0)) / Beta) + - T0); // Temperature in Celsius + sensor.last_reading_ = sensor.analog_; + sensorreads_++; + changed_ = true; + publish_sensor(sensor); + } } } } @@ -350,12 +385,14 @@ bool AnalogSensor::update(uint8_t gpio, std::string & name, double offset, doubl bool found_sensor = false; EMSESP::webCustomizationService.update([&](WebCustomization & settings) { for (auto & AnalogCustomization : settings.analogCustomizations) { - if (AnalogCustomization.type == AnalogType::COUNTER || AnalogCustomization.type >= AnalogType::DIGITAL_OUT) { + if (AnalogCustomization.type == AnalogType::COUNTER + || (AnalogCustomization.type >= AnalogType::DIGITAL_OUT && AnalogCustomization.type <= AnalogType::PWM_2) + || AnalogCustomization.type >= AnalogType::RGB) { Command::erase_command(EMSdevice::DeviceType::ANALOGSENSOR, AnalogCustomization.name.c_str()); } if (name.empty()) { char n[20]; - snprintf(n, sizeof(n), "%s_%02d", FL_(AnalogTypeName)[type], gpio); + snprintf(n, sizeof(n), "%s_%02d", FL_(list_sensortype)[type], gpio); name = n; } if (AnalogCustomization.gpio == gpio) { @@ -430,8 +467,13 @@ void AnalogSensor::publish_sensor(const Sensor & sensor) const { } else { snprintf(topic, sizeof(topic), "%s%s/%s", F_(analogsensor), "_data", sensor.name().c_str()); } - char payload[10]; - Mqtt::queue_publish(topic, Helpers::render_value(payload, sensor.value(), 2)); // always publish as doubles + char result[12]; + if (sensor.type() == AnalogType::DIGITAL_IN || sensor.type() == AnalogType::DIGITAL_OUT) { + Helpers::render_boolean(result, sensor.value() != 0); + } else { + Helpers::render_value(result, sensor.value(), 2); // double + } + Mqtt::queue_publish(topic, result); // always publish as doubles } char cmd[COMMAND_MAX_LENGTH]; snprintf(cmd, sizeof(cmd), "%s/%s", F_(analogsensor), sensor.name().c_str()); @@ -455,7 +497,9 @@ void AnalogSensor::remove_ha_topic(const int8_t type, const uint8_t gpio) const snprintf(topic, sizeof(topic), "switch/%s/%s_%02d/config", Mqtt::basename().c_str(), F_(analogsensor), gpio); } else if (type == AnalogType::DIGITAL_OUT) { // DAC snprintf(topic, sizeof(topic), "number/%s/%s_%02d/config", Mqtt::basename().c_str(), F_(analogsensor), gpio); - } else if (type >= AnalogType::PWM_0) { + } else if (type >= AnalogType::PWM_0 && type <= AnalogType::PWM_2) { + snprintf(topic, sizeof(topic), "number/%s/%s_%02d/config", Mqtt::basename().c_str(), F_(analogsensor), gpio); + } else if (type >= AnalogType::RGB) { snprintf(topic, sizeof(topic), "number/%s/%s_%02d/config", Mqtt::basename().c_str(), F_(analogsensor), gpio); } else if (type == AnalogType::DIGITAL_IN) { snprintf(topic, sizeof(topic), "binary_sensor/%s/%s_%02d/config", Mqtt::basename().c_str(), F_(analogsensor), gpio); @@ -495,6 +539,8 @@ void AnalogSensor::publish_values(const bool force) { case AnalogType::PWM_0: case AnalogType::PWM_1: case AnalogType::PWM_2: + case AnalogType::RGB: + case AnalogType::NTC: dataSensor["value"] = serialized(Helpers::render_value(s, sensor.value(), 2)); // double break; case AnalogType::DIGITAL_IN: @@ -597,6 +643,14 @@ void AnalogSensor::publish_values(const bool force) { config["max"] = 100; config["mode"] = "box"; // auto, slider or box config["step"] = 0.1; + } else if (sensor.type() == AnalogType::RGB) { + snprintf(topic, sizeof(topic), "number/%s/%s_%02d/config", Mqtt::basename().c_str(), F_(analogsensor), sensor.gpio()); + snprintf(command_topic, sizeof(command_topic), "%s/%s/%s", Mqtt::base().c_str(), F_(analogsensor), sensor.name().c_str()); + config["cmd_t"] = command_topic; + config["min"] = 0; + config["max"] = 999999; + config["mode"] = "box"; // auto, slider or box + config["step"] = 1; } else if (sensor.type() == AnalogType::COUNTER) { snprintf(topic, sizeof(topic), "sensor/%s/%s_%02d/config", Mqtt::basename().c_str(), F_(analogsensor), sensor.gpio()); snprintf(command_topic, sizeof(command_topic), "%s/%s/%s", Mqtt::base().c_str(), F_(analogsensor), sensor.name().c_str()); @@ -679,8 +733,9 @@ void AnalogSensor::get_value_json(JsonObject output, const Sensor & sensor) { output["analog"] = FL_(list_sensortype)[sensor.type()]; output["value"] = sensor.value(); output["readable"] = true; - output["writeable"] = sensor.type() == AnalogType::COUNTER || (sensor.type() >= AnalogType::DIGITAL_OUT && sensor.type() <= AnalogType::PWM_2); - output["visible"] = true; + output["writeable"] = sensor.type() == AnalogType::COUNTER || sensor.type() >= AnalogType::RGB + || (sensor.type() >= AnalogType::DIGITAL_OUT && sensor.type() <= AnalogType::PWM_2); + output["visible"] = true; if (sensor.type() == AnalogType::COUNTER) { output["min"] = 0; output["max"] = 4000000; @@ -733,10 +788,10 @@ bool AnalogSensor::command_setvalue(const char * value, const int8_t gpio) { double oldoffset = sensor.offset(); if (sensor.type() == AnalogType::COUNTER) { if (val < 0 || value[0] == '+') { // sign corrects values - sensor.set_offset(sensor.value() + val); + // sensor.set_offset(sensor.value() + val); sensor.set_value(sensor.value() + val); } else { // positive values are set - sensor.set_offset(val); + // sensor.set_offset(val); sensor.set_value(val); } if (oldoffset != sensor.offset() && sensor.offset() != EMSESP::nvs_.getDouble(sensor.name().c_str())) { @@ -744,6 +799,19 @@ bool AnalogSensor::command_setvalue(const char * value, const int8_t gpio) { } } else if (sensor.type() == AnalogType::ADC) { sensor.set_offset(val); + } else if (sensor.type() == AnalogType::RGB) { + uint32_t v = val; + sensor.set_offset(v); + sensor.set_value(v); + uint8_t r = v / 10000; + uint8_t g = (v - r * 10000) / 100; + uint8_t b = v % 100; +#if ESP_ARDUINO_VERSION_MAJOR < 3 + neopixelWrite(sensor.gpio(), 2 * r, 2 * g, 2 * b); +#else + rgbLedWrite(sensor.gpio(), 2 * r, 2 * g, 2 * b); +#endif + LOG_DEBUG("RGB set to %d, %d, %d", r, g, b); } else if (sensor.type() == AnalogType::DIGITAL_OUT) { uint8_t v = val; #if CONFIG_IDF_TARGET_ESP32 diff --git a/src/core/analogsensor.h b/src/core/analogsensor.h index cc8317543..0a14f0da0 100644 --- a/src/core/analogsensor.h +++ b/src/core/analogsensor.h @@ -27,8 +27,8 @@ namespace emsesp { -// names, same order as AnalogType -MAKE_ENUM_FIXED(AnalogTypeName, "disabled", "dig_in", "counter", "adc", "timer", "rate", "dig_out", "pwm0", "pwm1", "pwm2") +// names, same order as AnalogType, see list_sensortype in local_common.h +// MAKE_ENUM_FIXED(AnalogTypeName, "disabled", "dig_in", "counter", "adc", "timer", "rate", "dig_out", "pwm0", "pwm1", "pwm2") class AnalogSensor { public: @@ -122,7 +122,9 @@ class AnalogSensor { DIGITAL_OUT = 6, PWM_0 = 7, PWM_1 = 8, - PWM_2 = 9 + PWM_2 = 9, + NTC = 10, + RGB = 11 }; void start(); @@ -166,6 +168,11 @@ class AnalogSensor { void store_counters(); private: + static constexpr double Beta = 3380; + static constexpr double T0 = 273.15; + static constexpr double T25 = 298.15; + static constexpr double R0 = 10000; + static constexpr double Rt = 10000; static constexpr uint8_t MAX_SENSORS = 20; static constexpr uint32_t MEASURE_ANALOG_INTERVAL = 500; diff --git a/src/core/locale_common.h b/src/core/locale_common.h index 05b4c8cbd..a3cca81ce 100644 --- a/src/core/locale_common.h +++ b/src/core/locale_common.h @@ -276,7 +276,8 @@ MAKE_ENUM_FIXED(list_syslog_level, "off", "emerg", "alert", "crit", "error", "wa // sensors MAKE_ENUM_FIXED(counter, "counter") MAKE_ENUM_FIXED(digital_out, "digital_out") -MAKE_ENUM_FIXED(list_sensortype, "disabled", "digital in", "counter", "adc", "timer", "rate", "digital out", "pwm 0", "pwm 1", "pwm 2") +MAKE_ENUM_FIXED(RGB, "RGB") +MAKE_ENUM_FIXED(list_sensortype, "disabled", "digital in", "counter", "adc", "timer", "rate", "digital out", "pwm 0", "pwm 1", "pwm 2", "NTC Temp", "RGB Led") // watch MAKE_ENUM_FIXED(list_watch, "off", "on", "raw", "unknown") diff --git a/src/version.h b/src/version.h index 4ccc82558..cc8ff4cca 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.7.2-dev.28" +#define EMSESP_APP_VERSION "3.7.2-dev.29" diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index 031c246a5..13489e7c8 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -446,7 +446,9 @@ void WebDataService::dashboard_data(AsyncWebServerRequest * request) { dv["v"] = Helpers::transformNumFloat(sensor.value()); dv["u"] = sensor.uom(); } - if (sensor.type() == AnalogSensor::AnalogType::COUNTER || sensor.type() >= AnalogSensor::AnalogType::DIGITAL_OUT) { + if (sensor.type() == AnalogSensor::AnalogType::COUNTER + || (sensor.type() >= AnalogSensor::AnalogType::DIGITAL_OUT && sensor.type() <= AnalogSensor::AnalogType::PWM_2) + || sensor.type() == AnalogSensor::AnalogType::RGB) { dv["c"] = sensor.name(); } } From 4564e0b828301067bb47d07930356f565708405d Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 23 Mar 2025 10:06:49 +0100 Subject: [PATCH 4/9] fix printable chars in lastcode --- src/devices/boiler.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index 5f528888e..56421036e 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -1848,10 +1848,11 @@ void Boiler::process_UBAErrorMessage(std::shared_ptr telegram) { uint32_t date = (year - 2000) * 535680UL + month * 44640UL + day * 1440UL + hour * 60 + min + duration; // check valid https://github.com/emsesp/EMS-ESP32/issues/2189 if (day == 0 || day > 31 || month == 0 || month > 12 || !std::isprint(code[0]) || !std::isprint(code[1])) { - if (!lastCodeDate_) { + if (!lastCodeDate_ && std::isprint(code[0]) && std::isprint(code[1])) { char newCode[sizeof(lastCode_)]; snprintf(newCode, sizeof(lastCode_), "%s(%d)", code, codeNo); has_update(lastCode_, newCode, sizeof(lastCode_)); + lastCodeDate_ = 1; } return; } From 74c63bf17eaf92566b0f4a0996fe4abe668dc39e Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 23 Mar 2025 10:07:22 +0100 Subject: [PATCH 5/9] set HMC310 to BC400 compatible --- src/core/emsesp.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/emsesp.cpp b/src/core/emsesp.cpp index f4b11df0d..2b071d536 100644 --- a/src/core/emsesp.cpp +++ b/src/core/emsesp.cpp @@ -1314,6 +1314,10 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const flags = DeviceFlags::EMS_DEVICE_FLAG_CR120; default_name = "CR120"; } + if (product_id == 158 && strncmp(version,"73",2) == 0) { + flags = DeviceFlags::EMS_DEVICE_FLAG_BC400; + default_name = "HMC310"; + } // empty reply to version, read a generic device from database if (product_id == 0) { From 11b7e1f86ebb4c425ed0671e1aaa34786e1f345f Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 24 Mar 2025 18:44:02 +0100 Subject: [PATCH 6/9] update pkg --- interface/package.json | 6 +- interface/yarn.lock | 139 ++++++++++++++++++++++------------------- 2 files changed, 77 insertions(+), 68 deletions(-) diff --git a/interface/package.json b/interface/package.json index 768f03c74..8a85c05fa 100644 --- a/interface/package.json +++ b/interface/package.json @@ -47,7 +47,7 @@ "@preact/preset-vite": "^2.10.1", "@trivago/prettier-plugin-sort-imports": "^5.2.2", "@types/formidable": "^3", - "@types/node": "^22.13.11", + "@types/node": "^22.13.13", "@types/react": "^19.0.12", "@types/react-dom": "^19.0.4", "concurrently": "^9.1.2", @@ -57,8 +57,8 @@ "prettier": "^3.5.3", "rollup-plugin-visualizer": "^5.14.0", "terser": "^5.39.0", - "typescript-eslint": "8.27.0", - "vite": "^6.2.2", + "typescript-eslint": "8.28.0", + "vite": "^6.2.3", "vite-plugin-imagemin": "^0.6.1", "vite-tsconfig-paths": "^5.1.4" }, diff --git a/interface/yarn.lock b/interface/yarn.lock index 04f3c0cc0..d6733d27f 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -1406,7 +1406,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^22.13.11": +"@types/node@npm:*": version: 22.13.11 resolution: "@types/node@npm:22.13.11" dependencies: @@ -1415,6 +1415,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^22.13.13": + version: 22.13.13 + resolution: "@types/node@npm:22.13.13" + dependencies: + undici-types: "npm:~6.20.0" + checksum: 10c0/daf792ba5dcff1316abf4b33680f94b792f8d54d6ae495efc8929531e0ba1284a248d29aab117d2259f9280284d986ad5799b193b0516e2b926d713aab835f7d + languageName: node + linkType: hard + "@types/parse-json@npm:^4.0.0": version: 4.0.2 resolution: "@types/parse-json@npm:4.0.2" @@ -1474,15 +1483,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.27.0": - version: 8.27.0 - resolution: "@typescript-eslint/eslint-plugin@npm:8.27.0" +"@typescript-eslint/eslint-plugin@npm:8.28.0": + version: 8.28.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.28.0" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.27.0" - "@typescript-eslint/type-utils": "npm:8.27.0" - "@typescript-eslint/utils": "npm:8.27.0" - "@typescript-eslint/visitor-keys": "npm:8.27.0" + "@typescript-eslint/scope-manager": "npm:8.28.0" + "@typescript-eslint/type-utils": "npm:8.28.0" + "@typescript-eslint/utils": "npm:8.28.0" + "@typescript-eslint/visitor-keys": "npm:8.28.0" graphemer: "npm:^1.4.0" ignore: "npm:^5.3.1" natural-compare: "npm:^1.4.0" @@ -1491,64 +1500,64 @@ __metadata: "@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/95bbab011bfe51ca657ff346e4c6cac25652c88e5188a5e74d14372dba45c3d7aa713f4c90f80ebc885d77a8be89e131e8b77c096145c90da6c251a475b125fc + checksum: 10c0/f01b7d231b01ec2c1cc7c40599ddceb329532f2876664a39dec9d25c0aed4cfdbef3ec07f26bac357df000d798f652af6fdb6a2481b6120e43bfa38f7c7a7c48 languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.27.0": - version: 8.27.0 - resolution: "@typescript-eslint/parser@npm:8.27.0" +"@typescript-eslint/parser@npm:8.28.0": + version: 8.28.0 + resolution: "@typescript-eslint/parser@npm:8.28.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.27.0" - "@typescript-eslint/types": "npm:8.27.0" - "@typescript-eslint/typescript-estree": "npm:8.27.0" - "@typescript-eslint/visitor-keys": "npm:8.27.0" + "@typescript-eslint/scope-manager": "npm:8.28.0" + "@typescript-eslint/types": "npm:8.28.0" + "@typescript-eslint/typescript-estree": "npm:8.28.0" + "@typescript-eslint/visitor-keys": "npm:8.28.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/2ada98167ca5a474544fada7658d7c8d54ea4dfdd692e3d30d18b5531e50d7308a5b09d23dca651f9fe841f96075ccd18643431f4b61d0e4e7e7ccde888258e8 + checksum: 10c0/4bde6887bbf3fe031c01e46db90f9f384a8cac2e67c2972b113a62d607db75e01db943601279aac847b9187960a038981814042cb02fd5aa27ea4613028f9313 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.27.0": - version: 8.27.0 - resolution: "@typescript-eslint/scope-manager@npm:8.27.0" +"@typescript-eslint/scope-manager@npm:8.28.0": + version: 8.28.0 + resolution: "@typescript-eslint/scope-manager@npm:8.28.0" dependencies: - "@typescript-eslint/types": "npm:8.27.0" - "@typescript-eslint/visitor-keys": "npm:8.27.0" - checksum: 10c0/d87daeffb81f4e70f168c38f01c667713bda71c4545e28fcdf0792378fb3df171894ef77854c5c1a5e5a22c784ee1ccea2dd856b5baf825840710a6a74c14ac9 + "@typescript-eslint/types": "npm:8.28.0" + "@typescript-eslint/visitor-keys": "npm:8.28.0" + checksum: 10c0/f3bd76b3f54e60f1efe108b233b2d818e44ecf0dc6422cc296542f784826caf3c66d51b8acc83d8c354980bd201e1d9aa1ea01011de96e0613d320c00e40ccfd languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.27.0": - version: 8.27.0 - resolution: "@typescript-eslint/type-utils@npm:8.27.0" +"@typescript-eslint/type-utils@npm:8.28.0": + version: 8.28.0 + resolution: "@typescript-eslint/type-utils@npm:8.28.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:8.27.0" - "@typescript-eslint/utils": "npm:8.27.0" + "@typescript-eslint/typescript-estree": "npm:8.28.0" + "@typescript-eslint/utils": "npm:8.28.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^2.0.1" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/f38cdc660ebcb3b71496182b9ea52301ab08a4f062558aa7061a5f0b759ae3e8f68ae250a29e74251cb52c6c56733d7dabed7002b993544cbe0933bb75d67a57 + checksum: 10c0/b8936edc2153bf794efba39bfb06393a228217830051767360f4b691fed7c82f3831c4fc6deac6d78b90a58596e61f866c17eaee9dd793c3efda3ebdcf5a71d8 languageName: node linkType: hard -"@typescript-eslint/types@npm:8.27.0": - version: 8.27.0 - resolution: "@typescript-eslint/types@npm:8.27.0" - checksum: 10c0/9c5f2ba816a9baea5982feeadebe4d19f4df77ddb025a7b2307f9e1e6914076b63cbad81f7f915814e64b4d915052cf27bd79ce3e5a831340cb5ab244133941b +"@typescript-eslint/types@npm:8.28.0": + version: 8.28.0 + resolution: "@typescript-eslint/types@npm:8.28.0" + checksum: 10c0/1f95895e20dac1cf063dc93c99142fd1871e53be816bcbbee93f22a05e6b2a82ca83c20ce3a551f65555910aa0956443a23268edbb004369d0d5cb282d13c377 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.27.0": - version: 8.27.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.27.0" +"@typescript-eslint/typescript-estree@npm:8.28.0": + version: 8.28.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.28.0" dependencies: - "@typescript-eslint/types": "npm:8.27.0" - "@typescript-eslint/visitor-keys": "npm:8.27.0" + "@typescript-eslint/types": "npm:8.28.0" + "@typescript-eslint/visitor-keys": "npm:8.28.0" debug: "npm:^4.3.4" fast-glob: "npm:^3.3.2" is-glob: "npm:^4.0.3" @@ -1557,32 +1566,32 @@ __metadata: ts-api-utils: "npm:^2.0.1" peerDependencies: typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/c04d602825ff2a7b2a89746a68b32f7052fb4ce3d2355d1f4e6f43fd064f17c3b44fb974c98838a078fdebdc35152d2ab0af34663dfca99db7a790bd3fc5d8ac + checksum: 10c0/97a91c95b1295926098c12e2d2c2abaa68994dc879da132dcce1e75ec9d7dee8187695eaa5241d09cbc42b5e633917b6d35c624e78e3d3ee9bda42d1318080b6 languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.27.0": - version: 8.27.0 - resolution: "@typescript-eslint/utils@npm:8.27.0" +"@typescript-eslint/utils@npm:8.28.0": + version: 8.28.0 + resolution: "@typescript-eslint/utils@npm:8.28.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:8.27.0" - "@typescript-eslint/types": "npm:8.27.0" - "@typescript-eslint/typescript-estree": "npm:8.27.0" + "@typescript-eslint/scope-manager": "npm:8.28.0" + "@typescript-eslint/types": "npm:8.28.0" + "@typescript-eslint/typescript-estree": "npm:8.28.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/dcfd5f2c17f1a33061e3ec70d0946ff23a4238aabacae3d85087165beccedf84fb8506d30848f2470e3b60ab98b230aef79c6e8b4c5d39648a37ac559ac5b1e0 + checksum: 10c0/d3425be7f86c1245a11f0ea39136af681027797417348d8e666d38c76646945eaed7b35eb8db66372b067dee8b02a855caf2c24c040ec9c31e59681ab223b59d languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.27.0": - version: 8.27.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.27.0" +"@typescript-eslint/visitor-keys@npm:8.28.0": + version: 8.28.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.28.0" dependencies: - "@typescript-eslint/types": "npm:8.27.0" + "@typescript-eslint/types": "npm:8.28.0" eslint-visitor-keys: "npm:^4.2.0" - checksum: 10c0/d86fd4032db07123816aab3a6b8b53f840387385ab2a4d8f96b22fc76b5438fb27ac8dc42b63caf23f3d265c33e9075dbf1ce8d31f939df12f5cd077d3b10295 + checksum: 10c0/245a78ed983fe95fbd1b0f2d4cb9e9d1d964bddc0aa3e3d6ab10c19c4273855bfb27d840bb1fd55deb7ae3078b52f26592472baf6fd2c7019a5aa3b1da974f35 languageName: node linkType: hard @@ -1602,7 +1611,7 @@ __metadata: "@table-library/react-table-library": "npm:4.1.12" "@trivago/prettier-plugin-sort-imports": "npm:^5.2.2" "@types/formidable": "npm:^3" - "@types/node": "npm:^22.13.11" + "@types/node": "npm:^22.13.13" "@types/react": "npm:^19.0.12" "@types/react-dom": "npm:^19.0.4" alova: "npm:3.2.10" @@ -1624,8 +1633,8 @@ __metadata: terser: "npm:^5.39.0" typesafe-i18n: "npm:^5.26.2" typescript: "npm:^5.8.2" - typescript-eslint: "npm:8.27.0" - vite: "npm:^6.2.2" + typescript-eslint: "npm:8.28.0" + vite: "npm:^6.2.3" vite-plugin-imagemin: "npm:^0.6.1" vite-tsconfig-paths: "npm:^5.1.4" languageName: unknown @@ -6654,17 +6663,17 @@ __metadata: languageName: node linkType: hard -"typescript-eslint@npm:8.27.0": - version: 8.27.0 - resolution: "typescript-eslint@npm:8.27.0" +"typescript-eslint@npm:8.28.0": + version: 8.28.0 + resolution: "typescript-eslint@npm:8.28.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.27.0" - "@typescript-eslint/parser": "npm:8.27.0" - "@typescript-eslint/utils": "npm:8.27.0" + "@typescript-eslint/eslint-plugin": "npm:8.28.0" + "@typescript-eslint/parser": "npm:8.28.0" + "@typescript-eslint/utils": "npm:8.28.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/f66f8311418b12bca751e8e1c68e42c638745765be40621b65f287a15dd58d4a71e3a0f80756d5c3cc9070a93bb1745887fce2260117e19e1b70f2804cefd351 + checksum: 10c0/bf1c1e4b2f21a95930758d5b285c39a394a50e3b6983f373413b93b80a6cb5aabc1d741780e60c63cb42ad5d645ea9c1e6d441d98174c5a2884ab88f4ac46df6 languageName: node linkType: hard @@ -6867,9 +6876,9 @@ __metadata: languageName: node linkType: hard -"vite@npm:^6.2.2": - version: 6.2.2 - resolution: "vite@npm:6.2.2" +"vite@npm:^6.2.3": + version: 6.2.3 + resolution: "vite@npm:6.2.3" dependencies: esbuild: "npm:^0.25.0" fsevents: "npm:~2.3.3" @@ -6915,7 +6924,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10c0/52f5b1c10cfe5e3b6382c6de1811ebbf76df9b5a8bab3d65169446c6b54a5f1528f775b1548009a6d8aad11def20fba046bb3e9abb10c0c2c9ccd78118623bb8 + checksum: 10c0/ba6ad7e83e5a63fb0b6f62d3a3963624b8784bdc1bfa2a83e16cf268fb58c76bd9f8e69f39ed34bf8711cdb8fd7702916f878781da53c232c34ef7a85e0600cf languageName: node linkType: hard From 40d48f4407f4c7866d092ed7e5e5c7d4ca6a789a Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Tue, 25 Mar 2025 18:07:57 +0100 Subject: [PATCH 7/9] add FLAG_HMC310, fix switchtimeWW --- CHANGELOG_LATEST.md | 3 ++- docs/Modbus-Entity-Registers.md | 8 ++++---- docs/dump_entities.csv | 2 +- src/core/emsdevice.h | 1 + src/core/emsesp.cpp | 2 +- src/core/locale_translations.h | 1 - src/core/modbus_entity_parameters.hpp | 2 +- src/devices/thermostat.cpp | 24 ++++++++++++++++-------- src/devices/thermostat.h | 4 ++-- src/version.h | 2 +- 10 files changed, 29 insertions(+), 20 deletions(-) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 661cdc59a..fffbdbcf8 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -7,10 +7,11 @@ For more details go to [docs.emsesp.org](https://docs.emsesp.org/). ## Added - analogsensor types: NTC and RGB-Led +- Flag for HMC310 ## Fixed -- +- dhw/switchtime [#2490](https://github.com/emsesp/EMS-ESP32/issues/2490) ## Changed diff --git a/docs/Modbus-Entity-Registers.md b/docs/Modbus-Entity-Registers.md index b0b4e6aa9..853e12ef9 100644 --- a/docs/Modbus-Entity-Registers.md +++ b/docs/Modbus-Entity-Registers.md @@ -4371,7 +4371,7 @@ | dhw.disinfecthour | disinfection hour | uint8 (>=0<=23) | | true | DHW | 14 | 1 | 1 | | dhw.maxtemp | maximum temperature | uint8 (>=0<=254) | C | true | DHW | 15 | 1 | 1 | | dhw.onetimekey | one time key function | boolean | | true | DHW | 16 | 1 | 1 | -| dhw.switchtimeWW | program switchtime warm water | string | | true | DHW | 17 | 11 | 1 | +| dhw.switchtime | program switchtime | string | | true | DHW | 17 | 11 | 1 | | dhw.circswitchtime | circulation program switchtime | string | | true | DHW | 28 | 8 | 1 | | dhw.holidays | holiday dates | string | | true | DHW | 36 | 13 | 1 | | dhw.vacations | vacation dates | string | | true | DHW | 49 | 13 | 1 | @@ -4437,7 +4437,7 @@ | dhw.disinfecthour | disinfection hour | uint8 (>=0<=23) | | true | DHW | 14 | 1 | 1 | | dhw.maxtemp | maximum temperature | uint8 (>=60<=80) | C | true | DHW | 15 | 1 | 1 | | dhw.onetimekey | one time key function | boolean | | true | DHW | 16 | 1 | 1 | -| dhw.switchtimeWW | program switchtime warm water | string | | true | DHW | 17 | 11 | 1 | +| dhw.switchtime | program switchtime | string | | true | DHW | 17 | 11 | 1 | | dhw.circswitchtime | circulation program switchtime | string | | true | DHW | 28 | 8 | 1 | | dhw.holidays | holiday dates | string | | true | DHW | 36 | 13 | 1 | | dhw.vacations | vacation dates | string | | true | DHW | 49 | 13 | 1 | @@ -5344,7 +5344,7 @@ | dhw.disinfecthour | disinfection hour | uint8 (>=0<=23) | | true | DHW | 14 | 1 | 1 | | dhw.maxtemp | maximum temperature | uint8 (>=0<=254) | C | true | DHW | 15 | 1 | 1 | | dhw.onetimekey | one time key function | boolean | | true | DHW | 16 | 1 | 1 | -| dhw.switchtimeWW | program switchtime warm water | string | | true | DHW | 17 | 11 | 1 | +| dhw.switchtime | program switchtime | string | | true | DHW | 17 | 11 | 1 | | dhw.circswitchtime | circulation program switchtime | string | | true | DHW | 28 | 8 | 1 | | dhw.holidays | holiday dates | string | | true | DHW | 36 | 13 | 1 | | dhw.vacations | vacation dates | string | | true | DHW | 49 | 13 | 1 | @@ -5410,7 +5410,7 @@ | dhw.disinfecthour | disinfection hour | uint8 (>=0<=23) | | true | DHW | 14 | 1 | 1 | | dhw.maxtemp | maximum temperature | uint8 (>=60<=80) | C | true | DHW | 15 | 1 | 1 | | dhw.onetimekey | one time key function | boolean | | true | DHW | 16 | 1 | 1 | -| dhw.switchtimeWW | program switchtime warm water | string | | true | DHW | 17 | 11 | 1 | +| dhw.switchtime | program switchtime | string | | true | DHW | 17 | 11 | 1 | | dhw.circswitchtime | circulation program switchtime | string | | true | DHW | 28 | 8 | 1 | | dhw.holidays | holiday dates | string | | true | DHW | 36 | 13 | 1 | | dhw.vacations | vacation dates | string | | true | DHW | 49 | 13 | 1 | diff --git a/docs/dump_entities.csv b/docs/dump_entities.csv index c2674c065..8b7cbc6d7 100644 --- a/docs/dump_entities.csv +++ b/docs/dump_entities.csv @@ -3753,7 +3753,7 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/ "RC30",thermostat,67,dhw.disinfecthour,disinfection hour,uint8 (>=0<=23), ,true,number.thermostat_dhw_disinfection_hour,number.thermostat_dhw_disinfecthour,6,9,1,14,1 "RC30",thermostat,67,dhw.maxtemp,maximum temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_maximum_temperature,number.thermostat_dhw_maxtemp,6,9,1,15,1 "RC30",thermostat,67,dhw.onetimekey,one time key function,boolean, ,true,switch.thermostat_dhw_one_time_key_function,switch.thermostat_dhw_onetimekey,6,9,1,16,1 -"RC30",thermostat,67,dhw.switchtimeWW,program switchtime warm water,string, ,true,sensor.thermostat_dhw_program_switchtime_warm_water,sensor.thermostat_dhw_switchtimeWW,6,9,1,17,11 +"RC30",thermostat,67,dhw.switchtime,program switchtime,string, ,true,sensor.thermostat_dhw_program_switchtime,sensor.thermostat_dhw_switchtime,6,9,1,17,11 "RC30",thermostat,67,dhw.circswitchtime,circulation program switchtime,string, ,true,sensor.thermostat_dhw_circulation_program_switchtime,sensor.thermostat_dhw_circswitchtime,6,9,1,28,8 "RC30",thermostat,67,dhw.holidays,holiday dates,string, ,true,sensor.thermostat_dhw_holiday_dates,sensor.thermostat_dhw_holidays,6,9,1,36,13 "RC30",thermostat,67,dhw.vacations,vacation dates,string, ,true,sensor.thermostat_dhw_vacation_dates,sensor.thermostat_dhw_vacations,6,9,1,49,13 diff --git a/src/core/emsdevice.h b/src/core/emsdevice.h index df7e72852..5824f44c1 100644 --- a/src/core/emsdevice.h +++ b/src/core/emsdevice.h @@ -468,6 +468,7 @@ class EMSdevice { 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 + static constexpr uint8_t EMS_DEVICE_FLAG_HMC310 = 18; uint8_t count_entities(); uint8_t count_entities_fav(); diff --git a/src/core/emsesp.cpp b/src/core/emsesp.cpp index 2b071d536..3ef9c2a07 100644 --- a/src/core/emsesp.cpp +++ b/src/core/emsesp.cpp @@ -1315,7 +1315,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const default_name = "CR120"; } if (product_id == 158 && strncmp(version,"73",2) == 0) { - flags = DeviceFlags::EMS_DEVICE_FLAG_BC400; + flags = DeviceFlags::EMS_DEVICE_FLAG_HMC310; default_name = "HMC310"; } diff --git a/src/core/locale_translations.h b/src/core/locale_translations.h index 275d7bb34..87b45a9ad 100644 --- a/src/core/locale_translations.h +++ b/src/core/locale_translations.h @@ -652,7 +652,6 @@ MAKE_TRANSLATION(wwSolarTemp, "solartemp", "solar boiler temperature", "Solarkes MAKE_TRANSLATION(switchtime, "switchtime", "program switchtime", "Programmschaltzeit", "Programma schakeltijd", "Program Bytestid", "program czasowy", "programbyttetid", "heure commutation programme", "program değiştirme süresi", "ora commutazione programmata", "čas prepnutia programu", "čas přepnutí programu") MAKE_TRANSLATION(switchtime1, "switchtime1", "own1 program switchtime", "Programmschaltzeit Eigen 1", "Schakeltijd programma 1", "Program 1 Bytestid", "program przełączania 1", "byttetidprogram 1", "heure de commutation programme 1", "program1 değiştirme süresi", "ora commutazione programma 1", "vlastný 1 program prepnutia", "vlastní program 1 přepnutí") MAKE_TRANSLATION(switchtime2, "switchtime2", "own2 program switchtime", "Programmschaltzeit Eigen 2", "Schakeltijd programma 2", "Program 2 Bytestid", "program przełączania 2", "byttetid program 2", "heure de changement programme 2", "program1 değiştirme süresi", "ora commutazione programma 2", "vlastný 2 program prepnutia", "vlastní program 2 přepnutí") -MAKE_TRANSLATION(wwswitchtime, "switchtimeWW", "program switchtime warm water", "Programmschaltzeit Warmwasser", "Warm water programma schakeltijd", "Varmvattenprogram Bytestid", "program czasowy", "byttetid varmtvannsprogram", "heure commutation programme", "sıcak kullanıom suyu program değiştirme süresi", "Tempo di commutazione del programma", "čas prepnutia programu", "čas přepnutí program TUV") MAKE_TRANSLATION(wwcircswitchtime, "circswitchtime", "circulation program switchtime", "Zirculationsprogramm Schaltzeit", "Schakeltijd circulatieprogramma", "Cirkulationsprogram Bytestid", "program cyrkulacji", "byttetid sirkulasjonsprogram", "heure commutation programme circulation", "sirkülasyon program değiştirme süresi", "ora commutazione programma circolazione", "čas prepnutia cirkulačného programu", "čas přepnutí programu cirkulace") MAKE_TRANSLATION(dateTime, "datetime", "date/time", "Datum/Zeit", "Datum/Tijd", "Datum/Tid", "data i godzina", "dato/tid", "date/heure", "zaman/saat", "Data/Ora", "dátum/čas", "datum/čas") MAKE_TRANSLATION(errorCode, "errorcode", "error code", "Fehlercode", "Foutmeldingscode", "Felkod", "kod błędu", "feikode", "code erreur", "hata kodu", "codice errore", "error kód", "chybový kód") diff --git a/src/core/modbus_entity_parameters.hpp b/src/core/modbus_entity_parameters.hpp index 4d5c5c1db..707e15c3d 100644 --- a/src/core/modbus_entity_parameters.hpp +++ b/src/core/modbus_entity_parameters.hpp @@ -393,7 +393,7 @@ const std::initializer_list Modbus::modbus_register_ma REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(wwDisinfectHour), 14, 1), // disinfecthour REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(wwMaxTemp), 15, 1), // maxtemp REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(wwOneTimeKey), 16, 1), // onetimekey - REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(wwswitchtime), 17, 11), // switchtimeWW + REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(switchtime), 17, 11), // switchtime REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(wwcircswitchtime), 28, 8), // circswitchtime REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(holidays), 36, 13), // holidays REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(vacations), 49, 13), // vacations diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index 1b617b302..6d7275a37 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -513,7 +513,8 @@ uint8_t Thermostat::HeatingCircuit::get_mode() const { } else if (mode_new == 2) { return HeatingCircuit::Mode::AUTO; } - } else if ((model == EMSdevice::EMS_DEVICE_FLAG_RC300) || (model == EMSdevice::EMS_DEVICE_FLAG_R3000) || (model == EMSdevice::EMS_DEVICE_FLAG_RC100)) { + } else if (model == EMSdevice::EMS_DEVICE_FLAG_RC300 || model == EMSdevice::EMS_DEVICE_FLAG_R3000 || model == EMSdevice::EMS_DEVICE_FLAG_RC100 + || model == EMSdevice::EMS_DEVICE_FLAG_HMC310) { if (mode == 0) { return HeatingCircuit::Mode::MANUAL; } else if (mode == 1) { @@ -565,7 +566,8 @@ uint8_t Thermostat::HeatingCircuit::get_mode_type() const { } else if (modetype == 1) { return HeatingCircuit::Mode::ON; } - } else if ((model == EMSdevice::EMS_DEVICE_FLAG_RC300) || (model == EMSdevice::EMS_DEVICE_FLAG_R3000) || (model == EMSdevice::EMS_DEVICE_FLAG_BC400)) { + } else if (model == EMSdevice::EMS_DEVICE_FLAG_RC300 || model == EMSdevice::EMS_DEVICE_FLAG_R3000 || model == EMSdevice::EMS_DEVICE_FLAG_BC400 + || model == EMSdevice::EMS_DEVICE_FLAG_HMC310) { if (modetype == 0) { return HeatingCircuit::Mode::ECO; } else if (modetype == 1) { @@ -1265,7 +1267,7 @@ void Thermostat::process_RC300WWmode(std::shared_ptr telegram) { // circulation pump see: https://github.com/Th3M3/buderus_ems-wiki/blob/master/Einstellungen%20der%20Bedieneinheit%20RC310.md has_update(telegram, dhw->wwCircPump_, 1); // FF=off, 0=on ? - if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400) { + if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310) { const uint8_t modes[] = {0, 5, 1, 2, 4}; // off, eco+, eco, comfort, auto uint8_t wwmode = dhw->wwMode_ < sizeof(modes) ? modes[dhw->wwMode_] : EMS_VALUE_UINT8_NOTSET; telegram->read_value(wwmode, 2); @@ -2235,7 +2237,7 @@ bool Thermostat::set_wwmode(const char * value, const int8_t id) { return false; } write_command(0xB0, 2, set, 0xB0); - } else if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400) { + } else if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310) { if (!Helpers::value2enum(value, set, FL_(enum_wwMode4))) { // off, eco+, eco, comfort, auto return false; } @@ -2946,6 +2948,7 @@ bool Thermostat::set_mode(const char * value, const int8_t id) { case EMSdevice::EMS_DEVICE_FLAG_RC300: case EMSdevice::EMS_DEVICE_FLAG_RC100: case EMSdevice::EMS_DEVICE_FLAG_R3000: + case EMSdevice::EMS_DEVICE_FLAG_HMC310: mode_list = FL_(enum_mode); break; case EMSdevice::EMS_DEVICE_FLAG_JUNKERS: @@ -3071,6 +3074,7 @@ bool Thermostat::set_mode_n(const uint8_t mode, const int8_t id) { case EMSdevice::EMS_DEVICE_FLAG_RC300: case EMSdevice::EMS_DEVICE_FLAG_RC100: case EMSdevice::EMS_DEVICE_FLAG_R3000: + case EMSdevice::EMS_DEVICE_FLAG_HMC310: offset = EMS_OFFSET_RCPLUSSet_mode; set_mode_value = set_mode_value == 2 ? 0xFF : 0; break; @@ -3105,7 +3109,8 @@ bool Thermostat::set_mode_n(const uint8_t mode, const int8_t id) { hc->mode = set_mode_value >> 1; } else if (model_ == EMSdevice::EMS_DEVICE_FLAG_BC400 || model_ == EMSdevice::EMS_DEVICE_FLAG_CR120) { hc->mode_new = set_mode_value; - } else if (model_ == EMSdevice::EMS_DEVICE_FLAG_RC300 || model_ == EMSdevice::EMS_DEVICE_FLAG_R3000 || model_ == EMSdevice::EMS_DEVICE_FLAG_RC100) { + } else if (model_ == EMSdevice::EMS_DEVICE_FLAG_RC300 || model_ == EMSdevice::EMS_DEVICE_FLAG_R3000 || model_ == EMSdevice::EMS_DEVICE_FLAG_HMC310 + || model_ == EMSdevice::EMS_DEVICE_FLAG_RC100) { hc->mode = set_mode_value == 0xFF ? 1 : 0; } else if (model_ == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) { hc->mode = set_mode_value - 1; @@ -4188,6 +4193,7 @@ void Thermostat::register_device_values() { case EMSdevice::EMS_DEVICE_FLAG_R3000: case EMSdevice::EMS_DEVICE_FLAG_BC400: case EMSdevice::EMS_DEVICE_FLAG_CR120: + case EMSdevice::EMS_DEVICE_FLAG_HMC310: register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dateTime_, DeviceValueType::STRING, @@ -4619,6 +4625,7 @@ void Thermostat::register_device_values_hc(std::shared_ptrmode_new, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode)); } else { @@ -5058,7 +5065,8 @@ void Thermostat::register_device_values_dhw(std::shared_ptrwwMode_, DeviceValueType::ENUM, FL_(enum_wwMode4), FL_(wwMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwmode)); } else if (model() == EMSdevice::EMS_DEVICE_FLAG_R3000) { register_device_value(tag, &dhw->wwMode_, DeviceValueType::ENUM, FL_(enum_wwMode5), FL_(wwMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwmode)); @@ -5134,7 +5142,7 @@ void Thermostat::register_device_values_dhw(std::shared_ptrwwMaxTemp_, DeviceValueType::UINT8, FL_(wwMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwMaxTemp)); register_device_value(tag, &dhw->wwOneTimeKey_, DeviceValueType::BOOL, FL_(wwOneTimeKey), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwOneTimeKey)); register_device_value( - tag, &dhw->wwSwitchTime_, DeviceValueType::STRING, FL_(tpl_switchtime), FL_(wwswitchtime), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwSwitchTime)); + tag, &dhw->wwSwitchTime_, DeviceValueType::STRING, FL_(tpl_switchtime), FL_(switchtime), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwSwitchTime)); register_device_value(tag, &dhw->wwCircSwitchTime_, DeviceValueType::STRING, @@ -5157,7 +5165,7 @@ void Thermostat::register_device_values_dhw(std::shared_ptrwwMaxTemp_, DeviceValueType::UINT8, FL_(wwMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwMaxTemp), 60, 80); register_device_value(tag, &dhw->wwOneTimeKey_, DeviceValueType::BOOL, FL_(wwOneTimeKey), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwOneTimeKey)); register_device_value( - tag, &dhw->wwSwitchTime_, DeviceValueType::STRING, FL_(tpl_switchtime), FL_(wwswitchtime), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwSwitchTime)); + tag, &dhw->wwSwitchTime_, DeviceValueType::STRING, FL_(tpl_switchtime), FL_(switchtime), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwSwitchTime)); register_device_value(tag, &dhw->wwCircSwitchTime_, DeviceValueType::STRING, diff --git a/src/devices/thermostat.h b/src/devices/thermostat.h index 843872f52..616e4759e 100644 --- a/src/devices/thermostat.h +++ b/src/devices/thermostat.h @@ -229,8 +229,8 @@ class Thermostat : public EMSdevice { // check to see if the thermostat is a hybrid of the R300 inline bool isRC300() const { - return ((model() == EMSdevice::EMS_DEVICE_FLAG_RC300) || (model() == EMSdevice::EMS_DEVICE_FLAG_R3000) || (model() == EMSdevice::EMS_DEVICE_FLAG_BC400) - || (model() == EMSdevice::EMS_DEVICE_FLAG_CR120)); + return (model() == EMSdevice::EMS_DEVICE_FLAG_RC300 || model() == EMSdevice::EMS_DEVICE_FLAG_R3000 || model() == EMSdevice::EMS_DEVICE_FLAG_BC400 + || model() == EMSdevice::EMS_DEVICE_FLAG_CR120 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310); } inline uint8_t id2dhw(const int8_t id) const { // returns telegram offset for TAG(id) diff --git a/src/version.h b/src/version.h index 90654f617..06be1ce7a 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.7.3-dev.1" +#define EMSESP_APP_VERSION "3.7.3-dev.2" From f31329ceff30d0fcf49ce1e571cca0636b56f5b2 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Wed, 26 Mar 2025 07:16:08 +0100 Subject: [PATCH 8/9] fix dhw progMode, #2490 --- src/devices/thermostat.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index 6d7275a37..7e29724a4 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -908,12 +908,12 @@ void Thermostat::process_IBASettings(std::shared_ptr telegram) { // Settings WW 0x37 - RC35 void Thermostat::process_RC35wwSettings(std::shared_ptr telegram) { auto dhw = dhw_circuit(0, true); - has_update(telegram, dhw->wwProgMode_, 0); // 0-like hc, 0xFF own prog - has_update(telegram, dhw->wwCircProg_, 1); // 0-like hc, 0xFF own prog - has_update(telegram, dhw->wwMode_, 2); // 0-off, 1-on, 2-auto - has_update(telegram, dhw->wwCircMode_, 3); // 0-off, 1-on, 2-auto - has_update(telegram, dhw->wwDisinfecting_, 4); // 0-off, 0xFF on - has_update(telegram, dhw->wwDisinfectDay_, 5); // 0-6 Day of week, 7 every day + has_bitupdate(telegram, dhw->wwProgMode_, 0, 0); // 0-like hc, 0xFF own prog + has_bitupdate(telegram, dhw->wwCircProg_, 1, 0); // 0-like hc, 0xFF own prog + has_update(telegram, dhw->wwMode_, 2); // 0-off, 1-on, 2-auto + has_update(telegram, dhw->wwCircMode_, 3); // 0-off, 1-on, 2-auto + has_update(telegram, dhw->wwDisinfecting_, 4); // 0-off, 0xFF on + has_update(telegram, dhw->wwDisinfectDay_, 5); // 0-6 Day of week, 7 every day has_update(telegram, dhw->wwDisinfectHour_, 6); has_update(telegram, dhw->wwMaxTemp_, 8); // Limiter 60 degrees has_update(telegram, dhw->wwOneTimeKey_, 9); // 0-off, 0xFF on From b5471aef94ac07c9e3d42c555c4c3b439af3cf96 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Wed, 26 Mar 2025 17:03:51 +0100 Subject: [PATCH 9/9] fix typo in `set_wwswitchtime`, fixes #2490 --- src/devices/thermostat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index 7e29724a4..52f07bd20 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -3619,7 +3619,7 @@ bool Thermostat::set_wwCircSwitchTime(const char * value, const int8_t id) { // sets a single switchtime in the thermostat circulation program for RC35 bool Thermostat::set_wwSwitchTime(const char * value, const int8_t id) { auto dhw = dhw_circuit(id2dhw(id)); - if (dhw != nullptr) { + if (dhw == nullptr) { return false; } char out[sizeof(dhw->wwSwitchTime_)] = {'\0'};