90 Commits

Author SHA1 Message Date
proddy
ee3a5d231a Merge remote-tracking branch 'origin/dev' 2026-05-12 20:15:32 +02:00
Proddy
ddb2390bf7 Merge pull request #3071 from proddy/dev
support filesystem ota
2026-05-12 19:59:58 +02:00
Proddy
91912cf5be Merge branch 'emsesp:dev' into dev 2026-05-12 19:49:18 +02:00
Proddy
4f9851a9fe Merge pull request #3072 from MichaelDvP/dev
add polarity setting for digital_in sensor, #3070
2026-05-12 19:48:27 +02:00
MichaelDvP
a897afd4e6 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2026-05-11 14:36:44 +02:00
MichaelDvP
344dcd0019 add polarity setting for digital_in sensor, #3070 2026-05-11 14:35:48 +02:00
proddy
7854349dbe support filesystem ota 2026-05-10 13:22:00 +02:00
proddy
d1d046f3fd package update 2026-05-10 13:21:47 +02:00
proddy
b988c67c8e update example 2026-05-10 13:21:37 +02:00
proddy
37a94f8e0f auto-formatting 2026-05-10 13:21:28 +02:00
Proddy
017a7de639 Merge pull request #3068 from MichaelDvP/dev
tx-mode: auto, default bus-id 0x49
2026-05-09 08:11:59 +02:00
MichaelDvP
7b61429a02 fix testdata to device-id 0x49, txMode 5 2026-05-09 08:01:29 +02:00
MichaelDvP
fed15f0f96 tx-mode: auto, default bus-id 0x49 2026-05-07 21:08:56 +02:00
Proddy
ad5d13168b Merge pull request #3066 from MichaelDvP/dev
fix modbus start #3064
2026-05-07 18:05:48 +02:00
MichaelDvP
ae5beccb9d dev.20, fixes #3064, handling of optional gpios 2026-05-07 12:02:33 +02:00
MichaelDvP
764c660b14 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2026-05-06 09:23:27 +02:00
MichaelDvP
ca0f32b087 update pkg 2026-05-06 09:06:15 +02:00
Proddy
8ad91de54a Merge pull request #3061 from MichaelDvP/dev 2026-05-06 09:05:10 +02:00
MichaelDvP
58da157272 chore: update generated files for v3.8.2-dev.20 2026-05-05 16:04:29 +00:00
MichaelDvP
b5014bf9ac dev.20, check and set 0x470 to summer2_typeids[0] ony if received. #2686 2026-05-05 17:51:52 +02:00
MichaelDvP
14351436a7 fixes #3055, revert commit daffdcf 2026-05-05 10:33:56 +02:00
proddy
e8f57b6343 v3.8.1 2026-01-11 19:28:38 +01:00
proddy
a1ab81de66 Merge branch 'dev' 2026-01-11 19:14:11 +01:00
proddy
28135c225b Merge branch 'dev' 2025-12-31 21:26:15 +01:00
proddy
eaa277fef0 v3.7.2 2025-03-22 10:32:03 +01:00
proddy
e418b7d8e7 fix routing in tabs - #2264 2024-11-30 21:31:42 +01:00
proddy
a4e3be6a69 3.7.1 changelog 2024-11-29 10:30:14 +01:00
proddy
a1bc5bb055 3.7.1 2024-11-29 10:30:05 +01:00
proddy
f444ca31e0 Merge remote-tracking branch 'origin/dev' 2024-10-27 11:41:47 +01:00
proddy
1b70b55989 update demo url 2024-08-10 14:58:48 +02:00
proddy
1487f30c43 Merge remote-tracking branch 'origin/dev' for 3.6.5 2024-03-23 17:56:05 +01:00
Proddy
e00eb8e64f 3.6.4 2023-11-26 20:11:36 +01:00
Proddy
f41bb3671c 3.6.4 2023-11-24 07:36:36 +01:00
Proddy
22c75e6df3 3.6.4 2023-11-24 07:36:29 +01:00
proddy
5ab10b7aa6 fixes #1450 2023-11-22 09:48:09 +01:00
Proddy
ee5fd4d0eb 3.6.3 2023-11-21 14:40:47 +01:00
Proddy
46f35bc67c another patch on 3.6.3 2023-11-21 14:40:32 +01:00
Proddy
ec85a7ec24 3.6.3 (refershed) 2023-11-19 21:24:01 +01:00
Proddy
02f2389587 add workflow_dispatch: 2023-11-18 18:51:12 +01:00
Proddy
7f140021aa quick fix - https://github.com/emsesp/EMS-ESP32/pull/1438 2023-11-18 18:47:28 +01:00
Proddy
6796962c1e 3.6.3 2023-11-18 13:35:20 +01:00
Proddy
df6de21cf4 Merge remote-tracking branch 'origin/dev' 2023-11-18 13:35:04 +01:00
Proddy
df9f75a5c9 updated yarn for 3.6.2 2023-10-01 17:42:54 +02:00
Proddy
7bd8710eb6 3.6.2 2023-10-01 17:40:09 +02:00
Proddy
32f2c6d341 Merge remote-tracking branch 'origin/dev' 2023-10-01 17:40:02 +02:00
Proddy
86919c1684 Merge branch 'origin/dev' 2023-09-09 14:12:07 +02:00
Proddy
86e29515e7 build s3 2023-08-15 18:44:24 +02:00
Proddy
46eb4185d7 update with 3.6.0 2023-08-13 14:37:13 +02:00
Proddy
8da6761a48 Merge branch 'dev' 2023-08-13 14:32:41 +02:00
Proddy
9233f0dfcc v3.5.1 - merge with patch 2023-03-11 16:06:05 +01:00
Proddy
292f743b14 Update bug_report.md 2023-02-19 11:18:08 +01:00
Proddy
dd6dfffd57 Delete questions---troubleshooting.md 2023-02-19 10:49:52 +01:00
Proddy
ec705a5307 Delete feature_request.md 2023-02-19 10:49:45 +01:00
Proddy
f45f071710 Create config.yml 2023-02-19 10:49:32 +01:00
Proddy
f3858546de Merge branch 'origin/dev' 2023-02-06 21:58:27 +01:00
Proddy
d0ac0b7804 update with version on dev 2022-10-30 16:58:37 +01:00
Proddy
d8284ec09f Merge pull request #705 from MichaelDvP/main
v3.4.4 Fix for new installations with filesystem not initializing
2022-10-29 10:46:41 +02:00
MichaelDvP
6e982acde8 v3.4.4 Fix for new installations with filesystem not initializing 2022-10-28 10:50:51 +02:00
Proddy
8c94ce99b2 quick fix for filesystem initialization 2022-10-08 09:23:00 +02:00
proddy
fc057d18c9 Merge remote-tracking branch 'origin/dev' 2022-09-18 14:33:23 +02:00
Proddy
18e9b99413 Merge remote-tracking branch 'origin/dev' into main 2022-05-29 16:16:38 +02:00
Proddy
a47e0e8266 update for 3.4.0 2022-05-23 21:20:45 +02:00
Proddy
f412ddc716 Merge remote-tracking branch 'origin/dev' into main 2022-05-23 21:20:36 +02:00
proddy
29110e96e5 Merge remote-tracking branch 'origin/dev' 2022-01-20 10:51:40 +01:00
proddy
b65866217a 3.4.0 2021-11-28 23:03:28 +01:00
proddy
611e3b1243 Merge remote-tracking branch 'origin/dev' 2021-11-28 23:03:15 +01:00
proddy
2ca0a0c634 v3.2.1 merged from dev 2021-08-08 14:46:14 +02:00
proddy
7eb1f061b7 Merge remote-tracking branch 'origin/dev' for 3.2.0 release 2021-08-06 12:06:08 +02:00
proddy
50459a23fe force v16 of nodejs 2021-06-26 11:13:07 +02:00
proddy
5bf53c3389 3.1.1 2021-06-26 11:03:03 +02:00
proddy
4b7aa95be3 Merge remote-tracking branch 'origin/dev' 2021-06-26 11:02:55 +02:00
Proddy
70943f5758 Update pre_release.yml 2021-05-16 15:52:09 +02:00
Proddy
3bc280b817 Delete check_code.yml 2021-05-16 15:51:56 +02:00
Proddy
62b15a5319 Update pre_release.yml 2021-05-16 15:35:06 +02:00
Proddy
8dd18802d6 Update tagged_release.yml 2021-05-16 15:34:45 +02:00
proddy
57a516a83a updated README and images 2021-05-09 15:13:16 +02:00
proddy
a57fdaa4b3 Merge remote-tracking branch 'origin/dev' into main 2021-05-04 12:21:51 +02:00
proddy
4841e42286 Merge remote-tracking branch 'origin/dev' into main 2021-03-30 16:35:18 +02:00
proddy
8c2d2b06ed cleaned up old changelog 2021-03-18 20:59:09 +01:00
proddy
38c8b1b7f0 3.0.0 2021-03-18 20:58:21 +01:00
proddy
6fb5933a02 Merge remote-tracking branch 'origin/dev' into main 2021-03-18 20:58:12 +01:00
proddy
c0944433be remove workspace.code-workspace 2021-03-16 17:41:42 +01:00
Proddy
478e6362c9 Merge pull request #27 from FauthD:main
Add global names to Dallas sensors to avoid ugly <unknown> and other …
2021-03-16 17:39:00 +01:00
fauthd
4d6354db78 Add stuff to gitignore, add vscode workspace 2021-03-16 16:47:09 +01:00
fauthd
beab0f0c77 Add global names to Dallas sensors to avoid ugly <unknown> and other issues in HA 2021-03-16 16:00:23 +01:00
Proddy
c17749bd22 Update README.md 2021-03-14 23:43:33 +01:00
proddy
2bad769c5c build: include assets 2021-03-14 21:20:51 +01:00
proddy
8ad89ca64b move repo 2021-03-14 21:05:15 +01:00
proddy
9244d8daec Semantic Commit Messages 2021-03-14 18:10:57 +01:00
proddy
02d01334b2 update new build 2021-03-14 17:37:18 +01:00
36 changed files with 797 additions and 657 deletions

View File

