From 3101f5e6ae11dfb6d5f1face256cb036f733ac74 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sat, 4 Nov 2023 15:24:43 +0100 Subject: [PATCH] move dhw entities from mixer/solar to new water device, add pool device --- CHANGELOG_LATEST.md | 3 + interface/package.json | 4 +- .../src/framework/mqtt/MqttSettingsForm.tsx | 15 + interface/src/i18n/de/index.ts | 1 + interface/src/i18n/en/index.ts | 1 + interface/src/i18n/fr/index.ts | 1 + interface/src/i18n/it/index.ts | 1 + interface/src/i18n/nl/index.ts | 1 + interface/src/i18n/no/index.ts | 1 + interface/src/i18n/pl/index.ts | 1 + interface/src/i18n/sv/index.ts | 1 + interface/src/i18n/tr/index.ts | 1 + interface/src/project/DeviceIcon.tsx | 8 +- interface/src/project/types.ts | 5 +- interface/src/types/mqtt.ts | 1 + interface/yarn.lock | 40 +- lib/framework/MqttSettingsService.cpp | 6 + lib/framework/MqttSettingsService.h | 1 + src/device_library.h | 2 +- src/devices/boiler.cpp | 112 +++-- src/devices/mixer.cpp | 297 +------------ src/devices/mixer.h | 52 --- src/devices/pool.cpp | 50 +++ src/devices/pool.h | 46 ++ src/devices/solar.cpp | 265 +----------- src/devices/solar.h | 45 -- src/devices/water.cpp | 392 ++++++++++++++++++ src/devices/water.h | 115 +++++ src/emsdevice.cpp | 18 +- src/emsdevice.h | 14 +- src/emsesp.cpp | 14 +- src/locale_common.h | 2 + src/locale_translations.h | 19 +- src/mqtt.cpp | 17 + src/mqtt.h | 3 + src/version.h | 2 +- 36 files changed, 842 insertions(+), 715 deletions(-) create mode 100644 src/devices/pool.cpp create mode 100644 src/devices/pool.h create mode 100644 src/devices/water.cpp create mode 100644 src/devices/water.h diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 3ffef4fdf..7e59c5db5 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -4,6 +4,8 @@ ## **IMPORTANT! BREAKING CHANGES** +- move dhw functions from mixer/solar to water + ## Added - humidity for ventilation devices @@ -16,6 +18,7 @@ - heatpump high res energy counters [#1348, #1349. #1350](https://github.com/emsesp/EMS-ESP32/issues/1348) - optional bssid in network settings - extension module EM100 [#1315](https://github.com/emsesp/EMS-ESP32/discussions/1315) +- digital_out with new options for polarity and startup state ## Fixed diff --git a/interface/package.json b/interface/package.json index bcc223484..702e68c46 100644 --- a/interface/package.json +++ b/interface/package.json @@ -54,7 +54,7 @@ "@typescript-eslint/eslint-plugin": "^6.9.1", "@typescript-eslint/parser": "^6.9.1", "concurrently": "^8.2.2", - "eslint": "^8.52.0", + "eslint": "^8.53.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^17.1.0", "eslint-config-prettier": "^9.0.0", @@ -65,7 +65,7 @@ "eslint-plugin-prettier": "alpha", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", - "preact": "^10.18.1", + "preact": "^10.18.2", "prettier": "^3.0.3", "rollup-plugin-visualizer": "^5.9.2", "terser": "^5.24.0", diff --git a/interface/src/framework/mqtt/MqttSettingsForm.tsx b/interface/src/framework/mqtt/MqttSettingsForm.tsx index 1647c3f9d..969ec37a9 100644 --- a/interface/src/framework/mqtt/MqttSettingsForm.tsx +++ b/interface/src/framework/mqtt/MqttSettingsForm.tsx @@ -382,6 +382,21 @@ const MqttSettingsForm: FC = () => { margin="normal" /> + + {LL.SECONDS()} + }} + fullWidth + variant="outlined" + value={numberValue(data.publish_time_water)} + type="number" + onChange={updateFormValue} + margin="normal" + /> + = ({ type_id }) => { return ; case DeviceType.EXTENSION: return ; + case DeviceType.WATER: + return ; + case DeviceType.POOL: + return ; case DeviceType.CUSTOM: return ; default: diff --git a/interface/src/project/types.ts b/interface/src/project/types.ts index 05cf46073..97dceded3 100644 --- a/interface/src/project/types.ts +++ b/interface/src/project/types.ts @@ -355,6 +355,7 @@ export const enum DeviceType { TEMPERATURESENSOR, ANALOGSENSOR, SCHEDULER, + CUSTOM, BOILER, THERMOSTAT, MIXER, @@ -368,7 +369,9 @@ export const enum DeviceType { EXTENSION, GENERIC, HEATSOURCE, - CUSTOM, + VENTILATION, + WATER, + POOL, UNKNOWN } diff --git a/interface/src/types/mqtt.ts b/interface/src/types/mqtt.ts index df9261f4a..cf5b1ce48 100644 --- a/interface/src/types/mqtt.ts +++ b/interface/src/types/mqtt.ts @@ -35,6 +35,7 @@ export interface MqttSettings { publish_time_thermostat: number; publish_time_solar: number; publish_time_mixer: number; + publish_time_water: number; publish_time_other: number; publish_time_sensor: number; publish_time_heartbeat: number; diff --git a/interface/yarn.lock b/interface/yarn.lock index cc0410c85..8d8492cc3 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -641,9 +641,9 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.1.2": - version: 2.1.2 - resolution: "@eslint/eslintrc@npm:2.1.2" +"@eslint/eslintrc@npm:^2.1.3": + version: 2.1.3 + resolution: "@eslint/eslintrc@npm:2.1.3" dependencies: ajv: "npm:^6.12.4" debug: "npm:^4.3.2" @@ -654,14 +654,14 @@ __metadata: js-yaml: "npm:^4.1.0" minimatch: "npm:^3.1.2" strip-json-comments: "npm:^3.1.1" - checksum: fa25638f2666cac6810f98ee7d0f4b912f191806467c1b40d72bac759fffef0b3357f12a1869817286837b258e4de3517e0c7408520e156ca860fc53a1fbaed9 + checksum: 77b70a89232fe702c2f765b5b92970f5e4224b55363b923238b996c66fcd991504f40d3663c0543ae17d6c5049ab9b07ab90b65d7601e6f25e8bcd4caf69ac75 languageName: node linkType: hard -"@eslint/js@npm:8.52.0": - version: 8.52.0 - resolution: "@eslint/js@npm:8.52.0" - checksum: 86beff213d0ae4ced203a922b74e2cc4d767d109e7815f985bf648946ba072198977102e32afc9fa04f7825a6de83a831874f6b6675ba0c1d0743ade2dc2d53d +"@eslint/js@npm:8.53.0": + version: 8.53.0 + resolution: "@eslint/js@npm:8.53.0" + checksum: a372d55aa2bbe0d9399acc8de3c892dcfe507fd914d29fde6826ae54a13452619be626aa7eb70b1ec4d4da5302b6ed8e8ac9bf1f830003f15c0ad56c30b4f520 languageName: node linkType: hard @@ -1566,7 +1566,7 @@ __metadata: alova: "npm:^2.13.1" async-validator: "npm:^4.2.5" concurrently: "npm:^8.2.2" - eslint: "npm:^8.52.0" + eslint: "npm:^8.53.0" eslint-config-airbnb: "npm:^19.0.4" eslint-config-airbnb-typescript: "npm:^17.1.0" eslint-config-prettier: "npm:^9.0.0" @@ -1581,7 +1581,7 @@ __metadata: jwt-decode: "npm:^4.0.0" lodash-es: "npm:^4.17.21" mime-types: "npm:^2.1.35" - preact: "npm:^10.18.1" + preact: "npm:^10.18.2" prettier: "npm:^3.0.3" react: "npm:latest" react-dom: "npm:latest" @@ -3654,14 +3654,14 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.52.0": - version: 8.52.0 - resolution: "eslint@npm:8.52.0" +"eslint@npm:^8.53.0": + version: 8.53.0 + resolution: "eslint@npm:8.53.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.6.1" - "@eslint/eslintrc": "npm:^2.1.2" - "@eslint/js": "npm:8.52.0" + "@eslint/eslintrc": "npm:^2.1.3" + "@eslint/js": "npm:8.53.0" "@humanwhocodes/config-array": "npm:^0.11.13" "@humanwhocodes/module-importer": "npm:^1.0.1" "@nodelib/fs.walk": "npm:^1.2.8" @@ -3698,7 +3698,7 @@ __metadata: text-table: "npm:^0.2.0" bin: eslint: bin/eslint.js - checksum: 01784ab15351d749bc95446039ed7acd5124f7cc84acdbf98c7199272eae06212a8f3ea4a9b47e7cc54ab17ca094c3a664bbfc3002c7de27936220e278b5028a + checksum: e305a71ce2b9a8631b293266fe53e346c76f28bc8d004af33f10e537cf133db1fb87af3599376e70ed6e0f89a78be10c4f08ddd0c1c9c0c497cd143b4a270420 languageName: node linkType: hard @@ -6661,10 +6661,10 @@ __metadata: languageName: node linkType: hard -"preact@npm:^10.18.1": - version: 10.18.1 - resolution: "preact@npm:10.18.1" - checksum: 587c4634b310efc306ef9315f849b8e4ff538435087a1dca626e1394b98570af1ecdc254b7f0bb3060fc7ab87456c5f891f9b8a167d5c34dbbcfcf60b6e993f4 +"preact@npm:^10.18.2": + version: 10.18.2 + resolution: "preact@npm:10.18.2" + checksum: c7dcd6ea812adb0bdc215366b14aadc44724b6dd6c4e9aadd986126d94abde62f3e02e18d6157a9984873be9877f206c0afa10a09346178c4c828a103a66a0e1 languageName: node linkType: hard diff --git a/lib/framework/MqttSettingsService.cpp b/lib/framework/MqttSettingsService.cpp index 8f96f2f15..14c407bc2 100644 --- a/lib/framework/MqttSettingsService.cpp +++ b/lib/framework/MqttSettingsService.cpp @@ -234,6 +234,7 @@ void MqttSettings::read(MqttSettings & settings, JsonObject & root) { root["publish_time_thermostat"] = settings.publish_time_thermostat; root["publish_time_solar"] = settings.publish_time_solar; root["publish_time_mixer"] = settings.publish_time_mixer; + root["publish_time_water"] = settings.publish_time_water; root["publish_time_other"] = settings.publish_time_other; root["publish_time_sensor"] = settings.publish_time_sensor; root["publish_time_heartbeat"] = settings.publish_time_heartbeat; @@ -271,6 +272,7 @@ StateUpdateResult MqttSettings::update(JsonObject & root, MqttSettings & setting newSettings.publish_time_thermostat = root["publish_time_thermostat"] | EMSESP_DEFAULT_PUBLISH_TIME; newSettings.publish_time_solar = root["publish_time_solar"] | EMSESP_DEFAULT_PUBLISH_TIME; newSettings.publish_time_mixer = root["publish_time_mixer"] | EMSESP_DEFAULT_PUBLISH_TIME; + newSettings.publish_time_water = root["publish_time_water"] | EMSESP_DEFAULT_PUBLISH_TIME; newSettings.publish_time_other = root["publish_time_other"] | EMSESP_DEFAULT_PUBLISH_TIME; newSettings.publish_time_sensor = root["publish_time_sensor"] | EMSESP_DEFAULT_PUBLISH_TIME; newSettings.publish_time_heartbeat = root["publish_time_heartbeat"] | EMSESP_DEFAULT_PUBLISH_HEARTBEAT; @@ -358,6 +360,10 @@ StateUpdateResult MqttSettings::update(JsonObject & root, MqttSettings & setting emsesp::EMSESP::mqtt_.set_publish_time_mixer(newSettings.publish_time_mixer); } + if (newSettings.publish_time_water != settings.publish_time_water) { + emsesp::EMSESP::mqtt_.set_publish_time_water(newSettings.publish_time_water); + } + if (newSettings.publish_time_other != settings.publish_time_other) { emsesp::EMSESP::mqtt_.set_publish_time_other(newSettings.publish_time_other); } diff --git a/lib/framework/MqttSettingsService.h b/lib/framework/MqttSettingsService.h index 90d1a53c7..f1ae73b33 100644 --- a/lib/framework/MqttSettingsService.h +++ b/lib/framework/MqttSettingsService.h @@ -82,6 +82,7 @@ class MqttSettings { uint16_t publish_time_thermostat; uint16_t publish_time_solar; uint16_t publish_time_mixer; + uint16_t publish_time_water; uint16_t publish_time_other; uint16_t publish_time_sensor; uint16_t publish_time_heartbeat; diff --git a/src/device_library.h b/src/device_library.h index a955cf52e..42367883c 100644 --- a/src/device_library.h +++ b/src/device_library.h @@ -142,7 +142,7 @@ {160, DeviceType::MIXER, "MM100", DeviceFlags::EMS_DEVICE_FLAG_MMPLUS}, {161, DeviceType::MIXER, "MM200", DeviceFlags::EMS_DEVICE_FLAG_MMPLUS}, {193, DeviceType::MIXER, "MZ100", DeviceFlags::EMS_DEVICE_FLAG_MMPLUS}, -{204, DeviceType::MIXER, "MP100", DeviceFlags::EMS_DEVICE_FLAG_MP}, // pool +{204, DeviceType::POOL, "MP100", DeviceFlags::EMS_DEVICE_FLAG_MP}, // pool // Heat Pumps - 0x38? This is a thermostat like RC100H // also prod-id of wifi module and wireless base diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index 330eb6cef..ea7f9cc09 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -176,31 +176,76 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const DeviceValueNumOp::DV_NUMOP_DIV10, FL_(boilTemp), DeviceValueUOM::DEGREES); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, - &exhaustTemp_, - DeviceValueType::USHORT, - DeviceValueNumOp::DV_NUMOP_DIV10, - FL_(exhaustTemp), - DeviceValueUOM::DEGREES); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, - &heatblock_, - DeviceValueType::USHORT, - DeviceValueNumOp::DV_NUMOP_DIV10, - FL_(heatblock), - DeviceValueUOM::DEGREES); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &headertemp_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(headertemp), DeviceValueUOM::DEGREES); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &burnGas_, DeviceValueType::BOOL, FL_(burnGas), DeviceValueUOM::NONE); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &burnGas2_, DeviceValueType::BOOL, FL_(burnGas2), DeviceValueUOM::NONE); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &flameCurr_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(flameCurr), DeviceValueUOM::UA); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &heatingPump_, DeviceValueType::BOOL, FL_(heatingPump), DeviceValueUOM::NONE); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &fanWork_, DeviceValueType::BOOL, FL_(fanWork), DeviceValueUOM::NONE); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &ignWork_, DeviceValueType::BOOL, FL_(ignWork), DeviceValueUOM::NONE); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &oilPreHeat_, DeviceValueType::BOOL, FL_(oilPreHeat), DeviceValueUOM::NONE); + + if (model() != EMS_DEVICE_FLAG_HEATPUMP && model() != EMS_DEVICE_FLAG_HIU) { + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &exhaustTemp_, + DeviceValueType::USHORT, + DeviceValueNumOp::DV_NUMOP_DIV10, + FL_(exhaustTemp), + DeviceValueUOM::DEGREES); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &heatblock_, + DeviceValueType::USHORT, + DeviceValueNumOp::DV_NUMOP_DIV10, + FL_(heatblock), + DeviceValueUOM::DEGREES); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &burnGas_, DeviceValueType::BOOL, FL_(burnGas), DeviceValueUOM::NONE); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &burnGas2_, DeviceValueType::BOOL, FL_(burnGas2), DeviceValueUOM::NONE); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &flameCurr_, + DeviceValueType::USHORT, + DeviceValueNumOp::DV_NUMOP_DIV10, + FL_(flameCurr), + DeviceValueUOM::UA); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &heatingPump_, DeviceValueType::BOOL, FL_(heatingPump), DeviceValueUOM::NONE); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &fanWork_, DeviceValueType::BOOL, FL_(fanWork), DeviceValueUOM::NONE); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &ignWork_, DeviceValueType::BOOL, FL_(ignWork), DeviceValueUOM::NONE); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &oilPreHeat_, DeviceValueType::BOOL, FL_(oilPreHeat), DeviceValueUOM::NONE); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &burnMinPower_, + DeviceValueType::UINT, + FL_(burnMinPower), + DeviceValueUOM::PERCENT, + MAKE_CF_CB(set_min_power)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &burnMaxPower_, + DeviceValueType::UINT, + FL_(burnMaxPower), + DeviceValueUOM::PERCENT, + MAKE_CF_CB(set_max_power), + 0, + 254); + register_device_value( + DeviceValueTAG::TAG_DEVICE_DATA, &boilHystOn_, DeviceValueType::INT, FL_(boilHystOn), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_hyst_on), -20, 0); + register_device_value( + DeviceValueTAG::TAG_DEVICE_DATA, &boilHystOff_, DeviceValueType::INT, FL_(boilHystOff), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_hyst_off), 0, 20); + register_device_value( + DeviceValueTAG::TAG_DEVICE_DATA, &boil2HystOn_, DeviceValueType::INT, FL_(boil2HystOn), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_hyst2_on), -20, 0); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &boil2HystOff_, + DeviceValueType::INT, + FL_(boil2HystOff), + DeviceValueUOM::DEGREES_R, + MAKE_CF_CB(set_hyst2_off), + 0, + 20); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &burnMinPeriod_, + DeviceValueType::UINT, + FL_(burnMinPeriod), + DeviceValueUOM::MINUTES, + MAKE_CF_CB(set_burn_period), + 0, + 120); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &absBurnPow_, DeviceValueType::UINT, FL_(absBurnPow), DeviceValueUOM::PERCENT); + } register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &heatingActivated_, DeviceValueType::BOOL, @@ -215,33 +260,8 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const DeviceValueTAG::TAG_DEVICE_DATA, &pumpMode_, DeviceValueType::ENUM, FL_(enum_pumpMode), FL_(pumpMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_pumpMode)); register_device_value( DeviceValueTAG::TAG_DEVICE_DATA, &pumpDelay_, DeviceValueType::UINT, FL_(pumpDelay), DeviceValueUOM::MINUTES, MAKE_CF_CB(set_pump_delay), 0, 60); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, - &burnMinPeriod_, - DeviceValueType::UINT, - FL_(burnMinPeriod), - DeviceValueUOM::MINUTES, - MAKE_CF_CB(set_burn_period), - 0, - 120); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, - &burnMinPower_, - DeviceValueType::UINT, - FL_(burnMinPower), - DeviceValueUOM::PERCENT, - MAKE_CF_CB(set_min_power)); - register_device_value( - DeviceValueTAG::TAG_DEVICE_DATA, &burnMaxPower_, DeviceValueType::UINT, FL_(burnMaxPower), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_max_power), 0, 254); - register_device_value( - DeviceValueTAG::TAG_DEVICE_DATA, &boilHystOn_, DeviceValueType::INT, FL_(boilHystOn), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_hyst_on), -20, 0); - register_device_value( - DeviceValueTAG::TAG_DEVICE_DATA, &boilHystOff_, DeviceValueType::INT, FL_(boilHystOff), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_hyst_off), 0, 20); - register_device_value( - DeviceValueTAG::TAG_DEVICE_DATA, &boil2HystOn_, DeviceValueType::INT, FL_(boil2HystOn), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_hyst2_on), -20, 0); - register_device_value( - DeviceValueTAG::TAG_DEVICE_DATA, &boil2HystOff_, DeviceValueType::INT, FL_(boil2HystOff), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_hyst2_off), 0, 20); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &setFlowTemp_, DeviceValueType::UINT, FL_(setFlowTemp), DeviceValueUOM::DEGREES); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &setBurnPow_, DeviceValueType::UINT, FL_(setBurnPow), DeviceValueUOM::PERCENT); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &absBurnPow_, DeviceValueType::UINT, FL_(absBurnPow), DeviceValueUOM::PERCENT); register_device_value( DeviceValueTAG::TAG_DEVICE_DATA, &selBurnPow_, DeviceValueType::UINT, FL_(selBurnPow), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_burn_power), 0, 254); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &curBurnPow_, DeviceValueType::UINT, FL_(curBurnPow), DeviceValueUOM::PERCENT); @@ -924,7 +944,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const EMSESP::send_read_request(0xC2, device_id); // read last errorcode on start (only published on errors) - if (model() != EMS_DEVICE_FLAG_HEATPUMP) { + if (model() != EMS_DEVICE_FLAG_HEATPUMP && model() != EMS_DEVICE_FLAG_HIU) { register_telegram_type(0x04, "UBAFactory", true, MAKE_PF_CB(process_UBAFactory)); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &nomPower_, DeviceValueType::UINT, FL_(nomPower), DeviceValueUOM::KW, MAKE_CF_CB(set_nomPower)); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, @@ -1269,7 +1289,7 @@ void Boiler::process_UBAMonitorFastPlus(std::shared_ptr telegram has_update(telegram, heatblock_, 23); // see #1317 has_update(telegram, headertemp_, 25); // see #1317 //has_update(telegram, temperatur_, 27); // unknown temperature - telegram->read_value(exhaustTemp1_ , 31); + telegram->read_value(exhaustTemp1_, 31); if (Helpers::hasValue(exhaustTemp1_)) { has_update(exhaustTemp_, exhaustTemp1_); } diff --git a/src/devices/mixer.cpp b/src/devices/mixer.cpp index 5f4a94fbe..836036753 100644 --- a/src/devices/mixer.cpp +++ b/src/devices/mixer.cpp @@ -26,61 +26,16 @@ uuid::log::Logger Mixer::logger_{F_(mixer), uuid::log::Facility::CONSOLE}; Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand) : EMSdevice(device_type, device_id, product_id, version, name, flags, brand) { - // Pool module - if (flags == EMSdevice::EMS_DEVICE_FLAG_MP) { - register_telegram_type(0x5BA, "HpPoolStatus", true, MAKE_PF_CB(process_HpPoolStatus)); - type_ = Type::MP; - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, - &poolTemp_, - DeviceValueType::SHORT, - DeviceValueNumOp::DV_NUMOP_DIV10, - FL_(poolTemp), - DeviceValueUOM::DEGREES); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &poolShuntStatus_, DeviceValueType::ENUM, FL_(enum_shunt), FL_(poolShuntStatus), DeviceValueUOM::NONE); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &poolShunt_, DeviceValueType::UINT, FL_(poolShunt), DeviceValueUOM::PERCENT); - } - // EMS+ if (flags == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { - if (device_id >= 0x20 && device_id <= 0x27) { - register_telegram_type(device_id - 0x20 + 0x02D7, "MMPLUSStatusMessage_HC", false, MAKE_PF_CB(process_MMPLUSStatusMessage_HC)); - // register_telegram_type(device_id - 0x20 + 0x02E1, "MMPLUSSetMessage_HC", true, MAKE_PF_CB(process_MMPLUSSetMessage_HC)); - type_ = Type::HC; - hc_ = device_id - 0x20 + 1; - uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1; - register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(flowTempHc), DeviceValueUOM::DEGREES); - register_device_value(tag, &status_, DeviceValueType::INT, FL_(mixerStatus), DeviceValueUOM::PERCENT); - register_device_value(tag, &flowSetTemp_, DeviceValueType::UINT, FL_(flowSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flowSetTemp)); - register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, FL_(pumpStatus), DeviceValueUOM::NONE, MAKE_CF_CB(set_pump)); - } else if (device_id >= 0x28 && device_id <= 0x29) { - register_telegram_type(device_id - 0x28 + 0x0331, "MMPLUSStatusMessage_WWC", false, MAKE_PF_CB(process_MMPLUSStatusMessage_WWC)); - register_telegram_type(device_id - 0x28 + 0x0313, "MMPLUSConfigMessage_WWC", true, MAKE_PF_CB(process_MMPLUSConfigMessage_WWC)); - // register_telegram_type(device_id - 0x28 + 0x033B, "MMPLUSSetMessage_WWC", true, MAKE_PF_CB(process_MMPLUSSetMessage_WWC)); - type_ = Type::WWC; - hc_ = device_id - 0x28 + 1; - uint8_t tag = DeviceValueTAG::TAG_WWC1 + hc_ - 1; - register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp), DeviceValueUOM::DEGREES); - register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, FL_(wwPumpStatus), DeviceValueUOM::NONE); - register_device_value(tag, &status_, DeviceValueType::INT, FL_(wwTempStatus), DeviceValueUOM::NONE); - - register_device_value(tag, &wwMaxTemp_, DeviceValueType::UINT, FL_(wwMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwMaxTemp)); - register_device_value(tag, &wwDiffTemp_, DeviceValueType::INT, FL_(wwDiffTemp), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwDiffTemp)); - register_device_value(tag, - &wwDisinfectionTemp_, - DeviceValueType::UINT, - FL_(wwDisinfectionTemp), - DeviceValueUOM::DEGREES, - MAKE_CF_CB(set_wwDisinfectionTemp)); - register_device_value(tag, &wwReducedTemp_, DeviceValueType::UINT, FL_(wwRedTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwReducedTemp)); - register_device_value(tag, &wwRequiredTemp_, DeviceValueType::UINT, FL_(wwRequiredTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwRequiredTemp)); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwCircPump_, - DeviceValueType::BOOL, - FL_(wwCircPump), - DeviceValueUOM::NONE, - MAKE_CF_CB(set_wwCircPump)); - register_device_value(tag, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCircMode)); - } + register_telegram_type(device_id - 0x20 + 0x02D7, "MMPLUSStatusMessage_HC", false, MAKE_PF_CB(process_MMPLUSStatusMessage_HC)); + // register_telegram_type(device_id - 0x20 + 0x02E1, "MMPLUSSetMessage_HC", true, MAKE_PF_CB(process_MMPLUSSetMessage_HC)); + hc_ = device_id - 0x20 + 1; + uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1; + register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(flowTempHc), DeviceValueUOM::DEGREES); + register_device_value(tag, &status_, DeviceValueType::UINT, FL_(mixerStatus), DeviceValueUOM::PERCENT); + register_device_value(tag, &flowSetTemp_, DeviceValueType::UINT, FL_(flowSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flowSetTemp)); + register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, FL_(pumpStatus), DeviceValueUOM::NONE, MAKE_CF_CB(set_pump)); } // EMS 1.0 @@ -88,7 +43,6 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c register_telegram_type(0x00AA, "MMConfigMessage", true, MAKE_PF_CB(process_MMConfigMessage)); register_telegram_type(0x00AB, "MMStatusMessage", false, MAKE_PF_CB(process_MMStatusMessage)); register_telegram_type(0x00AC, "MMSetMessage", false, MAKE_PF_CB(process_MMSetMessage)); - type_ = Type::HC; hc_ = device_id - 0x20 + 1; uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1; register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(flowTempHc), DeviceValueUOM::DEGREES); @@ -109,48 +63,16 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c // HT3 if (flags == EMSdevice::EMS_DEVICE_FLAG_IPM) { - if (device_id >= 0x40) { // special DHW pos 10 - register_telegram_type(0x34, "UBAMonitorWW", false, MAKE_PF_CB(process_IPMMonitorWW)); - register_telegram_type(0x1E, "HydrTemp", false, MAKE_PF_CB(process_IPMHydrTemp)); - register_telegram_type(0x33, "UBAParameterWW", true, MAKE_PF_CB(process_IPMParameterWW)); - // register_telegram_type(0x10D, "wwNTCStatus", false, MAKE_PF_CB(process_wwNTCStatus)); - type_ = Type::WWC; - hc_ = device_id - 0x40 + 1; - uint8_t tag = DeviceValueTAG::TAG_WWC9 + hc_ - 1; - register_device_value(tag, &wwSelTemp_, DeviceValueType::UINT, FL_(wwSelTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwSelTemp)); - register_device_value(tag, &wwCurTemp_1_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwCurTemp), DeviceValueUOM::DEGREES); - register_device_value(tag, &wwCurTemp_2_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwCurTemp2), DeviceValueUOM::DEGREES); - register_device_value(tag, &HydrTemp_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(hydrTemp), DeviceValueUOM::DEGREES); - register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, FL_(pumpStatus), DeviceValueUOM::NONE); - register_device_value(tag, &wwFlowTempOffset_, DeviceValueType::UINT, FL_(wwFlowTempOffset), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwFlowTempOffset)); - register_device_value(tag, &wwHystOn_, DeviceValueType::INT, FL_(wwHystOn), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwHystOn)); - register_device_value(tag, &wwHystOff_, DeviceValueType::INT, FL_(wwHystOff), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwHystOff)); - register_device_value(tag, - &wwDisinfectionTemp_, - DeviceValueType::UINT, - FL_(wwDisinfectionTemp), - DeviceValueUOM::DEGREES, - MAKE_CF_CB(set_wwDisinfectionTemp)); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwCircPump_, - DeviceValueType::BOOL, - FL_(wwCircPump), - DeviceValueUOM::NONE, - MAKE_CF_CB(set_wwCircPump)); - register_device_value(tag, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCircMode)); - } else { - register_telegram_type(0x010C, "IPMStatusMessage", false, MAKE_PF_CB(process_IPMStatusMessage)); - register_telegram_type(0x011E, "IPMTempMessage", false, MAKE_PF_CB(process_IPMTempMessage)); - // register_telegram_type(0x0123, "IPMSetMessage", false, MAKE_PF_CB(process_IPMSetMessage)); - type_ = Type::HC; - hc_ = device_id - 0x20 + 1; - uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1; - register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(flowTempHc), DeviceValueUOM::DEGREES); - register_device_value(tag, &status_, DeviceValueType::INT, FL_(mixerStatus), DeviceValueUOM::PERCENT); - register_device_value(tag, &flowSetTemp_, DeviceValueType::UINT, FL_(flowSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flowSetTemp)); - register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, FL_(pumpStatus), DeviceValueUOM::NONE, MAKE_CF_CB(set_pump)); - register_device_value(tag, &flowTempVf_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(flowTempVf), DeviceValueUOM::DEGREES); - } + register_telegram_type(0x010C, "IPMStatusMessage", false, MAKE_PF_CB(process_IPMStatusMessage)); + register_telegram_type(0x011E, "IPMTempMessage", false, MAKE_PF_CB(process_IPMTempMessage)); + // register_telegram_type(0x0123, "IPMSetMessage", false, MAKE_PF_CB(process_IPMSetMessage)); + hc_ = device_id - 0x20 + 1; + uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1; + register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(flowTempHc), DeviceValueUOM::DEGREES); + register_device_value(tag, &status_, DeviceValueType::UINT, FL_(mixerStatus), DeviceValueUOM::PERCENT); + register_device_value(tag, &flowSetTemp_, DeviceValueType::UINT, FL_(flowSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flowSetTemp)); + register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, FL_(pumpStatus), DeviceValueUOM::NONE, MAKE_CF_CB(set_pump)); + register_device_value(tag, &flowTempVf_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(flowTempVf), DeviceValueUOM::DEGREES); } } @@ -164,15 +86,6 @@ void Mixer::process_MMPLUSStatusMessage_HC(std::shared_ptr teleg has_update(telegram, status_, 2); // valve status } -// Mixer warm water loading/DHW - 0x0331, 0x0332 -// e.g. A9 00 FF 00 02 32 02 6C 00 3C 00 3C 3C 46 02 03 03 00 3C // on 0x28 -// A8 00 FF 00 02 31 02 35 00 3C 00 3C 3C 46 02 03 03 00 3C // in 0x29 -void Mixer::process_MMPLUSStatusMessage_WWC(std::shared_ptr telegram) { - has_update(telegram, flowTempHc_, 0); // is * 10 - has_bitupdate(telegram, pumpStatus_, 2, 0); - has_update(telegram, status_, 11); // temp status -} - // Mixer IPM - 0x010C // e.g. A0 00 FF 00 00 0C 01 00 00 00 00 00 54 // A1 00 FF 00 00 0C 02 04 00 01 1D 00 82 @@ -200,15 +113,6 @@ void Mixer::process_IPMTempMessage(std::shared_ptr telegram) { has_update(telegram, flowTempVf_, 0); // TC1, is * 10 } -// Mixer MP100 for pools - 0x5BA -void Mixer::process_HpPoolStatus(std::shared_ptr telegram) { - has_update(telegram, poolTemp_, 0); - has_update(telegram, poolShunt_, 3); // 0-100% how much is the shunt open? - telegram->read_value(poolShuntStatus__, 2); - uint8_t pss = poolShunt_ == 100 ? 3 : (poolShunt_ == 0 ? 4 : poolShuntStatus__); - has_update(poolShuntStatus_, pss); -} - // Mixer on a MM10 - 0xAB // e.g. Mixer Module -> All, type 0xAB, telegram: 21 00 AB 00 2D 01 BE 64 04 01 00 (CRC=15) #data=7 // see also https://github.com/emsesp/EMS-ESP/issues/386 @@ -235,43 +139,6 @@ void Mixer::process_MMConfigMessage(std::shared_ptr telegram) { has_update(telegram, setValveTime_, 1); // valve runtime in 10 sec, max 120 s } -// Config message 0x313, has to be fetched -void Mixer::process_MMPLUSConfigMessage_WWC(std::shared_ptr telegram) { - has_update(telegram, wwRequiredTemp_, 4); - has_update(telegram, wwReducedTemp_, 5); - has_update(telegram, wwDiffTemp_, 7); - has_update(telegram, wwDisinfectionTemp_, 9); - has_update(telegram, wwMaxTemp_, 10); -} - -// 0x34 only 8 bytes long -// Mixer(0x41) -> All(0x00), UBAMonitorWW(0x34), data: 37 02 1E 02 1E 00 00 00 00 -void Mixer::process_IPMMonitorWW(std::shared_ptr telegram) { - has_update(telegram, wwSelTemp_, 0); - has_update(telegram, wwCurTemp_1_, 1); - has_update(telegram, wwCurTemp_2_, 3); - has_bitupdate(telegram, pumpStatus_, 5, 3); -} - -// Mixer(0x41) -> Me(0x0B), UBAParameterWW(0x33), data: 08 FF 46 FB FF 28 FF 07 46 00 FF 00 -void Mixer::process_IPMParameterWW(std::shared_ptr telegram) { - // has_update(telegram, wwActivated_, 1); // 0xFF means on - // has_update(telegram, wwSelTemp_, 2); - has_update(telegram, wwHystOn_, 3); // Hyst on (default -5) - has_update(telegram, wwHystOff_, 4); // Hyst off (default -1) - has_update(telegram, wwFlowTempOffset_, 5); // default 40 - has_update(telegram, wwCircPump_, 6); // 0xFF means on - has_update(telegram, wwCircMode_, 7); // 1=1x3min 6=6x3min 7=continuous - has_update(telegram, wwDisinfectionTemp_, 8); - // has_bitupdate(telegram, wwChargeType_, 10, 0); // 0 = charge pump, 0xff = 3-way valve -} - - -// 0x1E, only16 bit temperature -// Mixer(0x41) -> Boiler(0x08), HydrTemp(0x1E), data: 01 D8 -void Mixer::process_IPMHydrTemp(std::shared_ptr telegram) { - has_update(telegram, HydrTemp_, 0); -} #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" @@ -284,16 +151,6 @@ void Mixer::process_MMPLUSSetMessage_HC(std::shared_ptr telegram // pos2: pump } -// unknown, 2 examples from older threads -// Thermostat(0x10) -> Mixer(0x28), ?(0x33B), data: 01 01 00 -// Thermostat -> Mixing Module, type 0x023B, telegram: 90 28 FF 00 02 3B 00 02 00 (CRC=68) -void Mixer::process_MMPLUSSetMessage_WWC(std::shared_ptr telegram) { -} - -// MMPLUS telegram 0x345 unknown -// Solar Module -> Mixing Module, type 0x0245, telegram: B0 28 FF 00 02 45 64 01 01 (CRC=36) -// ? - // Mixer on a MM10 - 0xAC // e.g. Thermostat -> Mixer Module, type 0xAC, telegram: 10 21 AC 00 1E 64 01 AB void Mixer::process_MMSetMessage(std::shared_ptr telegram) { @@ -311,15 +168,6 @@ void Mixer::process_IPMSetMessage(std::shared_ptr telegram) { #pragma GCC diagnostic pop -bool Mixer::set_wwSelTemp(const char * value, const int8_t id) { - int temperature; - if (!Helpers::value2temperature(value, temperature)) { - return false; - } - write_command(0x35, 3, (uint8_t)temperature, 0x34); - return true; -} - bool Mixer::set_flowSetTemp(const char * value, const int8_t id) { int v; if (!Helpers::value2number(value, v)) { @@ -389,113 +237,4 @@ bool Mixer::set_setValveTime(const char * value, const int8_t id) { return false; } -bool Mixer::set_wwMaxTemp(const char * value, const int8_t id) { - uint8_t wwc = device_id() - 0x28; - float v; - if (!Helpers::value2temperature(value, v)) { - return false; - } - write_command(0x313 + wwc, 10, (uint8_t)v, 0x313 + wwc); - return true; -} - -bool Mixer::set_wwDiffTemp(const char * value, const int8_t id) { - uint8_t wwc = device_id() - 0x28; - float v; - if (!Helpers::value2temperature(value, v)) { - return false; - } - write_command(0x313 + wwc, 7, (int8_t)(v * 10), 0x313 + wwc); - return true; -} - -bool Mixer::set_wwReducedTemp(const char * value, const int8_t id) { - uint8_t wwc = device_id() - 0x28; - float v; - if (!Helpers::value2temperature(value, v)) { - return false; - } - write_command(0x313 + wwc, 5, (uint8_t)v, 0x313 + wwc); - return true; -} - -bool Mixer::set_wwRequiredTemp(const char * value, const int8_t id) { - uint8_t wwc = device_id() - 0x28; - float v; - if (!Helpers::value2temperature(value, v)) { - return false; - } - write_command(0x313 + wwc, 4, (uint8_t)v, 0x313 + wwc); - return true; -} - -bool Mixer::set_wwDisinfectionTemp(const char * value, const int8_t id) { - float v; - if (!Helpers::value2temperature(value, v)) { - return false; - } - if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) { - write_command(0x33, 8, (uint8_t)v, 0x33); - } else { - uint8_t wwc = device_id() - 0x28; - write_command(0x313 + wwc, 9, (uint8_t)v, 0x313 + wwc); - } - return true; -} - -bool Mixer::set_wwCircPump(const char * value, const int8_t id) { - bool v; - if (!Helpers::value2bool(value, v)) { - return false; - } - if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) { - write_command(0x33, 6, v ? 0xFF : 0x00, 0x33); - } else { - uint8_t wwc = device_id() - 0x28; - write_command(0x33B + wwc, 0, v ? 0x01 : 0x00, 0x33B + wwc); - } - return true; -} - -bool Mixer::set_wwCircMode(const char * value, const int8_t id) { - uint8_t n; - if (!Helpers::value2enum(value, n, FL_(enum_wwCircMode))) { - return false; - } - if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) { - write_command(0x33, 7, n, 0x33); - } else { - uint8_t wwc = device_id() - 0x28; - write_command(0x313 + wwc, 0, n, 0x313 + wwc); - } - return true; -} - -bool Mixer::set_wwFlowTempOffset(const char * value, const int8_t id) { - int n; - if (!Helpers::value2number(value, n)) { - return false; - } - write_command(0x33, 5, n, 0x33); - return true; -} - -bool Mixer::set_wwHystOn(const char * value, const int8_t id) { - int n; - if (!Helpers::value2number(value, n)) { - return false; - } - write_command(0x33, 3, n, 0x33); - return true; -} - -bool Mixer::set_wwHystOff(const char * value, const int8_t id) { - int n; - if (!Helpers::value2number(value, n)) { - return false; - } - write_command(0x33, 4, n, 0x33); - return true; -} - } // namespace emsesp diff --git a/src/devices/mixer.h b/src/devices/mixer.h index b509cd3e6..cb19c9d7b 100644 --- a/src/devices/mixer.h +++ b/src/devices/mixer.h @@ -32,46 +32,18 @@ class Mixer : public EMSdevice { void process_MMPLUSStatusMessage_HC(std::shared_ptr telegram); void process_MMPLUSSetMessage_HC(std::shared_ptr telegram); - void process_MMPLUSStatusMessage_WWC(std::shared_ptr telegram); - void process_MMPLUSSetMessage_WWC(std::shared_ptr telegram); - void process_MMPLUSConfigMessage_WWC(std::shared_ptr telegram); void process_IPMStatusMessage(std::shared_ptr telegram); void process_IPMTempMessage(std::shared_ptr telegram); void process_IPMSetMessage(std::shared_ptr telegram); void process_MMStatusMessage(std::shared_ptr telegram); void process_MMConfigMessage(std::shared_ptr telegram); void process_MMSetMessage(std::shared_ptr telegram); - void process_HpPoolStatus(std::shared_ptr telegram); - - void process_IPMMonitorWW(std::shared_ptr telegram); - void process_IPMHydrTemp(std::shared_ptr telegram); - void process_IPMParameterWW(std::shared_ptr telegram); bool set_flowSetTemp(const char * value, const int8_t id); bool set_pump(const char * value, const int8_t id); bool set_activated(const char * value, const int8_t id); bool set_setValveTime(const char * value, const int8_t id); - bool set_wwMaxTemp(const char * value, const int8_t id); - bool set_wwDiffTemp(const char * value, const int8_t id); - bool set_wwReducedTemp(const char * value, const int8_t id); - bool set_wwRequiredTemp(const char * value, const int8_t id); - bool set_wwDisinfectionTemp(const char * value, const int8_t id); - bool set_wwCircPump(const char * value, const int8_t id); - bool set_wwCircMode(const char * value, const int8_t id); - - bool set_wwSelTemp(const char * value, const int8_t id); - bool set_wwFlowTempOffset(const char * value, const int8_t id); - bool set_wwHystOn(const char * value, const int8_t id); - bool set_wwHystOff(const char * value, const int8_t id); - - enum class Type { - NONE, - HC, // heating circuit - WWC, // warm water circuit - MP // pool - }; - private: uint16_t flowTempHc_; uint16_t flowTempVf_; @@ -81,31 +53,7 @@ class Mixer : public EMSdevice { uint8_t activated_; uint8_t setValveTime_; - // MM100wwParam - 0x0313, 0x033B - uint8_t wwMaxTemp_; - uint8_t wwRequiredTemp_; - uint8_t wwReducedTemp_; - uint8_t wwDiffTemp_; - uint8_t wwDisinfectionTemp_; - uint8_t wwCircPump_; - uint8_t wwCircMode_; - - // MP100 pool - int16_t poolTemp_; - uint8_t poolShuntStatus_; - uint8_t poolShunt_; - - Type type_ = Type::NONE; uint16_t hc_ = EMS_VALUE_USHORT_NOTSET; - uint8_t poolShuntStatus__ = EMS_VALUE_UINT_NOTSET; // temp value - - uint8_t wwSelTemp_; - uint16_t wwCurTemp_1_; - uint16_t wwCurTemp_2_; - uint16_t HydrTemp_; - int8_t wwHystOn_; // Hyst on (default -5) - int8_t wwHystOff_; // Hyst off (default -1) - uint8_t wwFlowTempOffset_; // default 40 }; } // namespace emsesp diff --git a/src/devices/pool.cpp b/src/devices/pool.cpp new file mode 100644 index 000000000..16b1cd232 --- /dev/null +++ b/src/devices/pool.cpp @@ -0,0 +1,50 @@ +/* + * EMS-ESP - https://github.com/emsesp/EMS-ESP + * Copyright 2020-2023 Paul Derbyshire + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "pool.h" + +namespace emsesp { + +REGISTER_FACTORY(Pool, EMSdevice::DeviceType::POOL); + +uuid::log::Logger Pool::logger_{F_(pool), uuid::log::Facility::CONSOLE}; + +Pool::Pool(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand) + : EMSdevice(device_type, device_id, product_id, version, name, flags, brand) { + // Pool module + register_telegram_type(0x5BA, "HpPoolStatus", true, MAKE_PF_CB(process_HpPoolStatus)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &poolTemp_, + DeviceValueType::SHORT, + DeviceValueNumOp::DV_NUMOP_DIV10, + FL_(poolTemp), + DeviceValueUOM::DEGREES); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &poolShuntStatus_, DeviceValueType::ENUM, FL_(enum_shunt), FL_(poolShuntStatus), DeviceValueUOM::NONE); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &poolShunt_, DeviceValueType::UINT, FL_(poolShunt), DeviceValueUOM::PERCENT); +} + +// Mixer MP100 for pools - 0x5BA +void Pool::process_HpPoolStatus(std::shared_ptr telegram) { + has_update(telegram, poolTemp_, 0); + has_update(telegram, poolShunt_, 3); // 0-100% how much is the shunt open? + telegram->read_value(poolShuntStatus__, 2); + uint8_t pss = poolShunt_ == 100 ? 3 : (poolShunt_ == 0 ? 4 : poolShuntStatus__); + has_update(poolShuntStatus_, pss); +} + +} // namespace emsesp diff --git a/src/devices/pool.h b/src/devices/pool.h new file mode 100644 index 000000000..dc4092eb1 --- /dev/null +++ b/src/devices/pool.h @@ -0,0 +1,46 @@ +/* + * EMS-ESP - https://github.com/emsesp/EMS-ESP + * Copyright 2020-2023 Paul Derbyshire + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef EMSESP_POOL_H +#define EMSESP_POOL_H + +#include "emsesp.h" + +namespace emsesp { + +class Pool : public EMSdevice { + public: + Pool(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand); + + private: + static uuid::log::Logger logger_; + + void process_HpPoolStatus(std::shared_ptr telegram); + + private: + // MP100 pool + int16_t poolTemp_; + uint8_t poolShuntStatus_; + uint8_t poolShunt_; + + uint8_t poolShuntStatus__ = EMS_VALUE_UINT_NOTSET; // temp value +}; + +} // namespace emsesp + +#endif diff --git a/src/devices/solar.cpp b/src/devices/solar.cpp index 53e1547fc..08e5c9fab 100644 --- a/src/devices/solar.cpp +++ b/src/devices/solar.cpp @@ -34,32 +34,22 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c } if (flags == EMSdevice::EMS_DEVICE_FLAG_SM100) { - if (device_id == 0x2A) { // SM100 DHW - register_telegram_type(0x07D6, "SM100wwTemperature", false, MAKE_PF_CB(process_SM100wwTemperature)); - register_telegram_type(0x07AA, "SM100wwStatus", false, MAKE_PF_CB(process_SM100wwStatus)); - register_telegram_type(0x07AB, "SM100wwCommand", false, MAKE_PF_CB(process_SM100wwCommand)); - register_telegram_type(0x07A5, "SM100wwCirc", true, MAKE_PF_CB(process_SM100wwCirc)); - register_telegram_type(0x07A6, "SM100wwParam", true, MAKE_PF_CB(process_SM100wwParam)); - register_telegram_type(0x07AE, "SM100wwKeepWarm", true, MAKE_PF_CB(process_SM100wwKeepWarm)); - register_telegram_type(0x07E0, "SM100wwStatus2", true, MAKE_PF_CB(process_SM100wwStatus2)); - } else { - // F9 is not a telegram type, it's a flag for configure - // register_telegram_type(0xF9, "ParamCfg", false, MAKE_PF_CB(process_SM100ParamCfg)); - register_telegram_type(0x0358, "SM100SystemConfig", true, MAKE_PF_CB(process_SM100SystemConfig)); - register_telegram_type(0x035A, "SM100CircuitConfig", true, MAKE_PF_CB(process_SM100CircuitConfig)); - register_telegram_type(0x035D, "SM100Circuit2Config", true, MAKE_PF_CB(process_SM100Circuit2Config)); - register_telegram_type(0x0362, "SM100Monitor", false, MAKE_PF_CB(process_SM100Monitor)); - register_telegram_type(0x0363, "SM100Monitor2", false, MAKE_PF_CB(process_SM100Monitor2)); - register_telegram_type(0x0366, "SM100Config", false, MAKE_PF_CB(process_SM100Config)); - register_telegram_type(0x0364, "SM100Status", false, MAKE_PF_CB(process_SM100Status)); - register_telegram_type(0x036A, "SM100Status2", false, MAKE_PF_CB(process_SM100Status2)); - register_telegram_type(0x0380, "SM100CollectorConfig", true, MAKE_PF_CB(process_SM100CollectorConfig)); - register_telegram_type(0x038E, "SM100Energy", true, MAKE_PF_CB(process_SM100Energy)); - register_telegram_type(0x0391, "SM100Time", true, MAKE_PF_CB(process_SM100Time)); - register_telegram_type(0x035F, "SM100Config1", true, MAKE_PF_CB(process_SM100Config1)); - register_telegram_type(0x035C, "SM100HeatAssist", true, MAKE_PF_CB(process_SM100HeatAssist)); - register_telegram_type(0x0361, "SM100Differential", true, MAKE_PF_CB(process_SM100Differential)); - } + // F9 is not a telegram type, it's a flag for configure + // register_telegram_type(0xF9, "ParamCfg", false, MAKE_PF_CB(process_SM100ParamCfg)); + register_telegram_type(0x0358, "SM100SystemConfig", true, MAKE_PF_CB(process_SM100SystemConfig)); + register_telegram_type(0x035A, "SM100CircuitConfig", true, MAKE_PF_CB(process_SM100CircuitConfig)); + register_telegram_type(0x035D, "SM100Circuit2Config", true, MAKE_PF_CB(process_SM100Circuit2Config)); + register_telegram_type(0x0362, "SM100Monitor", false, MAKE_PF_CB(process_SM100Monitor)); + register_telegram_type(0x0363, "SM100Monitor2", false, MAKE_PF_CB(process_SM100Monitor2)); + register_telegram_type(0x0366, "SM100Config", false, MAKE_PF_CB(process_SM100Config)); + register_telegram_type(0x0364, "SM100Status", false, MAKE_PF_CB(process_SM100Status)); + register_telegram_type(0x036A, "SM100Status2", false, MAKE_PF_CB(process_SM100Status2)); + register_telegram_type(0x0380, "SM100CollectorConfig", true, MAKE_PF_CB(process_SM100CollectorConfig)); + register_telegram_type(0x038E, "SM100Energy", true, MAKE_PF_CB(process_SM100Energy)); + register_telegram_type(0x0391, "SM100Time", true, MAKE_PF_CB(process_SM100Time)); + register_telegram_type(0x035F, "SM100Config1", true, MAKE_PF_CB(process_SM100Config1)); + register_telegram_type(0x035C, "SM100HeatAssist", true, MAKE_PF_CB(process_SM100HeatAssist)); + register_telegram_type(0x0361, "SM100Differential", true, MAKE_PF_CB(process_SM100Differential)); } if (flags == EMSdevice::EMS_DEVICE_FLAG_ISM) { @@ -69,94 +59,6 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c } // device values... - // special case for a SM100 DHW device_id with 0x2A where it's not actual a solar module - if (device_id == 0x2A) { - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwTemp_1_, - DeviceValueType::USHORT, - DeviceValueNumOp::DV_NUMOP_DIV10, - FL_(wwTemp1), - DeviceValueUOM::DEGREES); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwTemp_3_, - DeviceValueType::USHORT, - DeviceValueNumOp::DV_NUMOP_DIV10, - FL_(wwTemp3), - DeviceValueUOM::DEGREES); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwTemp_4_, - DeviceValueType::USHORT, - DeviceValueNumOp::DV_NUMOP_DIV10, - FL_(wwTemp4), - DeviceValueUOM::DEGREES); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwTemp_5_, - DeviceValueType::USHORT, - DeviceValueNumOp::DV_NUMOP_DIV10, - FL_(wwTemp5), - DeviceValueUOM::DEGREES); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwTemp_7_, - DeviceValueType::USHORT, - DeviceValueNumOp::DV_NUMOP_DIV10, - FL_(wwTemp7), - DeviceValueUOM::DEGREES); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwPump_, DeviceValueType::BOOL, FL_(wwPump), DeviceValueUOM::NONE); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwMaxTemp_, - DeviceValueType::UINT, - FL_(wwMaxTemp), - DeviceValueUOM::DEGREES, - MAKE_CF_CB(set_wwMaxTemp)); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwSelTemp_, - DeviceValueType::UINT, - FL_(wwSelTemp), - DeviceValueUOM::DEGREES, - MAKE_CF_CB(set_wwSelTemp)); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwRedTemp_, - DeviceValueType::UINT, - FL_(wwRedTemp), - DeviceValueUOM::DEGREES, - MAKE_CF_CB(set_wwRedTemp)); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwDailyTemp_, - DeviceValueType::UINT, - FL_(wwDailyTemp), - DeviceValueUOM::DEGREES, - MAKE_CF_CB(set_wwDailyTemp)); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwDisinfectionTemp_, - DeviceValueType::UINT, - FL_(wwDisinfectionTemp), - DeviceValueUOM::DEGREES, - MAKE_CF_CB(set_wwDisinfectionTemp)); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwCirc_, DeviceValueType::BOOL, FL_(wwCirc), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCirc)); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwCircMode_, - DeviceValueType::ENUM, - FL_(enum_wwCircMode), - FL_(wwCircMode), - DeviceValueUOM::NONE, - MAKE_CF_CB(set_wwCircMode)); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwKeepWarm_, - DeviceValueType::BOOL, - FL_(wwKeepWarm), - DeviceValueUOM::NONE, - MAKE_CF_CB(set_wwKeepWarm)); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwStatus2_, DeviceValueType::ENUM, FL_(enum_wwStatus2), FL_(wwStatus2), DeviceValueUOM::NONE); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwPumpMod_, DeviceValueType::UINT, FL_(wwPumpMod), DeviceValueUOM::PERCENT); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW, - &wwFlow_, - DeviceValueType::UINT, - DeviceValueNumOp::DV_NUMOP_DIV10, - FL_(wwFlow), - DeviceValueUOM::LMIN); - return; - } - // common solar values for all modules (except dhw) register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &collectorTemp_, @@ -690,58 +592,6 @@ void Solar::process_SM100Monitor(std::shared_ptr telegram) { has_update(telegram, retHeatAssist_, 10); // is *10 - TS15: return temperature heating assistance } -// SM100wwTemperature - 0x07D6 -// Solar Module(0x2A) -> (0x00), (0x7D6), data: 01 C1 00 00 02 5B 01 AF 01 AD 80 00 01 90 -void Solar::process_SM100wwTemperature(std::shared_ptr telegram) { - has_update(telegram, wwTemp_1_, 0); // is *10 - has_update(telegram, wwTemp_3_, 4); // is *10 - has_update(telegram, wwTemp_4_, 6); // is *10 - has_update(telegram, wwTemp_5_, 8); // is *10 - has_update(telegram, wwTemp_7_, 12); // is *10 -} - -// SM100wwStatus - 0x07AA -// Solar Module(0x2A) -> (0x00), (0x7AA), data: 64 00 04 00 03 00 28 01 0F -void Solar::process_SM100wwStatus(std::shared_ptr telegram) { - has_update(telegram, wwPump_, 0); -} - -// SM100wwParam - 0x07A6, Solar Module(0x2A) -> (0x00) -// data: FF 05 0F 5F 00 01 3C 3C 3C 3C 28 12 46 01 3C 1E 03 07 3C 00 0F 00 05 -void Solar::process_SM100wwParam(std::shared_ptr telegram) { - has_update(telegram, wwMaxTemp_, 8); - has_update(telegram, wwSelTemp_, 9); - has_update(telegram, wwRedTemp_, 10); - has_update(telegram, wwDailyTemp_, 6); - has_update(telegram, wwDisinfectionTemp_, 12); - // (daily heating time thermostat 2F5, offset 9, offset 8 on/off) -} - -// SM100wwCirc - 0x07A5 -// Solar Module(0x2A) -> (0x00), (0x7A5), data: -void Solar::process_SM100wwCirc(std::shared_ptr telegram) { - has_update(telegram, wwCirc_, 0); - has_update(telegram, wwCircMode_, 3); -} - -// SM100wwKeepWarm - 0x7AE, keepWarm -// Thermostat(0x10) -> Solar(0x2A), ?(0x7AE), data: FF -void Solar::process_SM100wwKeepWarm(std::shared_ptr telegram) { - has_update(telegram, wwKeepWarm_, 0); -} - -/* -// SM100ww? - 0x7E0, some kind of status -// data: 00 00 46 00 00 01 06 0E 06 0E 00 00 00 00 00 03 03 03 03 -// publishes single values offset 1/2(16bit), offset 5, offset 6, offset 7, offset 8, offset 9, -// status2 = 03:"no heat", 06:"heat request", 08:"disinfecting", 09:"hold" -*/ -void Solar::process_SM100wwStatus2(std::shared_ptr telegram) { - has_update(telegram, wwFlow_, 7); - has_update(telegram, wwStatus2_, 8); - has_update(telegram, wwPumpMod_, 9); -} - // SM100Monitor2 - 0x0363 Heatcounter // e.g. B0 00 FF 00 02 63 80 00 80 00 00 00 80 00 80 00 80 00 00 80 00 5A // Solar(0x30) -> All(0x00), SM100Monitor2(0x363), data: 01 E1 01 6B 00 00 01 5D 02 8E 80 00 0F 80 00 @@ -753,17 +603,6 @@ void Solar::process_SM100Monitor2(std::shared_ptr telegram) { has_update(telegram->read_value(swapFlowTemp_, 8)); // is *10 } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" - -// SM100wwCommand - 0x07AB -// Thermostat(0x10) -> Solar Module(0x2A), (0x7AB), data: 01 00 01 -void Solar::process_SM100wwCommand(std::shared_ptr telegram) { - // not implemented yet -} - -#pragma GCC diagnostic pop - // SM100Config - 0x0366 // e.g. B0 00 FF 00 02 66 01 62 00 13 40 14 void Solar::process_SM100Config(std::shared_ptr telegram) { @@ -1249,76 +1088,4 @@ bool Solar::set_diffControl(const char * value, const int8_t id) { return true; } -bool Solar::set_wwSelTemp(const char * value, const int8_t id) { - int temperature; - if (!Helpers::value2temperature(value, temperature)) { - return false; - } - write_command(0x7A6, 9, (uint8_t)temperature, 0x7A6); - return true; -} - -bool Solar::set_wwMaxTemp(const char * value, const int8_t id) { - int temperature; - if (!Helpers::value2temperature(value, temperature)) { - return false; - } - write_command(0x7A6, 8, (uint8_t)temperature, 0x7A6); - return true; -} - -bool Solar::set_wwRedTemp(const char * value, const int8_t id) { - int temperature; - if (!Helpers::value2temperature(value, temperature)) { - return false; - } - write_command(0x7A6, 10, (uint8_t)temperature, 0x7A6); - return true; -} - -bool Solar::set_wwDailyTemp(const char * value, const int8_t id) { - int temperature; - if (!Helpers::value2temperature(value, temperature)) { - return false; - } - write_command(0x7A6, 6, (uint8_t)temperature, 0x7A6); - return true; -} - -bool Solar::set_wwDisinfectionTemp(const char * value, const int8_t id) { - int temperature; - if (!Helpers::value2temperature(value, temperature)) { - return false; - } - write_command(0x7A6, 12, (uint8_t)temperature, 0x7A6); - return true; -} - -bool Solar::set_wwCirc(const char * value, const int8_t id) { - bool b; - if (!Helpers::value2bool(value, b)) { - return false; - } - write_command(0x7A5, 0, b ? 0xFF : 0x00, 0x7A5); - return true; -} - -bool Solar::set_wwCircMode(const char * value, const int8_t id) { - uint8_t num; - if (!Helpers::value2enum(value, num, FL_(enum_wwCircMode))) { - return false; - } - write_command(0x7A5, 3, num, 0x7A5); - return true; -} - -bool Solar::set_wwKeepWarm(const char * value, const int8_t id) { - bool b; - if (!Helpers::value2bool(value, b)) { - return false; - } - write_command(0x7AE, 0, b ? 0xFF : 0x00, 0x7AE); - return true; -} - } // namespace emsesp diff --git a/src/devices/solar.h b/src/devices/solar.h index 16bb379bf..ef69095d1 100644 --- a/src/devices/solar.h +++ b/src/devices/solar.h @@ -114,35 +114,6 @@ class Solar : public EMSdevice { uint16_t collector2Area_; // Area of collector field 2 uint8_t collector2Type_; // Type of collector field 2, 01=flat, 02=vacuum - // SM100wwTemperature - 0x07D6 - uint16_t wwTemp_1_; - uint16_t wwTemp_3_; - uint16_t wwTemp_4_; - uint16_t wwTemp_5_; - uint16_t wwTemp_7_; - - // SM100wwStatus - 0x07AA - uint8_t wwPump_; - - // SM100wwParam - 0x07A6 - uint8_t wwMaxTemp_; - uint8_t wwSelTemp_; - uint8_t wwRedTemp_; - uint8_t wwDailyTemp_; - uint8_t wwDisinfectionTemp_; - - // SM100wwKeepWarm - 0x07AE - uint8_t wwKeepWarm_; - - // SM100wwCirc - 0x07A5 - uint8_t wwCirc_; - uint8_t wwCircMode_; - - // SM100wwStatus2 - 0x07E0 - uint8_t wwFlow_; - uint8_t wwPumpMod_; - uint8_t wwStatus2_; - // SM10Config - 0x96 uint8_t wwMinTemp_; uint8_t maxFlow_; // set this to calculate power @@ -178,14 +149,6 @@ class Solar : public EMSdevice { void process_SM100HeatAssist(std::shared_ptr telegram); void process_SM100Differential(std::shared_ptr telegram); - void process_SM100wwTemperature(std::shared_ptr telegram); - void process_SM100wwStatus(std::shared_ptr telegram); - void process_SM100wwStatus2(std::shared_ptr telegram); - void process_SM100wwCommand(std::shared_ptr telegram); - void process_SM100wwCirc(std::shared_ptr telegram); - void process_SM100wwParam(std::shared_ptr telegram); - void process_SM100wwKeepWarm(std::shared_ptr telegram); - void process_ISM1StatusMessage(std::shared_ptr telegram); void process_ISM1Set(std::shared_ptr telegram); void process_ISM2StatusMessage(std::shared_ptr telegram); @@ -226,14 +189,6 @@ class Solar : public EMSdevice { bool set_heatAssist(const char * value, const int8_t id); bool set_diffControl(const char * value, const int8_t id); - bool set_wwSelTemp(const char * value, const int8_t id); - bool set_wwMaxTemp(const char * value, const int8_t id); - bool set_wwRedTemp(const char * value, const int8_t id); - bool set_wwCirc(const char * value, const int8_t id); - bool set_wwCircMode(const char * value, const int8_t id); - bool set_wwKeepWarm(const char * value, const int8_t id); - bool set_wwDisinfectionTemp(const char * value, const int8_t id); - bool set_wwDailyTemp(const char * value, const int8_t id); }; } // namespace emsesp diff --git a/src/devices/water.cpp b/src/devices/water.cpp new file mode 100644 index 000000000..486af763b --- /dev/null +++ b/src/devices/water.cpp @@ -0,0 +1,392 @@ +/* + * EMS-ESP - https://github.com/emsesp/EMS-ESP + * Copyright 2020-2023 Paul Derbyshire + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "water.h" + +namespace emsesp { + +REGISTER_FACTORY(Water, EMSdevice::DeviceType::WATER); + +uuid::log::Logger Water::logger_{F_(water), uuid::log::Facility::CONSOLE}; + +Water::Water(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand) + : EMSdevice(device_type, device_id, product_id, version, name, flags, brand) { + uint8_t tag = DeviceValueTAG::TAG_WWC1 + device_id - EMSdevice::EMS_DEVICE_ID_DHW1; + if (device_id == 0x2A) { // SM100, DHW3 + wwc_ = 2; + // telegram handlers + register_telegram_type(0x07D6, "SM100wwTemperature", false, MAKE_PF_CB(process_SM100wwTemperature)); + register_telegram_type(0x07AA, "SM100wwStatus", false, MAKE_PF_CB(process_SM100wwStatus)); + register_telegram_type(0x07AB, "SM100wwCommand", false, MAKE_PF_CB(process_SM100wwCommand)); + register_telegram_type(0x07A5, "SM100wwCirc", true, MAKE_PF_CB(process_SM100wwCirc)); + register_telegram_type(0x07A6, "SM100wwParam", true, MAKE_PF_CB(process_SM100wwParam)); + register_telegram_type(0x07AE, "SM100wwKeepWarm", true, MAKE_PF_CB(process_SM100wwKeepWarm)); + register_telegram_type(0x07E0, "SM100wwStatus2", true, MAKE_PF_CB(process_SM100wwStatus2)); + // device values... + register_device_value(tag, &wwTemp_1_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp1), DeviceValueUOM::DEGREES); + register_device_value(tag, &wwTemp_2_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp2), DeviceValueUOM::DEGREES); + register_device_value(tag, &wwTemp_3_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp3), DeviceValueUOM::DEGREES); + register_device_value(tag, &wwTemp_4_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp4), DeviceValueUOM::DEGREES); + register_device_value(tag, &wwTemp_5_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp5), DeviceValueUOM::DEGREES); + register_device_value(tag, &wwTemp_6_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp6), DeviceValueUOM::DEGREES); + register_device_value(tag, &wwTemp_7_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp7), DeviceValueUOM::DEGREES); + register_device_value(tag, &wwPump_, DeviceValueType::BOOL, FL_(wwPump), DeviceValueUOM::NONE); + register_device_value(tag, &wwMaxTemp_, DeviceValueType::UINT, FL_(wwMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwMaxTemp)); + register_device_value(tag, &wwSelTemp_, DeviceValueType::UINT, FL_(wwSelTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwSelTemp)); + register_device_value(tag, &wwRedTemp_, DeviceValueType::UINT, FL_(wwRedTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwRedTemp)); + register_device_value(tag, &wwDailyTemp_, DeviceValueType::UINT, FL_(wwDailyTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwDailyTemp)); + register_device_value(tag, &wwDisinfectionTemp_, DeviceValueType::UINT, FL_(wwDisinfectionTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwDisinfectionTemp)); + register_device_value(tag, &wwCirc_, DeviceValueType::BOOL, FL_(wwCirc), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCirc)); + register_device_value(tag, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCircMode)); + register_device_value(tag, &wwKeepWarm_, DeviceValueType::BOOL, FL_(wwKeepWarm), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwKeepWarm)); + register_device_value(tag, &wwStatus2_, DeviceValueType::ENUM, FL_(enum_wwStatus2), FL_(wwStatus2), DeviceValueUOM::NONE); + register_device_value(tag, &wwPumpMod_, DeviceValueType::UINT, FL_(wwPumpMod), DeviceValueUOM::PERCENT); + register_device_value(tag, &wwFlow_, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwFlow), DeviceValueUOM::LMIN); + + } else if (device_id >= EMSdevice::EMS_DEVICE_ID_DHW1 && device_id <= EMSdevice::EMS_DEVICE_ID_DHW2) { + wwc_ = device_id - EMSdevice::EMS_DEVICE_ID_DHW1; + register_telegram_type(0x331 + wwc_, "MMPLUSStatusMessage_WWC", false, MAKE_PF_CB(process_MMPLUSStatusMessage_WWC)); + register_telegram_type(0x313 + wwc_, "MMPLUSConfigMessage_WWC", true, MAKE_PF_CB(process_MMPLUSConfigMessage_WWC)); + // register_telegram_type(0x33B + type_offset, "MMPLUSSetMessage_WWC", true, MAKE_PF_CB(process_MMPLUSSetMessage_WWC)); + // device values... + register_device_value(tag, &wwFlowTemp_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp), DeviceValueUOM::DEGREES); + register_device_value(tag, &wwStatus_, DeviceValueType::INT, FL_(wwTempStatus), DeviceValueUOM::NONE); + register_device_value(tag, &wwPump_, DeviceValueType::BOOL, FL_(wwPump), DeviceValueUOM::NONE); + register_device_value(tag, &wwMaxTemp_, DeviceValueType::UINT, FL_(wwMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwMaxTemp)); + register_device_value(tag, &wwDiffTemp_, DeviceValueType::INT, FL_(wwDiffTemp), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwDiffTemp)); + register_device_value(tag, &wwDisinfectionTemp_, DeviceValueType::UINT, FL_(wwDisinfectionTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwDisinfectionTemp)); + register_device_value(tag, &wwRedTemp_, DeviceValueType::UINT, FL_(wwRedTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwRedTemp)); + register_device_value(tag, &wwRequiredTemp_, DeviceValueType::UINT, FL_(wwRequiredTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwRequiredTemp)); + register_device_value(tag, &wwCirc_, DeviceValueType::BOOL, FL_(wwCirc), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCirc)); + register_device_value(tag, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCircMode)); + } else if (device_id == 0x40) { // flags == EMSdevice::EMS_DEVICE_FLAG_IPM, special DHW pos 10 + wwc_ = 0; + tag = DeviceValueTAG::TAG_WWC1; + register_telegram_type(0x34, "UBAMonitorWW", false, MAKE_PF_CB(process_IPMMonitorWW)); + register_telegram_type(0x1E, "HydrTemp", false, MAKE_PF_CB(process_IPMHydrTemp)); + register_telegram_type(0x33, "UBAParameterWW", true, MAKE_PF_CB(process_IPMParameterWW)); + // register_telegram_type(0x10D, "wwNTCStatus", false, MAKE_PF_CB(process_wwNTCStatus)); + // device values... + register_device_value(tag, &wwSelTemp_, DeviceValueType::UINT, FL_(wwSelTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwSelTemp)); + register_device_value(tag, &wwTemp_1_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp1), DeviceValueUOM::DEGREES); + register_device_value(tag, &wwTemp_2_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp2), DeviceValueUOM::DEGREES); + register_device_value(tag, &HydrTemp_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(hydrTemp), DeviceValueUOM::DEGREES); + register_device_value(tag, &wwPump_, DeviceValueType::BOOL, FL_(wwPump), DeviceValueUOM::NONE); + register_device_value(tag, &wwFlowTempOffset_, DeviceValueType::UINT, FL_(wwFlowTempOffset), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwFlowTempOffset)); + register_device_value(tag, &wwHystOn_, DeviceValueType::INT, FL_(wwHystOn), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwHystOn)); + register_device_value(tag, &wwHystOff_, DeviceValueType::INT, FL_(wwHystOff), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwHystOff)); + register_device_value(tag, &wwDisinfectionTemp_, DeviceValueType::UINT, FL_(wwDisinfectionTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwDisinfectionTemp)); + register_device_value(tag, &wwCirc_, DeviceValueType::BOOL, FL_(wwCirc), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCirc)); + register_device_value(tag, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCircMode)); + } +} + +// SM100wwTemperature - 0x07D6 +// Solar Module(0x2A) -> (0x00), (0x7D6), data: 01 C1 00 00 02 5B 01 AF 01 AD 80 00 01 90 +void Water::process_SM100wwTemperature(std::shared_ptr telegram) { + has_update(telegram, wwTemp_1_, 0); // is *10 + has_update(telegram, wwTemp_2_, 2); // is *10 + has_update(telegram, wwTemp_3_, 4); // is *10 + has_update(telegram, wwTemp_4_, 6); // is *10 + has_update(telegram, wwTemp_5_, 8); // is *10 + has_update(telegram, wwTemp_6_, 10); // is *10 + has_update(telegram, wwTemp_7_, 12); // is *10 +} + +// SM100wwStatus - 0x07AA +// Solar Module(0x2A) -> (0x00), (0x7AA), data: 64 00 04 00 03 00 28 01 0F +void Water::process_SM100wwStatus(std::shared_ptr telegram) { + has_update(telegram, wwPump_, 0); +} + +// SM100wwParam - 0x07A6, Solar Module(0x2A) -> (0x00) +// data: FF 05 0F 5F 00 01 3C 3C 3C 3C 28 12 46 01 3C 1E 03 07 3C 00 0F 00 05 +void Water::process_SM100wwParam(std::shared_ptr telegram) { + has_update(telegram, wwMaxTemp_, 8); + has_update(telegram, wwSelTemp_, 9); + has_update(telegram, wwRedTemp_, 10); + has_update(telegram, wwDailyTemp_, 6); + has_update(telegram, wwDisinfectionTemp_, 12); + // (daily heating time thermostat 2F5, offset 9, offset 8 on/off) +} + +// SM100wwCirc - 0x07A5 +// Solar Module(0x2A) -> (0x00), (0x7A5), data: +void Water::process_SM100wwCirc(std::shared_ptr telegram) { + has_update(telegram, wwCirc_, 0); + has_update(telegram, wwCircMode_, 3); +} + +// SM100wwKeepWarm - 0x7AE, keepWarm +// Thermostat(0x10) -> Solar(0x2A), ?(0x7AE), data: FF +void Water::process_SM100wwKeepWarm(std::shared_ptr telegram) { + has_update(telegram, wwKeepWarm_, 0); +} + +/* +// SM100ww? - 0x7E0, some kind of status +// data: 00 00 46 00 00 01 06 0E 06 0E 00 00 00 00 00 03 03 03 03 +// publishes single values offset 1/2(16bit), offset 5, offset 6, offset 7, offset 8, offset 9, +// status2 = 03:"no heat", 06:"heat request", 08:"disinfecting", 09:"hold" +*/ +void Water::process_SM100wwStatus2(std::shared_ptr telegram) { + has_update(telegram, wwFlow_, 7); + has_update(telegram, wwStatus2_, 8); + has_update(telegram, wwPumpMod_, 9); +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +// SM100wwCommand - 0x07AB +// Thermostat(0x10) -> Solar Module(0x2A), (0x7AB), data: 01 00 01 +void Water::process_SM100wwCommand(std::shared_ptr telegram) { + // not implemented yet +} +#pragma GCC diagnostic pop + +/* + * MM100 messages + */ + +// Mixer warm water loading/DHW - 0x0331, 0x0332 +// e.g. A9 00 FF 00 02 32 02 6C 00 3C 00 3C 3C 46 02 03 03 00 3C // on 0x28 +// A8 00 FF 00 02 31 02 35 00 3C 00 3C 3C 46 02 03 03 00 3C // in 0x29 +void Water::process_MMPLUSStatusMessage_WWC(std::shared_ptr telegram) { + has_update(telegram, wwFlowTemp_, 0); // is * 10 + has_bitupdate(telegram, wwPump_, 2, 0); + has_update(telegram, wwStatus_, 11); // temp status +} + +// Config message 0x313, has to be fetched +void Water::process_MMPLUSConfigMessage_WWC(std::shared_ptr telegram) { + has_update(telegram, wwRequiredTemp_, 4); + has_update(telegram, wwRedTemp_, 5); + has_update(telegram, wwDiffTemp_, 7); + has_update(telegram, wwDisinfectionTemp_, 9); + has_update(telegram, wwMaxTemp_, 10); +} + +// unknown, 2 examples from older threads +// Thermostat(0x10) -> Mixer(0x28), ?(0x33B), data: 01 01 00 +// Thermostat -> Mixing Module, type 0x023B, telegram: 90 28 FF 00 02 3B 00 02 00 (CRC=68) +void Water::process_MMPLUSSetMessage_WWC(std::shared_ptr telegram) { +} + +// MMPLUS telegram 0x345 unknown +// Solar Module -> Mixing Module, type 0x0245, telegram: B0 28 FF 00 02 45 64 01 01 (CRC=36) +// ? + +/* + * IPM messages + */ + +// 0x34 only 8 bytes long +// Mixer(0x41) -> All(0x00), UBAMonitorWW(0x34), data: 37 02 1E 02 1E 00 00 00 00 +void Water::process_IPMMonitorWW(std::shared_ptr telegram) { + has_update(telegram, wwSelTemp_, 0); + has_update(telegram, wwTemp_1_, 1); + has_update(telegram, wwTemp_2_, 3); + has_bitupdate(telegram, wwPump_, 5, 3); +} + +// Mixer(0x41) -> Me(0x0B), UBAParameterWW(0x33), data: 08 FF 46 FB FF 28 FF 07 46 00 FF 00 +void Water::process_IPMParameterWW(std::shared_ptr telegram) { + // has_update(telegram, wwActivated_, 1); // 0xFF means on + // has_update(telegram, wwSelTemp_, 2); + has_update(telegram, wwHystOn_, 3); // Hyst on (default -5) + has_update(telegram, wwHystOff_, 4); // Hyst off (default -1) + has_update(telegram, wwFlowTempOffset_, 5); // default 40 + has_update(telegram, wwCirc_, 6); // 0xFF means on + has_update(telegram, wwCircMode_, 7); // 1=1x3min 6=6x3min 7=continuous + has_update(telegram, wwDisinfectionTemp_, 8); + // has_bitupdate(telegram, wwChargeType_, 10, 0); // 0 = charge pump, 0xff = 3-way valve +} + + +// 0x1E, only16 bit temperature +// Mixer(0x41) -> Boiler(0x08), HydrTemp(0x1E), data: 01 D8 +void Water::process_IPMHydrTemp(std::shared_ptr telegram) { + has_update(telegram, HydrTemp_, 0); +} + +/* + * Settings + */ + +bool Water::set_wwSelTemp(const char * value, const int8_t id) { + int temperature; + if (!Helpers::value2temperature(value, temperature)) { + return false; + } + if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) { + write_command(0x35, 3, (uint8_t)temperature, 0x34); + } else if (flags() == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { + return false; + } else { // SM100 + write_command(0x7A6, 9, (uint8_t)temperature, 0x7A6); + } + return true; +} + +bool Water::set_wwMaxTemp(const char * value, const int8_t id) { + int temperature; + if (!Helpers::value2temperature(value, temperature)) { + return false; + } + if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) { + return false; + } else if (flags() == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { + write_command(0x313 + wwc_, 10, (uint8_t)temperature, 0x313 + wwc_); + } else { // SM100 + write_command(0x7A6, 8, (uint8_t)temperature, 0x7A6); + } + return true; +} + +bool Water::set_wwRedTemp(const char * value, const int8_t id) { + int temperature; + if (!Helpers::value2temperature(value, temperature)) { + return false; + } + if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) { + return false; + } else if (flags() == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { + write_command(0x313 + wwc_, 5, (uint8_t)temperature, 0x313 + wwc_); + } else { // SM100 + write_command(0x7A6, 10, (uint8_t)temperature, 0x7A6); + } + return true; +} + +bool Water::set_wwDailyTemp(const char * value, const int8_t id) { + int temperature; + if (!Helpers::value2temperature(value, temperature)) { + return false; + } + write_command(0x7A6, 6, (uint8_t)temperature, 0x7A6); + return true; +} + +bool Water::set_wwDisinfectionTemp(const char * value, const int8_t id) { + int temperature; + if (!Helpers::value2temperature(value, temperature)) { + return false; + } + if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) { + write_command(0x33, 8, (uint8_t)temperature, 0x33); + } else if (flags() == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { + write_command(0x313 + wwc_, 9, (uint8_t)temperature, 0x313 + wwc_); + } else { // SM100 + write_command(0x7A6, 12, (uint8_t)temperature, 0x7A6); + } + return true; +} + +bool Water::set_wwCirc(const char * value, const int8_t id) { + bool b; + if (!Helpers::value2bool(value, b)) { + return false; + } + if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) { + write_command(0x33, 6, b ? 0xFF : 0x00, 0x33); + } else if (flags() == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { + write_command(0x33B + wwc_, 0, b ? 0x01 : 0x00, 0x33B + wwc_); + } else { // SM100 + write_command(0x7A5, 0, b ? 0xFF : 0x00, 0x7A5); + } + return true; +} + +bool Water::set_wwCircMode(const char * value, const int8_t id) { + uint8_t num; + if (!Helpers::value2enum(value, num, FL_(enum_wwCircMode))) { + return false; + } + if (flags() == EMSdevice::EMS_DEVICE_FLAG_IPM) { + write_command(0x33, 7, num, 0x33); + } else if (flags() == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { + write_command(0x313 + wwc_, 0, num, 0x313 + wwc_); + } else { // SM100 + write_command(0x7A5, 3, num, 0x7A5); + } + return true; +} + +bool Water::set_wwKeepWarm(const char * value, const int8_t id) { + bool b; + if (!Helpers::value2bool(value, b)) { + return false; + } + write_command(0x7AE, 0, b ? 0xFF : 0x00, 0x7AE); + return true; +} + +bool Water::set_wwDiffTemp(const char * value, const int8_t id) { + uint8_t wwc = device_id() - 0x28; + float v; + if (!Helpers::value2temperature(value, v)) { + return false; + } + if (flags() == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { + write_command(0x313 + wwc, 7, (int8_t)(v * 10), 0x313 + wwc); + return true; + } + return false; +} + +bool Water::set_wwRequiredTemp(const char * value, const int8_t id) { + uint8_t wwc = device_id() - 0x28; + float v; + if (!Helpers::value2temperature(value, v)) { + return false; + } + if (flags() == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { + write_command(0x313 + wwc, 4, (uint8_t)v, 0x313 + wwc); + return true; + } + return false; +} + + +bool Water::set_wwFlowTempOffset(const char * value, const int8_t id) { + int n; + if (!Helpers::value2number(value, n)) { + return false; + } + write_command(0x33, 5, n, 0x33); + return true; +} + +bool Water::set_wwHystOn(const char * value, const int8_t id) { + int n; + if (!Helpers::value2number(value, n)) { + return false; + } + write_command(0x33, 3, n, 0x33); + return true; +} + +bool Water::set_wwHystOff(const char * value, const int8_t id) { + int n; + if (!Helpers::value2number(value, n)) { + return false; + } + write_command(0x33, 4, n, 0x33); + return true; +} +} // namespace emsesp diff --git a/src/devices/water.h b/src/devices/water.h new file mode 100644 index 000000000..c39c252fe --- /dev/null +++ b/src/devices/water.h @@ -0,0 +1,115 @@ +/* + * EMS-ESP - https://github.com/emsesp/EMS-ESP + * Copyright 2020-2023 Paul Derbyshire + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef EMSESP_WATER_H +#define EMSESP_WATER_H + +#include "emsesp.h" + +namespace emsesp { + +class Water : public EMSdevice { + public: + Water(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand); + + private: + static uuid::log::Logger logger_; + + uint8_t wwc_; + + // SM100wwTemperature - 0x07D6 + uint16_t wwTemp_1_; + uint16_t wwTemp_2_; + uint16_t wwTemp_3_; + uint16_t wwTemp_4_; + uint16_t wwTemp_5_; + uint16_t wwTemp_6_; + uint16_t wwTemp_7_; + + // SM100wwStatus - 0x07AA + uint8_t wwPump_; + + // SM100wwParam - 0x07A6 + uint8_t wwMaxTemp_; + uint8_t wwSelTemp_; + uint8_t wwRedTemp_; + uint8_t wwDailyTemp_; + uint8_t wwDisinfectionTemp_; + + // SM100wwKeepWarm - 0x07AE + uint8_t wwKeepWarm_; + + // SM100wwCirc - 0x07A5 + uint8_t wwCirc_; + uint8_t wwCircMode_; + + // SM100wwStatus2 - 0x07E0 + uint8_t wwFlow_; + uint8_t wwPumpMod_; + uint8_t wwStatus2_; + + // mixer + uint8_t wwStatus_; + uint16_t wwFlowTemp_; + int8_t wwDiffTemp_; + uint8_t wwRequiredTemp_; + + // IPM + uint16_t HydrTemp_; + int8_t wwHystOn_; // Hyst on (default -5) + int8_t wwHystOff_; // Hyst off (default -1) + uint8_t wwFlowTempOffset_; // default 40 + + + void process_SM100wwTemperature(std::shared_ptr telegram); + void process_SM100wwStatus(std::shared_ptr telegram); + void process_SM100wwStatus2(std::shared_ptr telegram); + void process_SM100wwCommand(std::shared_ptr telegram); + void process_SM100wwCirc(std::shared_ptr telegram); + void process_SM100wwParam(std::shared_ptr telegram); + void process_SM100wwKeepWarm(std::shared_ptr telegram); + + void process_MMPLUSStatusMessage_WWC(std::shared_ptr telegram); + void process_MMPLUSSetMessage_WWC(std::shared_ptr telegram); + void process_MMPLUSConfigMessage_WWC(std::shared_ptr telegram); + + void process_IPMMonitorWW(std::shared_ptr telegram); + void process_IPMHydrTemp(std::shared_ptr telegram); + void process_IPMParameterWW(std::shared_ptr telegram); + + + bool set_wwSelTemp(const char * value, const int8_t id); + bool set_wwMaxTemp(const char * value, const int8_t id); + bool set_wwRedTemp(const char * value, const int8_t id); + bool set_wwCirc(const char * value, const int8_t id); + bool set_wwCircMode(const char * value, const int8_t id); + bool set_wwKeepWarm(const char * value, const int8_t id); + bool set_wwDisinfectionTemp(const char * value, const int8_t id); + bool set_wwDailyTemp(const char * value, const int8_t id); + + bool set_wwDiffTemp(const char * value, const int8_t id); + bool set_wwRequiredTemp(const char * value, const int8_t id); + + bool set_wwFlowTempOffset(const char * value, const int8_t id); + bool set_wwHystOn(const char * value, const int8_t id); + bool set_wwHystOff(const char * value, const int8_t id); +}; + +} // namespace emsesp + +#endif diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index af78b4648..2d056996e 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -107,6 +107,8 @@ const char * EMSdevice::device_type_2_device_name(const uint8_t device_type) { return F_(system); case DeviceType::SCHEDULER: return F_(scheduler); + case DeviceType::CUSTOM: + return F_(custom); case DeviceType::BOILER: return F_(boiler); case DeviceType::THERMOSTAT: @@ -135,10 +137,12 @@ const char * EMSdevice::device_type_2_device_name(const uint8_t device_type) { return F_(extension); case DeviceType::HEATSOURCE: return F_(heatsource); - case DeviceType::CUSTOM: - return F_(custom); 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); } @@ -174,6 +178,10 @@ const char * EMSdevice::device_type_2_device_name_translated() { return Helpers::translated_word(FL_(heatsource_device)); case DeviceType::VENTILATION: return Helpers::translated_word(FL_(ventilation_device)); + case DeviceType::WATER: + return Helpers::translated_word(FL_(water_device)); + case DeviceType::POOL: + return Helpers::translated_word(FL_(pool_device)); default: break; } @@ -241,6 +249,12 @@ uint8_t EMSdevice::device_name_2_device_type(const char * topic) { if (!strcmp(lowtopic, F_(ventilation))) { return DeviceType::VENTILATION; } + if (!strcmp(lowtopic, F_(water))) { + return DeviceType::WATER; + } + if (!strcmp(lowtopic, F_(pool))) { + return DeviceType::POOL; + } return DeviceType::UNKNOWN; } diff --git a/src/emsdevice.h b/src/emsdevice.h index 93986a76e..0f917fdc9 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -339,7 +339,9 @@ class EMSdevice { SYSTEM = 0, // this is us (EMS-ESP) TEMPERATURESENSOR, // for internal temperature sensors ANALOGSENSOR, // for internal analog sensors - SCHEDULER, + SCHEDULER, // for internal schedule + CUSTOM, // for user defined entities + BOILER, THERMOSTAT, MIXER, @@ -353,8 +355,9 @@ class EMSdevice { EXTENSION, GENERIC, HEATSOURCE, - CUSTOM, VENTILATION, + WATER, + POOL, UNKNOWN }; @@ -379,8 +382,11 @@ class EMSdevice { static constexpr uint8_t EMS_DEVICE_ID_MODEM = 0x48; static constexpr uint8_t EMS_DEVICE_ID_RFSENSOR = 0x40; // RF sensor only sending, no reply static constexpr uint8_t EMS_DEVICE_ID_RFBASE = 0x50; - static constexpr uint8_t EMS_DEVICE_ID_ROOMTHERMOSTAT = 0x17; // TADO using this with no version reply - static constexpr uint8_t EMS_DEVICE_ID_TADO_OLD = 0x19; // TADO using this with no broadcast and version + static constexpr uint8_t EMS_DEVICE_ID_ROOMTHERMOSTAT = 0x17; // TADO using this with no version reply #174 + static constexpr uint8_t EMS_DEVICE_ID_TADO_OLD = 0x19; // older TADO using this with no version reply, #1031 + static constexpr uint8_t EMS_DEVICE_ID_DHW1 = 0x28; // MM100 module as water station + static constexpr uint8_t EMS_DEVICE_ID_DHW2 = 0x29; // MM100 module as water station + static constexpr uint8_t EMS_DEVICE_ID_DHW8 = 0x2F; // last DHW module id? // generic type IDs static constexpr uint16_t EMS_TYPE_VERSION = 0x02; // type ID for Version information. Generic across all EMS devices. diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 0f50df108..273027ccc 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -480,6 +480,7 @@ void EMSESP::publish_all(bool force) { publish_device_values(EMSdevice::DeviceType::THERMOSTAT); publish_device_values(EMSdevice::DeviceType::SOLAR); publish_device_values(EMSdevice::DeviceType::MIXER); + publish_device_values(EMSdevice::DeviceType::WATER); publish_other_values(); // switch and heat pump, ... webSchedulerService.publish(); webCustomEntityService.publish(); @@ -513,14 +514,17 @@ void EMSESP::publish_all_loop() { publish_device_values(EMSdevice::DeviceType::MIXER); break; case 5: + publish_device_values(EMSdevice::DeviceType::WATER); + break; + case 6: publish_other_values(); // switch and heat pump webSchedulerService.publish(true); webCustomEntityService.publish(true); break; - case 6: + case 7: publish_sensor_values(true, true); break; - case 7: + case 8: if (Mqtt::ha_enabled()) { Mqtt::ha_status(); } @@ -602,6 +606,7 @@ void EMSESP::publish_other_values() { publish_device_values(EMSdevice::DeviceType::VENTILATION); publish_device_values(EMSdevice::DeviceType::EXTENSION); publish_device_values(EMSdevice::DeviceType::ALERT); + publish_device_values(EMSdevice::DeviceType::POOL); // other devices without values yet // publish_device_values(EMSdevice::DeviceType::GATEWAY); // publish_device_values(EMSdevice::DeviceType::CONNECT); @@ -1080,7 +1085,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const auto device_type = device_p->device_type; auto flags = device_p->flags; - // check for integrated modules with same product id + // check for integrated modules with same product id, but different function (device_id) if (device_type == DeviceType::HEATPUMP) { if (device_id == EMSdevice::EMS_DEVICE_ID_MODEM) { device_type = DeviceType::GATEWAY; @@ -1090,6 +1095,9 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const name = "Wireless sensor base"; } } + if (device_id >= EMSdevice::EMS_DEVICE_ID_DHW1 && device_id <= EMSdevice::EMS_DEVICE_ID_DHW8) { + device_type = DeviceType::WATER; + } // empty reply to version, read a generic device from database if (product_id == 0) { diff --git a/src/locale_common.h b/src/locale_common.h index 7d8a5db83..1184a2269 100644 --- a/src/locale_common.h +++ b/src/locale_common.h @@ -102,6 +102,8 @@ MAKE_WORD(heatsource) MAKE_WORD(scheduler) MAKE_WORD(custom) MAKE_WORD(ventilation) +MAKE_WORD(water) +MAKE_WORD(pool) // brands MAKE_WORD_CUSTOM(bosch, "Bosch") diff --git a/src/locale_translations.h b/src/locale_translations.h index 98d9c1a65..2c2cf4a49 100644 --- a/src/locale_translations.h +++ b/src/locale_translations.h @@ -54,6 +54,8 @@ MAKE_WORD_TRANSLATION(unknown_device, "Unknown", "Unbekannt", "Onbekend", "Okän MAKE_WORD_TRANSLATION(custom_device, "Custom", "Nutzerdefiniert", "Aangepast", "", "Niestandardowe", "", "", "Özel", "Personalizzato") // TODO translate MAKE_WORD_TRANSLATION(custom_device_name, "User defined entities", "Nutzer deklarierte Entitäten", "Gebruiker gedefineerd", "", "Encje zdefiniowane przez użytkownika", "", "", "Kullanıcı tarafından tanımlanmış varlıklar", "Entità definita da utente") // TODO translate MAKE_WORD_TRANSLATION(ventilation_device, "Ventilation", "Lüftung", "Ventilatie", "", "", "", "", "Havalandırma", "Ventilazione") // TODO translate +MAKE_WORD_TRANSLATION(water_device, "Water Module", "Wassermodul", "", "", "", "", "", "", "") // TODO translate +MAKE_WORD_TRANSLATION(pool_device, "Pool Module", "Poolmodul", "", "", "", "", "", "", "") // TODO translate // commands // TODO translate @@ -687,10 +689,6 @@ MAKE_TRANSLATION(pumpStatus, "pumpstatus", "pump status (PC1)", "Pumpenstatus HK MAKE_TRANSLATION(mixerStatus, "valvestatus", "mixing valve actuator (VC1)", "Mischerventil Position (VC1)", "positie mixerklep (VC1)", "Shuntventil Status (VC1)", "siłownik zaworu mieszającego (VC1)", "shuntventil status (VC1)", "actionnement vanne mélangeur (VC1)", "karışım vanası aktüatörü (VC1)", "posizione valvola miscela (VC1)") MAKE_TRANSLATION(flowTempVf, "flowtempvf", "flow temperature in header (T0/Vf)", "Vorlauftemperatur am Verteiler (T0/Vf)", "aanvoertemperatuur verdeler (T0/Vf)", "Flödestemperatur Fördelare (T0/Vf)", "temperatura zasilania na rozdzielaczu (T0/Vf)", "turtemperatur ved fordeleren (T0/Vf)", "température départ collecteur (T0/Vf)", "başlıkta akış sıcaklığı", "Temperatura di mandata al distributore (T0/Vf)") MAKE_TRANSLATION(mixerSetTime, "valvesettime", "time to set valve", "Zeit zum Einstellen des Ventils", "Inschakeltijd mengklep", "Inställningstid Ventil", "czas na ustawienie zaworu", "instillningstid ventil", "délai activation vanne", "vana ayar zamanı", "ritardo attivazione valvola") -// mixer prefixed with wwc -MAKE_TRANSLATION(wwPumpStatus, "pumpstatus", "pump status in assigned wwc (PC1)", "Pumpenstatus des wwk (PC1)", "Pompstatus in WW circuit (PC1)", "Pumpstatus i VV-krets (PC1)", "stan pompy w obwodzie c.w.u. (PC1)", "Pumpestatus i VV-krets (PC1)", "état pompe wwc (PC1)", "Kullanım suyu devresindeki(PC1) pompa durumu", "stato pompa assegnato nel ciruito WW (PC1)") -MAKE_TRANSLATION(wwTempStatus, "wwtempstatus", "temperature switch in assigned wwc (MC1)", "Temperaturschalter des wwk (MC1)", "Temperatuurschakeling in WW circuit (MC1)", "Temperaturventil i VV-krets (MC1)", "temperatura w obwodzie c.w.u. (MC1)", "temperaturventil i VV-krets (MC1)", "température bascule wwc (MC1).", "atanmış sıcak su devresinde sıcaklık", "interruttore di temperatura del wwk (MC1)") -MAKE_TRANSLATION(wwTemp, "wwtemp", "current temperature", "aktuelle Temperatur", "huidige temperatuur", "Aktuell Temperatur", "temperatura c.w.u.", "aktuell temperatur", "température actuelle", "güncel sıcaklık", "temperatura attuale") // mixer pool MAKE_TRANSLATION(poolSetTemp, "poolsettemp", "pool set temperature", "Pool Solltemperatur", "Streeftemperatuur zwembad", "Pool Temperatur Börvärde", "zadana temperatura basenu", "valgt temp basseng", "température consigne piscine", "hedef havuz sıcaklığı", "temperatura nominale piscina") MAKE_TRANSLATION(poolTemp, "pooltemp", "pool temperature", "Pool Temperatur", "Zwembadtemperatuur", "Pooltemperatur", "temperatura basenu", "bassengtemperatur", "température piscine", "havuz sıcaklığı", "temperatura piscina") @@ -737,10 +735,12 @@ MAKE_TRANSLATION(energyToday, "energytoday", "total energy today", "Energie heut // solar ww MAKE_TRANSLATION(wwTemp1, "wwtemp1", "temperature 1", "Temperatur 1", "Temperatuur 1", "Temperatur 1", "temperatura 1", "temperatur 1", "température 1", "sıcaklık 1", "Temperatura 1") -MAKE_TRANSLATION(wwTemp3, "wwtemp3", "temperature 3", "Temperatur 3", "Temperatuur 2", "Temperatur 2", "temperatura 2", "Temperatur 3", "température 3", "sıcaklık 3", "Temperatura 3") -MAKE_TRANSLATION(wwTemp4, "wwtemp4", "temperature 4", "Temperatur 4", "Temperatuur 3", "Temperatur 3", "temperatura 3", "Temperatur 4", "température 4", "sıcaklık 4", "Temperatura 4") -MAKE_TRANSLATION(wwTemp5, "wwtemp5", "temperature 5", "Temperatur 5", "Temperatuur 5", "Temperatur 4", "temperatura 4", "Temperatur 5", "température 5", "sıcaklık 5", "Temperatura 5") -MAKE_TRANSLATION(wwTemp7, "wwtemp7", "temperature 7", "Temperatur 7", "Temperatuur 7", "Temperatur 5", "temperatura 5", "Temperatur 7", "température 7", "sıcaklık 7", "Temperatura 7") +MAKE_TRANSLATION(wwTemp2, "wwtemp2", "temperature 2", "Temperatur 2", "Temperatuur 2", "Temperatur 2", "temperatura 2", "temperatur 2", "température 2", "sıcaklık 2", "Temperatura 2") +MAKE_TRANSLATION(wwTemp3, "wwtemp3", "temperature 3", "Temperatur 3", "Temperatuur 3", "Temperatur 3", "temperatura 3", "Temperatur 3", "température 3", "sıcaklık 3", "Temperatura 3") +MAKE_TRANSLATION(wwTemp4, "wwtemp4", "temperature 4", "Temperatur 4", "Temperatuur 4", "Temperatur 4", "temperatura 4", "Temperatur 4", "température 4", "sıcaklık 4", "Temperatura 4") +MAKE_TRANSLATION(wwTemp5, "wwtemp5", "temperature 5", "Temperatur 5", "Temperatuur 5", "Temperatur 5", "temperatura 5", "Temperatur 5", "température 5", "sıcaklık 5", "Temperatura 5") +MAKE_TRANSLATION(wwTemp6, "wwtemp6", "temperature 1", "Temperatur 6", "Temperatuur 6", "Temperatur 6", "temperatura 6", "temperatur 6", "température 6", "sıcaklık 6", "Temperatura 6") +MAKE_TRANSLATION(wwTemp7, "wwtemp7", "temperature 7", "Temperatur 7", "Temperatuur 7", "Temperatur 7", "temperatura 7", "Temperatur 7", "température 7", "sıcaklık 7", "Temperatura 7") MAKE_TRANSLATION(wwPump, "wwpump", "pump", "Pumpe", "Pomp", "Pump", "pompa", "pumpe", "pompe", "pompa", "Pompa") // solar ww and mixer wwc MAKE_TRANSLATION(wwMinTemp, "wwmintemp", "minimum temperature", "minimale Temperatur", "Minimale temperatuur", "Min Temperatur", "temperatura minimalna", "min temperatur", "température min", "minimum sıcaklık", "temperatura minima") @@ -753,6 +753,9 @@ MAKE_TRANSLATION(wwFlow, "wwflow", "flow rate", "Volumenstrom", "Doorstroomsnelh // extra mixer ww MAKE_TRANSLATION(wwRequiredTemp, "wwrequiredtemp", "required temperature", "benötigte Temperatur", "Benodigde temperatuur", "Nödvändig Temperatur", "temperatura wymagana", "nødvendig temperatur", "température requise", "gerekli sıcaklık", "temperatura richiesta") MAKE_TRANSLATION(wwDiffTemp, "wwdifftemp", "start differential temperature", "Start Differential Temperatur", "Start differentiele temperatuur", "Start Differentialtemperatur", "start temperatury różnicowej", "start differensialtemperatur", "température différentielle de départ", "diferansiyel sıcaklık", "avvia temperatura differenziale") +MAKE_TRANSLATION(wwPumpStatus, "pumpstatus", "pump status in assigned wwc (PC1)", "Pumpenstatus des wwk (PC1)", "Pompstatus in WW circuit (PC1)", "Pumpstatus i VV-krets (PC1)", "stan pompy w obwodzie c.w.u. (PC1)", "Pumpestatus i VV-krets (PC1)", "état pompe wwc (PC1)", "Kullanım suyu devresindeki(PC1) pompa durumu", "stato pompa assegnato nel ciruito WW (PC1)") +MAKE_TRANSLATION(wwTempStatus, "wwtempstatus", "temperature switch in assigned wwc (MC1)", "Temperaturschalter des wwk (MC1)", "Temperatuurschakeling in WW circuit (MC1)", "Temperaturventil i VV-krets (MC1)", "temperatura w obwodzie c.w.u. (MC1)", "temperaturventil i VV-krets (MC1)", "température bascule wwc (MC1).", "atanmış sıcak su devresinde sıcaklık", "interruttore di temperatura del wwk (MC1)") +MAKE_TRANSLATION(wwTemp, "wwtemp", "current temperature", "aktuelle Temperatur", "huidige temperatuur", "Aktuell Temperatur", "temperatura c.w.u.", "aktuell temperatur", "température actuelle", "güncel sıcaklık", "temperatura attuale") // SM100 MAKE_TRANSLATION(heatTransferSystem, "heattransfersystem", "heattransfer system", "Wärmeübertragungs-System", "Warmteoverdrachtssysteem", "Värmeöverföringssystem", "system wymiany ciepła", "varmeoverføringssystem", "système de transfert de chaleur", "ıs transfer sistemi", "sistema di trasferimento del calore") diff --git a/src/mqtt.cpp b/src/mqtt.cpp index d700f4f32..2735bbbc0 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -34,6 +34,7 @@ uint32_t Mqtt::publish_time_boiler_; uint32_t Mqtt::publish_time_thermostat_; uint32_t Mqtt::publish_time_solar_; uint32_t Mqtt::publish_time_mixer_; +uint32_t Mqtt::publish_time_water_; uint32_t Mqtt::publish_time_sensor_; uint32_t Mqtt::publish_time_other_; uint32_t Mqtt::publish_time_heartbeat_; @@ -170,6 +171,11 @@ void Mqtt::loop() { EMSESP::publish_device_values(EMSdevice::DeviceType::MIXER); } else + if (publish_time_water_ && (currentMillis - last_publish_mixer_ > publish_time_water_)) { + last_publish_water_ = (currentMillis / publish_time_water_) * publish_time_water_; + EMSESP::publish_device_values(EMSdevice::DeviceType::WATER); + } else + if (publish_time_other_ && (currentMillis - last_publish_other_ > publish_time_other_)) { last_publish_other_ = (currentMillis / publish_time_other_) * publish_time_other_; EMSESP::publish_other_values(); // switch and heatpump @@ -330,6 +336,7 @@ void Mqtt::reset_mqtt() { } } +// load the settings from service void Mqtt::load_settings() { EMSESP::esp8266React.getMqttSettingsService()->read([&](MqttSettings & mqttSettings) { mqtt_base_ = mqttSettings.base.c_str(); // Convert String to std::string @@ -350,6 +357,7 @@ void Mqtt::load_settings() { publish_time_thermostat_ = mqttSettings.publish_time_thermostat * 1000; publish_time_solar_ = mqttSettings.publish_time_solar * 1000; publish_time_mixer_ = mqttSettings.publish_time_mixer * 1000; + publish_time_water_ = mqttSettings.publish_time_water * 1000; publish_time_other_ = mqttSettings.publish_time_other * 1000; publish_time_sensor_ = mqttSettings.publish_time_sensor * 1000; publish_time_heartbeat_ = mqttSettings.publish_time_heartbeat * 1000; @@ -361,6 +369,7 @@ void Mqtt::load_settings() { std::replace(mqtt_basename_.begin(), mqtt_basename_.end(), '/', '_'); } +// start mqtt void Mqtt::start() { mqttClient_ = EMSESP::esp8266React.getMqttClient(); @@ -412,6 +421,10 @@ void Mqtt::set_publish_time_mixer(uint16_t publish_time) { publish_time_mixer_ = publish_time * 1000; // convert to milliseconds } +void Mqtt::set_publish_time_water(uint16_t publish_time) { + publish_time_water_ = publish_time * 1000; // convert to milliseconds +} + void Mqtt::set_publish_time_other(uint16_t publish_time) { publish_time_other_ = publish_time * 1000; // convert to milliseconds } @@ -444,6 +457,10 @@ bool Mqtt::get_publish_onchange(uint8_t device_type) { if (!publish_time_mixer_) { return true; } + } else if (device_type == EMSdevice::DeviceType::WATER) { + if (!publish_time_water_) { + return true; + } } else if (!publish_time_other_) { return true; } diff --git a/src/mqtt.h b/src/mqtt.h index d02fff23c..b128f2621 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -47,6 +47,7 @@ class Mqtt { void set_publish_time_thermostat(uint16_t publish_time); void set_publish_time_solar(uint16_t publish_time); void set_publish_time_mixer(uint16_t publish_time); + void set_publish_time_water(uint16_t publish_time); void set_publish_time_other(uint16_t publish_time); void set_publish_time_sensor(uint16_t publish_time); void set_publish_time_heartbeat(uint16_t publish_time); @@ -253,6 +254,7 @@ class Mqtt { uint32_t last_publish_thermostat_ = 0; uint32_t last_publish_solar_ = 0; uint32_t last_publish_mixer_ = 0; + uint32_t last_publish_water_ = 0; uint32_t last_publish_other_ = 0; uint32_t last_publish_sensor_ = 0; uint32_t last_publish_heartbeat_ = 0; @@ -279,6 +281,7 @@ class Mqtt { static uint32_t publish_time_thermostat_; static uint32_t publish_time_solar_; static uint32_t publish_time_mixer_; + static uint32_t publish_time_water_; static uint32_t publish_time_other_; static uint32_t publish_time_sensor_; static uint32_t publish_time_heartbeat_; diff --git a/src/version.h b/src/version.h index 6aabb9bbe..3aeb319d6 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.6.3-dev.5b" +#define EMSESP_APP_VERSION "3.6.3-dev.6a"