Compare commits

...
190 Commits
Author SHA1 Message Date
proddy c8a96352ec 3.8.4 2026-08-04 08:13:45 +02:00
proddy 02caaef916 fix firmware size check 2026-08-03 09:59:46 +02:00
proddy ba0f4cd008 3.8.3 2026-08-02 09:56:04 +02:00
proddy 45f7d91b43 Merge remote-tracking branch 'origin/dev' 2026-08-02 09:55:48 +02:00
Proddy e0f59a4c31 Merge pull request #3176 from proddy/dev
pkg update and getting ready for stable
2026-08-01 17:05:18 +02:00
proddy 7eba8acbb4 3.8.3-dev.11 2026-08-01 17:04:13 +02:00
proddy d0e6a603bb auto-formatting 2026-08-01 16:57:41 +02:00
proddy 36b4dd55a7 pkg update 2026-08-01 16:44:16 +02:00
proddy 341a4d4e1d update version 2026-08-01 16:44:11 +02:00
proddy a61745b710 formatting 2026-08-01 16:44:03 +02:00
proddy b1ebd81ca2 update 2026-08-01 16:43:55 +02:00
Proddy 1ff53e6ac7 Merge pull request #3171 from MichaelDvP/dev
fix water SM100
2026-07-28 19:02:52 +02:00
MichaelDvP 9cab3b480e chore: update generated files for v3.8.3-dev.10 2026-07-22 15:37:09 +00:00
MichaelDvP edfbbe68b0 language code "cs" 2026-07-22 17:28:16 +02:00
MichaelDvP 96e8a0d916 fix water module #3164 2026-07-22 17:27:08 +02:00
MichaelDvP 8c90d10601 dump 2026-07-20 15:35:48 +02:00
Proddy bacd3faac2 Merge pull request #3159 from MichaelDvP/dev
dev9
2026-07-15 08:44:31 +02:00
MichaelDvP 2b187fb848 dev8f->dev9 2026-07-14 21:56:41 +02:00
MichaelDvP 4a12066e37 update pkg 2026-07-13 15:08:19 +02:00
MichaelDvP b82f8c979f process message from scheduler 2026-07-13 12:32:21 +02:00
MichaelDvP 342878f628 fix standalone 2026-07-12 17:25:51 +02:00
MichaelDvP 4e47be7fa6 Merge remote-tracking branch 'mdvp/dev' into dev 2026-07-12 17:17:42 +02:00
MichaelDvP 2b25ae18d1 set 10 sectimeout for http requests 2026-07-12 17:17:07 +02:00
MichaelDvP 98c9e011bc chore: update generated files for v3.8.3-dev.8d 2026-07-12 09:16:46 +00:00
MichaelDvP cb1cb356ce prevent errorlogs for nonexisting nvs values, version numbering to dev.8d 2026-07-12 11:05:28 +02:00
MichaelDvP 20fc5ede78 changelog 2026-07-12 10:31:51 +02:00
MichaelDvP a20d1d8970 fix typo 2026-07-12 10:17:02 +02:00
MichaelDvP a647e16f68 update asyncwebserver, dev.11 2026-07-12 09:57:05 +02:00
MichaelDvP 49ab5e3d72 delay scheduler loop after startup 2026-07-12 09:46:43 +02:00
MichaelDvP 9c905c8bab donot fetch system_info for reset command 2026-07-12 09:46:18 +02:00
MichaelDvP 7ab343a216 fix crashes from #3146 2026-07-12 08:17:40 +02:00
MichaelDvP 188cc7b666 check for "http" before allocating a http-client 2026-07-11 19:12:34 +02:00
MichaelDvP 193e5d591c block too many api GET requests 2026-07-11 14:48:19 +02:00
MichaelDvP ff3f4d3a6d update pkg 2026-07-11 14:47:39 +02:00
MichaelDvP 5129b475c5 NTP sync enabled by default 2026-07-11 14:47:19 +02:00
MichaelDvP f31dbd44a5 rollback regex 2026-07-10 12:13:31 +02:00
MichaelDvP 5c55c2216e rollback regex
crashes
2026-07-10 10:41:43 +02:00
MichaelDvP 5a1d06d39e fix possible memory leaks 2026-07-10 09:33:15 +02:00
MichaelDvP 9443cf3c87 Merge remote-tracking branch 'mdvp/dev' into dev 2026-07-10 08:35:03 +02:00
MichaelDvP fa31dcdf24 use F7 only for auto mode 2026-07-10 08:33:19 +02:00
MichaelDvP 2c80cc597e SRC modes from set-telegram 2026-07-10 08:17:53 +02:00
MichaelDvP d7641fbb2f use regex for isnum 2026-07-10 08:16:58 +02:00
MichaelDvP 5742c03eee chore: update generated files for v3.8.3-dev.10 2026-07-09 18:14:31 +00:00
MichaelDvP b2858ab3e7 Merge remote-tracking branch 'mdvp/dev' into dev 2026-07-09 19:59:37 +02:00
MichaelDvP 2255ad0b17 update modbus 2026-07-09 19:46:45 +02:00
MichaelDvP ed8adf2617 SRC modes from MenuConfig F7 2026-07-09 19:42:32 +02:00
MichaelDvP 5c2205cf65 calc_dew to helpers 2026-07-09 19:41:54 +02:00
MichaelDvP f6cb695635 direct call compute 2026-07-09 19:41:13 +02:00
MichaelDvP 1450e79b64 chore: update generated files for v3.8.3-dev.10 2026-07-06 15:24:45 +00:00
MichaelDvP fae0f9fb49 changelog 2026-07-06 17:12:41 +02:00
MichaelDvP 8638424d5b fix water circulation for dhw circuits 1/2 2026-07-06 17:00:12 +02:00
MichaelDvP 1d016ec356 formatting, manual set time 2026-07-06 16:55:23 +02:00
MichaelDvP f16b10f544 fix different timezones 2026-07-06 16:11:14 +02:00
MichaelDvP dd0c8a5ca8 SRC cooling mode, guess 2026-07-06 10:24:27 +02:00
MichaelDvP 7175191c66 Merge remote-tracking branch 'emsesp/dev' into dev 2026-07-06 08:25:11 +02:00
MichaelDvP f7a81c50b0 fix standalone, formatting 2026-07-06 08:24:43 +02:00
Proddy cfbcaa6fce Merge pull request #3149 from Cali1205/dev
update water.cpp: modify set_wwCircTc to use new command values
2026-07-05 22:02:16 +02:00
MichaelDvP abd1c36ec9 option to sync thermostat clock 2026-07-05 21:20:54 +02:00
Rainer ebd6d15c48 update water.cpp: modify set_wwCircTc to use new command values 2026-07-05 17:34:20 +02:00
MichaelDvP f4979d905d hpminflowtemp telegramoffset depends on control 2026-06-29 21:17:51 +02:00
MichaelDvP 496884c78a dev.9, changelog 2026-06-29 10:02:58 +02:00
MichaelDvP 696c82364e fix offset of hpminflowtemp #3144 2026-06-29 10:01:34 +02:00
Proddy c55655c0c5 Merge pull request #3143 from proddy/dev
fix thermostat date/time for HT3
2026-06-28 16:35:39 +02:00
proddy 55a0e4b2b5 Revert "Reduce DeviceValue heap usage with on-demand custom name"
This reverts commit 5aadf7234f.
2026-06-28 16:30:24 +02:00
proddy eceb097cc7 fix thermostat date/time for HT3 2026-06-28 16:08:31 +02:00
Proddy 0e18645ba5 Merge branch 'emsesp:dev' into dev 2026-06-27 14:32:48 +02:00
Proddy 63f49a347b Merge pull request #3136 from MichaelDvP/dev
fixes for #3127 and #3135
2026-06-27 14:32:04 +02:00
MichaelDvP 943048a920 dev.7 2026-06-27 13:14:57 +02:00
MichaelDvP 2b8a0bd8b7 Merge remote-tracking branch 'emsesp/dev' into dev 2026-06-27 13:06:19 +02:00
MichaelDvP d83b56a13c calcutae dewtemp for Easycontrol, #3135 2026-06-27 13:03:10 +02:00
Proddy 1f34a41d27 Merge branch 'emsesp:dev' into dev 2026-06-25 21:14:59 +02:00
Proddy 343ac5880c Merge pull request #3134 from s-schnitzer/fix-negative-dew-point-calculation
fix: negative dew point calculation (emulated RC100H)
2026-06-25 21:05:17 +02:00
s-schnitzer 855edace20 fix: negative dew point calc. (emulated RC100H) 2026-06-25 18:10:52 +02:00
Proddy aabc4f021c Merge pull request #3128 from soderdaen/fix-wifi-scan
Fix: AP crash and infinite loop during WiFi scan.
2026-06-23 21:01:21 +02:00
MichaelDvP 0aaa566e73 Merge remote-tracking branch 'emsesp/dev' into dev 2026-06-23 08:02:32 +02:00
MichaelDvP 20e3d6a19b dev.7, fix crash 2026-06-23 07:57:55 +02:00
MichaelDvP 67953fccd6 from PR #3128 2026-06-22 11:59:06 +02:00
MichaelDvP 0c910bc822 fix mock-api 2026-06-22 11:58:05 +02:00
soderdaen b6a7fb0bf0 Update changelog_latest.md and emsesp_version 2026-06-21 21:15:47 +02:00
MichaelDvP 95f475ab6f command message calsl compute direct,#3127 2026-06-21 10:53:10 +02:00
soderdaen f8fa092ac3 Fix: AP crash and infinite loop during WiFi scan. 2026-06-20 10:42:38 +02:00
proddyandCursor 5aadf7234f Reduce DeviceValue heap usage with on-demand custom name
Store the per-entity custom_fullname as a heap-allocated string that is
only created when a custom name is actually set, instead of an inline
std::string on every DeviceValue. Saves ~20 bytes per entity (hundreds to
~1000 entities), reclaiming internal heap on no-PSRAM boards.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 19:53:14 +02:00
Proddy b8a63aeac6 Merge pull request #3125 from proddy/dev
remove old S3 binaries #3123
2026-06-15 18:24:46 +02:00
proddy 908a9ebbfc remove old S3 binaries #3123 2026-06-15 18:23:58 +02:00
Proddy dbf970d869 Merge branch 'emsesp:dev' into dev 2026-06-07 12:52:09 +02:00
Proddy 9cb2455af2 Merge pull request #3111 from MichaelDvP/dev
reset system status
2026-06-07 12:51:51 +02:00
MichaelDvP f99ca7f013 seltemp write in cooling mode #1781 2026-06-04 12:21:16 +02:00
MichaelDvP 7349bc9ebf reset system status 2026-06-04 12:20:12 +02:00
MichaelDvP ccd3a7b223 Merge remote branch “emsesp/dev” 2026-06-04 11:52:53 +02:00
Proddy 33602f65f3 Merge branch 'emsesp:dev' into dev 2026-05-28 20:55:54 +01:00
Proddy 0493f93976 Merge pull request #3101 from MichaelDvP/dev
extra handling for 0x470. #3096, fix scheduler onChange name check
2026-05-28 20:55:14 +01:00
MichaelDvP 238c9b7860 fix scheduler onChange 2026-05-28 13:14:14 +02:00
MichaelDvP 0823b7882b Merge remote branch “mdvp/dev” 2026-05-28 13:12:14 +02:00
MichaelDvP cf2f816527 chore: update generated files for v3.8.3-dev.5 2026-05-27 09:19:59 +00:00
MichaelDvP 559336a2a7 Merge remote branch “mdvp/dev” 2026-05-27 11:08:35 +02:00
MichaelDvP 0e6cb363ad 0x470 telegram is not hc dependend 2026-05-27 10:52:18 +02:00
MichaelDvP 66b1b1cb24 revert settings for txmode off and 0x0d without ack 2026-05-27 10:49:29 +02:00
MichaelDvP 1d608b7705 chore: update generated files for v3.8.3-dev.4a 2026-05-25 15:11:10 +00:00
MichaelDvP 6dc8072106 FLAG UI800, no poll-ack on id 0x0D 2026-05-25 16:59:41 +02:00
MichaelDvP 88f75038e0 allow txmode 0, show expected crc 2026-05-25 11:12:07 +02:00
MichaelDvP f5bc3e82bb formatting 2026-05-25 11:11:30 +02:00
MichaelDvP c206f069c6 heating/cooling delays, #3096 2026-05-25 11:11:05 +02:00
MichaelDvP 6697aebc3b Merge remote-tracking branch 'emsesp/dev' into dev 2026-05-25 09:02:41 +02:00
MichaelDvP 3d335dad27 remove trailing comma 2026-05-25 09:00:58 +02:00
Proddy 1ae547a710 Merge branch 'emsesp:dev' into dev 2026-05-19 22:33:59 +02:00
Proddy 20d6966633 Merge pull request #3087 from MichaelDvP/dev
fixes for #3084 and #3086
2026-05-19 22:33:44 +02:00
MichaelDvP d5c96f6d48 changelog 2026-05-19 22:13:30 +02:00
MichaelDvP d1192e707d set upload file limit to 1M again 2026-05-19 22:13:14 +02:00
Proddy 70cfbd96e2 Merge branch 'emsesp:dev' into dev 2026-05-19 12:09:53 +02:00
MichaelDvP 0dacd2c71f don't allocate ariable size on stack 2026-05-18 20:55:57 +02:00
MichaelDvP 3962adc911 Merge remote branch “emsesp/dev” 2026-05-18 08:58:14 +02:00
MichaelDvP 0892738cd9 add KM300 #3084 2026-05-18 07:55:07 +02:00
proddy b441fd83dd chore: update generated files for v3.8.3-dev.1 2026-05-14 10:25:29 +00:00
proddy 690cb9df96 chore: update generated files for v3.8.3-dev.1 2026-05-14 10:25:26 +00:00
Proddy 377407f3d1 Merge pull request #3079 from MichaelDvP/dev
fixes for #3077
2026-05-14 12:13:44 +02:00
MichaelDvP 6e0530c84c max limit is uint32 2026-05-14 10:46:32 +02:00
MichaelDvP 59eba07a33 dev.1, changelog, translation 2026-05-13 16:26:07 +02:00
MichaelDvP 5f6d156f63 chore: update generated files for v3.8.3-dev.0 2026-05-13 09:32:00 +00:00
MichaelDvP 07a9bd5f33 fix solar influence, #3077 2026-05-13 11:19:02 +02:00
MichaelDvP 5a8771a8bd Merge remote branch “emsesp/dev” 2026-05-13 08:52:17 +02:00
proddy ee3a5d231a Merge remote-tracking branch 'origin/dev' 2026-05-12 20:15:32 +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
56 changed files with 1780 additions and 1908 deletions
+37 -1
View File
@@ -5,6 +5,43 @@ 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/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.8.4] 4 August 2026
## Fixed
- Allow auto-download and install of firmware versions which are smaller to allow update to the latest 3.9.0-development version.
## [3.8.3] 1 August 2026
## Added
- KM300 at address 0x4A [#3084](https://github.com/emsesp/EMS-ESP32/issues/3084)
## Fixed
- signed value for solarInfuence [#3077](https://github.com/emsesp/EMS-ESP32/issues/3077)
- set bin file upload limit to 1M again [#3086](https://github.com/emsesp/EMS-ESP32/issues/3086)
- check arithmetric operations on strings [#3127](https://github.com/emsesp/EMS-ESP32/discussions/3127)
- prevent system crash during WiFi network discovery on ESP32-S3 hardware [#3128](https://github.com/emsesp/EMS-ESP32/pull/3128)
- fix setting date/time on Junkers thermostats
- offset of hpminflowtemp [#3144](https://github.com/emsesp/EMS-ESP32/issues/3144)
- water circulation command [#3149](https://github.com/emsesp/EMS-ESP32/pull/3149)
- start scheduler after customEntities, delay scheduler loop after startup, handling of `system/restart` command [#3146](https://github.com/emsesp/EMS-ESP32/issues/3146)
- possible memory leaks fixed.
- repeated startup schedules compute value
- call `system/message` called from scheduler processes compute twice
- water module SM100/200 as dhw1/dhw2 [#3164](https://github.com/emsesp/EMS-ESP32/issues/3164)
## Changed
- call compute value direct, enlarge TCP stack [#3127](https://github.com/emsesp/EMS-ESP32/discussions/3127)
- Dewtemperature for Easycontrol calculated by ems-esp [#3135](https://github.com/emsesp/EMS-ESP32/issues/3135)
- add option for sync thermostat to ntp, allow different time zones [#3148](https://github.com/emsesp/EMS-ESP32/discussions/3148), **defaults to sync**.
- block too many GET requests [mentioned in #3104](https://github.com/emsesp/EMS-ESP32/issues/3104)
- set 10 sec timeout for http requests [#3104](https://github.com/emsesp/EMS-ESP32/issues/3104)
- language code "cs" [#3161](https://github.com/emsesp/EMS-ESP32/issues/3161)
## [3.8.2] 12 May 2026
## Added
@@ -71,7 +108,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
- mqtt sends round values without decimals (`28` instead of `28.0`)
## [3.8.0] 31 December 2025
## Added
-8
View File
@@ -1,11 +1,3 @@
# Changelog
For more details go to [emsesp.org](https://emsesp.org/).
## [3.8.3]
## Added
## Fixed
## Changed
+67 -94
View File
@@ -5363,22 +5363,22 @@ uint8
uint8
| hc1.heatoffdelay | heat-off delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 48 | 1 | 1 |
uint8
| hc1.instantstart | instant start | uint8 (&gt;=1&lt;=10) | K | true | HC | 49 | 1 | 1 |
| hc1.boost | boost mode | boolean | | true | HC | 50 | 1 | 1 |
| hc1.coolondelay | cooling on delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 49 | 1 | 1 |
uint8
| hc1.boosttime | boost time | uint8 (&gt;=0&lt;=0) | hours | true | HC | 51 | 1 | 1 |
| hc1.cooloffdelay | cooling off delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 50 | 1 | 1 |
uint8
| hc1.instantstart | instant start | uint8 (&gt;=1&lt;=10) | K | true | HC | 51 | 1 | 1 |
uint8
| hc1.coolstart | cooling starttemp | uint8 (&gt;=20&lt;=35) | C | true | HC | 52 | 1 | 1 |
| hc1.boost | boost mode | boolean | | true | HC | 53 | 1 | 1 |
uint8
| hc1.coolondelay | cooling on delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 53 | 1 | 1 |
uint8
| hc1.cooloffdelay | cooling off delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 54 | 1 | 1 |
| hc1.boosttime | boost time | uint8 (&gt;=0&lt;=0) | hours | true | HC | 54 | 1 | 1 |
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
int8
| hc1.redthreshold | reduction threshold | int8 (&gt;=12&lt;=22) | C | true | HC | 56 | 1 | 1/2 |
uint8
| hc1.solarinfl | solar influence | uint8 (&gt;=-5&lt;=4294967295) | C | true | HC | 57 | 1 | 1 |
| hc1.currsolarinfl | current solar influence | uint8 | C | false | HC | 58 | 1 | 1/10 |
int8
| hc1.solarinfl | solar influence | int8 (&gt;=-5&lt;=0) | C | true | HC | 57 | 1 | 1 |
| hc1.currsolarinfl | current solar influence | int8 | C | false | HC | 58 | 1 | 1/10 |
| hc1.heatingpid | heating PID | enum | | true | HC | 59 | 1 | 1 |
| hc1.pumpopt | pump optimization | boolean | | true | HC | 60 | 1 | 1 |
uint8
@@ -5972,22 +5972,22 @@ uint8
uint8
| hc1.heatoffdelay | heat-off delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 48 | 1 | 1 |
uint8
| hc1.instantstart | instant start | uint8 (&gt;=1&lt;=10) | K | true | HC | 49 | 1 | 1 |
| hc1.boost | boost mode | boolean | | true | HC | 50 | 1 | 1 |
| hc1.coolondelay | cooling on delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 49 | 1 | 1 |
uint8
| hc1.boosttime | boost time | uint8 (&gt;=0&lt;=0) | hours | true | HC | 51 | 1 | 1 |
| hc1.cooloffdelay | cooling off delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 50 | 1 | 1 |
uint8
| hc1.instantstart | instant start | uint8 (&gt;=1&lt;=10) | K | true | HC | 51 | 1 | 1 |
uint8
| hc1.coolstart | cooling starttemp | uint8 (&gt;=20&lt;=35) | C | true | HC | 52 | 1 | 1 |
| hc1.boost | boost mode | boolean | | true | HC | 53 | 1 | 1 |
uint8
| hc1.coolondelay | cooling on delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 53 | 1 | 1 |
uint8
| hc1.cooloffdelay | cooling off delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 54 | 1 | 1 |
| hc1.boosttime | boost time | uint8 (&gt;=0&lt;=0) | hours | true | HC | 54 | 1 | 1 |
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
int8
| hc1.redthreshold | reduction threshold | int8 (&gt;=12&lt;=22) | C | true | HC | 56 | 1 | 1/2 |
uint8
| hc1.solarinfl | solar influence | uint8 (&gt;=-5&lt;=4294967295) | C | true | HC | 57 | 1 | 1 |
| hc1.currsolarinfl | current solar influence | uint8 | C | false | HC | 58 | 1 | 1/10 |
int8
| hc1.solarinfl | solar influence | int8 (&gt;=-5&lt;=0) | C | true | HC | 57 | 1 | 1 |
| hc1.currsolarinfl | current solar influence | int8 | C | false | HC | 58 | 1 | 1/10 |
| hc1.heatingpid | heating PID | enum | | true | HC | 59 | 1 | 1 |
| hc1.pumpopt | pump optimization | boolean | | true | HC | 60 | 1 | 1 |
uint8
@@ -6124,22 +6124,22 @@ uint8
uint8
| hc1.heatoffdelay | heat-off delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 48 | 1 | 1 |
uint8
| hc1.instantstart | instant start | uint8 (&gt;=1&lt;=10) | K | true | HC | 49 | 1 | 1 |
| hc1.boost | boost mode | boolean | | true | HC | 50 | 1 | 1 |
| hc1.coolondelay | cooling on delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 49 | 1 | 1 |
uint8
| hc1.boosttime | boost time | uint8 (&gt;=0&lt;=0) | hours | true | HC | 51 | 1 | 1 |
| hc1.cooloffdelay | cooling off delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 50 | 1 | 1 |
uint8
| hc1.instantstart | instant start | uint8 (&gt;=1&lt;=10) | K | true | HC | 51 | 1 | 1 |
uint8
| hc1.coolstart | cooling starttemp | uint8 (&gt;=20&lt;=35) | C | true | HC | 52 | 1 | 1 |
| hc1.boost | boost mode | boolean | | true | HC | 53 | 1 | 1 |
uint8
| hc1.coolondelay | cooling on delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 53 | 1 | 1 |
uint8
| hc1.cooloffdelay | cooling off delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 54 | 1 | 1 |
| hc1.boosttime | boost time | uint8 (&gt;=0&lt;=0) | hours | true | HC | 54 | 1 | 1 |
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
int8
| hc1.redthreshold | reduction threshold | int8 (&gt;=12&lt;=22) | C | true | HC | 56 | 1 | 1/2 |
uint8
| hc1.solarinfl | solar influence | uint8 (&gt;=-5&lt;=4294967295) | C | true | HC | 57 | 1 | 1 |
| hc1.currsolarinfl | current solar influence | uint8 | C | false | HC | 58 | 1 | 1/10 |
int8
| hc1.solarinfl | solar influence | int8 (&gt;=-5&lt;=0) | C | true | HC | 57 | 1 | 1 |
| hc1.currsolarinfl | current solar influence | int8 | C | false | HC | 58 | 1 | 1/10 |
| hc1.heatingpid | heating PID | enum | | true | HC | 59 | 1 | 1 |
| hc1.pumpopt | pump optimization | boolean | | true | HC | 60 | 1 | 1 |
uint8
@@ -6291,22 +6291,22 @@ uint8
uint8
| hc1.heatoffdelay | heat-off delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 48 | 1 | 1 |
uint8
| hc1.instantstart | instant start | uint8 (&gt;=1&lt;=10) | K | true | HC | 49 | 1 | 1 |
| hc1.boost | boost mode | boolean | | true | HC | 50 | 1 | 1 |
| hc1.coolondelay | cooling on delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 49 | 1 | 1 |
uint8
| hc1.boosttime | boost time | uint8 (&gt;=0&lt;=0) | hours | true | HC | 51 | 1 | 1 |
| hc1.cooloffdelay | cooling off delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 50 | 1 | 1 |
uint8
| hc1.instantstart | instant start | uint8 (&gt;=1&lt;=10) | K | true | HC | 51 | 1 | 1 |
uint8
| hc1.coolstart | cooling starttemp | uint8 (&gt;=20&lt;=35) | C | true | HC | 52 | 1 | 1 |
| hc1.boost | boost mode | boolean | | true | HC | 53 | 1 | 1 |
uint8
| hc1.coolondelay | cooling on delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 53 | 1 | 1 |
uint8
| hc1.cooloffdelay | cooling off delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 54 | 1 | 1 |
| hc1.boosttime | boost time | uint8 (&gt;=0&lt;=0) | hours | true | HC | 54 | 1 | 1 |
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
int8
| hc1.redthreshold | reduction threshold | int8 (&gt;=12&lt;=22) | C | true | HC | 56 | 1 | 1/2 |
uint8
| hc1.solarinfl | solar influence | uint8 (&gt;=-5&lt;=4294967295) | C | true | HC | 57 | 1 | 1 |
| hc1.currsolarinfl | current solar influence | uint8 | C | false | HC | 58 | 1 | 1/10 |
int8
| hc1.solarinfl | solar influence | int8 (&gt;=-5&lt;=0) | C | true | HC | 57 | 1 | 1 |
| hc1.currsolarinfl | current solar influence | int8 | C | false | HC | 58 | 1 | 1/10 |
| hc1.heatingpid | heating PID | enum | | true | HC | 59 | 1 | 1 |
| hc1.pumpopt | pump optimization | boolean | | true | HC | 60 | 1 | 1 |
uint8
@@ -6410,6 +6410,21 @@ int8
int8
| pvlowercool | lower cooling with PV | int8 (&gt;=-5&lt;=0) | K | true | DEVICE_DATA | 63 | 1 | 1 |
| absent | absent | boolean | | true | DEVICE_DATA | 64 | 1 | 1 |
| hpoperatingmode | heatpump operating mode | enum | | true | DEVICE_DATA | 89 | 1 | 1 |
uint8
| summertemp | summer temperature | uint8 (&gt;=10&lt;=30) | C | true | DEVICE_DATA | 90 | 1 | 1 |
uint8
| instantstart | instant start | uint8 (&gt;=1&lt;=10) | K | true | DEVICE_DATA | 91 | 1 | 1 |
uint8
| coolstart | cooling starttemp | uint8 (&gt;=20&lt;=35) | C | true | DEVICE_DATA | 92 | 1 | 1 |
uint8
| heatondelay | heat-on delay | uint8 (&gt;=1&lt;=48) | hours | true | DEVICE_DATA | 93 | 1 | 1/4 |
uint8
| heatoffdelay | heat-off delay | uint8 (&gt;=1&lt;=48) | hours | true | DEVICE_DATA | 94 | 1 | 1/4 |
uint8
| coolondelay | cooling on delay | uint8 (&gt;=1&lt;=48) | hours | true | DEVICE_DATA | 95 | 1 | 1/4 |
uint8
| cooloffdelay | cooling off delay | uint8 (&gt;=1&lt;=48) | hours | true | DEVICE_DATA | 96 | 1 | 1/4 |
int16
| hc1.seltemp | selected room temperature | int16 (&gt;=0&lt;=30) | C | true | HC | 0 | 1 | 1/2 |
| hc1.currtemp | current room temperature | int16 | C | false | HC | 1 | 1 | 1/10 |
@@ -6480,27 +6495,15 @@ uint8
| hc1.control | control device | enum | | true | HC | 44 | 1 | 1 |
| hc1.remotetemp | room temperature from remote | cmd | C | true | HC | 45 | 1 | 1/10 |
| hc1.remotehum | room humidity from remote | cmd | % | true | HC | 46 | 1 | 1 |
| hc1.boost | boost mode | boolean | | true | HC | 53 | 1 | 1 |
uint8
| hc1.heatondelay | heat-on delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 47 | 1 | 1 |
uint8
| hc1.heatoffdelay | heat-off delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 48 | 1 | 1 |
uint8
| hc1.instantstart | instant start | uint8 (&gt;=1&lt;=10) | K | true | HC | 49 | 1 | 1 |
| hc1.boost | boost mode | boolean | | true | HC | 50 | 1 | 1 |
uint8
| hc1.boosttime | boost time | uint8 (&gt;=0&lt;=0) | hours | true | HC | 51 | 1 | 1 |
uint8
| hc1.coolstart | cooling starttemp | uint8 (&gt;=20&lt;=35) | C | true | HC | 52 | 1 | 1 |
uint8
| hc1.coolondelay | cooling on delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 53 | 1 | 1 |
uint8
| hc1.cooloffdelay | cooling off delay | uint8 (&gt;=1&lt;=48) | hours | true | HC | 54 | 1 | 1 |
| hc1.boosttime | boost time | uint8 (&gt;=0&lt;=0) | hours | true | HC | 54 | 1 | 1 |
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
int8
| hc1.redthreshold | reduction threshold | int8 (&gt;=12&lt;=22) | C | true | HC | 56 | 1 | 1/2 |
uint8
| hc1.solarinfl | solar influence | uint8 (&gt;=-5&lt;=4294967295) | C | true | HC | 57 | 1 | 1 |
| hc1.currsolarinfl | current solar influence | uint8 | C | false | HC | 58 | 1 | 1/10 |
int8
| hc1.solarinfl | solar influence | int8 (&gt;=-5&lt;=0) | C | true | HC | 57 | 1 | 1 |
| hc1.currsolarinfl | current solar influence | int8 | C | false | HC | 58 | 1 | 1/10 |
| hc1.heatingpid | heating PID | enum | | true | HC | 59 | 1 | 1 |
| hc1.pumpopt | pump optimization | boolean | | true | HC | 60 | 1 | 1 |
uint8
@@ -8143,7 +8146,7 @@ uint8
| datetime | date/time | string | | false | DEVICE_DATA | 0 | 13 | 1 |
| outdoortemp | outside temperature | int16 | C | false | DEVICE_DATA | 13 | 1 | 1/10 |
| src1.currtemp | current room temperature | int16 | C | false | SRC | 0 | 1 | 1/10 |
| src1.airhumidity | relative air humidity | int8 | % | false | SRC | 1 | 1 | 1 |
| src1.airhumidity | relative air humidity | uint8 | % | false | SRC | 1 | 1 | 1 |
| src1.dewtemperature | dew point temperature | int16 | C | false | SRC | 2 | 1 | 1/10 |
uint8
| src1.seltemp | selected room temperature | uint8 (&gt;=5&lt;=30) | C | true | SRC | 3 | 1 | 1/2 |
@@ -8353,70 +8356,40 @@ uint8
| shortname | fullname | type | uom | writeable | tag type | register offset | register count | scale factor |
|-|-|-|-|-|-|-|-|-|
| dhw.temp | current temperature | uint16 | C | false | DHW | 1 | 1 | 1/10 |
| dhw.storagetemp1 | storage intern temperature | uint16 | C | false | DHW | 16 | 1 | 1/10 |
| dhw.coldtemp | cold water | uint16 | C | false | DHW | 17 | 1 | 1/10 |
| dhw.temp5 | temperature 5 | uint16 | C | false | DHW | 18 | 1 | 1/10 |
| dhw.rettemp | return temperature | uint16 | C | false | DHW | 19 | 1 | 1/10 |
| dhw.tempstatus | temperature switch in assigned dhw (MC1) | int8 | | false | DHW | 11 | 1 | 1 |
| dhw.pump | pump | boolean | | false | DHW | 4 | 1 | 1 |
uint8
| dhw.maxtemp | maximum temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 12 | 1 | 1 |
int8
| dhw.difftemp | start differential temperature | int8 (&gt;=0&lt;=0) | C | true | DHW | 13 | 1 | 1 |
uint8
| dhw.seltemp | selected temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 0 | 1 | 1 |
| dhw.disinfectiontemp | disinfection temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 8 | 1 | 1 |
uint8
| dhw.redtemp | reduced temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 14 | 1 | 1 |
uint8
| dhw.hottemp | extra hot temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 20 | 1 | 1 |
uint8
| dhw.dailytemp | daily temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 21 | 1 | 1 |
uint8
| dhw.disinfectiontemp | disinfection temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 8 | 1 | 1 |
| dhw.requiredtemp | required temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 15 | 1 | 1 |
| dhw.circ | circulation active | boolean | | true | DHW | 9 | 1 | 1 |
| dhw.circmode | circulation pump mode | enum | | true | DHW | 10 | 1 | 1 |
| dhw.circtc | circulation time controlled | boolean | | true | DHW | 22 | 1 | 1 |
| dhw.keepwarm | keep warm | boolean | | true | DHW | 23 | 1 | 1 |
| dhw.status2 | status 2 | enum | | false | DHW | 24 | 1 | 1 |
| dhw.pumpmod | pump modulation | uint8 | % | false | DHW | 25 | 1 | 1 |
| dhw.flow | flow rate | uint16 | l/min | false | DHW | 26 | 1 | 1/10 |
uint8
| dhw.valvereturn | return valve | uint8 (&gt;=0&lt;=0) | % | true | DHW | 27 | 1 | 1 |
uint8
| dhw.deltatret | temp. diff. return valve | uint8 (&gt;=0&lt;=0) | K | true | DHW | 28 | 1 | 1 |
| dhw.errordisp | error display | enum | | true | DHW | 29 | 1 | 1 |
### SM200, MS200
| shortname | fullname | type | uom | writeable | tag type | register offset | register count | scale factor |
|-|-|-|-|-|-|-|-|-|
| dhw.temp | current temperature | uint16 | C | false | DHW | 1 | 1 | 1/10 |
| dhw.storagetemp1 | storage intern temperature | uint16 | C | false | DHW | 16 | 1 | 1/10 |
| dhw.coldtemp | cold water | uint16 | C | false | DHW | 17 | 1 | 1/10 |
| dhw.temp5 | temperature 5 | uint16 | C | false | DHW | 18 | 1 | 1/10 |
| dhw.rettemp | return temperature | uint16 | C | false | DHW | 19 | 1 | 1/10 |
| dhw.tempstatus | temperature switch in assigned dhw (MC1) | int8 | | false | DHW | 11 | 1 | 1 |
| dhw.pump | pump | boolean | | false | DHW | 4 | 1 | 1 |
uint8
| dhw.maxtemp | maximum temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 12 | 1 | 1 |
int8
| dhw.difftemp | start differential temperature | int8 (&gt;=0&lt;=0) | C | true | DHW | 13 | 1 | 1 |
uint8
| dhw.seltemp | selected temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 0 | 1 | 1 |
| dhw.disinfectiontemp | disinfection temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 8 | 1 | 1 |
uint8
| dhw.redtemp | reduced temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 14 | 1 | 1 |
uint8
| dhw.hottemp | extra hot temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 20 | 1 | 1 |
uint8
| dhw.dailytemp | daily temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 21 | 1 | 1 |
uint8
| dhw.disinfectiontemp | disinfection temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 8 | 1 | 1 |
| dhw.requiredtemp | required temperature | uint8 (&gt;=0&lt;=0) | C | true | DHW | 15 | 1 | 1 |
| dhw.circ | circulation active | boolean | | true | DHW | 9 | 1 | 1 |
| dhw.circmode | circulation pump mode | enum | | true | DHW | 10 | 1 | 1 |
| dhw.circtc | circulation time controlled | boolean | | true | DHW | 22 | 1 | 1 |
| dhw.keepwarm | keep warm | boolean | | true | DHW | 23 | 1 | 1 |
| dhw.status2 | status 2 | enum | | false | DHW | 24 | 1 | 1 |
| dhw.pumpmod | pump modulation | uint8 | % | false | DHW | 25 | 1 | 1 |
| dhw.flow | flow rate | uint16 | l/min | false | DHW | 26 | 1 | 1/10 |
uint8
| dhw.valvereturn | return valve | uint8 (&gt;=0&lt;=0) | % | true | DHW | 27 | 1 | 1 |
uint8
| dhw.deltatret | temp. diff. return valve | uint8 (&gt;=0&lt;=0) | K | true | DHW | 28 | 1 | 1 |
| dhw.errordisp | error display | enum | | true | DHW | 29 | 1 | 1 |
## Devices of type \_pool
+53 -75
View File
@@ -4044,21 +4044,21 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
"UI800, BC400",thermostat,4,hc1.dewoffset,dew point offset,uint8 (>=2<=10),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset,6,1,1,41,1
"UI800, BC400",thermostat,4,hc1.roomtempdiff,room temp difference,uint8 (>=0<=0),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff,6,1,1,42,1
"UI800, BC400",thermostat,4,hc1.hpminflowtemp,HP min. flow temp.,uint8 (>=0<=0),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp,6,1,1,43,1
"UI800, BC400",thermostat,4,hc1.control,control device,enum [off\|-\|RC100\|RC100H\|-\|RC120RF\|RC220/RT800\|single] (>=0<=0), ,true,select.thermostat_hc1_control_device,select.thermostat_hc1_control,6,1,1,44,1
"UI800, BC400",thermostat,4,hc1.control,control device,enum [off\|-\|RC100\|RC100H\|-\|RC120RF\|RC220\|single] (>=0<=0), ,true,select.thermostat_hc1_control_device,select.thermostat_hc1_control,6,1,1,44,1
"UI800, BC400",thermostat,4,hc1.remotetemp,room temperature from remote,cmd [] (>=-1<=101),C,true,sensor.thermostat_hc1_room_temperature_from_remote,sensor.thermostat_hc1_remotetemp,6,1,1/10,45,1
"UI800, BC400",thermostat,4,hc1.remotehum,room humidity from remote,cmd [] (>=-1<=101),%,true,sensor.thermostat_hc1_room_humidity_from_remote,sensor.thermostat_hc1_remotehum,6,1,1,46,1
"UI800, BC400",thermostat,4,hc1.heatondelay,heat-on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_heat-on_delay,number.thermostat_hc1_heatondelay,6,1,1,47,1
"UI800, BC400",thermostat,4,hc1.heatoffdelay,heat-off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_heat-off_delay,number.thermostat_hc1_heatoffdelay,6,1,1,48,1
"UI800, BC400",thermostat,4,hc1.instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,49,1
"UI800, BC400",thermostat,4,hc1.boost,boost mode,boolean (>=0<=0), ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,50,1
"UI800, BC400",thermostat,4,hc1.boosttime,boost time,uint8 (>=0<=0),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,51,1
"UI800, BC400",thermostat,4,hc1.coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,49,1
"UI800, BC400",thermostat,4,hc1.cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,50,1
"UI800, BC400",thermostat,4,hc1.instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,51,1
"UI800, BC400",thermostat,4,hc1.coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,52,1
"UI800, BC400",thermostat,4,hc1.coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,53,1
"UI800, BC400",thermostat,4,hc1.cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,54,1
"UI800, BC400",thermostat,4,hc1.boost,boost mode,boolean (>=0<=0), ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,53,1
"UI800, BC400",thermostat,4,hc1.boosttime,boost time,uint8 (>=0<=0),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,54,1
"UI800, BC400",thermostat,4,hc1.switchprogmode,switch program mode,enum [level\|absolute] (>=0<=0), ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,55,1
"UI800, BC400",thermostat,4,hc1.redthreshold,reduction threshold,int8 (>=12<=22),C,true,number.thermostat_hc1_reduction_threshold,number.thermostat_hc1_redthreshold,6,1,1/2,56,1
"UI800, BC400",thermostat,4,hc1.solarinfl,solar influence,uint8 (>=-5<=4294967295),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
"UI800, BC400",thermostat,4,hc1.currsolarinfl,current solar influence,uint8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
"UI800, BC400",thermostat,4,hc1.solarinfl,solar influence,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
"UI800, BC400",thermostat,4,hc1.currsolarinfl,current solar influence,int8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
"UI800, BC400",thermostat,4,hc1.heatingpid,heating PID,enum [fast\|medium\|slow] (>=0<=0), ,true,select.thermostat_hc1_heating_PID,select.thermostat_hc1_heatingpid,6,1,1,59,1
"UI800, BC400",thermostat,4,hc1.pumpopt,pump optimization,boolean (>=0<=0), ,true,switch.thermostat_hc1_pump_optimization,switch.thermostat_hc1_pumpopt,6,1,1,60,1
"UI800, BC400",thermostat,4,hc1.inttimefloor,integral time floor,uint8 (>=160<=320),minutes,true,number.thermostat_hc1_integral_time_floor,number.thermostat_hc1_inttimefloor,6,1,10,61,1
@@ -4439,16 +4439,16 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
"RC200, CW100, CR120, CR50",thermostat,157,hc1.control,control device,enum [RC310\|RC200\|RC100\|RC100H\|TC100] (>=0<=0), ,true,select.thermostat_hc1_control_device,select.thermostat_hc1_control,6,1,1,44,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.heatondelay,heat-on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_heat-on_delay,number.thermostat_hc1_heatondelay,6,1,1,47,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.heatoffdelay,heat-off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_heat-off_delay,number.thermostat_hc1_heatoffdelay,6,1,1,48,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,49,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.boost,boost mode,boolean (>=0<=0), ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,50,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.boosttime,boost time,uint8 (>=0<=0),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,51,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,49,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,50,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,51,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,52,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,53,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,54,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.boost,boost mode,boolean (>=0<=0), ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,53,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.boosttime,boost time,uint8 (>=0<=0),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,54,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.switchprogmode,switch program mode,enum [level\|absolute] (>=0<=0), ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,55,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.redthreshold,reduction threshold,int8 (>=12<=22),C,true,number.thermostat_hc1_reduction_threshold,number.thermostat_hc1_redthreshold,6,1,1/2,56,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.solarinfl,solar influence,uint8 (>=-5<=4294967295),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.currsolarinfl,current solar influence,uint8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.solarinfl,solar influence,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.currsolarinfl,current solar influence,int8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.heatingpid,heating PID,enum [fast\|medium\|slow] (>=0<=0), ,true,select.thermostat_hc1_heating_PID,select.thermostat_hc1_heatingpid,6,1,1,59,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.pumpopt,pump optimization,boolean (>=0<=0), ,true,switch.thermostat_hc1_pump_optimization,switch.thermostat_hc1_pumpopt,6,1,1,60,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.inttimefloor,integral time floor,uint8 (>=160<=320),minutes,true,number.thermostat_hc1_integral_time_floor,number.thermostat_hc1_inttimefloor,6,1,10,61,1
@@ -4537,16 +4537,16 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.remotehum,room humidity from remote,cmd [] (>=-1<=101),%,true,sensor.thermostat_hc1_room_humidity_from_remote,sensor.thermostat_hc1_remotehum,6,1,1,46,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.heatondelay,heat-on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_heat-on_delay,number.thermostat_hc1_heatondelay,6,1,1,47,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.heatoffdelay,heat-off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_heat-off_delay,number.thermostat_hc1_heatoffdelay,6,1,1,48,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,49,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.boost,boost mode,boolean (>=0<=0), ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,50,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.boosttime,boost time,uint8 (>=0<=0),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,51,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,49,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,50,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,51,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,52,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,53,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,54,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.boost,boost mode,boolean (>=0<=0), ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,53,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.boosttime,boost time,uint8 (>=0<=0),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,54,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.switchprogmode,switch program mode,enum [level\|absolute] (>=0<=0), ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,55,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.redthreshold,reduction threshold,int8 (>=12<=22),C,true,number.thermostat_hc1_reduction_threshold,number.thermostat_hc1_redthreshold,6,1,1/2,56,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.solarinfl,solar influence,uint8 (>=-5<=4294967295),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.currsolarinfl,current solar influence,uint8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.solarinfl,solar influence,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.currsolarinfl,current solar influence,int8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.heatingpid,heating PID,enum [fast\|medium\|slow] (>=0<=0), ,true,select.thermostat_hc1_heating_PID,select.thermostat_hc1_heatingpid,6,1,1,59,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.pumpopt,pump optimization,boolean (>=0<=0), ,true,switch.thermostat_hc1_pump_optimization,switch.thermostat_hc1_pumpopt,6,1,1,60,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.inttimefloor,integral time floor,uint8 (>=160<=320),minutes,true,number.thermostat_hc1_integral_time_floor,number.thermostat_hc1_inttimefloor,6,1,10,61,1
@@ -4644,16 +4644,16 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
"Rego 2000/3000",thermostat,172,hc1.remotehum,room humidity from remote,cmd [] (>=-1<=101),%,true,sensor.thermostat_hc1_room_humidity_from_remote,sensor.thermostat_hc1_remotehum,6,1,1,46,1
"Rego 2000/3000",thermostat,172,hc1.heatondelay,heat-on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_heat-on_delay,number.thermostat_hc1_heatondelay,6,1,1,47,1
"Rego 2000/3000",thermostat,172,hc1.heatoffdelay,heat-off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_heat-off_delay,number.thermostat_hc1_heatoffdelay,6,1,1,48,1
"Rego 2000/3000",thermostat,172,hc1.instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,49,1
"Rego 2000/3000",thermostat,172,hc1.boost,boost mode,boolean (>=0<=0), ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,50,1
"Rego 2000/3000",thermostat,172,hc1.boosttime,boost time,uint8 (>=0<=0),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,51,1
"Rego 2000/3000",thermostat,172,hc1.coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,49,1
"Rego 2000/3000",thermostat,172,hc1.cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,50,1
"Rego 2000/3000",thermostat,172,hc1.instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,51,1
"Rego 2000/3000",thermostat,172,hc1.coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,52,1
"Rego 2000/3000",thermostat,172,hc1.coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,53,1
"Rego 2000/3000",thermostat,172,hc1.cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,54,1
"Rego 2000/3000",thermostat,172,hc1.boost,boost mode,boolean (>=0<=0), ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,53,1
"Rego 2000/3000",thermostat,172,hc1.boosttime,boost time,uint8 (>=0<=0),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,54,1
"Rego 2000/3000",thermostat,172,hc1.switchprogmode,switch program mode,enum [level\|absolute] (>=0<=0), ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,55,1
"Rego 2000/3000",thermostat,172,hc1.redthreshold,reduction threshold,int8 (>=12<=22),C,true,number.thermostat_hc1_reduction_threshold,number.thermostat_hc1_redthreshold,6,1,1/2,56,1
"Rego 2000/3000",thermostat,172,hc1.solarinfl,solar influence,uint8 (>=-5<=4294967295),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
"Rego 2000/3000",thermostat,172,hc1.currsolarinfl,current solar influence,uint8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
"Rego 2000/3000",thermostat,172,hc1.solarinfl,solar influence,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
"Rego 2000/3000",thermostat,172,hc1.currsolarinfl,current solar influence,int8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
"Rego 2000/3000",thermostat,172,hc1.heatingpid,heating PID,enum [fast\|medium\|slow] (>=0<=0), ,true,select.thermostat_hc1_heating_PID,select.thermostat_hc1_heatingpid,6,1,1,59,1
"Rego 2000/3000",thermostat,172,hc1.pumpopt,pump optimization,boolean (>=0<=0), ,true,switch.thermostat_hc1_pump_optimization,switch.thermostat_hc1_pumpopt,6,1,1,60,1
"Rego 2000/3000",thermostat,172,hc1.inttimefloor,integral time floor,uint8 (>=160<=320),minutes,true,number.thermostat_hc1_integral_time_floor,number.thermostat_hc1_inttimefloor,6,1,10,61,1
@@ -4720,6 +4720,14 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
"Rego 3000, UI800, Logamatic BC400",thermostat,253,pvraiseheat,raise heating with PV,int8 (>=0<=5),K,true,number.thermostat_raise_heating_with_PV,number.thermostat_pvraiseheat,6,0,1,62,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,pvlowercool,lower cooling with PV,int8 (>=-5<=0),K,true,number.thermostat_lower_cooling_with_PV,number.thermostat_pvlowercool,6,0,1,63,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,absent,absent,boolean (>=0<=0), ,true,switch.thermostat_absent,switch.thermostat_absent,6,0,1,64,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hpoperatingmode,heatpump operating mode,enum [off\|auto\|heating\|cooling] (>=0<=0), ,true,select.thermostat_heatpump_operating_mode,select.thermostat_hpoperatingmode,6,0,1,89,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,summertemp,summer temperature,uint8 (>=10<=30),C,true,number.thermostat_summer_temperature,number.thermostat_summertemp,6,0,1,90,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_instant_start,number.thermostat_instantstart,6,0,1,91,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_cooling_starttemp,number.thermostat_coolstart,6,0,1,92,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,heatondelay,heat-on delay,uint8 (>=1<=48),hours,true,number.thermostat_heat-on_delay,number.thermostat_heatondelay,6,0,1/4,93,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,heatoffdelay,heat-off delay,uint8 (>=1<=48),hours,true,number.thermostat_heat-off_delay,number.thermostat_heatoffdelay,6,0,1/4,94,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_cooling_on_delay,number.thermostat_coolondelay,6,0,1/4,95,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_cooling_off_delay,number.thermostat_cooloffdelay,6,0,1/4,96,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.seltemp,selected room temperature,int16 (>=0<=30),C,true,number.thermostat_hc1_selected_room_temperature,number.thermostat_hc1_seltemp,6,1,1/2,0,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.currtemp,current room temperature,int16,C,false,sensor.thermostat_hc1_current_room_temperature,sensor.thermostat_hc1_currtemp,6,1,1/10,1,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.haclimate,mqtt discovery current room temperature,enum [selTemp\|roomTemp], ,false,sensor.thermostat_hc1_mqtt_discovery_current_room_temperature,sensor.thermostat_hc1_haclimate,6,1,1,2,1
@@ -4764,21 +4772,15 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.dewoffset,dew point offset,uint8 (>=2<=10),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset,6,1,1,41,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.roomtempdiff,room temp difference,uint8 (>=0<=0),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff,6,1,1,42,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.hpminflowtemp,HP min. flow temp.,uint8 (>=0<=0),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp,6,1,1,43,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.control,control device,enum [off\|-\|RC100\|RC100H\|-\|RC120RF\|RC220/RT800\|single] (>=0<=0), ,true,select.thermostat_hc1_control_device,select.thermostat_hc1_control,6,1,1,44,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.control,control device,enum [off\|-\|CR10\|CR10H\|-\|CR20RF\|RT800\|single] (>=0<=0), ,true,select.thermostat_hc1_control_device,select.thermostat_hc1_control,6,1,1,44,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.remotetemp,room temperature from remote,cmd [] (>=-1<=101),C,true,sensor.thermostat_hc1_room_temperature_from_remote,sensor.thermostat_hc1_remotetemp,6,1,1/10,45,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.remotehum,room humidity from remote,cmd [] (>=-1<=101),%,true,sensor.thermostat_hc1_room_humidity_from_remote,sensor.thermostat_hc1_remotehum,6,1,1,46,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.heatondelay,heat-on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_heat-on_delay,number.thermostat_hc1_heatondelay,6,1,1,47,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.heatoffdelay,heat-off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_heat-off_delay,number.thermostat_hc1_heatoffdelay,6,1,1,48,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,49,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.boost,boost mode,boolean (>=0<=0), ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,50,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.boosttime,boost time,uint8 (>=0<=0),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,51,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,52,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,53,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,54,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.boost,boost mode,boolean (>=0<=0), ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,53,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.boosttime,boost time,uint8 (>=0<=0),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,54,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.switchprogmode,switch program mode,enum [level\|absolute] (>=0<=0), ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,55,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.redthreshold,reduction threshold,int8 (>=12<=22),C,true,number.thermostat_hc1_reduction_threshold,number.thermostat_hc1_redthreshold,6,1,1/2,56,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.solarinfl,solar influence,uint8 (>=-5<=4294967295),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.currsolarinfl,current solar influence,uint8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.solarinfl,solar influence,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.currsolarinfl,current solar influence,int8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.heatingpid,heating PID,enum [fast\|medium\|slow] (>=0<=0), ,true,select.thermostat_hc1_heating_PID,select.thermostat_hc1_heatingpid,6,1,1,59,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.pumpopt,pump optimization,boolean (>=0<=0), ,true,switch.thermostat_hc1_pump_optimization,switch.thermostat_hc1_pumpopt,6,1,1,60,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.inttimefloor,integral time floor,uint8 (>=160<=320),minutes,true,number.thermostat_hc1_integral_time_floor,number.thermostat_hc1_inttimefloor,6,1,10,61,1
@@ -5859,7 +5861,7 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
"MX400",connect,17,datetime,date/time,string, ,false,sensor.connect_date/time,sensor.connect_datetime,13,0,1,0,13
"MX400",connect,17,outdoortemp,outside temperature,int16,C,false,sensor.connect_outside_temperature,sensor.connect_outdoortemp,13,0,1/10,13,1
"MX400",connect,17,src1.currtemp,current room temperature,int16,C,false,sensor.connect_src1_current_room_temperature,sensor.connect_src1_currtemp,13,36,1/10,0,1
"MX400",connect,17,src1.airhumidity,relative air humidity,int8,%,false,sensor.connect_src1_relative_air_humidity,sensor.connect_src1_airhumidity,13,36,1,1,1
"MX400",connect,17,src1.airhumidity,relative air humidity,uint8,%,false,sensor.connect_src1_relative_air_humidity,sensor.connect_src1_airhumidity,13,36,1,1,1
"MX400",connect,17,src1.dewtemperature,dew point temperature,int16,C,false,sensor.connect_src1_dew_point_temperature,sensor.connect_src1_dewtemperature,13,36,1/10,2,1
"MX400",connect,17,src1.seltemp,selected room temperature,uint8 (>=5<=30),C,true,number.connect_src1_selected_room_temperature,number.connect_src1_seltemp,13,36,1/2,3,1
"MX400",connect,17,src1.mode,operating mode,enum [off\|manual\|auto] (>=0<=0), ,true,select.connect_src1_operating_mode,select.connect_src1_mode,13,36,1,4,1
@@ -5973,49 +5975,25 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
"MM200",water,161,dhw.circ,circulation active,boolean (>=0<=0), ,true,switch.water_dhw_circulation_active,switch.water_dhw_circ,19,9,1,9,1
"MM200",water,161,dhw.circmode,circulation pump mode,enum [off\|on\|auto\|own prog] (>=0<=0), ,true,select.water_dhw_circulation_pump_mode,select.water_dhw_circmode,19,9,1,10,1
"SM100, MS100",water,163,dhw.temp,current temperature,uint16,C,false,sensor.water_dhw_current_temperature,sensor.water_dhw_temp,19,9,1/10,1,1
"SM100, MS100",water,163,dhw.storagetemp1,storage intern temperature,uint16,C,false,sensor.water_dhw_storage_intern_temperature,sensor.water_dhw_storagetemp1,19,9,1/10,16,1
"SM100, MS100",water,163,dhw.coldtemp,cold water,uint16,C,false,sensor.water_dhw_cold_water,sensor.water_dhw_coldtemp,19,9,1/10,17,1
"SM100, MS100",water,163,dhw.temp5,temperature 5,uint16,C,false,sensor.water_dhw_temperature_5,sensor.water_dhw_temp5,19,9,1/10,18,1
"SM100, MS100",water,163,dhw.rettemp,return temperature,uint16,C,false,sensor.water_dhw_return_temperature,sensor.water_dhw_rettemp,19,9,1/10,19,1
"SM100, MS100",water,163,dhw.tempstatus,temperature switch in assigned dhw (MC1),int8, ,false,sensor.water_dhw_temperature_switch_in_assigned_dhw_(MC1),sensor.water_dhw_tempstatus,19,9,1,11,1
"SM100, MS100",water,163,dhw.pump,pump,boolean, ,false,binary_sensor.water_dhw_pump,binary_sensor.water_dhw_pump,19,9,1,4,1
"SM100, MS100",water,163,dhw.maxtemp,maximum temperature,uint8 (>=0<=0),C,true,number.water_dhw_maximum_temperature,number.water_dhw_maxtemp,19,9,1,12,1
"SM100, MS100",water,163,dhw.seltemp,selected temperature,uint8 (>=0<=0),C,true,number.water_dhw_selected_temperature,number.water_dhw_seltemp,19,9,1,0,1
"SM100, MS100",water,163,dhw.redtemp,reduced temperature,uint8 (>=0<=0),C,true,number.water_dhw_reduced_temperature,number.water_dhw_redtemp,19,9,1,14,1
"SM100, MS100",water,163,dhw.hottemp,extra hot temperature,uint8 (>=0<=0),C,true,number.water_dhw_extra_hot_temperature,number.water_dhw_hottemp,19,9,1,20,1
"SM100, MS100",water,163,dhw.dailytemp,daily temperature,uint8 (>=0<=0),C,true,number.water_dhw_daily_temperature,number.water_dhw_dailytemp,19,9,1,21,1
"SM100, MS100",water,163,dhw.difftemp,start differential temperature,int8 (>=0<=0),C,true,number.water_dhw_start_differential_temperature,number.water_dhw_difftemp,19,9,1,13,1
"SM100, MS100",water,163,dhw.disinfectiontemp,disinfection temperature,uint8 (>=0<=0),C,true,number.water_dhw_disinfection_temperature,number.water_dhw_disinfectiontemp,19,9,1,8,1
"SM100, MS100",water,163,dhw.redtemp,reduced temperature,uint8 (>=0<=0),C,true,number.water_dhw_reduced_temperature,number.water_dhw_redtemp,19,9,1,14,1
"SM100, MS100",water,163,dhw.requiredtemp,required temperature,uint8 (>=0<=0),C,true,number.water_dhw_required_temperature,number.water_dhw_requiredtemp,19,9,1,15,1
"SM100, MS100",water,163,dhw.circ,circulation active,boolean (>=0<=0), ,true,switch.water_dhw_circulation_active,switch.water_dhw_circ,19,9,1,9,1
"SM100, MS100",water,163,dhw.circmode,circulation pump mode,enum [off\|1x3min\|2x3min\|3x3min\|4x3min\|5x3min\|6x3min\|continuous] (>=0<=0), ,true,select.water_dhw_circulation_pump_mode,select.water_dhw_circmode,19,9,1,10,1
"SM100, MS100",water,163,dhw.circtc,circulation time controlled,boolean (>=0<=0), ,true,switch.water_dhw_circulation_time_controlled,switch.water_dhw_circtc,19,9,1,22,1
"SM100, MS100",water,163,dhw.keepwarm,keep warm,boolean (>=0<=0), ,true,switch.water_dhw_keep_warm,switch.water_dhw_keepwarm,19,9,1,23,1
"SM100, MS100",water,163,dhw.status2,status 2,enum [\|\|\|no heat\|\|\|heat request\|\|disinfecting\|hold], ,false,sensor.water_dhw_status_2,sensor.water_dhw_status2,19,9,1,24,1
"SM100, MS100",water,163,dhw.pumpmod,pump modulation,uint8,%,false,sensor.water_dhw_pump_modulation,sensor.water_dhw_pumpmod,19,9,1,25,1
"SM100, MS100",water,163,dhw.flow,flow rate,uint16,l/min,false,sensor.water_dhw_flow_rate,sensor.water_dhw_flow,19,9,1/10,26,1
"SM100, MS100",water,163,dhw.valvereturn,return valve,uint8 (>=0<=0),%,true,number.water_dhw_return_valve,number.water_dhw_valvereturn,19,9,1,27,1
"SM100, MS100",water,163,dhw.deltatret,temp. diff. return valve,uint8 (>=0<=0),K,true,number.water_dhw_temp._diff._return_valve,number.water_dhw_deltatret,19,9,1,28,1
"SM100, MS100",water,163,dhw.errordisp,error display,enum [off\|normal\|inverted] (>=0<=0), ,true,select.water_dhw_error_display,select.water_dhw_errordisp,19,9,1,29,1
"SM100, MS100",water,163,dhw.circmode,circulation pump mode,enum [off\|on\|auto\|own prog] (>=0<=0), ,true,select.water_dhw_circulation_pump_mode,select.water_dhw_circmode,19,9,1,10,1
"SM200, MS200",water,164,dhw.temp,current temperature,uint16,C,false,sensor.water_dhw_current_temperature,sensor.water_dhw_temp,19,9,1/10,1,1
"SM200, MS200",water,164,dhw.storagetemp1,storage intern temperature,uint16,C,false,sensor.water_dhw_storage_intern_temperature,sensor.water_dhw_storagetemp1,19,9,1/10,16,1
"SM200, MS200",water,164,dhw.coldtemp,cold water,uint16,C,false,sensor.water_dhw_cold_water,sensor.water_dhw_coldtemp,19,9,1/10,17,1
"SM200, MS200",water,164,dhw.temp5,temperature 5,uint16,C,false,sensor.water_dhw_temperature_5,sensor.water_dhw_temp5,19,9,1/10,18,1
"SM200, MS200",water,164,dhw.rettemp,return temperature,uint16,C,false,sensor.water_dhw_return_temperature,sensor.water_dhw_rettemp,19,9,1/10,19,1
"SM200, MS200",water,164,dhw.tempstatus,temperature switch in assigned dhw (MC1),int8, ,false,sensor.water_dhw_temperature_switch_in_assigned_dhw_(MC1),sensor.water_dhw_tempstatus,19,9,1,11,1
"SM200, MS200",water,164,dhw.pump,pump,boolean, ,false,binary_sensor.water_dhw_pump,binary_sensor.water_dhw_pump,19,9,1,4,1
"SM200, MS200",water,164,dhw.maxtemp,maximum temperature,uint8 (>=0<=0),C,true,number.water_dhw_maximum_temperature,number.water_dhw_maxtemp,19,9,1,12,1
"SM200, MS200",water,164,dhw.seltemp,selected temperature,uint8 (>=0<=0),C,true,number.water_dhw_selected_temperature,number.water_dhw_seltemp,19,9,1,0,1
"SM200, MS200",water,164,dhw.redtemp,reduced temperature,uint8 (>=0<=0),C,true,number.water_dhw_reduced_temperature,number.water_dhw_redtemp,19,9,1,14,1
"SM200, MS200",water,164,dhw.hottemp,extra hot temperature,uint8 (>=0<=0),C,true,number.water_dhw_extra_hot_temperature,number.water_dhw_hottemp,19,9,1,20,1
"SM200, MS200",water,164,dhw.dailytemp,daily temperature,uint8 (>=0<=0),C,true,number.water_dhw_daily_temperature,number.water_dhw_dailytemp,19,9,1,21,1
"SM200, MS200",water,164,dhw.difftemp,start differential temperature,int8 (>=0<=0),C,true,number.water_dhw_start_differential_temperature,number.water_dhw_difftemp,19,9,1,13,1
"SM200, MS200",water,164,dhw.disinfectiontemp,disinfection temperature,uint8 (>=0<=0),C,true,number.water_dhw_disinfection_temperature,number.water_dhw_disinfectiontemp,19,9,1,8,1
"SM200, MS200",water,164,dhw.redtemp,reduced temperature,uint8 (>=0<=0),C,true,number.water_dhw_reduced_temperature,number.water_dhw_redtemp,19,9,1,14,1
"SM200, MS200",water,164,dhw.requiredtemp,required temperature,uint8 (>=0<=0),C,true,number.water_dhw_required_temperature,number.water_dhw_requiredtemp,19,9,1,15,1
"SM200, MS200",water,164,dhw.circ,circulation active,boolean (>=0<=0), ,true,switch.water_dhw_circulation_active,switch.water_dhw_circ,19,9,1,9,1
"SM200, MS200",water,164,dhw.circmode,circulation pump mode,enum [off\|1x3min\|2x3min\|3x3min\|4x3min\|5x3min\|6x3min\|continuous] (>=0<=0), ,true,select.water_dhw_circulation_pump_mode,select.water_dhw_circmode,19,9,1,10,1
"SM200, MS200",water,164,dhw.circtc,circulation time controlled,boolean (>=0<=0), ,true,switch.water_dhw_circulation_time_controlled,switch.water_dhw_circtc,19,9,1,22,1
"SM200, MS200",water,164,dhw.keepwarm,keep warm,boolean (>=0<=0), ,true,switch.water_dhw_keep_warm,switch.water_dhw_keepwarm,19,9,1,23,1
"SM200, MS200",water,164,dhw.status2,status 2,enum [\|\|\|no heat\|\|\|heat request\|\|disinfecting\|hold], ,false,sensor.water_dhw_status_2,sensor.water_dhw_status2,19,9,1,24,1
"SM200, MS200",water,164,dhw.pumpmod,pump modulation,uint8,%,false,sensor.water_dhw_pump_modulation,sensor.water_dhw_pumpmod,19,9,1,25,1
"SM200, MS200",water,164,dhw.flow,flow rate,uint16,l/min,false,sensor.water_dhw_flow_rate,sensor.water_dhw_flow,19,9,1/10,26,1
"SM200, MS200",water,164,dhw.valvereturn,return valve,uint8 (>=0<=0),%,true,number.water_dhw_return_valve,number.water_dhw_valvereturn,19,9,1,27,1
"SM200, MS200",water,164,dhw.deltatret,temp. diff. return valve,uint8 (>=0<=0),K,true,number.water_dhw_temp._diff._return_valve,number.water_dhw_deltatret,19,9,1,28,1
"SM200, MS200",water,164,dhw.errordisp,error display,enum [off\|normal\|inverted] (>=0<=0), ,true,select.water_dhw_error_display,select.water_dhw_errordisp,19,9,1,29,1
"SM200, MS200",water,164,dhw.circmode,circulation pump mode,enum [off\|on\|auto\|own prog] (>=0<=0), ,true,select.water_dhw_circulation_pump_mode,select.water_dhw_circmode,19,9,1,10,1
"MP100",pool,204,pooltemp,pool temperature,int16,C,false,sensor.pool_pool_temperature,sensor.pool_pooltemp,20,0,1/10,-1,1
"MP100",pool,204,poolshuntstatus,pool shunt status opening/closing,enum [stopped\|opening\|closing\|open\|close], ,false,sensor.pool_pool_shunt_status_opening/closing,sensor.pool_poolshuntstatus,20,0,1,-1,1
"MP100",pool,204,poolshunt,pool shunt open/close (0% = pool / 100% = heat),uint8,%,false,sensor.pool_pool_shunt_open/close_(0%_=_pool_/_100%_=_heat),sensor.pool_poolshunt,20,0,1,-1,1
Can't render this file because it is too large.
+14 -14
View File
@@ -13,7 +13,7 @@ telegram_type_id,name,is_fetched
0x19,UBAMonitorSlow,
0x1A,UBASetPoints,
0x1C,UBAMaintenanceStatus,
0x1E,HydrTemp,
0x1E,WM10TempMessage,
0x23,JunkersSetMixer,fetched
0x27,UBASettingsWW,fetched
0x28,WeatherComp,fetched
@@ -77,7 +77,7 @@ telegram_type_id,name,is_fetched
0x0103,ISM1StatusMessage,fetched
0x0104,ISM2StatusMessage,
0x010C,IPMStatusMessage,
0x011E,IPMTempMessage,
0x011E,JunkersDisp,fetched
0x012E,HPEnergy1,
0x013B,HPEnergy2,
0x0165,JunkersSet,
@@ -112,10 +112,10 @@ telegram_type_id,name,is_fetched
0x02A0,RC300Curves,
0x02A1,RC300Curves,
0x02A2,RC300Curves,
0x02A5,RC300Monitor,
0x02A5,CRFMonitor,
0x02A6,RC300Monitor,
0x02A7,RC300Monitor,
0x02A8,RC300Monitor,
0x02A8,CRFMonitor,
0x02A9,RC300Monitor,
0x02AA,RC300Monitor,
0x02AB,RC300Monitor,
@@ -171,15 +171,15 @@ telegram_type_id,name,is_fetched
0x0468,HPSet,
0x0469,HPSet,
0x046A,HPSet,
0x0470,RC300Summer2,fetched
0x0471,RC300Summer2,
0x0472,RC300Summer2,
0x0473,RC300Summer2,
0x0474,RC300Summer2,
0x0475,RC300Summer2,
0x0476,RC300Summer2,
0x0477,RC300Summer2,
0x0478,RC300Summer2,
0x0470,RC300Summer3,fetched
0x0471,RC300Sumr2,
0x0472,RC300Sumr2,
0x0473,RC300Sumr2,
0x0474,RC300Sumr2,
0x0475,RC300Sumr2,
0x0476,RC300Sumr2,
0x0477,RC300Sumr2,
0x0478,RC300Sumr2,
0x047B,HP2,
0x0484,HPSilentMode,fetched
0x0485,HpCooling,fetched
@@ -199,7 +199,7 @@ telegram_type_id,name,is_fetched
0x04A2,HpInput,fetched
0x04A5,HPFan,fetched
0x04A7,HPPowerLimit,fetched
0x04AA,HPPower,
0x04AA,HPPower2,fetched
0x04AE,HPEnergy,fetched
0x04AF,HPMeters,fetched
0x055C,VentilationSet,fetched
1 telegram_type_id name is_fetched
13 0x19 UBAMonitorSlow
14 0x1A UBASetPoints
15 0x1C UBAMaintenanceStatus
16 0x1E HydrTemp WM10TempMessage
17 0x23 JunkersSetMixer fetched
18 0x27 UBASettingsWW fetched
19 0x28 WeatherComp fetched
77 0x0103 ISM1StatusMessage fetched
78 0x0104 ISM2StatusMessage
79 0x010C IPMStatusMessage
80 0x011E IPMTempMessage JunkersDisp fetched
81 0x012E HPEnergy1
82 0x013B HPEnergy2
83 0x0165 JunkersSet
112 0x02A0 RC300Curves
113 0x02A1 RC300Curves
114 0x02A2 RC300Curves
115 0x02A5 RC300Monitor CRFMonitor
116 0x02A6 RC300Monitor
117 0x02A7 RC300Monitor
118 0x02A8 RC300Monitor CRFMonitor
119 0x02A9 RC300Monitor
120 0x02AA RC300Monitor
121 0x02AB RC300Monitor
171 0x0468 HPSet
172 0x0469 HPSet
173 0x046A HPSet
174 0x0470 RC300Summer2 RC300Summer3 fetched
175 0x0471 RC300Summer2 RC300Sumr2
176 0x0472 RC300Summer2 RC300Sumr2
177 0x0473 RC300Summer2 RC300Sumr2
178 0x0474 RC300Summer2 RC300Sumr2
179 0x0475 RC300Summer2 RC300Sumr2
180 0x0476 RC300Summer2 RC300Sumr2
181 0x0477 RC300Summer2 RC300Sumr2
182 0x0478 RC300Summer2 RC300Sumr2
183 0x047B HP2
184 0x0484 HPSilentMode fetched
185 0x0485 HpCooling fetched
199 0x04A2 HpInput fetched
200 0x04A5 HPFan fetched
201 0x04A7 HPPowerLimit fetched
202 0x04AA HPPower HPPower2 fetched
203 0x04AE HPEnergy fetched
204 0x04AF HPMeters fetched
205 0x055C VentilationSet fetched
+1
View File
@@ -24,6 +24,7 @@ build_flags =
-D FACTORY_NTP_TIME_ZONE_LABEL=\"Europe/Amsterdam\"
-D FACTORY_NTP_TIME_ZONE_FORMAT=\"CET-1CEST,M3.5.0,M10.5.0/3\"
-D FACTORY_NTP_SERVER=\"time.google.com\"
-D FACTORY_NTP_THERMOSTAT_SYNC=0
; MQTT settings
-D FACTORY_MQTT_ENABLED=false
+12 -12
View File
@@ -26,8 +26,8 @@
"@alova/adapter-xhr": "2.3.1",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@mui/icons-material": "^9.0.1",
"@mui/material": "^9.0.1",
"@mui/icons-material": "^9.2.0",
"@mui/material": "^9.2.0",
"@preact/compat": "^18.3.2",
"@table-library/react-table-library": "4.1.15",
"alova": "3.5.1",
@@ -37,17 +37,17 @@
"jwt-decode": "^4.0.0",
"magic-string": "^0.30.21",
"mime-types": "^3.0.2",
"preact": "^10.29.1",
"react": "^19.2.6",
"react-dom": "^19.2.6",
"react-icons": "^5.6.0",
"react-router": "^7.15.0",
"preact": "^10.29.7",
"react": "^19.2.7",
"react-dom": "^19.2.7",
"react-icons": "^5.7.0",
"react-router": "^7.18.1",
"react-toastify": "^11.1.0",
"typesafe-i18n": "^5.27.1",
"typescript": "^6.0.3"
},
"devDependencies": {
"@babel/core": "^7.29.0",
"@babel/core": "^7.29.7",
"@eslint/js": "^10.0.1",
"@preact/compat": "^18.3.2",
"@preact/preset-vite": "^2.10.5",
@@ -55,11 +55,11 @@
"@types/node": "^25.7.0",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"axe-core": "^4.11.4",
"concurrently": "^9.2.1",
"eslint": "^10.3.0",
"axe-core": "^4.12.1",
"concurrently": "^9.2.4",
"eslint": "^10.7.0",
"eslint-config-prettier": "^10.1.8",
"prettier": "^3.8.3",
"prettier": "^3.9.5",
"rollup-plugin-visualizer": "^7.0.1",
"terser": "^5.47.1",
"typescript-eslint": "^8.59.3",
+730 -1243
View File
File diff suppressed because it is too large Load Diff
+25
View File
@@ -1,3 +1,28 @@
allowBuilds:
cwebp-bin: set this to true or false
esbuild: set this to true or false
gifsicle: set this to true or false
jpegtran-bin: set this to true or false
mozjpeg: set this to true or false
optipng-bin: set this to true or false
pngquant-bin: set this to true or false
minimumReleaseAgeExclude:
- '@babel/code-frame@7.29.7'
- '@babel/compat-data@7.29.7'
- '@babel/core@7.29.7'
- '@babel/generator@7.29.7'
- '@babel/helper-compilation-targets@7.29.7'
- '@babel/helper-globals@7.29.7'
- '@babel/helper-module-imports@7.29.7'
- '@babel/helper-module-transforms@7.29.7'
- '@babel/helper-string-parser@7.29.7'
- '@babel/helper-validator-identifier@7.29.7'
- '@babel/helper-validator-option@7.29.7'
- '@babel/helpers@7.29.7'
- '@babel/parser@7.29.7'
- '@babel/template@7.29.7'
- '@babel/traverse@7.29.7'
- '@babel/types@7.29.7'
onlyBuiltDependencies:
- cwebp-bin
- esbuild
+1 -1
View File
@@ -19,7 +19,7 @@ const AVAILABLE_LOCALES = [
'sk',
'sv',
'tr',
'cz'
'cs'
] as Locales[];
// Static toast configuration - no need to recreate on every render
+1 -5
View File
@@ -13,11 +13,7 @@ import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';
import type { SvgIconProps } from '@mui/material';
export type OptionType =
| 'deleted'
| 'readonly'
| 'web_exclude'
| 'api_mqtt_exclude'
| 'favorite';
'deleted' | 'readonly' | 'web_exclude' | 'api_mqtt_exclude' | 'favorite';
type IconPair = [
React.ComponentType<SvgIconProps>,
@@ -396,7 +396,7 @@ const ApplicationSettings = () => {
margin="normal"
select
>
<MenuItem value="cz">Česky (CZ)</MenuItem>
<MenuItem value="cs">Česky (CS)</MenuItem>
<MenuItem value="de">Deutsch (DE)</MenuItem>
<MenuItem value="en">English (EN)</MenuItem>
<MenuItem value="fr">Français (FR)</MenuItem>
+67 -3
View File
@@ -12,6 +12,7 @@ import {
DialogActions,
DialogContent,
DialogTitle,
Grid,
MenuItem,
TextField,
Typography
@@ -39,7 +40,12 @@ import { formatLocalDateTime, updateValueDirty, useRest } from 'utils';
import { ValidationError, validate } from 'validators';
import { NTP_SETTINGS_VALIDATOR } from 'validators/ntp';
import { TIME_ZONES, selectedTimeZone, useTimeZoneSelectItems } from './TZ';
import {
TIME_ZONES,
selectedTimeZone,
timeZoneSelectItemsT,
useTimeZoneSelectItems
} from './TZ';
const NTPSettings = () => {
const {
@@ -63,13 +69,17 @@ const NTPSettings = () => {
// Memoized timezone select items for better performance
const timeZoneItems = useTimeZoneSelectItems();
const timeZoneItemsT = timeZoneSelectItemsT();
// Memoized selected timezone value
const selectedTzValue = useMemo(
() => (data ? selectedTimeZone(data.tz_label, data.tz_format) : undefined),
[data?.tz_label, data?.tz_format]
);
const selectedTzValueT = useMemo(
() => (data ? selectedTimeZone(data.tz_label_t, data.tz_format_t) : undefined),
[data?.tz_label_t, data?.tz_format_t]
);
const [localTime, setLocalTime] = useState<string>('');
const [settingTime, setSettingTime] = useState<boolean>(false);
const [processing, setProcessing] = useState<boolean>(false);
@@ -150,6 +160,18 @@ const NTPSettings = () => {
[updateFormValue]
);
const changeTimeZoneT = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
void updateState(readNTPSettings(), (settings: NTPSettingsType) => ({
...settings,
tz_label_t: event.target.value,
tz_format_t: TIME_ZONES[event.target.value]
}));
updateFormValue(event);
},
[updateFormValue]
);
// Memoize render content to prevent unnecessary re-renders
const renderContent = useMemo(() => {
if (!data) {
@@ -174,6 +196,7 @@ const NTPSettings = () => {
label={LL.NTP_SERVER()}
fullWidth
variant="outlined"
disabled={!data.enabled}
value={data.server}
onChange={updateFormValue}
margin="normal"
@@ -192,7 +215,47 @@ const NTPSettings = () => {
<MenuItem disabled>{LL.TIME_ZONE()}...</MenuItem>
{timeZoneItems}
</ValidatedTextField>
{data.enabled && (
<Grid container spacing={2} rowSpacing={0}>
<Grid>
<ValidatedTextField
fieldErrors={fieldErrors || {}}
name="thermostat_sync"
label="Sync EMS-Thermostat"
variant="outlined"
sx={{ width: '30ch' }}
value={data.thermostat_sync}
onChange={updateFormValue}
margin="normal"
select
>
<MenuItem value={0}>{LL.OFF()}</MenuItem>
<MenuItem value={1}>{LL.ON()}</MenuItem>
<MenuItem value={2}>
{LL.USE()} {LL.TIME_ZONE()}
</MenuItem>
</ValidatedTextField>
</Grid>
<Grid>
{data.thermostat_sync === 2 && (
<ValidatedTextField
fieldErrors={fieldErrors || {}}
name="tz_label_t"
label={LL.TIME_ZONE() + ' Thermostat'}
sx={{ width: '30ch' }}
variant="outlined"
value={selectedTzValueT}
onChange={changeTimeZoneT}
margin="normal"
select
>
<MenuItem disabled>{LL.TIME_ZONE()}...</MenuItem>
{timeZoneItemsT}
</ValidatedTextField>
)}
</Grid>
</Grid>
)}
<Box sx={{ display: 'flex', flexWrap: 'wrap' }}>
{!data.enabled && !dirtyFlags.length && (
<Box sx={{ flexWrap: 'nowrap', whiteSpace: 'nowrap' }}>
@@ -243,6 +306,7 @@ const NTPSettings = () => {
updateFormValue,
fieldErrors,
selectedTzValue,
selectedTzValueT,
changeTimeZone,
timeZoneItems,
dirtyFlags,
+4
View File
@@ -495,3 +495,7 @@ const precomputedTimeZoneItems = TIME_ZONE_LABELS.map((label) => (
export function timeZoneSelectItems() {
return precomputedTimeZoneItems;
}
export function timeZoneSelectItemsT() {
return precomputedTimeZoneItems;
}
@@ -28,7 +28,7 @@ interface LanguageOption {
}
const LANGUAGE_OPTIONS: LanguageOption[] = [
{ key: 'cz', flag: CZflag, label: 'CZ' },
{ key: 'cs', flag: CZflag, label: 'CS' },
{ key: 'de', flag: DEflag, label: 'DE' },
{ key: 'en', flag: GBflag, label: 'EN' },
{ key: 'fr', flag: FRflag, label: 'FR' },
@@ -1,6 +1,6 @@
import type { Translation } from '../i18n-types';
const cz: Translation = {
const cs: Translation = {
LANGUAGE: 'Jazyk',
RETRY: 'Zkusit znovu',
LOADING: 'Načítání',
@@ -368,4 +368,4 @@ const cz: Translation = {
};
export default cz;
export default cs;
+3
View File
@@ -16,6 +16,9 @@ export interface NTPSettingsType {
server: string;
tz_label: string;
tz_format: string;
thermostat_sync: number;
tz_label_t: string;
tz_format_t: string;
}
export interface Time {
+4
View File
@@ -81,6 +81,10 @@ class DummySettings {
// NTP
String server = "pool.ntp.org";
String tzLabel = "Europe/London";
String tzFormat = "GMT0BST,M3.5.0/1,M10.5.0";
String tzLabelT = "Europe/Berlin";
String tzFormatT = "CET-1CEST,M3.5.0,M10.5.0/3";
uint8_t thermostat_sync = 0;
static void read(DummySettings & settings, JsonObject root) {};
static void read(DummySettings & settings) {};
+3 -2
View File
@@ -2,6 +2,7 @@
"name": "mock-api",
"version": "3.8.2",
"description": "mock api for EMS-ESP",
"type": "module",
"author": "proddy, emsesp.org",
"license": "MIT",
"scripts": {
@@ -12,8 +13,8 @@
"@msgpack/msgpack": "^3.1.3",
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
"formidable": "^3.5.4",
"itty-router": "^5.0.23",
"prettier": "^3.8.3"
"itty-router": "^5.0.24",
"prettier": "^3.9.6"
},
"packageManager": "pnpm@10.33.4+sha512.1c67b3b359b2d408119ba1ed289f34b8fc3c6873412bec6fd264fbdc82489e510fcbecb9ce9d22dae7f3b76269d8441046014bdca53b9979cd7a561ad631b800"
}
+63 -63
View File
@@ -13,54 +13,54 @@ importers:
version: 3.1.3
'@trivago/prettier-plugin-sort-imports':
specifier: ^6.0.2
version: 6.0.2(prettier@3.8.3)
version: 6.0.2(prettier@3.9.6)
formidable:
specifier: ^3.5.4
version: 3.5.4
itty-router:
specifier: ^5.0.23
version: 5.0.23
specifier: ^5.0.24
version: 5.0.24
prettier:
specifier: ^3.8.3
version: 3.8.3
specifier: ^3.9.6
version: 3.9.6
packages:
'@babel/code-frame@7.29.0':
resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==}
'@babel/code-frame@7.29.7':
resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
engines: {node: '>=6.9.0'}
'@babel/generator@7.29.1':
resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==}
'@babel/generator@7.29.8':
resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==}
engines: {node: '>=6.9.0'}
'@babel/helper-globals@7.28.0':
resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
'@babel/helper-globals@7.29.7':
resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==}
engines: {node: '>=6.9.0'}
'@babel/helper-string-parser@7.27.1':
resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
'@babel/helper-string-parser@7.29.7':
resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==}
engines: {node: '>=6.9.0'}
'@babel/helper-validator-identifier@7.28.5':
resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
'@babel/helper-validator-identifier@7.29.7':
resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==}
engines: {node: '>=6.9.0'}
'@babel/parser@7.29.3':
resolution: {integrity: sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==}
'@babel/parser@7.29.8':
resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==}
engines: {node: '>=6.0.0'}
hasBin: true
'@babel/template@7.28.6':
resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==}
'@babel/template@7.29.7':
resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==}
engines: {node: '>=6.9.0'}
'@babel/traverse@7.29.0':
resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==}
'@babel/traverse@7.29.8':
resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==}
engines: {node: '>=6.9.0'}
'@babel/types@7.29.0':
resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
'@babel/types@7.29.8':
resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==}
engines: {node: '>=6.9.0'}
'@jridgewell/gen-mapping@0.3.13':
@@ -112,8 +112,8 @@ packages:
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
brace-expansion@2.1.0:
resolution: {integrity: sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==}
brace-expansion@2.1.4:
resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==}
debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
@@ -131,8 +131,8 @@ packages:
resolution: {integrity: sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==}
engines: {node: '>=14.0.0'}
itty-router@5.0.23:
resolution: {integrity: sha512-i49WU+SNPrwOZA4Z61En1RYd5h2Lcqa+5IvCpMrNi4dxymzJK15ozUUnRrWIUAv95Zamd4eJPAot2UvHRrQg7w==}
itty-router@5.0.24:
resolution: {integrity: sha512-PXij1qGKtE6jg3dLgrTRdh/Frovl5Wc4Av67sD2xfhDPrgNt4u79++/il8/c/OfZGkhD/8uYJub8tjo+H165rA==}
javascript-natural-sort@0.7.1:
resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==}
@@ -167,8 +167,8 @@ packages:
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
prettier@3.8.3:
resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==}
prettier@3.9.6:
resolution: {integrity: sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==}
engines: {node: '>=14'}
hasBin: true
@@ -177,52 +177,52 @@ packages:
snapshots:
'@babel/code-frame@7.29.0':
'@babel/code-frame@7.29.7':
dependencies:
'@babel/helper-validator-identifier': 7.28.5
'@babel/helper-validator-identifier': 7.29.7
js-tokens: 4.0.0
picocolors: 1.1.1
'@babel/generator@7.29.1':
'@babel/generator@7.29.8':
dependencies:
'@babel/parser': 7.29.3
'@babel/types': 7.29.0
'@babel/parser': 7.29.8
'@babel/types': 7.29.8
'@jridgewell/gen-mapping': 0.3.13
'@jridgewell/trace-mapping': 0.3.31
jsesc: 3.1.0
'@babel/helper-globals@7.28.0': {}
'@babel/helper-globals@7.29.7': {}
'@babel/helper-string-parser@7.27.1': {}
'@babel/helper-string-parser@7.29.7': {}
'@babel/helper-validator-identifier@7.28.5': {}
'@babel/helper-validator-identifier@7.29.7': {}
'@babel/parser@7.29.3':
'@babel/parser@7.29.8':
dependencies:
'@babel/types': 7.29.0
'@babel/types': 7.29.8
'@babel/template@7.28.6':
'@babel/template@7.29.7':
dependencies:
'@babel/code-frame': 7.29.0
'@babel/parser': 7.29.3
'@babel/types': 7.29.0
'@babel/code-frame': 7.29.7
'@babel/parser': 7.29.8
'@babel/types': 7.29.8
'@babel/traverse@7.29.0':
'@babel/traverse@7.29.8':
dependencies:
'@babel/code-frame': 7.29.0
'@babel/generator': 7.29.1
'@babel/helper-globals': 7.28.0
'@babel/parser': 7.29.3
'@babel/template': 7.28.6
'@babel/types': 7.29.0
'@babel/code-frame': 7.29.7
'@babel/generator': 7.29.8
'@babel/helper-globals': 7.29.7
'@babel/parser': 7.29.8
'@babel/template': 7.29.7
'@babel/types': 7.29.8
debug: 4.4.3
transitivePeerDependencies:
- supports-color
'@babel/types@7.29.0':
'@babel/types@7.29.8':
dependencies:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.28.5
'@babel/helper-string-parser': 7.29.7
'@babel/helper-validator-identifier': 7.29.7
'@jridgewell/gen-mapping@0.3.13':
dependencies:
@@ -246,17 +246,17 @@ snapshots:
dependencies:
'@noble/hashes': 1.8.0
'@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.8.3)':
'@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.9.6)':
dependencies:
'@babel/generator': 7.29.1
'@babel/parser': 7.29.3
'@babel/traverse': 7.29.0
'@babel/types': 7.29.0
'@babel/generator': 7.29.8
'@babel/parser': 7.29.8
'@babel/traverse': 7.29.8
'@babel/types': 7.29.8
javascript-natural-sort: 0.7.1
lodash-es: 4.18.1
minimatch: 9.0.9
parse-imports-exports: 0.2.4
prettier: 3.8.3
prettier: 3.9.6
transitivePeerDependencies:
- supports-color
@@ -264,7 +264,7 @@ snapshots:
balanced-match@1.0.2: {}
brace-expansion@2.1.0:
brace-expansion@2.1.4:
dependencies:
balanced-match: 1.0.2
@@ -283,7 +283,7 @@ snapshots:
dezalgo: 1.0.4
once: 1.4.0
itty-router@5.0.23: {}
itty-router@5.0.24: {}
javascript-natural-sort@0.7.1: {}
@@ -295,7 +295,7 @@ snapshots:
minimatch@9.0.9:
dependencies:
brace-expansion: 2.1.0
brace-expansion: 2.1.4
ms@2.1.3: {}
@@ -311,6 +311,6 @@ snapshots:
picocolors@1.1.1: {}
prettier@3.8.3: {}
prettier@3.9.6: {}
wrappy@1.0.2: {}
+3 -3
View File
@@ -141,8 +141,8 @@ let system_status = {
let DEV_VERSION_IS_UPGRADEABLE: boolean;
let STABLE_VERSION_IS_UPGRADEABLE: boolean;
let THIS_VERSION: string;
let LATEST_STABLE_VERSION = '3.8.2';
let LATEST_DEV_VERSION = '3.8.3-dev.2';
let LATEST_STABLE_VERSION = '3.8.3';
let LATEST_DEV_VERSION = '3.9.0-dev.0';
// scenarios for testing versioning
let version_test = 0; // on latest stable, or switch to dev
@@ -4139,7 +4139,7 @@ let emsesp_schedule = {
id: 5,
active: false,
flags: 130,
time: 'system/network info/rssi < -70',
time: 'system/network/rssi < -70',
cmd: 'system/restart',
value: '',
name: 'bad_wifi'
+2 -2
View File
@@ -39,7 +39,7 @@ build_flags =
-D CONFIG_ASYNC_TCP_PRIORITY=10 ; default
-D CONFIG_ASYNC_TCP_QUEUE_SIZE=64 ; default
-D CONFIG_ASYNC_TCP_RUNNING_CORE=1 ; force async_tcp task to be on same core as Arduino app (default is any core)
-D CONFIG_ASYNC_TCP_STACK_SIZE=6144 ; default is 16KB/8192*2
-D CONFIG_ASYNC_TCP_STACK_SIZE=8192 ; default is 16KB/8192*2
; ESPAsyncWebServer
; -D WS_MAX_QUEUED_MESSAGES=0 ; not used, default 8
; -D SSE_MAX_QUEUED_MESSAGES=1 ; for log messages, default 32
@@ -105,7 +105,7 @@ board_build.filesystem = littlefs
lib_deps =
bblanchon/ArduinoJson @ 7.4.3
ESP32Async/AsyncTCP @ 3.4.10
ESP32Async/ESPAsyncWebServer @ 3.11.0
ESP32Async/ESPAsyncWebServer @ 3.11.2
; https://github.com/emsesp/EMS-ESP-Modules.git @ 1.0.8
; builds the web interface only, not the firmware
-28
View File
@@ -88,34 +88,6 @@ def bin_copy(source, target, env):
print(f"MD5: {md5_hash}")
md5_file.write_text(md5_hash)
# Make a copy using the old 3.6.x filename format for backwards compatibility
# Note: there is a chance newer E32V2s (which use the 16MB partition table and PSRAM)
# are running a custom build of the 3.6.5 firmware as 3.6.5 was released before
# production of the gateway board. Updating via the WebUI will break the system
# and require a manual update.
pio_env = env.get('PIOENV', '')
extra_variant = None
if pio_env == "s3_16M_P":
extra_variant = f"EMS-ESP-{app_version.replace('.', '_')}-ESP32_S3"
elif pio_env == "s_4M":
extra_variant = f"EMS-ESP-{app_version.replace('.', '_')}-ESP32"
if extra_variant:
extra_bin_file = firmware_dir / f"{extra_variant}.bin"
extra_md5_file = firmware_dir / f"{extra_variant}.md5"
# Remove existing files if they exist
for file_path in [extra_bin_file, extra_md5_file]:
if file_path.exists():
file_path.unlink()
# Copy files
shutil.copy2(str(bin_file), str(extra_bin_file))
shutil.copy2(str(md5_file), str(extra_md5_file))
print(f"Filename copy for 3.6.x: {extra_bin_file}")
print("=" * 90)
+17 -11
View File
@@ -3,28 +3,34 @@
# run from root folder, like `sh ./scripts/update_all.sh`
# as well as GNUMake (make) and python3
# abort on first error so a failed lint/build isn't silently swallowed
set -e
cd interface
rm -rf node_modules
corepack use pnpm@latest-10
pnpm update --latest
corepack use pnpm@latest
pnpm update
pnpm install
pnpm format
pnpm lint
pnpm build-webUI
cd ../mock-api
rm -rf node_modules
corepack use pnpm@latest-10
pnpm update --latest
corepack use pnpm@latest
pnpm update
pnpm install
pnpm format
cd ..
cd interface
pnpm build-webUI
cd ..
npx cspell "**"
# platformio run -e build_modbus
# platformio run -e build_standalone
# platformio run -e native-test -t exec
# build files that go into docs folder
platformio run -e build_modbus -t clean
platformio run -e build_modbus
platformio run -e build_standalone -t clean
platformio run -e build_standalone
# run tests
platformio run -e native-test -t exec
+6
View File
@@ -90,6 +90,9 @@ void NTPSettings::read(NTPSettings & settings, JsonObject root) {
root["server"] = settings.server;
root["tz_label"] = settings.tzLabel;
root["tz_format"] = settings.tzFormat;
root["thermostat_sync"] = settings.thermostat_sync;
root["tz_label_t"] = settings.tzLabelT;
root["tz_format_t"] = settings.tzFormatT;
}
StateUpdateResult NTPSettings::update(JsonObject root, NTPSettings & settings) {
@@ -97,5 +100,8 @@ StateUpdateResult NTPSettings::update(JsonObject root, NTPSettings & settings) {
settings.server = root["server"] | FACTORY_NTP_SERVER;
settings.tzLabel = root["tz_label"] | FACTORY_NTP_TIME_ZONE_LABEL;
settings.tzFormat = root["tz_format"] | FACTORY_NTP_TIME_ZONE_FORMAT;
settings.thermostat_sync = root["thermostat_sync"] | FACTORY_NTP_THERMOSTAT_SYNC;
settings.tzLabelT = root["tz_label_t"] | FACTORY_NTP_TIME_ZONE_LABEL;
settings.tzFormatT = root["tz_format_t"] | FACTORY_NTP_TIME_ZONE_FORMAT;
return StateUpdateResult::CHANGED;
}
+7
View File
@@ -19,6 +19,10 @@
#define FACTORY_NTP_TIME_ZONE_FORMAT "GMT0BST,M3.5.0/1,M10.5.0"
#endif
#ifndef FACTORY_NTP_THERMOSTAT_SYNC
#define FACTORY_NTP_THERMOSTAT_SYNC 1
#endif
#ifndef FACTORY_NTP_SERVER
#define FACTORY_NTP_SERVER "time.google.com"
#endif
@@ -34,6 +38,9 @@ class NTPSettings {
String tzLabel = FACTORY_NTP_TIME_ZONE_LABEL;
String tzFormat = FACTORY_NTP_TIME_ZONE_FORMAT;
String server = FACTORY_NTP_SERVER;
uint8_t thermostat_sync = FACTORY_NTP_THERMOSTAT_SYNC;
String tzLabelT = FACTORY_NTP_TIME_ZONE_LABEL;
String tzFormatT = FACTORY_NTP_TIME_ZONE_FORMAT;
static void read(NTPSettings & settings, JsonObject root);
static StateUpdateResult update(JsonObject root, NTPSettings & settings);
+1 -1
View File
@@ -48,7 +48,7 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
// 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)) {
} else if ((extension == "bin") && (filesize > 1000000)) {
_is_firmware = true;
} else if (extension == "json") {
_md5[0] = '\0'; // clear md5
+6 -2
View File
@@ -15,7 +15,7 @@ void WiFiScanner::scanNetworks(AsyncWebServerRequest * request) {
if (WiFi.scanComplete() != -1) {
WiFi.scanDelete();
WiFi.scanNetworks(true);
WiFi.scanNetworks(true, false, true, 250);
}
}
@@ -38,6 +38,10 @@ void WiFiScanner::listNetworks(AsyncWebServerRequest * request) {
} else if (numNetworks == -1) {
request->send(202); // special code to indicate scan in progress
} else {
scanNetworks(request);
auto * response = new AsyncJsonResponse(false);
JsonObject root = response->getRoot();
root["networks"].to<JsonArray>();
response->setLength();
request->send(response);
}
}
+3 -1
View File
@@ -546,11 +546,13 @@ bool AnalogSensor::update(uint8_t gpio, const char * org_name, double offset, do
if (deleted) {
LOG_DEBUG("Removing analog sensor GPIO %02d", gpio);
EMSESP::system_.remove_gpio(gpio); // remove from used list only
if (EMSESP::nvs_.isKey(AnalogCustomization.name)) {
EMSESP::nvs_.remove(AnalogCustomization.name);
}
settings.analogCustomizations.remove(AnalogCustomization);
} else {
// update existing record
if (!strcmp(name, AnalogCustomization.name)) {
if (!strcmp(name, AnalogCustomization.name) && EMSESP::nvs_.isKey(AnalogCustomization.name)) {
EMSESP::nvs_.remove(AnalogCustomization.name);
}
strlcpy(AnalogCustomization.name, name, sizeof(AnalogCustomization.name));
+4 -3
View File
@@ -105,7 +105,7 @@
{215, DeviceType::THERMOSTAT, "Comfort RF", DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
{216, DeviceType::THERMOSTAT, "CRF200S", DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
{246, DeviceType::THERMOSTAT, "Comfort+2RF", DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
{253, DeviceType::THERMOSTAT, "Rego 3000, UI800, Logamatic BC400", DeviceFlags::EMS_DEVICE_FLAG_BC400}, // 0x10
{253, DeviceType::THERMOSTAT, "Rego 3000, UI800, Logamatic BC400", DeviceFlags::EMS_DEVICE_FLAG_UI800}, // 0x10
// Thermostat - Sieger - 0x10 / 0x17
{ 66, DeviceType::THERMOSTAT, "ES72, RC20", DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17 or remote
@@ -187,8 +187,9 @@
{ 74, DeviceType::ALERT, "EM10", DeviceFlags::EMS_DEVICE_FLAG_NONE},
// Gateways - 0x48
{17, DeviceType::GATEWAY, "MX400", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x48 and 0x4B
{189, DeviceType::GATEWAY, "KM200, MB LAN 2", DeviceFlags::EMS_DEVICE_FLAG_NONE},
{17, DeviceType::GATEWAY, "MX400", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x48, 0x4B, or 0x50 as wireless base
{189, DeviceType::GATEWAY, "KM200, MB LAN 2", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x48
{222, DeviceType::GATEWAY, "KM300", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x4A
{252, DeviceType::GATEWAY, "K30RF, MX300", DeviceFlags::EMS_DEVICE_FLAG_NONE},
// Generic - 0x40 or other with no product-id and no version
+1
View File
@@ -513,6 +513,7 @@ class EMSdevice {
static constexpr uint8_t EMS_DEVICE_FLAG_CR120 = 16; // mostly like RC300, but some changes
static constexpr uint8_t EMS_DEVICE_FLAG_CR11 = 17; // CRF200 only monitor
static constexpr uint8_t EMS_DEVICE_FLAG_HMC310 = 18;
static constexpr uint8_t EMS_DEVICE_FLAG_UI800 = 19;
uint8_t count_entities();
uint8_t count_entities_fav();
+1
View File
@@ -158,6 +158,7 @@ class DeviceValue {
enum DeviceValueNumOp : int8_t {
DV_NUMOP_NONE = 0, // default
DV_NUMOP_DIV2 = 2,
DV_NUMOP_DIV4 = 4,
DV_NUMOP_DIV10 = 10,
DV_NUMOP_DIV60 = 60,
DV_NUMOP_DIV100 = 100,
+23 -11
View File
@@ -1800,8 +1800,8 @@ void EMSESP::start() {
LOG_INFO("Library loaded: %d EMS devices, %d device entities, %s", device_library_.size(), EMSESP_TRANSLATION_COUNT, system_.languages_string().c_str());
webCustomizationService.begin(); // load the customizations
webSchedulerService.begin(); // load the scheduler events
webCustomEntityService.begin(); // load the custom telegram reads
webSchedulerService.begin(); // load the scheduler events
// start telnet service if it's enabled
// default idle is 10 minutes, default write timeout is 0 (automatic)
@@ -1864,16 +1864,9 @@ void EMSESP::loop() {
webLogService.loop(); // log in Web UI
// run the loop, unless we're in the middle of an OTA upload
if (EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_NORMAL || EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_INVALID_GPIO) {
// check for GPIO Errors - this is called once when booting
if (EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_INVALID_GPIO) {
static bool only_once = false;
if (!only_once) {
LOG_ERROR("Invalid GPIOs used. Please check your settings and the system log");
only_once = true;
}
}
// if (EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_NORMAL || EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_INVALID_GPIO) {
if (EMSESP::system_.systemStatus() != SYSTEM_STATUS::SYSTEM_STATUS_PENDING_UPLOAD
&& EMSESP::system_.systemStatus() != SYSTEM_STATUS::SYSTEM_STATUS_UPLOADING) {
// loop through the services
rxservice_.loop(); // process any incoming Rx telegrams
shower_.loop(); // check for shower on/off
@@ -1887,6 +1880,14 @@ void EMSESP::loop() {
}
scheduled_fetch_values(); // force a query on the EMS devices to fetch latest data at a set interval (1 min)
}
// check for GPIO Errors - this is called once when booting
if (EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_INVALID_GPIO) {
static bool only_once = false;
if (!only_once) {
LOG_ERROR("Invalid GPIOs used. Please check your settings and the system log");
only_once = true;
}
}
if (EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_PENDING_UPLOAD) {
// start an upload from a URL, assuming the URL exists and set from a previous pass
@@ -1899,6 +1900,17 @@ void EMSESP::loop() {
}
}
// reset status after 5 Minutes
if (EMSESP::system_.systemStatus() != SYSTEM_STATUS::SYSTEM_STATUS_NORMAL) {
static uint32_t starttime = 0;
if (starttime == 0) {
starttime = uuid::get_uptime_ms();
} else if (uuid::get_uptime_ms() - starttime > 300000) {
starttime = 0;
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_NORMAL);
}
}
// telnet service
#ifndef EMSESP_STANDALONE
if (system_.telnet_enabled()) {
+14 -1
View File
@@ -817,7 +817,7 @@ std::string Helpers::toUpper(std::string const & s) {
// capitalizes one UTF-8 character in char array
// works with Latin1 (1 byte), Polish and other (2 bytes) characters
// supports special characters for all 11 supported languages: EN, DE, NL, SV, PL, NO, FR, TR, IT, SK, CZ
// supports special characters for all 11 supported languages: EN, DE, NL, SV, PL, NO, FR, TR, IT, SK, CS
#if defined(EMSESP_STANDALONE)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits"
@@ -1033,4 +1033,17 @@ float Helpers::numericoperator2scalefactor(int8_t numeric_operator) {
return -numeric_operator;
}
int16_t Helpers::calc_dew(int16_t temp, uint8_t humi) {
if (humi == EMS_VALUE_UINT8_NOTSET || temp == EMS_VALUE_INT16_NOTSET) {
return EMS_VALUE_INT16_NOTSET;
}
const float k2 = 17.62;
const float k3 = 243.12;
const float t = (float)temp / 10;
const float h = (float)humi / 100;
int16_t dt = (10 * k3 * (((k2 * t) / (k3 + t)) + log(h)) / (((k2 * k3) / (k3 + t)) - log(h)));
return dt;
}
} // namespace emsesp
+1
View File
@@ -84,6 +84,7 @@ class Helpers {
static uint8_t count_items(const char * const * list);
static const char * translated_word(const char * const * strings, const bool force_en = false);
static int16_t calc_dew(int16_t temp, uint8_t hum);
#ifdef EMSESP_STANDALONE
static char * ultostr(char * ptr, uint32_t value, const uint8_t base);
+6 -1
View File
@@ -190,7 +190,11 @@ MAKE_NOTRANSLATION(rc100, "RC100")
MAKE_NOTRANSLATION(rc100h, "RC100H")
MAKE_NOTRANSLATION(tc100, "TC100")
MAKE_NOTRANSLATION(rc120rf, "RC120RF")
MAKE_NOTRANSLATION(rc220, "RC220/RT800")
MAKE_NOTRANSLATION(rc220, "RC220")
MAKE_NOTRANSLATION(rt800, "RT800")
MAKE_NOTRANSLATION(cr10, "CR10")
MAKE_NOTRANSLATION(cr10h, "CR10H")
MAKE_NOTRANSLATION(cr20rf, "CR20RF")
MAKE_NOTRANSLATION(single, "single")
MAKE_NOTRANSLATION(dash, "-")
MAKE_NOTRANSLATION(BLANK, "")
@@ -370,6 +374,7 @@ MAKE_ENUM(enum_roomsensor, FL_(extern), FL_(intern), FL_(auto))
MAKE_ENUM(enum_roominfluence, FL_(off), FL_(intern), FL_(extern), FL_(auto))
MAKE_ENUM(enum_control1, FL_(rc310), FL_(rc200), FL_(rc100), FL_(rc100h), FL_(tc100))
MAKE_ENUM(enum_control2, FL_(off), FL_(dash), FL_(rc100), FL_(rc100h), FL_(dash), FL_(rc120rf), FL_(rc220), FL_(single)) // BC400
MAKE_ENUM(enum_control3, FL_(off), FL_(dash), FL_(cr10), FL_(cr10h), FL_(dash), FL_(cr20rf), FL_(rt800), FL_(single)) // UI800
MAKE_ENUM(enum_switchmode, FL_(off), FL_(eco), FL_(comfort), FL_(heat))
MAKE_ENUM(enum_switchProgMode, FL_(level), FL_(absolute))
+6 -6
View File
@@ -30,9 +30,9 @@
#define EMSESP_LOCALE_TR "tr"
#define EMSESP_LOCALE_IT "it"
#define EMSESP_LOCALE_SK "sk"
#define EMSESP_LOCALE_CZ "cz"
#define EMSESP_LOCALE_CS "cs"
// IMPORTANT! translations are in the order: en, de, nl, sv, pl, no, fr, tr, it, sk, cz
// IMPORTANT! translations are in the order: en, de, nl, sv, pl, no, fr, tr, it, sk, cs
//
// if there is no translation, it will default to en
@@ -292,7 +292,7 @@ MAKE_WORD_TRANSLATION(curve, "heatingcurve", "Heizkurve", "stookkromme", "värme
MAKE_WORD_TRANSLATION(radiator, "radiator", "Heizkörper", "radiator", "Radiator", "grzejniki", "radiator", "radiateur", "radyatör", "radiatore", "radiátor", "radiátor")
MAKE_WORD_TRANSLATION(convector, "convector", "Konvektor", "convector", "Konvektor", "konwektory", "konvektor", "convecteur", "convector", "convettore", "konvektor", "konvektor")
MAKE_WORD_TRANSLATION(floor, "floor", "Fussboden", "vloer", "Golv", "podłoga", "gulv", "sol", "yer", "pavimento", "podlaha", "podlaha")
MAKE_WORD_TRANSLATION(roomflow, "roomflow", "Raum Fluß", "kamer doorstroming", "Rumsflöde", "przepływ w pomieszczeniu", "romstrøm", "flux de la pièce", "oda akışı", "flusso della stanza", "prúdenie miestnosti", "průtok mistnosti")
MAKE_WORD_TRANSLATION(roomflow, "roomflow", "Raum Fluss", "kamer doorstroming", "Rumsflöde", "przepływ w pomieszczeniu", "romstrøm", "flux de la pièce", "oda akışı", "flusso della stanza", "prúdenie miestnosti", "průtok mistnosti")
MAKE_WORD_TRANSLATION(roomload, "roomload", "Raum Bedarf", "kamer behoefte", "Rumsbehov", "zapotrzebowanie pomieszczenia", "rombelastning", "charge de la pièce", "oda yükü", "carico della stanza", "izbová zaťaž", "zatížení místnosti")
MAKE_WORD_TRANSLATION(summer, "summer", "Sommer", "zomer", "Sommar", "lato", "sommer", "été", "yaz", "estate", "leto", "léto")
MAKE_WORD_TRANSLATION(winter, "winter", "Winter", "winter", "Vinter", "zima", "vinter", "hiver", "kış", "inverno", "zima", "zima")
@@ -367,7 +367,7 @@ MAKE_WORD_TRANSLATION(bookshelf, "mdi:bookshelf", "mdi:bookshelf")
// MQTT Discovery - this is special device entity for 'climate'
MAKE_TRANSLATION(haclimate, "haclimate", "mqtt discovery current room temperature", "Discovery aktuelle Raumtemperatur", "Discovery huidige kamertemperatuur", "MQTT Discovery för aktuell rumstemperatur", "termostat w HA", "HA Avlest temp", "découverte mqtt température actuelle", "Güncel osa sıcaklığı", "verifica temperatura ambiente attuale", "mqtt discovery aktuálna teplota v miestnosti", "mqtt discovery aktuální pokojová teplota")
// Entity translations: tag, mqtt, en, de, nl, sv, pl, no, fr, tr, it, sk, cz
// Entity translations: tag, mqtt, en, de, nl, sv, pl, no, fr, tr, it, sk, cs
// Boiler
MAKE_TRANSLATION(chimneysweeper, "chimneysweeper", "chimney sweeper", "Schornsteinfeger", "schoorsteenveger", "Sotare", "tryb kominiarza", "feier", "ramoneur", "baca temizleyici", "spazzacamino", "kominár", "kominík")
MAKE_TRANSLATION(reset, "reset", "reset", "Reset", "Reset", "Återställ", "kasowanie komunikatu", "nullstill", "reset", "Sıfırla", "Reset", "reset", "reset")
@@ -826,8 +826,8 @@ MAKE_TRANSLATION(vacations7, "vacations7", "vacation dates 7", "Urlaubstage 7",
MAKE_TRANSLATION(vacations8, "vacations8", "vacation dates 8", "Urlaubstage 8", "Vakantiedagen 8", "Semesterdatum 8", "urlop 8", "feriedager 8", "dates vacances 8", "izin günleri 8", "date vacanze 8", "termíny dovolenky 8", "data prázdnin 8")
MAKE_TRANSLATION(absent, "absent", "absent", "Abwesend", "", "Frånvarande", "", "", "", "", "", "chýbajúci", "chybějící")
MAKE_TRANSLATION(redthreshold, "redthreshold", "reduction threshold", "Absenkschwelle", "", "Tröskel för sänkning", "", "", "", "", "", "zníženie tresholdu", "práh snížení")
MAKE_TRANSLATION(solarinfl, "solarinfl", "solar influence", "Solareinfluß", "", "", "", "", "", "", "", "slnečný vplyv", "sluneční vliv")
MAKE_TRANSLATION(currsolarinfl, "currsolarinfl", "current solar influence", "akt. Solareinfluß", "", "", "", "", "", "", "", "aktuálny slnečný vplyv", "aktuální sluneční vliv")
MAKE_TRANSLATION(solarinfl, "solarinfl", "solar influence", "Solareinfluss", "", "", "", "", "", "", "", "slnečný vplyv", "sluneční vliv")
MAKE_TRANSLATION(currsolarinfl, "currsolarinfl", "current solar influence", "akt. Solareinfluss", "", "", "", "", "", "", "", "aktuálny slnečný vplyv", "aktuální sluneční vliv")
MAKE_TRANSLATION(hpmode, "hpmode", "HP Mode", "WP-Modus", "Modus warmtepomp", "Värmepumpsläge", "tryb pracy pompy ciepła", "", "", "yüksek güç modu", "Modalità Termopompa", "Režim TČ", "režim tepelného čerpadla")
MAKE_TRANSLATION(dewoffset, "dewoffset", "dew point offset", "Taupunktdifferenz", "Offset dauwpunt", "Daggpunktsförskjutning", "przesunięcie punktu rosy", "", "", "çiğ noktası göreli", "differenza del punto di rugiada", "posun rosného bodu", "offset rosného bodu")
MAKE_TRANSLATION(roomtempdiff, "roomtempdiff", "room temp difference", "Raumtemperaturdifferenz", "Verschiltemperatuur kamertemp", "Rumstemperaturskillnad", "różnica temp. pomieszczenia", "", "", "oda sıcaklığı farkı", "differenza temperatura ambiente", "rozdiel izbovej teploty", "rozdíl teploty místnosti")
+13 -19
View File
@@ -300,6 +300,14 @@ const std::initializer_list<Modbus::EntityModbusInfo> Modbus::modbus_register_ma
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DEVICE_DATA, FL_(heatingPID), 74, 1), // heatingpid
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DEVICE_DATA, FL_(preheating), 75, 1), // preheating
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DEVICE_DATA, FL_(vacations), 76, 13), // vacations
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DEVICE_DATA, FL_(hpoperatingmode), 89, 1), // hpoperatingmode
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DEVICE_DATA, FL_(summertemp), 90, 1), // summertemp
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DEVICE_DATA, FL_(instantstart), 91, 1), // instantstart
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DEVICE_DATA, FL_(coolstart), 92, 1), // coolstart
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DEVICE_DATA, FL_(heatondelay), 93, 1), // heatondelay
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DEVICE_DATA, FL_(heatoffdelay), 94, 1), // heatoffdelay
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DEVICE_DATA, FL_(coolondelay), 95, 1), // coolondelay
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DEVICE_DATA, FL_(cooloffdelay), 96, 1), // cooloffdelay
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(selRoomTemp), 0, 1), // seltemp
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(roomTemp), 1, 1), // currtemp
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(haclimate), 2, 1), // haclimate
@@ -349,12 +357,12 @@ const std::initializer_list<Modbus::EntityModbusInfo> Modbus::modbus_register_ma
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(remotehum), 46, 1), // remotehum
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(heatondelay), 47, 1), // heatondelay
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(heatoffdelay), 48, 1), // heatoffdelay
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(instantstart), 49, 1), // instantstart
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(boost), 50, 1), // boost
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(boosttime), 51, 1), // boosttime
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(coolondelay), 49, 1), // coolondelay
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(cooloffdelay), 50, 1), // cooloffdelay
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(instantstart), 51, 1), // instantstart
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(coolstart), 52, 1), // coolstart
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(coolondelay), 53, 1), // coolondelay
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(cooloffdelay), 54, 1), // cooloffdelay
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(boost), 53, 1), // boost
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(boosttime), 54, 1), // boosttime
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(switchProgMode), 55, 1), // switchprogmode
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(redthreshold), 56, 1), // redthreshold
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(solarinfl), 57, 1), // solarinfl
@@ -629,20 +637,6 @@ const std::initializer_list<Modbus::EntityModbusInfo> Modbus::modbus_register_ma
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(wwDiffTemp), 13, 1), // difftemp
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(wwRedTemp), 14, 1), // redtemp
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(wwRequiredTemp), 15, 1), // requiredtemp
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(wwStorageTemp1), 16, 1), // storagetemp1
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(wwColdTemp), 17, 1), // coldtemp
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(wwTemp5), 18, 1), // temp5
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(retTemp), 19, 1), // rettemp
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(wwHotTemp), 20, 1), // hottemp
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(wwDailyTemp), 21, 1), // dailytemp
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(wwCircTc), 22, 1), // circtc
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(wwKeepWarm), 23, 1), // keepwarm
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(wwStatus2), 24, 1), // status2
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(wwPumpMod), 25, 1), // pumpmod
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(wwFlow), 26, 1), // flow
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(valveReturn), 27, 1), // valvereturn
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(deltaTRet), 28, 1), // deltatret
REGISTER_MAPPING(dt::WATER, TAG_TYPE_DHW, FL_(errorDisp), 29, 1), // errordisp
};
} // namespace emsesp
+8 -17
View File
@@ -377,18 +377,22 @@ void Roomctrl::temperature(uint8_t addr, uint8_t dst, uint8_t hc) {
// send telegram 0x047B only for RC100H
void Roomctrl::humidity(uint8_t addr, uint8_t dst, uint8_t hc) {
int16_t dew = Helpers::calc_dew(remotetemp_[hc], remotehum_[hc]);
int8_t dew8 = EMS_VALUE_INT8_NOTSET;
if (dew != EMS_VALUE_INT16_NOTSET) {
dew8 = static_cast<int8_t>((dew >= 0 ? dew + 5 : dew - 5) / 10);
}
uint8_t data[11];
data[0] = addr | EMSbus::ems_mask();
data[1] = dst & 0x7F;
uint16_t dew = calc_dew(remotetemp_[hc], remotehum_[hc]);
data[2] = 0xFF;
data[3] = 0;
data[4] = 3;
data[5] = 0x7B + hc;
data[6] = dew == EMS_VALUE_INT16_NOTSET ? EMS_VALUE_INT8_NOTSET : (uint8_t)((dew + 5) / 10);
data[6] = static_cast<uint8_t>(dew8);
data[7] = remotehum_[hc];
data[8] = (uint8_t)(dew << 8);
data[9] = (uint8_t)(dew & 0xFF);
data[8] = static_cast<uint8_t>(dew >> 8);
data[9] = static_cast<uint8_t>(dew & 0x00FF);
data[10] = EMSbus::calculate_crc(data, 10); // append CRC
EMSuart::transmit(data, 11);
}
@@ -436,17 +440,4 @@ void Roomctrl::replyF7(uint8_t addr, uint8_t dst, uint8_t offset, uint8_t typehh
EMSuart::transmit(data, 10);
}
int16_t Roomctrl::calc_dew(int16_t temp, uint8_t humi) {
if (humi == EMS_VALUE_UINT8_NOTSET || temp == EMS_VALUE_INT16_NOTSET) {
return EMS_VALUE_INT16_NOTSET;
}
const float k2 = 17.62;
const float k3 = 243.12;
const float t = (float)temp / 10;
const float h = (float)humi / 100;
int16_t dt = (10 * k3 * (((k2 * t) / (k3 + t)) + log(h)) / (((k2 * k3) / (k3 + t)) - log(h)));
return dt;
}
} // namespace emsesp
-1
View File
@@ -50,7 +50,6 @@ class Roomctrl {
static void nack_write();
static void ack_write();
static void replyF7(uint8_t addr, uint8_t dst, uint8_t offset, uint8_t typehh, uint8_t typeh, uint8_t typel, uint8_t hc);
static int16_t calc_dew(int16_t temp, uint8_t hum);
static bool switch_off_[HCS];
static uint32_t send_time_[HCS];
+17 -13
View File
@@ -39,17 +39,8 @@ std::deque<Token> exprToTokens(const std::string & expr) {
i += (*p == '{') ? 1 : (*p == '}') ? -1 : 0;
++p;
}
if (*p) {
++p;
}
// Use string_view to avoid unnecessary string copies
std::string_view s(b, p - b);
auto n = s.find("\"\"");
while (n != std::string_view::npos) {
s.remove_prefix(n + 2);
n = s.find("\"\"");
}
tokens.emplace_back(Token::Type::String, std::string(s), -3);
const auto s = std::string(b, p);
tokens.emplace_back(Token::Type::String, s, -3);
if (*p == '\0') {
--p;
}
@@ -333,7 +324,10 @@ std::deque<Token> shuntingYard(const std::deque<Token> & tokens) {
// check if string is a number
bool isnum(const std::string & s) {
if (!s.empty() && (s.find_first_not_of("0123456789.") == std::string::npos || (s[0] == '-' && s.find_first_not_of("0123456789.", 1) == std::string::npos))) {
if (s.empty() || s.find_first_of("0123456789") == std::string::npos) {
return false;
}
if (s.find_first_not_of("0123456789.") == std::string::npos || (s[0] == '-' && s.find_first_not_of("0123456789.", 1) == std::string::npos)) {
return true;
}
return false;
@@ -636,6 +630,10 @@ std::string calculate(const std::string & expr) {
stack.push_back(lhs + rhs);
break;
}
if (!isnum(rhs) || !isnum(lhs)) {
stack.push_back(lhs + token.str + rhs);
break;
}
auto lhd = std::stod(lhs);
auto rhd = std::stod(rhs);
switch (token.str[0]) {
@@ -700,7 +698,6 @@ std::string compute(const std::string & expr) {
std::string cmd = expr_new.substr(f, e - f).c_str();
JsonDocument doc;
if (DeserializationError::Ok == deserializeJson(doc, cmd)) {
HTTPClient * http = new HTTPClient;
std::string url, header_s, value_s, method_s, key_s, keys_s;
// search keys lower case
for (JsonPair p : doc.as<JsonObject>()) {
@@ -720,6 +717,12 @@ std::string compute(const std::string & expr) {
keys_s = p.key().c_str();
}
}
if (url.substr(0, 4) == "http") { // match http and https
HTTPClient * http = new HTTPClient;
#ifndef EMSESP_STANDALONE
http->setConnectTimeout(10000);
http->setTimeout(10000);
#endif
if (http->begin(url.c_str())) {
int httpResult = 0;
for (JsonPair p : doc[header_s].as<JsonObject>()) {
@@ -770,6 +773,7 @@ std::string compute(const std::string & expr) {
expr_new.replace(f, e - f, result.c_str());
}
http->end();
}
delete http;
}
}
+20 -24
View File
@@ -30,7 +30,7 @@
#include <HTTPClient.h>
#include <map>
#include "shuntingYard.h" // for compute() used by the message
#include "EMSESP_Version.h"
#if defined(EMSESP_TEST)
@@ -61,7 +61,7 @@ const char * const languages[] = {EMSESP_LOCALE_EN,
EMSESP_LOCALE_TR,
EMSESP_LOCALE_IT,
EMSESP_LOCALE_SK,
EMSESP_LOCALE_CZ};
EMSESP_LOCALE_CS};
#endif
static constexpr uint8_t NUM_LANGUAGES = sizeof(languages) / sizeof(const char *);
@@ -222,22 +222,10 @@ bool System::command_message(const char * value, const int8_t id, JsonObject out
LOG_WARNING("Message is empty");
return false; // must have a string value
}
EMSESP::webSchedulerService.computed_value.clear();
EMSESP::webSchedulerService.raw_value = value;
for (uint16_t wait = 0; wait < 2000 && !EMSESP::webSchedulerService.raw_value.empty(); wait++) {
delay(1);
}
if (EMSESP::webSchedulerService.computed_value.empty()) {
LOG_WARNING("Message result is empty");
return false;
}
LOG_INFO("Message: %s", EMSESP::webSchedulerService.computed_value.c_str()); // send to log
Mqtt::queue_publish(F_(message), EMSESP::webSchedulerService.computed_value); // send to MQTT if enabled
output["api_data"] = EMSESP::webSchedulerService.computed_value; // send to API
std::string computed_value = compute(value);
LOG_INFO("Message: %s", computed_value.c_str()); // send to log
Mqtt::queue_publish(F_(message), computed_value); // send to MQTT if enabled
output["api_data"] = computed_value; // send to API
return true;
}
@@ -1964,7 +1952,9 @@ bool System::get_value_info(JsonObject output, const char * cmd) {
LOG_ERROR("empty system command");
return false;
}
if (!strcmp(cmd, "restart")) { // restart is a command, not an entity
return false;
}
// check for hardcoded "info"/"value"
if (!strcmp(cmd, F_(info)) || !strcmp(cmd, F_(values))) {
return command_info("", 0, output);
@@ -3034,18 +3024,24 @@ bool System::uploadFirmwareURL(const char * url) {
return false; // error
}
// the Content-Length from the response header, -1 if the server didn't send one.
int firmware_size = http.getSize();
if (firmware_size <= 0) {
LOG_ERROR("Firmware upload failed - unknown size");
http.end();
return false; // error
}
// check we have a valid size
if (firmware_size < 2097152) { // 2MB or greater is required
LOG_ERROR("Firmware upload failed - invalid size");
// catch a wrong URL early, before streaming. Smallest shipped image is ~1.9MB
if (firmware_size < 1677721) { // 1.6MB
LOG_ERROR("Firmware upload failed - too small (%d KB)", firmware_size / 1024);
http.end();
return false; // error
}
// check we have enough space for the upload in the ota partition
if (!Update.begin(firmware_size)) {
LOG_ERROR("Firmware upload failed - no space");
LOG_ERROR("Firmware upload failed - %s", Update.errorString());
http.end();
return false; // error
}
@@ -3062,7 +3058,7 @@ bool System::uploadFirmwareURL(const char * url) {
// get tcp stream and send it to Updater
WiFiClient * stream = http.getStreamPtr();
if (Update.writeStream(*stream) != firmware_size) {
if (Update.writeStream(*stream) != (size_t)firmware_size) {
LOG_ERROR("Firmware upload failed - size differences");
http.end();
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_ERROR_UPLOAD);
+7 -7
View File
@@ -161,9 +161,9 @@ void RxService::add(uint8_t * data, uint8_t length) {
}
if (data[0] != EMSuart::last_tx_src()) { // do not count echos as errors
telegram_error_count_++;
LOG_WARNING("Incomplete Rx: %s", Helpers::data_to_hex(data, length).c_str()); // include CRC
LOG_WARNING("Incomplete Rx: %s (crc: %02X)", Helpers::data_to_hex(data, length).c_str(), crc); // include CRC
} else {
LOG_TRACE("Incomplete Rx: %s", Helpers::data_to_hex(data, length).c_str()); // include CRC
LOG_TRACE("Incomplete Rx: %s (crc: %02X)", Helpers::data_to_hex(data, length).c_str(), crc); // include CRC
}
return;
}
@@ -276,6 +276,7 @@ void TxService::start() {
// sends a 1 byte poll which is our own deviceID
void TxService::send_poll() const {
// LOG_DEBUG("Ack %02X",ems_bus_id() ^ ems_mask());
// if (tx_mode() != EMS_TXMODE_OFF && ems_bus_id() != 0x0D) { // use 0x0D for tests without poll-Ack
if (tx_mode() != EMS_TXMODE_OFF) {
EMSuart::send_poll(ems_bus_id() ^ ems_mask());
}
@@ -572,12 +573,11 @@ bool TxService::send_raw(const char * telegram_data) {
return false;
}
// since the telegram data is a const, make a copy. add 1 to grab the \0 EOS
char telegram[strlen(telegram_data) + 1];
strlcpy(telegram, telegram_data, sizeof(telegram));
// since the telegram data is a const, make a copy
char * telegram = strdup(telegram_data);
uint8_t count = 0;
uint8_t data[2 + strlen(telegram) / 3];
uint8_t data[256]; // max raw telegram length
// get values
char * p = strtok(telegram, " ,"); // delimiter
@@ -585,7 +585,7 @@ bool TxService::send_raw(const char * telegram_data) {
data[count++] = (uint8_t)strtol(p, 0, 16);
p = strtok(nullptr, " ,");
}
free(telegram);
// check valid length
if (count < 4) {
return false;
+94 -15
View File
@@ -45,7 +45,8 @@ Connect::Connect(uint8_t device_type, uint8_t device_id, uint8_t product_id, con
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(0xDB65, "Roomschedule", true, MAKE_PF_CB(process_roomSchedule));
register_telegram_type(0x0B65, "Roomschedule", true, MAKE_PF_CB(process_roomSchedule));
register_telegram_type(0xF7, "MenuConfig", false, MAKE_PF_CB(process_roomConfig));
// 0x2040, broadcast 36 bytes:
// data: 0E 60 00 DF 0D AF 0A 46 0A 46 02 9A 1C 53 1C 53 12 AD 12 AD 00 00 13 C2
// data: 1F 37 1F 37 00 00 00 00 18 97 11 27 (offset 24)
@@ -88,11 +89,12 @@ void Connect::process_RCTime(std::shared_ptr<const Telegram> telegram) {
void Connect::register_device_values_room(std::shared_ptr<Connect::RoomCircuit> room) {
auto tag = DeviceValueTAG::TAG_SRC1 + room->room();
register_device_value(tag, &room->temp_, DeviceValueType::INT16, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(roomTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &room->humidity_, DeviceValueType::INT8, FL_(airHumidity), DeviceValueUOM::PERCENT);
register_device_value(tag, &room->humidity_, DeviceValueType::UINT8, FL_(airHumidity), DeviceValueUOM::PERCENT);
register_device_value(tag, &room->dewtemp_, DeviceValueType::INT16, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(dewTemperature), DeviceValueUOM::DEGREES);
register_device_value(
tag, &room->seltemp_, DeviceValueType::UINT8, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(selRoomTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_seltemp), 5, 30);
register_device_value(tag, &room->mode_, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode));
// register_device_value(tag, &room->coolmode_, DeviceValueType::BOOL, FL_(coolingOn), DeviceValueUOM::NONE, MAKE_CF_CB(set_coolmode));
register_device_value(tag, &room->name_, DeviceValueType::STRING, FL_(name), DeviceValueUOM::NONE, MAKE_CF_CB(set_name));
register_device_value(tag, &room->childlock_, DeviceValueType::BOOL, FL_(childlock), DeviceValueUOM::NONE, MAKE_CF_CB(set_childlock));
register_device_value(tag, &room->icon_, DeviceValueType::ENUM, FL_(enum_icons), FL_(icon), DeviceValueUOM::NONE, MAKE_CF_CB(set_icon));
@@ -133,16 +135,8 @@ void Connect::process_roomThermostat(std::shared_ptr<const Telegram> telegram) {
if (!Mqtt::ha_enabled() || (Helpers::hasValue(rc->mode_) && Helpers::hasValue(rc->icon_))) {
has_update(telegram, rc->seltemp_, 3);
}
// calculate dew temperature
if (rc->humidity_ >= 0 && rc->humidity_ <= 100) {
const float k2 = 17.62;
const float k3 = 243.12;
const float t = (float)rc->temp_ / 10;
const float h = (float)rc->humidity_ / 100;
int16_t dt = (10 * k3 * (((k2 * t) / (k3 + t)) + log(h)) / (((k2 * k3) / (k3 + t)) - log(h)));
has_update(rc->dewtemp_, dt);
}
has_update(rc->dewtemp_, Helpers::calc_dew(rc->temp_, rc->humidity_));
}
// gateway(0x48) W gateway(0x50), ?(0x0B42), data: 01 // icon in offset 0
@@ -168,11 +162,33 @@ void Connect::process_roomThermostatSettings(std::shared_ptr<const Telegram> tel
if (rc == nullptr) {
return;
}
has_enumupdate(telegram, rc->mode_, 0, {3, 1, 0}); // modes off, manual auto
// has_enumupdate(telegram, rc->mode_, 0, {3, 1, 0}); // modes off, manual auto
// has_update(telegram, rc->mode_, 0); // modes: auto, heat, cool, off
// has_update(telegram, rc->tempautotemp_, 1); // FF means off
// has_update(telegram, rc->manualtemp_, 3);
// has_update(telegram, rc->coolmode_, 4); // 01-cooling, 00-heating
// has_update(telegram, rc->coolautotemp_, 5);
// has_update(telegram, rc->cooltemp_, 6);
has_update(telegram, rc->childlock_, 7);
uint8_t mh = 0xFF;
uint8_t mc = 0xFF;
telegram->read_value(mh, 0);
telegram->read_value(mc, 4);
if (mc == 3) {
rc->coolmode_ = 1;
rc->mode_ = 0;
} else if (mh == 3) {
rc->coolmode_ = 0;
rc->mode_ = 0;
} else if (mc == 1) {
rc->coolmode_ = 1;
rc->mode_ = 1;
} else if (mh == 1) {
rc->coolmode_ = 0;
rc->mode_ = 1;
} else {
rc->mode_ = 2;
}
}
// unknown telegrams, needs fetch
@@ -203,6 +219,53 @@ void Connect::process_roomSchedule(std::shared_ptr<const Telegram> telegram) {
toggle_fetch(telegram->type_id, false); // fetch only once if all is initialized
}
void Connect::process_roomConfig(std::shared_ptr<const Telegram> telegram) {
if (telegram->offset == 0 && telegram->message_length > 3) {
uint16_t t = 0;
telegram->read_value(t, 1);
if (t >= 0x0AB5 && t <= 0x0AB5 + 15) {
auto rc = room_circuit(t - 0x0AB5);
if (rc == nullptr) {
return;
}
uint8_t bits = telegram->message_data[3];
if (rc->mode_ == 2) {
if (bits & 0x02) {
rc->coolmode_ = 0;
} else if (bits & 0x20) {
rc->coolmode_ = 1;
}
}
/*
switch (bits & 0x6A) {
case 0: // cooling off
rc->mode_ = 0;
rc->coolmode_ = 1;
break;
case 0x40: // manual cooling or heating off
rc->mode_ = 1;
rc->coolmode_ = 1;
break;
case 0x20: // auto cooling
rc->mode_ = 2;
rc->coolmode_ = 1;
break;
case 0x48: // manual heating
case 0x08: // manual heating
rc->mode_ = 1;
rc->coolmode_ = 0;
break;
case 0x42: // auto heating
case 0x02: // auto heating
rc->mode_ = 2;
rc->coolmode_ = 0;
break;
}
*/
}
}
}
// Settings:
bool Connect::set_mode(const char * value, const int8_t id) {
@@ -216,7 +279,7 @@ bool Connect::set_mode(const char * value, const int8_t id) {
return false;
}
}
write_command(0xBB5 + rc->room(), 0, v); // no validate, mode change is broadcasted
write_command(0xBB5 + rc->room(), rc->coolmode_ == 1 ? 4 : 0, v); // no validate, mode change is broadcasted
return true;
}
@@ -226,10 +289,13 @@ bool Connect::set_seltemp(const char * value, const int8_t id) {
return false;
}
float v;
if (Helpers::value2float(value, v)) {
if (Helpers::value2temperature(value, v)) {
// depends on mode, auto (2 for enum_mode2, 0 for enum_mode8) set in offset 1
if (rc->coolmode_ == 1) {
write_command(0xBB5 + rc->room(), rc->mode_ == 2 ? 5 : 6, v == -1 ? 0xFF : uint8_t(v * 2));
} else {
write_command(0xBB5 + rc->room(), rc->mode_ == 2 ? 1 : 3, v == -1 ? 0xFF : uint8_t(v * 2));
// write_command(0xBB5 + rc->room(), rc->mode_ == 0 ? 1 : 3, v == -1 ? 0xFF : uint8_t(v * 2));
}
return true;
}
return false;
@@ -257,6 +323,19 @@ bool Connect::set_name(const char * value, const int8_t id) {
return true;
}
bool Connect::set_coolmode(const char * value, const int8_t id) {
auto rc = room_circuit(id - DeviceValueTAG::TAG_SRC1);
if (rc == nullptr) {
return false;
}
bool b;
if (Helpers::value2bool(value, b)) {
write_command(0xBB5 + rc->room(), 4, b ? 1 : 0, 0xBB5 + rc->room());
return true;
}
return false;
}
bool Connect::set_childlock(const char * value, const int8_t id) {
auto rc = room_circuit(id - DeviceValueTAG::TAG_SRC1);
if (rc == nullptr) {
+6 -1
View File
@@ -34,15 +34,18 @@ class Connect : public EMSdevice {
}
~RoomCircuit() = default;
int16_t temp_;
int8_t humidity_;
uint8_t humidity_;
uint8_t seltemp_;
uint8_t mode_;
char name_[51];
int16_t dewtemp_;
uint8_t childlock_;
uint8_t icon_;
uint8_t coolmode_;
// uint8_t tempautotemp_;
// uint8_t manualtemp_;
// uint8_t coolautotemp_;
// uint8_t cooltemp_;
uint8_t room() {
return room_;
@@ -62,9 +65,11 @@ class Connect : public EMSdevice {
void process_roomThermostatParam(std::shared_ptr<const Telegram> telegram);
void process_roomThermostatData(std::shared_ptr<const Telegram> telegram);
void process_roomSchedule(std::shared_ptr<const Telegram> telegram);
void process_roomConfig(std::shared_ptr<const Telegram> telegram);
bool set_mode(const char * value, const int8_t id);
bool set_seltemp(const char * value, const int8_t id);
bool set_name(const char * value, const int8_t id);
bool set_coolmode(const char * value, const int8_t id);
bool set_childlock(const char * value, const int8_t id);
bool set_icon(const char * value, const int8_t id);
+254 -80
View File
@@ -175,7 +175,9 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(set_typeids[i], "RC300Set", false, MAKE_PF_CB(process_RC300Set), 29);
register_telegram_type(summer_typeids[i], "RC300Summer", false, MAKE_PF_CB(process_RC300Summer), 14);
register_telegram_type(curve_typeids[i], "RC300Curves", false, MAKE_PF_CB(process_RC300Curve), 9);
register_telegram_type(summer2_typeids[i], "RC300Summer2", false, MAKE_PF_CB(process_RC300Summer2), 8);
if (model != EMSdevice::EMS_DEVICE_FLAG_UI800) {
register_telegram_type(summer2_typeids[i], "RC300Sumr2", false, MAKE_PF_CB(process_RC300Summer2), 8);
}
}
const size_t set2_size = set2_typeids.size();
for (uint8_t i = 0; i < set2_size; i++) {
@@ -207,7 +209,9 @@ 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(0xBF, "ErrorMessage", false, MAKE_PF_CB(process_ErrorMessageBF));
register_telegram_type(0xC0, "RCErrorMessage", false, MAKE_PF_CB(process_RCErrorMessage2));
register_telegram_type(0x470, "RC300Summer2", true, MAKE_PF_CB(process_RC300Summer2), 8);
if (model == EMSdevice::EMS_DEVICE_FLAG_UI800) {
register_telegram_type(0x470, "RC300Summer3", true, MAKE_PF_CB(process_RC300Summer3), 8);
}
EMSESP::send_read_request(0xC0, device_id, 0, 20); // read last errorcode on start (only published on errors)
// JUNKERS/HT3
@@ -543,7 +547,7 @@ uint8_t Thermostat::HeatingCircuit::get_mode() const {
} else {
return HeatingCircuit::Mode::OFF;
}
} else if (model == EMSdevice::EMS_DEVICE_FLAG_BC400 || model == EMSdevice::EMS_DEVICE_FLAG_CR120) {
} else if (model == EMSdevice::EMS_DEVICE_FLAG_BC400 || model == EMSdevice::EMS_DEVICE_FLAG_UI800 || model == EMSdevice::EMS_DEVICE_FLAG_CR120) {
if (mode_new == 0) {
return HeatingCircuit::Mode::OFF;
} else if (mode_new == 1) {
@@ -607,7 +611,7 @@ uint8_t Thermostat::HeatingCircuit::get_mode_type() const {
return HeatingCircuit::Mode::ON;
}
} else if (model == EMSdevice::EMS_DEVICE_FLAG_RC300 || model == EMSdevice::EMS_DEVICE_FLAG_R3000 || model == EMSdevice::EMS_DEVICE_FLAG_BC400
|| model == EMSdevice::EMS_DEVICE_FLAG_HMC310) {
|| model == EMSdevice::EMS_DEVICE_FLAG_UI800 || model == EMSdevice::EMS_DEVICE_FLAG_HMC310) {
if (modetype == 0) {
return HeatingCircuit::Mode::ECO;
} else if (modetype == 1) {
@@ -806,16 +810,16 @@ void Thermostat::process_RemoteTemp(std::shared_ptr<const Telegram> telegram) {
// e.g. "38 10 FF 00 03 7B 08 24 00 4B"
void Thermostat::process_RemoteHumidity(std::shared_ptr<const Telegram> telegram) {
// has_update(telegram, dewtemperature_, 0); // this is int8
has_update(telegram, humidity_, 1);
has_update(telegram, dewtemperature_, 2); // this is int16
// some thermostats use short telegram with int8 dewpoint, https://github.com/emsesp/EMS-ESP32/issues/1491
if (telegram->offset == 0 && telegram->message_length < 4) {
int8_t dew = dewtemperature_ / 10;
telegram->read_value(dew, 0);
if (dew != EMS_VALUE_INT8_NOTSET && dewtemperature_ != dew * 10) {
dewtemperature_ = dew * 10;
has_update(dewtemperature_);
}
// but it's not a dewpoint in offset 0, removed, see https://github.com/emsesp/EMS-ESP32/issues/3135
has_update(telegram, humidity_, 1);
// has_update(telegram, dewtemperature_, 2); // this is int16
int16_t dew = EMS_VALUE_INT16_NOTSET;
if (telegram->read_value(dew, 2)) {
has_update(dewtemperature_, dew);
} else if (telegram->offset == 0 && telegram->message_length < 4) {
dew = Helpers::calc_dew(tempsensor1_, humidity_);
has_update(dewtemperature_, dew);
}
}
@@ -1264,19 +1268,26 @@ void Thermostat::process_RC300Summer(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, hc->comfortPointTemp, 12);
}
// type 0x470, only BC400/UI800
// (0x470), data: 01 0E 01 01 02 17 04 48
void Thermostat::process_RC300Summer3(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, hpoperatingmode, 0);
has_update(telegram, summertemp, 1);
has_update(telegram, heatondelay, 2);
has_update(telegram, heatoffdelay, 3);
has_update(telegram, instantstart, 4);
has_update(telegram, coolstart, 5);
has_update(telegram, coolondelay, 6);
has_update(telegram, cooloffdelay, 7);
}
// types 0x471 ff summer2_typeids
// (0x473), data: 00 11 04 01 01 1C 08 04
void Thermostat::process_RC300Summer2(std::shared_ptr<const Telegram> telegram) {
auto hc = heating_circuit(telegram);
if (hc == nullptr) {
// 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) {
has_update(telegram, hc->summersetmode, 0);
has_update(hc->hpoperatingmode, EMS_VALUE_UINT8_NOTSET);
@@ -1334,7 +1345,7 @@ void Thermostat::process_RC300WWmode(std::shared_ptr<const Telegram> telegram) {
// circulation pump see: https://github.com/Th3M3/buderus_ems-wiki/blob/master/Einstellungen%20der%20Bedieneinheit%20RC310.md
has_update(telegram, dhw->wwCircPump_, 1); // FF=off, 0=on ?
if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310) {
if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400 || model() == EMSdevice::EMS_DEVICE_FLAG_UI800 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310) {
has_enumupdate(telegram, dhw->wwMode_, 2, {0, 5, 1, 2, 4});
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_R3000) {
// https://github.com/emsesp/EMS-ESP32/pull/1722#discussion_r1582823521
@@ -1455,14 +1466,21 @@ void Thermostat::process_HPMode(std::shared_ptr<const Telegram> telegram) {
}
// 0x467 ff HP settings
// thermostat(0x10) -W-> Me(0x0B), ?(0x0467), data: 0A 15 00 01 04 (from #1187)
// thermostat(0x10) W me(0x0B), HPSet(0x0467), data: 14 13 02 01 02 (from #3144)
void Thermostat::process_HPSet(std::shared_ptr<const Telegram> telegram) {
auto hc = heating_circuit(telegram);
if (hc == nullptr) {
return;
}
has_update(telegram, hc->dewoffset, 4); // 7-35°C
if (hc->control == 3 || hc->control == 6) { // control with humidity
has_update(telegram, hc->hpminflowtemp, 0); // 7-35°C
} else {
has_update(telegram, hc->hpminflowtemp, 1); // 7-35°C
}
// has_update(telegram, hc->roomtempoffset, 2); // 1-10K // not implemented, mentioned in #3144
has_update(telegram, hc->roomtempdiff, 3); // 1-10K
has_update(telegram, hc->hpminflowtemp, 0); // 2-10K
has_update(telegram, hc->dewoffset, 4); // 2-10K
}
// type 0x41 - data from the RC30 thermostat(0x10) - 14 bytes long
@@ -1721,6 +1739,15 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
// check clock
time_t now = time(nullptr);
bool sync = false;
// change to thermostat timezone if different
EMSESP::esp32React.getNTPSettingsService()->read([&](const NTPSettings & settings) {
sync = settings.thermostat_sync != 0;
if (settings.thermostat_sync == 2) {
setenv("TZ", settings.tzFormatT.c_str(), 1);
tzset();
}
});
tm * tm_ = localtime(&now);
bool tset_ = tm_->tm_year > 110; // year 2010 and up, time is valid
tm_->tm_year = (telegram->message_data[0] & 0x7F) + 100; // IVT
@@ -1739,19 +1766,26 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
has_update(dateTime_, newdatetime, sizeof(dateTime_));
bool ivtclock = (telegram->message_data[0] & 0x80) == 0x80; // dont sync ivt-clock, #439
bool junkersclock = model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS;
time_t ttime = mktime(tm_); // thermostat time
tm_->tm_isdst = -1; // determine dst
time_t ttime = mktime(tm_); // make thermostat time
// change back emsesp timezone
EMSESP::esp32React.getNTPSettingsService()->read([&](const NTPSettings & settings) {
if (settings.thermostat_sync == 2) {
setenv("TZ", settings.tzFormat.c_str(), 1);
tzset();
}
});
// correct thermostat clock if we have valid ntp time, and could write the command
if (!ivtclock && !junkersclock && tset_ && EMSESP::system_.ntp_connected() && !EMSESP::system_.readonly_mode() && has_command(&dateTime_)) {
double difference = difftime(now, ttime);
if (sync && !ivtclock && tset_ && EMSESP::system_.ntp_connected() && !EMSESP::system_.readonly_mode() && has_command(&dateTime_)) {
int difference = difftime(now, ttime);
if (difference > 15 || difference < -15) {
if (setTimeRetry < 3) {
if (!use_dst) {
set_datetime("ntp", 0); // set from NTP without dst
LOG_INFO("thermostat time correction from ntp, ignoring dst");
LOG_INFO("thermostat time correction %d seconds from ntp, ignoring dst", difference);
} else {
set_datetime("ntp", -1); // set from NTP
LOG_INFO("thermostat time correction from ntp");
LOG_INFO("thermostat time correction %d seconds from ntp", difference);
}
setTimeRetry++;
}
@@ -1761,10 +1795,6 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
}
#ifndef EMSESP_STANDALONE
if (!tset_ && tm_->tm_year > 110) { // emsesp clock not set, but thermostat clock
if (ivtclock) {
tm_->tm_isdst = -1; // determine dst
ttime = mktime(tm_); // thermostat time
}
struct timeval newnow = {.tv_sec = ttime, .tv_usec = 0};
#if CONFIG_IDF_TARGET_ESP32C3
// unknown how to set time on C3
@@ -1915,7 +1945,11 @@ bool Thermostat::set_hpminflowtemp(const char * value, const int8_t id) {
}
int v;
if (Helpers::value2temperature(value, v)) {
if (hc->control == 3 || hc->control == 6) { // remotes with humidity
write_command(hp_typeids[hc->hc()], 0, v, hp_typeids[hc->hc()]);
} else {
write_command(hp_typeids[hc->hc()], 1, v, hp_typeids[hc->hc()]);
}
return true;
}
return false;
@@ -2355,7 +2389,7 @@ bool Thermostat::set_control(const char * value, const int8_t id) {
}
// BC400
// 1-RC100, 2-RC100H, 3-RC200
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400) {
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400 || model() == EMSdevice::EMS_DEVICE_FLAG_UI800) {
if (Helpers::value2enum(value, ctrl, FL_(enum_control2))) {
write_command(hpmode_typeids[hc->hc()], 3, ctrl);
hc->control = ctrl; // set in advance, dont wait for verify
@@ -2435,7 +2469,7 @@ bool Thermostat::set_wwmode(const char * value, const int8_t id) {
return false;
}
write_command(0xB0, 2, set, 0xB0);
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310) {
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400 || model() == EMSdevice::EMS_DEVICE_FLAG_UI800 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310) {
if (!Helpers::value2enum(value, set, FL_(enum_wwMode4), {0, 5, 1, 2, 4})) { // off, eco+, eco, comfort, auto
return false;
}
@@ -2590,30 +2624,36 @@ bool Thermostat::set_cooling(const char * value, const int8_t id) {
// set cooling delays
bool Thermostat::set_coolondelay(const char * value, const int8_t id) {
float f;
if (!Helpers::value2float(value, f)) {
return false;
}
if (model() == EMSdevice::EMS_DEVICE_FLAG_UI800) {
write_command(0x470, 6, (uint8_t)(f * 4), 0x470);
return true;
}
auto hc = heating_circuit(id);
if (hc == nullptr) {
return false;
}
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
write_command(summer2_typeids[hc->hc()], 6, v, summer2_typeids[hc->hc()]);
write_command(summer2_typeids[hc->hc()], 6, (uint8_t)f, summer2_typeids[hc->hc()]);
return true;
}
bool Thermostat::set_cooloffdelay(const char * value, const int8_t id) {
float f;
if (!Helpers::value2float(value, f)) {
return false;
}
if (model() == EMSdevice::EMS_DEVICE_FLAG_UI800) {
write_command(0x470, 7, (uint8_t)(f * 4), 0x470);
return true;
}
auto hc = heating_circuit(id);
if (hc == nullptr) {
return false;
}
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
write_command(summer2_typeids[hc->hc()], 7, v, summer2_typeids[hc->hc()]);
write_command(summer2_typeids[hc->hc()], 7, (uint8_t)f, summer2_typeids[hc->hc()]);
return true;
}
@@ -3038,6 +3078,15 @@ bool Thermostat::set_datetime(const char * value, const int8_t id) {
if (dt == "ntp") {
time_t now = time(nullptr);
tm * tm_ = localtime(&now);
EMSESP::esp32React.getNTPSettingsService()->read([&](const NTPSettings & settings) {
if (settings.thermostat_sync == 2) {
setenv("TZ", settings.tzFormatT.c_str(), 1);
tzset();
tm_ = localtime(&now);
setenv("TZ", settings.tzFormat.c_str(), 1);
tzset();
}
});
if (tm_->tm_year < 110) { // no valid time
return false;
}
@@ -3053,11 +3102,7 @@ bool Thermostat::set_datetime(const char * value, const int8_t id) {
data[5] = tm_->tm_sec;
data[6] = (tm_->tm_wday + 6) % 7; // Bosch counts from Mo, time from Su
data[7] = (id == 0) ? 2 : tm_->tm_isdst + 2; // set DST and flag for ext. clock
if (model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
data[6]++; // Junkers use 1-7;
data[7] = 0;
}
} else if (dt.length() == 23) {
} else if (dt.length() == 23 || dt.length() == 21) {
data[0] = (dt[7] - '0') * 100 + (dt[8] - '0') * 10 + (dt[9] - '0'); // year
data[1] = (dt[3] - '0') * 10 + (dt[4] - '0'); // month
data[2] = (dt[11] - '0') * 10 + (dt[12] - '0'); // hour
@@ -3065,10 +3110,35 @@ bool Thermostat::set_datetime(const char * value, const int8_t id) {
data[4] = (dt[14] - '0') * 10 + (dt[15] - '0'); // min
data[5] = (dt[17] - '0') * 10 + (dt[18] - '0'); // sec
data[6] = (dt[20] - '0'); // day of week, Mo:0
data[7] = (dt[22] - '0') + 2; // DST and flag
if (model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
data[7] = 0;
data[7] = dt.length() == 21 ? 2 : (dt[22] - '0') + 2; // DST and flag
} else if (dt.length() == 19 || dt.length() == 16) {
time_t now = time(nullptr);
tm * tm_ = localtime(&now);
data[0] = (dt[7] - '0') * 100 + (dt[8] - '0') * 10 + (dt[9] - '0'); // year
tm_->tm_year = 100 + data[0];
data[1] = (dt[3] - '0') * 10 + (dt[4] - '0'); // month
tm_->tm_mon = data[1] - 1;
tm_->tm_hour = data[2] = (dt[11] - '0') * 10 + (dt[12] - '0'); // hour
tm_->tm_mday = data[3] = (dt[0] - '0') * 10 + (dt[1] - '0'); // day
tm_->tm_min = data[4] = (dt[14] - '0') * 10 + (dt[15] - '0'); // min
tm_->tm_sec = data[5] = dt.length() == 16 ? 0 : (dt[17] - '0') * 10 + (dt[18] - '0'); // sec
tm_->tm_isdst = -1;
// use thermostat time zone to determine day of week and daylight saving
EMSESP::esp32React.getNTPSettingsService()->read([&](const NTPSettings & settings) {
if (settings.thermostat_sync == 2) {
setenv("TZ", settings.tzFormatT.c_str(), 1);
tzset();
auto t = mktime(tm_);
tm_ = localtime(&t);
setenv("TZ", settings.tzFormat.c_str(), 1);
tzset();
} else {
auto t = mktime(tm_);
tm_ = localtime(&t);
}
});
data[6] = (tm_->tm_wday + 6) % 7; // Bosch counts from Mo, time from Su
data[7] = tm_->tm_isdst + 2; // set DST and flag for ext. clock
} else {
LOG_WARNING("Set date: invalid data, wrong length");
return false;
@@ -3078,6 +3148,11 @@ bool Thermostat::set_datetime(const char * value, const int8_t id) {
return false;
}
if (model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
data[6]++; // Junkers use 1-7 for day of the week
data[7] = 0; // no dst setting
}
// LOG_INFO("Setting date and time: %02d.%02d.2%03d-%02d:%02d:%02d-%d-%d", data[3], data[1], data[0], data[2], data[4], data[5], data[6], data[7]);
write_command(EMS_TYPE_time, 0, data, 8, EMS_TYPE_time);
@@ -3142,6 +3217,7 @@ bool Thermostat::set_mode(const char * value, const int8_t id) {
mode_list = FL_(enum_mode3);
break;
case EMSdevice::EMS_DEVICE_FLAG_BC400:
case EMSdevice::EMS_DEVICE_FLAG_UI800:
case EMSdevice::EMS_DEVICE_FLAG_CR120:
mode_list = FL_(enum_mode2);
break;
@@ -3279,6 +3355,7 @@ bool Thermostat::set_mode_n(const uint8_t mode, const int8_t id) {
offset = EMS_OFFSET_RC35Set_mode;
break;
case EMSdevice::EMS_DEVICE_FLAG_BC400:
case EMSdevice::EMS_DEVICE_FLAG_UI800:
case EMSdevice::EMS_DEVICE_FLAG_CR120:
offset = EMS_OFFSET_RCPLUSSet_mode_new;
break;
@@ -3318,7 +3395,7 @@ bool Thermostat::set_mode_n(const uint8_t mode, const int8_t id) {
// set hc->mode temporary until validate is received
if (model_ == EMSdevice::EMS_DEVICE_FLAG_RC10) {
hc->mode = set_mode_value >> 1;
} else if (model_ == EMSdevice::EMS_DEVICE_FLAG_BC400 || model_ == EMSdevice::EMS_DEVICE_FLAG_CR120) {
} else if (model_ == EMSdevice::EMS_DEVICE_FLAG_BC400 || model_ == EMSdevice::EMS_DEVICE_FLAG_UI800 || model_ == EMSdevice::EMS_DEVICE_FLAG_CR120) {
hc->mode_new = set_mode_value;
} else if (model_ == EMSdevice::EMS_DEVICE_FLAG_RC300 || model_ == EMSdevice::EMS_DEVICE_FLAG_R3000 || model_ == EMSdevice::EMS_DEVICE_FLAG_HMC310
|| model_ == EMSdevice::EMS_DEVICE_FLAG_RC100) {
@@ -3335,13 +3412,19 @@ bool Thermostat::set_mode_n(const uint8_t mode, const int8_t id) {
// sets the thermostat summermode for RC300
bool Thermostat::set_summermode(const char * value, const int8_t id) {
uint8_t set;
if (model() == EMSdevice::EMS_DEVICE_FLAG_UI800) {
if (Helpers::value2enum(value, set, FL_(enum_hpoperatingmode))) {
write_command(0x470, 0, set, 0x470);
return true;
}
return false;
}
auto hc = heating_circuit(id);
if (hc == nullptr) {
return false;
}
uint8_t set;
if (is_received(summer2_typeids[hc->hc()])) {
if ((hc->statusbyte & 1) && Helpers::value2enum(value, set, FL_(enum_summermode))) {
write_command(summer2_typeids[hc->hc()], 0, set, summer2_typeids[hc->hc()]);
@@ -3487,40 +3570,52 @@ bool Thermostat::set_boosttime(const char * value, const int8_t id) {
}
bool Thermostat::set_heatondelay(const char * value, const int8_t id) {
float f;
if (!Helpers::value2float(value, f)) {
return false;
}
if (model() == EMSdevice::EMS_DEVICE_FLAG_UI800) {
write_command(0x470, 2, (uint8_t)(f * 4), 0x470);
return true;
}
auto hc = heating_circuit(id);
if (hc == nullptr) {
return false;
}
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
write_command(summer2_typeids[hc->hc()], 2, (uint8_t)v, summer2_typeids[hc->hc()]);
write_command(summer2_typeids[hc->hc()], 2, (uint8_t)f, summer2_typeids[hc->hc()]);
return true;
}
bool Thermostat::set_heatoffdelay(const char * value, const int8_t id) {
float f;
if (!Helpers::value2float(value, f)) {
return false;
}
if (model() == EMSdevice::EMS_DEVICE_FLAG_UI800) {
write_command(0x470, 3, (uint8_t)(f * 4), 0x470);
return true;
}
auto hc = heating_circuit(id);
if (hc == nullptr) {
return false;
}
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
write_command(summer2_typeids[hc->hc()], 3, (uint8_t)v, summer2_typeids[hc->hc()]);
write_command(summer2_typeids[hc->hc()], 3, (uint8_t)f, summer2_typeids[hc->hc()]);
return true;
}
bool Thermostat::set_instantstart(const char * value, const int8_t id) {
auto hc = heating_circuit(id);
if (hc == nullptr) {
return false;
}
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
if (model() == EMSdevice::EMS_DEVICE_FLAG_UI800) {
write_command(0x470, 4, (uint8_t)v, 0x470);
return true;
}
auto hc = heating_circuit(id);
if (hc == nullptr) {
return false;
}
write_command(summer2_typeids[hc->hc()], 4, (uint8_t)v, summer2_typeids[hc->hc()]);
return true;
}
@@ -4045,6 +4140,10 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
validate_typeid = set_typeids[hc->hc()];
switch (mode) {
case HeatingCircuit::Mode::SUMMER:
if (model == EMSdevice::EMS_DEVICE_FLAG_UI800) {
write_command(0x470, 1, temperature, 0x470);
return true;
}
if (is_received(summer2_typeids[hc->hc()])) {
offset = 0x01;
set_typeid = summer2_typeids[hc->hc()];
@@ -4056,6 +4155,10 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
factor = 1;
break;
case HeatingCircuit::Mode::COOLSTART:
if (model == EMSdevice::EMS_DEVICE_FLAG_UI800) {
write_command(0x470, 5, temperature, 0x470);
return true;
}
offset = 5;
set_typeid = summer2_typeids[hc->hc()];
validate_typeid = set_typeid;
@@ -4144,7 +4247,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
if (model == EMSdevice::EMS_DEVICE_FLAG_CR120 && mode_ == HeatingCircuit::Mode::MANUAL) {
offset = 22; // manual offset CR120
} else if (mode_ == HeatingCircuit::Mode::MANUAL) {
offset = 10; // manual offset
offset = hc->hpoperatingstate == 2 ? 17 : 10; // cooling or manual offset
} else {
offset = 8; // auto offset
// special case to reactivate auto temperature, see #737, #746
@@ -4443,6 +4546,7 @@ void Thermostat::register_device_values() {
case EMSdevice::EMS_DEVICE_FLAG_RC300:
case EMSdevice::EMS_DEVICE_FLAG_R3000:
case EMSdevice::EMS_DEVICE_FLAG_BC400:
case EMSdevice::EMS_DEVICE_FLAG_UI800:
case EMSdevice::EMS_DEVICE_FLAG_CR120:
case EMSdevice::EMS_DEVICE_FLAG_HMC310:
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
@@ -4560,6 +4664,70 @@ void Thermostat::register_device_values() {
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &pvLowerCool_, DeviceValueType::INT8, FL_(pvLowerCool), DeviceValueUOM::K, MAKE_CF_CB(set_pvLowerCool), -5, 0);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &absent_, DeviceValueType::BOOL, FL_(absent), DeviceValueUOM::NONE, MAKE_CF_CB(set_absent));
if (model() == EMSdevice::EMS_DEVICE_FLAG_UI800) {
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&hpoperatingmode,
DeviceValueType::ENUM,
FL_(enum_hpoperatingmode),
FL_(hpoperatingmode),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_summermode));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&summertemp,
DeviceValueType::UINT8,
FL_(summertemp),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_summertemp),
10,
30);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&instantstart,
DeviceValueType::UINT8,
FL_(instantstart),
DeviceValueUOM::K,
MAKE_CF_CB(set_instantstart),
1,
10);
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &coolstart, DeviceValueType::UINT8, FL_(coolstart), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_coolstart), 20, 35);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&heatondelay,
DeviceValueType::UINT8,
DeviceValueNumOp::DV_NUMOP_DIV4,
FL_(heatondelay),
DeviceValueUOM::HOURS,
MAKE_CF_CB(set_heatondelay),
1,
48);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&heatoffdelay,
DeviceValueType::UINT8,
DeviceValueNumOp::DV_NUMOP_DIV4,
FL_(heatoffdelay),
DeviceValueUOM::HOURS,
MAKE_CF_CB(set_heatoffdelay),
1,
48);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&coolondelay,
DeviceValueType::UINT8,
DeviceValueNumOp::DV_NUMOP_DIV4,
FL_(coolondelay),
DeviceValueUOM::HOURS,
MAKE_CF_CB(set_coolondelay),
1,
48);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&cooloffdelay,
DeviceValueType::UINT8,
DeviceValueNumOp::DV_NUMOP_DIV4,
FL_(cooloffdelay),
DeviceValueUOM::HOURS,
MAKE_CF_CB(set_cooloffdelay),
1,
48);
}
break;
case EMSdevice::EMS_DEVICE_FLAG_RC10:
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
@@ -4902,9 +5070,10 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
case EMSdevice::EMS_DEVICE_FLAG_RC300:
case EMSdevice::EMS_DEVICE_FLAG_R3000:
case EMSdevice::EMS_DEVICE_FLAG_BC400:
case EMSdevice::EMS_DEVICE_FLAG_UI800:
case EMSdevice::EMS_DEVICE_FLAG_CR120:
case EMSdevice::EMS_DEVICE_FLAG_HMC310:
if (model == EMSdevice::EMS_DEVICE_FLAG_BC400 || model == EMSdevice::EMS_DEVICE_FLAG_CR120) {
if (model == EMSdevice::EMS_DEVICE_FLAG_BC400 || model == EMSdevice::EMS_DEVICE_FLAG_UI800 || model == EMSdevice::EMS_DEVICE_FLAG_CR120) {
register_device_value(tag, &hc->mode_new, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode));
} else {
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode));
@@ -4997,6 +5166,8 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
register_device_value(tag, &hc->hpminflowtemp, DeviceValueType::UINT8, FL_(hpminflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_hpminflowtemp));
if (model == EMSdevice::EMS_DEVICE_FLAG_BC400) {
register_device_value(tag, &hc->control, DeviceValueType::ENUM, FL_(enum_control2), FL_(control), DeviceValueUOM::NONE, MAKE_CF_CB(set_control));
} else if (model == EMSdevice::EMS_DEVICE_FLAG_UI800) {
register_device_value(tag, &hc->control, DeviceValueType::ENUM, FL_(enum_control3), FL_(control), DeviceValueUOM::NONE, MAKE_CF_CB(set_control));
} else {
register_device_value(tag, &hc->control, DeviceValueType::ENUM, FL_(enum_control1), FL_(control), DeviceValueUOM::NONE, MAKE_CF_CB(set_control));
}
@@ -5012,14 +5183,16 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
101);
register_device_value(tag, &hc->remotehum, DeviceValueType::CMD, FL_(remotehum), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_remotehum), -1, 101);
}
if (model != EMSdevice::EMS_DEVICE_FLAG_UI800) {
register_device_value(tag, &hc->heatondelay, DeviceValueType::UINT8, FL_(heatondelay), DeviceValueUOM::HOURS, MAKE_CF_CB(set_heatondelay), 1, 48);
register_device_value(tag, &hc->heatoffdelay, DeviceValueType::UINT8, FL_(heatoffdelay), DeviceValueUOM::HOURS, MAKE_CF_CB(set_heatoffdelay), 1, 48);
register_device_value(tag, &hc->instantstart, DeviceValueType::UINT8, FL_(instantstart), DeviceValueUOM::K, MAKE_CF_CB(set_instantstart), 1, 10);
register_device_value(tag, &hc->boost, DeviceValueType::BOOL, FL_(boost), DeviceValueUOM::NONE, MAKE_CF_CB(set_boost));
register_device_value(tag, &hc->boosttime, DeviceValueType::UINT8, FL_(boosttime), DeviceValueUOM::HOURS, MAKE_CF_CB(set_boosttime));
register_device_value(tag, &hc->coolstart, DeviceValueType::UINT8, FL_(coolstart), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_coolstart), 20, 35);
register_device_value(tag, &hc->coolondelay, DeviceValueType::UINT8, FL_(coolondelay), DeviceValueUOM::HOURS, MAKE_CF_CB(set_coolondelay), 1, 48);
register_device_value(tag, &hc->cooloffdelay, DeviceValueType::UINT8, FL_(cooloffdelay), DeviceValueUOM::HOURS, MAKE_CF_CB(set_cooloffdelay), 1, 48);
register_device_value(tag, &hc->instantstart, DeviceValueType::UINT8, FL_(instantstart), DeviceValueUOM::K, MAKE_CF_CB(set_instantstart), 1, 10);
register_device_value(tag, &hc->coolstart, DeviceValueType::UINT8, FL_(coolstart), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_coolstart), 20, 35);
}
register_device_value(tag, &hc->boost, DeviceValueType::BOOL, FL_(boost), DeviceValueUOM::NONE, MAKE_CF_CB(set_boost));
register_device_value(tag, &hc->boosttime, DeviceValueType::UINT8, FL_(boosttime), DeviceValueUOM::HOURS, MAKE_CF_CB(set_boosttime));
register_device_value(tag,
&hc->switchProgMode,
DeviceValueType::ENUM,
@@ -5037,8 +5210,8 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
MAKE_CF_CB(set_redthreshold),
12,
22);
register_device_value(tag, &hc->solarInfl, DeviceValueType::UINT8, FL_(solarinfl), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_solarinfl), -5, -1);
register_device_value(tag, &hc->currSolarInfl, DeviceValueType::UINT8, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(currsolarinfl), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->solarInfl, DeviceValueType::INT8, FL_(solarinfl), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_solarinfl), -5, 0);
register_device_value(tag, &hc->currSolarInfl, DeviceValueType::INT8, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(currsolarinfl), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->heatingpid, DeviceValueType::ENUM, FL_(enum_PID), FL_(heatingPID), DeviceValueUOM::NONE, MAKE_CF_CB(set_heatingpid));
register_device_value(tag, &hc->pumpopt, DeviceValueType::BOOL, FL_(pumpopt), DeviceValueUOM::NONE, MAKE_CF_CB(set_pumpopt));
register_device_value(tag,
@@ -5359,9 +5532,10 @@ void Thermostat::register_device_values_dhw(std::shared_ptr<Thermostat::DhwCircu
case EMSdevice::EMS_DEVICE_FLAG_RC300:
case EMSdevice::EMS_DEVICE_FLAG_R3000:
case EMSdevice::EMS_DEVICE_FLAG_BC400:
case EMSdevice::EMS_DEVICE_FLAG_UI800:
case EMSdevice::EMS_DEVICE_FLAG_CR120:
case EMSdevice::EMS_DEVICE_FLAG_HMC310:
if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310) {
if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400 || model() == EMSdevice::EMS_DEVICE_FLAG_UI800 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310) {
register_device_value(tag, &dhw->wwMode_, DeviceValueType::ENUM, FL_(enum_wwMode4), FL_(wwMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwmode));
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_R3000) {
register_device_value(tag, &dhw->wwMode_, DeviceValueType::ENUM, FL_(enum_wwMode5), FL_(wwMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwmode));
+12 -1
View File
@@ -241,7 +241,7 @@ class Thermostat : public EMSdevice {
// check to see if the thermostat is a hybrid of the R300
inline bool isRC300() const {
return (model() == EMSdevice::EMS_DEVICE_FLAG_RC300 || model() == EMSdevice::EMS_DEVICE_FLAG_R3000 || model() == EMSdevice::EMS_DEVICE_FLAG_BC400
|| model() == EMSdevice::EMS_DEVICE_FLAG_CR120 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310);
|| model() == EMSdevice::EMS_DEVICE_FLAG_CR120 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310 || model() == EMSdevice::EMS_DEVICE_FLAG_UI800);
}
inline uint8_t id2dhw(const int8_t id) const { // returns telegram offset for TAG(id)
@@ -296,6 +296,16 @@ class Thermostat : public EMSdevice {
uint8_t absent_;
uint8_t hasSolar_;
// BC400/UI800 telegram 0x470
uint8_t hpoperatingmode;
uint8_t summertemp;
uint8_t heatondelay;
uint8_t heatoffdelay;
uint8_t instantstart;
uint8_t coolstart;
uint8_t coolondelay;
uint8_t cooloffdelay;
// HybridHP
uint8_t hybridStrategy_; // co2 = 1, cost = 2, temperature = 3, mix = 4
int8_t switchOverTemp_; // degrees
@@ -451,6 +461,7 @@ class Thermostat : public EMSdevice {
void process_RC300Set2(std::shared_ptr<const Telegram> telegram);
void process_RC300Summer(std::shared_ptr<const Telegram> telegram);
void process_RC300Summer2(std::shared_ptr<const Telegram> telegram);
void process_RC300Summer3(std::shared_ptr<const Telegram> telegram);
void process_RC300WWmode(std::shared_ptr<const Telegram> telegram);
void process_RC300WWmode2(std::shared_ptr<const Telegram> telegram);
void process_RC300WWtemp(std::shared_ptr<const Telegram> telegram);
+39 -38
View File
@@ -28,9 +28,41 @@ Water::Water(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
dhw_ = device_id - EMSdevice::EMS_DEVICE_ID_DHW1;
int8_t tag = DeviceValueTAG::TAG_DHW1 + dhw_;
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM100) { // device_id 0x2A, DHW3
// telegram handlers
if (flags == EMSdevice::EMS_DEVICE_FLAG_IPM) {
dhw_ = 0;
tag = DeviceValueTAG::TAG_DHW1;
register_telegram_type(0x34, "UBAMonitorWW", false, MAKE_PF_CB(process_IPMMonitorWW));
register_telegram_type(0x1E, "HydrTemp", false, MAKE_PF_CB(process_IPMHydrTemp));
register_telegram_type(0x33, "UBAParameterWW", true, MAKE_PF_CB(process_IPMParameterWW), 12);
// register_telegram_type(0x10D, "wwNTCStatus", false, MAKE_PF_CB(process_wwNTCStatus));
// device values...
register_device_value(tag, &wwSelTemp_, DeviceValueType::UINT8, FL_(wwSelTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwSelTemp));
register_device_value(tag, &wwTemp_, DeviceValueType::UINT16, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &wwTemp2_, DeviceValueType::UINT16, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwCurTemp2), DeviceValueUOM::DEGREES);
register_device_value(tag, &HydrTemp_, DeviceValueType::UINT16, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(hydrTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &wwPump_, DeviceValueType::BOOL, FL_(wwPump), DeviceValueUOM::NONE);
register_device_value(tag, &wwFlowTempOffset_, DeviceValueType::UINT8, FL_(wwFlowTempOffset), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwFlowTempOffset));
register_device_value(tag, &wwHystOn_, DeviceValueType::INT8, FL_(wwHystOn), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwHystOn));
register_device_value(tag, &wwHystOff_, DeviceValueType::INT8, FL_(wwHystOff), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwHystOff));
register_device_value(tag, &wwDisinfectionTemp_, DeviceValueType::UINT8, FL_(wwDisinfectionTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwDisinfectionTemp));
register_device_value(tag, &wwCirc_, DeviceValueType::BOOL, FL_(wwCirc), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCirc));
register_device_value(tag, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCircMode));
} else if (tag == DeviceValueTAG::TAG_DHW1 || tag == DeviceValueTAG::TAG_DHW2) { // MM100 or SM100
register_telegram_type(0x331 + dhw_, "MMPLUSStatusMessage_WWC", false, MAKE_PF_CB(process_MMPLUSStatusMessage_WWC));
register_telegram_type(0x313 + dhw_, "MMPLUSConfigMessage_WWC", true, MAKE_PF_CB(process_MMPLUSConfigMessage_WWC), 11);
// register_telegram_type(0x33B + type_offset, "MMPLUSSetMessage_WWC", true, MAKE_PF_CB(process_MMPLUSSetMessage_WWC));
// device values...
register_device_value(tag, &wwTemp_, DeviceValueType::UINT16, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &wwStatus_, DeviceValueType::INT8, FL_(wwTempStatus), DeviceValueUOM::NONE);
register_device_value(tag, &wwPump_, DeviceValueType::BOOL, FL_(wwPump), DeviceValueUOM::NONE);
register_device_value(tag, &wwMaxTemp_, DeviceValueType::UINT8, FL_(wwMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwMaxTemp));
register_device_value(tag, &wwDiffTemp_, DeviceValueType::INT8, FL_(wwDiffTemp), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwDiffTemp));
register_device_value(tag, &wwDisinfectionTemp_, DeviceValueType::UINT8, FL_(wwDisinfectionTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwDisinfectionTemp));
register_device_value(tag, &wwRedTemp_, DeviceValueType::UINT8, FL_(wwRedTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwRedTemp));
register_device_value(tag, &wwRequiredTemp_, DeviceValueType::UINT8, FL_(wwRequiredTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwRequiredTemp));
register_device_value(tag, &wwCirc_, DeviceValueType::BOOL, FL_(wwCirc), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCirc));
register_device_value(tag, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCircMode));
} else { // device_id 0x2A, DHW3, SM100
register_telegram_type(0x07D6 + dhw_ - 2, "SM100wwTemperature", false, MAKE_PF_CB(process_SM100wwTemperature));
register_telegram_type(0x07E0 + dhw_ - 2, "SM100wwStatus2", true, MAKE_PF_CB(process_SM100wwStatus2), 10);
register_telegram_type(0x07A6, "SM100wwParam", true, MAKE_PF_CB(process_SM100wwParam), 20); // same telegram for all circuits
@@ -67,41 +99,6 @@ Water::Water(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
register_device_value(tag, &wwRetValve_, DeviceValueType::UINT8, FL_(valveReturn), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_wwRetValve));
register_device_value(tag, &wwDeltaTRet_, DeviceValueType::UINT8, FL_(deltaTRet), DeviceValueUOM::K, MAKE_CF_CB(set_wwDeltaTRet));
register_device_value(tag, &errorDisp_, DeviceValueType::ENUM, FL_(enum_errorDisp), FL_(errorDisp), DeviceValueUOM::NONE, MAKE_CF_CB(set_errorDisp));
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { // dhw1 and dhw 2
register_telegram_type(0x331 + dhw_, "MMPLUSStatusMessage_WWC", false, MAKE_PF_CB(process_MMPLUSStatusMessage_WWC));
register_telegram_type(0x313 + dhw_, "MMPLUSConfigMessage_WWC", true, MAKE_PF_CB(process_MMPLUSConfigMessage_WWC), 11);
// register_telegram_type(0x33B + type_offset, "MMPLUSSetMessage_WWC", true, MAKE_PF_CB(process_MMPLUSSetMessage_WWC));
// device values...
register_device_value(tag, &wwTemp_, DeviceValueType::UINT16, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &wwStatus_, DeviceValueType::INT8, FL_(wwTempStatus), DeviceValueUOM::NONE);
register_device_value(tag, &wwPump_, DeviceValueType::BOOL, FL_(wwPump), DeviceValueUOM::NONE);
register_device_value(tag, &wwMaxTemp_, DeviceValueType::UINT8, FL_(wwMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwMaxTemp));
register_device_value(tag, &wwDiffTemp_, DeviceValueType::INT8, FL_(wwDiffTemp), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwDiffTemp));
register_device_value(tag, &wwDisinfectionTemp_, DeviceValueType::UINT8, FL_(wwDisinfectionTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwDisinfectionTemp));
register_device_value(tag, &wwRedTemp_, DeviceValueType::UINT8, FL_(wwRedTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwRedTemp));
register_device_value(tag, &wwRequiredTemp_, DeviceValueType::UINT8, FL_(wwRequiredTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwRequiredTemp));
register_device_value(tag, &wwCirc_, DeviceValueType::BOOL, FL_(wwCirc), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCirc));
register_device_value(tag, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCircMode));
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_IPM) {
dhw_ = 0;
tag = DeviceValueTAG::TAG_DHW1;
register_telegram_type(0x34, "UBAMonitorWW", false, MAKE_PF_CB(process_IPMMonitorWW));
register_telegram_type(0x1E, "HydrTemp", false, MAKE_PF_CB(process_IPMHydrTemp));
register_telegram_type(0x33, "UBAParameterWW", true, MAKE_PF_CB(process_IPMParameterWW), 12);
// register_telegram_type(0x10D, "wwNTCStatus", false, MAKE_PF_CB(process_wwNTCStatus));
// device values...
register_device_value(tag, &wwSelTemp_, DeviceValueType::UINT8, FL_(wwSelTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwSelTemp));
register_device_value(tag, &wwTemp_, DeviceValueType::UINT16, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &wwTemp2_, DeviceValueType::UINT16, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwCurTemp2), DeviceValueUOM::DEGREES);
register_device_value(tag, &HydrTemp_, DeviceValueType::UINT16, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(hydrTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &wwPump_, DeviceValueType::BOOL, FL_(wwPump), DeviceValueUOM::NONE);
register_device_value(tag, &wwFlowTempOffset_, DeviceValueType::UINT8, FL_(wwFlowTempOffset), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwFlowTempOffset));
register_device_value(tag, &wwHystOn_, DeviceValueType::INT8, FL_(wwHystOn), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwHystOn));
register_device_value(tag, &wwHystOff_, DeviceValueType::INT8, FL_(wwHystOff), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwHystOff));
register_device_value(tag, &wwDisinfectionTemp_, DeviceValueType::UINT8, FL_(wwDisinfectionTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwDisinfectionTemp));
register_device_value(tag, &wwCirc_, DeviceValueType::BOOL, FL_(wwCirc), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCirc));
register_device_value(tag, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCircMode));
}
}
@@ -361,7 +358,11 @@ bool Water::set_wwCircTc(const char * value, const int8_t id) {
if (!Helpers::value2bool(value, b)) {
return false;
}
if (flags() == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) {
write_command(0x33B + dhw_, 4, b ? 0x01 : 0x00, 0x33B + dhw_);
} else { // SM100
write_command(0x7A5, 4, b ? 0xFF : 0x00, 0x7A5);
}
return true;
}
+1 -1
View File
@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.8.3-dev.0"
#define EMSESP_APP_VERSION "3.8.4"
+6
View File
@@ -35,6 +35,11 @@ WebAPIService::WebAPIService(AsyncWebServer * server, SecurityManager * security
// POST|GET api/{device}
// POST|GET api/{device}/{entity}
void WebAPIService::webAPIService(AsyncWebServerRequest * request, JsonVariant json) {
static uint64_t lastcall = 0;
if (uuid::get_uptime_ms() - lastcall < 50 && request->method() == HTTP_GET) {
request->send(429); //too many requests
return;
}
JsonDocument input_doc; // has no body JSON so create dummy as empty input object
JsonObject input;
// if no body then treat it as a secure GET
@@ -49,6 +54,7 @@ void WebAPIService::webAPIService(AsyncWebServerRequest * request, JsonVariant j
input["data"] = json.as<std::string>();
}
parse(request, input);
lastcall = uuid::get_uptime_ms();
}
// for POSTS accepting plain text data
+2
View File
@@ -77,8 +77,10 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web
if (entityItem.ram == 2) { // NVS
char key[sizeof(entityItem.name) + 2];
snprintf(key, sizeof(key), "c:%s", entityItem.name);
if (EMSESP::nvs_.isKey(key)) {
EMSESP::nvs_.remove(key);
}
}
if (entityItem.ram) { // save name/value pairs for change checking
doc[entityItem.name] = entityItem.value;
}
+21 -11
View File
@@ -76,8 +76,10 @@ StateUpdateResult WebScheduler::update(JsonObject root, WebScheduler & webSchedu
for (ScheduleItem & scheduleItem : webScheduler.scheduleItems) {
char key[sizeof(scheduleItem.name) + 2];
snprintf(key, sizeof(key), "s:%s", scheduleItem.name);
if (EMSESP::nvs_.isKey(key)) {
EMSESP::nvs_.remove(key);
}
}
webScheduler.scheduleItems.clear();
EMSESP::webSchedulerService.ha_reset();
@@ -345,7 +347,11 @@ uint8_t WebSchedulerService::count_entities(bool cmd_only) {
// execute scheduled command
bool WebSchedulerService::command(const char * name, const std::string & command, const std::string & data) {
std::string cmd = Helpers::toLower(command);
if (cmd == "system/message") {
EMSESP::logger().info("Message: %s", data.c_str()); // send to log
Mqtt::queue_publish(F_(message), data); // send to MQTT if enabled
return true;
}
// check http commands. e.g.
// tasmota(get): http://<tasmotaIP>/cm?cmnd=power%20ON
// shelly(get): http://<shellyIP>/relais/0?turn=on
@@ -353,6 +359,10 @@ bool WebSchedulerService::command(const char * name, const std::string & command
JsonDocument doc;
if (deserializeJson(doc, cmd) == DeserializationError::Ok) {
HTTPClient * http = new HTTPClient;
#ifndef EMSESP_STANDALONE
http->setConnectTimeout(10000);
http->setTimeout(10000);
#endif
std::string url = doc["url"] | "";
// for a GET with parameters replace commands with values
// don't search the complete url, it may contain a devicename in path
@@ -401,6 +411,7 @@ bool WebSchedulerService::command(const char * name, const std::string & command
return true;
}
// we can add other json tests here
delete http;
}
doc.clear();
@@ -443,8 +454,7 @@ bool WebSchedulerService::command(const char * name, const std::string & command
// queue schedules to be handled executed in scheduler-loop
bool WebSchedulerService::onChange(const char * cmd) {
for (ScheduleItem & scheduleItem : *scheduleItems_) {
if (scheduleItem.active && scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_ONCHANGE
&& Helpers::toLower(scheduleItem.time.c_str()).find(Helpers::toLower(cmd)) != std::string::npos) {
if (scheduleItem.active && scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_ONCHANGE && Helpers::toLower(scheduleItem.time.c_str()) == Helpers::toLower(cmd)) {
cmd_changed_.push_back(&scheduleItem);
return true;
}
@@ -480,15 +490,14 @@ void WebSchedulerService::loop() {
static uint32_t last_uptime_min = 0;
static uint32_t last_uptime_sec = 0;
if (!raw_value.empty()) { // process a value from system/message command
computed_value = compute(raw_value);
raw_value.clear();
}
// get list of scheduler events and exit if it's empty
if (scheduleItems_->empty()) {
return;
}
// do not execute any command in the first 60 secondes
if (uuid::get_uptime_sec() < 60) {
return;
}
// check if we have onChange events
while (!cmd_changed_.empty()) {
@@ -532,7 +541,8 @@ void WebSchedulerService::loop() {
// retry startup commands not yet executed
if (scheduleItem.active && scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_TIMER && scheduleItem.elapsed_min == 0
&& scheduleItem.retry_cnt < MAX_STARTUP_RETRIES) {
scheduleItem.retry_cnt = command(scheduleItem.name, scheduleItem.cmd.c_str(), scheduleItem.value.c_str()) ? 0xFF : scheduleItem.retry_cnt + 1;
scheduleItem.retry_cnt =
command(scheduleItem.name, scheduleItem.cmd.c_str(), compute(scheduleItem.value.c_str())) ? 0xFF : scheduleItem.retry_cnt + 1;
}
// scheduled timer commands
if (scheduleItem.active && scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_TIMER && scheduleItem.elapsed_min > 0
@@ -543,10 +553,10 @@ void WebSchedulerService::loop() {
last_uptime_min = uptime_min;
}
// check calender, sync to RTC, only execute if year is valid
// check calender, sync to RTC, only execute if year is valid and uptime more than a minute
time_t now = time(nullptr);
tm * tm = localtime(&now);
if (tm->tm_min != last_tm_min && tm->tm_year > 120) {
if (tm->tm_min != last_tm_min && tm->tm_year > 120 && uuid::get_uptime_sec() > 60) {
// find the real dow and minute from RTC
uint8_t real_dow = 1 << tm->tm_wday; // 1 is Sunday
uint16_t real_min = tm->tm_hour * 60 + tm->tm_min;
-3
View File
@@ -90,9 +90,6 @@ class WebSchedulerService : public StatefulService<WebScheduler> {
std::string get_metrics_prometheus();
std::string raw_value;
std::string computed_value;
#if defined(EMSESP_TEST)
void load_test_data();
#endif
+3
View File
@@ -267,6 +267,9 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
}
settings.locale = root["locale"] | EMSESP_DEFAULT_LOCALE;
if (settings.locale == "cz") { // convert from older settings file
settings.locale = "cs";
}
EMSESP::system_.locale(settings.locale);
if (Mqtt::ha_enabled() && original_settings.locale != settings.locale) {
add_flags(ChangeFlags::MQTT);
+5
View File
@@ -177,6 +177,10 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
// we're ready to do the actual restart ASAP
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_RESTART_REQUESTED);
}
if (EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_ERROR_UPLOAD) {
// error is reported, back to normal state
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_NORMAL);
}
#endif
@@ -241,6 +245,7 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json)
if (!ok) {
EMSESP::logger().err("Action '%s' failed", action.c_str());
request->send(400); // bad request
delete response;
return;
}