mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-09-13 13:44:10 +00:00
Compare commits
183
Commits
690cb9df96
...
v3.8.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8a96352ec | ||
|
|
02caaef916 | ||
|
|
ba0f4cd008 | ||
|
|
45f7d91b43 | ||
|
|
e0f59a4c31 | ||
|
|
7eba8acbb4 | ||
|
|
d0e6a603bb | ||
|
|
36b4dd55a7 | ||
|
|
341a4d4e1d | ||
|
|
a61745b710 | ||
|
|
b1ebd81ca2 | ||
|
|
1ff53e6ac7 | ||
|
|
9cab3b480e | ||
|
|
edfbbe68b0 | ||
|
|
96e8a0d916 | ||
|
|
8c90d10601 | ||
|
|
bacd3faac2 | ||
|
|
2b187fb848 | ||
|
|
4a12066e37 | ||
|
|
b82f8c979f | ||
|
|
342878f628 | ||
|
|
4e47be7fa6 | ||
|
|
2b25ae18d1 | ||
|
|
98c9e011bc | ||
|
|
cb1cb356ce | ||
|
|
20fc5ede78 | ||
|
|
a20d1d8970 | ||
|
|
a647e16f68 | ||
|
|
49ab5e3d72 | ||
|
|
9c905c8bab | ||
|
|
7ab343a216 | ||
|
|
188cc7b666 | ||
|
|
193e5d591c | ||
|
|
ff3f4d3a6d | ||
|
|
5129b475c5 | ||
|
|
f31dbd44a5 | ||
|
|
5c55c2216e | ||
|
|
5a1d06d39e | ||
|
|
9443cf3c87 | ||
|
|
fa31dcdf24 | ||
|
|
2c80cc597e | ||
|
|
d7641fbb2f | ||
|
|
5742c03eee | ||
|
|
b2858ab3e7 | ||
|
|
2255ad0b17 | ||
|
|
ed8adf2617 | ||
|
|
5c2205cf65 | ||
|
|
f6cb695635 | ||
|
|
1450e79b64 | ||
|
|
fae0f9fb49 | ||
|
|
8638424d5b | ||
|
|
1d016ec356 | ||
|
|
f16b10f544 | ||
|
|
dd0c8a5ca8 | ||
|
|
7175191c66 | ||
|
|
f7a81c50b0 | ||
|
|
cfbcaa6fce | ||
|
|
abd1c36ec9 | ||
|
|
ebd6d15c48 | ||
|
|
f4979d905d | ||
|
|
496884c78a | ||
|
|
696c82364e | ||
|
|
c55655c0c5 | ||
|
|
55a0e4b2b5 | ||
|
|
eceb097cc7 | ||
|
|
0e18645ba5 | ||
|
|
63f49a347b | ||
|
|
943048a920 | ||
|
|
2b8a0bd8b7 | ||
|
|
d83b56a13c | ||
|
|
1f34a41d27 | ||
|
|
343ac5880c | ||
|
|
855edace20 | ||
|
|
aabc4f021c | ||
|
|
0aaa566e73 | ||
|
|
20e3d6a19b | ||
|
|
67953fccd6 | ||
|
|
0c910bc822 | ||
|
|
b6a7fb0bf0 | ||
|
|
95f475ab6f | ||
|
|
f8fa092ac3 | ||
|
|
5aadf7234f | ||
|
|
b8a63aeac6 | ||
|
|
908a9ebbfc | ||
|
|
dbf970d869 | ||
|
|
9cb2455af2 | ||
|
|
f99ca7f013 | ||
|
|
7349bc9ebf | ||
|
|
ccd3a7b223 | ||
|
|
33602f65f3 | ||
|
|
0493f93976 | ||
|
|
238c9b7860 | ||
|
|
0823b7882b | ||
|
|
cf2f816527 | ||
|
|
559336a2a7 | ||
|
|
0e6cb363ad | ||
|
|
66b1b1cb24 | ||
|
|
1d608b7705 | ||
|
|
6dc8072106 | ||
|
|
88f75038e0 | ||
|
|
f5bc3e82bb | ||
|
|
c206f069c6 | ||
|
|
6697aebc3b | ||
|
|
3d335dad27 | ||
|
|
1ae547a710 | ||
|
|
20d6966633 | ||
|
|
d5c96f6d48 | ||
|
|
d1192e707d | ||
|
|
70cfbd96e2 | ||
|
|
0dacd2c71f | ||
|
|
3962adc911 | ||
|
|
0892738cd9 | ||
|
|
b441fd83dd | ||
|
|
ee3a5d231a | ||
|
|
e8f57b6343 | ||
|
|
a1ab81de66 | ||
|
|
28135c225b | ||
|
|
eaa277fef0 | ||
|
|
e418b7d8e7 | ||
|
|
a4e3be6a69 | ||
|
|
a1bc5bb055 | ||
|
|
f444ca31e0 | ||
|
|
1b70b55989 | ||
|
|
1487f30c43 | ||
|
|
e00eb8e64f | ||
|
|
f41bb3671c | ||
|
|
22c75e6df3 | ||
|
|
5ab10b7aa6 | ||
|
|
ee5fd4d0eb | ||
|
|
46f35bc67c | ||
|
|
ec85a7ec24 | ||
|
|
02f2389587 | ||
|
|
7f140021aa | ||
|
|
6796962c1e | ||
|
|
df6de21cf4 | ||
|
|
df9f75a5c9 | ||
|
|
7bd8710eb6 | ||
|
|
32f2c6d341 | ||
|
|
86919c1684 | ||
|
|
86e29515e7 | ||
|
|
46eb4185d7 | ||
|
|
8da6761a48 | ||
|
|
9233f0dfcc | ||
|
|
292f743b14 | ||
|
|
dd6dfffd57 | ||
|
|
ec705a5307 | ||
|
|
f45f071710 | ||
|
|
f3858546de | ||
|
|
d0ac0b7804 | ||
|
|
d8284ec09f | ||
|
|
6e982acde8 | ||
|
|
8c94ce99b2 | ||
|
|
fc057d18c9 | ||
|
|
18e9b99413 | ||
|
|
a47e0e8266 | ||
|
|
f412ddc716 | ||
|
|
29110e96e5 | ||
|
|
b65866217a | ||
|
|
611e3b1243 | ||
|
|
2ca0a0c634 | ||
|
|
7eb1f061b7 | ||
|
|
50459a23fe | ||
|
|
5bf53c3389 | ||
|
|
4b7aa95be3 | ||
|
|
70943f5758 | ||
|
|
3bc280b817 | ||
|
|
62b15a5319 | ||
|
|
8dd18802d6 | ||
|
|
57a516a83a | ||
|
|
a57fdaa4b3 | ||
|
|
4841e42286 | ||
|
|
8c2d2b06ed | ||
|
|
38c8b1b7f0 | ||
|
|
6fb5933a02 | ||
|
|
c0944433be | ||
|
|
478e6362c9 | ||
|
|
4d6354db78 | ||
|
|
beab0f0c77 | ||
|
|
c17749bd22 | ||
|
|
2bad769c5c | ||
|
|
8ad89ca64b | ||
|
|
9244d8daec | ||
|
|
02d01334b2 |
+37
-1
@@ -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
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
# Changelog
|
||||
|
||||
For more details go to [emsesp.org](https://emsesp.org/).
|
||||
|
||||
## [3.8.3]
|
||||
|
||||
## Added
|
||||
|
||||
## Fixed
|
||||
|
||||
- signed value for solarInfuence [#3077](https://github.com/emsesp/EMS-ESP32/issues/3077)
|
||||
|
||||
## Changed
|
||||
|
||||
@@ -5363,16 +5363,16 @@ uint8
|
||||
uint8
|
||||
| hc1.heatoffdelay | heat-off delay | uint8 (>=1<=48) | hours | true | HC | 48 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.instantstart | instant start | uint8 (>=1<=10) | K | true | HC | 49 | 1 | 1 |
|
||||
| hc1.boost | boost mode | boolean | | true | HC | 50 | 1 | 1 |
|
||||
| hc1.coolondelay | cooling on delay | uint8 (>=1<=48) | hours | true | HC | 49 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.boosttime | boost time | uint8 (>=0<=0) | hours | true | HC | 51 | 1 | 1 |
|
||||
| hc1.cooloffdelay | cooling off delay | uint8 (>=1<=48) | hours | true | HC | 50 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.instantstart | instant start | uint8 (>=1<=10) | K | true | HC | 51 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.coolstart | cooling starttemp | uint8 (>=20<=35) | C | true | HC | 52 | 1 | 1 |
|
||||
| hc1.boost | boost mode | boolean | | true | HC | 53 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.coolondelay | cooling on delay | uint8 (>=1<=48) | hours | true | HC | 53 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.cooloffdelay | cooling off delay | uint8 (>=1<=48) | hours | true | HC | 54 | 1 | 1 |
|
||||
| hc1.boosttime | boost time | uint8 (>=0<=0) | hours | true | HC | 54 | 1 | 1 |
|
||||
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
|
||||
int8
|
||||
| hc1.redthreshold | reduction threshold | int8 (>=12<=22) | C | true | HC | 56 | 1 | 1/2 |
|
||||
@@ -5972,16 +5972,16 @@ uint8
|
||||
uint8
|
||||
| hc1.heatoffdelay | heat-off delay | uint8 (>=1<=48) | hours | true | HC | 48 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.instantstart | instant start | uint8 (>=1<=10) | K | true | HC | 49 | 1 | 1 |
|
||||
| hc1.boost | boost mode | boolean | | true | HC | 50 | 1 | 1 |
|
||||
| hc1.coolondelay | cooling on delay | uint8 (>=1<=48) | hours | true | HC | 49 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.boosttime | boost time | uint8 (>=0<=0) | hours | true | HC | 51 | 1 | 1 |
|
||||
| hc1.cooloffdelay | cooling off delay | uint8 (>=1<=48) | hours | true | HC | 50 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.instantstart | instant start | uint8 (>=1<=10) | K | true | HC | 51 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.coolstart | cooling starttemp | uint8 (>=20<=35) | C | true | HC | 52 | 1 | 1 |
|
||||
| hc1.boost | boost mode | boolean | | true | HC | 53 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.coolondelay | cooling on delay | uint8 (>=1<=48) | hours | true | HC | 53 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.cooloffdelay | cooling off delay | uint8 (>=1<=48) | hours | true | HC | 54 | 1 | 1 |
|
||||
| hc1.boosttime | boost time | uint8 (>=0<=0) | hours | true | HC | 54 | 1 | 1 |
|
||||
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
|
||||
int8
|
||||
| hc1.redthreshold | reduction threshold | int8 (>=12<=22) | C | true | HC | 56 | 1 | 1/2 |
|
||||
@@ -6124,16 +6124,16 @@ uint8
|
||||
uint8
|
||||
| hc1.heatoffdelay | heat-off delay | uint8 (>=1<=48) | hours | true | HC | 48 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.instantstart | instant start | uint8 (>=1<=10) | K | true | HC | 49 | 1 | 1 |
|
||||
| hc1.boost | boost mode | boolean | | true | HC | 50 | 1 | 1 |
|
||||
| hc1.coolondelay | cooling on delay | uint8 (>=1<=48) | hours | true | HC | 49 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.boosttime | boost time | uint8 (>=0<=0) | hours | true | HC | 51 | 1 | 1 |
|
||||
| hc1.cooloffdelay | cooling off delay | uint8 (>=1<=48) | hours | true | HC | 50 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.instantstart | instant start | uint8 (>=1<=10) | K | true | HC | 51 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.coolstart | cooling starttemp | uint8 (>=20<=35) | C | true | HC | 52 | 1 | 1 |
|
||||
| hc1.boost | boost mode | boolean | | true | HC | 53 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.coolondelay | cooling on delay | uint8 (>=1<=48) | hours | true | HC | 53 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.cooloffdelay | cooling off delay | uint8 (>=1<=48) | hours | true | HC | 54 | 1 | 1 |
|
||||
| hc1.boosttime | boost time | uint8 (>=0<=0) | hours | true | HC | 54 | 1 | 1 |
|
||||
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
|
||||
int8
|
||||
| hc1.redthreshold | reduction threshold | int8 (>=12<=22) | C | true | HC | 56 | 1 | 1/2 |
|
||||
@@ -6291,16 +6291,16 @@ uint8
|
||||
uint8
|
||||
| hc1.heatoffdelay | heat-off delay | uint8 (>=1<=48) | hours | true | HC | 48 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.instantstart | instant start | uint8 (>=1<=10) | K | true | HC | 49 | 1 | 1 |
|
||||
| hc1.boost | boost mode | boolean | | true | HC | 50 | 1 | 1 |
|
||||
| hc1.coolondelay | cooling on delay | uint8 (>=1<=48) | hours | true | HC | 49 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.boosttime | boost time | uint8 (>=0<=0) | hours | true | HC | 51 | 1 | 1 |
|
||||
| hc1.cooloffdelay | cooling off delay | uint8 (>=1<=48) | hours | true | HC | 50 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.instantstart | instant start | uint8 (>=1<=10) | K | true | HC | 51 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.coolstart | cooling starttemp | uint8 (>=20<=35) | C | true | HC | 52 | 1 | 1 |
|
||||
| hc1.boost | boost mode | boolean | | true | HC | 53 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.coolondelay | cooling on delay | uint8 (>=1<=48) | hours | true | HC | 53 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.cooloffdelay | cooling off delay | uint8 (>=1<=48) | hours | true | HC | 54 | 1 | 1 |
|
||||
| hc1.boosttime | boost time | uint8 (>=0<=0) | hours | true | HC | 54 | 1 | 1 |
|
||||
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
|
||||
int8
|
||||
| hc1.redthreshold | reduction threshold | int8 (>=12<=22) | C | true | HC | 56 | 1 | 1/2 |
|
||||
@@ -6410,6 +6410,21 @@ int8
|
||||
int8
|
||||
| pvlowercool | lower cooling with PV | int8 (>=-5<=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 (>=10<=30) | C | true | DEVICE_DATA | 90 | 1 | 1 |
|
||||
uint8
|
||||
| instantstart | instant start | uint8 (>=1<=10) | K | true | DEVICE_DATA | 91 | 1 | 1 |
|
||||
uint8
|
||||
| coolstart | cooling starttemp | uint8 (>=20<=35) | C | true | DEVICE_DATA | 92 | 1 | 1 |
|
||||
uint8
|
||||
| heatondelay | heat-on delay | uint8 (>=1<=48) | hours | true | DEVICE_DATA | 93 | 1 | 1/4 |
|
||||
uint8
|
||||
| heatoffdelay | heat-off delay | uint8 (>=1<=48) | hours | true | DEVICE_DATA | 94 | 1 | 1/4 |
|
||||
uint8
|
||||
| coolondelay | cooling on delay | uint8 (>=1<=48) | hours | true | DEVICE_DATA | 95 | 1 | 1/4 |
|
||||
uint8
|
||||
| cooloffdelay | cooling off delay | uint8 (>=1<=48) | hours | true | DEVICE_DATA | 96 | 1 | 1/4 |
|
||||
int16
|
||||
| hc1.seltemp | selected room temperature | int16 (>=0<=30) | C | true | HC | 0 | 1 | 1/2 |
|
||||
| hc1.currtemp | current room temperature | int16 | C | false | HC | 1 | 1 | 1/10 |
|
||||
@@ -6480,21 +6495,9 @@ 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 (>=1<=48) | hours | true | HC | 47 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.heatoffdelay | heat-off delay | uint8 (>=1<=48) | hours | true | HC | 48 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.instantstart | instant start | uint8 (>=1<=10) | K | true | HC | 49 | 1 | 1 |
|
||||
| hc1.boost | boost mode | boolean | | true | HC | 50 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.boosttime | boost time | uint8 (>=0<=0) | hours | true | HC | 51 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.coolstart | cooling starttemp | uint8 (>=20<=35) | C | true | HC | 52 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.coolondelay | cooling on delay | uint8 (>=1<=48) | hours | true | HC | 53 | 1 | 1 |
|
||||
uint8
|
||||
| hc1.cooloffdelay | cooling off delay | uint8 (>=1<=48) | hours | true | HC | 54 | 1 | 1 |
|
||||
| hc1.boosttime | boost time | uint8 (>=0<=0) | hours | true | HC | 54 | 1 | 1 |
|
||||
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
|
||||
int8
|
||||
| hc1.redthreshold | reduction threshold | int8 (>=12<=22) | C | true | HC | 56 | 1 | 1/2 |
|
||||
@@ -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 (>=5<=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 (>=0<=0) | C | true | DHW | 12 | 1 | 1 |
|
||||
int8
|
||||
| dhw.difftemp | start differential temperature | int8 (>=0<=0) | C | true | DHW | 13 | 1 | 1 |
|
||||
uint8
|
||||
| dhw.seltemp | selected temperature | uint8 (>=0<=0) | C | true | DHW | 0 | 1 | 1 |
|
||||
| dhw.disinfectiontemp | disinfection temperature | uint8 (>=0<=0) | C | true | DHW | 8 | 1 | 1 |
|
||||
uint8
|
||||
| dhw.redtemp | reduced temperature | uint8 (>=0<=0) | C | true | DHW | 14 | 1 | 1 |
|
||||
uint8
|
||||
| dhw.hottemp | extra hot temperature | uint8 (>=0<=0) | C | true | DHW | 20 | 1 | 1 |
|
||||
uint8
|
||||
| dhw.dailytemp | daily temperature | uint8 (>=0<=0) | C | true | DHW | 21 | 1 | 1 |
|
||||
uint8
|
||||
| dhw.disinfectiontemp | disinfection temperature | uint8 (>=0<=0) | C | true | DHW | 8 | 1 | 1 |
|
||||
| dhw.requiredtemp | required temperature | uint8 (>=0<=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 (>=0<=0) | % | true | DHW | 27 | 1 | 1 |
|
||||
uint8
|
||||
| dhw.deltatret | temp. diff. return valve | uint8 (>=0<=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 (>=0<=0) | C | true | DHW | 12 | 1 | 1 |
|
||||
int8
|
||||
| dhw.difftemp | start differential temperature | int8 (>=0<=0) | C | true | DHW | 13 | 1 | 1 |
|
||||
uint8
|
||||
| dhw.seltemp | selected temperature | uint8 (>=0<=0) | C | true | DHW | 0 | 1 | 1 |
|
||||
| dhw.disinfectiontemp | disinfection temperature | uint8 (>=0<=0) | C | true | DHW | 8 | 1 | 1 |
|
||||
uint8
|
||||
| dhw.redtemp | reduced temperature | uint8 (>=0<=0) | C | true | DHW | 14 | 1 | 1 |
|
||||
uint8
|
||||
| dhw.hottemp | extra hot temperature | uint8 (>=0<=0) | C | true | DHW | 20 | 1 | 1 |
|
||||
uint8
|
||||
| dhw.dailytemp | daily temperature | uint8 (>=0<=0) | C | true | DHW | 21 | 1 | 1 |
|
||||
uint8
|
||||
| dhw.disinfectiontemp | disinfection temperature | uint8 (>=0<=0) | C | true | DHW | 8 | 1 | 1 |
|
||||
| dhw.requiredtemp | required temperature | uint8 (>=0<=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 (>=0<=0) | % | true | DHW | 27 | 1 | 1 |
|
||||
uint8
|
||||
| dhw.deltatret | temp. diff. return valve | uint8 (>=0<=0) | K | true | DHW | 28 | 1 | 1 |
|
||||
| dhw.errordisp | error display | enum | | true | DHW | 29 | 1 | 1 |
|
||||
|
||||
## Devices of type \_pool
|
||||
|
||||
|
||||
+43
-65
@@ -4044,17 +4044,17 @@ 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,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
|
||||
@@ -4439,12 +4439,12 @@ 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,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
|
||||
@@ -4537,12 +4537,12 @@ 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,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
|
||||
@@ -4644,12 +4644,12 @@ 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,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,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,17 +4772,11 @@ 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,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,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
@@ -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
|
||||
|
||||
|
@@ -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
@@ -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",
|
||||
|
||||
Generated
+730
-1243
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -19,7 +19,7 @@ const AVAILABLE_LOCALES = [
|
||||
'sk',
|
||||
'sv',
|
||||
'tr',
|
||||
'cz'
|
||||
'cs'
|
||||
] as Locales[];
|
||||
|
||||
// Static toast configuration - no need to recreate on every render
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
@@ -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 {
|
||||
|
||||
@@ -79,8 +79,12 @@ class DummySettings {
|
||||
uint8_t provisionMode = 0;
|
||||
|
||||
// NTP
|
||||
String server = "pool.ntp.org";
|
||||
String tzLabel = "Europe/London";
|
||||
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) {};
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
Generated
+63
-63
@@ -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: {}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -86,16 +86,22 @@ void NTPSettingsService::ntp_received(struct timeval * tv) {
|
||||
}
|
||||
|
||||
void NTPSettings::read(NTPSettings & settings, JsonObject root) {
|
||||
root["enabled"] = settings.enabled;
|
||||
root["server"] = settings.server;
|
||||
root["tz_label"] = settings.tzLabel;
|
||||
root["tz_format"] = settings.tzFormat;
|
||||
root["enabled"] = settings.enabled;
|
||||
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) {
|
||||
settings.enabled = root["enabled"] | FACTORY_NTP_ENABLED;
|
||||
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.enabled = root["enabled"] | FACTORY_NTP_ENABLED;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -30,10 +34,13 @@
|
||||
|
||||
class NTPSettings {
|
||||
public:
|
||||
bool enabled = FACTORY_NTP_ENABLED;
|
||||
String tzLabel = FACTORY_NTP_TIME_ZONE_LABEL;
|
||||
String tzFormat = FACTORY_NTP_TIME_ZONE_FORMAT;
|
||||
String server = FACTORY_NTP_SERVER;
|
||||
bool enabled = FACTORY_NTP_ENABLED;
|
||||
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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
EMSESP::nvs_.remove(AnalogCustomization.name);
|
||||
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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
+16
-25
@@ -377,19 +377,23 @@ 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[7] = remotehum_[hc];
|
||||
data[8] = (uint8_t)(dew << 8);
|
||||
data[9] = (uint8_t)(dew & 0xFF);
|
||||
data[10] = EMSbus::calculate_crc(data, 10); // append CRC
|
||||
data[0] = addr | EMSbus::ems_mask();
|
||||
data[1] = dst & 0x7F;
|
||||
data[2] = 0xFF;
|
||||
data[3] = 0;
|
||||
data[4] = 3;
|
||||
data[5] = 0x7B + hc;
|
||||
data[6] = static_cast<uint8_t>(dew8);
|
||||
data[7] = remotehum_[hc];
|
||||
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
|
||||
|
||||
@@ -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];
|
||||
|
||||
+59
-55
@@ -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,8 +698,7 @@ 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;
|
||||
std::string url, header_s, value_s, method_s, key_s, keys_s;
|
||||
// search keys lower case
|
||||
for (JsonPair p : doc.as<JsonObject>()) {
|
||||
if (Helpers::toLower(p.key().c_str()) == "url") {
|
||||
@@ -720,56 +717,63 @@ std::string compute(const std::string & expr) {
|
||||
keys_s = p.key().c_str();
|
||||
}
|
||||
}
|
||||
if (http->begin(url.c_str())) {
|
||||
int httpResult = 0;
|
||||
for (JsonPair p : doc[header_s].as<JsonObject>()) {
|
||||
http->addHeader(p.key().c_str(), p.value().as<std::string>().c_str());
|
||||
}
|
||||
std::string value = doc[value_s] | "";
|
||||
std::string method = doc[method_s] | "get";
|
||||
|
||||
// if there is data, force a POST
|
||||
if (value.length() || Helpers::toLower(method) == "post") {
|
||||
if (value.find_first_of('{') != std::string::npos) {
|
||||
http->addHeader(asyncsrv::T_Content_Type, asyncsrv::T_application_json, false); // auto-set to JSON
|
||||
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>()) {
|
||||
http->addHeader(p.key().c_str(), p.value().as<std::string>().c_str());
|
||||
}
|
||||
httpResult = http->POST(value.c_str());
|
||||
} else {
|
||||
httpResult = http->GET(); // normal GET
|
||||
}
|
||||
std::string value = doc[value_s] | "";
|
||||
std::string method = doc[method_s] | "get";
|
||||
|
||||
if (httpResult > 0) {
|
||||
std::string result = http->getString().c_str();
|
||||
std::string key = doc[key_s] | "";
|
||||
JsonDocument keys_doc; // JsonDocument to hold "keys" after doc is parsed with HTTP body
|
||||
if (doc[keys_s].is<JsonArray>()) {
|
||||
keys_doc.set(doc[keys_s].as<JsonArray>());
|
||||
// if there is data, force a POST
|
||||
if (value.length() || Helpers::toLower(method) == "post") {
|
||||
if (value.find_first_of('{') != std::string::npos) {
|
||||
http->addHeader(asyncsrv::T_Content_Type, asyncsrv::T_application_json, false); // auto-set to JSON
|
||||
}
|
||||
httpResult = http->POST(value.c_str());
|
||||
} else {
|
||||
httpResult = http->GET(); // normal GET
|
||||
}
|
||||
JsonArray keys = keys_doc.as<JsonArray>();
|
||||
|
||||
if (key.length() || !keys.isNull()) {
|
||||
doc.clear();
|
||||
if (DeserializationError::Ok == deserializeJson(doc, result)) {
|
||||
if (key.length()) {
|
||||
result = doc[key.c_str()].as<std::string>();
|
||||
} else {
|
||||
JsonVariant json = doc.as<JsonVariant>();
|
||||
for (JsonVariant keys_key : keys) {
|
||||
if (keys_key.is<std::string>() && json.is<JsonObject>()) {
|
||||
json = json[keys_key.as<std::string>()].as<JsonVariant>();
|
||||
} else if (keys_key.is<int>() && json.is<JsonArray>()) {
|
||||
json = json[keys_key.as<int>()].as<JsonVariant>();
|
||||
} else {
|
||||
break; // type mismatch
|
||||
if (httpResult > 0) {
|
||||
std::string result = http->getString().c_str();
|
||||
std::string key = doc[key_s] | "";
|
||||
JsonDocument keys_doc; // JsonDocument to hold "keys" after doc is parsed with HTTP body
|
||||
if (doc[keys_s].is<JsonArray>()) {
|
||||
keys_doc.set(doc[keys_s].as<JsonArray>());
|
||||
}
|
||||
JsonArray keys = keys_doc.as<JsonArray>();
|
||||
|
||||
if (key.length() || !keys.isNull()) {
|
||||
doc.clear();
|
||||
if (DeserializationError::Ok == deserializeJson(doc, result)) {
|
||||
if (key.length()) {
|
||||
result = doc[key.c_str()].as<std::string>();
|
||||
} else {
|
||||
JsonVariant json = doc.as<JsonVariant>();
|
||||
for (JsonVariant keys_key : keys) {
|
||||
if (keys_key.is<std::string>() && json.is<JsonObject>()) {
|
||||
json = json[keys_key.as<std::string>()].as<JsonVariant>();
|
||||
} else if (keys_key.is<int>() && json.is<JsonArray>()) {
|
||||
json = json[keys_key.as<int>()].as<JsonVariant>();
|
||||
} else {
|
||||
break; // type mismatch
|
||||
}
|
||||
}
|
||||
result = json.as<std::string>();
|
||||
}
|
||||
result = json.as<std::string>();
|
||||
}
|
||||
}
|
||||
expr_new.replace(f, e - f, result.c_str());
|
||||
}
|
||||
expr_new.replace(f, e - f, result.c_str());
|
||||
http->end();
|
||||
}
|
||||
http->end();
|
||||
delete http;
|
||||
}
|
||||
}
|
||||
@@ -821,4 +825,4 @@ std::string compute(const std::string & expr) {
|
||||
return calculate(expr_new);
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
} // namespace emsesp
|
||||
|
||||
+20
-24
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
+95
-16
@@ -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
|
||||
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));
|
||||
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));
|
||||
}
|
||||
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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+262
-88
@@ -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,18 +1268,25 @@ 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;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (hc->statusbyte & 1) {
|
||||
has_update(telegram, hc->summersetmode, 0);
|
||||
@@ -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
|
||||
has_update(telegram, hc->roomtempdiff, 3); // 1-10K
|
||||
has_update(telegram, hc->hpminflowtemp, 0); // 2-10K
|
||||
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->dewoffset, 4); // 2-10K
|
||||
}
|
||||
|
||||
// type 0x41 - data from the RC30 thermostat(0x10) - 14 bytes long
|
||||
@@ -1720,9 +1738,18 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// check clock
|
||||
time_t now = time(nullptr);
|
||||
tm * tm_ = localtime(&now);
|
||||
bool tset_ = tm_->tm_year > 110; // year 2010 and up, time is valid
|
||||
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
|
||||
tm_->tm_mon = telegram->message_data[1] - 1;
|
||||
tm_->tm_mday = telegram->message_data[3];
|
||||
@@ -1738,20 +1765,27 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
|
||||
strftime(newdatetime, sizeof(dateTime_), "%d.%m.%Y %H:%M", tm_);
|
||||
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
|
||||
bool ivtclock = (telegram->message_data[0] & 0x80) == 0x80; // dont sync ivt-clock, #439
|
||||
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)) {
|
||||
write_command(hp_typeids[hc->hc()], 0, v, hp_typeids[hc->hc()]);
|
||||
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);
|
||||
}
|
||||
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);
|
||||
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->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->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->switchProgMode,
|
||||
DeviceValueType::ENUM,
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
+40
-39
@@ -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;
|
||||
}
|
||||
write_command(0x33B + dhw_, 4, b ? 0x01 : 0x00, 0x33B + dhw_);
|
||||
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 @@
|
||||
#define EMSESP_APP_VERSION "3.8.3-dev.1"
|
||||
#define EMSESP_APP_VERSION "3.8.4"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -77,7 +77,9 @@ 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);
|
||||
EMSESP::nvs_.remove(key);
|
||||
if (EMSESP::nvs_.isKey(key)) {
|
||||
EMSESP::nvs_.remove(key);
|
||||
}
|
||||
}
|
||||
if (entityItem.ram) { // save name/value pairs for change checking
|
||||
doc[entityItem.name] = entityItem.value;
|
||||
|
||||
@@ -76,7 +76,9 @@ 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);
|
||||
EMSESP::nvs_.remove(key);
|
||||
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,7 +359,11 @@ bool WebSchedulerService::command(const char * name, const std::string & command
|
||||
JsonDocument doc;
|
||||
if (deserializeJson(doc, cmd) == DeserializationError::Ok) {
|
||||
HTTPClient * http = new HTTPClient;
|
||||
std::string url = doc["url"] | "";
|
||||
#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
|
||||
auto q = url.find_first_of('?');
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -588,4 +588,4 @@ void run_tests() {
|
||||
RUN_TEST(test_57);
|
||||
}
|
||||
|
||||
// ---------- END - CUT HERE ----------
|
||||
// ---------- END - CUT HERE ----------
|
||||
Reference in New Issue
Block a user