mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-09-14 22:24:07 +00:00
Compare commits
141
Commits
5199375088
..
core3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e988df817 | ||
|
|
483e124484 | ||
|
|
34db81ab4b | ||
|
|
e9a422bd27 | ||
|
|
4a8ad71b63 | ||
|
|
6801f7b8cf | ||
|
|
c9b90e282f | ||
|
|
11eeb521d5 | ||
|
|
67c8b8429b | ||
|
|
c624e82ada | ||
|
|
722e4665af | ||
|
|
ba7c9cdc1b | ||
|
|
8c647331f2 | ||
|
|
9a98f6b2ff | ||
|
|
1631b607c5 | ||
|
|
4646572c80 | ||
|
|
9b5f9e7a28 | ||
|
|
4575f62e36 | ||
|
|
aa8481c42e | ||
|
|
454b45ee65 | ||
|
|
500f9ef5c5 | ||
|
|
96f2e6d5a7 | ||
|
|
a469507fb6 | ||
|
|
2bef33f81a | ||
|
|
e584adaa07 | ||
|
|
faa327cd08 | ||
|
|
ec4572c9fc | ||
|
|
1398aac828 | ||
|
|
a25f73f0ec | ||
|
|
3d402b0c94 | ||
|
|
c91488d2fe | ||
|
|
ac36b072e8 | ||
|
|
77fac47584 | ||
|
|
c349c2ad0b | ||
|
|
2c268bfc06 | ||
|
|
0a66991902 | ||
|
|
d6fcf16257 | ||
|
|
3ab402c56d | ||
|
|
edfbbe68b0 | ||
|
|
96e8a0d916 | ||
|
|
92f36c6849 | ||
|
|
8c90d10601 | ||
|
|
0ae46e9382 | ||
|
|
7989ab5b3f | ||
|
|
b7aa153f84 | ||
|
|
c760218024 | ||
|
|
3ee5b1ea1d | ||
|
|
9d5edd8e08 | ||
|
|
5397d5d33a | ||
|
|
2b187fb848 | ||
|
|
4a12066e37 | ||
|
|
a80ec9cf7e | ||
|
|
bc960980eb | ||
|
|
b82f8c979f | ||
|
|
342878f628 | ||
|
|
4e47be7fa6 | ||
|
|
2b25ae18d1 | ||
|
|
e9b300f20b | ||
|
|
98c9e011bc | ||
|
|
cb1cb356ce | ||
|
|
20fc5ede78 | ||
|
|
a20d1d8970 | ||
|
|
a647e16f68 | ||
|
|
49ab5e3d72 | ||
|
|
9c905c8bab | ||
|
|
7ab343a216 | ||
|
|
188cc7b666 | ||
|
|
c4c046f15f | ||
|
|
2350a1e1a4 | ||
|
|
99346c1db4 | ||
|
|
5ac1b486a7 | ||
|
|
1cd3cb854e | ||
|
|
eef1367ed2 | ||
|
|
bcad8f0819 | ||
|
|
df1065eb8e | ||
|
|
f36c02b9ed | ||
|
|
193e5d591c | ||
|
|
ff3f4d3a6d | ||
|
|
5129b475c5 | ||
|
|
036722f825 | ||
|
|
8bb464f2a9 | ||
|
|
534989e4bb | ||
|
|
eca8641c64 | ||
|
|
0a5d0fbf88 | ||
|
|
aa76e94b43 | ||
|
|
fd284ce57d | ||
|
|
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 | ||
|
|
ec8c94f733 | ||
|
|
b6a7fb0bf0 | ||
|
|
95f475ab6f | ||
|
|
f8fa092ac3 | ||
|
|
5aadf7234f | ||
|
|
b8a63aeac6 | ||
|
|
908a9ebbfc | ||
|
|
dbf970d869 | ||
|
|
33602f65f3 | ||
|
|
1ae547a710 | ||
|
|
70cfbd96e2 | ||
|
|
b441fd83dd |
@@ -5,6 +5,36 @@ 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.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
|
||||
|
||||
+7
-8
@@ -4,19 +4,18 @@ For more details go to [emsesp.org](https://emsesp.org/).
|
||||
|
||||
## [3.9.0]
|
||||
|
||||
This release is based on the latest Espressif/Arduino core version 3. It brings in many memory and performance optimizations. Note it does require the user to manually migrate settings from 3.8.x to 3.9.0.
|
||||
|
||||
## Added
|
||||
|
||||
- user-requested LED blink [#3063](https://github.com/emsesp/EMS-ESP32/issues/3063)
|
||||
- KM300 at address 0x4A [#3084](https://github.com/emsesp/EMS-ESP32/issues/3084)
|
||||
- Commands Service that can be called via MQTT or API or used in the Scheduler Service
|
||||
- option to disable factory reset [#3150](https://github.com/emsesp/EMS-ESP32/issues/3150)
|
||||
- TLS support with 4MB boards without PSRAM
|
||||
|
||||
## Fixed
|
||||
|
||||
- signed value for solarInfuence [#3077](https://github.com/emsesp/EMS-ESP32/issues/3077)
|
||||
- TLS support with 4MB boards without PSRAM
|
||||
- prevent system crash during WiFi network discovery on ESP32-S3 hardware [#3128](https://github.com/emsesp/EMS-ESP32/pull/3128)
|
||||
- check arithmetric operations on strings [#3127](https://github.com/emsesp/EMS-ESP32/discussions/3127)
|
||||
- fix setting date/time on Junkers thermostats
|
||||
- shunting yard show json
|
||||
|
||||
## Changed
|
||||
|
||||
@@ -24,5 +23,5 @@ For more details go to [emsesp.org](https://emsesp.org/).
|
||||
- Scheduler name is now mandatory
|
||||
- network fallback to AP only after start [#3090](https://github.com/emsesp/EMS-ESP32/issues/3090)
|
||||
- replaced Web async-validator with custom validator and toast with native snackbar to reduce bundle size
|
||||
- Dewtemperature for Easycontrol calculated by ems-esp [3135](https://github.com/emsesp/EMS-ESP32/issues/3135)
|
||||
- Gateway and Connect devices are not shown in the Devices page [3126](https://github.com/emsesp/EMS-ESP32/discussions/3126)
|
||||
- Gateway and Connect devices are shown in the Devices page, but disabled [3126](https://github.com/emsesp/EMS-ESP32/discussions/3126)
|
||||
|
||||
|
||||
+2
-1
@@ -134,6 +134,7 @@
|
||||
"modbus_max_clients": 10,
|
||||
"modbus_timeout": 300,
|
||||
"developer_mode": true,
|
||||
"disable_reset": false,
|
||||
"email_enabled": true,
|
||||
"email_security": 2,
|
||||
"email_server": "smtp.gmail.com",
|
||||
@@ -248,7 +249,7 @@
|
||||
"value_type": 9,
|
||||
"writeable": true,
|
||||
"hide": false,
|
||||
"value": "{\"stable\":{\"version\":\"3.8.2\",\"date\":\"2026-05-12\"},\"dev\":{\"version\":\"3.8.3-dev.5\",\"date\":\"2026-05-28T09:55:29Z\"}}"
|
||||
"value": "{\"stable\":{\"version\":\"3.8.3\",\"date\":\"2026-08-01\"},\"dev\":{\"version\":\"3.9.0-dev.0\",\"date\":\"2026-08-01T09:55:29Z\"}}"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
|
||||
@@ -8146,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 |
|
||||
@@ -8356,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
|
||||
|
||||
|
||||
+11
-35
@@ -5861,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,14,0,1,0,13
|
||||
"MX400",connect,17,outdoortemp,outside temperature,int16,C,false,sensor.connect_outside_temperature,sensor.connect_outdoortemp,14,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,14,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,14,36,1,1,1
|
||||
"MX400",connect,17,src1.airhumidity,relative air humidity,uint8,%,false,sensor.connect_src1_relative_air_humidity,sensor.connect_src1_airhumidity,14,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,14,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,14,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,14,36,1,4,1
|
||||
@@ -5975,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,20,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,20,9,1,10,1
|
||||
"SM100, MS100",water,163,dhw.temp,current temperature,uint16,C,false,sensor.water_dhw_current_temperature,sensor.water_dhw_temp,20,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,20,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,20,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,20,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,20,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,20,9,1,11,1
|
||||
"SM100, MS100",water,163,dhw.pump,pump,boolean, ,false,binary_sensor.water_dhw_pump,binary_sensor.water_dhw_pump,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,9,1,24,1
|
||||
"SM100, MS100",water,163,dhw.pumpmod,pump modulation,uint8,%,false,sensor.water_dhw_pump_modulation,sensor.water_dhw_pumpmod,20,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,20,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,20,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,20,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,20,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,20,9,1,10,1
|
||||
"SM200, MS200",water,164,dhw.temp,current temperature,uint16,C,false,sensor.water_dhw_current_temperature,sensor.water_dhw_temp,20,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,20,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,20,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,20,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,20,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,20,9,1,11,1
|
||||
"SM200, MS200",water,164,dhw.pump,pump,boolean, ,false,binary_sensor.water_dhw_pump,binary_sensor.water_dhw_pump,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,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,20,9,1,24,1
|
||||
"SM200, MS200",water,164,dhw.pumpmod,pump modulation,uint8,%,false,sensor.water_dhw_pump_modulation,sensor.water_dhw_pumpmod,20,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,20,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,20,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,20,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,20,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,20,9,1,10,1
|
||||
"MP100",pool,204,pooltemp,pool temperature,int16,C,false,sensor.pool_pool_temperature,sensor.pool_pooltemp,21,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,21,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,21,0,1,-1,1
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -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=1
|
||||
|
||||
; MQTT settings
|
||||
-D FACTORY_MQTT_ENABLED=false
|
||||
|
||||
+19
-19
@@ -29,34 +29,34 @@
|
||||
"@mui/icons-material": "^9.2.0",
|
||||
"@mui/material": "^9.2.0",
|
||||
"@table-library/react-table-library": "4.1.15",
|
||||
"alova": "^3.5.1",
|
||||
"etag": "^1.8.1",
|
||||
"alova": "^3.5.3",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"mime-types": "^3.0.2",
|
||||
"preact": "^10.29.7",
|
||||
"react": "^19.2.7",
|
||||
"react-dom": "^19.2.7",
|
||||
"preact": "^10.29.8",
|
||||
"react": "^19.2.8",
|
||||
"react-dom": "^19.2.8",
|
||||
"react-icons": "^5.7.0",
|
||||
"react-router": "^8.2.0",
|
||||
"typesafe-i18n": "^5.27.1",
|
||||
"typescript": "^6.0.3"
|
||||
"react-router": "^8.3.0",
|
||||
"typesafe-i18n": "^5.27.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@preact/preset-vite": "^2.10.5",
|
||||
"@preact/preset-vite": "^2.10.6",
|
||||
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
|
||||
"@types/node": "^26.1.1",
|
||||
"@types/react": "^19.2.17",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"concurrently": "^10.0.3",
|
||||
"eslint": "^10.7.0",
|
||||
"@types/node": "^26.1.2",
|
||||
"@types/react": "^19.2.18",
|
||||
"@types/react-dom": "^19.2.4",
|
||||
"concurrently": "^10.0.4",
|
||||
"eslint": "^10.8.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"prettier": "^3.9.5",
|
||||
"etag": "^1.8.1",
|
||||
"mime-types": "^3.0.2",
|
||||
"prettier": "^3.9.6",
|
||||
"rollup-plugin-visualizer": "^7.0.1",
|
||||
"terser": "^5.49.0",
|
||||
"typescript-eslint": "^8.63.0",
|
||||
"vite": "^8.1.4",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.65.0",
|
||||
"vite": "^8.2.0",
|
||||
"vite-plugin-imagemin": "^0.6.1"
|
||||
},
|
||||
"packageManager": "pnpm@11.12.0+sha512.820a6fbd0d9f04c226638002aead1e45340a9139dd5dc077c1d83ef44aa2481c8eb6637b4c9aa696a3c7e35ba818e49cf27213e5f2b91138d09b7a3e26e898ba"
|
||||
"packageManager": "pnpm@11.18.0+sha512.33d83c77da82f49fba836925c6f1b841181ec3132b670639bd012f7075f5c7cf634c5f870147c19aae7478fac01df09d8892e880454896edd23ee9b33757563c"
|
||||
}
|
||||
|
||||
Generated
+610
-538
File diff suppressed because it is too large
Load Diff
@@ -4,19 +4,5 @@ allowBuilds:
|
||||
gifsicle: false
|
||||
jpegtran-bin: false
|
||||
mozjpeg: false
|
||||
optipng-bin: true
|
||||
pngquant-bin: true
|
||||
minimumReleaseAgeExclude:
|
||||
- '@types/node@25.9.2'
|
||||
- '@types/react@19.2.17'
|
||||
- react-router@8.0.1
|
||||
overrides:
|
||||
# pin browserslist to one exact version so `pnpm update` can't re-resolve it to a
|
||||
# newer release it then fails to link (spurious "Failed to create bin ... ENOENT")
|
||||
browserslist: 4.28.5
|
||||
updateConfig:
|
||||
# typesafe-i18n / typescript-eslint rely on the classic compiler API that the
|
||||
# native TS 7 rewrite removes. TS 6.x still has it, so stay on 6.x by excluding
|
||||
# typescript from `pnpm update --latest` (which would otherwise jump it to 7).
|
||||
ignoreDependencies:
|
||||
- typescript
|
||||
optipng-bin: false
|
||||
pngquant-bin: false
|
||||
|
||||
@@ -50,7 +50,7 @@ static constexpr size_t WWW_ASSETS_COUNT = sizeof(WWW_ASSETS) / sizeof(WWW_ASSET
|
||||
// (e.g. "en,de,nl"). When set, locale chunks outside the list are NOT embedded
|
||||
// into firmware flash. `en` is always kept as the fallback. Unset => embed all.
|
||||
const ALL_LOCALES = [
|
||||
'cz',
|
||||
'cs',
|
||||
'de',
|
||||
'en',
|
||||
'fr',
|
||||
|
||||
@@ -20,7 +20,7 @@ const ALL_LOCALES = [
|
||||
'sk',
|
||||
'sv',
|
||||
'tr',
|
||||
'cz'
|
||||
'cs'
|
||||
] as Locales[];
|
||||
|
||||
// Optional build-time allow-list (e.g. VITE_APP_LOCALES="en,de,nl"). When unset,
|
||||
|
||||
@@ -489,7 +489,8 @@ const Customizations = () => {
|
||||
</MenuItem>
|
||||
{devices.devices.map(
|
||||
(device: Device) =>
|
||||
device.id < 90 && (
|
||||
device.id < 90 &&
|
||||
device.e !== 0 && (
|
||||
<MenuItem key={device.id} value={device.id}>
|
||||
{device.n} ({device.tn})
|
||||
</MenuItem>
|
||||
|
||||
@@ -558,16 +558,26 @@ const Devices = memo(() => {
|
||||
<CircularProgress sx={{ margin: 1 }} size={18} />
|
||||
)}
|
||||
{tableList.map((device: Device) => (
|
||||
<Row key={device.id} item={device}>
|
||||
<Row key={device.id} item={device} disabled={device.e === 0}>
|
||||
<Cell>
|
||||
<DeviceIcon type_id={device.t} />
|
||||
|
||||
{device.n}
|
||||
<span style={{ color: 'lightblue' }}>
|
||||
({device.e})
|
||||
<span style={{ color: device.e === 0 ? 'grey' : 'white' }}>
|
||||
{device.n}
|
||||
</span>
|
||||
{device.e !== 0 && (
|
||||
<span style={{ color: 'lightblue' }}>
|
||||
({device.e})
|
||||
</span>
|
||||
)}
|
||||
</Cell>
|
||||
<Cell stiff>
|
||||
<ButtonTooltip
|
||||
title={`DeviceID: 0x${('00' + device.d.toString(16).toUpperCase()).slice(-2)}, ProductID: ${device.p}`}
|
||||
>
|
||||
<span>{device.tn}</span>
|
||||
</ButtonTooltip>
|
||||
</Cell>
|
||||
<Cell stiff>{device.tn}</Cell>
|
||||
</Row>
|
||||
))}
|
||||
</Body>
|
||||
|
||||
@@ -54,6 +54,7 @@ export interface Settings {
|
||||
email_recp: string;
|
||||
email_subject: string;
|
||||
developer_mode: boolean;
|
||||
disable_reset: boolean;
|
||||
}
|
||||
|
||||
export enum busConnectionStatus {
|
||||
|
||||
@@ -548,7 +548,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>
|
||||
@@ -903,6 +903,16 @@ const ApplicationSettings = () => {
|
||||
}
|
||||
label={LL.DEVELOPER_MODE()}
|
||||
/>
|
||||
<BlockFormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={data.disable_reset}
|
||||
onChange={updateFormValue}
|
||||
name="disable_reset"
|
||||
/>
|
||||
}
|
||||
label={LL.DISABLE_RESET()}
|
||||
/>
|
||||
<BlockFormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Grid,
|
||||
MenuItem,
|
||||
TextField,
|
||||
Typography
|
||||
@@ -39,7 +40,12 @@ import { ValidationError, validate } from 'validators';
|
||||
import { NTP_SETTINGS_VALIDATOR } from 'validators/ntp';
|
||||
import type { ValidateFieldsError } from 'validators/schema';
|
||||
|
||||
import { TIME_ZONES, selectedTimeZone, useTimeZoneSelectItems } from './TZ';
|
||||
import {
|
||||
TIME_ZONES,
|
||||
selectedTimeZone,
|
||||
timeZoneSelectItemsT,
|
||||
useTimeZoneSelectItems
|
||||
} from './TZ';
|
||||
|
||||
const NTPSettings = () => {
|
||||
const {
|
||||
@@ -62,11 +68,15 @@ const NTPSettings = () => {
|
||||
useLayoutTitle('NTP');
|
||||
|
||||
const timeZoneItems = useTimeZoneSelectItems();
|
||||
const timeZoneItemsT = timeZoneSelectItemsT();
|
||||
|
||||
const selectedTzValue = data
|
||||
? selectedTimeZone(data.tz_label, data.tz_format)
|
||||
: undefined;
|
||||
|
||||
const selectedTzValueT = data
|
||||
? selectedTimeZone(data.tz_label_t, data.tz_format_t)
|
||||
: undefined;
|
||||
const [localTime, setLocalTime] = useState<string>('');
|
||||
const [settingTime, setSettingTime] = useState<boolean>(false);
|
||||
const [processing, setProcessing] = useState<boolean>(false);
|
||||
@@ -131,6 +141,15 @@ const NTPSettings = () => {
|
||||
updateFormValue(event);
|
||||
};
|
||||
|
||||
const changeTimeZoneT = (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);
|
||||
};
|
||||
|
||||
const renderContent = () => {
|
||||
if (!data) {
|
||||
return <FormLoader onRetry={loadData} errorMessage={errorMessage || ''} />;
|
||||
@@ -154,6 +173,7 @@ const NTPSettings = () => {
|
||||
label={LL.NTP_SERVER()}
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
disabled={!data.enabled}
|
||||
value={data.server}
|
||||
onChange={updateFormValue}
|
||||
margin="normal"
|
||||
@@ -172,7 +192,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' }}>
|
||||
|
||||
@@ -483,3 +483,7 @@ export function useTimeZoneSelectItems() {
|
||||
export function timeZoneSelectItems() {
|
||||
return precomputedTimeZoneItems;
|
||||
}
|
||||
|
||||
export function timeZoneSelectItemsT() {
|
||||
return precomputedTimeZoneItems;
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ interface VersionData {
|
||||
partition: string;
|
||||
partitions: PartitionData[];
|
||||
developer_mode: boolean;
|
||||
disable_reset: boolean;
|
||||
}
|
||||
|
||||
// Memoized components for better performance
|
||||
@@ -923,7 +924,7 @@ const Version = () => {
|
||||
>
|
||||
{LL.RESTART()}
|
||||
</Button>
|
||||
{data.developer_mode && (
|
||||
{!data.disable_reset && (
|
||||
<Button
|
||||
startIcon={<SettingsBackupRestoreIcon />}
|
||||
variant="outlined"
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { CSSProperties } from 'react';
|
||||
|
||||
import { MenuItem, TextField } from '@mui/material';
|
||||
|
||||
import CZflag from 'i18n/CZ.svg';
|
||||
import CZflag from 'i18n/CS.svg';
|
||||
import DEflag from 'i18n/DE.svg';
|
||||
import FRflag from 'i18n/FR.svg';
|
||||
import GBflag from 'i18n/GB.svg';
|
||||
@@ -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' },
|
||||
|
||||
|
Before Width: | Height: | Size: 207 B After Width: | Height: | Size: 207 B |
@@ -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í',
|
||||
@@ -340,6 +340,7 @@ const cz: Translation = {
|
||||
AUTO_SCROLL: 'Automatické rolování',
|
||||
DASHBOARD: 'Dashboard',
|
||||
DEVELOPER_MODE: 'Režim vývojáře',
|
||||
DISABLE_RESET: 'Zakázat obnovení továrního nastavení',
|
||||
BYTES: 'Bajty',
|
||||
BITMASK: 'Bit Mask',
|
||||
DUPLICATE: 'Duplikát',
|
||||
@@ -370,4 +371,4 @@ const cz: Translation = {
|
||||
EXECUTE_COMMAND_SENT: 'Příkaz odeslán',
|
||||
};
|
||||
|
||||
export default cz;
|
||||
export default cs;
|
||||
@@ -340,6 +340,7 @@ const de: Translation = {
|
||||
AUTO_SCROLL: 'Automatisches Scrollen',
|
||||
DASHBOARD: 'Dashboard',
|
||||
DEVELOPER_MODE: 'Entwicklermodus',
|
||||
DISABLE_RESET: 'Werkseinstellungen deaktivieren',
|
||||
BYTES: 'Bytes',
|
||||
BITMASK: 'Bit Maske',
|
||||
DUPLICATE: 'Kopieren',
|
||||
|
||||
@@ -293,11 +293,13 @@ const en: Translation = {
|
||||
TIMER: 'Timer',
|
||||
ONCHANGE: 'On Change',
|
||||
CONDITION: 'Condition',
|
||||
SCHEDULE_UPDATED: 'Schedule updated',
|
||||
SCHEDULE_TIMER_1: 'on startup',
|
||||
SCHEDULE_TIMER_2: 'every minute',
|
||||
SCHEDULE_TIMER_3: 'every hour',
|
||||
CUSTOM_ENTITIES: 'Custom Entities',
|
||||
ENTITIES_HELP_1: 'Define custom EMS entities or dynamic user variables',
|
||||
ENTITIES_UPDATED: 'Entities updated',
|
||||
WRITEABLE: 'Writeable',
|
||||
SHOWING: 'Showing',
|
||||
SEARCH: 'Search',
|
||||
@@ -318,6 +320,7 @@ const en: Translation = {
|
||||
DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware',
|
||||
MODULES: 'Modules',
|
||||
MODULES_1: 'Activate or deactivate external modules',
|
||||
MODULES_UPDATED: 'Modules updated',
|
||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules',
|
||||
MODULES_NONE: 'No external modules detected',
|
||||
RENAME: 'Rename',
|
||||
@@ -337,6 +340,7 @@ const en: Translation = {
|
||||
AUTO_SCROLL: 'Auto Scroll',
|
||||
DASHBOARD: 'Dashboard',
|
||||
DEVELOPER_MODE: 'Developer Mode',
|
||||
DISABLE_RESET: 'Disable Factory Reset',
|
||||
BYTES: 'Bytes',
|
||||
BITMASK: 'Bit Mask',
|
||||
DUPLICATE: 'Duplicate',
|
||||
|
||||
@@ -340,6 +340,7 @@ const fr: Translation = {
|
||||
AUTO_SCROLL: 'Défilement automatique',
|
||||
DASHBOARD: 'Tableau de bord',
|
||||
DEVELOPER_MODE: 'Mode développeur',
|
||||
DISABLE_RESET: 'Désactiver la réinitialisation de fabrique',
|
||||
BYTES: 'Octets',
|
||||
BITMASK: 'Masque de bits',
|
||||
DUPLICATE: 'Dupliquer',
|
||||
|
||||
@@ -340,6 +340,7 @@ const it: Translation = {
|
||||
AUTO_SCROLL: 'Scorrimento automatico',
|
||||
DASHBOARD: 'Pannello di controllo',
|
||||
DEVELOPER_MODE: 'Modalità sviluppatore',
|
||||
DISABLE_RESET: 'Disabilita la ripristino di fabbrica',
|
||||
BYTES: 'Byte',
|
||||
BITMASK: 'Bitmask',
|
||||
DUPLICATE: 'Duplicato',
|
||||
|
||||
@@ -340,6 +340,7 @@ const nl: Translation = {
|
||||
AUTO_SCROLL: 'Automatisch Scrollen',
|
||||
DASHBOARD: 'Dashboard',
|
||||
DEVELOPER_MODE: 'Ontwikkelaarsmodus',
|
||||
DISABLE_RESET: 'Fabrieksinstellingen uitschakelen',
|
||||
BYTES: 'Bytes',
|
||||
BITMASK: 'Bit Mask',
|
||||
DUPLICATE: 'Duplicaat',
|
||||
|
||||
@@ -340,6 +340,7 @@ const no: Translation = {
|
||||
AUTO_SCROLL: 'Automatisk rulling',
|
||||
DASHBOARD: 'Dashboard',
|
||||
DEVELOPER_MODE: 'Utvikler modus',
|
||||
DISABLE_RESET: 'Deaktiver fabrikkinnstillinger',
|
||||
BYTES: 'Bytes',
|
||||
BITMASK: 'Bitmask',
|
||||
DUPLICATE: 'Duplikat',
|
||||
|
||||
@@ -340,6 +340,7 @@ const pl: BaseTranslation = {
|
||||
AUTO_SCROLL: 'Auto Scroll',
|
||||
DASHBOARD: 'Pulpit',
|
||||
DEVELOPER_MODE: 'Tryb programisty',
|
||||
DISABLE_RESET: 'Wyłącz reset fabryczny',
|
||||
BYTES: 'Bajty',
|
||||
BITMASK: 'Bit Mask',
|
||||
DUPLICATE: 'Duplicate',
|
||||
|
||||
@@ -340,6 +340,7 @@ const sk: Translation = {
|
||||
AUTO_SCROLL: 'Automatické rolovanie',
|
||||
DASHBOARD: 'Panel',
|
||||
DEVELOPER_MODE: 'Režim vývojára',
|
||||
DISABLE_RESET: 'Zakázať továrenské nastavenia',
|
||||
BYTES: 'Bytov',
|
||||
BITMASK: 'Bitová maska',
|
||||
DUPLICATE: 'Duplicitné',
|
||||
|
||||
@@ -340,6 +340,7 @@ const sv: Translation = {
|
||||
AUTO_SCROLL: 'Autoskrolla',
|
||||
DASHBOARD: 'Kontrollpanel',
|
||||
DEVELOPER_MODE: 'Utvecklarläge',
|
||||
DISABLE_RESET: 'Inaktivera fabriksåterställning',
|
||||
BYTES: 'Bytes',
|
||||
BITMASK: 'Bitmask',
|
||||
DUPLICATE: 'Dublett',
|
||||
|
||||
@@ -340,6 +340,7 @@ const tr: Translation = {
|
||||
AUTO_SCROLL: 'Otomatik kaydırma',
|
||||
DASHBOARD: 'Kontrol Paneli',
|
||||
DEVELOPER_MODE: 'Geliştirici Modu',
|
||||
DISABLE_RESET: 'Fabrika ayarlarını devre dışı bırak',
|
||||
BYTES: 'Bayt',
|
||||
BITMASK: 'Bit Maskesi',
|
||||
DUPLICATE: 'Çift',
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -61,6 +61,7 @@ export interface SystemStatus {
|
||||
}[];
|
||||
status: number; // System Status Codes which matches SYSTEM_STATUS in System.h
|
||||
developer_mode: boolean;
|
||||
disable_reset: boolean;
|
||||
temperature?: number;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,11 +62,16 @@ MqttClient::MqttClient(espMqttClientTypes::UseInternalTask useInternalTask, uint
|
||||
_xSemaphore = xSemaphoreCreateMutex();
|
||||
EMC_SEMAPHORE_GIVE(); // release before first use
|
||||
if (_useInternalTask == espMqttClientTypes::UseInternalTask::YES) {
|
||||
#ifdef CONFIG_FREERTOS_UNICORE
|
||||
// no core to pin to on single-core targets (S2, C3, C6)
|
||||
xTaskCreate((TaskFunction_t)_loop, "mqttclient", EMC_TASK_STACK_SIZE, this, priority, &_taskHandle);
|
||||
#else
|
||||
if (core > 1) {
|
||||
xTaskCreate((TaskFunction_t)_loop, "mqttclient", EMC_TASK_STACK_SIZE, this, priority, &_taskHandle);
|
||||
} else {
|
||||
xTaskCreatePinnedToCore((TaskFunction_t)_loop, "mqttclient", EMC_TASK_STACK_SIZE, this, priority, &_taskHandle, core);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
(void) useInternalTask;
|
||||
|
||||
@@ -154,8 +154,12 @@ class Outbox {
|
||||
if (!it) return;
|
||||
Node* node = it._node;
|
||||
Node* prev = it._prev;
|
||||
++it;
|
||||
Node* next = node->next;
|
||||
|
||||
_remove(prev, node);
|
||||
|
||||
it._prev = prev;
|
||||
it._node = next;
|
||||
}
|
||||
|
||||
// remove current node, current points to next
|
||||
|
||||
@@ -84,8 +84,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) {};
|
||||
|
||||
@@ -4,16 +4,19 @@
|
||||
"description": "mock api for EMS-ESP",
|
||||
"author": "proddy, emsesp.org",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"mock-rest": "bun --watch restServer.ts",
|
||||
"format": "prettier -l -w '**/*.{ts,tsx,js,css,json,md}'"
|
||||
},
|
||||
"dependencies": {
|
||||
"@msgpack/msgpack": "^3.1.3",
|
||||
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
|
||||
"formidable": "^3.5.4",
|
||||
"itty-router": "^5.0.24",
|
||||
"prettier": "^3.9.5"
|
||||
"itty-router": "^5.0.24"
|
||||
},
|
||||
"packageManager": "pnpm@11.12.0+sha512.820a6fbd0d9f04c226638002aead1e45340a9139dd5dc077c1d83ef44aa2481c8eb6637b4c9aa696a3c7e35ba818e49cf27213e5f2b91138d09b7a3e26e898ba"
|
||||
"devDependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
|
||||
"prettier": "^3.9.6"
|
||||
},
|
||||
"packageManager": "pnpm@11.18.0+sha512.33d83c77da82f49fba836925c6f1b841181ec3132b670639bd012f7075f5c7cf634c5f870147c19aae7478fac01df09d8892e880454896edd23ee9b33757563c"
|
||||
}
|
||||
|
||||
Generated
+39
-38
@@ -11,18 +11,19 @@ importers:
|
||||
'@msgpack/msgpack':
|
||||
specifier: ^3.1.3
|
||||
version: 3.1.3
|
||||
'@trivago/prettier-plugin-sort-imports':
|
||||
specifier: ^6.0.2
|
||||
version: 6.0.2(prettier@3.9.5)
|
||||
formidable:
|
||||
specifier: ^3.5.4
|
||||
version: 3.5.4
|
||||
itty-router:
|
||||
specifier: ^5.0.24
|
||||
version: 5.0.24
|
||||
devDependencies:
|
||||
'@trivago/prettier-plugin-sort-imports':
|
||||
specifier: ^6.0.2
|
||||
version: 6.0.2(prettier@3.9.6)
|
||||
prettier:
|
||||
specifier: ^3.9.5
|
||||
version: 3.9.5
|
||||
specifier: ^3.9.6
|
||||
version: 3.9.6
|
||||
|
||||
packages:
|
||||
|
||||
@@ -30,8 +31,8 @@ packages:
|
||||
resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/generator@7.29.7':
|
||||
resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==}
|
||||
'@babel/generator@7.29.8':
|
||||
resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-globals@7.29.7':
|
||||
@@ -46,8 +47,8 @@ packages:
|
||||
resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/parser@7.29.7':
|
||||
resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==}
|
||||
'@babel/parser@7.29.8':
|
||||
resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
|
||||
@@ -55,12 +56,12 @@ packages:
|
||||
resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/traverse@7.29.7':
|
||||
resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==}
|
||||
'@babel/traverse@7.29.8':
|
||||
resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/types@7.29.7':
|
||||
resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==}
|
||||
'@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 +113,8 @@ packages:
|
||||
balanced-match@1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
|
||||
brace-expansion@2.1.2:
|
||||
resolution: {integrity: sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==}
|
||||
brace-expansion@2.1.4:
|
||||
resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==}
|
||||
|
||||
debug@4.4.3:
|
||||
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
|
||||
@@ -167,8 +168,8 @@ packages:
|
||||
picocolors@1.1.1:
|
||||
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||
|
||||
prettier@3.9.5:
|
||||
resolution: {integrity: sha512-/FVl766LpUfB5vXgCYOYa0MeV/441Ia99AeICQIQFTY/Nw0roZwULcXpku5i1/m5kt/baz+s4Zogspd839HSMg==}
|
||||
prettier@3.9.6:
|
||||
resolution: {integrity: sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
|
||||
@@ -183,10 +184,10 @@ snapshots:
|
||||
js-tokens: 4.0.0
|
||||
picocolors: 1.1.1
|
||||
|
||||
'@babel/generator@7.29.7':
|
||||
'@babel/generator@7.29.8':
|
||||
dependencies:
|
||||
'@babel/parser': 7.29.7
|
||||
'@babel/types': 7.29.7
|
||||
'@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
|
||||
@@ -197,29 +198,29 @@ snapshots:
|
||||
|
||||
'@babel/helper-validator-identifier@7.29.7': {}
|
||||
|
||||
'@babel/parser@7.29.7':
|
||||
'@babel/parser@7.29.8':
|
||||
dependencies:
|
||||
'@babel/types': 7.29.7
|
||||
'@babel/types': 7.29.8
|
||||
|
||||
'@babel/template@7.29.7':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.29.7
|
||||
'@babel/parser': 7.29.7
|
||||
'@babel/types': 7.29.7
|
||||
'@babel/parser': 7.29.8
|
||||
'@babel/types': 7.29.8
|
||||
|
||||
'@babel/traverse@7.29.7':
|
||||
'@babel/traverse@7.29.8':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.29.7
|
||||
'@babel/generator': 7.29.7
|
||||
'@babel/generator': 7.29.8
|
||||
'@babel/helper-globals': 7.29.7
|
||||
'@babel/parser': 7.29.7
|
||||
'@babel/parser': 7.29.8
|
||||
'@babel/template': 7.29.7
|
||||
'@babel/types': 7.29.7
|
||||
'@babel/types': 7.29.8
|
||||
debug: 4.4.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/types@7.29.7':
|
||||
'@babel/types@7.29.8':
|
||||
dependencies:
|
||||
'@babel/helper-string-parser': 7.29.7
|
||||
'@babel/helper-validator-identifier': 7.29.7
|
||||
@@ -246,17 +247,17 @@ snapshots:
|
||||
dependencies:
|
||||
'@noble/hashes': 1.8.0
|
||||
|
||||
'@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.9.5)':
|
||||
'@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.9.6)':
|
||||
dependencies:
|
||||
'@babel/generator': 7.29.7
|
||||
'@babel/parser': 7.29.7
|
||||
'@babel/traverse': 7.29.7
|
||||
'@babel/types': 7.29.7
|
||||
'@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.9.5
|
||||
prettier: 3.9.6
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -264,7 +265,7 @@ snapshots:
|
||||
|
||||
balanced-match@1.0.2: {}
|
||||
|
||||
brace-expansion@2.1.2:
|
||||
brace-expansion@2.1.4:
|
||||
dependencies:
|
||||
balanced-match: 1.0.2
|
||||
|
||||
@@ -295,7 +296,7 @@ snapshots:
|
||||
|
||||
minimatch@9.0.9:
|
||||
dependencies:
|
||||
brace-expansion: 2.1.2
|
||||
brace-expansion: 2.1.4
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
@@ -311,6 +312,6 @@ snapshots:
|
||||
|
||||
picocolors@1.1.1: {}
|
||||
|
||||
prettier@3.9.5: {}
|
||||
prettier@3.9.6: {}
|
||||
|
||||
wrappy@1.0.2: {}
|
||||
|
||||
+21
-6
@@ -64,7 +64,8 @@ let settings = {
|
||||
modbus_port: 502,
|
||||
modbus_max_clients: 10,
|
||||
modbus_timeout: 10000,
|
||||
developer_mode: true
|
||||
developer_mode: true,
|
||||
disable_reset: false
|
||||
};
|
||||
|
||||
// EMS-ESP System Settings
|
||||
@@ -129,6 +130,7 @@ let system_status = {
|
||||
],
|
||||
// partitions: [],
|
||||
developer_mode: settings.developer_mode,
|
||||
disable_reset: settings.disable_reset,
|
||||
model: '',
|
||||
board: '',
|
||||
// model: 'BBQKees Electronics EMS Gateway E32 V2 (E32 V2.0 P3/2024011)',
|
||||
@@ -141,7 +143,7 @@ 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_STABLE_VERSION = '3.8.3';
|
||||
let LATEST_DEV_VERSION = '3.9.0-dev.1';
|
||||
|
||||
// scenarios for testing versioning
|
||||
@@ -1063,6 +1065,18 @@ const emsesp_coredata = {
|
||||
v: '01.20',
|
||||
e: 0,
|
||||
url: 'gateway'
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
tn: 'Connect',
|
||||
t: 12,
|
||||
b: '',
|
||||
n: 'Easy Connect',
|
||||
d: 2,
|
||||
p: 206,
|
||||
v: '12.34',
|
||||
e: 0,
|
||||
url: 'connect'
|
||||
}
|
||||
]
|
||||
};
|
||||
@@ -4173,7 +4187,7 @@ let emsesp_customentities = {
|
||||
writeable: true,
|
||||
hide: false,
|
||||
value:
|
||||
'{"stable":{"version":"3.8.2","date":"2026-05-12"},"dev":{"version":"3.8.3-dev.5","date":"2026-05-28T09:55:29Z"}}'
|
||||
'{"stable":{"version":"3.8.3","date":"2026-08-01"},"dev":{"version":"3.9.0-dev.0","date":"2026-08-01T09:55:29Z"}}'
|
||||
}
|
||||
]
|
||||
};
|
||||
@@ -4709,6 +4723,7 @@ router
|
||||
settings = await request.json();
|
||||
console.log('application settings saved', settings);
|
||||
system_status.developer_mode = settings.developer_mode;
|
||||
system_status.disable_reset = settings.disable_reset;
|
||||
return status(200); // no restart needed
|
||||
// return status(205); // reboot required
|
||||
})
|
||||
@@ -4716,9 +4731,9 @@ router
|
||||
// Device Data
|
||||
.get(EMSESP_CORE_DATA_ENDPOINT, () => {
|
||||
// remove gateway and connect devices
|
||||
emsesp_coredata.devices = emsesp_coredata.devices.filter(
|
||||
(item) => item.t !== 11 && item.t !== 12
|
||||
);
|
||||
// emsesp_coredata.devices = emsesp_coredata.devices.filter(
|
||||
// (item) => item.t !== 11 && item.t !== 12
|
||||
// );
|
||||
// sort by type, like its done in the C++ code
|
||||
let sorted_devices = [...emsesp_coredata.devices].sort((a, b) => a.t - b.t);
|
||||
// append emsesp_coredata to sorted_devices so Custom is always at the end of the list
|
||||
|
||||
+2
-2
@@ -89,8 +89,8 @@ board_build.filesystem = littlefs
|
||||
board_build.littlefs_version = 2.0
|
||||
lib_deps =
|
||||
bblanchon/ArduinoJson @ 7.4.3
|
||||
ESP32Async/AsyncTCP @ 3.4.10
|
||||
ESP32Async/ESPAsyncWebServer @ 3.11.2
|
||||
ESP32Async/AsyncTCP @ 3.5.0
|
||||
ESP32Async/ESPAsyncWebServer @ 3.12.0
|
||||
https://github.com/mobizt/ReadyMail.git @ 0.4.2
|
||||
https://github.com/mobizt/ESP_SSLClient.git @ 3.1.3
|
||||
; https://github.com/emsesp/EMS-ESP-Modules.git @ 1.0.8
|
||||
|
||||
+2
-1
@@ -1342,4 +1342,5 @@ SPIRAM
|
||||
optimisations
|
||||
IILE
|
||||
Sumr
|
||||
eraseap
|
||||
eraseap
|
||||
roomtempoffset
|
||||
@@ -12,8 +12,8 @@ corepack use pnpm@latest
|
||||
pnpm update
|
||||
pnpm install
|
||||
pnpm format
|
||||
pnpm lint
|
||||
pnpm build-webUI
|
||||
pnpm lint
|
||||
|
||||
cd ../mock-api
|
||||
rm -rf node_modules
|
||||
@@ -25,12 +25,13 @@ pnpm format
|
||||
cd ..
|
||||
npx cspell "**"
|
||||
|
||||
# build files that go into docs folder
|
||||
# exit 0
|
||||
|
||||
# platformio run -e build_modbus -t clean
|
||||
# platformio run -e build_modbus
|
||||
# platformio run -e build_standalone -t clean
|
||||
# platformio run -e build_standalone
|
||||
# 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
|
||||
platformio run -e native-test -t exec
|
||||
|
||||
@@ -74,16 +74,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);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "WiFiScanner.h"
|
||||
#include <emsesp.h>
|
||||
|
||||
WiFiScanner::WiFiScanner(AsyncWebServer * server, SecurityManager * securityManager) {
|
||||
securityManager->addEndpoint(server, SCAN_NETWORKS_SERVICE_PATH, AuthenticationPredicates::IS_ADMIN, [this](AsyncWebServerRequest * request) {
|
||||
@@ -20,12 +21,12 @@ void WiFiScanner::scanNetworks(AsyncWebServerRequest * request) {
|
||||
}
|
||||
|
||||
void WiFiScanner::listNetworks(AsyncWebServerRequest * request) {
|
||||
const int numNetworks = WiFi.scanComplete();
|
||||
if (numNetworks > -1) {
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
const int16_t numNetworks = WiFi.scanComplete();
|
||||
if (numNetworks != -1) {
|
||||
auto * response = new emsesp::PsramAsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
JsonArray networks = root["networks"].to<JsonArray>();
|
||||
for (uint8_t i = 0; i < numNetworks; i++) {
|
||||
for (int16_t i = 0; i < numNetworks; i++) {
|
||||
JsonObject network = networks.add<JsonObject>();
|
||||
network["rssi"] = WiFi.RSSI(i);
|
||||
network["ssid"] = WiFi.SSID(i);
|
||||
@@ -35,13 +36,7 @@ void WiFiScanner::listNetworks(AsyncWebServerRequest * request) {
|
||||
}
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
} else if (numNetworks == -1) {
|
||||
request->send(202); // special code to indicate scan in progress
|
||||
} else {
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
root["networks"].to<JsonArray>();
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
request->send(202); // special code to indicate scan in progress
|
||||
}
|
||||
}
|
||||
@@ -537,11 +537,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));
|
||||
|
||||
@@ -382,7 +382,7 @@ uint8_t Command::call(const uint8_t device_type, const char * command, const cha
|
||||
// rather than returning its definition, so skip the value-info lookup and fall through
|
||||
// to the registered command function. The list keywords above are still handled.
|
||||
bool is_named_command = (device_type == EMSdevice::DeviceType::COMMAND) && strcmp(cmd, F_(info)) && strcmp(cmd, F_(values)) && strcmp(cmd, F_(entities))
|
||||
&& strcmp(cmd, F_(metrics));
|
||||
&& strcmp(cmd, F_(metrics)) && !strchr(cmd, '/') && is_admin;
|
||||
if (!is_named_command && EMSESP::get_device_value_info(output, cmd, id, device_type)) { // entity = cmd
|
||||
LOG_DEBUG("Fetched device entity/attributes for %s/%s (id=%d)", dname, cmd, id);
|
||||
return CommandRet::OK;
|
||||
|
||||
@@ -81,6 +81,7 @@ class DeviceValue {
|
||||
HERTZ, // 27 - Hz - frequency
|
||||
CONNECTIVITY, // 28 - used in HA - connectivity
|
||||
TIMESTAMP, // 29 - used in HA - timestamp
|
||||
UPTIME, // 30 - used in HA - uptime for boot time
|
||||
};
|
||||
|
||||
// TAG mapping - maps to DeviceValueTAG_s in emsdevicevalue.cpp
|
||||
|
||||
+1
-1
@@ -1799,8 +1799,8 @@ void EMSESP::start() {
|
||||
// this will also handle any MQTT subscriptions
|
||||
webCustomizationService.begin(); // load the customizations
|
||||
webCommandService.begin(); // load the user commands
|
||||
webSchedulerService.begin(); // load the scheduler events
|
||||
webCustomEntityService.begin(); // load the custom telegram reads
|
||||
webSchedulerService.begin(); // load the scheduler events
|
||||
|
||||
// perform any system upgrades
|
||||
if (!factory_settings) {
|
||||
|
||||
+14
-1
@@ -814,7 +814,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"
|
||||
@@ -1030,4 +1030,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);
|
||||
|
||||
+1
-1
@@ -131,7 +131,7 @@ void LED::led_fast_flash() {
|
||||
set_led(led_flash_state_ ? Color::YELLOW : Color::OFF); // Yellow
|
||||
}
|
||||
|
||||
// after duration, turn off the LED
|
||||
// after duration, turn off the LED, and call the format command
|
||||
if (current_time - led_flash_start_time_ >= led_flash_duration_) {
|
||||
set_led(Color::OFF);
|
||||
led_fast_flash_timer_ = false;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -369,7 +369,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")
|
||||
|
||||
@@ -637,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
|
||||
|
||||
+5
-2
@@ -587,7 +587,7 @@ void Mqtt::ha_status() {
|
||||
|
||||
// These come from the info MQTT topic - and handled in the publish_ha_sensor_config function
|
||||
publish_system_ha_sensor_config(DeviceValueType::STRING, "Version", "version", DeviceValueUOM::NONE);
|
||||
publish_system_ha_sensor_config(DeviceValueType::STRING, "Boot time", "bootTime", DeviceValueUOM::TIMESTAMP);
|
||||
publish_system_ha_sensor_config(DeviceValueType::STRING, "Boot time", "bootTime", DeviceValueUOM::UPTIME);
|
||||
}
|
||||
|
||||
// add sub or pub task to the queue.
|
||||
@@ -1178,7 +1178,7 @@ void Mqtt::add_ha_classes(JsonObject doc, const uint8_t device_type, const uint8
|
||||
doc[uom_ha] = "L/h";
|
||||
} else if (uom == DeviceValueUOM::L) {
|
||||
doc[uom_ha] = "L";
|
||||
} else if (uom == DeviceValueUOM::TIMESTAMP) {
|
||||
} else if (uom == DeviceValueUOM::TIMESTAMP || uom == DeviceValueUOM::UPTIME) {
|
||||
// do nothing
|
||||
} else if (uom != DeviceValueUOM::NONE) {
|
||||
auto uom_str = EMSdevice::uom_to_string(uom);
|
||||
@@ -1280,6 +1280,9 @@ void Mqtt::add_ha_classes(JsonObject doc, const uint8_t device_type, const uint8
|
||||
doc[sc_ha] = sc_ha_measurement;
|
||||
doc[dc_ha] = "timestamp";
|
||||
break;
|
||||
case DeviceValueUOM::UPTIME:
|
||||
doc[dc_ha] = "uptime";
|
||||
break;
|
||||
case DeviceValueUOM::MV:
|
||||
case DeviceValueUOM::VOLTS:
|
||||
doc[sc_ha] = sc_ha_measurement;
|
||||
|
||||
+24
-37
@@ -299,8 +299,8 @@ void Roomctrl::temperature(uint8_t addr, uint8_t dst, uint8_t hc) {
|
||||
if (type_[hc] == RC20) { // RC20, telegram 0xAF
|
||||
data[2] = 0xAF;
|
||||
data[3] = 0;
|
||||
data[4] = (uint8_t)(remotetemp_[hc] >> 8);
|
||||
data[5] = (uint8_t)(remotetemp_[hc] & 0xFF);
|
||||
data[4] = static_cast<uint8_t>(remotetemp_[hc] >> 8);
|
||||
data[5] = static_cast<uint8_t>(remotetemp_[hc] & 0xFF);
|
||||
data[6] = 0;
|
||||
data[7] = EMSbus::calculate_crc(data, 7); // append CRC
|
||||
EMSuart::transmit(data, 8);
|
||||
@@ -309,8 +309,8 @@ void Roomctrl::temperature(uint8_t addr, uint8_t dst, uint8_t hc) {
|
||||
data[3] = 0;
|
||||
data[4] = 0;
|
||||
data[5] = 0x23; // fixed for all hc
|
||||
data[6] = (uint8_t)(remotetemp_[hc] >> 8);
|
||||
data[7] = (uint8_t)(remotetemp_[hc] & 0xFF);
|
||||
data[6] = static_cast<uint8_t>(remotetemp_[hc] >> 8);
|
||||
data[7] = static_cast<uint8_t>(remotetemp_[hc] & 0xFF);
|
||||
data[8] = EMSbus::calculate_crc(data, 8); // append CRC
|
||||
EMSuart::transmit(data, 9);
|
||||
} else if (type_[hc] == RC200) { // RC200, telegram 42B, ff
|
||||
@@ -318,11 +318,11 @@ void Roomctrl::temperature(uint8_t addr, uint8_t dst, uint8_t hc) {
|
||||
data[3] = 0;
|
||||
data[4] = 3;
|
||||
data[5] = 0x2B + hc;
|
||||
data[6] = (uint8_t)(remotetemp_[hc] >> 8);
|
||||
data[7] = (uint8_t)(remotetemp_[hc] & 0xFF);
|
||||
data[6] = static_cast<uint8_t>(remotetemp_[hc] >> 8);
|
||||
data[7] = static_cast<uint8_t>(remotetemp_[hc] & 0xFF);
|
||||
uint16_t t1 = remotetemp_[hc] * 10;
|
||||
data[8] = (uint8_t)(t1 >> 8);
|
||||
data[9] = (uint8_t)(t1 & 0xFF);
|
||||
data[8] = static_cast<uint8_t>(t1 >> 8);
|
||||
data[9] = static_cast<uint8_t>(t1 & 0xFF);
|
||||
data[10] = 1; // not sure what this is and if we need it, maybe mode?
|
||||
data[11] = EMSbus::calculate_crc(data, 11); // append CRC
|
||||
EMSuart::transmit(data, 12);
|
||||
@@ -331,8 +331,8 @@ void Roomctrl::temperature(uint8_t addr, uint8_t dst, uint8_t hc) {
|
||||
data[3] = 0;
|
||||
data[4] = 3;
|
||||
data[5] = 0x2B + hc;
|
||||
data[6] = (uint8_t)(remotetemp_[hc] >> 8);
|
||||
data[7] = (uint8_t)(remotetemp_[hc] & 0xFF);
|
||||
data[6] = static_cast<uint8_t>(remotetemp_[hc] >> 8);
|
||||
data[7] = static_cast<uint8_t>(remotetemp_[hc] & 0xFF);
|
||||
data[8] = EMSbus::calculate_crc(data, 8); // append CRC
|
||||
EMSuart::transmit(data, 9);
|
||||
} else if (type_[hc] == SENSOR) { // wireless sensor, broadcast id 435
|
||||
@@ -340,8 +340,8 @@ void Roomctrl::temperature(uint8_t addr, uint8_t dst, uint8_t hc) {
|
||||
data[3] = 0;
|
||||
data[4] = 3;
|
||||
data[5] = 0x35 + hc;
|
||||
data[6] = (uint8_t)(remotetemp_[hc] >> 8);
|
||||
data[7] = (uint8_t)(remotetemp_[hc] & 0xFF);
|
||||
data[6] = static_cast<uint8_t>(remotetemp_[hc] >> 8);
|
||||
data[7] = static_cast<uint8_t>(remotetemp_[hc] & 0xFF);
|
||||
data[8] = EMSbus::calculate_crc(data, 8); // append CRC
|
||||
EMSuart::transmit(data, 9);
|
||||
} else if (type_[hc] == RT800) { // RC200, telegram 42B, ff
|
||||
@@ -349,11 +349,11 @@ void Roomctrl::temperature(uint8_t addr, uint8_t dst, uint8_t hc) {
|
||||
data[3] = 0;
|
||||
data[4] = 3;
|
||||
data[5] = 0x2B + hc;
|
||||
data[6] = (uint8_t)(remotetemp_[hc] >> 8);
|
||||
data[7] = (uint8_t)(remotetemp_[hc] & 0xFF);
|
||||
data[6] = static_cast<uint8_t>(remotetemp_[hc] >> 8);
|
||||
data[7] = static_cast<uint8_t>(remotetemp_[hc] & 0xFF);
|
||||
uint16_t t1 = remotetemp_[hc] * 10;
|
||||
data[8] = (uint8_t)(t1 >> 8);
|
||||
data[9] = (uint8_t)(t1 & 0xFF);
|
||||
data[8] = static_cast<uint8_t>(t1 >> 8);
|
||||
data[9] = static_cast<uint8_t>(t1 & 0xFF);
|
||||
data[10] = 1; // not sure what this is and if we need it, maybe mode?
|
||||
data[11] = 9; // not sure what this is and if we need it, maybe mode?
|
||||
data[12] = EMSbus::calculate_crc(data, 12); // append CRC
|
||||
@@ -363,11 +363,11 @@ void Roomctrl::temperature(uint8_t addr, uint8_t dst, uint8_t hc) {
|
||||
data[3] = 0;
|
||||
data[4] = 3;
|
||||
data[5] = 0x2B + hc;
|
||||
data[6] = (uint8_t)(remotetemp_[hc] >> 8);
|
||||
data[7] = (uint8_t)(remotetemp_[hc] & 0xFF);
|
||||
data[6] = static_cast<uint8_t>(remotetemp_[hc] >> 8);
|
||||
data[7] = static_cast<uint8_t>(remotetemp_[hc] & 0xFF);
|
||||
uint16_t t1 = remotetemp_[hc] * 10;
|
||||
data[8] = (uint8_t)(t1 >> 8);
|
||||
data[9] = (uint8_t)(t1 & 0xFF);
|
||||
data[8] = static_cast<uint8_t>(t1 >> 8);
|
||||
data[9] = static_cast<uint8_t>(t1 & 0xFF);
|
||||
data[10] = 0; // not sure what this is and if we need it
|
||||
data[11] = 0; // not sure what this is and if we need it
|
||||
data[12] = EMSbus::calculate_crc(data, 12); // append CRC
|
||||
@@ -377,7 +377,7 @@ 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 = calc_dew(remotetemp_[hc], remotehum_[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);
|
||||
@@ -391,8 +391,8 @@ void Roomctrl::humidity(uint8_t addr, uint8_t dst, uint8_t hc) {
|
||||
data[5] = 0x7B + hc;
|
||||
data[6] = static_cast<uint8_t>(dew8);
|
||||
data[7] = remotehum_[hc];
|
||||
data[8] = static_cast<uint8_t>(static_cast<uint16_t>(dew) >> 8);
|
||||
data[9] = static_cast<uint8_t>(static_cast<uint16_t>(dew) & 0xFF);
|
||||
data[8] = static_cast<uint8_t>(dew >> 8);
|
||||
data[9] = static_cast<uint8_t>(dew & 0x00FF);
|
||||
data[10] = EMSbus::calculate_crc(data, 10); // append CRC
|
||||
EMSuart::transmit(data, 11);
|
||||
}
|
||||
@@ -440,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
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -34,8 +34,7 @@ class Roomctrl {
|
||||
static bool is_remote(const uint8_t hc) {
|
||||
return (hc < 4 && remotetemp_[hc] != EMS_VALUE_INT16_NOTSET);
|
||||
}
|
||||
static void set_timeout(uint8_t t);
|
||||
static int16_t calc_dew(int16_t temp, uint8_t hum);
|
||||
static void set_timeout(uint8_t t);
|
||||
|
||||
private:
|
||||
static constexpr uint32_t SEND_INTERVAL = 15000; // 15 sec
|
||||
|
||||
@@ -42,17 +42,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;
|
||||
}
|
||||
@@ -862,6 +853,7 @@ std::string compute(const std::string & expr) {
|
||||
}
|
||||
result = json.as<std::string>();
|
||||
}
|
||||
expr_new.replace(f, e - f, result.c_str());
|
||||
}
|
||||
}
|
||||
expr_new.replace(f, e - f, result);
|
||||
@@ -918,4 +910,4 @@ std::string compute(const std::string & expr) {
|
||||
return calculate(expr_new);
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
} // namespace emsesp
|
||||
|
||||
+20
-2
@@ -71,7 +71,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 *);
|
||||
@@ -677,6 +677,7 @@ void System::store_settings(WebSettings & settings) {
|
||||
locale_ = settings.locale;
|
||||
system_name_ = settings.system_name;
|
||||
developer_mode_ = settings.developer_mode;
|
||||
disable_reset_ = settings.disable_reset;
|
||||
}
|
||||
|
||||
// Starts up core services
|
||||
@@ -761,6 +762,10 @@ void System::button_OnLongPress(PButton & b) {
|
||||
|
||||
// button indefinite press
|
||||
void System::button_OnVLongPress(PButton & b) {
|
||||
if (EMSESP::system_.disable_reset()) {
|
||||
LOG_NOTICE("Factory reset disabled");
|
||||
return;
|
||||
}
|
||||
LOG_NOTICE("Button pressed - very long press - perform factory reset");
|
||||
EMSESP::led_.start_led_fast_flash(5); // Start LED flash timer for 5 seconds
|
||||
}
|
||||
@@ -1632,6 +1637,11 @@ bool System::check_upgrade() {
|
||||
return StateUpdateResult::CHANGED;
|
||||
}
|
||||
}
|
||||
// Migrate language from cz to cs
|
||||
if (settings.locale == "cz") {
|
||||
settings.locale = "cs";
|
||||
return StateUpdateResult::CHANGED;
|
||||
}
|
||||
return StateUpdateResult::UNCHANGED;
|
||||
});
|
||||
} else if (this_version < settings_version) {
|
||||
@@ -1958,7 +1968,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);
|
||||
@@ -2639,6 +2651,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output
|
||||
node["modbusEnabled"] = settings.modbus_enabled;
|
||||
node["forceHeatingOff"] = settings.boiler_heatingoff;
|
||||
node["developerMode"] = settings.developer_mode;
|
||||
node["disableReset"] = settings.disable_reset;
|
||||
});
|
||||
|
||||
// Devices - show EMS devices if we have any
|
||||
@@ -2863,6 +2876,11 @@ bool System::command_txpause(const char * value, const int8_t id) {
|
||||
|
||||
// format command - factory reset, removing all config files
|
||||
bool System::command_format(const char * value, const int8_t id) {
|
||||
if (EMSESP::system_.disable_reset()) {
|
||||
LOG_NOTICE("Factory reset disabled");
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(EMSESP_STANDALONE) && !defined(EMSESP_TEST)
|
||||
// don't really format the filesystem in test or standalone mode
|
||||
if (LittleFS.format()) {
|
||||
|
||||
@@ -199,6 +199,14 @@ class System {
|
||||
developer_mode_ = developer_mode;
|
||||
}
|
||||
|
||||
bool disable_reset() {
|
||||
return disable_reset_;
|
||||
}
|
||||
|
||||
void disable_reset(bool disable_reset) {
|
||||
disable_reset_ = disable_reset;
|
||||
}
|
||||
|
||||
// Boolean Format API/MQTT
|
||||
uint8_t bool_format() {
|
||||
return bool_format_;
|
||||
@@ -438,6 +446,7 @@ class System {
|
||||
uint8_t modbus_max_clients_;
|
||||
uint32_t modbus_timeout_;
|
||||
bool developer_mode_;
|
||||
bool disable_reset_;
|
||||
uint32_t fstotal_;
|
||||
uint32_t psram_;
|
||||
uint32_t appused_;
|
||||
|
||||
+81
-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,7 +89,7 @@ void Connect::process_RCTime(const 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);
|
||||
@@ -133,16 +134,8 @@ void Connect::process_roomThermostat(const std::shared_ptr<const Telegram> & tel
|
||||
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 +161,33 @@ void Connect::process_roomThermostatSettings(const std::shared_ptr<const Telegra
|
||||
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 +218,53 @@ void Connect::process_roomSchedule(const std::shared_ptr<const Telegram> & teleg
|
||||
toggle_fetch(telegram->type_id, false); // fetch only once if all is initialized
|
||||
}
|
||||
|
||||
void Connect::process_roomConfig(const 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 +278,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 +288,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;
|
||||
|
||||
@@ -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,6 +65,7 @@ class Connect : public EMSdevice {
|
||||
void process_roomThermostatParam(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_roomThermostatData(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_roomSchedule(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_roomConfig(const 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);
|
||||
|
||||
+82
-29
@@ -816,7 +816,6 @@ void Thermostat::process_RemoteTemp(const std::shared_ptr<const Telegram> & tele
|
||||
// e.g. "38 10 FF 00 03 7B 08 24 00 4B"
|
||||
void Thermostat::process_RemoteHumidity(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// has_update(telegram, dewtemperature_, 0); // this is int8
|
||||
|
||||
// some thermostats use short telegram with int8 dewpoint, https://github.com/emsesp/EMS-ESP32/issues/1491
|
||||
// but it's not a dewpoint in offset 0, removed, see https://github.com/emsesp/EMS-ESP32/issues/3135
|
||||
has_update(telegram, humidity_, 1);
|
||||
@@ -825,7 +824,8 @@ void Thermostat::process_RemoteHumidity(const std::shared_ptr<const Telegram> &
|
||||
if (telegram->read_value(dew, 2)) {
|
||||
has_update(dewtemperature_, dew);
|
||||
} else if (telegram->offset == 0 && telegram->message_length < 4) {
|
||||
has_update(dewtemperature_, Roomctrl::calc_dew(tempsensor1_, humidity_));
|
||||
dew = Helpers::calc_dew(tempsensor1_, humidity_);
|
||||
has_update(dewtemperature_, dew);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1477,9 +1477,14 @@ void Thermostat::process_HPSet(const std::shared_ptr<const Telegram> & 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
|
||||
@@ -1737,9 +1742,18 @@ void Thermostat::process_RCTime(const 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];
|
||||
@@ -1755,20 +1769,27 @@ void Thermostat::process_RCTime(const 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++;
|
||||
}
|
||||
@@ -1778,10 +1799,6 @@ void Thermostat::process_RCTime(const 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
|
||||
@@ -1932,7 +1949,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;
|
||||
@@ -3061,6 +3082,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;
|
||||
}
|
||||
@@ -3076,10 +3106,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[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
|
||||
@@ -3087,10 +3114,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;
|
||||
@@ -3101,7 +3153,8 @@ bool Thermostat::set_datetime(const char * value, const int8_t id) {
|
||||
}
|
||||
|
||||
if (model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
|
||||
data[6]++; // Junkers use 1-7 for day of the week
|
||||
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]);
|
||||
|
||||
+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(0x7A5, 4, b ? 0xFF : 0x00, 0x7A5);
|
||||
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.9.0-dev.16"
|
||||
#define EMSESP_APP_VERSION "3.9.0-dev.0"
|
||||
|
||||
@@ -39,6 +39,12 @@ WebAPIService::WebAPIService(AsyncWebServer * server, SecurityManager * security
|
||||
// POST|GET api/{device}
|
||||
// POST|GET api/{device}/{entity}
|
||||
void WebAPIService::webAPIService(AsyncWebServerRequest * request, JsonVariant json) {
|
||||
static bool busy = false;
|
||||
if (busy && request->method() == HTTP_GET) {
|
||||
request->send(429); // too many requests
|
||||
return;
|
||||
}
|
||||
busy = true;
|
||||
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
|
||||
@@ -53,6 +59,7 @@ void WebAPIService::webAPIService(AsyncWebServerRequest * request, JsonVariant j
|
||||
input["data"] = json.as<std::string>();
|
||||
}
|
||||
parse(request, input);
|
||||
busy = false;
|
||||
}
|
||||
|
||||
// for POSTS accepting plain text data
|
||||
|
||||
@@ -318,10 +318,19 @@ bool WebCommandService::get_value_info(JsonObject output, const char * cmd) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!strlen(cmd) || !strcmp(cmd, F_(values)) || !strcmp(cmd, F_(info))) {
|
||||
if (!strlen(cmd) || !strcmp(cmd, F_(values))) {
|
||||
for (const CommandItem & ci : *commandItems_) {
|
||||
if (ci.name[0] != '\0') {
|
||||
output[(const char *)ci.name] = ci.cmd;
|
||||
output[(const char *)ci.name] = ci.value.c_str();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!strcmp(cmd, F_(info))) {
|
||||
for (const CommandItem & ci : *commandItems_) {
|
||||
if (ci.name[0] != '\0') {
|
||||
output[(const char *)ci.name] = std::string(ci.cmd + ": " + ci.value);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -364,7 +373,7 @@ std::string WebCommandService::get_metrics_prometheus() {
|
||||
if (ci.name[0] == '\0') {
|
||||
continue;
|
||||
}
|
||||
result += (std::string) "# HELP emsesp_cmd_" + ci.name + " " + ci.name + "\n";
|
||||
result += (std::string) "# HELP emsesp_cmd_" + ci.name + " " + ci.name + ", readable, writable, visible\n";
|
||||
result += (std::string) "# TYPE emsesp_cmd_" + ci.name + " gauge\n";
|
||||
result += (std::string) "emsesp_cmd_" + ci.name + " 1\n";
|
||||
}
|
||||
@@ -372,15 +381,14 @@ std::string WebCommandService::get_metrics_prometheus() {
|
||||
}
|
||||
|
||||
void WebCommandService::get_value_json(JsonObject output, const CommandItem & ci) {
|
||||
output["name"] = (const char *)ci.name;
|
||||
// output["fullname"] = (const char *)ci.name;
|
||||
// output["type"] = "command";
|
||||
output["command"] = ci.cmd;
|
||||
output["value"] = ci.value;
|
||||
// bool hasName = ci.name[0] != '\0';
|
||||
// output["readable"] = hasName;
|
||||
// output["writeable"] = hasName;
|
||||
// output["visible"] = hasName;
|
||||
output["name"] = (const char *)ci.name;
|
||||
output["fullname"] = (const char *)ci.name;
|
||||
output["type"] = "string";
|
||||
output["command"] = ci.cmd;
|
||||
output["value"] = ci.value;
|
||||
output["readable"] = true;
|
||||
output["writeable"] = true;
|
||||
output["visible"] = true;
|
||||
}
|
||||
|
||||
void WebCommandService::publish(const bool force) {
|
||||
@@ -395,7 +403,7 @@ void WebCommandService::publish(const bool force) {
|
||||
JsonObject output = doc.to<JsonObject>();
|
||||
for (const CommandItem & ci : *commandItems_) {
|
||||
if (ci.name[0] != '\0' && !output[ci.name].is<JsonVariantConst>()) {
|
||||
output[(const char *)ci.name] = ci.cmd;
|
||||
output[(const char *)ci.name] = ci.value.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -415,13 +417,13 @@ std::string WebCustomEntityService::get_metrics_prometheus() {
|
||||
|
||||
// build the json for specific entity
|
||||
void WebCustomEntityService::get_value_json(JsonObject output, CustomEntityItem const & entity) {
|
||||
output["name"] = (const char *)entity.name;
|
||||
output["fullname"] = (const char *)entity.name;
|
||||
output["storage"] = entity.ram == 1 ? "ram" : entity.ram == 2 ? "nvs" : "ems";
|
||||
output["type"] = entity.value_type == DeviceValueType::BOOL ? "boolean" : entity.value_type == DeviceValueType::STRING ? "string" : F_(number);
|
||||
// output["readable"] = true;
|
||||
output["name"] = (const char *)entity.name;
|
||||
output["fullname"] = (const char *)entity.name;
|
||||
output["storage"] = entity.ram == 1 ? "ram" : entity.ram == 2 ? "nvs" : "ems";
|
||||
output["type"] = entity.value_type == DeviceValueType::BOOL ? "boolean" : entity.value_type == DeviceValueType::STRING ? "string" : F_(number);
|
||||
output["readable"] = true;
|
||||
output["writeable"] = entity.writeable;
|
||||
// output["visible"] = true;
|
||||
output["visible"] = true;
|
||||
|
||||
if (entity.ram == 0) {
|
||||
output["device_id"] = Helpers::hextoa(entity.device_id);
|
||||
|
||||
+11
-14
@@ -64,20 +64,17 @@ void WebDataService::core_data(AsyncWebServerRequest * request) {
|
||||
// list is already sorted by device type
|
||||
JsonArray devices = root["devices"].to<JsonArray>();
|
||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||
// ignore controller and gateway
|
||||
if (emsdevice && (emsdevice->device_type() != EMSdevice::DeviceType::CONTROLLER && emsdevice->device_type() != EMSdevice::DeviceType::GATEWAY && emsdevice->count_entities() > 0)) {
|
||||
JsonObject obj = devices.add<JsonObject>();
|
||||
obj["id"] = emsdevice->unique_id(); // a unique id
|
||||
obj["tn"] = emsdevice->device_type_2_device_name_translated(); // translated device type name
|
||||
obj["t"] = emsdevice->device_type(); // device type number
|
||||
obj["b"] = emsdevice->brand_to_char(); // brand (std::string → copied into doc, safe across async serialize)
|
||||
obj["n"] = emsdevice->name(); // custom name
|
||||
obj["d"] = emsdevice->device_id(); // deviceid
|
||||
obj["p"] = emsdevice->product_id(); // productid
|
||||
obj["v"] = emsdevice->version(); // version
|
||||
obj["e"] = emsdevice->count_entities(); // number of entities
|
||||
obj["url"] = emsdevice->device_type_name(); // non-translated, lower-case, used for API URL in customization page
|
||||
}
|
||||
JsonObject obj = devices.add<JsonObject>();
|
||||
obj["id"] = emsdevice->unique_id(); // a unique id
|
||||
obj["tn"] = emsdevice->device_type_2_device_name_translated(); // translated device type name
|
||||
obj["t"] = emsdevice->device_type(); // device type number
|
||||
obj["b"] = emsdevice->brand_to_char(); // brand (std::string → copied into doc, safe across async serialize)
|
||||
obj["n"] = emsdevice->name(); // custom name
|
||||
obj["d"] = emsdevice->device_id(); // deviceid
|
||||
obj["p"] = emsdevice->product_id(); // productid
|
||||
obj["v"] = emsdevice->version(); // version
|
||||
obj["e"] = emsdevice->count_entities(); // number of entities
|
||||
obj["url"] = emsdevice->device_type_name(); // non-translated, lower-case, used for API URL in customization page
|
||||
}
|
||||
|
||||
// add any custom entities
|
||||
|
||||
@@ -203,7 +203,7 @@ void WebSchedulerService::get_value_json(JsonObject output, const ScheduleItem &
|
||||
output["name"] = (const char *)scheduleItem.name;
|
||||
output["fullname"] = (const char *)scheduleItem.name;
|
||||
output["type"] = "boolean";
|
||||
Mqtt::add_value_bool(output, "active", scheduleItem.active);
|
||||
Mqtt::add_value_bool(output, "value", scheduleItem.active);
|
||||
if (scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_CONDITION) {
|
||||
output["condition"] = scheduleItem.time;
|
||||
} else if (scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_ONCHANGE) {
|
||||
@@ -213,11 +213,10 @@ void WebSchedulerService::get_value_json(JsonObject output, const ScheduleItem &
|
||||
} else {
|
||||
output["time"] = scheduleItem.time;
|
||||
}
|
||||
output["cmd_name"] = scheduleItem.cmd_name;
|
||||
// bool hasName = scheduleItem.name[0] != '\0';
|
||||
// output["readable"] = hasName;
|
||||
// output["writeable"] = hasName;
|
||||
// output["visible"] = hasName;
|
||||
output["cmd_name"] = scheduleItem.cmd_name;
|
||||
output["readable"] = true;
|
||||
output["writeable"] = true;
|
||||
output["visible"] = true;
|
||||
}
|
||||
|
||||
// publish single value
|
||||
@@ -370,6 +369,10 @@ void WebSchedulerService::loop() {
|
||||
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()) {
|
||||
|
||||
@@ -84,6 +84,7 @@ void WebSettings::read(WebSettings & settings, JsonObject root) {
|
||||
root["modbus_max_clients"] = settings.modbus_max_clients;
|
||||
root["modbus_timeout"] = settings.modbus_timeout;
|
||||
root["developer_mode"] = settings.developer_mode;
|
||||
root["disable_reset"] = settings.disable_reset;
|
||||
root["email_enabled"] = settings.email_enabled;
|
||||
root["email_security"] = settings.email_security;
|
||||
root["email_server"] = settings.email_server;
|
||||
@@ -306,6 +307,9 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
|
||||
settings.developer_mode = root["developer_mode"];
|
||||
EMSESP::system_.developer_mode(settings.developer_mode);
|
||||
|
||||
settings.disable_reset = root["disable_reset"];
|
||||
EMSESP::system_.disable_reset(settings.disable_reset);
|
||||
|
||||
settings.bool_dashboard = root["bool_dashboard"] | EMSESP_DEFAULT_BOOL_FORMAT;
|
||||
EMSESP::system_.bool_dashboard(settings.bool_dashboard);
|
||||
|
||||
|
||||
@@ -121,6 +121,7 @@ class WebSettings {
|
||||
uint8_t eth_clock_mode;
|
||||
|
||||
bool developer_mode; // developer mode
|
||||
bool disable_reset; // disable reset
|
||||
|
||||
static void read(WebSettings & settings, JsonObject root);
|
||||
static StateUpdateResult update(JsonObject root, WebSettings & settings);
|
||||
|
||||
@@ -172,6 +172,7 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
|
||||
}
|
||||
|
||||
root["developer_mode"] = EMSESP::system_.developer_mode();
|
||||
root["disable_reset"] = EMSESP::system_.disable_reset();
|
||||
|
||||
// Also used in SystemMonitor.tsx
|
||||
root["status"] = EMSESP::system_.systemStatus(); // send the status. See System.h for status codes
|
||||
@@ -247,6 +248,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;
|
||||
}
|
||||
|
||||
@@ -365,13 +367,13 @@ void WebStatusService::getVersions(JsonObject root) {
|
||||
#else
|
||||
// standalone/test build: provide deterministic dummy data
|
||||
JsonObject stable_out = root["stable"].to<JsonObject>();
|
||||
stable_out["version"] = "3.8.2";
|
||||
stable_out["date"] = "2026-04-25";
|
||||
stable_out["upgradeable"] = FirmwareVersion("3.8.2") > current_version;
|
||||
stable_out["version"] = "3.8.3";
|
||||
stable_out["date"] = "2026-08-01";
|
||||
stable_out["upgradeable"] = FirmwareVersion("3.8.3") > current_version;
|
||||
|
||||
JsonObject dev_out = root["dev"].to<JsonObject>();
|
||||
dev_out["version"] = "3.9.0-dev.1";
|
||||
dev_out["date"] = "2026-04-25";
|
||||
dev_out["date"] = "2026-08-02";
|
||||
dev_out["upgradeable"] = FirmwareVersion("3.9.0-dev.1") > current_version;
|
||||
#endif
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,103 +0,0 @@
|
||||
{
|
||||
"Boiler Nefit Trendline HRC30 (DeviceID:0x08, ProductID:123, Version:06.01)": {
|
||||
"force heating off": "off",
|
||||
"heating active": "off",
|
||||
"tapwater active": "off",
|
||||
"selected flow temperature": 5,
|
||||
"heating pump modulation": 0,
|
||||
"current flow temperature": 41.4,
|
||||
"return temperature": 37.7,
|
||||
"system pressure": 1.3,
|
||||
"actual boiler temperature": 44.2,
|
||||
"gas": "off",
|
||||
"gas stage 2": "off",
|
||||
"flame current": 0,
|
||||
"fan": "off",
|
||||
"ignition": "off",
|
||||
"oil preheating": "off",
|
||||
"burner min power": 0,
|
||||
"burner max power": 50,
|
||||
"burner min period": 10,
|
||||
"hysteresis on temperature": -6,
|
||||
"hysteresis off temperature": 6,
|
||||
"heating activated": "on",
|
||||
"heating temperature": 70,
|
||||
"heating pump": "off",
|
||||
"boiler pump max power": 70,
|
||||
"boiler pump min power": 50,
|
||||
"boiler pump mode": "proportional",
|
||||
"pump delay": 2,
|
||||
"burner selected max power": 0,
|
||||
"burner current power": 0,
|
||||
"burner starts": 394602,
|
||||
"total burner operating time": "480 days 4 hours 23 minutes",
|
||||
"burner stage 2 operating time": "0 days 0 hours 0 minutes",
|
||||
"total heat operating time": "395 days 2 hours 14 minutes",
|
||||
"burner starts heating": 46245,
|
||||
"total UBA operating time": "3932 days 23 hours 58 minutes",
|
||||
"last error code": "2E(207) 100.75.2000 65:00 (0 min)",
|
||||
"service code": "0H",
|
||||
"service code number": 203,
|
||||
"maintenance message": "H00",
|
||||
"maintenance scheduled": "manual",
|
||||
"time to next maintenance": 6000,
|
||||
"next maintenance date": "01.01.2012",
|
||||
"dhw turn on/off": "on",
|
||||
"dhw set temperature": 62,
|
||||
"dhw selected temperature": 60,
|
||||
"dhw type": "flow",
|
||||
"dhw comfort": "hot",
|
||||
"dhw flow temperature offset": 40,
|
||||
"dhw max power": 100,
|
||||
"dhw circulation pump available": "off",
|
||||
"dhw charging type": "3-way valve",
|
||||
"dhw hysteresis on temperature": -5,
|
||||
"dhw hysteresis off temperature": 0,
|
||||
"dhw disinfection temperature": 70,
|
||||
"dhw circulation pump mode": "off",
|
||||
"dhw circulation active": "off",
|
||||
"dhw current intern temperature": 33.5,
|
||||
"dhw current tap water flow": 0,
|
||||
"dhw storage intern temperature": 33.5,
|
||||
"dhw activated": "on",
|
||||
"dhw one time charging": "off",
|
||||
"dhw disinfecting": "off",
|
||||
"dhw charging": "off",
|
||||
"dhw recharging": "off",
|
||||
"dhw temperature ok": "on",
|
||||
"dhw active": "off",
|
||||
"dhw 3-way valve active": "on",
|
||||
"dhw set pump power": 0,
|
||||
"dhw starts": 348357,
|
||||
"dhw active time": "85 days 2 hours 9 minutes",
|
||||
"nominal Power": 30,
|
||||
"total energy": 3088.69,
|
||||
"energy heating": 2532.94,
|
||||
"dhw energy": 555.75
|
||||
},
|
||||
"Thermostat RC20 (DeviceID:0x17, ProductID:77, Version:03.03)": {
|
||||
"date/time": "10.12.2023 13:49",
|
||||
"hc1 how hot lounge should be": 19,
|
||||
"hc1 current room temp": 19.5,
|
||||
"hc1 mqtt discovery current room temperature": "roomTemp",
|
||||
"hc1 mode": "auto",
|
||||
"hc1 manual temperature": 21.5,
|
||||
"hc1 temperature when mode is off": 7,
|
||||
"hc1 day temperature T2": 20,
|
||||
"hc1 day temperature T3": 20,
|
||||
"hc1 day temperature T4": 20,
|
||||
"hc1 night temperature T1": 15,
|
||||
"hc1 program switchtime": "00 mo 00:00 T1"
|
||||
},
|
||||
"Controller Module BC10 (DeviceID:0x09, ProductID:190, Version:01.03)": {},
|
||||
"Custom Entities": {
|
||||
"boiler_flowtemp": 5,
|
||||
"nominalpower": 30,
|
||||
"minmodulation": 23,
|
||||
"maxmodulation": 115
|
||||
},
|
||||
"Analog Sensors": {},
|
||||
"Temperature Sensors": {
|
||||
"zolder": 18.3
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
{
|
||||
"type": "customizations",
|
||||
"Customizations": {
|
||||
"ts": [],
|
||||
"as": [],
|
||||
"masked_entities": [
|
||||
{
|
||||
"product_id": 77,
|
||||
"device_id": 23,
|
||||
"custom_name": "",
|
||||
"custom_brand": "",
|
||||
"entity_ids": [
|
||||
"08datetime",
|
||||
"08hc1/seltemp|<30",
|
||||
"08hc1/currtemp",
|
||||
"08hc1/mode"
|
||||
]
|
||||
},
|
||||
{
|
||||
"product_id": 123,
|
||||
"device_id": 8,
|
||||
"custom_name": "",
|
||||
"custom_brand": "",
|
||||
"entity_ids": [
|
||||
"08heatingactive",
|
||||
"08burngas",
|
||||
"08fanwork",
|
||||
"08ignwork",
|
||||
"08burnmaxpower|>23<121",
|
||||
"08burnminperiod|<120",
|
||||
"08lastcode",
|
||||
"08servicecode"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"type": "entities",
|
||||
"Entities": {
|
||||
"entities": []
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"type": "schedule",
|
||||
"Schedule": {
|
||||
"schedule": []
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
{
|
||||
"type": "settings",
|
||||
"System": {
|
||||
"version": "3.8.2"
|
||||
},
|
||||
"Network": {
|
||||
"ssid": "",
|
||||
"bssid": "",
|
||||
"password": "",
|
||||
"hostname": "ems-esp",
|
||||
"static_ip_config": false,
|
||||
"bandwidth20": false,
|
||||
"nosleep": true,
|
||||
"enableMDNS": true,
|
||||
"enableCORS": false,
|
||||
"CORSOrigin": "*",
|
||||
"tx_power": 0
|
||||
},
|
||||
"AP": {
|
||||
"provision_mode": 2,
|
||||
"ssid": "ems-esp",
|
||||
"password": "ems-esp-neo",
|
||||
"channel": 1,
|
||||
"ssid_hidden": false,
|
||||
"max_clients": 4,
|
||||
"local_ip": "192.168.4.1",
|
||||
"gateway_ip": "192.168.4.1",
|
||||
"subnet_mask": "255.255.255.0"
|
||||
},
|
||||
"MQTT": {
|
||||
"enableTLS": false,
|
||||
"rootCA": "",
|
||||
"enabled": true,
|
||||
"host": "192.168.X.X",
|
||||
"port": 1883,
|
||||
"base": "ems-esp",
|
||||
"username": "xxxx",
|
||||
"password": "xxxx",
|
||||
"client_id": "esp32-395c7bcc",
|
||||
"keep_alive": 60,
|
||||
"clean_session": false,
|
||||
"entity_format": 1,
|
||||
"publish_time_boiler": 60,
|
||||
"publish_time_thermostat": 60,
|
||||
"publish_time_solar": 60,
|
||||
"publish_time_mixer": 60,
|
||||
"publish_time_water": 60,
|
||||
"publish_time_other": 60,
|
||||
"publish_time_sensor": 60,
|
||||
"publish_time_heartbeat": 10,
|
||||
"mqtt_qos": 0,
|
||||
"mqtt_retain": false,
|
||||
"ha_enabled": true,
|
||||
"nested_format": 1,
|
||||
"discovery_prefix": "homeassistant",
|
||||
"discovery_type": 0,
|
||||
"ha_number_mode": 1,
|
||||
"publish_single": false,
|
||||
"publish_single2cmd": false,
|
||||
"send_response": false
|
||||
},
|
||||
"NTP": {
|
||||
"enabled": true,
|
||||
"server": "time.google.com",
|
||||
"tz_label": "Europe/Amsterdam",
|
||||
"tz_format": "CET-1CEST,M3.5.0,M10.5.0/3"
|
||||
},
|
||||
"Security": {
|
||||
"jwt_secret": "ems-esp-neo",
|
||||
"users": [
|
||||
{
|
||||
"username": "admin",
|
||||
"password": "admin",
|
||||
"admin": true
|
||||
},
|
||||
{
|
||||
"username": "guest",
|
||||
"password": "guest",
|
||||
"admin": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"Settings": {
|
||||
"version": "3.8.2",
|
||||
"board_profile": "E32V2",
|
||||
"platform": "ESP32",
|
||||
"locale": "en",
|
||||
"tx_mode": 1,
|
||||
"ems_bus_id": 11,
|
||||
"syslog_enabled": false,
|
||||
"syslog_level": 3,
|
||||
"trace_raw": false,
|
||||
"syslog_mark_interval": 0,
|
||||
"syslog_host": "",
|
||||
"syslog_port": 514,
|
||||
"boiler_heatingoff": false,
|
||||
"remote_timeout": 24,
|
||||
"remote_timeout_en": false,
|
||||
"shower_timer": true,
|
||||
"shower_alert": false,
|
||||
"shower_alert_coldshot": 10,
|
||||
"shower_alert_trigger": 7,
|
||||
"shower_min_duration": 180,
|
||||
"rx_gpio": 4,
|
||||
"tx_gpio": 5,
|
||||
"dallas_gpio": 14,
|
||||
"dallas_parasite": false,
|
||||
"led_gpio": 2,
|
||||
"hide_led": true,
|
||||
"led_type": 0,
|
||||
"low_clock": false,
|
||||
"telnet_enabled": true,
|
||||
"notoken_api": false,
|
||||
"readonly_mode": false,
|
||||
"analog_enabled": true,
|
||||
"pbutton_gpio": 34,
|
||||
"solar_maxflow": 30,
|
||||
"fahrenheit": false,
|
||||
"bool_format": 1,
|
||||
"bool_dashboard": 1,
|
||||
"enum_format": 1,
|
||||
"weblog_level": 6,
|
||||
"weblog_buffer": 500,
|
||||
"weblog_compact": true,
|
||||
"phy_type": 1,
|
||||
"eth_power": 15,
|
||||
"eth_phy_addr": 0,
|
||||
"eth_clock_mode": 1,
|
||||
"modbus_enabled": false,
|
||||
"modbus_port": 502,
|
||||
"modbus_max_clients": 10,
|
||||
"modbus_timeout": 300,
|
||||
"developer_mode": true,
|
||||
"email_enabled": false,
|
||||
"email_security": 2,
|
||||
"email_server": "smtp.example.net",
|
||||
"email_port": 587,
|
||||
"email_login": "",
|
||||
"email_pass": "",
|
||||
"email_sender": "ems-esp@example.net",
|
||||
"email_recp": "",
|
||||
"email_subject": "ems-esp notification"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"type": "systembackup",
|
||||
"version": "3.8.2",
|
||||
"date": "2026-04-15T08:06:45",
|
||||
"version": "3.9.0",
|
||||
"date": "2026-08-02T08:06:45",
|
||||
"systembackup": [
|
||||
{
|
||||
"type": "settings",
|
||||
@@ -83,7 +83,7 @@
|
||||
]
|
||||
},
|
||||
"Settings": {
|
||||
"version": "3.8.2",
|
||||
"version": "3.9.0",
|
||||
"board_profile": "E32V2",
|
||||
"platform": "ESP32",
|
||||
"locale": "en",
|
||||
@@ -132,7 +132,8 @@
|
||||
"modbus_port": 502,
|
||||
"modbus_max_clients": 10,
|
||||
"modbus_timeout": 300,
|
||||
"developer_mode": true
|
||||
"developer_mode": true,
|
||||
"disable_reset": false
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user