@@ -5,6 +5,44 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.8.2] 12 May 2026
## Added
- comfortpoint for BC400 [#2935](https://github.com/emsesp/EMS-ESP32/issues/2935)
- customize device brand [#2784](https://github.com/emsesp/EMS-ESP32/issues/2784)
- set model for ems-esp devices temperature, analog, etc. [#2958](https://github.com/emsesp/EMS-ESP32/discussions/2958)
- prometheus metrics for temperature/analog/scheduler/custom [#2962](https://github.com/emsesp/EMS-ESP32/issues/2962)
- boiler pumpkick [#2965](https://github.com/emsesp/EMS-ESP32/discussions/2965)
- heatpump reset [#2933](https://github.com/emsesp/EMS-ESP32/issues/2933)
- 2.nd freshwater module (dhw4, dhw5) [#2991](https://github.com/emsesp/EMS-ESP32/issues/2991)
- full system backup and restore
- auto-logic to set ht3/ems+ tx-mode
- polariity for digital_in sensors [#3070](https://github.com/emsesp/EMS-ESP32/discussions/3070)
## Fixed
- SRC climate creation [#2936](https://github.com/emsesp/EMS-ESP32/issues/2936) and [#2960](https://github.com/emsesp/EMS-ESP32/issues/2960)
- missing translations [#3015](https://github.com/emsesp/EMS-ESP32/issues/3015)
- custom entities check fetch length
- modbus initialization [#3064](https://github.com/emsesp/EMS-ESP32/issues/3064)
## Changed
- weblogbuffer up to 1000 messages with PSRAM, mentioned in [#2933](https://github.com/emsesp/EMS-ESP32/issues/2933)
- validate custom entity writes, [#2931](https://github.com/emsesp/EMS-ESP32/issues/2931)
- remove wrong burnMinPower [#2918](https://github.com/emsesp/EMS-ESP32/issues/2918)
- store scheduler active state to nvs [#2946](https://github.com/emsesp/EMS-ESP32/discussions/2946)
- translated modes `heat` and `eco` for HA-climate mode-str-tpl
- support `minflowtemp` and `baseflowtemp` [#2969](https://github.com/emsesp/EMS-ESP32/discussions/2969)
- update version if it is 00.00 in first read [#2981](https://github.com/emsesp/EMS-ESP32/issues/2981)
- device class for % values [#2980](https://github.com/emsesp/EMS-ESP32/issues/2980)
- fetch telegrams: set length to fetch [#3017](https://github.com/emsesp/EMS-ESP32/issues/3017)
- move http client from stack to heap
- heap optimizations [#3021](https://github.com/emsesp/EMS-ESP32/discussions/3021)
- check and read 0x470 as summer2_typeids[0] only if received [#2686](https://github.com/emsesp/EMS-ESP32/issues/2686), [#3055](https://github.com/emsesp/EMS-ESP32/issues/3055)
- default bus-id: gateway1(0x49), tx-mode: auto
## [3.8.1] 11 January 2026 ## [3.8.1] 11 January 2026
## Added ## Added
@@ -33,7 +71,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- board profile `CUSTOM` can only be selected in developer mode - board profile `CUSTOM` can only be selected in developer mode
- mqtt sends round values without decimals (`28` instead of `28.0`) - mqtt sends round values without decimals (`28` instead of `28.0`)
## [3.8.0] 31 December 2025 ## [3.8.0] 31 December 2025
## Added ## Added

View File

@@ -2,35 +2,12 @@
For more details go to [emsesp.org](https://emsesp.org/). For more details go to [emsesp.org](https://emsesp.org/).
## [3.8.2] ## [3.8.3]
## Added ## Added
- comfortpoint for BC400 [#2935](https://github.com/emsesp/EMS-ESP32/issues/2935)
- customize device brand [#2784](https://github.com/emsesp/EMS-ESP32/issues/2784)
- set model for ems-esp devices temperature, analog, etc. [#2958](https://github.com/emsesp/EMS-ESP32/discussions/2958)
- prometheus metrics for temperature/analog/scheduler/custom [#2962](https://github.com/emsesp/EMS-ESP32/issues/2962)
- boiler pumpkick [#2965](https://github.com/emsesp/EMS-ESP32/discussions/2965)
- heatpump reset [#2933](https://github.com/emsesp/EMS-ESP32/issues/2933)
- 2.nd freshwater module (dhw4, dhw5) [#2991](https://github.com/emsesp/EMS-ESP32/issues/2991)
- full system backup and restore
## Fixed ## Fixed
- SRC climate creation [#2936](https://github.com/emsesp/EMS-ESP32/issues/2936) and [#2960](https://github.com/emsesp/EMS-ESP32/issues/2960)
- missing translations [#3015](https://github.com/emsesp/EMS-ESP32/issues/3015)
- custom entities check fetch length
## Changed ## Changed
- weblogbuffer up to 1000 messages with PSRAM, mentioned in [#2933](https://github.com/emsesp/EMS-ESP32/issues/2933)
- validate custom entity writes, [#2931](https://github.com/emsesp/EMS-ESP32/issues/2931)
- remove wrong burnMinPower [#2918](https://github.com/emsesp/EMS-ESP32/issues/2918)
- store scheduler active state to nvs [#2946](https://github.com/emsesp/EMS-ESP32/discussions/2946)
- translated modes `heat` and `eco` for HA-climate mode-str-tpl
- support `minflowtemp` and `baseflowtemp` [#2969](https://github.com/emsesp/EMS-ESP32/discussions/2969)
- update version if it is 00.00 in first read [#2981](https://github.com/emsesp/EMS-ESP32/issues/2981)
- device class for % values [#2980](https://github.com/emsesp/EMS-ESP32/issues/2980)
- fetch telegrams: set length to fetch [#3017](https://github.com/emsesp/EMS-ESP32/issues/3017)
- move http client from stack to heap
- heap optimizations [#3021](https://github.com/emsesp/EMS-ESP32/discussions/3021)

View File

@@ -1,7 +1,6 @@
{ {
"type": "systembackup", "type": "systembackup",
"version": "3.8.2", "version": "3.8.2",
"date": "2026-03-29T13:28:15",
"systembackup": [ "systembackup": [
{ {
"type": "settings", "type": "settings",
@@ -19,7 +18,7 @@
"tx_power": 0 "tx_power": 0
}, },
"AP": { "AP": {
"provision_mode": 2, "provision_mode": 1,
"ssid": "ems-esp", "ssid": "ems-esp",
"password": "ems-esp-neo", "password": "ems-esp-neo",
"channel": 1, "channel": 1,
@@ -62,7 +61,7 @@
"send_response": false "send_response": false
}, },
"NTP": { "NTP": {
"enabled": true, "enabled": false,
"server": "time.google.com", "server": "time.google.com",
"tz_label": "Europe/Amsterdam", "tz_label": "Europe/Amsterdam",
"tz_format": "CET-1CEST,M3.5.0,M10.5.0/3" "tz_format": "CET-1CEST,M3.5.0,M10.5.0/3"
@@ -83,12 +82,12 @@
] ]
}, },
"Settings": { "Settings": {
"version": "3.8.2", "version": "3.8.2-dev.22",
"board_profile": "E32V2_2", "board_profile": "E32V2_2",
"platform": "ESP32", "platform": "ESP32",
"locale": "en", "locale": "en",
"tx_mode": 1, "tx_mode": 5,
"ems_bus_id": 11, "ems_bus_id": 73,
"syslog_enabled": false, "syslog_enabled": false,
"syslog_level": 3, "syslog_level": 3,
"trace_raw": false, "trace_raw": false,
@@ -132,17 +131,7 @@
"modbus_port": 502, "modbus_port": 502,
"modbus_max_clients": 10, "modbus_max_clients": 10,
"modbus_timeout": 300, "modbus_timeout": 300,
"developer_mode": true, "developer_mode": false
"email_enabled": false,
"email_ssl": false,
"email_starttls": true,
"email_server": "smtp.example.net",
"email_port": 587,
"email_login": "",
"email_pass": "",
"email_sender": "ems-esp@example.net",
"email_recp": "",
"email_subject": "ems-esp notification"
} }
}, },
{ {
@@ -207,22 +196,14 @@
} }
}, },
{ {
"type": "customSupport", "type": "nvs",
"Support": { "nvs": [
"html": [ {
"This product is installed and managed by:", "type": 1,
"", "key": "fresh_firmware",
"<b>Bosch Installer Example</b>", "value": 0
"", }
"Nefit Road 12", ]
"1234 AB Amsterdam",
"Phone: +31 123 456 789",
"email: support@boschinstaller.nl",
"",
"For help and questions please <a target='_blank' href='https://emsesp.org'>contact</a> your installer."
],
"img_url": "https://emsesp.org/media/images/designer.png"
}
} }
] ]
} }

View File

@@ -112,10 +112,10 @@ telegram_type_id,name,is_fetched
0x02A0,RC300Curves, 0x02A0,RC300Curves,
0x02A1,RC300Curves, 0x02A1,RC300Curves,
0x02A2,RC300Curves, 0x02A2,RC300Curves,
0x02A5,RC300Monitor,fetched 0x02A5,RC300Monitor,
0x02A6,CRFMonitor, 0x02A6,RC300Monitor,
0x02A7,RC300Monitor, 0x02A7,RC300Monitor,
0x02A8,CRFMonitor, 0x02A8,RC300Monitor,
0x02A9,RC300Monitor, 0x02A9,RC300Monitor,
0x02AA,RC300Monitor, 0x02AA,RC300Monitor,
0x02AB,RC300Monitor, 0x02AB,RC300Monitor,
@@ -171,7 +171,7 @@ telegram_type_id,name,is_fetched
0x0468,HPSet, 0x0468,HPSet,
0x0469,HPSet, 0x0469,HPSet,
0x046A,HPSet, 0x046A,HPSet,
0x0470,RC300Summer2, 0x0470,RC300Summer2,fetched
0x0471,RC300Summer2, 0x0471,RC300Summer2,
0x0472,RC300Summer2, 0x0472,RC300Summer2,
0x0473,RC300Summer2, 0x0473,RC300Summer2,
@@ -179,6 +179,7 @@ telegram_type_id,name,is_fetched
0x0475,RC300Summer2, 0x0475,RC300Summer2,
0x0476,RC300Summer2, 0x0476,RC300Summer2,
0x0477,RC300Summer2, 0x0477,RC300Summer2,
0x0478,RC300Summer2,
0x047B,HP2, 0x047B,HP2,
0x0484,HPSilentMode,fetched 0x0484,HPSilentMode,fetched
0x0485,HpCooling,fetched 0x0485,HpCooling,fetched
1 telegram_type_id name is_fetched
112 0x02A0 RC300Curves
113 0x02A1 RC300Curves
114 0x02A2 RC300Curves
115 0x02A5 RC300Monitor fetched
116 0x02A6 CRFMonitor RC300Monitor
117 0x02A7 RC300Monitor
118 0x02A8 CRFMonitor RC300Monitor
119 0x02A9 RC300Monitor
120 0x02AA RC300Monitor
121 0x02AB RC300Monitor
171 0x0468 HPSet
172 0x0469 HPSet
173 0x046A HPSet
174 0x0470 RC300Summer2 fetched
175 0x0471 RC300Summer2
176 0x0472 RC300Summer2
177 0x0473 RC300Summer2
179 0x0475 RC300Summer2
180 0x0476 RC300Summer2
181 0x0477 RC300Summer2
182 0x0478 RC300Summer2
183 0x047B HP2
184 0x0484 HPSilentMode fetched
185 0x0485 HpCooling fetched

View File

@@ -26,8 +26,8 @@
"@alova/adapter-xhr": "2.3.1", "@alova/adapter-xhr": "2.3.1",
"@emotion/react": "^11.14.0", "@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1", "@emotion/styled": "^11.14.1",
"@mui/icons-material": "^9.0.0", "@mui/icons-material": "^9.0.1",
"@mui/material": "^9.0.0", "@mui/material": "^9.0.1",
"@preact/compat": "^18.3.2", "@preact/compat": "^18.3.2",
"@table-library/react-table-library": "4.1.15", "@table-library/react-table-library": "4.1.15",
"alova": "3.5.1", "alova": "3.5.1",
@@ -38,10 +38,10 @@
"magic-string": "^0.30.21", "magic-string": "^0.30.21",
"mime-types": "^3.0.2", "mime-types": "^3.0.2",
"preact": "^10.29.1", "preact": "^10.29.1",
"react": "^19.2.5", "react": "^19.2.6",
"react-dom": "^19.2.5", "react-dom": "^19.2.6",
"react-icons": "^5.6.0", "react-icons": "^5.6.0",
"react-router": "^7.14.2", "react-router": "^7.15.0",
"react-toastify": "^11.1.0", "react-toastify": "^11.1.0",
"typesafe-i18n": "^5.27.1", "typesafe-i18n": "^5.27.1",
"typescript": "^6.0.3" "typescript": "^6.0.3"
@@ -52,20 +52,20 @@
"@preact/compat": "^18.3.2", "@preact/compat": "^18.3.2",
"@preact/preset-vite": "^2.10.5", "@preact/preset-vite": "^2.10.5",
"@trivago/prettier-plugin-sort-imports": "^6.0.2", "@trivago/prettier-plugin-sort-imports": "^6.0.2",
"@types/node": "^25.6.0", "@types/node": "^25.7.0",
"@types/react": "^19.2.14", "@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"axe-core": "^4.11.3", "axe-core": "^4.11.4",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"eslint": "^10.2.1", "eslint": "^10.3.0",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"prettier": "^3.8.3", "prettier": "^3.8.3",
"rollup-plugin-visualizer": "^7.0.1", "rollup-plugin-visualizer": "^7.0.1",
"terser": "^5.46.1", "terser": "^5.47.1",
"typescript-eslint": "^8.59.0", "typescript-eslint": "^8.59.3",
"vite": "^8.0.9", "vite": "^8.0.12",
"vite-plugin-imagemin": "^0.6.1", "vite-plugin-imagemin": "^0.6.1",
"vite-tsconfig-paths": "^6.1.1" "vite-tsconfig-paths": "^6.1.1"
}, },
"packageManager": "pnpm@10.33.1+sha512.05ba3c1d5d1c18f68df06470d74055e62d41fc110a0c660db1b2dfb2785327f04cf0f68345d4609bc52089e7fa0343c31593b2f9594e2c5d5da426230acc9820" "packageManager": "pnpm@10.33.4+sha512.1c67b3b359b2d408119ba1ed289f34b8fc3c6873412bec6fd264fbdc82489e510fcbecb9ce9d22dae7f3b76269d8441046014bdca53b9979cd7a561ad631b800"
} }

800
interface/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -242,6 +242,23 @@ const SensorsAnalogDialog = ({
</ValidatedTextField> </ValidatedTextField>
</Grid> </Grid>
)} )}
{editItem.t === AnalogType.DIGITAL_IN && (
<Grid>
<ValidatedTextField
name="f"
label={LL.POLARITY()}
value={editItem.f}
sx={{ width: '15ch' }}
fullWidth
select
onChange={updateFormValue}
disabled={editItem.s}
>
<MenuItem value={1}>{LL.ACTIVEHIGH()}</MenuItem>
<MenuItem value={0}>{LL.ACTIVELOW()}</MenuItem>
</ValidatedTextField>
</Grid>
)}
{editItem.t === AnalogType.ADC && ( {editItem.t === AnalogType.ADC && (
<Grid> <Grid>
<ValidatedTextField <ValidatedTextField
@@ -447,7 +464,7 @@ const SensorsAnalogDialog = ({
name="o" name="o"
label={LL.POLARITY()} label={LL.POLARITY()}
value={editItem.o} value={editItem.o}
sx={{ width: '11ch' }} sx={{ width: '15ch' }}
select select
onChange={updateFormValue} onChange={updateFormValue}
disabled={editItem.s} disabled={editItem.s}

View File

@@ -677,6 +677,7 @@ const ApplicationSettings = () => {
<MenuItem value={2}>EMS+</MenuItem> <MenuItem value={2}>EMS+</MenuItem>
<MenuItem value={3}>HT3</MenuItem> <MenuItem value={3}>HT3</MenuItem>
<MenuItem value={4}>{LL.HARDWARE()}</MenuItem> <MenuItem value={4}>{LL.HARDWARE()}</MenuItem>
<MenuItem value={5}>Auto</MenuItem>
</TextField> </TextField>
</Grid> </Grid>
<Grid> <Grid>

View File

@@ -22,10 +22,11 @@
#include "Arduino.h" #include "Arduino.h"
#define EMS_TXMODE_OFF 0 #define EMS_TXMODE_OFF 0
#define EMS_TXMODE_DEFAULT 1 #define EMS_TXMODE_EMS 1
#define EMS_TXMODE_EMSPLUS 2 #define EMS_TXMODE_EMSPLUS 2
#define EMS_TXMODE_HT3 3 #define EMS_TXMODE_HT3 3
#define EMS_TXMODE_HW 4 #define EMS_TXMODE_HW 4
#define EMS_TXMODE_AUTO 5
namespace emsesp { namespace emsesp {

View File

@@ -15,5 +15,5 @@
"itty-router": "^5.0.23", "itty-router": "^5.0.23",
"prettier": "^3.8.3" "prettier": "^3.8.3"
}, },
"packageManager": "pnpm@10.33.1+sha512.05ba3c1d5d1c18f68df06470d74055e62d41fc110a0c660db1b2dfb2785327f04cf0f68345d4609bc52089e7fa0343c31593b2f9594e2c5d5da426230acc9820" "packageManager": "pnpm@10.33.4+sha512.1c67b3b359b2d408119ba1ed289f34b8fc3c6873412bec6fd264fbdc82489e510fcbecb9ce9d22dae7f3b76269d8441046014bdca53b9979cd7a561ad631b800"
} }

View File

@@ -46,8 +46,8 @@ packages:
resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
'@babel/parser@7.29.2': '@babel/parser@7.29.3':
resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} resolution: {integrity: sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
hasBin: true hasBin: true
@@ -185,7 +185,7 @@ snapshots:
'@babel/generator@7.29.1': '@babel/generator@7.29.1':
dependencies: dependencies:
'@babel/parser': 7.29.2 '@babel/parser': 7.29.3
'@babel/types': 7.29.0 '@babel/types': 7.29.0
'@jridgewell/gen-mapping': 0.3.13 '@jridgewell/gen-mapping': 0.3.13
'@jridgewell/trace-mapping': 0.3.31 '@jridgewell/trace-mapping': 0.3.31
@@ -197,14 +197,14 @@ snapshots:
'@babel/helper-validator-identifier@7.28.5': {} '@babel/helper-validator-identifier@7.28.5': {}
'@babel/parser@7.29.2': '@babel/parser@7.29.3':
dependencies: dependencies:
'@babel/types': 7.29.0 '@babel/types': 7.29.0
'@babel/template@7.28.6': '@babel/template@7.28.6':
dependencies: dependencies:
'@babel/code-frame': 7.29.0 '@babel/code-frame': 7.29.0
'@babel/parser': 7.29.2 '@babel/parser': 7.29.3
'@babel/types': 7.29.0 '@babel/types': 7.29.0
'@babel/traverse@7.29.0': '@babel/traverse@7.29.0':
@@ -212,7 +212,7 @@ snapshots:
'@babel/code-frame': 7.29.0 '@babel/code-frame': 7.29.0
'@babel/generator': 7.29.1 '@babel/generator': 7.29.1
'@babel/helper-globals': 7.28.0 '@babel/helper-globals': 7.28.0
'@babel/parser': 7.29.2 '@babel/parser': 7.29.3
'@babel/template': 7.28.6 '@babel/template': 7.28.6
'@babel/types': 7.29.0 '@babel/types': 7.29.0
debug: 4.4.3 debug: 4.4.3
@@ -249,7 +249,7 @@ snapshots:
'@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.8.3)': '@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.8.3)':
dependencies: dependencies:
'@babel/generator': 7.29.1 '@babel/generator': 7.29.1
'@babel/parser': 7.29.2 '@babel/parser': 7.29.3
'@babel/traverse': 7.29.0 '@babel/traverse': 7.29.0
'@babel/types': 7.29.0 '@babel/types': 7.29.0
javascript-natural-sort: 0.7.1 javascript-natural-sort: 0.7.1

View File

@@ -59,7 +59,7 @@ framework = arduino
board_build.partitions = partitions/esp32_partition_16M.csv board_build.partitions = partitions/esp32_partition_16M.csv
board_upload.flash_size = 16MB board_upload.flash_size = 16MB
board_build.app_partition_name = app0 board_build.app_partition_name = app0
platform = espressif32@6.13.0 ; Arduino Core 2.0.17 / IDF 4.4.7 platform = espressif32@7.0.0 ; Arduino Core 2.0.17 / IDF 4.4.7
; 32MB Flash variants ; 32MB Flash variants
[espressif32_base_32M] [espressif32_base_32M]
@@ -67,7 +67,7 @@ framework = arduino
board_build.partitions = partitions/esp32_partition_32M.csv board_build.partitions = partitions/esp32_partition_32M.csv
board_upload.flash_size = 32MB board_upload.flash_size = 32MB
board_build.app_partition_name = app0 board_build.app_partition_name = app0
platform = espressif32@6.13.0 ; Arduino Core 2.0.17 / IDF 4.4.7 platform = espressif32@7.0.0 ; Arduino Core 2.0.17 / IDF 4.4.7
; use Tasmota's library for 4MB Flash variants. ; use Tasmota's library for 4MB Flash variants.
; Removes libs (like mbedtsl, so no WiFi_secure.h) to increase available heap ; Removes libs (like mbedtsl, so no WiFi_secure.h) to increase available heap
@@ -105,7 +105,7 @@ board_build.filesystem = littlefs
lib_deps = lib_deps =
bblanchon/ArduinoJson @ 7.4.3 bblanchon/ArduinoJson @ 7.4.3
ESP32Async/AsyncTCP @ 3.4.10 ESP32Async/AsyncTCP @ 3.4.10
ESP32Async/ESPAsyncWebServer @ 3.10.3 ESP32Async/ESPAsyncWebServer @ 3.11.0
; https://github.com/emsesp/EMS-ESP-Modules.git @ 1.0.8 ; https://github.com/emsesp/EMS-ESP-Modules.git @ 1.0.8
; builds the web interface only, not the firmware ; builds the web interface only, not the firmware

View File

@@ -185,10 +185,14 @@ bool MqttSettingsService::configureMqtt() {
#ifndef TASMOTA_SDK #ifndef TASMOTA_SDK
if (_state.enableTLS) { if (_state.enableTLS) {
if (_state.rootCA == "insecure") { if (_state.rootCA == "insecure") {
#if defined(EMSESP_DEBUG)
emsesp::EMSESP::logger().debug("Start insecure MQTT"); emsesp::EMSESP::logger().debug("Start insecure MQTT");
#endif
static_cast<espMqttClientSecure *>(_mqttClient)->setInsecure(); static_cast<espMqttClientSecure *>(_mqttClient)->setInsecure();
} else { } else {
#if defined(EMSESP_DEBUG)
emsesp::EMSESP::logger().debug("Start secure MQTT with rootCA"); emsesp::EMSESP::logger().debug("Start secure MQTT with rootCA");
#endif
String certificate = "-----BEGIN CERTIFICATE-----\n" + _state.rootCA + "\n-----END CERTIFICATE-----\n"; String certificate = "-----BEGIN CERTIFICATE-----\n" + _state.rootCA + "\n-----END CERTIFICATE-----\n";
static_cast<espMqttClientSecure *>(_mqttClient)->setCACert(certificate.c_str()); static_cast<espMqttClientSecure *>(_mqttClient)->setCACert(certificate.c_str());
} }

View File

@@ -4,6 +4,7 @@
#include <esp_app_format.h> #include <esp_app_format.h>
#include <esp_ota_ops.h> #include <esp_ota_ops.h>
// #include <esp_partition.h>
static String getFilenameExtension(const String & filename) { static String getFilenameExtension(const String & filename) {
const auto pos = filename.lastIndexOf('.'); const auto pos = filename.lastIndexOf('.');
@@ -16,8 +17,8 @@ static String getFilenameExtension(const String & filename) {
UploadFileService::UploadFileService(AsyncWebServer * server, SecurityManager * securityManager) UploadFileService::UploadFileService(AsyncWebServer * server, SecurityManager * securityManager)
: _securityManager(securityManager) : _securityManager(securityManager)
, _is_firmware(false) , _is_firmware(false)
, _is_filesystem(false)
, _md5() { , _md5() {
// upload a file via a form
server->on( server->on(
UPLOAD_FILE_PATH, UPLOAD_FILE_PATH,
HTTP_POST, HTTP_POST,
@@ -41,8 +42,14 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
const String extension = getFilenameExtension(filename); const String extension = getFilenameExtension(filename);
const std::size_t filesize = request->contentLength(); const std::size_t filesize = request->contentLength();
_is_firmware = false; _is_firmware = false;
if ((extension == "bin") && (filesize > 1000000)) { _is_filesystem = false;
if (extension == "bin" && filename.endsWith("littlefs.bin")) {
// LittleFS filesystem image
_is_filesystem = true;
_md5[0] = '\0'; // clear any stale md5 so Update.end() doesn't compare against it
} else if ((extension == "bin") && (filesize > 2000000)) {
_is_firmware = true; _is_firmware = true;
} else if (extension == "json") { } else if (extension == "json") {
_md5[0] = '\0'; // clear md5 _md5[0] = '\0'; // clear md5
@@ -88,6 +95,7 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
#endif #endif
// it's firmware - initialize the ArduinoOTA updater // it's firmware - initialize the ArduinoOTA updater
emsesp::EMSESP::logger().info("Uploading firmware file %s (size: %d KB). Please wait...", filename.c_str(), filesize / 1024); emsesp::EMSESP::logger().info("Uploading firmware file %s (size: %d KB). Please wait...", filename.c_str(), filesize / 1024);
// turn off UART to prevent interference with the upload // turn off UART to prevent interference with the upload
emsesp::EMSuart::stop(); emsesp::EMSuart::stop();
@@ -96,28 +104,55 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
Update.setMD5(_md5.data()); Update.setMD5(_md5.data());
_md5.front() = '\0'; _md5.front() = '\0';
} }
request->onDisconnect([this] { handleEarlyDisconnect(); }); // success, let's make sure we end the update if the client hangs up request->onDisconnect([this] { handleDisconnect(); }); // success, let's make sure we end the update if the client hangs up
} else { } else {
handleError(request, 507); // failed to begin, send an error response Insufficient Storage handleError(request, 507); // failed to begin, send an error response Insufficient Storage
return; return;
} }
} else if (_is_filesystem) {
// LittleFS filesystem image - flash directly to the spiffs/littlefs partition
emsesp::EMSESP::logger().info("Uploading filesystem image %s (size: %u KB). Please wait...", filename.c_str(), static_cast<unsigned>(filesize / 1024));
emsesp::EMSuart::stop();
LittleFS.end(); // unmount LittleFS before we overwrite the partition under it
// request->contentLength() is the multipart HTTP body size, not the file size,
// so it can exceed the partition by a few hundred bytes. Use UPDATE_SIZE_UNKNOWN
// and let the Update library size against the whole partition.
if (Update.begin(UPDATE_SIZE_UNKNOWN, U_SPIFFS)) {
// emsesp::EMSESP::logger().info("Update.begin(U_SPIFFS) ok, partition size %u bytes", static_cast<unsigned>(Update.size()));
request->onDisconnect([this] { handleDisconnect(); });
} else {
emsesp::EMSESP::logger().err("Update.begin(U_SPIFFS) failed: %s", Update.errorString());
handleError(request, 507);
return;
}
} else { } else {
// its a normal file, open a new temp file to write the contents too // its a normal file, open a new temp file to write the contents too
request->_tempFile = LittleFS.open(TEMP_FILENAME_PATH, "w"); request->_tempFile = LittleFS.open(TEMP_FILENAME_PATH, "w");
} }
} }
if (!_is_firmware) { if (_is_firmware || _is_filesystem) {
if (len && len != request->_tempFile.write(data, len)) { // stream the incoming chunk to the opened file if (!request->_tempObject) { // if we haven't delt with an error, continue with the OTA update
handleError(request, 507); // 507-Insufficient Storage if (Update.write(data, len) != len) {
} emsesp::EMSESP::logger().err("Update.write failed at offset %u (chunk %u): %s",
} else if (!request->_tempObject) { // if we haven't delt with an error, continue with the firmware update static_cast<unsigned>(Update.progress()),
if (Update.write(data, len) != len) { static_cast<unsigned>(len),
handleError(request, 500); // internal error, failed Update.errorString());
return; handleError(request, 500); // internal error, failed
} return;
if (final && !Update.end(true)) { }
handleError(request, 500); // internal error, failed if (final) {
if (!Update.end(true)) {
emsesp::EMSESP::logger().err("Update.end failed: %s", Update.errorString());
handleError(request, 500);
return;
}
}
} else {
if (len && len != request->_tempFile.write(data, len)) { // stream the incoming chunk to the opened file
handleError(request, 507); // 507-Insufficient Storage
}
} }
} }
} }
@@ -135,11 +170,13 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) {
return; return;
} }
// check if it was a firmware upgrade // check if it was a firmware or filesystem image upgrade
// if no error, send the success response as a JSON // if no error, send the success response and request a restart
if (_is_firmware && !request->_tempObject) { if ((_is_firmware || _is_filesystem) && !request->_tempObject) {
// set NVS to tell EMS-ESP this is a new fresh firmware on next restart if (_is_firmware) {
emsesp::EMSESP::nvs_.putBool(emsesp::EMSESP_NVS_BOOT_NEW_FIRMWARE, true); // set NVS to tell EMS-ESP this is a new fresh firmware on next restart
emsesp::EMSESP::nvs_.putBool(emsesp::EMSESP_NVS_BOOT_NEW_FIRMWARE, true);
}
AsyncWebServerResponse * response = request->beginResponse(200); AsyncWebServerResponse * response = request->beginResponse(200);
request->send(response); request->send(response);
@@ -178,15 +215,21 @@ void UploadFileService::handleError(AsyncWebServerRequest * request, int code) {
// that is caught by the web code. Unfortunately the http error code is not sent to the client on fast network connections // that is caught by the web code. Unfortunately the http error code is not sent to the client on fast network connections
if (code == 406) { if (code == 406) {
request->client()->close(); request->client()->close();
_is_firmware = false; _is_firmware = false;
_is_filesystem = false;
Update.abort(); Update.abort();
} }
// if we aborted a filesystem upload, remount LittleFS so the device keeps working
if (_is_filesystem) {
LittleFS.begin();
}
} }
void UploadFileService::handleEarlyDisconnect() { void UploadFileService::handleDisconnect() {
emsesp::EMSESP::logger().info("Upload finished"); emsesp::EMSESP::logger().info("Upload finished");
emsesp::EMSESP::system_.uart_init(); // re-enable UART emsesp::EMSESP::system_.uart_init(); // re-enable UART
_is_firmware = false; _is_firmware = false;
Update.abort(); _is_filesystem = false;
} }

View File

@@ -22,13 +22,14 @@ class UploadFileService {
private: private:
SecurityManager * _securityManager; SecurityManager * _securityManager;
bool _is_firmware; bool _is_firmware;
bool _is_filesystem;
std::array<char, 33> _md5; std::array<char, 33> _md5;
void handleUpload(AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final); void handleUpload(AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final);
void uploadComplete(AsyncWebServerRequest * request); void uploadComplete(AsyncWebServerRequest * request);
void handleError(AsyncWebServerRequest * request, int code); void handleError(AsyncWebServerRequest * request, int code);
void handleEarlyDisconnect(); void handleDisconnect();
}; };
#endif #endif

View File

@@ -287,8 +287,8 @@ void AnalogSensor::reload(bool get_nvs) {
#endif #endif
} else if (sensor.type() == AnalogType::DIGITAL_IN) { } else if (sensor.type() == AnalogType::DIGITAL_IN) {
LOG_DEBUG("Digital Read on GPIO %02d", sensor.gpio()); LOG_DEBUG("Digital Read on GPIO %02d", sensor.gpio());
sensor.set_value(digitalRead(sensor.gpio())); // initial value sensor.set_value(sensor.factor() == 0 ? !digitalRead(sensor.gpio()) : digitalRead(sensor.gpio())); // initial value
sensor.set_uom(0); // no uom, just for safe measures sensor.set_uom(0); // no uom, just for safe measures
sensor.polltime_ = 0; sensor.polltime_ = 0;
sensor.poll_ = digitalRead(sensor.gpio()); sensor.poll_ = digitalRead(sensor.gpio());
publish_sensor(sensor); publish_sensor(sensor);
@@ -465,7 +465,7 @@ void AnalogSensor::measure() {
if (uuid::get_uptime() - sensor.polltime_ >= 15 && sensor.poll_ != sensor.last_reading_) { if (uuid::get_uptime() - sensor.polltime_ >= 15 && sensor.poll_ != sensor.last_reading_) {
sensor.last_reading_ = sensor.poll_; sensor.last_reading_ = sensor.poll_;
if (sensor.type() == AnalogType::DIGITAL_IN) { if (sensor.type() == AnalogType::DIGITAL_IN) {
sensor.set_value(sensor.poll_); sensor.set_value(sensor.factor() == 0 ? !sensor.poll_ : sensor.poll_);
} else if (!sensor.poll_) { // falling edge } else if (!sensor.poll_) { // falling edge
if (sensor.type() == AnalogType::COUNTER) { if (sensor.type() == AnalogType::COUNTER) {
sensor.set_value(old_value + sensor.factor()); sensor.set_value(old_value + sensor.factor());

View File

@@ -26,11 +26,11 @@
#endif #endif
#ifndef EMSESP_DEFAULT_TX_MODE #ifndef EMSESP_DEFAULT_TX_MODE
#define EMSESP_DEFAULT_TX_MODE 1 // EMS1.0 #define EMSESP_DEFAULT_TX_MODE 5 // Auto
#endif #endif
#ifndef EMSESP_DEFAULT_EMS_BUS_ID #ifndef EMSESP_DEFAULT_EMS_BUS_ID
#define EMSESP_DEFAULT_EMS_BUS_ID 0x0B // service key #define EMSESP_DEFAULT_EMS_BUS_ID 0x49 // gateway 2
#endif #endif
#ifndef EMSESP_DEFAULT_SYSLOG_ENABLED #ifndef EMSESP_DEFAULT_SYSLOG_ENABLED

View File

@@ -448,6 +448,14 @@ class EMSdevice {
static constexpr uint8_t EMS_DEVICE_ID_DHW2 = 0x29; // 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? static constexpr uint8_t EMS_DEVICE_ID_DHW8 = 0x2F; // last DHW module id?
static constexpr uint8_t EMS_DEVICE_ID_IPM_DHW = 0x41; // IPM module as water station static constexpr uint8_t EMS_DEVICE_ID_IPM_DHW = 0x41; // IPM module as water station
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY1 = 0x48; // KM200, MX300, MX400
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY2 = 0x49;
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY3 = 0x4A;
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY4 = 0x4B;
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY5 = 0x4C;
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY6 = 0x4D;
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY7 = 0x4E;
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY8 = 0x4F;
// generic type IDs // generic type IDs
static constexpr uint16_t EMS_TYPE_NAME = 0x01; // device config for ems devices, name ascii on offset 27ff for ems+ static constexpr uint16_t EMS_TYPE_NAME = 0x01; // device config for ems devices, name ascii on offset 27ff for ems+

View File

@@ -1710,6 +1710,11 @@ void EMSESP::start() {
bool factory_settings = false; bool factory_settings = false;
#endif #endif
#if defined(EMSESP_DEBUG)
// LOG_DEBUG("Listing root directory before:");
// system_.listDir("/", 3); // show the contents of the root directory
#endif
// start NVS storage // start NVS storage
if (!nvs_.begin("ems-esp", false, "nvs1")) { // try bigger nvs partition on 16M flash first if (!nvs_.begin("ems-esp", false, "nvs1")) { // try bigger nvs partition on 16M flash first
nvs_.begin("ems-esp", false, "nvs"); // fallback to small nvs nvs_.begin("ems-esp", false, "nvs"); // fallback to small nvs
@@ -1724,6 +1729,11 @@ void EMSESP::start() {
// loads core system services settings (network, mqtt, ap, ntp etc) // loads core system services settings (network, mqtt, ap, ntp etc)
esp32React.begin(); esp32React.begin();
#if defined(EMSESP_DEBUG)
// LOG_DEBUG("Listing root directory before:");
// system_.listDir("/", 3); // show the contents of the root directory
#endif
#ifndef EMSESP_STANDALONE #ifndef EMSESP_STANDALONE
if (factory_settings) { if (factory_settings) {
LOG_WARNING("No settings found on filesystem. Using factory settings."); LOG_WARNING("No settings found on filesystem. Using factory settings.");

View File

@@ -526,6 +526,29 @@ void System::syslog_init() {
#endif #endif
} }
// start or reconfigure modbus
void System::modbus_init() {
EMSESP::webSettingsService.read([&](WebSettings & settings) {
if (settings.modbus_enabled) {
if (EMSESP::modbus_ == nullptr) {
EMSESP::modbus_ = new Modbus;
EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000);
} else if (settings.modbus_port != modbus_port_ || settings.modbus_max_clients != modbus_max_clients_ || settings.modbus_timeout != modbus_timeout_) {
EMSESP::modbus_->stop();
EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000);
}
} else if (EMSESP::modbus_ != nullptr) {
EMSESP::modbus_->stop();
delete EMSESP::modbus_;
EMSESP::modbus_ = nullptr;
}
modbus_enabled_ = settings.modbus_enabled;
modbus_port_ = settings.modbus_port;
modbus_max_clients_ = settings.modbus_max_clients;
modbus_timeout_ = settings.modbus_timeout;
});
}
// read specific major system settings to store locally for faster access // read specific major system settings to store locally for faster access
void System::store_settings(WebSettings & settings) { void System::store_settings(WebSettings & settings) {
version_ = settings.version; version_ = settings.version;
@@ -563,25 +586,6 @@ void System::store_settings(WebSettings & settings) {
locale_ = settings.locale; locale_ = settings.locale;
developer_mode_ = settings.developer_mode; developer_mode_ = settings.developer_mode;
// start services
if (settings.modbus_enabled) {
if (EMSESP::modbus_ == nullptr) {
EMSESP::modbus_ = new Modbus;
EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000);
} else if (settings.modbus_port != modbus_port_ || settings.modbus_max_clients != modbus_max_clients_ || settings.modbus_timeout != modbus_timeout_) {
EMSESP::modbus_->stop();
EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000);
}
} else if (EMSESP::modbus_ != nullptr) {
EMSESP::modbus_->stop();
delete EMSESP::modbus_;
EMSESP::modbus_ = nullptr;
}
modbus_enabled_ = settings.modbus_enabled;
modbus_port_ = settings.modbus_port;
modbus_max_clients_ = settings.modbus_max_clients;
modbus_timeout_ = settings.modbus_timeout;
} }
// Starts up core services // Starts up core services
@@ -631,17 +635,16 @@ void System::start() {
network_init(); // network network_init(); // network
uart_init(); // start UART uart_init(); // start UART
syslog_init(); // start syslog syslog_init(); // start syslog
modbus_init(); // start modbus
} }
// button single click // button single click
void System::button_OnClick(PButton & b) { void System::button_OnClick(PButton & b) {
LOG_NOTICE("Button pressed - single click"); LOG_NOTICE("Button pressed - single click");
#if defined(EMSESP_TEST)
#ifndef EMSESP_STANDALONE #ifndef EMSESP_STANDALONE
// show filesystem // show filesystem
Test::listDir(LittleFS, "/", 3); listDir("/", 3);
#endif
#endif #endif
} }
@@ -1713,7 +1716,7 @@ void System::exportSystemBackup(JsonObject output) {
output["version"] = EMSESP_APP_VERSION; // add the version to the output output["version"] = EMSESP_APP_VERSION; // add the version to the output
#ifndef EMSESP_STANDALONE #ifndef EMSESP_STANDALONE
// add date/time if NTP enabled and active // add date/time if NTP enabled and active
if ((esp_sntp_enabled()) && (EMSESP::system_.ntp_connected())) { if ((esp_sntp_enabled()) && (EMSESP::system_.ntp_connected())) {
time_t now = time(nullptr); time_t now = time(nullptr);
if (now > 1500000000L) { if (now > 1500000000L) {
@@ -3266,7 +3269,7 @@ void System::set_valid_system_gpios() {
valid_system_gpios_ = string_range_to_vector("0-21", "2, 8, 12-17, 18-19"); valid_system_gpios_ = string_range_to_vector("0-21", "2, 8, 12-17, 18-19");
#elif CONFIG_IDF_TARGET_ESP32S2 #elif CONFIG_IDF_TARGET_ESP32S2
// https://docs.espressif.com/projects/esp-idf/en/stable/esp32s2/api-reference/peripherals/gpio.html // https://docs.espressif.com/projects/esp-idf/en/stable/esp32s2/api-reference/peripherals/gpio.html
// excluded: // excluded:
// GPIO26 - GPIO32 = SPI flash and PSRAM // GPIO26 - GPIO32 = SPI flash and PSRAM
// GPIO45 - GPIO46 = strapping pins // GPIO45 - GPIO46 = strapping pins
@@ -3279,7 +3282,7 @@ void System::set_valid_system_gpios() {
valid_system_gpios_ = string_range_to_vector("0-46", "19, 20, 26-32, 45-46, 39-42, 22-25"); valid_system_gpios_ = string_range_to_vector("0-46", "19, 20, 26-32, 45-46, 39-42, 22-25");
#elif CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S3
// https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/api-reference/peripherals/gpio.html // https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/api-reference/peripherals/gpio.html
// excluded: // excluded:
// GPIO3, GPIO45 - GPIO46 = strapping pins // GPIO3, GPIO45 - GPIO46 = strapping pins
// GPIO26 - GPIO32 = SPI flash and PSRAM and not recommended // GPIO26 - GPIO32 = SPI flash and PSRAM and not recommended
@@ -3298,7 +3301,7 @@ void System::set_valid_system_gpios() {
} }
#elif CONFIG_IDF_TARGET_ESP32 #elif CONFIG_IDF_TARGET_ESP32
// https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/peripherals/gpio.html // https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/peripherals/gpio.html
// excluded: // excluded:
// GPIO6 - GPIO11, GPIO16 - GPIO17 = used for SPI flash and PSRAM (dio mode only GPIO06-GPIO08, GPIO11) // GPIO6 - GPIO11, GPIO16 - GPIO17 = used for SPI flash and PSRAM (dio mode only GPIO06-GPIO08, GPIO11)
// GPIO20, GPIO24, GPIO28 - GPIO31 = don't exist // GPIO20, GPIO24, GPIO28 - GPIO31 = don't exist
@@ -3378,6 +3381,24 @@ void System::remove_gpio(uint8_t pin, bool also_system) {
} }
} }
// remove a gpio that has 0 for disable
void System::remove_optional_gpio(uint8_t pin) {
if (pin) {
remove_gpio(pin, false);
}
}
// set unused gpios to default state input high-Z
void System::reset_unused_gpios() {
for (const auto & pin : valid_system_gpios_) {
auto it = std::find_if(used_gpios_.begin(), used_gpios_.end(), [pin](const GpioUsage & usage) { return usage.pin == pin; });
if (it == used_gpios_.end()) {
LOG_DEBUG("reset pin %d", pin);
pinMode(pin, INPUT);
}
}
}
// return a list of GPIO's available for use // return a list of GPIO's available for use
std::vector<uint8_t> System::available_gpios() { std::vector<uint8_t> System::available_gpios() {
std::vector<uint8_t> gpios; std::vector<uint8_t> gpios;
@@ -3412,4 +3433,39 @@ void System::restore_snapshot_gpios(std::vector<int8_t> & u_gpios, std::vector<i
} }
} }
// show the contents of a directory in the LittleFS filesystem
void System::listDir(const char * dirname, uint8_t levels) {
#if defined(EMSESP_DEBUG)
#ifndef EMSESP_STANDALONE
File root = LittleFS.open(dirname);
if (!root) {
LOG_DEBUG("Failed to open directory %s", dirname);
return;
}
if (!root.isDirectory()) {
LOG_DEBUG("%s is not a directory", dirname);
return;
}
LOG_DEBUG("(directory) %s", dirname);
File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
std::string line = std::string(file.name()) + "/";
if (levels) {
// prefix a / to the name to make it a full path
listDir(("/" + String(file.name())).c_str(), levels - 1);
}
} else {
std::string line = " (file) " + std::string(file.name()) + " (" + std::to_string(file.size()) + " bytes)";
LOG_DEBUG("%s", line.c_str());
}
file = root.openNextFile();
}
#endif
#endif
}
} // namespace emsesp } // namespace emsesp

View File

@@ -109,6 +109,8 @@ class System {
static void get_value_json(JsonObject output, const std::string & circuit, const std::string & name, JsonVariant val); static void get_value_json(JsonObject output, const std::string & circuit, const std::string & name, JsonVariant val);
static std::string get_metrics_prometheus(); static std::string get_metrics_prometheus();
static void listDir(const char * dirname, uint8_t levels);
#if defined(EMSESP_TEST) #if defined(EMSESP_TEST)
static bool command_test(const char * value, const int8_t id); static bool command_test(const char * value, const int8_t id);
#endif #endif
@@ -122,6 +124,7 @@ class System {
void show_mem(const char * note); void show_mem(const char * note);
void store_settings(class WebSettings & settings); void store_settings(class WebSettings & settings);
void syslog_init(); void syslog_init();
void modbus_init();
bool check_upgrade(); bool check_upgrade();
bool check_restore(); bool check_restore();
void heartbeat_json(JsonObject output); void heartbeat_json(JsonObject output);
@@ -376,6 +379,8 @@ class System {
#endif #endif
static void remove_gpio(uint8_t pin, bool also_system = false); // remove a gpio from both valid (optional) and used lists static void remove_gpio(uint8_t pin, bool also_system = false); // remove a gpio from both valid (optional) and used lists
static void remove_optional_gpio(uint8_t pin);
static void reset_unused_gpios();
// Partition info map: partition name -> {version, size, install_date} // Partition info map: partition name -> {version, size, install_date}
std::map<std::string, PartitionInfo, std::less<>, AllocatorPSRAM<std::pair<const std::string, PartitionInfo>>> partition_info_; std::map<std::string, PartitionInfo, std::less<>, AllocatorPSRAM<std::pair<const std::string, PartitionInfo>>> partition_info_;

View File

@@ -43,6 +43,7 @@ uint8_t EMSbus::ems_mask_ = EMS_MASK_UNSET; // unset so its triggered
uint8_t EMSbus::ems_bus_id_ = EMSESP_DEFAULT_EMS_BUS_ID; uint8_t EMSbus::ems_bus_id_ = EMSESP_DEFAULT_EMS_BUS_ID;
uint8_t EMSbus::tx_mode_ = EMSESP_DEFAULT_TX_MODE; uint8_t EMSbus::tx_mode_ = EMSESP_DEFAULT_TX_MODE;
uint8_t EMSbus::tx_state_ = Telegram::Operation::NONE; uint8_t EMSbus::tx_state_ = Telegram::Operation::NONE;
bool EMSbus::isEMS2_ = false;
uuid::log::Logger EMSbus::logger_{F_(telegram), uuid::log::Facility::CONSOLE}; uuid::log::Logger EMSbus::logger_{F_(telegram), uuid::log::Facility::CONSOLE};
@@ -206,7 +207,9 @@ void RxService::add(uint8_t * data, uint8_t length) {
message_data = data + 6; message_data = data + 6;
message_length = length - 7; message_length = length - 7;
} }
if (type_id > 0x0FF && message_length > 1) { // used for auto tx_mode
set_ems2();
}
// if we're watching and "raw" print out actual telegram as bytes to the console // if we're watching and "raw" print out actual telegram as bytes to the console
// including the CRC at the end // including the CRC at the end
if (EMSESP::watch() == EMSESP::Watch::WATCH_RAW) { if (EMSESP::watch() == EMSESP::Watch::WATCH_RAW) {

View File

@@ -168,6 +168,15 @@ class EMSbus {
return (ems_mask_ == EMS_MASK_HT3); return (ems_mask_ == EMS_MASK_HT3);
} }
static bool is_ems2() {
return isEMS2_;
}
static void set_ems2() {
isEMS2_ = true;
;
}
static uint8_t ems_mask() { static uint8_t ems_mask() {
return ems_mask_; return ems_mask_;
} }
@@ -242,6 +251,7 @@ class EMSbus {
static uint8_t ems_bus_id_; // the bus id, which configurable and stored in settings static uint8_t ems_bus_id_; // the bus id, which configurable and stored in settings
static uint8_t tx_mode_; // local copy of the tx mode static uint8_t tx_mode_; // local copy of the tx mode
static uint8_t tx_state_; // state of the Tx line (NONE or waiting on a TX_READ or TX_WRITE) static uint8_t tx_state_; // state of the Tx line (NONE or waiting on a TX_READ or TX_WRITE)
static bool isEMS2_;
}; };
class RxService : public EMSbus { class RxService : public EMSbus {

View File

@@ -39,11 +39,11 @@ Connect::Connect(uint8_t device_type, uint8_t device_id, uint8_t product_id, con
DeviceValueUOM::DEGREES); DeviceValueUOM::DEGREES);
// Roomthermostats // Roomthermostats
for (uint8_t i = 0; i < 16; i++) { for (uint8_t i = 0; i < 16; i++) {
register_telegram_type(0x0BDD + i, "Room", false, MAKE_PF_CB(process_roomThermostat)); // broadcasted register_telegram_type(0x0BDD + i, "Room", false, MAKE_PF_CB(process_roomThermostat)); // broadcasted
register_telegram_type(0x0B3D + i, "Roomname", false, MAKE_PF_CB(process_roomThermostatName), 100); // fetch for active circuits register_telegram_type(0x0B3D + i, "Roomname", false, MAKE_PF_CB(process_roomThermostatName), 100); // fetch for active circuits
register_telegram_type(0x0BB5 + i, "Roomsettings", false, MAKE_PF_CB(process_roomThermostatSettings), 8); // fetch for active circuits register_telegram_type(0x0BB5 + i, "Roomsettings", false, MAKE_PF_CB(process_roomThermostatSettings), 8); // fetch for active circuits
register_telegram_type(0x1230 + i, "Roomparams", false, MAKE_PF_CB(process_roomThermostatParam)); // fetch for active circuits register_telegram_type(0x1230 + i, "Roomparams", false, MAKE_PF_CB(process_roomThermostatParam)); // fetch for active circuits
register_telegram_type(0x1244 + i, "Roomdata", false, MAKE_PF_CB(process_roomThermostatData)); // broadcasted register_telegram_type(0x1244 + i, "Roomdata", false, MAKE_PF_CB(process_roomThermostatData)); // broadcasted
} }
register_telegram_type(0xDB65, "Roomschedule", true, MAKE_PF_CB(process_roomSchedule)); register_telegram_type(0xDB65, "Roomschedule", true, MAKE_PF_CB(process_roomSchedule));
// 0x2040, broadcast 36 bytes: // 0x2040, broadcast 36 bytes:

View File

@@ -166,7 +166,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
set2_typeids = {0x0421, 0x0422, 0x0423, 0x0424}; set2_typeids = {0x0421, 0x0422, 0x0423, 0x0424};
summer_typeids = {0x02AF, 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6}; summer_typeids = {0x02AF, 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6};
curve_typeids = {0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1, 0x02A2}; curve_typeids = {0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1, 0x02A2};
summer2_typeids = {0x0470, 0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0476, 0x0477, 0x0478}; summer2_typeids = {0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0476, 0x0477, 0x0478};
hp_typeids = {0x0467, 0x0468, 0x0469, 0x046A}; hp_typeids = {0x0467, 0x0468, 0x0469, 0x046A};
hpmode_typeids = {0x0291, 0x0292, 0x0293, 0x0294}; hpmode_typeids = {0x0291, 0x0292, 0x0293, 0x0294};
const size_t monitor_size = monitor_typeids.size(); const size_t monitor_size = monitor_typeids.size();
@@ -207,6 +207,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(0x16E, "Absent", true, MAKE_PF_CB(process_Absent), 1); register_telegram_type(0x16E, "Absent", true, MAKE_PF_CB(process_Absent), 1);
register_telegram_type(0xBF, "ErrorMessage", false, MAKE_PF_CB(process_ErrorMessageBF)); register_telegram_type(0xBF, "ErrorMessage", false, MAKE_PF_CB(process_ErrorMessageBF));
register_telegram_type(0xC0, "RCErrorMessage", false, MAKE_PF_CB(process_RCErrorMessage2)); register_telegram_type(0xC0, "RCErrorMessage", false, MAKE_PF_CB(process_RCErrorMessage2));
register_telegram_type(0x470, "RC300Summer2", true, MAKE_PF_CB(process_RC300Summer2), 8);
EMSESP::send_read_request(0xC0, device_id, 0, 20); // read last errorcode on start (only published on errors) EMSESP::send_read_request(0xC0, device_id, 0, 20); // read last errorcode on start (only published on errors)
// JUNKERS/HT3 // JUNKERS/HT3
@@ -1268,7 +1269,13 @@ void Thermostat::process_RC300Summer(std::shared_ptr<const Telegram> telegram) {
void Thermostat::process_RC300Summer2(std::shared_ptr<const Telegram> telegram) { void Thermostat::process_RC300Summer2(std::shared_ptr<const Telegram> telegram) {
auto hc = heating_circuit(telegram); auto hc = heating_circuit(telegram);
if (hc == nullptr) { if (hc == nullptr) {
return; // telegram 0x470 see https://github.com/emsesp/EMS-ESP32/issues/2686
if (telegram->type_id == 0x470 && telegram->message_length > 2) {
hc = heating_circuit(1);
summer2_typeids[0] = 0x470;
} else {
return;
}
} }
if (hc->statusbyte & 1) { if (hc->statusbyte & 1) {
has_update(telegram, hc->summersetmode, 0); has_update(telegram, hc->summersetmode, 0);

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.8.2-dev.19" #define EMSESP_APP_VERSION "3.8.2"

View File

@@ -68,7 +68,7 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) {
uart_telegram({0x08, 0x98, 0x33, 0x00, 0x23, 0x24}); uart_telegram({0x08, 0x98, 0x33, 0x00, 0x23, 0x24});
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13) // Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00}); uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
// Thermostat RCPLUSStatusMessage_HC1(0x01A5) // Thermostat RCPLUSStatusMessage_HC1(0x01A5)
uart_telegram({0x98, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xCF, 0x21, 0x2E, 0x00, 0x00, 0x2E, 0x24, uart_telegram({0x98, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xCF, 0x21, 0x2E, 0x00, 0x00, 0x2E, 0x24,
@@ -89,7 +89,7 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) {
add_device(0x08, 219); // Greenstar HIU/Logamax kompakt WS170 add_device(0x08, 219); // Greenstar HIU/Logamax kompakt WS170
// [emsesp] boiler(0x08) -W-> Me(0x0B), UBAMonitorFastPlus(0xE4), data: 00 01 35 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00 (offset 6) // [emsesp] boiler(0x08) -W-> Me(0x49), UBAMonitorFastPlus(0xE4), data: 00 01 35 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00 (offset 6)
uart_telegram({0x08, 0x00, 0xE4, 0x00, // uart_telegram({0x08, 0x00, 0xE4, 0x00, //
00, 01, 0x35, 00, 00, 00, 00, 00, 00, 00, 00, 0x80, 00, 00, 00, 00, 00, 00, 00, 0x80, 00}); 00, 01, 0x35, 00, 00, 00, 00, 00, 00, 00, 00, 0x80, 00, 00, 00, 00, 00, 00, 00, 0x80, 00});
@@ -112,7 +112,7 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) {
uart_telegram({0x08, 0x90, 0x33, 0x00, 0x23, 0x24}); uart_telegram({0x08, 0x90, 0x33, 0x00, 0x23, 0x24});
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13) // Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00}); uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
// Thermostat 0x2A5 for HC1 // Thermostat 0x2A5 for HC1
uart_telegram({0x10, 00, 0xFF, 00, 01, 0xA5, 0x80, 00, 01, 0x30, 0x28, 00, 0x30, 0x28, 01, 0x54, uart_telegram({0x10, 00, 0xFF, 00, 01, 0xA5, 0x80, 00, 01, 0x30, 0x28, 00, 0x30, 0x28, 01, 0x54,
@@ -144,7 +144,7 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) {
uart_telegram({0x08, 0x90, 0x33, 0x00, 0x23, 0x24}); uart_telegram({0x08, 0x90, 0x33, 0x00, 0x23, 0x24});
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13) // Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00}); uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
// Thermostat 0x2A5 for HC1 // Thermostat 0x2A5 for HC1
uart_telegram({0x10, 00, 0xFF, 00, 01, 0xA5, 0x80, 00, 01, 0x30, 0x28, 00, 0x30, 0x28, 01, 0x54, uart_telegram({0x10, 00, 0xFF, 00, 01, 0xA5, 0x80, 00, 01, 0x30, 0x28, 00, 0x30, 0x28, 01, 0x54,
@@ -160,7 +160,7 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) {
EMSESP::logger().notice("Adding a Gateway..."); EMSESP::logger().notice("Adding a Gateway...");
// add 0x48 KM200, via a version command // add 0x48 KM200, via a version command
rx_telegram({0x48, 0x0B, 0x02, 0x00, 0xBD, 0x04, 0x06, 00, 00, 00, 00, 00, 00, 00}); rx_telegram({0x48, 0x49, 0x02, 0x00, 0xBD, 0x04, 0x06, 00, 00, 00, 00, 00, 00, 00});
// Boiler(0x08) -> All(0x00), UBADevices(0x07), data: 09 01 00 00 00 00 00 00 01 00 00 00 00 // Boiler(0x08) -> All(0x00), UBADevices(0x07), data: 09 01 00 00 00 00 00 00 01 00 00 00 00
// check: make sure 0x48 is not detected again ! // check: make sure 0x48 is not detected again !
@@ -203,14 +203,14 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) {
add_device(0x08, 123); // Nefit Trendline add_device(0x08, 123); // Nefit Trendline
// UBAuptime // UBAuptime
uart_telegram({0x08, 0x0B, 0x14, 00, 0x3C, 0x1F, 0xAC, 0x70}); uart_telegram({0x08, 0x49, 0x14, 00, 0x3C, 0x1F, 0xAC, 0x70});
// Boiler -> Me, UBAMonitorFast(0x18), telegram: 08 00 18 00 00 02 5A 73 3D 0A 10 65 40 02 1A 80 00 01 E1 01 76 0E 3D 48 00 C9 44 02 00 (#data=25) // Boiler -> Me, UBAMonitorFast(0x18), telegram: 08 00 18 00 00 02 5A 73 3D 0A 10 65 40 02 1A 80 00 01 E1 01 76 0E 3D 48 00 C9 44 02 00 (#data=25)
uart_telegram({0x08, 0x00, 0x18, 0x00, 0x00, 0x02, 0x5A, 0x73, 0x3D, 0x0A, 0x10, 0x65, 0x40, 0x02, 0x1A, uart_telegram({0x08, 0x00, 0x18, 0x00, 0x00, 0x02, 0x5A, 0x73, 0x3D, 0x0A, 0x10, 0x65, 0x40, 0x02, 0x1A,
0x80, 0x00, 0x01, 0xE1, 0x01, 0x76, 0x0E, 0x3D, 0x48, 0x00, 0xC9, 0x44, 0x02, 0x00}); 0x80, 0x00, 0x01, 0xE1, 0x01, 0x76, 0x0E, 0x3D, 0x48, 0x00, 0xC9, 0x44, 0x02, 0x00});
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13) // Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00}); uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
return true; return true;
} }
@@ -234,10 +234,10 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) {
add_device(0x30, 163); // SM100 add_device(0x30, 163); // SM100
// SM100Monitor - type 0x0362 EMS+ - for SM100 and SM200 // SM100Monitor - type 0x0362 EMS+ - for SM100 and SM200
uart_telegram({0xB0, 0x0B, 0xFF, 00, 0x02, 0x62, 00, 0x44, 0x02, 0x7A, 0x80, 00, 0x80, 0x00, 0x80, 00, uart_telegram({0xB0, 0x49, 0xFF, 00, 0x02, 0x62, 00, 0x44, 0x02, 0x7A, 0x80, 00, 0x80, 0x00, 0x80, 00,
0x80, 00, 0x80, 00, 0x80, 00, 00, 0x7C, 0x80, 00, 0x80, 00, 0x80, 00, 0x80}); 0x80, 00, 0x80, 00, 0x80, 00, 00, 0x7C, 0x80, 00, 0x80, 00, 0x80, 00, 0x80});
uart_telegram({0xB0, 0x0B, 0xFF, 0x00, 0x02, 0x62, 0x01, 0x44, 0x03, 0x30, 0x80, 00, 0x80, 00, 0x80, 00, uart_telegram({0xB0, 0x49, 0xFF, 0x00, 0x02, 0x62, 0x01, 0x44, 0x03, 0x30, 0x80, 00, 0x80, 00, 0x80, 00,
0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 0x33}); 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 0x33});
uart_telegram({0xB0, 00, 0xFF, 0x18, 02, 0x62, 0x80, 00, 0xB8}); uart_telegram({0xB0, 00, 0xFF, 0x18, 02, 0x62, 0x80, 00, 0xB8});
@@ -450,7 +450,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
// THESE ONLY WORK WITH AN ESP32, not in standalone/native mode // THESE ONLY WORK WITH AN ESP32, not in standalone/native mode
#ifndef EMSESP_STANDALONE #ifndef EMSESP_STANDALONE
if (command == "ls") { if (command == "ls") {
listDir(LittleFS, "/", 3); System::listDir("/", 3);
ok = true; ok = true;
} }
@@ -580,7 +580,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
add_device(0x09, 206); // Nefit Excellent HR30 Controller add_device(0x09, 206); // Nefit Excellent HR30 Controller
// UBAuptime // UBAuptime
uart_telegram({0x08, 0x0B, 0x14, 00, 0x3C, 0x1F, 0xAC, 0x70}); uart_telegram({0x08, 0x49, 0x14, 00, 0x3C, 0x1F, 0xAC, 0x70});
ok = true; ok = true;
} }
@@ -588,10 +588,10 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
EMSESP::logger().notice("Testing 620..."); EMSESP::logger().notice("Testing 620...");
// Version Controller // Version Controller
uart_telegram({0x09, 0x0B, 0x02, 0x00, 0x5F, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); uart_telegram({0x09, 0x49, 0x02, 0x00, 0x5F, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
// Version Boiler // Version Boiler
uart_telegram({0x08, 0x0B, 0x02, 0x00, 0x5F, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); uart_telegram({0x08, 0x49, 0x02, 0x00, 0x5F, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
ok = true; ok = true;
} }
@@ -607,7 +607,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
// simulate getting version information back from an unknown device // simulate getting version information back from an unknown device
// note there is no brand (byte 9) // note there is no brand (byte 9)
rx_telegram({0x09, 0x0B, 0x02, 0x00, 0x59, 0x09, 0x0a}); rx_telegram({0x09, 0x49, 0x02, 0x00, 0x59, 0x09, 0x0a});
shell.invoke_command("show devices"); shell.invoke_command("show devices");
shell.invoke_command("call system report"); shell.invoke_command("call system report");
@@ -618,7 +618,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
shell.printfln("Testing unknown2..."); shell.printfln("Testing unknown2...");
// simulate getting version information back from an unknown device // simulate getting version information back from an unknown device
rx_telegram({0x09, 0x0B, 0x02, 0x00, 0x5A, 0x01, 0x02}); // productID is 90 which doesn't exist rx_telegram({0x09, 0x49, 0x02, 0x00, 0x5A, 0x01, 0x02}); // productID is 90 which doesn't exist
ok = true; ok = true;
} }
@@ -815,9 +815,9 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
// test("thermostat"); // test("thermostat");
// 0xC2 // 0xC2
// [emsesp] Boiler(0x08) -> Me(0x0B), UBAErrorMessage3(0xC2), data: 08 AC 00 10 31 48 30 31 15 80 95 0B 0E 10 38 00 7F FF FF FF 08 AC 00 10 09 41 30 // [emsesp] Boiler(0x08) -> Me(0x49), UBAErrorMessage3(0xC2), data: 08 AC 00 10 31 48 30 31 15 80 95 0B 0E 10 38 00 7F FF FF FF 08 AC 00 10 09 41 30
uart_telegram( uart_telegram(
{0x08, 0x0B, 0xC2, 0, 0x08, 0xAC, 00, 0x10, 0x31, 0x48, 0x30, 0x31, 0x15, 0x80, 0x95, 0x0B, 0x0E, 0x10, 0x38, 00, 0x7F, 0xFF, 0xFF, 0xFF}); {0x08, 0x49, 0xC2, 0, 0x08, 0xAC, 00, 0x10, 0x31, 0x48, 0x30, 0x31, 0x15, 0x80, 0x95, 0x0B, 0x0E, 0x10, 0x38, 00, 0x7F, 0xFF, 0xFF, 0xFF});
// shell.invoke_command("show values"); // shell.invoke_command("show values");
@@ -1042,7 +1042,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
// Boiler -> Me, UBAParameterWW(0x33) // Boiler -> Me, UBAParameterWW(0x33)
// wwseltemp = goes from 52 degrees (0x34) to void (0xFF) // wwseltemp = goes from 52 degrees (0x34) to void (0xFF)
// it should delete the HA config topic homeassistant/sensor/ems-esp/boiler_wwseltemp/config // it should delete the HA config topic homeassistant/sensor/ems-esp/boiler_wwseltemp/config
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0xFF, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00}); uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0xFF, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
shell.invoke_command("call boiler wwseltemp"); shell.invoke_command("call boiler wwseltemp");
shell.invoke_command("call system publish"); shell.invoke_command("call system publish");
@@ -1795,7 +1795,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
add_device(0x18, 202); // Bosch TC100 - https://github.com/emsesp/EMS-ESP/issues/474 add_device(0x18, 202); // Bosch TC100 - https://github.com/emsesp/EMS-ESP/issues/474
// 0x0A // 0x0A
uart_telegram({0x98, 0x0B, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, uart_telegram({0x98, 0x49, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
ok = true; ok = true;
} }
@@ -1829,10 +1829,10 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
// SM100Monitor - type 0x0362 EMS+ - for SM100 and SM200 // SM100Monitor - type 0x0362 EMS+ - for SM100 and SM200
// B0 0B FF 00 02 62 00 44 02 7A 80 00 80 00 80 00 80 00 80 00 80 00 00 7C 80 00 80 00 80 00 80 // B0 0B FF 00 02 62 00 44 02 7A 80 00 80 00 80 00 80 00 80 00 80 00 00 7C 80 00 80 00 80 00 80
rx_telegram({0xB0, 0x0B, 0xFF, 00, 0x02, 0x62, 00, 0x44, 0x02, 0x7A, 0x80, 00, 0x80, 0x00, 0x80, 00, rx_telegram({0xB0, 0x49, 0xFF, 00, 0x02, 0x62, 00, 0x44, 0x02, 0x7A, 0x80, 00, 0x80, 0x00, 0x80, 00,
0x80, 00, 0x80, 00, 0x80, 00, 00, 0x7C, 0x80, 00, 0x80, 00, 0x80, 00, 0x80}); 0x80, 00, 0x80, 00, 0x80, 00, 00, 0x7C, 0x80, 00, 0x80, 00, 0x80, 00, 0x80});
rx_telegram({0xB0, 0x0B, 0xFF, 0x00, 0x02, 0x62, 0x01, 0x44, 0x03, 0x30, 0x80, 00, 0x80, 00, 0x80, 00, rx_telegram({0xB0, 0x49, 0xFF, 0x00, 0x02, 0x62, 0x01, 0x44, 0x03, 0x30, 0x80, 00, 0x80, 00, 0x80, 00,
0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 0x33}); 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 0x33});
rx_telegram({0xB0, 00, 0xFF, 0x18, 02, 0x62, 0x80, 00, 0xB8}); rx_telegram({0xB0, 00, 0xFF, 0x18, 02, 0x62, 0x80, 00, 0xB8});
@@ -1936,7 +1936,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
if (command == "rx2") { if (command == "rx2") {
shell.printfln("Testing Rx2..."); shell.printfln("Testing Rx2...");
for (uint8_t i = 0; i < 30; i++) { for (uint8_t i = 0; i < 30; i++) {
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00}); uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
ok = true; ok = true;
} }
} }
@@ -1953,23 +1953,23 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
uart_telegram({0x08, 0x97, 0x33, 0x00, 0x23, 0x24}); uart_telegram({0x08, 0x97, 0x33, 0x00, 0x23, 0x24});
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13) // Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00}); uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
// Thermostat -> Me, RC20StatusMessage(0x91), telegram: 17 0B 91 05 44 45 46 47 (#data=4) // Thermostat -> Me, RC20StatusMessage(0x91), telegram: 17 0B 91 05 44 45 46 47 (#data=4)
uart_telegram({0x17, 0x0B, 0x91, 0x05, 0x44, 0x45, 0x46, 0x47}); uart_telegram({0x17, 0x49, 0x91, 0x05, 0x44, 0x45, 0x46, 0x47});
// bad CRC - corrupt telegram - CRC should be 0x8E // bad CRC - corrupt telegram - CRC should be 0x8E
uint8_t t5[] = {0x17, 0x0B, 0x91, 0x05, 0x44, 0x45, 0x46, 0x47, 0x99}; uint8_t t5[] = {0x17, 0x49, 0x91, 0x05, 0x44, 0x45, 0x46, 0x47, 0x99};
EMSESP::rxservice_.add(t5, sizeof(t5)); EMSESP::rxservice_.add(t5, sizeof(t5));
// simulating a Tx record // simulating a Tx record
uart_telegram({0x0B, 0x88, 0x07, 0x00, 0x20}); uart_telegram({0x49, 0x88, 0x07, 0x00, 0x20});
// Version Boiler // Version Boiler
uart_telegram({0x08, 0x0B, 0x02, 0x00, 0x7B, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04}); uart_telegram({0x08, 0x49, 0x02, 0x00, 0x7B, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04});
// Version Thermostat, device_id 0x11 // Version Thermostat, device_id 0x11
uart_telegram({0x11, 0x0B, 0x02, 0x00, 0x4D, 0x03, 0x03}); uart_telegram({0x11, 0x49, 0x02, 0x00, 0x4D, 0x03, 0x03});
// Thermostat -> all, telegram: 10 00 FF 00 01 A5 00 D7 21 00 00 00 00 30 01 84 01 01 03 01 84 01 F1 00 00 11 01 00 08 63 00 // Thermostat -> all, telegram: 10 00 FF 00 01 A5 00 D7 21 00 00 00 00 30 01 84 01 01 03 01 84 01 F1 00 00 11 01 00 08 63 00
// 0x1A5 test ems+ // 0x1A5 test ems+
@@ -1987,7 +1987,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
uart_telegram({0x17, 0x08, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00}); uart_telegram({0x17, 0x08, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00});
// Thermostat -> Me, RC20Set(0xA8), telegram: 17 0B A8 00 01 00 FF F6 01 06 00 01 0D 01 00 FF FF 01 02 02 02 00 00 05 1F 05 1F 02 0E 00 FF (#data=27) // Thermostat -> Me, RC20Set(0xA8), telegram: 17 0B A8 00 01 00 FF F6 01 06 00 01 0D 01 00 FF FF 01 02 02 02 00 00 05 1F 05 1F 02 0E 00 FF (#data=27)
uart_telegram({0x17, 0x0B, 0xA8, 0x00, 0x01, 0x00, 0xFF, 0xF6, 0x01, 0x06, 0x00, 0x01, 0x0D, 0x01, 0x00, 0xFF, uart_telegram({0x17, 0x49, 0xA8, 0x00, 0x01, 0x00, 0xFF, 0xF6, 0x01, 0x06, 0x00, 0x01, 0x0D, 0x01, 0x00, 0xFF,
0xFF, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x05, 0x1F, 0x05, 0x1F, 0x02, 0x0E, 0x00, 0xFF}); 0xFF, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x05, 0x1F, 0x05, 0x1F, 0x02, 0x0E, 0x00, 0xFF});
// Boiler(0x08) -> All(0x00), UBAMonitorWW(0x34), data: 36 01 A5 80 00 21 00 00 01 00 01 3E 8D 03 77 91 00 80 00 // Boiler(0x08) -> All(0x00), UBAMonitorWW(0x34), data: 36 01 A5 80 00 21 00 00 01 00 01 3E 8D 03 77 91 00 80 00
@@ -2021,7 +2021,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
EMSESP::send_write_request(0x91, 0x17, 0x00, t18, sizeof(t18), 0x00); EMSESP::send_write_request(0x91, 0x17, 0x00, t18, sizeof(t18), 0x00);
// TX - send EMS+ // TX - send EMS+
const uint8_t t13[] = {0x90, 0x0B, 0xFF, 00, 01, 0xBA, 00, 0x2E, 0x2A, 0x26, 0x1E, 0x03, const uint8_t t13[] = {0x90, 0x49, 0xFF, 00, 01, 0xBA, 00, 0x2E, 0x2A, 0x26, 0x1E, 0x03,
00, 0xFF, 0xFF, 05, 0x2A, 01, 0xE1, 0x20, 0x01, 0x0F, 05, 0x2A}; 00, 0xFF, 0xFF, 05, 0x2A, 01, 0xE1, 0x20, 0x01, 0x0F, 05, 0x2A};
EMSESP::txservice_.add(Telegram::Operation::TX_RAW, t13, sizeof(t13), 0); EMSESP::txservice_.add(Telegram::Operation::TX_RAW, t13, sizeof(t13), 0);
@@ -2145,7 +2145,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
uart_telegram({0x08, 0x98, 0x33, 0x00, 0x23, 0x24}); uart_telegram({0x08, 0x98, 0x33, 0x00, 0x23, 0x24});
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13) // Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00}); uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
// add a thermostat // add a thermostat
add_device(0x18, 157); // Bosch CR100 add_device(0x18, 157); // Bosch CR100
@@ -2487,7 +2487,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
if (command == "rx3") { if (command == "rx3") {
shell.printfln("Testing rx3..."); shell.printfln("Testing rx3...");
uart_telegram({0x21, 0x0B, 0xFF, 0x00}); uart_telegram({0x21, 0x49, 0xFF, 0x00});
ok = true; ok = true;
} }
@@ -2495,7 +2495,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
if (command == "tx2") { if (command == "tx2") {
shell.printfln("Testing tx2..."); shell.printfln("Testing tx2...");
uint8_t t[] = {0x0B, 0x88, 0x18, 0x00, 0x20, 0xD4}; // including CRC uint8_t t[] = {0x49, 0x88, 0x18, 0x00, 0x20, 0xD4}; // including CRC
EMSuart::transmit(t, sizeof(t)); EMSuart::transmit(t, sizeof(t));
ok = true; ok = true;
} }
@@ -2676,45 +2676,6 @@ void Test::add_device(uint8_t device_id, uint8_t product_id) {
uart_telegram({device_id, EMSESP_DEFAULT_EMS_BUS_ID, EMSdevice::EMS_TYPE_VERSION, 0, product_id, 1, 0}); uart_telegram({device_id, EMSESP_DEFAULT_EMS_BUS_ID, EMSdevice::EMS_TYPE_VERSION, 0, product_id, 1, 0});
} }
#ifdef EMSESP_TEST
#ifndef EMSESP_STANDALONE
void Test::listDir(fs::FS & fs, const char * dirname, uint8_t levels) {
Serial.println();
Serial.printf("%s\r\n", dirname);
File root = fs.open(dirname);
if (!root) {
Serial.println("- failed to open directory");
return;
}
if (!root.isDirectory()) {
Serial.println(" - not a directory");
return;
}
File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.print(file.name());
Serial.println("/");
if (levels) {
// prefix a / to the name to make it a full path
listDir(fs, ("/" + String(file.name())).c_str(), levels - 1);
}
Serial.println();
} else {
Serial.print(" ");
Serial.print(file.name());
Serial.print(" (");
Serial.print(file.size());
Serial.println(" bytes)");
}
file = root.openNextFile();
}
}
#endif
#endif
} // namespace emsesp } // namespace emsesp
#endif #endif

View File

@@ -80,7 +80,6 @@ class Test {
static void uart_telegram_withCRC(const char * rx_data); static void uart_telegram_withCRC(const char * rx_data);
static void add_device(uint8_t device_id, uint8_t product_id); static void add_device(uint8_t device_id, uint8_t product_id);
static void refresh(); static void refresh();
static void listDir(fs::FS & fs, const char * dirname, uint8_t levels);
}; };
} // namespace emsesp } // namespace emsesp

View File

@@ -149,8 +149,10 @@ uint8_t EMSuart::transmit(const uint8_t * buf, const uint8_t len) {
return EMS_TX_STATUS_OK; return EMS_TX_STATUS_OK;
} }
auto tx_mode = tx_mode_ != EMS_TXMODE_AUTO ? tx_mode_ : EMSbus::is_ht3() ? EMS_TXMODE_HT3 : EMSbus::is_ems2() ? EMS_TXMODE_EMSPLUS : EMS_TXMODE_EMS;
// TXMODE is EMS+ with long delay // TXMODE is EMS+ with long delay
if (tx_mode_ == EMS_TXMODE_EMSPLUS) { if (tx_mode == EMS_TXMODE_EMSPLUS) {
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {
uart_write_bytes(EMSUART_NUM, &buf[i], 1); uart_write_bytes(EMSUART_NUM, &buf[i], 1);
delayMicroseconds(EMSUART_TX_WAIT_PLUS); delayMicroseconds(EMSUART_TX_WAIT_PLUS);
@@ -160,7 +162,7 @@ uint8_t EMSuart::transmit(const uint8_t * buf, const uint8_t len) {
} }
// TXMODE is HT3 with 7 bittimes delay // TXMODE is HT3 with 7 bittimes delay
if (tx_mode_ == EMS_TXMODE_HT3) { if (tx_mode == EMS_TXMODE_HT3) {
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {
uart_write_bytes(EMSUART_NUM, &buf[i], 1); uart_write_bytes(EMSUART_NUM, &buf[i], 1);
delayMicroseconds(EMSUART_TX_WAIT_HT3); delayMicroseconds(EMSUART_TX_WAIT_HT3);

View File

@@ -42,10 +42,11 @@
#define EMS_TXMODE_INIT 0xFF #define EMS_TXMODE_INIT 0xFF
#define EMS_TXMODE_OFF 0 #define EMS_TXMODE_OFF 0
#define EMS_TXMODE_DEFAULT 1 #define EMS_TXMODE_EMS 1
#define EMS_TXMODE_EMSPLUS 2 #define EMS_TXMODE_EMSPLUS 2
#define EMS_TXMODE_HT3 3 #define EMS_TXMODE_HT3 3
#define EMS_TXMODE_HW 4 #define EMS_TXMODE_HW 4
#define EMS_TXMODE_AUTO 5
// LEGACY // LEGACY
#define EMSUART_TX_BIT_TIME 104 // bit time @9600 baud #define EMSUART_TX_BIT_TIME 104 // bit time @9600 baud

View File

@@ -166,7 +166,9 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web
bool WebCustomEntityService::command_setvalue(const char * value, const int8_t id, const char * name) { bool WebCustomEntityService::command_setvalue(const char * value, const int8_t id, const char * name) {
// don't write if there is no value, to prevent setting an empty value by mistake when parsing attributes // don't write if there is no value, to prevent setting an empty value by mistake when parsing attributes
if (!strlen(value)) { if (!strlen(value)) {
#if defined(EMSESP_DEBUG)
EMSESP::logger().debug("can't set empty value!"); EMSESP::logger().debug("can't set empty value!");
#endif
return false; return false;
} }

View File

@@ -352,8 +352,8 @@ bool WebSchedulerService::command(const char * name, const std::string & command
// parse json // parse json
JsonDocument doc; JsonDocument doc;
if (deserializeJson(doc, cmd) == DeserializationError::Ok) { if (deserializeJson(doc, cmd) == DeserializationError::Ok) {
HTTPClient * http = new HTTPClient; HTTPClient * http = new HTTPClient;
std::string url = doc["url"] | ""; std::string url = doc["url"] | "";
// for a GET with parameters replace commands with values // for a GET with parameters replace commands with values
// don't search the complete url, it may contain a devicename in path // don't search the complete url, it may contain a devicename in path
auto q = url.find_first_of('?'); auto q = url.find_first_of('?');
@@ -465,7 +465,9 @@ void WebSchedulerService::condition() {
} else if (match.length() == 1 && match[0] == '0' && scheduleItem.retry_cnt == 1) { } else if (match.length() == 1 && match[0] == '0' && scheduleItem.retry_cnt == 1) {
scheduleItem.retry_cnt = 0xFF; scheduleItem.retry_cnt = 0xFF;
} else if (match.length() != 1) { // the match is not boolean } else if (match.length() != 1) { // the match is not boolean
#if defined(EMSESP_DEBUG)
EMSESP::logger().debug("condition result: %s", match.c_str()); EMSESP::logger().debug("condition result: %s", match.c_str());
#endif
} }
} }
} }

View File

@@ -20,7 +20,7 @@
namespace emsesp { namespace emsesp {
uint8_t WebSettings::flags_ = 0; uint16_t WebSettings::flags_ = 0;
WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager) WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
: _httpEndpoint(WebSettings::read, WebSettings::update, this, server, EMSESP_SETTINGS_SERVICE_PATH, securityManager) : _httpEndpoint(WebSettings::read, WebSettings::update, this, server, EMSESP_SETTINGS_SERVICE_PATH, securityManager)
@@ -114,11 +114,11 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
reset_flags(); reset_flags();
// before loading new board profile free old gpios from used list to allow remapping // before loading new board profile free old gpios from used list to allow remapping
EMSESP::system_.remove_gpio(original_settings.led_gpio); EMSESP::system_.remove_optional_gpio(original_settings.led_gpio);
EMSESP::system_.remove_gpio(original_settings.dallas_gpio); EMSESP::system_.remove_optional_gpio(original_settings.dallas_gpio);
EMSESP::system_.remove_gpio(original_settings.pbutton_gpio); EMSESP::system_.remove_gpio(original_settings.pbutton_gpio);
EMSESP::system_.remove_gpio(original_settings.rx_gpio); EMSESP::system_.remove_optional_gpio(original_settings.rx_gpio);
EMSESP::system_.remove_gpio(original_settings.tx_gpio); EMSESP::system_.remove_optional_gpio(original_settings.tx_gpio);
// see if the user has changed the board profile // see if the user has changed the board profile
// this will set: led_gpio, dallas_gpio, rx_gpio, tx_gpio, pbutton_gpio, phy_type, eth_power, eth_phy_addr, eth_clock_mode, led_type // this will set: led_gpio, dallas_gpio, rx_gpio, tx_gpio, pbutton_gpio, phy_type, eth_power, eth_phy_addr, eth_clock_mode, led_type
@@ -243,13 +243,13 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
// Modbus settings // Modbus settings
settings.modbus_enabled = root["modbus_enabled"] | EMSESP_DEFAULT_MODBUS_ENABLED; settings.modbus_enabled = root["modbus_enabled"] | EMSESP_DEFAULT_MODBUS_ENABLED;
check_flag(original_settings.modbus_enabled, settings.modbus_enabled, ChangeFlags::RESTART); check_flag(original_settings.modbus_enabled, settings.modbus_enabled, ChangeFlags::MODBUS);
settings.modbus_port = root["modbus_port"] | EMSESP_DEFAULT_MODBUS_PORT; settings.modbus_port = root["modbus_port"] | EMSESP_DEFAULT_MODBUS_PORT;
check_flag(original_settings.modbus_port, settings.modbus_port, ChangeFlags::RESTART); check_flag(original_settings.modbus_port, settings.modbus_port, ChangeFlags::MODBUS);
settings.modbus_max_clients = root["modbus_max_clients"] | EMSESP_DEFAULT_MODBUS_MAX_CLIENTS; settings.modbus_max_clients = root["modbus_max_clients"] | EMSESP_DEFAULT_MODBUS_MAX_CLIENTS;
check_flag(original_settings.modbus_max_clients, settings.modbus_max_clients, ChangeFlags::RESTART); check_flag(original_settings.modbus_max_clients, settings.modbus_max_clients, ChangeFlags::MODBUS);
settings.modbus_timeout = root["modbus_timeout"] | EMSESP_DEFAULT_MODBUS_TIMEOUT; settings.modbus_timeout = root["modbus_timeout"] | EMSESP_DEFAULT_MODBUS_TIMEOUT;
check_flag(original_settings.modbus_timeout, settings.modbus_timeout, ChangeFlags::RESTART); check_flag(original_settings.modbus_timeout, settings.modbus_timeout, ChangeFlags::MODBUS);
// //
// these may need mqtt restart to rebuild HA discovery topics // these may need mqtt restart to rebuild HA discovery topics
@@ -372,7 +372,11 @@ void WebSettingsService::onUpdate() {
Mqtt::reset_mqtt(); // reload MQTT, init HA etc Mqtt::reset_mqtt(); // reload MQTT, init HA etc
} }
if (WebSettings::has_flags(WebSettings::ChangeFlags::MODBUS)) {
EMSESP::system_.modbus_init();
}
WebSettings::reset_flags(); WebSettings::reset_flags();
EMSESP::system_.reset_unused_gpios();
} }
void WebSettingsService::begin() { void WebSettingsService::begin() {
@@ -523,7 +527,7 @@ void WebSettings::set_board_profile(WebSettings & settings) {
} }
// returns true if the value was changed // returns true if the value was changed
bool WebSettings::check_flag(int prev_v, int new_v, uint8_t flag) { bool WebSettings::check_flag(int prev_v, int new_v, uint16_t flag) {
if (prev_v != new_v) { if (prev_v != new_v) {
add_flags(flag); add_flags(flag);
#if defined(EMSESP_DEBUG) #if defined(EMSESP_DEBUG)
@@ -534,11 +538,11 @@ bool WebSettings::check_flag(int prev_v, int new_v, uint8_t flag) {
return false; return false;
} }
void WebSettings::add_flags(uint8_t flags) { void WebSettings::add_flags(uint16_t flags) {
flags_ |= flags; flags_ |= flags;
} }
bool WebSettings::has_flags(uint8_t flags) { bool WebSettings::has_flags(uint16_t flags) {
return (flags_ & flags) == flags; return (flags_ & flags) == flags;
} }
@@ -546,7 +550,7 @@ void WebSettings::reset_flags() {
flags_ = ChangeFlags::NONE; flags_ = ChangeFlags::NONE;
} }
uint8_t WebSettings::get_flags() { uint16_t WebSettings::get_flags() {
return flags_; return flags_;
} }

View File

@@ -88,7 +88,7 @@ class WebSettings {
static void read(WebSettings & settings, JsonObject root); static void read(WebSettings & settings, JsonObject root);
static StateUpdateResult update(JsonObject root, WebSettings & settings); static StateUpdateResult update(JsonObject root, WebSettings & settings);
enum ChangeFlags : uint8_t { enum ChangeFlags : uint16_t {
NONE = 0, NONE = 0,
UART = (1 << 0), // 1 - uart UART = (1 << 0), // 1 - uart
SYSLOG = (1 << 1), // 2 - syslog SYSLOG = (1 << 1), // 2 - syslog
@@ -98,19 +98,20 @@ class WebSettings {
LED = (1 << 5), // 32 - led LED = (1 << 5), // 32 - led
BUTTON = (1 << 6), // 64 - button BUTTON = (1 << 6), // 64 - button
MQTT = (1 << 7), // 128 - mqtt MQTT = (1 << 7), // 128 - mqtt
RESTART = 0xFF // 255 - restart request (all changes) MODBUS = (1 << 8), // 256 - modbus
RESTART = 0xFFFF // restart request (all changes)
}; };
static bool check_flag(int prev_v, int new_v, uint8_t flag); static bool check_flag(int prev_v, int new_v, uint16_t flag);
static void add_flags(uint8_t flags); static void add_flags(uint16_t flags);
static bool has_flags(uint8_t flags); static bool has_flags(uint16_t flags);
static void reset_flags(); static void reset_flags();
static uint8_t get_flags(); static uint16_t get_flags();
private: private:
static void set_board_profile(WebSettings & settings); static void set_board_profile(WebSettings & settings);
static uint8_t flags_; static uint16_t flags_;
}; };
class WebSettingsService : public StatefulService<WebSettings> { class WebSettingsService : public StatefulService<WebSettings> {

View File

@@ -132,7 +132,7 @@ void uart_telegram(const char * rx_data) {
// add an EMS device and register it // add an EMS device and register it
void add_device(uint8_t device_id, uint8_t product_id) { void add_device(uint8_t device_id, uint8_t product_id) {
uart_telegram({device_id, 0x0B, EMSdevice::EMS_TYPE_VERSION, 0, product_id, 1, 0}); uart_telegram({device_id, 0x49, EMSdevice::EMS_TYPE_VERSION, 0, product_id, 1, 0});
} }
// add our EMS test devices // add our EMS test devices
@@ -143,14 +143,14 @@ void add_devices() {
add_device(0x08, 123); // Nefit Trendline add_device(0x08, 123); // Nefit Trendline
// UBAuptime // UBAuptime
uart_telegram({0x08, 0x0B, 0x14, 00, 0x3C, 0x1F, 0xAC, 0x70}); uart_telegram({0x08, 0x49, 0x14, 00, 0x3C, 0x1F, 0xAC, 0x70});
// Boiler -> Me, UBAMonitorFast(0x18), telegram: 08 00 18 00 00 02 5A 73 3D 0A 10 65 40 02 1A 80 00 01 E1 01 76 0E 3D 48 00 C9 44 02 00 (#data=25) // Boiler -> Me, UBAMonitorFast(0x18), telegram: 08 00 18 00 00 02 5A 73 3D 0A 10 65 40 02 1A 80 00 01 E1 01 76 0E 3D 48 00 C9 44 02 00 (#data=25)
uart_telegram({0x08, 0x00, 0x18, 0x00, 0x00, 0x02, 0x5A, 0x73, 0x3D, 0x0A, 0x10, 0x65, 0x40, 0x02, 0x1A, uart_telegram({0x08, 0x00, 0x18, 0x00, 0x00, 0x02, 0x5A, 0x73, 0x3D, 0x0A, 0x10, 0x65, 0x40, 0x02, 0x1A,
0x80, 0x00, 0x01, 0xE1, 0x01, 0x76, 0x0E, 0x3D, 0x48, 0x00, 0xC9, 0x44, 0x02, 0x00}); 0x80, 0x00, 0x01, 0xE1, 0x01, 0x76, 0x0E, 0x3D, 0x48, 0x00, 0xC9, 0x44, 0x02, 0x00});
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13) // Boiler -> Me, UBAParameterWW(0x33), telegram: 08 49 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00}); uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
// //
// thermostat // thermostat

View File

@@ -228,7 +228,7 @@ void test_23() {
"\"temperatureSensorReads\":0,\"temperatureSensorFails\":0},\"analog\":{\"enabled\":true,\"analogSensors\":5,\"analogSensorReads\":0," "\"temperatureSensorReads\":0,\"temperatureSensorFails\":0},\"analog\":{\"enabled\":true,\"analogSensors\":5,\"analogSensorReads\":0,"
"\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{\"busStatus\":\"connected\",\"busProtocol\":\"Buderus\"," "\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{\"busStatus\":\"connected\",\"busProtocol\":\"Buderus\","
"\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,\"busReadsFailed\":0,\"busWritesFailed\":0," "\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,\"busReadsFailed\":0,\"busWritesFailed\":0,"
"\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":\"en\",\"txMode\":1,\"emsBusID\":11," "\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":\"en\",\"txMode\":5,\"emsBusID\":73,"
"\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,\"readonlyMode\":false,\"fahrenheit\":" "\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,\"readonlyMode\":false,\"fahrenheit\":"
"false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,\"telnetEnabled\":true," "false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,\"telnetEnabled\":true,"
"\"maxWebLogBuffer\":25,\"modbusEnabled\":false,\"forceHeatingOff\":false,\"developerMode\":false},\"devices\":[{\"type\":\"boiler\",\"name\":\"My " "\"maxWebLogBuffer\":25,\"modbusEnabled\":false,\"forceHeatingOff\":false,\"developerMode\":false},\"devices\":[{\"type\":\"boiler\",\"name\":\"My "
@@ -259,7 +259,7 @@ void test_24() {
"\"temperatureSensorReads\":0,\"temperatureSensorFails\":0},\"analog\":{\"enabled\":true,\"analogSensors\":5,\"analogSensorReads\":0," "\"temperatureSensorReads\":0,\"temperatureSensorFails\":0},\"analog\":{\"enabled\":true,\"analogSensors\":5,\"analogSensorReads\":0,"
"\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{\"busStatus\":\"connected\",\"busProtocol\":\"Buderus\"," "\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{\"busStatus\":\"connected\",\"busProtocol\":\"Buderus\","
"\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,\"busReadsFailed\":0,\"busWritesFailed\":0," "\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,\"busReadsFailed\":0,\"busWritesFailed\":0,"
"\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":\"en\",\"txMode\":1,\"emsBusID\":11," "\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":\"en\",\"txMode\":5,\"emsBusID\":73,"
"\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,\"readonlyMode\":false,\"fahrenheit\":" "\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,\"readonlyMode\":false,\"fahrenheit\":"
"false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,\"telnetEnabled\":true," "false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,\"telnetEnabled\":true,"
"\"maxWebLogBuffer\":25,\"modbusEnabled\":false,\"forceHeatingOff\":false,\"developerMode\":false},\"devices\":[{\"type\":\"boiler\",\"name\":\"My " "\"maxWebLogBuffer\":25,\"modbusEnabled\":false,\"forceHeatingOff\":false,\"developerMode\":false},\"devices\":[{\"type\":\"boiler\",\"name\":\"My "
@@ -330,8 +330,8 @@ void test_25() {
"gauge\\nemsesp_bus_buswritesfailed 0\\n# HELP emsesp_bus_busrxlinequality busRxLineQuality\\n# TYPE emsesp_bus_busrxlinequality " "gauge\\nemsesp_bus_buswritesfailed 0\\n# HELP emsesp_bus_busrxlinequality busRxLineQuality\\n# TYPE emsesp_bus_busrxlinequality "
"gauge\\nemsesp_bus_busrxlinequality 100\\n# HELP emsesp_bus_bustxlinequality busTxLineQuality\\n# TYPE emsesp_bus_bustxlinequality " "gauge\\nemsesp_bus_busrxlinequality 100\\n# HELP emsesp_bus_bustxlinequality busTxLineQuality\\n# TYPE emsesp_bus_bustxlinequality "
"gauge\\nemsesp_bus_bustxlinequality 100\\n# HELP emsesp_bus_info info\\n# TYPE emsesp_bus_info gauge\\nemsesp_bus_info{busstatus=\\\"connected\\\", " "gauge\\nemsesp_bus_bustxlinequality 100\\n# HELP emsesp_bus_info info\\n# TYPE emsesp_bus_info gauge\\nemsesp_bus_info{busstatus=\\\"connected\\\", "
"busprotocol=\\\"Buderus\\\"} 1\\n# HELP emsesp_settings_txmode txMode\\n# TYPE emsesp_settings_txmode gauge\\nemsesp_settings_txmode 1\\n# HELP " "busprotocol=\\\"Buderus\\\"} 1\\n# HELP emsesp_settings_txmode txMode\\n# TYPE emsesp_settings_txmode gauge\\nemsesp_settings_txmode 5\\n# HELP "
"emsesp_settings_emsbusid emsBusID\\n# TYPE emsesp_settings_emsbusid gauge\\nemsesp_settings_emsbusid 11\\n# HELP emsesp_settings_showertimer " "emsesp_settings_emsbusid emsBusID\\n# TYPE emsesp_settings_emsbusid gauge\\nemsesp_settings_emsbusid 73\\n# HELP emsesp_settings_showertimer "
"showerTimer\\n# TYPE emsesp_settings_showertimer gauge\\nemsesp_settings_showertimer 0\\n# HELP emsesp_settings_showerminduration " "showerTimer\\n# TYPE emsesp_settings_showertimer gauge\\nemsesp_settings_showertimer 0\\n# HELP emsesp_settings_showerminduration "
"showerMinDuration\\n# TYPE emsesp_settings_showerminduration gauge\\nemsesp_settings_showerminduration 180\\n# HELP emsesp_settings_showeralert " "showerMinDuration\\n# TYPE emsesp_settings_showerminduration gauge\\nemsesp_settings_showerminduration 180\\n# HELP emsesp_settings_showeralert "
"showerAlert\\n# TYPE emsesp_settings_showeralert gauge\\nemsesp_settings_showeralert 0\\n# HELP emsesp_settings_hideled hideLed\\n# TYPE " "showerAlert\\n# TYPE emsesp_settings_showeralert gauge\\nemsesp_settings_showeralert 0\\n# HELP emsesp_settings_hideled hideLed\\n# TYPE "