mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-09-13 21:54:07 +00:00
Merge remote-tracking branch 'emsesp/core3' into core3
This commit is contained in:
@@ -5,6 +5,44 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [3.8.2] 12 May 2026
|
||||
|
||||
## Added
|
||||
|
||||
- comfortpoint for BC400 [#2935](https://github.com/emsesp/EMS-ESP32/issues/2935)
|
||||
- customize device brand [#2784](https://github.com/emsesp/EMS-ESP32/issues/2784)
|
||||
- set model for ems-esp devices temperature, analog, etc. [#2958](https://github.com/emsesp/EMS-ESP32/discussions/2958)
|
||||
- prometheus metrics for temperature/analog/scheduler/custom [#2962](https://github.com/emsesp/EMS-ESP32/issues/2962)
|
||||
- boiler pumpkick [#2965](https://github.com/emsesp/EMS-ESP32/discussions/2965)
|
||||
- heatpump reset [#2933](https://github.com/emsesp/EMS-ESP32/issues/2933)
|
||||
- 2.nd freshwater module (dhw4, dhw5) [#2991](https://github.com/emsesp/EMS-ESP32/issues/2991)
|
||||
- full system backup and restore
|
||||
- auto-logic to set ht3/ems+ tx-mode
|
||||
- polariity for digital_in sensors [#3070](https://github.com/emsesp/EMS-ESP32/discussions/3070)
|
||||
|
||||
## Fixed
|
||||
|
||||
- SRC climate creation [#2936](https://github.com/emsesp/EMS-ESP32/issues/2936) and [#2960](https://github.com/emsesp/EMS-ESP32/issues/2960)
|
||||
- missing translations [#3015](https://github.com/emsesp/EMS-ESP32/issues/3015)
|
||||
- custom entities check fetch length
|
||||
- modbus initialization [#3064](https://github.com/emsesp/EMS-ESP32/issues/3064)
|
||||
|
||||
## Changed
|
||||
|
||||
- weblogbuffer up to 1000 messages with PSRAM, mentioned in [#2933](https://github.com/emsesp/EMS-ESP32/issues/2933)
|
||||
- validate custom entity writes, [#2931](https://github.com/emsesp/EMS-ESP32/issues/2931)
|
||||
- remove wrong burnMinPower [#2918](https://github.com/emsesp/EMS-ESP32/issues/2918)
|
||||
- store scheduler active state to nvs [#2946](https://github.com/emsesp/EMS-ESP32/discussions/2946)
|
||||
- translated modes `heat` and `eco` for HA-climate mode-str-tpl
|
||||
- support `minflowtemp` and `baseflowtemp` [#2969](https://github.com/emsesp/EMS-ESP32/discussions/2969)
|
||||
- update version if it is 00.00 in first read [#2981](https://github.com/emsesp/EMS-ESP32/issues/2981)
|
||||
- device class for % values [#2980](https://github.com/emsesp/EMS-ESP32/issues/2980)
|
||||
- fetch telegrams: set length to fetch [#3017](https://github.com/emsesp/EMS-ESP32/issues/3017)
|
||||
- move http client from stack to heap
|
||||
- heap optimizations [#3021](https://github.com/emsesp/EMS-ESP32/discussions/3021)
|
||||
- check and read 0x470 as summer2_typeids[0] only if received [#2686](https://github.com/emsesp/EMS-ESP32/issues/2686), [#3055](https://github.com/emsesp/EMS-ESP32/issues/3055)
|
||||
- default bus-id: gateway1(0x49), tx-mode: auto
|
||||
|
||||
## [3.8.1] 11 January 2026
|
||||
|
||||
## Added
|
||||
|
||||
+3
-32
@@ -6,43 +6,14 @@ For more details go to [emsesp.org](https://emsesp.org/).
|
||||
|
||||
## Added
|
||||
|
||||
- comfortpoint for BC400 [#2935](https://github.com/emsesp/EMS-ESP32/issues/2935)
|
||||
- customize device brand [#2784](https://github.com/emsesp/EMS-ESP32/issues/2784)
|
||||
- set model for ems-esp devices temperature, analog, etc. [#2958](https://github.com/emsesp/EMS-ESP32/discussions/2958)
|
||||
- prometheus metrics for temperature/analog/scheduler/custom [#2962](https://github.com/emsesp/EMS-ESP32/issues/2962)
|
||||
- boiler pumpkick [#2965](https://github.com/emsesp/EMS-ESP32/discussions/2965)
|
||||
- heatpump reset [#2933](https://github.com/emsesp/EMS-ESP32/issues/2933)
|
||||
- e-mail notification using ReadyMail Client
|
||||
- 2.nd freshwater module (dhw4, dhw5) [#2991](https://github.com/emsesp/EMS-ESP32/issues/2991)
|
||||
- full system backup and restore
|
||||
- updated version check [#3047](https://github.com/emsesp/EMS-ESP32/issues/3047)
|
||||
- auto-logic to set ht3/ems+ tx-mode
|
||||
- polarity for digital_in sensors [#3070](https://github.com/emsesp/EMS-ESP32/discussions/3070)
|
||||
- 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)
|
||||
|
||||
## Fixed
|
||||
|
||||
- SRC climate creation [#2936](https://github.com/emsesp/EMS-ESP32/issues/2936) and [#2960](https://github.com/emsesp/EMS-ESP32/issues/2960)
|
||||
- missing translations [#3015](https://github.com/emsesp/EMS-ESP32/issues/3015)
|
||||
- custom entities check fetch length
|
||||
- modbus initialization [#3064](https://github.com/emsesp/EMS-ESP32/issues/3064)
|
||||
- signed value for solarInfuence [#3077](https://github.com/emsesp/EMS-ESP32/issues/3077)
|
||||
|
||||
## Changed
|
||||
|
||||
- weblogbuffer up to 1000 messages with PSRAM, mentioned in [#2933](https://github.com/emsesp/EMS-ESP32/issues/2933)
|
||||
- validate custom entity writes, [#2931](https://github.com/emsesp/EMS-ESP32/issues/2931)
|
||||
- remove wrong burnMinPower [#2918](https://github.com/emsesp/EMS-ESP32/issues/2918)
|
||||
- store scheduler active state to nvs [#2946](https://github.com/emsesp/EMS-ESP32/discussions/2946)
|
||||
- translated modes `heat` and `eco` for HA-climate mode-str-tpl
|
||||
- support `minflowtemp` and `baseflowtemp` [#2969](https://github.com/emsesp/EMS-ESP32/discussions/2969)
|
||||
- update version if it is 00.00 in first read [#2981](https://github.com/emsesp/EMS-ESP32/issues/2981)
|
||||
- device class for % values [#2980](https://github.com/emsesp/EMS-ESP32/issues/2980)
|
||||
- use tasmota core 2026.03.30
|
||||
- secure mqtt uses ESP_SSLClient
|
||||
- fetch telegrams: set length to fetch [#3017](https://github.com/emsesp/EMS-ESP32/issues/3017)
|
||||
- move http client from stack to heap
|
||||
- heap optimizations [#3021](https://github.com/emsesp/EMS-ESP32/discussions/3021)
|
||||
- refactored network code into a single class [#3052](https://github.com/emsesp/EMS-ESP32/pull/3052)
|
||||
- check and read 0x470 as summer2_typeids[0] only if received [#2686](https://github.com/emsesp/EMS-ESP32/issues/2686), [#3055](https://github.com/emsesp/EMS-ESP32/issues/3055)
|
||||
- default bus-id: gateway1(0x49), tx-mode: auto
|
||||
- various memory optimizations [#3083](https://github.com/emsesp/EMS-ESP32/issues/3083)
|
||||
- network fallback to AP only after start [#3090](https://github.com/emsesp/EMS-ESP32/issues/3090)
|
||||
@@ -113,8 +113,8 @@ CXX := /usr/bin/g++
|
||||
CPPFLAGS += $(DEFINES) $(DEFAULTS) $(INCLUDE)
|
||||
CPPFLAGS += -ggdb -g3 -MMD
|
||||
CPPFLAGS += -flto=auto
|
||||
CPPFLAGS += -Wall -Wextra -Werror -Wno-switch-enum
|
||||
CPPFLAGS += -Wno-unused-parameter -Wno-missing-braces -Wno-vla-cxx-extension
|
||||
CPPFLAGS += -Wall -Wextra -Werror
|
||||
CPPFLAGS += -Wno-unused-parameter -Wno-missing-braces -Wno-vla-cxx-extension -Wno-switch-enum -Wno-unused-lambda-capture
|
||||
CPPFLAGS += -ffunction-sections -fdata-sections -fno-exceptions -fno-rtti -fno-threadsafe-statics
|
||||
CPPFLAGS += -Os -DNDEBUG
|
||||
|
||||
|
||||
@@ -5376,9 +5376,9 @@ uint8
|
||||
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
|
||||
int8
|
||||
| hc1.redthreshold | reduction threshold | int8 (>=12<=22) | C | true | HC | 56 | 1 | 1/2 |
|
||||
uint8
|
||||
| hc1.solarinfl | solar influence | uint8 (>=-5<=4294967295) | C | true | HC | 57 | 1 | 1 |
|
||||
| hc1.currsolarinfl | current solar influence | uint8 | C | false | HC | 58 | 1 | 1/10 |
|
||||
int8
|
||||
| hc1.solarinfl | solar influence | int8 (>=-5<=0) | C | true | HC | 57 | 1 | 1 |
|
||||
| hc1.currsolarinfl | current solar influence | int8 | C | false | HC | 58 | 1 | 1/10 |
|
||||
| hc1.heatingpid | heating PID | enum | | true | HC | 59 | 1 | 1 |
|
||||
| hc1.pumpopt | pump optimization | boolean | | true | HC | 60 | 1 | 1 |
|
||||
uint8
|
||||
@@ -5985,9 +5985,9 @@ uint8
|
||||
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
|
||||
int8
|
||||
| hc1.redthreshold | reduction threshold | int8 (>=12<=22) | C | true | HC | 56 | 1 | 1/2 |
|
||||
uint8
|
||||
| hc1.solarinfl | solar influence | uint8 (>=-5<=4294967295) | C | true | HC | 57 | 1 | 1 |
|
||||
| hc1.currsolarinfl | current solar influence | uint8 | C | false | HC | 58 | 1 | 1/10 |
|
||||
int8
|
||||
| hc1.solarinfl | solar influence | int8 (>=-5<=0) | C | true | HC | 57 | 1 | 1 |
|
||||
| hc1.currsolarinfl | current solar influence | int8 | C | false | HC | 58 | 1 | 1/10 |
|
||||
| hc1.heatingpid | heating PID | enum | | true | HC | 59 | 1 | 1 |
|
||||
| hc1.pumpopt | pump optimization | boolean | | true | HC | 60 | 1 | 1 |
|
||||
uint8
|
||||
@@ -6137,9 +6137,9 @@ uint8
|
||||
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
|
||||
int8
|
||||
| hc1.redthreshold | reduction threshold | int8 (>=12<=22) | C | true | HC | 56 | 1 | 1/2 |
|
||||
uint8
|
||||
| hc1.solarinfl | solar influence | uint8 (>=-5<=4294967295) | C | true | HC | 57 | 1 | 1 |
|
||||
| hc1.currsolarinfl | current solar influence | uint8 | C | false | HC | 58 | 1 | 1/10 |
|
||||
int8
|
||||
| hc1.solarinfl | solar influence | int8 (>=-5<=0) | C | true | HC | 57 | 1 | 1 |
|
||||
| hc1.currsolarinfl | current solar influence | int8 | C | false | HC | 58 | 1 | 1/10 |
|
||||
| hc1.heatingpid | heating PID | enum | | true | HC | 59 | 1 | 1 |
|
||||
| hc1.pumpopt | pump optimization | boolean | | true | HC | 60 | 1 | 1 |
|
||||
uint8
|
||||
@@ -6304,9 +6304,9 @@ uint8
|
||||
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
|
||||
int8
|
||||
| hc1.redthreshold | reduction threshold | int8 (>=12<=22) | C | true | HC | 56 | 1 | 1/2 |
|
||||
uint8
|
||||
| hc1.solarinfl | solar influence | uint8 (>=-5<=4294967295) | C | true | HC | 57 | 1 | 1 |
|
||||
| hc1.currsolarinfl | current solar influence | uint8 | C | false | HC | 58 | 1 | 1/10 |
|
||||
int8
|
||||
| hc1.solarinfl | solar influence | int8 (>=-5<=0) | C | true | HC | 57 | 1 | 1 |
|
||||
| hc1.currsolarinfl | current solar influence | int8 | C | false | HC | 58 | 1 | 1/10 |
|
||||
| hc1.heatingpid | heating PID | enum | | true | HC | 59 | 1 | 1 |
|
||||
| hc1.pumpopt | pump optimization | boolean | | true | HC | 60 | 1 | 1 |
|
||||
uint8
|
||||
@@ -6498,9 +6498,9 @@ uint8
|
||||
| hc1.switchprogmode | switch program mode | enum | | true | HC | 55 | 1 | 1 |
|
||||
int8
|
||||
| hc1.redthreshold | reduction threshold | int8 (>=12<=22) | C | true | HC | 56 | 1 | 1/2 |
|
||||
uint8
|
||||
| hc1.solarinfl | solar influence | uint8 (>=-5<=4294967295) | C | true | HC | 57 | 1 | 1 |
|
||||
| hc1.currsolarinfl | current solar influence | uint8 | C | false | HC | 58 | 1 | 1/10 |
|
||||
int8
|
||||
| hc1.solarinfl | solar influence | int8 (>=-5<=0) | C | true | HC | 57 | 1 | 1 |
|
||||
| hc1.currsolarinfl | current solar influence | int8 | C | false | HC | 58 | 1 | 1/10 |
|
||||
| hc1.heatingpid | heating PID | enum | | true | HC | 59 | 1 | 1 |
|
||||
| hc1.pumpopt | pump optimization | boolean | | true | HC | 60 | 1 | 1 |
|
||||
uint8
|
||||
|
||||
+10
-10
@@ -4057,8 +4057,8 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
|
||||
"UI800, BC400",thermostat,4,hc1.cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,54,1
|
||||
"UI800, BC400",thermostat,4,hc1.switchprogmode,switch program mode,enum [level\|absolute] (>=0<=0), ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,55,1
|
||||
"UI800, BC400",thermostat,4,hc1.redthreshold,reduction threshold,int8 (>=12<=22),C,true,number.thermostat_hc1_reduction_threshold,number.thermostat_hc1_redthreshold,6,1,1/2,56,1
|
||||
"UI800, BC400",thermostat,4,hc1.solarinfl,solar influence,uint8 (>=-5<=4294967295),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
|
||||
"UI800, BC400",thermostat,4,hc1.currsolarinfl,current solar influence,uint8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
|
||||
"UI800, BC400",thermostat,4,hc1.solarinfl,solar influence,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
|
||||
"UI800, BC400",thermostat,4,hc1.currsolarinfl,current solar influence,int8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
|
||||
"UI800, BC400",thermostat,4,hc1.heatingpid,heating PID,enum [fast\|medium\|slow] (>=0<=0), ,true,select.thermostat_hc1_heating_PID,select.thermostat_hc1_heatingpid,6,1,1,59,1
|
||||
"UI800, BC400",thermostat,4,hc1.pumpopt,pump optimization,boolean (>=0<=0), ,true,switch.thermostat_hc1_pump_optimization,switch.thermostat_hc1_pumpopt,6,1,1,60,1
|
||||
"UI800, BC400",thermostat,4,hc1.inttimefloor,integral time floor,uint8 (>=160<=320),minutes,true,number.thermostat_hc1_integral_time_floor,number.thermostat_hc1_inttimefloor,6,1,10,61,1
|
||||
@@ -4447,8 +4447,8 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
|
||||
"RC200, CW100, CR120, CR50",thermostat,157,hc1.cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,54,1
|
||||
"RC200, CW100, CR120, CR50",thermostat,157,hc1.switchprogmode,switch program mode,enum [level\|absolute] (>=0<=0), ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,55,1
|
||||
"RC200, CW100, CR120, CR50",thermostat,157,hc1.redthreshold,reduction threshold,int8 (>=12<=22),C,true,number.thermostat_hc1_reduction_threshold,number.thermostat_hc1_redthreshold,6,1,1/2,56,1
|
||||
"RC200, CW100, CR120, CR50",thermostat,157,hc1.solarinfl,solar influence,uint8 (>=-5<=4294967295),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
|
||||
"RC200, CW100, CR120, CR50",thermostat,157,hc1.currsolarinfl,current solar influence,uint8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
|
||||
"RC200, CW100, CR120, CR50",thermostat,157,hc1.solarinfl,solar influence,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
|
||||
"RC200, CW100, CR120, CR50",thermostat,157,hc1.currsolarinfl,current solar influence,int8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
|
||||
"RC200, CW100, CR120, CR50",thermostat,157,hc1.heatingpid,heating PID,enum [fast\|medium\|slow] (>=0<=0), ,true,select.thermostat_hc1_heating_PID,select.thermostat_hc1_heatingpid,6,1,1,59,1
|
||||
"RC200, CW100, CR120, CR50",thermostat,157,hc1.pumpopt,pump optimization,boolean (>=0<=0), ,true,switch.thermostat_hc1_pump_optimization,switch.thermostat_hc1_pumpopt,6,1,1,60,1
|
||||
"RC200, CW100, CR120, CR50",thermostat,157,hc1.inttimefloor,integral time floor,uint8 (>=160<=320),minutes,true,number.thermostat_hc1_integral_time_floor,number.thermostat_hc1_inttimefloor,6,1,10,61,1
|
||||
@@ -4545,8 +4545,8 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
|
||||
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,54,1
|
||||
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.switchprogmode,switch program mode,enum [level\|absolute] (>=0<=0), ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,55,1
|
||||
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.redthreshold,reduction threshold,int8 (>=12<=22),C,true,number.thermostat_hc1_reduction_threshold,number.thermostat_hc1_redthreshold,6,1,1/2,56,1
|
||||
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.solarinfl,solar influence,uint8 (>=-5<=4294967295),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
|
||||
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.currsolarinfl,current solar influence,uint8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
|
||||
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.solarinfl,solar influence,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
|
||||
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.currsolarinfl,current solar influence,int8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
|
||||
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.heatingpid,heating PID,enum [fast\|medium\|slow] (>=0<=0), ,true,select.thermostat_hc1_heating_PID,select.thermostat_hc1_heatingpid,6,1,1,59,1
|
||||
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.pumpopt,pump optimization,boolean (>=0<=0), ,true,switch.thermostat_hc1_pump_optimization,switch.thermostat_hc1_pumpopt,6,1,1,60,1
|
||||
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.inttimefloor,integral time floor,uint8 (>=160<=320),minutes,true,number.thermostat_hc1_integral_time_floor,number.thermostat_hc1_inttimefloor,6,1,10,61,1
|
||||
@@ -4652,8 +4652,8 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
|
||||
"Rego 2000/3000",thermostat,172,hc1.cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,54,1
|
||||
"Rego 2000/3000",thermostat,172,hc1.switchprogmode,switch program mode,enum [level\|absolute] (>=0<=0), ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,55,1
|
||||
"Rego 2000/3000",thermostat,172,hc1.redthreshold,reduction threshold,int8 (>=12<=22),C,true,number.thermostat_hc1_reduction_threshold,number.thermostat_hc1_redthreshold,6,1,1/2,56,1
|
||||
"Rego 2000/3000",thermostat,172,hc1.solarinfl,solar influence,uint8 (>=-5<=4294967295),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
|
||||
"Rego 2000/3000",thermostat,172,hc1.currsolarinfl,current solar influence,uint8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
|
||||
"Rego 2000/3000",thermostat,172,hc1.solarinfl,solar influence,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
|
||||
"Rego 2000/3000",thermostat,172,hc1.currsolarinfl,current solar influence,int8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
|
||||
"Rego 2000/3000",thermostat,172,hc1.heatingpid,heating PID,enum [fast\|medium\|slow] (>=0<=0), ,true,select.thermostat_hc1_heating_PID,select.thermostat_hc1_heatingpid,6,1,1,59,1
|
||||
"Rego 2000/3000",thermostat,172,hc1.pumpopt,pump optimization,boolean (>=0<=0), ,true,switch.thermostat_hc1_pump_optimization,switch.thermostat_hc1_pumpopt,6,1,1,60,1
|
||||
"Rego 2000/3000",thermostat,172,hc1.inttimefloor,integral time floor,uint8 (>=160<=320),minutes,true,number.thermostat_hc1_integral_time_floor,number.thermostat_hc1_inttimefloor,6,1,10,61,1
|
||||
@@ -4777,8 +4777,8 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
|
||||
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,54,1
|
||||
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.switchprogmode,switch program mode,enum [level\|absolute] (>=0<=0), ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,55,1
|
||||
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.redthreshold,reduction threshold,int8 (>=12<=22),C,true,number.thermostat_hc1_reduction_threshold,number.thermostat_hc1_redthreshold,6,1,1/2,56,1
|
||||
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.solarinfl,solar influence,uint8 (>=-5<=4294967295),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
|
||||
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.currsolarinfl,current solar influence,uint8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
|
||||
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.solarinfl,solar influence,int8 (>=-5<=0),C,true,number.thermostat_hc1_solar_influence,number.thermostat_hc1_solarinfl,6,1,1,57,1
|
||||
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.currsolarinfl,current solar influence,int8,C,false,sensor.thermostat_hc1_current_solar_influence,sensor.thermostat_hc1_currsolarinfl,6,1,1/10,58,1
|
||||
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.heatingpid,heating PID,enum [fast\|medium\|slow] (>=0<=0), ,true,select.thermostat_hc1_heating_PID,select.thermostat_hc1_heatingpid,6,1,1,59,1
|
||||
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.pumpopt,pump optimization,boolean (>=0<=0), ,true,switch.thermostat_hc1_pump_optimization,switch.thermostat_hc1_pumpopt,6,1,1,60,1
|
||||
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.inttimefloor,integral time floor,uint8 (>=160<=320),minutes,true,number.thermostat_hc1_integral_time_floor,number.thermostat_hc1_inttimefloor,6,1,10,61,1
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -34,7 +34,7 @@
|
||||
"etag": "^1.8.1",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"mime-types": "^3.0.2",
|
||||
"preact": "^10.29.1",
|
||||
"preact": "^10.29.2",
|
||||
"react": "^19.2.6",
|
||||
"react-dom": "^19.2.6",
|
||||
"react-icons": "^5.6.0",
|
||||
@@ -47,8 +47,8 @@
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@preact/preset-vite": "^2.10.5",
|
||||
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
|
||||
"@types/node": "^25.8.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/node": "^25.9.1",
|
||||
"@types/react": "^19.2.15",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"concurrently": "^9.2.1",
|
||||
"eslint": "^10.4.0",
|
||||
@@ -56,7 +56,7 @@
|
||||
"prettier": "^3.8.3",
|
||||
"rollup-plugin-visualizer": "^7.0.1",
|
||||
"terser": "^5.47.1",
|
||||
"typescript-eslint": "^8.59.3",
|
||||
"typescript-eslint": "^8.59.4",
|
||||
"vite": "^8.0.13",
|
||||
"vite-plugin-imagemin": "^0.6.1"
|
||||
},
|
||||
|
||||
Generated
+166
-166
@@ -13,19 +13,19 @@ importers:
|
||||
version: 2.3.1(alova@3.5.1)
|
||||
'@emotion/react':
|
||||
specifier: ^11.14.0
|
||||
version: 11.14.0(@types/react@19.2.14)(react@19.2.6)
|
||||
version: 11.14.0(@types/react@19.2.15)(react@19.2.6)
|
||||
'@emotion/styled':
|
||||
specifier: ^11.14.1
|
||||
version: 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6)
|
||||
version: 11.14.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6)
|
||||
'@mui/icons-material':
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1(@mui/material@9.0.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@types/react@19.2.14)(react@19.2.6)
|
||||
version: 9.0.1(@mui/material@9.0.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@types/react@19.2.15)(react@19.2.6)
|
||||
'@mui/material':
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
|
||||
version: 9.0.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
|
||||
'@table-library/react-table-library':
|
||||
specifier: 4.1.15
|
||||
version: 4.1.15(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
|
||||
version: 4.1.15(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
|
||||
alova:
|
||||
specifier: ^3.5.1
|
||||
version: 3.5.1
|
||||
@@ -42,8 +42,8 @@ importers:
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2
|
||||
preact:
|
||||
specifier: ^10.29.1
|
||||
version: 10.29.1
|
||||
specifier: ^10.29.2
|
||||
version: 10.29.2
|
||||
react:
|
||||
specifier: ^19.2.6
|
||||
version: 19.2.6
|
||||
@@ -71,19 +71,19 @@ importers:
|
||||
version: 10.0.1(eslint@10.4.0)
|
||||
'@preact/preset-vite':
|
||||
specifier: ^2.10.5
|
||||
version: 2.10.5(@babel/core@7.29.0)(preact@10.29.1)(rollup@4.59.0)(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1))
|
||||
version: 2.10.5(@babel/core@7.29.0)(preact@10.29.2)(rollup@4.59.0)(vite@8.0.13(@types/node@25.9.1)(terser@5.47.1))
|
||||
'@trivago/prettier-plugin-sort-imports':
|
||||
specifier: ^6.0.2
|
||||
version: 6.0.2(prettier@3.8.3)
|
||||
'@types/node':
|
||||
specifier: ^25.8.0
|
||||
version: 25.8.0
|
||||
specifier: ^25.9.1
|
||||
version: 25.9.1
|
||||
'@types/react':
|
||||
specifier: ^19.2.14
|
||||
version: 19.2.14
|
||||
specifier: ^19.2.15
|
||||
version: 19.2.15
|
||||
'@types/react-dom':
|
||||
specifier: ^19.2.3
|
||||
version: 19.2.3(@types/react@19.2.14)
|
||||
version: 19.2.3(@types/react@19.2.15)
|
||||
concurrently:
|
||||
specifier: ^9.2.1
|
||||
version: 9.2.1
|
||||
@@ -103,14 +103,14 @@ importers:
|
||||
specifier: ^5.47.1
|
||||
version: 5.47.1
|
||||
typescript-eslint:
|
||||
specifier: ^8.59.3
|
||||
version: 8.59.3(eslint@10.4.0)(typescript@6.0.3)
|
||||
specifier: ^8.59.4
|
||||
version: 8.59.4(eslint@10.4.0)(typescript@6.0.3)
|
||||
vite:
|
||||
specifier: ^8.0.13
|
||||
version: 8.0.13(@types/node@25.8.0)(terser@5.47.1)
|
||||
version: 8.0.13(@types/node@25.9.1)(terser@5.47.1)
|
||||
vite-plugin-imagemin:
|
||||
specifier: ^0.6.1
|
||||
version: 0.6.1(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1))
|
||||
version: 0.6.1(vite@8.0.13(@types/node@25.9.1)(terser@5.47.1))
|
||||
|
||||
packages:
|
||||
|
||||
@@ -829,8 +829,8 @@ packages:
|
||||
resolution: {integrity: sha512-zmPitbQ8+6zNutpwgcQuLcsEpn/Cj54Kbn7L5pX0Os5kdWplB7xPgEh/g+SWOB/qmows2gpuCaPyduq8ZZRnxA==}
|
||||
deprecated: This is a stub types definition. minimatch provides its own type definitions, so you do not need this installed.
|
||||
|
||||
'@types/node@25.8.0':
|
||||
resolution: {integrity: sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ==}
|
||||
'@types/node@25.9.1':
|
||||
resolution: {integrity: sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==}
|
||||
|
||||
'@types/parse-json@4.0.2':
|
||||
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
|
||||
@@ -848,8 +848,8 @@ packages:
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
|
||||
'@types/react@19.2.14':
|
||||
resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==}
|
||||
'@types/react@19.2.15':
|
||||
resolution: {integrity: sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==}
|
||||
|
||||
'@types/responselike@1.0.3':
|
||||
resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==}
|
||||
@@ -857,63 +857,63 @@ packages:
|
||||
'@types/svgo@2.6.4':
|
||||
resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.59.3':
|
||||
resolution: {integrity: sha512-PwFvSKsXGShKGW6n5bZOhGHEcCZXM8HofLK9fNsEwZXzFRjoY+XT1Vsf1zgyXdwTr0ZYz1/2tkZ0DBTT9jZjhw==}
|
||||
'@typescript-eslint/eslint-plugin@8.59.4':
|
||||
resolution: {integrity: sha512-PegsU+XfyJJNjd4+u/k6f9yTyp0lEXXiPopUNobZcIAUJFGICFLN+sP0Rb3JehVmiij1Ph0dFGYqODoRo/2+6A==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': ^8.59.3
|
||||
'@typescript-eslint/parser': ^8.59.4
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/parser@8.59.3':
|
||||
resolution: {integrity: sha512-HPwA+hVkfcriajbNvTmZv4VRauibay+cWArYUYq7u7W7PmGShMxbPxLvrwDme55a6d5alG3nrYfhyJ/G28XlLg==}
|
||||
'@typescript-eslint/parser@8.59.4':
|
||||
resolution: {integrity: sha512-zORHqO/tuhxY1zWuTvMUqddRxpiFJ72xVfcNoWpqdLjs6lfPbuQBJuW4pk+49/uBMy7Ssr4bzgjiKmmDB1UbZQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/project-service@8.59.3':
|
||||
resolution: {integrity: sha512-ECiUWa/KYRGDFUqTNehaRgzDshnJfkTABJxVemHk4ko22gcr0ukloKjWvyQ64g8YCV/UI47kN1dbmjf/GaQYng==}
|
||||
'@typescript-eslint/project-service@8.59.4':
|
||||
resolution: {integrity: sha512-Ly00Vu4oAacfDeHp2Zg85ioNG6l8HG+tN1D7J+xTHSxu9y0awYKJ2zH1rFBn8ZSfuGK+7FxK3Cgl3uAz0aZZLg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/scope-manager@8.59.3':
|
||||
resolution: {integrity: sha512-t2LvZnoEfzKtnPjgeEu41xw5gxq9mQVfYy4OoZ4Vlt0sk3JwxmhCca/AR7DwOiHrjWgjAj6as4AhRLKSDfvZIA==}
|
||||
'@typescript-eslint/scope-manager@8.59.4':
|
||||
resolution: {integrity: sha512-mUeR/3H1WrTAddJrwut8OoPjfauaztMQmRwV5fQTUyNVJCLiUXXe4lGEyYIL2oFDpP7UtgbGJXCt72wT0z2S3Q==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/tsconfig-utils@8.59.3':
|
||||
resolution: {integrity: sha512-PcIJHjmaREXLgIAIzLnSY9VucEzz8FKXsRgFa1DmdGCK/5tJpW03TKJF01Q6VZd1lLdz2sIKPWaDUZN9dp//dw==}
|
||||
'@typescript-eslint/tsconfig-utils@8.59.4':
|
||||
resolution: {integrity: sha512-DLCpnKgD4alVxTBSKulK+gU1KCqOgUXfDRDXh2mZgzokQKa/70ax93I2uVO3m/LLvIAtWZIFoiifudmIqAxpMA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/type-utils@8.59.3':
|
||||
resolution: {integrity: sha512-g71d8QD8UaiHGvrJwyIS1hCX5r63w6Jll+4VEYhEAHXTDIqX1JgxhTAbEHtKntL9kuc4jRo7/GWw5xfCepSccQ==}
|
||||
'@typescript-eslint/type-utils@8.59.4':
|
||||
resolution: {integrity: sha512-uonTuPAAKr9XaBGqJ3LjYTh72zy5DyGesljO9gtmk/eFW0W1fRHjnwVYKB35Lm8d5Q5CluEW3gPHjTvZTmgrfA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/types@8.59.3':
|
||||
resolution: {integrity: sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg==}
|
||||
'@typescript-eslint/types@8.59.4':
|
||||
resolution: {integrity: sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.59.3':
|
||||
resolution: {integrity: sha512-CbRjVRAf7Lr9Kr8RopKcbY45p2VfmmHrm0ygOCYFi7oU8q19m0Fs/6iHS7kNOmwpp+ob07ZVcAqlxUod9lYdmg==}
|
||||
'@typescript-eslint/typescript-estree@8.59.4':
|
||||
resolution: {integrity: sha512-F+RuOmcDXo4+TPdfd/TCLS3m2nw8gE9XXyZLrA3JBfaA5tz9TtdkyD3YJFmPxulyc2cKbEok/CvFE3MgSLWnag==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/utils@8.59.3':
|
||||
resolution: {integrity: sha512-JAvT14goBzRzzzZyqq3P9BLArIxTtQURUtFgQ/V7FO+eU+Gg6ES+5ymOPP1wRxXcxAYeivCk4uS3jCKWI1K8Zg==}
|
||||
'@typescript-eslint/utils@8.59.4':
|
||||
resolution: {integrity: sha512-cYXeNAUsG4lJo5dbc1FcKm+JwIWrj1/UpTORsC6tGMjEZ81DYcvIr9/ueikhMa/Y/gDQYGp+YX9/xQrXje5BJw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/visitor-keys@8.59.3':
|
||||
resolution: {integrity: sha512-f1UQF7ggd42YiwI5wGrRaPsa+P0CINBlrkLPmGfpq/u/I/oVtecoEIfFR9ag/oa1sLOsRNZ6xehf6qMZhQGBDg==}
|
||||
'@typescript-eslint/visitor-keys@8.59.4':
|
||||
resolution: {integrity: sha512-U3gxVaDVnuZKhSspW/MzMxE1kq7zOdc072FcSNoqA1I9p8HyKbBFfEHoWckBAMgNMph4MamwS5iTVzFmrnt8TQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
acorn-jsx@5.3.2:
|
||||
@@ -998,8 +998,8 @@ packages:
|
||||
base64-js@1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
|
||||
baseline-browser-mapping@2.10.29:
|
||||
resolution: {integrity: sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==}
|
||||
baseline-browser-mapping@2.10.31:
|
||||
resolution: {integrity: sha512-MujYO3eP72uvmSE0i4wltsodRfIpZATP3jvzRNRGGxgzId7aVocVJJV3nf01qnzzKFGxQVC9bpWxl5cjxTr/7Q==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
|
||||
@@ -1097,8 +1097,8 @@ packages:
|
||||
resolution: {integrity: sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
caniuse-lite@1.0.30001792:
|
||||
resolution: {integrity: sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==}
|
||||
caniuse-lite@1.0.30001793:
|
||||
resolution: {integrity: sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==}
|
||||
|
||||
caw@2.0.1:
|
||||
resolution: {integrity: sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==}
|
||||
@@ -1330,8 +1330,8 @@ packages:
|
||||
duplexer3@0.1.5:
|
||||
resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==}
|
||||
|
||||
electron-to-chromium@1.5.357:
|
||||
resolution: {integrity: sha512-NHlTIQDK8fmVwHwuIzmXYEJ1Ewq3D9wDNc0cWXxDGysP6Pb21giwGNkxiTifyKy/4SoPuN5l6GLP1W9Sv7zB2g==}
|
||||
electron-to-chromium@1.5.360:
|
||||
resolution: {integrity: sha512-GkcBt6YYAw9SxFWn+xVar4cLVGlXVuswwtRLBozi2zp0GjXs4ZnOrqV4zbXzg35n7w81hCkyJNYicgXlVHAmBA==}
|
||||
|
||||
emoji-regex@10.6.0:
|
||||
resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
|
||||
@@ -2516,16 +2516,16 @@ packages:
|
||||
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
postcss@8.5.14:
|
||||
resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==}
|
||||
postcss@8.5.15:
|
||||
resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
powershell-utils@0.1.0:
|
||||
resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
preact@10.29.1:
|
||||
resolution: {integrity: sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==}
|
||||
preact@10.29.2:
|
||||
resolution: {integrity: sha512-7tNmwg/7mzzAoB/8kSg6Hl37JraAZw3Z3A0JSY7VXlZwo82Xn0G7wKbNNs2qoF4ZEEsQGTwDAroNdqKs1ofJxQ==}
|
||||
|
||||
prelude-ls@1.2.1:
|
||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||
@@ -2995,8 +2995,8 @@ packages:
|
||||
peerDependencies:
|
||||
typescript: '>=3.5.1'
|
||||
|
||||
typescript-eslint@8.59.3:
|
||||
resolution: {integrity: sha512-KgusgyDgG4LI8Ih/sWaCtZ06tckLAS5CvT5A4D1Q7bYVoAAyzwiZvE4BmwDHkhRVkvhRBepKeASoFzQetha7Fg==}
|
||||
typescript-eslint@8.59.4:
|
||||
resolution: {integrity: sha512-Rw6+44QNFaXtgHSjPy+Kw8hrJniMYzR85E9yLmOLcfZ91/rz+JXQbDTCmc6ccxMPY6K6PgAq26f0JCBfR7LIPQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
@@ -3366,7 +3366,7 @@ snapshots:
|
||||
|
||||
'@emotion/memoize@0.9.0': {}
|
||||
|
||||
'@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6)':
|
||||
'@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@emotion/babel-plugin': 11.13.5
|
||||
@@ -3378,7 +3378,7 @@ snapshots:
|
||||
hoist-non-react-statics: 3.3.2
|
||||
react: 19.2.6
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.14
|
||||
'@types/react': 19.2.15
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -3392,18 +3392,18 @@ snapshots:
|
||||
|
||||
'@emotion/sheet@1.4.0': {}
|
||||
|
||||
'@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6)':
|
||||
'@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@emotion/babel-plugin': 11.13.5
|
||||
'@emotion/is-prop-valid': 1.4.0
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.6)
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.15)(react@19.2.6)
|
||||
'@emotion/serialize': 1.3.3
|
||||
'@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.6)
|
||||
'@emotion/utils': 1.4.2
|
||||
react: 19.2.6
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.14
|
||||
'@types/react': 19.2.15
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -3496,23 +3496,23 @@ snapshots:
|
||||
|
||||
'@mui/core-downloads-tracker@9.0.1': {}
|
||||
|
||||
'@mui/icons-material@9.0.1(@mui/material@9.0.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@types/react@19.2.14)(react@19.2.6)':
|
||||
'@mui/icons-material@9.0.1(@mui/material@9.0.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@types/react@19.2.15)(react@19.2.6)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@mui/material': 9.0.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
|
||||
'@mui/material': 9.0.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
|
||||
react: 19.2.6
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.14
|
||||
'@types/react': 19.2.15
|
||||
|
||||
'@mui/material@9.0.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
|
||||
'@mui/material@9.0.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@mui/core-downloads-tracker': 9.0.1
|
||||
'@mui/system': 9.0.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6)
|
||||
'@mui/types': 9.0.0(@types/react@19.2.14)
|
||||
'@mui/utils': 9.0.1(@types/react@19.2.14)(react@19.2.6)
|
||||
'@mui/system': 9.0.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6)
|
||||
'@mui/types': 9.0.0(@types/react@19.2.15)
|
||||
'@mui/utils': 9.0.1(@types/react@19.2.15)(react@19.2.6)
|
||||
'@popperjs/core': 2.11.8
|
||||
'@types/react-transition-group': 4.4.12(@types/react@19.2.14)
|
||||
'@types/react-transition-group': 4.4.12(@types/react@19.2.15)
|
||||
clsx: 2.1.1
|
||||
csstype: 3.2.3
|
||||
prop-types: 15.8.1
|
||||
@@ -3521,20 +3521,20 @@ snapshots:
|
||||
react-is: 19.2.6
|
||||
react-transition-group: 4.4.5(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
|
||||
optionalDependencies:
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.6)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6)
|
||||
'@types/react': 19.2.14
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.15)(react@19.2.6)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6)
|
||||
'@types/react': 19.2.15
|
||||
|
||||
'@mui/private-theming@9.0.1(@types/react@19.2.14)(react@19.2.6)':
|
||||
'@mui/private-theming@9.0.1(@types/react@19.2.15)(react@19.2.6)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@mui/utils': 9.0.1(@types/react@19.2.14)(react@19.2.6)
|
||||
'@mui/utils': 9.0.1(@types/react@19.2.15)(react@19.2.6)
|
||||
prop-types: 15.8.1
|
||||
react: 19.2.6
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.14
|
||||
'@types/react': 19.2.15
|
||||
|
||||
'@mui/styled-engine@9.0.0(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6))(react@19.2.6)':
|
||||
'@mui/styled-engine@9.0.0(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6))(react@19.2.6)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@emotion/cache': 11.14.0
|
||||
@@ -3544,42 +3544,42 @@ snapshots:
|
||||
prop-types: 15.8.1
|
||||
react: 19.2.6
|
||||
optionalDependencies:
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.6)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6)
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.15)(react@19.2.6)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6)
|
||||
|
||||
'@mui/system@9.0.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6)':
|
||||
'@mui/system@9.0.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@mui/private-theming': 9.0.1(@types/react@19.2.14)(react@19.2.6)
|
||||
'@mui/styled-engine': 9.0.0(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6))(react@19.2.6)
|
||||
'@mui/types': 9.0.0(@types/react@19.2.14)
|
||||
'@mui/utils': 9.0.1(@types/react@19.2.14)(react@19.2.6)
|
||||
'@mui/private-theming': 9.0.1(@types/react@19.2.15)(react@19.2.6)
|
||||
'@mui/styled-engine': 9.0.0(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6))(react@19.2.6)
|
||||
'@mui/types': 9.0.0(@types/react@19.2.15)
|
||||
'@mui/utils': 9.0.1(@types/react@19.2.15)(react@19.2.6)
|
||||
clsx: 2.1.1
|
||||
csstype: 3.2.3
|
||||
prop-types: 15.8.1
|
||||
react: 19.2.6
|
||||
optionalDependencies:
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.6)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(@types/react@19.2.14)(react@19.2.6)
|
||||
'@types/react': 19.2.14
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.15)(react@19.2.6)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(@types/react@19.2.15)(react@19.2.6)
|
||||
'@types/react': 19.2.15
|
||||
|
||||
'@mui/types@9.0.0(@types/react@19.2.14)':
|
||||
'@mui/types@9.0.0(@types/react@19.2.15)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.14
|
||||
'@types/react': 19.2.15
|
||||
|
||||
'@mui/utils@9.0.1(@types/react@19.2.14)(react@19.2.6)':
|
||||
'@mui/utils@9.0.1(@types/react@19.2.15)(react@19.2.6)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@mui/types': 9.0.0(@types/react@19.2.14)
|
||||
'@mui/types': 9.0.0(@types/react@19.2.15)
|
||||
'@types/prop-types': 15.7.15
|
||||
clsx: 2.1.1
|
||||
prop-types: 15.8.1
|
||||
react: 19.2.6
|
||||
react-is: 19.2.6
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.14
|
||||
'@types/react': 19.2.15
|
||||
|
||||
'@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)':
|
||||
dependencies:
|
||||
@@ -3604,19 +3604,19 @@ snapshots:
|
||||
|
||||
'@popperjs/core@2.11.8': {}
|
||||
|
||||
'@preact/preset-vite@2.10.5(@babel/core@7.29.0)(preact@10.29.1)(rollup@4.59.0)(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1))':
|
||||
'@preact/preset-vite@2.10.5(@babel/core@7.29.0)(preact@10.29.2)(rollup@4.59.0)(vite@8.0.13(@types/node@25.9.1)(terser@5.47.1))':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0)
|
||||
'@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.29.0)
|
||||
'@prefresh/vite': 2.4.12(preact@10.29.1)(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1))
|
||||
'@prefresh/vite': 2.4.12(preact@10.29.2)(vite@8.0.13(@types/node@25.9.1)(terser@5.47.1))
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.59.0)
|
||||
babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.29.0)
|
||||
debug: 4.4.3
|
||||
magic-string: 0.30.21
|
||||
picocolors: 1.1.1
|
||||
vite: 8.0.13(@types/node@25.8.0)(terser@5.47.1)
|
||||
vite-prerender-plugin: 0.5.13(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1))
|
||||
vite: 8.0.13(@types/node@25.9.1)(terser@5.47.1)
|
||||
vite-prerender-plugin: 0.5.13(vite@8.0.13(@types/node@25.9.1)(terser@5.47.1))
|
||||
zimmerframe: 1.1.4
|
||||
transitivePeerDependencies:
|
||||
- preact
|
||||
@@ -3625,21 +3625,21 @@ snapshots:
|
||||
|
||||
'@prefresh/babel-plugin@0.5.3': {}
|
||||
|
||||
'@prefresh/core@1.5.10(preact@10.29.1)':
|
||||
'@prefresh/core@1.5.10(preact@10.29.2)':
|
||||
dependencies:
|
||||
preact: 10.29.1
|
||||
preact: 10.29.2
|
||||
|
||||
'@prefresh/utils@1.2.1': {}
|
||||
|
||||
'@prefresh/vite@2.4.12(preact@10.29.1)(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1))':
|
||||
'@prefresh/vite@2.4.12(preact@10.29.2)(vite@8.0.13(@types/node@25.9.1)(terser@5.47.1))':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@prefresh/babel-plugin': 0.5.3
|
||||
'@prefresh/core': 1.5.10(preact@10.29.1)
|
||||
'@prefresh/core': 1.5.10(preact@10.29.2)
|
||||
'@prefresh/utils': 1.2.1
|
||||
'@rollup/pluginutils': 4.2.1
|
||||
preact: 10.29.1
|
||||
vite: 8.0.13(@types/node@25.8.0)(terser@5.47.1)
|
||||
preact: 10.29.2
|
||||
vite: 8.0.13(@types/node@25.9.1)(terser@5.47.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -3784,9 +3784,9 @@ snapshots:
|
||||
|
||||
'@sindresorhus/is@0.7.0': {}
|
||||
|
||||
'@table-library/react-table-library@4.1.15(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
|
||||
'@table-library/react-table-library@4.1.15(@emotion/react@11.14.0(@types/react@19.2.15)(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
|
||||
dependencies:
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.6)
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.15)(react@19.2.6)
|
||||
clsx: 1.1.1
|
||||
react: 19.2.6
|
||||
react-dom: 19.2.6(react@19.2.6)
|
||||
@@ -3822,7 +3822,7 @@ snapshots:
|
||||
'@types/glob@7.2.0':
|
||||
dependencies:
|
||||
'@types/minimatch': 6.0.0
|
||||
'@types/node': 25.8.0
|
||||
'@types/node': 25.9.1
|
||||
|
||||
'@types/imagemin-gifsicle@7.0.4':
|
||||
dependencies:
|
||||
@@ -3851,19 +3851,19 @@ snapshots:
|
||||
|
||||
'@types/imagemin@7.0.1':
|
||||
dependencies:
|
||||
'@types/node': 25.8.0
|
||||
'@types/node': 25.9.1
|
||||
|
||||
'@types/json-schema@7.0.15': {}
|
||||
|
||||
'@types/keyv@3.1.4':
|
||||
dependencies:
|
||||
'@types/node': 25.8.0
|
||||
'@types/node': 25.9.1
|
||||
|
||||
'@types/minimatch@6.0.0':
|
||||
dependencies:
|
||||
minimatch: 10.2.5
|
||||
|
||||
'@types/node@25.8.0':
|
||||
'@types/node@25.9.1':
|
||||
dependencies:
|
||||
undici-types: 7.24.6
|
||||
|
||||
@@ -3871,34 +3871,34 @@ snapshots:
|
||||
|
||||
'@types/prop-types@15.7.15': {}
|
||||
|
||||
'@types/react-dom@19.2.3(@types/react@19.2.14)':
|
||||
'@types/react-dom@19.2.3(@types/react@19.2.15)':
|
||||
dependencies:
|
||||
'@types/react': 19.2.14
|
||||
'@types/react': 19.2.15
|
||||
|
||||
'@types/react-transition-group@4.4.12(@types/react@19.2.14)':
|
||||
'@types/react-transition-group@4.4.12(@types/react@19.2.15)':
|
||||
dependencies:
|
||||
'@types/react': 19.2.14
|
||||
'@types/react': 19.2.15
|
||||
|
||||
'@types/react@19.2.14':
|
||||
'@types/react@19.2.15':
|
||||
dependencies:
|
||||
csstype: 3.2.3
|
||||
|
||||
'@types/responselike@1.0.3':
|
||||
dependencies:
|
||||
'@types/node': 25.8.0
|
||||
'@types/node': 25.9.1
|
||||
|
||||
'@types/svgo@2.6.4':
|
||||
dependencies:
|
||||
'@types/node': 25.8.0
|
||||
'@types/node': 25.9.1
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.4.0)(typescript@6.0.3))(eslint@10.4.0)(typescript@6.0.3)':
|
||||
'@typescript-eslint/eslint-plugin@8.59.4(@typescript-eslint/parser@8.59.4(eslint@10.4.0)(typescript@6.0.3))(eslint@10.4.0)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.2
|
||||
'@typescript-eslint/parser': 8.59.3(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/scope-manager': 8.59.3
|
||||
'@typescript-eslint/type-utils': 8.59.3(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.59.3(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/visitor-keys': 8.59.3
|
||||
'@typescript-eslint/parser': 8.59.4(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/scope-manager': 8.59.4
|
||||
'@typescript-eslint/type-utils': 8.59.4(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.59.4(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/visitor-keys': 8.59.4
|
||||
eslint: 10.4.0
|
||||
ignore: 7.0.5
|
||||
natural-compare: 1.4.0
|
||||
@@ -3907,41 +3907,41 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/parser@8.59.3(eslint@10.4.0)(typescript@6.0.3)':
|
||||
'@typescript-eslint/parser@8.59.4(eslint@10.4.0)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 8.59.3
|
||||
'@typescript-eslint/types': 8.59.3
|
||||
'@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3)
|
||||
'@typescript-eslint/visitor-keys': 8.59.3
|
||||
'@typescript-eslint/scope-manager': 8.59.4
|
||||
'@typescript-eslint/types': 8.59.4
|
||||
'@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3)
|
||||
'@typescript-eslint/visitor-keys': 8.59.4
|
||||
debug: 4.4.3
|
||||
eslint: 10.4.0
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/project-service@8.59.3(typescript@6.0.3)':
|
||||
'@typescript-eslint/project-service@8.59.4(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/tsconfig-utils': 8.59.3(typescript@6.0.3)
|
||||
'@typescript-eslint/types': 8.59.3
|
||||
'@typescript-eslint/tsconfig-utils': 8.59.4(typescript@6.0.3)
|
||||
'@typescript-eslint/types': 8.59.4
|
||||
debug: 4.4.3
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/scope-manager@8.59.3':
|
||||
'@typescript-eslint/scope-manager@8.59.4':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.59.3
|
||||
'@typescript-eslint/visitor-keys': 8.59.3
|
||||
'@typescript-eslint/types': 8.59.4
|
||||
'@typescript-eslint/visitor-keys': 8.59.4
|
||||
|
||||
'@typescript-eslint/tsconfig-utils@8.59.3(typescript@6.0.3)':
|
||||
'@typescript-eslint/tsconfig-utils@8.59.4(typescript@6.0.3)':
|
||||
dependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@typescript-eslint/type-utils@8.59.3(eslint@10.4.0)(typescript@6.0.3)':
|
||||
'@typescript-eslint/type-utils@8.59.4(eslint@10.4.0)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.59.3
|
||||
'@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.59.3(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/types': 8.59.4
|
||||
'@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.59.4(eslint@10.4.0)(typescript@6.0.3)
|
||||
debug: 4.4.3
|
||||
eslint: 10.4.0
|
||||
ts-api-utils: 2.5.0(typescript@6.0.3)
|
||||
@@ -3949,14 +3949,14 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/types@8.59.3': {}
|
||||
'@typescript-eslint/types@8.59.4': {}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.59.3(typescript@6.0.3)':
|
||||
'@typescript-eslint/typescript-estree@8.59.4(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/project-service': 8.59.3(typescript@6.0.3)
|
||||
'@typescript-eslint/tsconfig-utils': 8.59.3(typescript@6.0.3)
|
||||
'@typescript-eslint/types': 8.59.3
|
||||
'@typescript-eslint/visitor-keys': 8.59.3
|
||||
'@typescript-eslint/project-service': 8.59.4(typescript@6.0.3)
|
||||
'@typescript-eslint/tsconfig-utils': 8.59.4(typescript@6.0.3)
|
||||
'@typescript-eslint/types': 8.59.4
|
||||
'@typescript-eslint/visitor-keys': 8.59.4
|
||||
debug: 4.4.3
|
||||
minimatch: 10.2.5
|
||||
semver: 7.8.0
|
||||
@@ -3966,20 +3966,20 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/utils@8.59.3(eslint@10.4.0)(typescript@6.0.3)':
|
||||
'@typescript-eslint/utils@8.59.4(eslint@10.4.0)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0)
|
||||
'@typescript-eslint/scope-manager': 8.59.3
|
||||
'@typescript-eslint/types': 8.59.3
|
||||
'@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3)
|
||||
'@typescript-eslint/scope-manager': 8.59.4
|
||||
'@typescript-eslint/types': 8.59.4
|
||||
'@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3)
|
||||
eslint: 10.4.0
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/visitor-keys@8.59.3':
|
||||
'@typescript-eslint/visitor-keys@8.59.4':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.59.3
|
||||
'@typescript-eslint/types': 8.59.4
|
||||
eslint-visitor-keys: 5.0.1
|
||||
|
||||
acorn-jsx@5.3.2(acorn@8.16.0):
|
||||
@@ -4046,7 +4046,7 @@ snapshots:
|
||||
|
||||
base64-js@1.5.1: {}
|
||||
|
||||
baseline-browser-mapping@2.10.29: {}
|
||||
baseline-browser-mapping@2.10.31: {}
|
||||
|
||||
bin-build@3.0.0:
|
||||
dependencies:
|
||||
@@ -4107,9 +4107,9 @@ snapshots:
|
||||
|
||||
browserslist@4.28.2:
|
||||
dependencies:
|
||||
baseline-browser-mapping: 2.10.29
|
||||
caniuse-lite: 1.0.30001792
|
||||
electron-to-chromium: 1.5.357
|
||||
baseline-browser-mapping: 2.10.31
|
||||
caniuse-lite: 1.0.30001793
|
||||
electron-to-chromium: 1.5.360
|
||||
node-releases: 2.0.44
|
||||
update-browserslist-db: 1.2.3(browserslist@4.28.2)
|
||||
|
||||
@@ -4171,7 +4171,7 @@ snapshots:
|
||||
|
||||
camelcase@2.1.1: {}
|
||||
|
||||
caniuse-lite@1.0.30001792: {}
|
||||
caniuse-lite@1.0.30001793: {}
|
||||
|
||||
caw@2.0.1:
|
||||
dependencies:
|
||||
@@ -4468,7 +4468,7 @@ snapshots:
|
||||
|
||||
duplexer3@0.1.5: {}
|
||||
|
||||
electron-to-chromium@1.5.357: {}
|
||||
electron-to-chromium@1.5.360: {}
|
||||
|
||||
emoji-regex@10.6.0: {}
|
||||
|
||||
@@ -5588,7 +5588,7 @@ snapshots:
|
||||
|
||||
possible-typed-array-names@1.1.0: {}
|
||||
|
||||
postcss@8.5.14:
|
||||
postcss@8.5.15:
|
||||
dependencies:
|
||||
nanoid: 3.3.12
|
||||
picocolors: 1.1.1
|
||||
@@ -5596,7 +5596,7 @@ snapshots:
|
||||
|
||||
powershell-utils@0.1.0: {}
|
||||
|
||||
preact@10.29.1: {}
|
||||
preact@10.29.2: {}
|
||||
|
||||
prelude-ls@1.2.1: {}
|
||||
|
||||
@@ -6070,12 +6070,12 @@ snapshots:
|
||||
dependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
typescript-eslint@8.59.3(eslint@10.4.0)(typescript@6.0.3):
|
||||
typescript-eslint@8.59.4(eslint@10.4.0)(typescript@6.0.3):
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.4.0)(typescript@6.0.3))(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/parser': 8.59.3(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.59.3(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/eslint-plugin': 8.59.4(@typescript-eslint/parser@8.59.4(eslint@10.4.0)(typescript@6.0.3))(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/parser': 8.59.4(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.59.4(eslint@10.4.0)(typescript@6.0.3)
|
||||
eslint: 10.4.0
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
@@ -6121,7 +6121,7 @@ snapshots:
|
||||
spdx-correct: 3.2.0
|
||||
spdx-expression-parse: 3.0.1
|
||||
|
||||
vite-plugin-imagemin@0.6.1(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1)):
|
||||
vite-plugin-imagemin@0.6.1(vite@8.0.13(@types/node@25.9.1)(terser@5.47.1)):
|
||||
dependencies:
|
||||
'@types/imagemin': 7.0.1
|
||||
'@types/imagemin-gifsicle': 7.0.4
|
||||
@@ -6146,11 +6146,11 @@ snapshots:
|
||||
imagemin-webp: 6.1.0
|
||||
jpegtran-bin: 6.0.1
|
||||
pathe: 0.2.0
|
||||
vite: 8.0.13(@types/node@25.8.0)(terser@5.47.1)
|
||||
vite: 8.0.13(@types/node@25.9.1)(terser@5.47.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-prerender-plugin@0.5.13(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1)):
|
||||
vite-prerender-plugin@0.5.13(vite@8.0.13(@types/node@25.9.1)(terser@5.47.1)):
|
||||
dependencies:
|
||||
kolorist: 1.8.0
|
||||
magic-string: 0.30.21
|
||||
@@ -6158,17 +6158,17 @@ snapshots:
|
||||
simple-code-frame: 1.3.0
|
||||
source-map: 0.7.6
|
||||
stack-trace: 1.0.0
|
||||
vite: 8.0.13(@types/node@25.8.0)(terser@5.47.1)
|
||||
vite: 8.0.13(@types/node@25.9.1)(terser@5.47.1)
|
||||
|
||||
vite@8.0.13(@types/node@25.8.0)(terser@5.47.1):
|
||||
vite@8.0.13(@types/node@25.9.1)(terser@5.47.1):
|
||||
dependencies:
|
||||
lightningcss: 1.32.0
|
||||
picomatch: 4.0.4
|
||||
postcss: 8.5.14
|
||||
postcss: 8.5.15
|
||||
rolldown: 1.0.1
|
||||
tinyglobby: 0.2.16
|
||||
optionalDependencies:
|
||||
'@types/node': 25.8.0
|
||||
'@types/node': 25.9.1
|
||||
fsevents: 2.3.3
|
||||
terser: 5.47.1
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
#include "ESPAsyncWebServer.h"
|
||||
#include "AsyncJson.h"
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#define FACTORY_JWT_SECRET "ems-esp"
|
||||
#define ACCESS_TOKEN_PARAMATER "access_token"
|
||||
#define ACCESS_TOKEN_PARAMETER "access_token"
|
||||
#define AUTHORIZATION_HEADER "Authorization"
|
||||
#define AUTHORIZATION_HEADER_PREFIX "Bearer "
|
||||
#define AUTHORIZATION_HEADER_PREFIX_LEN 7
|
||||
@@ -31,21 +31,15 @@ class User {
|
||||
|
||||
class Authentication {
|
||||
public:
|
||||
User * user;
|
||||
boolean authenticated;
|
||||
std::unique_ptr<User> user;
|
||||
boolean authenticated = false;
|
||||
|
||||
public:
|
||||
Authentication(User & user)
|
||||
: user(new User(user))
|
||||
explicit Authentication(const User & u)
|
||||
: user(std::make_unique<User>(u))
|
||||
, authenticated(true) {
|
||||
}
|
||||
Authentication()
|
||||
: user(nullptr)
|
||||
, authenticated(false) {
|
||||
}
|
||||
~Authentication() {
|
||||
delete (user);
|
||||
}
|
||||
Authentication() = default;
|
||||
};
|
||||
|
||||
typedef std::function<boolean(Authentication & authentication)> AuthenticationPredicate;
|
||||
@@ -66,10 +60,8 @@ class AuthenticationPredicates {
|
||||
class SecurityManager {
|
||||
public:
|
||||
virtual Authentication authenticateRequest(AsyncWebServerRequest * request) = 0;
|
||||
virtual ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate) = 0;
|
||||
virtual ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate) = 0;
|
||||
virtual ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate) = 0;
|
||||
|
||||
// Json endpoints - default POST. Registered with the shared dispatcher.
|
||||
void addEndpoint(AsyncWebServer * server,
|
||||
const String & path,
|
||||
AuthenticationPredicate predicate,
|
||||
|
||||
@@ -10,22 +10,9 @@ SecuritySettingsService::SecuritySettingsService(AsyncWebServer * server, FS * f
|
||||
SecuritySettingsService::~SecuritySettingsService() {
|
||||
}
|
||||
|
||||
ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) {
|
||||
return [predicate](AsyncWebServerRequest * request) { return true; };
|
||||
}
|
||||
|
||||
// Return the admin user on all request - disabling security features
|
||||
// Return the admin user on all requests - disabling security features
|
||||
Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerRequest * request) {
|
||||
return Authentication(ADMIN_USER);
|
||||
}
|
||||
|
||||
// Return the function unwrapped
|
||||
ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate) {
|
||||
return onRequest;
|
||||
}
|
||||
|
||||
ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate) {
|
||||
return onRequest;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -31,9 +31,6 @@ class SecuritySettingsService : public SecurityManager {
|
||||
|
||||
// minimal set of functions to support framework with security settings disabled
|
||||
Authentication authenticateRequest(AsyncWebServerRequest * request);
|
||||
ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate);
|
||||
ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate);
|
||||
ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1337,3 +1337,7 @@ startm
|
||||
netifs
|
||||
testemail
|
||||
sendmail
|
||||
serialises
|
||||
SPIRAM
|
||||
optimisations
|
||||
IILE
|
||||
@@ -10,7 +10,7 @@ APStatus::APStatus(AsyncWebServer * server, SecurityManager * securityManager, A
|
||||
}
|
||||
|
||||
void APStatus::apStatus(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new emsesp::PsramAsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
root["status"] = _apSettingsService->getAPNetworkStatus();
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
#include "AuthenticationService.h"
|
||||
|
||||
#include "../core/psram_async_json_response.h"
|
||||
|
||||
AuthenticationService::AuthenticationService(AsyncWebServer * server, SecurityManager * securityManager)
|
||||
: _securityManager(securityManager) {
|
||||
// none of these need authentication
|
||||
server->on(VERIFY_AUTHORIZATION_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { verifyAuthorization(request); });
|
||||
auto * handler = new AsyncCallbackJsonWebHandler(SIGN_IN_PATH);
|
||||
handler->onRequest([this](AsyncWebServerRequest * request, JsonVariant json) { signIn(request, json); });
|
||||
server->addHandler(handler);
|
||||
// None of these need authentication: verifyAuthorization checks the JWT itself, and signIn IS the authentication flow.
|
||||
securityManager->addEndpoint(server, VERIFY_AUTHORIZATION_PATH, AuthenticationPredicates::NONE_REQUIRED, [this](AsyncWebServerRequest * request) {
|
||||
verifyAuthorization(request);
|
||||
});
|
||||
securityManager->addEndpoint(server, SIGN_IN_PATH, AuthenticationPredicates::NONE_REQUIRED, [this](AsyncWebServerRequest * request, JsonVariant json) {
|
||||
signIn(request, json);
|
||||
});
|
||||
}
|
||||
|
||||
// Verifies that the request supplied a valid JWT.
|
||||
@@ -22,10 +26,9 @@ void AuthenticationService::signIn(AsyncWebServerRequest * request, JsonVariant
|
||||
String password = json["password"];
|
||||
Authentication authentication = _securityManager->authenticate(username, password);
|
||||
if (authentication.authenticated) {
|
||||
User * user = authentication.user;
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new emsesp::PsramAsyncJsonResponse(false);
|
||||
JsonObject jsonObject = response->getRoot();
|
||||
jsonObject["access_token"] = _securityManager->generateJWT(user);
|
||||
jsonObject["access_token"] = _securityManager->generateJWT(authentication.user.get());
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "SecurityManager.h"
|
||||
#include "StatefulService.h"
|
||||
#include "../core/psram_async_json_response.h"
|
||||
|
||||
#define HTTP_ENDPOINT_ORIGIN_ID "http"
|
||||
|
||||
@@ -58,7 +59,7 @@ class HttpEndpoint {
|
||||
}
|
||||
}
|
||||
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new emsesp::PsramAsyncJsonResponse(false);
|
||||
JsonObject jsonObject = response->getRoot().to<JsonObject>();
|
||||
_statefulService->read(jsonObject, _stateReader);
|
||||
response->setLength();
|
||||
|
||||
@@ -10,7 +10,7 @@ MqttStatus::MqttStatus(AsyncWebServer * server, MqttSettingsService * mqttSettin
|
||||
}
|
||||
|
||||
void MqttStatus::mqttStatus(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new emsesp::PsramAsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
root["enabled"] = _mqttSettingsService->isEnabled();
|
||||
|
||||
@@ -30,7 +30,7 @@ String toLocalTimeString(tm * time) {
|
||||
}
|
||||
|
||||
void NTPStatus::ntpStatus(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new emsesp::PsramAsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
// grab the current instant in unix seconds
|
||||
|
||||
@@ -13,7 +13,7 @@ NetworkStatus::NetworkStatus(AsyncWebServer * server, SecurityManager * security
|
||||
}
|
||||
|
||||
void NetworkStatus::networkStatus(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new emsesp::PsramAsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
wl_status_t wifi_status = WiFi.status();
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
#include "SecurityManager.h"
|
||||
|
||||
void SecurityManager::addEndpoint(AsyncWebServer * server,
|
||||
const String & path,
|
||||
AuthenticationPredicate predicate,
|
||||
ArJsonRequestHandlerFunction function,
|
||||
WebRequestMethodComposite method) {
|
||||
ensureRestDispatcher(server);
|
||||
const bool requiresAuth = !isPublicPredicate(predicate);
|
||||
_restRoutes.push_back({AsyncURIMatcher(path), method, std::move(predicate), {}, std::move(function), true, requiresAuth});
|
||||
}
|
||||
|
||||
void SecurityManager::addEndpoint(AsyncWebServer * server,
|
||||
const String & path,
|
||||
AuthenticationPredicate predicate,
|
||||
ArRequestHandlerFunction function,
|
||||
WebRequestMethodComposite method) {
|
||||
ensureRestDispatcher(server);
|
||||
const bool requiresAuth = !isPublicPredicate(predicate);
|
||||
_restRoutes.push_back({AsyncURIMatcher(path), method, std::move(predicate), std::move(function), {}, false, requiresAuth});
|
||||
}
|
||||
|
||||
// Detects routes registered with AuthenticationPredicates::NONE_REQUIRED so we can
|
||||
// skip the JWT parse in dispatchRest. Relies on std::function::target returning the
|
||||
// raw function pointer when the predicate was assigned directly from the static fn;
|
||||
// if a caller wraps NONE_REQUIRED in a lambda this falls back to "requires auth"
|
||||
// which is correctness-preserving (just no optimization).
|
||||
bool SecurityManager::isPublicPredicate(const AuthenticationPredicate & predicate) {
|
||||
using Fn = bool (*)(const Authentication &);
|
||||
auto * fn = predicate.target<Fn>();
|
||||
return fn != nullptr && *fn == &AuthenticationPredicates::NONE_REQUIRED;
|
||||
}
|
||||
|
||||
// Lazily attach the single catch-all handler. Idempotent.
|
||||
void SecurityManager::ensureRestDispatcher(AsyncWebServer * server) {
|
||||
if (_restDispatcherInstalled || server == nullptr) {
|
||||
return;
|
||||
}
|
||||
_restDispatcherInstalled = true;
|
||||
server->addHandler(new RestCatchAllHandler(this));
|
||||
}
|
||||
|
||||
void SecurityManager::dispatchRest(AsyncWebServerRequest * request, JsonVariant json) {
|
||||
WebRequestMethod method = request->method();
|
||||
|
||||
for (auto & route : _restRoutes) {
|
||||
if (!route.method.matches(method)) {
|
||||
continue;
|
||||
}
|
||||
if (!route.uri.matches(request)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (route.requiresAuth) {
|
||||
Authentication authentication = authenticateRequest(request);
|
||||
if (!route.predicate(authentication)) {
|
||||
request->send(401);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (route.isJson) {
|
||||
route.jsonHandler(request, json);
|
||||
} else {
|
||||
route.plainHandler(request);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// canHandle returned true so some route matched the URI+method;
|
||||
// a mismatch here means the request slipped between the two checks.
|
||||
request->send(404);
|
||||
}
|
||||
|
||||
// ---- RestCatchAllHandler ----
|
||||
|
||||
bool SecurityManager::RestCatchAllHandler::canHandle(AsyncWebServerRequest * request) const {
|
||||
if (!request->isHTTP()) {
|
||||
return false;
|
||||
}
|
||||
for (const auto & route : _owner->_restRoutes) {
|
||||
if (route.method.matches(request->method()) && route.uri.matches(request)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returning false ensures the server invokes handleBody() so we can buffer JSON bodies.
|
||||
bool SecurityManager::RestCatchAllHandler::isRequestHandlerTrivial() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void SecurityManager::RestCatchAllHandler::handleBody(AsyncWebServerRequest * request, uint8_t * data, size_t len, size_t index, size_t total) {
|
||||
// Only buffer JSON bodies; everything else is routed with an empty JsonVariant.
|
||||
if (total == 0 || total > kMaxBodySize || !isJsonContent(request)) {
|
||||
return;
|
||||
}
|
||||
if (index == 0 && request->_tempObject == nullptr) {
|
||||
request->_tempObject = calloc(total + 1, sizeof(uint8_t)); // freed by request destructor
|
||||
if (request->_tempObject == nullptr) {
|
||||
request->abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (request->_tempObject != nullptr) {
|
||||
memcpy(static_cast<uint8_t *>(request->_tempObject) + index, data, len);
|
||||
}
|
||||
}
|
||||
|
||||
void SecurityManager::RestCatchAllHandler::handleRequest(AsyncWebServerRequest * request) {
|
||||
JsonDocument doc;
|
||||
JsonVariant json;
|
||||
if (request->_tempObject != nullptr) {
|
||||
if (deserializeJson(doc, static_cast<const char *>(request->_tempObject))) {
|
||||
request->send(400);
|
||||
return;
|
||||
}
|
||||
json = doc.as<JsonVariant>();
|
||||
}
|
||||
_owner->dispatchRest(request, json);
|
||||
}
|
||||
|
||||
bool SecurityManager::RestCatchAllHandler::isJsonContent(AsyncWebServerRequest * request) {
|
||||
return request->contentType().equalsIgnoreCase("application/json");
|
||||
}
|
||||
@@ -6,9 +6,10 @@
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <AsyncJson.h>
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#define ACCESS_TOKEN_PARAMATER "access_token"
|
||||
#define ACCESS_TOKEN_PARAMETER "access_token"
|
||||
#define AUTHORIZATION_HEADER "Authorization"
|
||||
#define AUTHORIZATION_HEADER_PREFIX "Bearer "
|
||||
#define AUTHORIZATION_HEADER_PREFIX_LEN 7
|
||||
@@ -29,20 +30,16 @@ class User {
|
||||
|
||||
class Authentication {
|
||||
public:
|
||||
User * user = nullptr;
|
||||
std::unique_ptr<User> user;
|
||||
boolean authenticated = false;
|
||||
|
||||
public:
|
||||
explicit Authentication(const User & user)
|
||||
: user(new User(user))
|
||||
explicit Authentication(const User & u)
|
||||
: user(std::make_unique<User>(u))
|
||||
, authenticated(true) {
|
||||
}
|
||||
|
||||
Authentication() = default;
|
||||
|
||||
~Authentication() {
|
||||
delete user;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::function<boolean(Authentication & authentication)> AuthenticationPredicate;
|
||||
@@ -63,6 +60,8 @@ class AuthenticationPredicates {
|
||||
|
||||
class SecurityManager {
|
||||
public:
|
||||
virtual ~SecurityManager() = default;
|
||||
|
||||
// Authenticate, returning the user if found
|
||||
virtual Authentication authenticate(const String & username, const String & password) = 0;
|
||||
|
||||
@@ -72,40 +71,70 @@ class SecurityManager {
|
||||
// Check the request header for the Authorization token
|
||||
virtual Authentication authenticateRequest(AsyncWebServerRequest * request) = 0;
|
||||
|
||||
// Filter a request with the provided predicate, only returning true if the predicate matches.
|
||||
virtual ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate) = 0;
|
||||
|
||||
// Wrap the provided request to provide validation against an AuthenticationPredicate.
|
||||
virtual ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate) = 0;
|
||||
|
||||
// Wrap the provided json request callback to provide validation against an AuthenticationPredicate.
|
||||
virtual ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate) = 0;
|
||||
|
||||
// Json endpoints - default POST
|
||||
// Json endpoints - default POST. Registered with the shared dispatcher.
|
||||
void addEndpoint(AsyncWebServer * server,
|
||||
const String & path,
|
||||
AuthenticationPredicate predicate,
|
||||
ArJsonRequestHandlerFunction function,
|
||||
WebRequestMethodComposite method = HTTP_POST) {
|
||||
auto handler = new AsyncCallbackJsonWebHandler(path);
|
||||
handler->onRequest(
|
||||
wrapCallback([this, function](AsyncWebServerRequest * request, JsonVariant json) { function(request, json); }, AuthenticationPredicates::IS_ADMIN));
|
||||
handler->setMethod(method);
|
||||
server->addHandler(handler);
|
||||
}
|
||||
WebRequestMethodComposite method = HTTP_POST);
|
||||
|
||||
// non-Json endpoints - default GET
|
||||
// non-Json endpoints - default GET. Registered with the shared dispatcher.
|
||||
void addEndpoint(AsyncWebServer * server,
|
||||
const String & path,
|
||||
AuthenticationPredicate predicate,
|
||||
ArRequestHandlerFunction function,
|
||||
WebRequestMethodComposite method = HTTP_GET) {
|
||||
auto * handler = new AsyncCallbackWebHandler();
|
||||
handler->onRequest(wrapRequest([this, function](AsyncWebServerRequest * request) { function(request); }, predicate));
|
||||
handler->setUri(path);
|
||||
handler->setMethod(method);
|
||||
server->addHandler(handler);
|
||||
WebRequestMethodComposite method = HTTP_GET);
|
||||
|
||||
private:
|
||||
// Single internal route record. Each route holds either a plain or JSON handler.
|
||||
// The URI matcher uses backward-compatible mode by default (constructed from a
|
||||
// plain String), which preserves the original library handler's matching semantics
|
||||
// (e.g. /api also matches /api/boiler/heating).
|
||||
struct RestRoute {
|
||||
AsyncURIMatcher uri;
|
||||
WebRequestMethodComposite method;
|
||||
AuthenticationPredicate predicate;
|
||||
ArRequestHandlerFunction plainHandler;
|
||||
ArJsonRequestHandlerFunction jsonHandler;
|
||||
bool isJson;
|
||||
bool requiresAuth; // false when predicate is NONE_REQUIRED, lets dispatchRest skip the JWT parse
|
||||
};
|
||||
|
||||
// Single catch-all handler. canHandle() claims a request only if some registered
|
||||
// route matches its URI + method, so non-matching URLs (static files, websockets,
|
||||
// etc.) still fall through to other handlers. handleBody buffers JSON bodies, then
|
||||
// handleRequest hands off to SecurityManager::dispatchRest for routing + auth.
|
||||
//
|
||||
// We can't reuse AsyncCallbackJsonWebHandler here because its canHandle() rejects
|
||||
// POST/PUT/PATCH without an application/json content-type (so a bodyless POST like
|
||||
// /rest/resetCustomizations would fall through to a 404), and both canHandle and
|
||||
// handleRequest are marked final on that class.
|
||||
class RestCatchAllHandler : public AsyncWebHandler {
|
||||
public:
|
||||
explicit RestCatchAllHandler(SecurityManager * owner)
|
||||
: _owner(owner) {
|
||||
}
|
||||
|
||||
bool canHandle(AsyncWebServerRequest * request) const override;
|
||||
bool isRequestHandlerTrivial() const override;
|
||||
void handleBody(AsyncWebServerRequest * request, uint8_t * data, size_t len, size_t index, size_t total) override;
|
||||
void handleRequest(AsyncWebServerRequest * request) override;
|
||||
|
||||
private:
|
||||
static constexpr size_t kMaxBodySize = 16384;
|
||||
|
||||
static bool isJsonContent(AsyncWebServerRequest * request);
|
||||
|
||||
SecurityManager * _owner;
|
||||
};
|
||||
|
||||
static bool isPublicPredicate(const AuthenticationPredicate & predicate);
|
||||
|
||||
void ensureRestDispatcher(AsyncWebServer * server);
|
||||
void dispatchRest(AsyncWebServerRequest * request, JsonVariant json);
|
||||
|
||||
std::vector<RestRoute> _restRoutes;
|
||||
bool _restDispatcherInstalled = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#include "SecuritySettingsService.h"
|
||||
|
||||
#include "../core/psram_async_json_response.h"
|
||||
|
||||
SecuritySettingsService::SecuritySettingsService(AsyncWebServer * server, FS * fs)
|
||||
: _httpEndpoint(SecuritySettings::read, SecuritySettings::update, this, server, SECURITY_SETTINGS_PATH, this)
|
||||
, _fsPersistence(SecuritySettings::read, SecuritySettings::update, this, fs, SECURITY_SETTINGS_FILE)
|
||||
, _jwtHandler(FACTORY_JWT_SECRET) {
|
||||
addUpdateHandler([this] { configureJWTHandler(); }, false);
|
||||
|
||||
server->on(GENERATE_TOKEN_PATH,
|
||||
HTTP_GET,
|
||||
SecuritySettingsService::wrapRequest([this](AsyncWebServerRequest * request) { generateToken(request); }, AuthenticationPredicates::IS_ADMIN));
|
||||
addEndpoint(server, GENERATE_TOKEN_PATH, AuthenticationPredicates::IS_ADMIN, [this](AsyncWebServerRequest * request) { generateToken(request); });
|
||||
}
|
||||
|
||||
void SecuritySettingsService::begin() {
|
||||
@@ -24,8 +24,8 @@ Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerReques
|
||||
value = value.substring(AUTHORIZATION_HEADER_PREFIX_LEN);
|
||||
return authenticateJWT(value);
|
||||
}
|
||||
} else if (request->hasParam(ACCESS_TOKEN_PARAMATER)) {
|
||||
auto tokenParamater = request->getParam(ACCESS_TOKEN_PARAMATER);
|
||||
} else if (request->hasParam(ACCESS_TOKEN_PARAMETER)) {
|
||||
auto tokenParamater = request->getParam(ACCESS_TOKEN_PARAMETER);
|
||||
String value = tokenParamater->value();
|
||||
return authenticateJWT(value);
|
||||
}
|
||||
@@ -79,40 +79,11 @@ String SecuritySettingsService::generateJWT(const User * user) {
|
||||
return _jwtHandler.buildJWT(payload);
|
||||
}
|
||||
|
||||
ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) {
|
||||
return [this, predicate](AsyncWebServerRequest * request) {
|
||||
Authentication authentication = authenticateRequest(request);
|
||||
return predicate(authentication);
|
||||
};
|
||||
}
|
||||
|
||||
ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate) {
|
||||
return [this, onRequest, predicate](AsyncWebServerRequest * request) {
|
||||
Authentication authentication = authenticateRequest(request);
|
||||
if (!predicate(authentication)) {
|
||||
request->send(401);
|
||||
return;
|
||||
}
|
||||
onRequest(request);
|
||||
};
|
||||
}
|
||||
|
||||
ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate) {
|
||||
return [this, onRequest, predicate](AsyncWebServerRequest * request, JsonVariant json) {
|
||||
Authentication authentication = authenticateRequest(request);
|
||||
if (!predicate(authentication)) {
|
||||
request->send(401);
|
||||
return;
|
||||
}
|
||||
onRequest(request, json);
|
||||
};
|
||||
}
|
||||
|
||||
void SecuritySettingsService::generateToken(AsyncWebServerRequest * request) {
|
||||
auto usernameParam = request->getParam("username");
|
||||
for (const User & _user : _state.users) {
|
||||
if (_user.username == usernameParam->value()) {
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new emsesp::PsramAsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
root["token"] = generateJWT(&_user);
|
||||
response->setLength();
|
||||
|
||||
@@ -75,9 +75,6 @@ class SecuritySettingsService final : public StatefulService<SecuritySettings>,
|
||||
Authentication authenticate(const String & username, const String & password) override;
|
||||
Authentication authenticateRequest(AsyncWebServerRequest * request) override;
|
||||
String generateJWT(const User * user) override;
|
||||
ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate) override;
|
||||
ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate) override;
|
||||
ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction callback, AuthenticationPredicate predicate) override;
|
||||
|
||||
private:
|
||||
HttpEndpoint<SecuritySettings> _httpEndpoint;
|
||||
|
||||
@@ -48,7 +48,7 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
|
||||
// LittleFS filesystem image
|
||||
_is_filesystem = true;
|
||||
_md5[0] = '\0'; // clear any stale md5 so Update.end() doesn't compare against it
|
||||
} else if ((extension == "bin") && (filesize > 1900000)) {
|
||||
} else if ((extension == "bin") && (filesize > 1000000)) {
|
||||
_is_firmware = true;
|
||||
} else if (extension == "json") {
|
||||
_md5[0] = '\0'; // clear md5
|
||||
@@ -189,7 +189,7 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) {
|
||||
|
||||
// add MD5 to the response
|
||||
if (strlen(_md5.data()) == _md5.size() - 1) {
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new emsesp::PsramAsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
root["md5"] = _md5.data();
|
||||
response->setLength();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "WiFiScanner.h"
|
||||
|
||||
#include "../core/psram_async_json_response.h"
|
||||
|
||||
WiFiScanner::WiFiScanner(AsyncWebServer * server, SecurityManager * securityManager) {
|
||||
securityManager->addEndpoint(server, SCAN_NETWORKS_SERVICE_PATH, AuthenticationPredicates::IS_ADMIN, [this](AsyncWebServerRequest * request) {
|
||||
scanNetworks(request);
|
||||
@@ -22,7 +24,7 @@ void WiFiScanner::scanNetworks(AsyncWebServerRequest * request) {
|
||||
void WiFiScanner::listNetworks(AsyncWebServerRequest * request) {
|
||||
const int numNetworks = WiFi.scanComplete();
|
||||
if (numNetworks > -1) {
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new emsesp::PsramAsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
JsonArray networks = root["networks"].to<JsonArray>();
|
||||
for (uint8_t i = 0; i < numNetworks; i++) {
|
||||
|
||||
@@ -119,9 +119,8 @@ void AnalogSensor::reload(bool get_nvs) {
|
||||
#if defined(EMSESP_STANDALONE)
|
||||
analog_enabled_ = true; // for local offline testing
|
||||
#endif
|
||||
for (auto sensor : sensors_) {
|
||||
for (const auto & sensor : sensors_) {
|
||||
remove_ha_topic(sensor.type(), sensor.gpio());
|
||||
sensor.ha_registered = false;
|
||||
#ifndef EMSESP_STANDALONE
|
||||
if ((sensor.type() >= AnalogType::CNT_0 && sensor.type() <= AnalogType::CNT_2)
|
||||
|| (sensor.type() >= AnalogType::FREQ_0 && sensor.type() <= AnalogType::FREQ_2)) {
|
||||
@@ -675,7 +674,7 @@ void AnalogSensor::publish_values(const bool force) {
|
||||
}
|
||||
}
|
||||
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
JsonObject obj = doc.to<JsonObject>();
|
||||
bool ha_dev_created = false;
|
||||
|
||||
@@ -704,7 +703,7 @@ void AnalogSensor::publish_values(const bool force) {
|
||||
if (Mqtt::ha_enabled() && (!sensor.ha_registered || force)) {
|
||||
LOG_DEBUG("Recreating HA config for analog sensor GPIO %02d", sensor.gpio());
|
||||
|
||||
JsonDocument config;
|
||||
JsonDocument config(PSRAM_DOC);
|
||||
config["~"] = Mqtt::base();
|
||||
|
||||
char stat_t[50];
|
||||
|
||||
@@ -146,7 +146,7 @@ class AnalogSensor {
|
||||
bool updated_values();
|
||||
|
||||
// return back reference to the sensor list, used by other classes
|
||||
std::vector<Sensor, AllocatorPSRAM<Sensor>> sensors() const {
|
||||
const std::vector<Sensor, AllocatorPSRAM<Sensor>> & sensors() const {
|
||||
return sensors_;
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ class AnalogSensor {
|
||||
bool get_value_info(JsonObject output, const char * cmd, const int8_t id = -1);
|
||||
void store_counters();
|
||||
std::string get_metrics_prometheus();
|
||||
static std::vector<uint8_t> exclude_types() {
|
||||
static const std::vector<uint8_t> & exclude_types() {
|
||||
return exclude_types_;
|
||||
}
|
||||
|
||||
|
||||
@@ -527,8 +527,9 @@ Command::CmdFunction * Command::find_command(const uint8_t device_type, const ui
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::string cmd_lower = Helpers::toLower(cmd);
|
||||
for (auto & cf : cmdfunctions_) {
|
||||
if (Helpers::toLower(cmd) == Helpers::toLower(cf.cmd_) && (cf.device_type_ == device_type) && (!device_id || cf.device_id_ == device_id)
|
||||
if (cmd_lower == Helpers::toLower(cf.cmd_) && (cf.device_type_ == device_type) && (!device_id || cf.device_id_ == device_id)
|
||||
&& (cf.device_type_ < EMSdevice::DeviceType::BOILER || flag == CommandFlag::CMD_FLAG_DEFAULT || (flag & 0x3F) == (cf.flags_ & 0x3F))) {
|
||||
return &cf;
|
||||
}
|
||||
@@ -554,9 +555,10 @@ void Command::erase_command(const uint8_t device_type, const char * cmd, uint8_t
|
||||
if ((cmd == nullptr) || (strlen(cmd) == 0) || (cmdfunctions_.empty())) {
|
||||
return;
|
||||
}
|
||||
const std::string cmd_lower = Helpers::toLower(cmd);
|
||||
auto it = cmdfunctions_.begin();
|
||||
for (auto const & cf : cmdfunctions_) {
|
||||
if (Helpers::toLower(cmd) == Helpers::toLower(cf.cmd_) && (cf.device_type_ == device_type) && ((flag & 0x3F) == (cf.flags_ & 0x3F))) {
|
||||
if (cmd_lower == Helpers::toLower(cf.cmd_) && (cf.device_type_ == device_type) && ((flag & 0x3F) == (cf.flags_ & 0x3F))) {
|
||||
cmdfunctions_.erase(it);
|
||||
return;
|
||||
}
|
||||
|
||||
+1
-1
@@ -98,7 +98,7 @@ class Command {
|
||||
}
|
||||
};
|
||||
|
||||
static std::vector<CmdFunction, AllocatorPSRAM<CmdFunction>> commands() {
|
||||
static const std::vector<CmdFunction, AllocatorPSRAM<CmdFunction>> & commands() {
|
||||
return cmdfunctions_;
|
||||
}
|
||||
|
||||
|
||||
@@ -187,8 +187,9 @@
|
||||
{ 74, DeviceType::ALERT, "EM10", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||
|
||||
// Gateways - 0x48
|
||||
{17, DeviceType::GATEWAY, "MX400", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x48 and 0x4B
|
||||
{189, DeviceType::GATEWAY, "KM200, MB LAN 2", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||
{17, DeviceType::GATEWAY, "MX400", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x48, 0x4B, or 0x50 as wireless base
|
||||
{189, DeviceType::GATEWAY, "KM200, MB LAN 2", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x48
|
||||
{222, DeviceType::GATEWAY, "KM300,", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x4A
|
||||
{252, DeviceType::GATEWAY, "K30RF, MX300", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||
|
||||
// Generic - 0x40 or other with no product-id and no version
|
||||
|
||||
+10
-6
@@ -105,8 +105,12 @@ const char * EMSdevice::uom_to_string(uint8_t uom) {
|
||||
}
|
||||
|
||||
std::string EMSdevice::brand_to_char() {
|
||||
return std::string{brand_to_cstr()};
|
||||
}
|
||||
|
||||
const char * EMSdevice::brand_to_cstr() const {
|
||||
if (!custom_brand().empty()) {
|
||||
return custom_brand();
|
||||
return custom_brand().c_str();
|
||||
}
|
||||
switch (brand_) {
|
||||
case EMSdevice::Brand::BOSCH:
|
||||
@@ -2160,7 +2164,7 @@ void EMSdevice::mqtt_ha_entity_config_create() {
|
||||
if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && dv.has_state(DeviceValueState::DV_ACTIVE)
|
||||
&& !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE)) {
|
||||
// create_device_config is only done once for the EMS device. It can added to any entity, so we take the first
|
||||
if (Mqtt::publish_ha_sensor_config_dv(dv, name().c_str(), brand_to_char().c_str(), to_string_version().c_str(), false, create_device_config)) {
|
||||
if (Mqtt::publish_ha_sensor_config_dv(dv, name().c_str(), brand_to_cstr(), to_string_version().c_str(), false, create_device_config)) {
|
||||
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
||||
create_device_config = false; // only create the main config once
|
||||
count++;
|
||||
@@ -2224,7 +2228,7 @@ bool EMSdevice::has_telegram_id(uint16_t id) const {
|
||||
}
|
||||
|
||||
// return the name of the telegram type
|
||||
const char * EMSdevice::telegram_type_name(std::shared_ptr<const Telegram> telegram) {
|
||||
const char * EMSdevice::telegram_type_name(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// see if it's one of the common ones, like Version
|
||||
if (telegram->type_id == EMS_TYPE_VERSION) {
|
||||
return "Version";
|
||||
@@ -2243,12 +2247,12 @@ const char * EMSdevice::telegram_type_name(std::shared_ptr<const Telegram> teleg
|
||||
|
||||
// take a telegram_type_id and call the matching handler
|
||||
// return true if match found
|
||||
bool EMSdevice::handle_telegram(std::shared_ptr<const Telegram> telegram) {
|
||||
bool EMSdevice::handle_telegram(const std::shared_ptr<const Telegram> & telegram) {
|
||||
for (auto & tf : telegram_functions_) {
|
||||
if (tf.telegram_type_id_ == telegram->type_id) {
|
||||
// for telegram destination only read telegram
|
||||
if (telegram->dest == device_id_ && telegram->message_length > 0) {
|
||||
tf.process_function_(telegram);
|
||||
tf.process_function_(this, telegram);
|
||||
return true;
|
||||
}
|
||||
// if the data block is empty and we have not received data before, assume that this telegram
|
||||
@@ -2266,7 +2270,7 @@ bool EMSdevice::handle_telegram(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
if (telegram->message_length > 0) {
|
||||
tf.received_ = true;
|
||||
tf.process_function_(telegram);
|
||||
tf.process_function_(this, telegram);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
+40
-19
@@ -26,6 +26,7 @@
|
||||
#include "emsdevicevalue.h"
|
||||
|
||||
#include <esp32-psram.h>
|
||||
#include <initializer_list>
|
||||
#include <map>
|
||||
|
||||
namespace emsesp {
|
||||
@@ -34,7 +35,15 @@ class EMSdevice {
|
||||
public:
|
||||
virtual ~EMSdevice() = default; // destructor of base class must always be virtual because it's a polymorphic class
|
||||
|
||||
using process_function_p = std::function<void(std::shared_ptr<const Telegram>)>;
|
||||
// Raw function pointer + EMSdevice* context, instead of std::function.
|
||||
// Each std::function<void(...)> typically heap-allocates its capture (a few
|
||||
// bytes for the [&] closure) on libstdc++ ESP32 builds. With hundreds of
|
||||
// registered telegram handlers across devices, that's tens of KB of
|
||||
// long-lived heap. The MAKE_PF_CB macro produces a non-capturing trampoline
|
||||
// that decays to this raw pointer (zero heap, zero indirection beyond the
|
||||
// call itself). The first parameter receives `this` of the dispatching
|
||||
// EMSdevice instance; the trampoline downcasts to the actual derived type.
|
||||
using process_function_p = void (*)(EMSdevice * dev, const std::shared_ptr<const Telegram> & t);
|
||||
|
||||
// device_type defines which derived class to use, e.g. BOILER, THERMOSTAT etc..
|
||||
EMSdevice(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * default_name, uint8_t flags, uint8_t brand)
|
||||
@@ -64,6 +73,7 @@ class EMSdevice {
|
||||
bool has_tags(const int8_t tag) const;
|
||||
bool has_cmd(const char * cmd, const int8_t id) const;
|
||||
std::string brand_to_char();
|
||||
const char * brand_to_cstr() const;
|
||||
std::string to_string();
|
||||
std::string to_string_short();
|
||||
std::string to_string_version();
|
||||
@@ -125,7 +135,7 @@ class EMSdevice {
|
||||
custom_name_ = custom_name;
|
||||
}
|
||||
|
||||
std::string custom_name() const {
|
||||
const std::string & custom_name() const {
|
||||
return custom_name_;
|
||||
}
|
||||
|
||||
@@ -134,7 +144,7 @@ class EMSdevice {
|
||||
custom_brand_ = custom_brand;
|
||||
}
|
||||
|
||||
std::string custom_brand() const {
|
||||
const std::string & custom_brand() const {
|
||||
return custom_brand_;
|
||||
}
|
||||
// set device model
|
||||
@@ -142,7 +152,7 @@ class EMSdevice {
|
||||
model_ = model;
|
||||
}
|
||||
|
||||
std::string model() const {
|
||||
const std::string & model() const {
|
||||
return model_;
|
||||
}
|
||||
|
||||
@@ -207,29 +217,36 @@ class EMSdevice {
|
||||
}
|
||||
}
|
||||
|
||||
void has_enumupdate(std::shared_ptr<const Telegram> telegram, uint8_t & value, const uint8_t index, int8_t s = 0) {
|
||||
void has_enumupdate(const std::shared_ptr<const Telegram> & telegram, uint8_t & value, const uint8_t index, int8_t s = 0) {
|
||||
if (telegram->read_enumvalue(value, index, s)) {
|
||||
has_update_ = true;
|
||||
publish_value((void *)&value);
|
||||
}
|
||||
}
|
||||
|
||||
void has_enumupdate(std::shared_ptr<const Telegram> telegram, uint8_t & value, const uint8_t index, const std::vector<uint8_t> & maskIn) {
|
||||
uint8_t val = value < maskIn.size() ? maskIn[value] : EMS_VALUE_UINT8_NOTSET;
|
||||
// maskIn is taken as a std::initializer_list so brace-list call sites
|
||||
// like has_enumupdate(t, v, idx, {0,5,1,2,4}) avoid the per-call
|
||||
// heap allocation of a temporary std::vector<uint8_t>. The backing
|
||||
// array of an initializer_list of integral constants is placed in
|
||||
// static storage or on the stack — never on the heap.
|
||||
void has_enumupdate(const std::shared_ptr<const Telegram> & telegram, uint8_t & value, const uint8_t index, std::initializer_list<uint8_t> maskIn) {
|
||||
uint8_t val = value < maskIn.size() ? *(maskIn.begin() + value) : EMS_VALUE_UINT8_NOTSET;
|
||||
if (telegram->read_value(val, index)) {
|
||||
for (uint8_t i = 0; i < maskIn.size(); i++) {
|
||||
if (val == maskIn[i]) {
|
||||
uint8_t i = 0;
|
||||
for (auto m : maskIn) {
|
||||
if (val == m) {
|
||||
value = i;
|
||||
has_update_ = true;
|
||||
publish_value((void *)&value);
|
||||
return;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Value>
|
||||
void has_update(std::shared_ptr<const Telegram> telegram, Value & value, const uint8_t index, uint8_t s = 0) {
|
||||
void has_update(const std::shared_ptr<const Telegram> & telegram, Value & value, const uint8_t index, uint8_t s = 0) {
|
||||
if (telegram->read_value(value, index, s)) {
|
||||
has_update_ = true;
|
||||
publish_value((void *)&value);
|
||||
@@ -237,7 +254,7 @@ class EMSdevice {
|
||||
}
|
||||
|
||||
template <typename BitValue>
|
||||
void has_bitupdate(std::shared_ptr<const Telegram> telegram, BitValue & value, const uint8_t index, uint8_t b) {
|
||||
void has_bitupdate(const std::shared_ptr<const Telegram> & telegram, BitValue & value, const uint8_t index, uint8_t b) {
|
||||
if (telegram->read_bitvalue(value, index, b)) {
|
||||
has_update_ = true;
|
||||
publish_value((void *)&value);
|
||||
@@ -260,7 +277,7 @@ class EMSdevice {
|
||||
void getCustomizationEntities(std::vector<std::string> & entity_ids);
|
||||
|
||||
void register_telegram_type(const uint16_t telegram_type_id, const char * telegram_type_name, bool fetch, const process_function_p cb, uint8_t length = 0);
|
||||
bool handle_telegram(std::shared_ptr<const Telegram> telegram);
|
||||
bool handle_telegram(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
std::string get_value_uom(const std::string & shortname) const;
|
||||
bool get_value_info(JsonObject root, const char * cmd, const int8_t id);
|
||||
@@ -359,7 +376,7 @@ class EMSdevice {
|
||||
void publish_value(void * value_p) const;
|
||||
void publish_all_values();
|
||||
void mqtt_ha_entity_config_create();
|
||||
const char * telegram_type_name(std::shared_ptr<const Telegram> telegram);
|
||||
const char * telegram_type_name(const std::shared_ptr<const Telegram> & telegram);
|
||||
void fetch_values();
|
||||
void toggle_fetch(uint16_t telegram_id, bool toggle);
|
||||
bool is_fetch(uint16_t telegram_id, uint8_t len = 0) const;
|
||||
@@ -518,13 +535,17 @@ class EMSdevice {
|
||||
uint8_t count_entities_fav();
|
||||
bool has_entities() const;
|
||||
|
||||
// void reserve_device_values(uint8_t elements) {
|
||||
// devicevalues_.reserve(elements);
|
||||
// }
|
||||
// Pre-allocate vector capacity to avoid realloc storms during device
|
||||
// construction. Realloc here is especially expensive because each entry
|
||||
// contains a std::function (heap-allocated functor) and DeviceValue
|
||||
// (with std::string member), so growing copies a lot.
|
||||
void reserve_device_values(uint16_t elements) {
|
||||
devicevalues_.reserve(elements);
|
||||
}
|
||||
|
||||
// void reserve_telegram_functions(uint8_t elements) {
|
||||
// telegram_functions_.reserve(elements);
|
||||
// }
|
||||
void reserve_telegram_functions(uint8_t elements) {
|
||||
telegram_functions_.reserve(elements);
|
||||
}
|
||||
|
||||
#if defined(EMSESP_STANDALONE)
|
||||
struct TelegramFunctionDump {
|
||||
|
||||
@@ -38,21 +38,23 @@ DeviceValue::DeviceValue(uint8_t device_type,
|
||||
int16_t min,
|
||||
uint32_t max,
|
||||
uint8_t state)
|
||||
: device_type(device_type)
|
||||
, tag(tag)
|
||||
, value_p(value_p)
|
||||
, type(type)
|
||||
, options(options)
|
||||
, options_single(options_single)
|
||||
, numeric_operator(numeric_operator)
|
||||
// Initializer list ordered to match the reordered field declarations in
|
||||
// emsdevicevalue.h (pointers first, then 1-byte block, then 2/4-byte, then std::string)
|
||||
: value_p(value_p)
|
||||
, short_name(short_name)
|
||||
, fullname(fullname)
|
||||
, custom_fullname(custom_fullname)
|
||||
, options(options)
|
||||
, options_single(options_single)
|
||||
, device_type(device_type)
|
||||
, tag(tag)
|
||||
, type(type)
|
||||
, state(state)
|
||||
, numeric_operator(numeric_operator)
|
||||
, uom(uom)
|
||||
, has_cmd(has_cmd)
|
||||
, min(min)
|
||||
, max(max)
|
||||
, state(state) {
|
||||
, custom_fullname(custom_fullname) {
|
||||
// calculate #options in options list
|
||||
if (options_single) {
|
||||
options_size = 1;
|
||||
|
||||
+14
-10
@@ -167,23 +167,27 @@ class DeviceValue {
|
||||
DV_NUMOP_MUL50 = -50
|
||||
};
|
||||
|
||||
uint8_t device_type; // EMSdevice::DeviceType
|
||||
int8_t tag; // DeviceValueTAG::*
|
||||
// Layout chosen for compact packing AND cache locality on 32-bit ESP32.
|
||||
// pointers — 5 × 4 bytes, all naturally aligned
|
||||
void * value_p; // pointer to variable of any type
|
||||
uint8_t type; // DeviceValueType::*
|
||||
const char * const ** options; // options as a flash char array
|
||||
const char * const * options_single; // options are not translated
|
||||
int8_t numeric_operator;
|
||||
const char * const short_name; // used in MQTT and API
|
||||
const char * const * fullname; // used in Web and Console, is translated
|
||||
std::string custom_fullname; // optional, from customization
|
||||
const char * const ** options; // options as a flash char array
|
||||
const char * const * options_single; // options are not translated
|
||||
// single-byte fields packed together — hot fields, share cache line 0 with the pointers above
|
||||
uint8_t device_type; // EMSdevice::DeviceType
|
||||
int8_t tag; // DeviceValueTAG::*
|
||||
uint8_t type; // DeviceValueType::*
|
||||
uint8_t state; // DeviceValueState::*
|
||||
int8_t numeric_operator; // DeviceValueNumOp::*
|
||||
uint8_t uom; // DeviceValueUOM::*
|
||||
bool has_cmd; // true if there is a Console/MQTT command which matches the short_name
|
||||
uint8_t options_size; // number of options in the char array, calculated at class initialization
|
||||
// wider numeric range fields
|
||||
int16_t min; // min range
|
||||
uint32_t max; // max range
|
||||
uint8_t state; // DeviceValueState::*
|
||||
|
||||
uint8_t options_size; // number of options in the char array, calculated at class initialization
|
||||
// largest member last (cold path: only read during customization save/load and web display)
|
||||
std::string custom_fullname; // optional, from customization
|
||||
|
||||
DeviceValue(uint8_t device_type, // EMSdevice::DeviceType
|
||||
int8_t tag, // DeviceValueTAG::*
|
||||
|
||||
+10
-10
@@ -436,7 +436,7 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) {
|
||||
// print header, with device type translated
|
||||
shell.printfln("%s: %s (%d)", emsdevice->device_type_2_device_name_translated(), emsdevice->to_string().c_str(), emsdevice->count_entities());
|
||||
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
JsonObject json = doc.to<JsonObject>();
|
||||
|
||||
emsdevice->generate_values(json, DeviceValueTAG::TAG_NONE, true, EMSdevice::OUTPUT_TARGET::CONSOLE);
|
||||
@@ -460,7 +460,7 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) {
|
||||
// show any custom entities
|
||||
if (webCustomEntityService.count_entities() > 0) {
|
||||
shell.printfln("Custom Entities:");
|
||||
JsonDocument custom_doc; // use max size
|
||||
JsonDocument custom_doc(PSRAM_DOC); // use max size
|
||||
JsonObject custom_output = custom_doc.to<JsonObject>();
|
||||
webCustomEntityService.show_values(custom_output);
|
||||
for (JsonPair p : custom_output) {
|
||||
@@ -625,7 +625,7 @@ void EMSESP::reset_mqtt_ha() {
|
||||
// this will also create the HA /config topic for each device value
|
||||
// generate_values_json is called to build the device value (dv) object array
|
||||
void EMSESP::publish_device_values(uint8_t device_type) {
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
JsonObject json = doc.to<JsonObject>();
|
||||
bool need_publish = false;
|
||||
bool nested = (Mqtt::is_nested());
|
||||
@@ -701,7 +701,7 @@ void EMSESP::publish_sensor_values(const bool time, const bool force) {
|
||||
}
|
||||
|
||||
// MQTT publish a telegram as raw data to the topic 'response'
|
||||
void EMSESP::publish_response(std::shared_ptr<const Telegram> telegram) {
|
||||
void EMSESP::publish_response(const std::shared_ptr<const Telegram> & telegram) {
|
||||
static char * buffer = nullptr;
|
||||
static uint8_t offset = 0;
|
||||
static uint16_t type = 0;
|
||||
@@ -815,7 +815,7 @@ std::string EMSESP::device_tostring(const uint8_t device_id) {
|
||||
|
||||
// create a pretty print telegram as a text string
|
||||
// e.g. Boiler(0x08) -> Me(0x0B), Version(0x02), data: 7B 06 01 00 00 00 00 00 00 04 (offset 1)
|
||||
std::string EMSESP::pretty_telegram(std::shared_ptr<const Telegram> telegram) {
|
||||
std::string EMSESP::pretty_telegram(const std::shared_ptr<const Telegram> & telegram) {
|
||||
uint8_t src = telegram->src & 0x7F;
|
||||
uint8_t dest = telegram->dest & 0x7F;
|
||||
uint8_t offset = telegram->offset;
|
||||
@@ -975,7 +975,7 @@ std::string EMSESP::pretty_telegram(std::shared_ptr<const Telegram> telegram) {
|
||||
* e.g. in example above 1st byte = x0B = b1011 so we have deviceIDs 0x08, 0x09, 0x011
|
||||
* and 2nd byte = x80 = b1000 b0000 = deviceID 0x17
|
||||
*/
|
||||
void EMSESP::process_UBADevices(std::shared_ptr<const Telegram> telegram) {
|
||||
void EMSESP::process_UBADevices(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// exit it length is incorrect (must be 13 or 15 bytes long)
|
||||
if (telegram->message_length > 15) {
|
||||
return;
|
||||
@@ -1001,7 +1001,7 @@ void EMSESP::process_UBADevices(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// read deviceName from telegram 0x01 offset 27 and set it to custom name
|
||||
void EMSESP::process_deviceName(std::shared_ptr<const Telegram> telegram) {
|
||||
void EMSESP::process_deviceName(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// exit if only part of name fields
|
||||
if (telegram->offset > 27 || (telegram->offset + telegram->message_length) < 29) {
|
||||
return;
|
||||
@@ -1029,7 +1029,7 @@ void EMSESP::process_deviceName(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// process the Version telegram (type 0x02), which is a common type
|
||||
// e.g. 09 0B 02 00 PP V1 V2
|
||||
void EMSESP::process_version(std::shared_ptr<const Telegram> telegram) {
|
||||
void EMSESP::process_version(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// check for valid telegram, just in case
|
||||
if (telegram->offset != 0) {
|
||||
return;
|
||||
@@ -1087,7 +1087,7 @@ void EMSESP::process_version(std::shared_ptr<const Telegram> telegram) {
|
||||
// but only process if the telegram is sent to us or it's a broadcast (dest=0x00=all)
|
||||
// We also check for common telegram types, like the Version(0x02)
|
||||
// returns false if there are none found
|
||||
bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
|
||||
bool EMSESP::process_telegram(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// if watching or reading...
|
||||
if ((telegram->type_id == read_id_ || telegram->type_id == response_id_) && (telegram->dest == EMSbus::ems_bus_id())) {
|
||||
if (telegram->type_id == response_id_) {
|
||||
@@ -1868,7 +1868,7 @@ void EMSESP::loop() {
|
||||
// start an upload from a URL, assuming the URL exists and set from a previous pass
|
||||
// Note this next call is synchronous and blocking.
|
||||
if (!system_.uploadFirmwareURL()) {
|
||||
// upload failed, send a "reset" to return back to normal
|
||||
// upload failed, send a "reset" to reset the OTA URL
|
||||
Shell::loop_all(); // flush log buffers so latest error message are shown in console
|
||||
system_.uploadFirmwareURL("reset");
|
||||
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_ERROR_UPLOAD);
|
||||
|
||||
+21
-7
@@ -56,6 +56,8 @@
|
||||
#include "../web/WebCustomEntityService.h"
|
||||
#include "../web/WebModulesService.h"
|
||||
|
||||
#include "psram_json_allocator.h"
|
||||
#include "psram_async_json_response.h"
|
||||
#include "emsdevicevalue.h"
|
||||
#include "emsdevice.h"
|
||||
#include "emsfactory.h"
|
||||
@@ -82,7 +84,19 @@ class Module {}; // forward declaration
|
||||
#define WATCH_ID_NONE 0 // no watch id set
|
||||
|
||||
// helpers for callback functions
|
||||
#define MAKE_PF_CB(__f) [&](std::shared_ptr<const Telegram> t) { __f(t); } // for Process Function callbacks to EMSDevice::process_function_p
|
||||
//
|
||||
// MAKE_PF_CB(member) produces a non-capturing trampoline that decays to a
|
||||
// plain function pointer (EMSdevice::process_function_p). The outer IILE
|
||||
// (immediately-invoked lambda expression) captures `this` purely to deduce
|
||||
// the derived-class type via decltype; the inner lambda is non-capturing and
|
||||
// therefore convertible to a function pointer via the unary `+` operator.
|
||||
// Result: zero heap (no std::function control block) and direct dispatch.
|
||||
#define MAKE_PF_CB(__f) \
|
||||
([this]() { \
|
||||
using SelfT = std::remove_pointer_t<decltype(this)>; \
|
||||
return +[](emsesp::EMSdevice * dev, const std::shared_ptr<const Telegram> & t) { static_cast<SelfT *>(dev)->__f(t); }; \
|
||||
}())
|
||||
|
||||
#define MAKE_CF_CB(__f) [&](const char * value, const int8_t id) { return __f(value, id); } // for Command Function callbacks Command::cmd_function_p
|
||||
|
||||
namespace emsesp {
|
||||
@@ -121,8 +135,8 @@ class EMSESP {
|
||||
static void uart_telegram(const std::vector<uint8_t> & rx_data);
|
||||
#endif
|
||||
|
||||
static bool process_telegram(std::shared_ptr<const Telegram> telegram);
|
||||
static std::string pretty_telegram(std::shared_ptr<const Telegram> telegram);
|
||||
static bool process_telegram(const std::shared_ptr<const Telegram> & telegram);
|
||||
static std::string pretty_telegram(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
static void send_read_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset = 0, const uint8_t length = 0, const bool front = false);
|
||||
static void send_write_request(const uint16_t type_id,
|
||||
@@ -251,10 +265,10 @@ class EMSESP {
|
||||
|
||||
private:
|
||||
static std::string device_tostring(const uint8_t device_id);
|
||||
static void process_UBADevices(std::shared_ptr<const Telegram> telegram);
|
||||
static void process_deviceName(std::shared_ptr<const Telegram> telegram);
|
||||
static void process_version(std::shared_ptr<const Telegram> telegram);
|
||||
static void publish_response(std::shared_ptr<const Telegram> telegram);
|
||||
static void process_UBADevices(const std::shared_ptr<const Telegram> & telegram);
|
||||
static void process_deviceName(const std::shared_ptr<const Telegram> & telegram);
|
||||
static void process_version(const std::shared_ptr<const Telegram> & telegram);
|
||||
static void publish_response(const std::shared_ptr<const Telegram> & telegram);
|
||||
static void publish_all_loop();
|
||||
|
||||
void shell_prompt();
|
||||
|
||||
@@ -23,17 +23,21 @@
|
||||
|
||||
using uuid::log::Level;
|
||||
|
||||
// Log macros gate on logger_.enabled(level) so that expensive argument
|
||||
// expressions (e.g. pretty_telegram(...).c_str()) are not evaluated when
|
||||
// the level is filtered out. Without this, every LOG_TRACE on the RX path
|
||||
// allocates a std::string even when no handler is interested.
|
||||
#if defined(EMSESP_DEBUG)
|
||||
#define LOG_DEBUG(...) logger_.debug(__VA_ARGS__)
|
||||
#define LOG_DEBUG(...) (logger_.enabled(uuid::log::Level::DEBUG) ? logger_.debug(__VA_ARGS__) : (void)0)
|
||||
#else
|
||||
#define LOG_DEBUG(...)
|
||||
#define LOG_DEBUG(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#define LOG_INFO(...) logger_.info(__VA_ARGS__)
|
||||
#define LOG_TRACE(...) logger_.trace(__VA_ARGS__)
|
||||
#define LOG_NOTICE(...) logger_.notice(__VA_ARGS__)
|
||||
#define LOG_WARNING(...) logger_.warning(__VA_ARGS__)
|
||||
#define LOG_ERROR(...) logger_.err(__VA_ARGS__)
|
||||
#define LOG_INFO(...) (logger_.enabled(uuid::log::Level::INFO) ? logger_.info(__VA_ARGS__) : (void)0)
|
||||
#define LOG_TRACE(...) (logger_.enabled(uuid::log::Level::TRACE) ? logger_.trace(__VA_ARGS__) : (void)0)
|
||||
#define LOG_NOTICE(...) (logger_.enabled(uuid::log::Level::NOTICE) ? logger_.notice(__VA_ARGS__) : (void)0)
|
||||
#define LOG_WARNING(...) (logger_.enabled(uuid::log::Level::WARNING) ? logger_.warning(__VA_ARGS__) : (void)0)
|
||||
#define LOG_ERROR(...) (logger_.enabled(uuid::log::Level::ERR) ? logger_.err(__VA_ARGS__) : (void)0)
|
||||
|
||||
// flash strings
|
||||
using uuid::string_vector;
|
||||
|
||||
@@ -293,7 +293,7 @@ MAKE_WORD_TRANSLATION(curve, "heatingcurve", "Heizkurve", "stookkromme", "värme
|
||||
MAKE_WORD_TRANSLATION(radiator, "radiator", "Heizkörper", "radiator", "Radiator", "grzejniki", "radiator", "radiateur", "radyatör", "radiatore", "radiátor", "radiátor")
|
||||
MAKE_WORD_TRANSLATION(convector, "convector", "Konvektor", "convector", "Konvektor", "konwektory", "konvektor", "convecteur", "convector", "convettore", "konvektor", "konvektor")
|
||||
MAKE_WORD_TRANSLATION(floor, "floor", "Fussboden", "vloer", "Golv", "podłoga", "gulv", "sol", "yer", "pavimento", "podlaha", "podlaha")
|
||||
MAKE_WORD_TRANSLATION(roomflow, "roomflow", "Raum Fluß", "kamer doorstroming", "Rumsflöde", "przepływ w pomieszczeniu", "romstrøm", "flux de la pièce", "oda akışı", "flusso della stanza", "prúdenie miestnosti", "průtok mistnosti")
|
||||
MAKE_WORD_TRANSLATION(roomflow, "roomflow", "Raum Fluss", "kamer doorstroming", "Rumsflöde", "przepływ w pomieszczeniu", "romstrøm", "flux de la pièce", "oda akışı", "flusso della stanza", "prúdenie miestnosti", "průtok mistnosti")
|
||||
MAKE_WORD_TRANSLATION(roomload, "roomload", "Raum Bedarf", "kamer behoefte", "Rumsbehov", "zapotrzebowanie pomieszczenia", "rombelastning", "charge de la pièce", "oda yükü", "carico della stanza", "izbová zaťaž", "zatížení místnosti")
|
||||
MAKE_WORD_TRANSLATION(summer, "summer", "Sommer", "zomer", "Sommar", "lato", "sommer", "été", "yaz", "estate", "leto", "léto")
|
||||
MAKE_WORD_TRANSLATION(winter, "winter", "Winter", "winter", "Vinter", "zima", "vinter", "hiver", "kış", "inverno", "zima", "zima")
|
||||
@@ -827,8 +827,8 @@ MAKE_TRANSLATION(vacations7, "vacations7", "vacation dates 7", "Urlaubstage 7",
|
||||
MAKE_TRANSLATION(vacations8, "vacations8", "vacation dates 8", "Urlaubstage 8", "Vakantiedagen 8", "Semesterdatum 8", "urlop 8", "feriedager 8", "dates vacances 8", "izin günleri 8", "date vacanze 8", "termíny dovolenky 8", "data prázdnin 8")
|
||||
MAKE_TRANSLATION(absent, "absent", "absent", "Abwesend", "", "Frånvarande", "", "", "", "", "", "chýbajúci", "chybějící")
|
||||
MAKE_TRANSLATION(redthreshold, "redthreshold", "reduction threshold", "Absenkschwelle", "", "Tröskel för sänkning", "", "", "", "", "", "zníženie tresholdu", "práh snížení")
|
||||
MAKE_TRANSLATION(solarinfl, "solarinfl", "solar influence", "Solareinfluß", "", "", "", "", "", "", "", "slnečný vplyv", "sluneční vliv")
|
||||
MAKE_TRANSLATION(currsolarinfl, "currsolarinfl", "current solar influence", "akt. Solareinfluß", "", "", "", "", "", "", "", "aktuálny slnečný vplyv", "aktuální sluneční vliv")
|
||||
MAKE_TRANSLATION(solarinfl, "solarinfl", "solar influence", "Solareinfluss", "", "", "", "", "", "", "", "slnečný vplyv", "sluneční vliv")
|
||||
MAKE_TRANSLATION(currsolarinfl, "currsolarinfl", "current solar influence", "akt. Solareinfluss", "", "", "", "", "", "", "", "aktuálny slnečný vplyv", "aktuální sluneční vliv")
|
||||
MAKE_TRANSLATION(hpmode, "hpmode", "HP Mode", "WP-Modus", "Modus warmtepomp", "Värmepumpsläge", "tryb pracy pompy ciepła", "", "", "yüksek güç modu", "Modalità Termopompa", "Režim TČ", "režim tepelného čerpadla")
|
||||
MAKE_TRANSLATION(dewoffset, "dewoffset", "dew point offset", "Taupunktdifferenz", "Offset dauwpunt", "Daggpunktsförskjutning", "przesunięcie punktu rosy", "", "", "çiğ noktası göreli", "differenza del punto di rugiada", "posun rosného bodu", "offset rosného bodu")
|
||||
MAKE_TRANSLATION(roomtempdiff, "roomtempdiff", "room temp difference", "Raumtemperaturdifferenz", "Verschiltemperatuur kamertemp", "Rumstemperaturskillnad", "różnica temp. pomieszczenia", "", "", "oda sıcaklığı farkı", "differenza temperatura ambiente", "rozdiel izbovej teploty", "rozdíl teploty místnosti")
|
||||
|
||||
+3
-3
@@ -519,7 +519,7 @@ void Mqtt::on_connect() {
|
||||
// e.g. homeassistant/sensor/ems-esp/status/config
|
||||
// all the values from the heartbeat payload will be added as attributes to the entity state
|
||||
void Mqtt::ha_status() {
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
|
||||
char uniq[70];
|
||||
if (Mqtt::entity_format() == entityFormat::MULTI_SHORT) {
|
||||
@@ -981,7 +981,7 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
||||
}
|
||||
|
||||
// build the full topic's payload
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
doc["~"] = Mqtt::base();
|
||||
doc["uniq_id"] = uniq_id;
|
||||
|
||||
@@ -1406,7 +1406,7 @@ bool Mqtt::publish_ha_climate_config(const DeviceValue & dv, const bool has_room
|
||||
snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/%s/%s%d/seltemp", devicename, tagname, hc_num);
|
||||
snprintf(mode_cmd_s, sizeof(mode_cmd_s), "~/%s/%s%d/mode", devicename, tagname, hc_num);
|
||||
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
|
||||
doc["~"] = Mqtt::base();
|
||||
doc["uniq_id"] = uniq_id_s;
|
||||
|
||||
+3
-3
@@ -146,11 +146,11 @@ class Mqtt {
|
||||
mqtt_enabled_ = mqtt_enabled;
|
||||
}
|
||||
|
||||
static std::string base() {
|
||||
static const std::string & base() {
|
||||
return mqtt_base_;
|
||||
}
|
||||
|
||||
static std::string basename() {
|
||||
static const std::string & basename() {
|
||||
return mqtt_basename_;
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ class Mqtt {
|
||||
ha_enabled_ = ha_enabled;
|
||||
}
|
||||
|
||||
static std::string get_response() {
|
||||
static const std::string & get_response() {
|
||||
return lastresponse_;
|
||||
}
|
||||
|
||||
|
||||
@@ -501,8 +501,6 @@ void Network::startWIFI() {
|
||||
|
||||
wifi_connect_pending_ = true;
|
||||
|
||||
LOG_DEBUG("WiFi connection with %s and %s", ssid_.c_str(), password_.c_str());
|
||||
|
||||
// attempt to connect to the wifi network
|
||||
// the event handlers handle error handling and retries
|
||||
uint8_t bssid[6];
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2025 emsesp.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef EMSESP_PSRAM_ASYNC_JSON_RESPONSE_H
|
||||
#define EMSESP_PSRAM_ASYNC_JSON_RESPONSE_H
|
||||
|
||||
#include "psram_json_allocator.h"
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
#include <AsyncJson.h>
|
||||
#include <ChunkPrint.h>
|
||||
#else
|
||||
#include <AsyncJson.h>
|
||||
#endif
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
// AsyncJsonResponse subclass whose JsonDocument lives in PSRAM instead of
|
||||
// internal SRAM.
|
||||
//
|
||||
// Why: every web API response goes through AsyncJsonResponse. The library's
|
||||
// base class declares `JsonDocument _jsonBuffer;` with the *default*
|
||||
// allocator, which on ESP32 means malloc() → internal heap. For large
|
||||
// payloads (Dashboard, /rest/coreData, /rest/sensorData, full settings,
|
||||
// customizations, etc.) this transiently consumes many KB of the same
|
||||
// internal heap that LwIP / AsyncTCP / mbedTLS also need. Each concurrent
|
||||
// browser tab compounds the cost.
|
||||
//
|
||||
// We can't change the base class's _jsonBuffer allocator (the upstream
|
||||
// constructor doesn't take one), but we can route around it: keep our own
|
||||
// PSRAM-backed document, override the virtual setLength()/_fillBuffer() so
|
||||
// the framework serialises *our* document, and name-hide getRoot() so
|
||||
// callers populate *our* document. The base's _jsonBuffer stays empty
|
||||
// (just one root slot, <~32 bytes).
|
||||
//
|
||||
// Callers must use the derived type (or `auto`) when calling getRoot(),
|
||||
// because getRoot() is non-virtual in the base. `request->send(response)`
|
||||
// works as-is because setLength()/_fillBuffer() ARE virtual in the
|
||||
// AsyncAbstractResponse grandparent.
|
||||
//
|
||||
// On standalone the lib_standalone AsyncJsonResponse stub never actually
|
||||
// serves responses, so this whole class still compiles and behaves
|
||||
// identically (allocator falls back to malloc anyway).
|
||||
class PsramAsyncJsonResponse : public ::AsyncJsonResponse {
|
||||
public:
|
||||
explicit PsramAsyncJsonResponse(bool isArray = false)
|
||||
: ::AsyncJsonResponse(isArray)
|
||||
, psram_doc_(PsramJsonAllocator::instance()) {
|
||||
if (isArray) {
|
||||
psram_root_ = psram_doc_.add<JsonArray>();
|
||||
} else {
|
||||
psram_root_ = psram_doc_.add<JsonObject>();
|
||||
}
|
||||
}
|
||||
|
||||
// Hides AsyncJsonResponse::getRoot(). Must be called through a
|
||||
// derived-type pointer/reference (the framework's base pointer keeps
|
||||
// pointing at the empty base _jsonBuffer, which is intentional).
|
||||
JsonVariant getRoot() {
|
||||
return psram_root_;
|
||||
}
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
size_t setLength() override {
|
||||
_contentLength = measureJson(psram_root_);
|
||||
if (_contentLength) {
|
||||
_isValid = true;
|
||||
}
|
||||
return _contentLength;
|
||||
}
|
||||
|
||||
size_t _fillBuffer(uint8_t * data, size_t len) override {
|
||||
ChunkPrint dest(data, _sentLength, len);
|
||||
serializeJson(psram_root_, dest);
|
||||
return dest.written();
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
JsonDocument psram_doc_;
|
||||
JsonVariant psram_root_;
|
||||
};
|
||||
|
||||
#if !defined(EMSESP_STANDALONE) && defined(ASYNC_MSG_PACK_SUPPORT) && ASYNC_MSG_PACK_SUPPORT == 1
|
||||
// MessagePack equivalent — same routing trick but serialises with MsgPack.
|
||||
class PsramAsyncMessagePackResponse : public ::AsyncMessagePackResponse {
|
||||
public:
|
||||
explicit PsramAsyncMessagePackResponse(bool isArray = false)
|
||||
: ::AsyncMessagePackResponse(isArray)
|
||||
, psram_doc_(PsramJsonAllocator::instance()) {
|
||||
if (isArray) {
|
||||
psram_root_ = psram_doc_.add<JsonArray>();
|
||||
} else {
|
||||
psram_root_ = psram_doc_.add<JsonObject>();
|
||||
}
|
||||
}
|
||||
|
||||
JsonVariant getRoot() {
|
||||
return psram_root_;
|
||||
}
|
||||
|
||||
size_t setLength() override {
|
||||
_contentLength = measureMsgPack(psram_root_);
|
||||
if (_contentLength) {
|
||||
_isValid = true;
|
||||
}
|
||||
return _contentLength;
|
||||
}
|
||||
|
||||
size_t _fillBuffer(uint8_t * data, size_t len) override {
|
||||
ChunkPrint dest(data, _sentLength, len);
|
||||
serializeMsgPack(psram_root_, dest);
|
||||
return dest.written();
|
||||
}
|
||||
|
||||
private:
|
||||
JsonDocument psram_doc_;
|
||||
JsonVariant psram_root_;
|
||||
};
|
||||
#else
|
||||
// Standalone or no msgpack support: alias to plain JSON response so the
|
||||
// codebase compiles unchanged.
|
||||
using PsramAsyncMessagePackResponse = PsramAsyncJsonResponse;
|
||||
#endif
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2025 emsesp.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef EMSESP_PSRAM_JSON_ALLOCATOR_H
|
||||
#define EMSESP_PSRAM_JSON_ALLOCATOR_H
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
#include <esp_heap_caps.h>
|
||||
#endif
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
// PSRAM-backed ArduinoJson allocator with internal-heap fallback.
|
||||
//
|
||||
// Rationale: by default ArduinoJson allocates with malloc(), which on the
|
||||
// ESP32 lands in internal DRAM. Large transient JsonDocuments (full MQTT
|
||||
// payload, HA discovery configs, Web API responses, settings load/save)
|
||||
// were eating multiple KB of the same internal heap that LwIP, mbedTLS and
|
||||
// AsyncTCP also need. Routing them through SPIRAM via heap_caps_malloc
|
||||
// keeps internal heap available for the network stack, at the cost of a
|
||||
// small latency penalty on PSRAM reads/writes (a few cycles per access,
|
||||
// negligible for JSON build-up which is dominated by string formatting).
|
||||
//
|
||||
// On the standalone (Linux) build, PSRAM doesn't exist; the allocator
|
||||
// silently falls through to plain malloc/free/realloc.
|
||||
//
|
||||
// Usage:
|
||||
// JsonDocument doc(emsesp::PsramJsonAllocator::instance());
|
||||
// or with the convenience macro:
|
||||
// JsonDocument doc(PSRAM_DOC);
|
||||
class PsramJsonAllocator : public ArduinoJson::Allocator {
|
||||
public:
|
||||
void * allocate(size_t size) override {
|
||||
#ifdef EMSESP_STANDALONE
|
||||
return malloc(size);
|
||||
#else
|
||||
// Try SPIRAM first; fall back to internal heap so we never fail
|
||||
// on boards without PSRAM or when PSRAM is full.
|
||||
void * p = heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
|
||||
if (p == nullptr) {
|
||||
p = malloc(size);
|
||||
}
|
||||
return p;
|
||||
#endif
|
||||
}
|
||||
|
||||
void deallocate(void * ptr) override {
|
||||
#ifdef EMSESP_STANDALONE
|
||||
free(ptr);
|
||||
#else
|
||||
// heap_caps_free handles both PSRAM- and internal-heap pointers.
|
||||
heap_caps_free(ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void * reallocate(void * ptr, size_t new_size) override {
|
||||
#ifdef EMSESP_STANDALONE
|
||||
return realloc(ptr, new_size);
|
||||
#else
|
||||
// Prefer keeping the block in PSRAM; heap_caps_realloc will move
|
||||
// the data if the original region can't be grown in-place.
|
||||
void * p = heap_caps_realloc(ptr, new_size, MALLOC_CAP_SPIRAM);
|
||||
if (p == nullptr) {
|
||||
p = realloc(ptr, new_size);
|
||||
}
|
||||
return p;
|
||||
#endif
|
||||
}
|
||||
|
||||
static ArduinoJson::Allocator * instance() {
|
||||
static PsramJsonAllocator inst;
|
||||
return &inst;
|
||||
}
|
||||
|
||||
private:
|
||||
PsramJsonAllocator() = default;
|
||||
~PsramJsonAllocator() = default;
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
// Convenience shorthand. Use only for *large* or *transient* JsonDocuments
|
||||
// (MQTT publish payloads, HA discovery, full API responses, big settings
|
||||
// load/save). For small hot-path docs (single-command output, parse of a
|
||||
// short HTTP body), keep the default allocator: PSRAM has higher access
|
||||
// latency than internal SRAM, so tiny docs are faster on the regular heap.
|
||||
#define PSRAM_DOC emsesp::PsramJsonAllocator::instance()
|
||||
|
||||
#endif
|
||||
+34
-7
@@ -87,6 +87,7 @@ PButton System::myPButton_;
|
||||
bool System::test_set_all_active_ = false;
|
||||
uint32_t System::max_alloc_mem_;
|
||||
uint32_t System::heap_mem_;
|
||||
uint32_t System::min_free_mem_;
|
||||
|
||||
// GPIOs
|
||||
std::vector<uint8_t, AllocatorPSRAM<uint8_t>> System::valid_system_gpios_;
|
||||
@@ -173,7 +174,7 @@ bool System::command_sendmail(const char * value, const int8_t id) {
|
||||
delete basic_client;
|
||||
return false;
|
||||
}
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
String body = value;
|
||||
if (body.length()) {
|
||||
auto error = deserializeJson(doc, (const char *)value);
|
||||
@@ -922,6 +923,11 @@ void System::heartbeat_json(JsonObject output) {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
output["freemem"] = getHeapMem();
|
||||
output["max_alloc"] = getMaxAllocMem();
|
||||
// All-time low watermark of free internal heap (KB). Unlike freemem
|
||||
// (sampled now), this captures the worst transient dip since boot —
|
||||
// the actual metric to watch when measuring the effect of transient
|
||||
// allocation optimisations (e.g. JsonDocument on PSRAM).
|
||||
output["min_free"] = getMinFreeMem();
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
|
||||
output["temperature"] = (int)temperature_;
|
||||
@@ -1076,13 +1082,33 @@ void System::show_system(uuid::console::Shell & shell) {
|
||||
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
|
||||
shell.printfln(" CPU temperature: %d °C", (int)temperature());
|
||||
#endif
|
||||
shell.printfln(" Free heap/Max alloc: %lu KB / %lu KB", getHeapMem(), getMaxAllocMem());
|
||||
// Free heap = current; Min free = all-time low watermark (lowest free
|
||||
// heap has ever been since boot). Min free is the actual metric that
|
||||
// reflects optimisations targeting transient peaks (publishes, /api/system,
|
||||
// TLS handshakes). If transient peaks are reduced, min_free goes up.
|
||||
shell.printfln(" Free heap/Max alloc/Min free: %lu KB / %lu KB / %lu KB", getHeapMem(), getMaxAllocMem(), getMinFreeMem());
|
||||
#ifndef EMSESP_STANDALONE
|
||||
// Largest contiguous free block of *internal* SRAM. Network stack
|
||||
// (LwIP/mbedTLS/AsyncTCP) and JSON output allocations need this to be
|
||||
// healthy — total free heap can look fine while this collapses due to
|
||||
// fragmentation. Compare before and after a big API call or MQTT publish.
|
||||
shell.printfln(" Internal heap free/largest block: %u KB / %u KB",
|
||||
heap_caps_get_free_size(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) / 1024,
|
||||
heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) / 1024);
|
||||
#endif
|
||||
shell.printfln(" App used/free: %lu KB / %lu KB", appUsed(), appFree());
|
||||
uint32_t FSused = LittleFS.usedBytes() / 1024;
|
||||
shell.printfln(" FS used/free: %lu KB / %lu KB", FSused, FStotal() - FSused);
|
||||
shell.printfln(" Flash size: %lu KB", ESP.getFlashChipSize() / 1024);
|
||||
if (PSram()) {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
shell.printfln(" PSRAM size/free/largest block: %lu KB / %lu KB / %u KB",
|
||||
PSram(),
|
||||
ESP.getFreePsram() / 1024,
|
||||
heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM) / 1024);
|
||||
#else
|
||||
shell.printfln(" PSRAM size/free: %lu KB / %lu KB", PSram(), ESP.getFreePsram() / 1024);
|
||||
#endif
|
||||
} else {
|
||||
shell.printfln(" PSRAM: not available");
|
||||
}
|
||||
@@ -1227,7 +1253,7 @@ bool System::check_restore() {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
File new_file = LittleFS.open(TEMP_FILENAME_PATH);
|
||||
if (new_file) {
|
||||
JsonDocument jsonDocument;
|
||||
JsonDocument jsonDocument(PSRAM_DOC);
|
||||
DeserializationError error = deserializeJson(jsonDocument, new_file);
|
||||
if (error == DeserializationError::Ok && jsonDocument.is<JsonObject>()) {
|
||||
JsonObject input = jsonDocument.as<JsonObject>();
|
||||
@@ -1591,7 +1617,7 @@ void System::exportSettings(const std::string & type, const char * filename, Jso
|
||||
File settingsFile = LittleFS.open(filename);
|
||||
if (settingsFile) {
|
||||
{
|
||||
JsonDocument jsonDocument;
|
||||
JsonDocument jsonDocument(PSRAM_DOC);
|
||||
DeserializationError error = deserializeJson(jsonDocument, settingsFile);
|
||||
settingsFile.close(); // close early, we no longer need the file
|
||||
if (error || !jsonDocument.is<JsonObject>()) {
|
||||
@@ -1650,7 +1676,7 @@ void System::exportSystemBackup(JsonObject output) {
|
||||
// special case for custom support
|
||||
File file = LittleFS.open(EMSESP_CUSTOMSUPPORT_FILE, "r");
|
||||
if (file) {
|
||||
JsonDocument jsonDocument;
|
||||
JsonDocument jsonDocument(PSRAM_DOC);
|
||||
DeserializationError error = deserializeJson(jsonDocument, file);
|
||||
file.close(); // close early, we no longer need the file
|
||||
if (!error && jsonDocument.is<JsonObject>()) {
|
||||
@@ -1859,7 +1885,7 @@ bool System::get_value_info(JsonObject output, const char * cmd) {
|
||||
}
|
||||
|
||||
// fetch all the data from the system in a different json
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
(void)command_info("", 0, root);
|
||||
|
||||
@@ -1954,7 +1980,7 @@ std::string System::get_metrics_prometheus() {
|
||||
result.reserve(16000);
|
||||
|
||||
// get system data
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
(void)command_info("", 0, root);
|
||||
|
||||
@@ -2233,6 +2259,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output
|
||||
node["sdk"] = ESP.getSdkVersion();
|
||||
node["freeMem"] = getHeapMem();
|
||||
node["maxAlloc"] = getMaxAllocMem();
|
||||
node["minFree"] = getMinFreeMem(); // all-time low watermark of internal heap
|
||||
node["freeCaps"] = heap_caps_get_free_size(MALLOC_CAP_8BIT) / 1024; // includes heap and psram
|
||||
node["usedApp"] = EMSESP::system_.appUsed(); // kilobytes
|
||||
node["freeApp"] = EMSESP::system_.appFree(); // kilobytes
|
||||
|
||||
@@ -299,10 +299,20 @@ class System {
|
||||
static uint32_t getHeapMem() {
|
||||
return heap_mem_;
|
||||
}
|
||||
// All-time low watermark of free internal heap (KB).
|
||||
// Unlike getHeapMem() (sampled now), this captures the *lowest* free heap
|
||||
// has ever been since boot — i.e. the worst transient dip during MQTT
|
||||
// publishes, HA discovery, /api/system calls, TLS handshakes, etc.
|
||||
// This is the number that actually reflects optimisations targeting
|
||||
// transient JSON / buffer peaks (e.g. Phase C PSRAM JsonDocuments).
|
||||
static uint32_t getMinFreeMem() {
|
||||
return min_free_mem_;
|
||||
}
|
||||
static void refreshHeapMem() {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
max_alloc_mem_ = ESP.getMaxAllocHeap() / 1024;
|
||||
heap_mem_ = ESP.getFreeHeap() / 1024;
|
||||
min_free_mem_ = ESP.getMinFreeHeap() / 1024;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -346,6 +356,7 @@ class System {
|
||||
static bool test_set_all_active_; // force all entities in a device to have a value
|
||||
static uint32_t max_alloc_mem_;
|
||||
static uint32_t heap_mem_;
|
||||
static uint32_t min_free_mem_;
|
||||
|
||||
uint8_t systemStatus_; // uses SYSTEM_STATUS enum
|
||||
|
||||
|
||||
@@ -572,11 +572,11 @@ bool TxService::send_raw(const char * telegram_data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// since the telegram data is a const, make a copy. add 1 to grab the \0 EOS
|
||||
// since the telegram data is a const, make a copy
|
||||
char * telegram = strdup(telegram_data);
|
||||
|
||||
uint8_t count = 0;
|
||||
uint8_t data[256];
|
||||
uint8_t data[256]; // max raw telegram length
|
||||
|
||||
// get values
|
||||
char * p = strtok(telegram, " ,"); // delimiter
|
||||
|
||||
@@ -494,7 +494,7 @@ void TemperatureSensor::publish_values(const bool force) {
|
||||
}
|
||||
}
|
||||
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
bool ha_dev_created = false;
|
||||
|
||||
for (auto & sensor : sensors_) {
|
||||
@@ -519,7 +519,7 @@ void TemperatureSensor::publish_values(const bool force) {
|
||||
} else if (!sensor.ha_registered || force) {
|
||||
LOG_DEBUG("Recreating HA config for sensor ID %s", sensor.id());
|
||||
|
||||
JsonDocument config;
|
||||
JsonDocument config(PSRAM_DOC);
|
||||
config["~"] = Mqtt::base();
|
||||
config["dev_cla"] = "temperature";
|
||||
config["stat_cla"] = "measurement";
|
||||
|
||||
@@ -99,7 +99,7 @@ class TemperatureSensor {
|
||||
std::string get_metrics_prometheus();
|
||||
|
||||
// return back reference to the sensor list, used by other classes
|
||||
std::vector<Sensor, AllocatorPSRAM<Sensor>> sensors() const {
|
||||
const std::vector<Sensor, AllocatorPSRAM<Sensor>> & sensors() const {
|
||||
return sensors_;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ Alert::Alert(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &setBurnPow_, DeviceValueType::UINT8, FL_(setBurnPow), DeviceValueUOM::PERCENT);
|
||||
}
|
||||
// UBASetPoint 0x1A
|
||||
void Alert::process_UBASetPoints(std::shared_ptr<const Telegram> telegram) {
|
||||
void Alert::process_UBASetPoints(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, setFlowTemp_, 0); // boiler set temp from thermostat
|
||||
has_update(telegram, setBurnPow_, 1); // max burner power in %
|
||||
}
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ class Alert : public EMSdevice {
|
||||
Alert(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
|
||||
|
||||
private:
|
||||
void process_UBASetPoints(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBASetPoints(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
uint8_t setFlowTemp_; // boiler setpoint temp
|
||||
uint8_t setBurnPow_; // Burner power %
|
||||
|
||||
+61
-55
@@ -28,6 +28,12 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
// register values for master boiler/cascade module
|
||||
|
||||
// pre-size containers; max in-code counts are ~56 telegrams / ~272 values
|
||||
// but real per-instance counts after flag-discriminated branches are
|
||||
// ~30-40 telegrams / ~120-180 values. Reserve generously to avoid realloc.
|
||||
reserve_telegram_functions(48);
|
||||
reserve_device_values(180);
|
||||
|
||||
// the telegram handlers...
|
||||
// common for all boilers
|
||||
register_telegram_type(0xBF, "ErrorMessage", false, MAKE_PF_CB(process_ErrorMessage));
|
||||
@@ -1294,7 +1300,7 @@ void Boiler::check_active() {
|
||||
// 0x04
|
||||
// boiler(0x08) -W-> Me(0x0B), ?(0x04), data: 13 96 09 81 00 64 64 35 05 64 5A 22 00 00 00 00 00 00 00 00 B7
|
||||
// offset 4 - nominal Power kW, could be zero, 5 - min. Burner, 6 - max. Burner
|
||||
void Boiler::process_UBAFactory(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAFactory(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// check for all wanted info in telegram
|
||||
if (telegram->offset > 4 || telegram->offset + telegram->message_length < 7) {
|
||||
return;
|
||||
@@ -1319,7 +1325,7 @@ void Boiler::process_UBAFactory(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// 0x18
|
||||
void Boiler::process_UBAMonitorFast(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAMonitorFast(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, selFlowTemp_, 0);
|
||||
has_update(telegram, curFlowTemp_, 1);
|
||||
// has_update(telegram, selBurnPow_, 3); // burn power max setting
|
||||
@@ -1381,7 +1387,7 @@ void Boiler::process_UBAMonitorFast(std::shared_ptr<const Telegram> telegram) {
|
||||
* UBATotalUptime - type 0x14 - total uptime
|
||||
* received only after requested (not broadcasted)
|
||||
*/
|
||||
void Boiler::process_UBATotalUptime(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBATotalUptime(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, UBAuptime_, 0, 3); // force to 3 bytes
|
||||
// if broadcasted there is no need to fetch
|
||||
if (telegram->dest == 0) {
|
||||
@@ -1393,7 +1399,7 @@ void Boiler::process_UBATotalUptime(std::shared_ptr<const Telegram> telegram) {
|
||||
* UBAParameters - type 0x16
|
||||
* data: FF 5A 64 00 0A FA 0F 02 06 64 64 02 08 F8 0F 0F 0F 0F 1E 05 04 09 09 00 28 00 3C
|
||||
*/
|
||||
void Boiler::process_UBAParameters(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAParameters(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, heatingActivated_, 0);
|
||||
has_update(telegram, heatingTemp_, 1);
|
||||
has_update(telegram, burnMaxPower_, 2);
|
||||
@@ -1415,13 +1421,13 @@ void Boiler::process_UBAParameters(std::shared_ptr<const Telegram> telegram) {
|
||||
* UBASettingsWW - type 0x26 - max power on offset 7, https://github.com/emsesp/EMS-ESP/issues/740
|
||||
* Boiler(0x08) -> Me(0x0B), ?(0x26), data: 01 05 00 0F 00 1E 58 5A
|
||||
*/
|
||||
void Boiler::process_UBASettingsWW(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBASettingsWW(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwMaxPower_, 10);
|
||||
}
|
||||
|
||||
// 0x33
|
||||
// Boiler(0x08) -> Me(0x0B), UBAParameterWW(0x33), data: 08 FF 30 FB FF 28 FF 07 46 00 00
|
||||
void Boiler::process_UBAParameterWW(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAParameterWW(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// has_bitupdate(telegram, wwEquipt_,0,3); // 8=boiler has ww
|
||||
has_update(telegram, wwActivated_, 1); // 0xFF means on
|
||||
has_update(telegram, wwSelTemp_, 2);
|
||||
@@ -1453,7 +1459,7 @@ void Boiler::process_UBAParameterWW(std::shared_ptr<const Telegram> telegram) {
|
||||
* received every 10 seconds
|
||||
* Boiler(0x08) -> Me(0x0B), UBAMonitorWW(0x34), data: 30 01 BA 7D 00 21 00 00 03 00 01 22 2B 00 19 5B
|
||||
*/
|
||||
void Boiler::process_UBAMonitorWW(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAMonitorWW(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwSetTemp_, 0);
|
||||
has_update(telegram, wwCurTemp_, 1);
|
||||
has_update(telegram, wwCurTemp2_, 3);
|
||||
@@ -1480,7 +1486,7 @@ void Boiler::process_UBAMonitorWW(std::shared_ptr<const Telegram> telegram) {
|
||||
+ * GB125/Logamatic MC110: issue #650: add retTemp & sysPress
|
||||
+ * 08 00 E4 00 10 20 2D 48 00 C8 38 02 37 3C 27 03 00 00 00 00 00 01 7B 01 8F 11 00 02 37 80 00 02 1B 80 00 7F FF 80 00
|
||||
*/
|
||||
void Boiler::process_UBAMonitorFastPlus(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAMonitorFastPlus(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, selFlowTemp_, 6);
|
||||
has_bitupdate(telegram, burnGas_, 11, 0);
|
||||
//has_bitupdate(telegram, heatingPump_, 11, 1); // heating active? see SlowPlus
|
||||
@@ -1546,7 +1552,7 @@ void Boiler::process_UBAMonitorFastPlus(std::shared_ptr<const Telegram> telegram
|
||||
* 08 0B 19 00 FF EA 02 47 80 00 00 00 00 62 03 CA 24 2C D6 23 00 00 00 27 4A B6 03 6E 43
|
||||
* 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 17 19 20 21 22 23 24
|
||||
*/
|
||||
void Boiler::process_UBAMonitorSlow(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAMonitorSlow(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, outdoorTemp_, 0);
|
||||
has_update(telegram, boilTemp_, 2);
|
||||
has_update(telegram, exhaustTemp_, 4);
|
||||
@@ -1565,7 +1571,7 @@ void Boiler::process_UBAMonitorSlow(std::shared_ptr<const Telegram> telegram) {
|
||||
* https://github.com/Th3M3/buderus_ems-wiki/blob/master/Quelle_08.md
|
||||
* https://github.com/emsesp/EMS-ESP32/issues/908
|
||||
*/
|
||||
void Boiler::process_UBAMonitorSlowPlus2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAMonitorSlowPlus2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, absBurnPow_, 13); // current burner absolute power (percent of rating plate power)
|
||||
if (model() == EMSdevice::EMS_DEVICE_FLAG_HIU) {
|
||||
uint8_t state = EMS_VALUE_UINT8_NOTSET;
|
||||
@@ -1586,7 +1592,7 @@ void Boiler::process_UBAMonitorSlowPlus2(std::shared_ptr<const Telegram> telegra
|
||||
* Boiler(0x08) -> Me(0x0B), UBAMonitorSlowPlus(0xE5),
|
||||
* data: 01 00 20 00 00 78 00 00 00 00 00 1E EB 00 9D 3E 00 00 00 00 6B 5E 00 06 4C 64 00 00 00 00 8A A3
|
||||
*/
|
||||
void Boiler::process_UBAMonitorSlowPlus(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAMonitorSlowPlus(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_bitupdate(telegram, fanWork_, 2, 2);
|
||||
has_bitupdate(telegram, ignWork_, 2, 3);
|
||||
has_bitupdate(telegram, heatingPump_, 2, 5);
|
||||
@@ -1612,7 +1618,7 @@ void Boiler::process_UBAMonitorSlowPlus(std::shared_ptr<const Telegram> telegram
|
||||
* from: issue #732
|
||||
* data: 01 50 1E 5A 46 12 64 00 06 FA 3C 03 05 64 00 00 00 28 00 41 03 00 00 00 00 00 00 00 00 00
|
||||
*/
|
||||
void Boiler::process_UBAParametersPlus(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAParametersPlus(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, heatingActivated_, 0);
|
||||
has_update(telegram, heatingTemp_, 1);
|
||||
has_update(telegram, burnMaxPower_, 4);
|
||||
@@ -1632,7 +1638,7 @@ void Boiler::process_UBAParametersPlus(std::shared_ptr<const Telegram> telegram)
|
||||
|
||||
// 0xEA
|
||||
// Boiler(0x08) -> (0x0B), (0xEA), data: 00 00 00 00 00 00 3C FB 00 28 00 02 46 00 00 00 3C 3C 28
|
||||
void Boiler::process_UBAParameterWWPlus(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAParameterWWPlus(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwSelTempOff_, 0); // confusing description in #96
|
||||
has_update(telegram, wwActivated_, 5); // 0x01 means on
|
||||
has_update(telegram, wwSelTemp_, 6); // setting here
|
||||
@@ -1667,7 +1673,7 @@ void Boiler::process_UBAParameterWWPlus(std::shared_ptr<const Telegram> telegram
|
||||
|
||||
// 0xE9 - WW monitor ems+
|
||||
// e.g. 08 00 E9 00 37 01 F6 01 ED 00 00 00 00 41 3C 00 00 00 00 00 00 00 00 00 00 00 00 37 00 00 00 (CRC=77) #data=27
|
||||
void Boiler::process_UBAMonitorWWPlus(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAMonitorWWPlus(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwSetTemp_, 0);
|
||||
has_update(telegram, wwCurTemp_, 1);
|
||||
has_update(telegram, wwCurTemp2_, 3);
|
||||
@@ -1699,7 +1705,7 @@ void Boiler::process_UBAMonitorWWPlus(std::shared_ptr<const Telegram> telegram)
|
||||
* 08 00 FF 48 03 95 00 00 01 15 00 00 00 00 00 00 00 F9 29 00
|
||||
*
|
||||
*/
|
||||
void Boiler::process_UBAInformation(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAInformation(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, upTimeControl_, 0);
|
||||
has_update(telegram, upTimeCompHeating_, 8);
|
||||
has_update(telegram, upTimeCompCooling_, 16);
|
||||
@@ -1733,7 +1739,7 @@ void Boiler::process_UBAInformation(std::shared_ptr<const Telegram> telegram) {
|
||||
* 08 00 FF 18 03 94 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 7E
|
||||
* 08 00 FF 31 03 94 00 00 00 00 00 00 00 38
|
||||
*/
|
||||
void Boiler::process_UBAEnergySupplied(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAEnergySupplied(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, upTimeTotal_, 0);
|
||||
has_update(telegram, nrgSuppTotal_, 4);
|
||||
has_update(telegram, nrgSuppHeating_, 12);
|
||||
@@ -1746,7 +1752,7 @@ void Boiler::process_UBAEnergySupplied(std::shared_ptr<const Telegram> telegram)
|
||||
//08 00 FF 00 03 8D 03 00 10 30 10 60 00 04 00 00 00 17 00 00 00 3C 38 0E 64 00 00 0C 33 C7 00
|
||||
//XR1A050001 A05 Pump Heat circuit (1.0 ) 1 >> 1 & 0x01 ?
|
||||
//XR1A040001 A04 Pump Cold circuit (1.0 ) 1 & 0x1 ?
|
||||
void Boiler::process_HpPower(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpPower(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_bitupdate(telegram, VC0valve_, 0, 7);
|
||||
has_bitupdate(telegram, hp3wayValve_, 0, 6);
|
||||
// has_bitupdate(telegram, heating_, 0, 0); // heating on? https://github.com/emsesp/EMS-ESP32/discussions/1898
|
||||
@@ -1787,7 +1793,7 @@ void Boiler::process_HpPower(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// Heatpump temperatures - type 0x48F
|
||||
void Boiler::process_HpTemperatures(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpTemperatures(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, hpTc0_, 6);
|
||||
has_update(telegram, hpTc1_, 4);
|
||||
has_update(telegram, hpTc3_, 2);
|
||||
@@ -1808,7 +1814,7 @@ void Boiler::process_HpTemperatures(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// Heatpump pool unit - type 0x48A
|
||||
// 08 00 FF 00 03 8A 01 4C 01 0C 00 00 0A 00 1E 00 00 01 00 04 4A 00
|
||||
void Boiler::process_HpPool(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpPool(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, poolSetTemp_, 1);
|
||||
}
|
||||
|
||||
@@ -1816,14 +1822,14 @@ void Boiler::process_HpPool(std::shared_ptr<const Telegram> telegram) {
|
||||
// Boiler(0x08) -> All(0x00), ?(0x04A2), data: 02 01 01 00 01 00
|
||||
// Boiler(0x08) -W-> Me(0x0B), HpInput(0x04A2), data: 20 07 06 01 00 (from #802)
|
||||
// see https://github.com/emsesp/EMS-ESP32/issues/2844#issuecomment-3689049155
|
||||
void Boiler::process_HpInput(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpInput(const std::shared_ptr<const Telegram> & telegram) {
|
||||
}
|
||||
|
||||
// Heatpump inputs settings- type 0x486 (https://github.com/emsesp/EMS-ESP32/issues/600)
|
||||
// Boiler(0x08) -> All(0x00), ?(0x0486), data: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
// Boiler(0x08) -> All(0x00), ?(0x0486), data: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 01 00 00 00 00 00 (offset 25)
|
||||
// Boiler(0x08) -> All(0x00), ?(0x0486), data: 00 00 (offset 51)
|
||||
void Boiler::process_HpInConfig(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpInConfig(const std::shared_ptr<const Telegram> & telegram) {
|
||||
char option[16];
|
||||
// inputs 1,2,3 <inv>[<evu1><evu2><evu3><comp><aux><cool><heat><dhw><pv><prot><pres><mod>]
|
||||
uint8_t index[] = {0, 3, 6, 9, 12, 15, 18, 21, 24, 39, 36, 30, 27};
|
||||
@@ -1852,14 +1858,14 @@ void Boiler::process_HpInConfig(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// Boiler(0x08) -W-> Me(0x0B), HpHeaterConfig(0x0485)
|
||||
void Boiler::process_HpCooling(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpCooling(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// coolingtype to set 4wayvalve (0x48D), type not published yet, https://github.com/emsesp/EMS-ESP32/issues/2844#issuecomment-3869770845
|
||||
has_update(telegram, coolingType_, 0); // none = 0, passive cooling box = 1, active cooling box = 2, 4-way valve = 3, active and passive cooling box = 4.
|
||||
has_update(telegram, pvCooling_, 21);
|
||||
}
|
||||
|
||||
// Boiler(0x08) -W-> Me(0x0B), HpHeaterConfig(0x0492), data: 03 00 00 04 00
|
||||
void Boiler::process_HpHeaterConfig(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpHeaterConfig(const std::shared_ptr<const Telegram> & telegram) {
|
||||
if (model() == EMSdevice::EMS_DEVICE_FLAG_CS6800) {
|
||||
has_enumupdate(telegram, maxHeatComp_, 2, {0, 2, 4, 5});
|
||||
has_enumupdate(telegram, maxHeatHeat_, 3, {2, 4, 5});
|
||||
@@ -1874,7 +1880,7 @@ void Boiler::process_HpHeaterConfig(std::shared_ptr<const Telegram> telegram) {
|
||||
// 0x2A - MC110Status
|
||||
// e.g. 88 00 2A 00 00 00 00 00 00 00 00 00 D2 00 00 80 00 00 01 08 80 00 02 47 00
|
||||
// see https://github.com/emsesp/EMS-ESP/issues/397
|
||||
void Boiler::process_MC110Status(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_MC110Status(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwMixerTemp_, 14);
|
||||
has_update(telegram, wwCylMiddleTemp_, 18);
|
||||
}
|
||||
@@ -1882,12 +1888,12 @@ void Boiler::process_MC110Status(std::shared_ptr<const Telegram> telegram) {
|
||||
/*
|
||||
* UBAOutdoorTemp - type 0xD1 - external temperature EMS+
|
||||
*/
|
||||
void Boiler::process_UBAOutdoorTemp(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAOutdoorTemp(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, outdoorTemp_, 0);
|
||||
}
|
||||
|
||||
// UBASetPoint 0x1A
|
||||
void Boiler::process_UBASetPoints(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBASetPoints(const std::shared_ptr<const Telegram> & telegram) {
|
||||
uint8_t setFlowTemp_ = 0;
|
||||
uint8_t setBurnPow_ = 0;
|
||||
uint8_t setPumpMod_ = 0;
|
||||
@@ -1903,7 +1909,7 @@ void Boiler::process_UBASetPoints(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// UBASetPoints ems+ 0x2E0
|
||||
void Boiler::process_UBASetPoints2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBASetPoints2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
uint8_t setFlowTemp_ = 0;
|
||||
uint8_t setBurnPow_ = 0;
|
||||
telegram->read_value(setFlowTemp_, 0);
|
||||
@@ -1917,13 +1923,13 @@ void Boiler::process_UBASetPoints2(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// 0x35 - not yet implemented, not readable, only for settings
|
||||
void Boiler::process_UBAFlags(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAFlags(const std::shared_ptr<const Telegram> & telegram) {
|
||||
}
|
||||
|
||||
// 0x1C
|
||||
// 08 00 1C 94 0B 0A 1D 31 08 00 80 00 00 00 -> message for 29.11.2020
|
||||
// 08 00 1C 94 0B 0A 1D 31 00 00 00 00 00 00 -> message reset
|
||||
void Boiler::process_UBAMaintenanceStatus(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAMaintenanceStatus(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// 5. byte: Maintenance due (0 = no, 3 = yes, due to operating hours, 8 = yes, due to date)
|
||||
uint8_t message_code = maintenanceMessage_[2] - '0';
|
||||
telegram->read_value(message_code, 5);
|
||||
@@ -1936,13 +1942,13 @@ void Boiler::process_UBAMaintenanceStatus(std::shared_ptr<const Telegram> telegr
|
||||
}
|
||||
|
||||
// 0xBF
|
||||
void Boiler::process_ErrorMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_ErrorMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
EMSESP::send_read_request(0xC2, device_id(), 0, 20); // read last errorcode
|
||||
EMSESP::send_read_request(0xC6, device_id(), 0, 21); // read last errorcode
|
||||
}
|
||||
|
||||
// 0x10, 0x11
|
||||
void Boiler::process_UBAErrorMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAErrorMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
if (telegram->offset > 0 || telegram->message_length < 11) {
|
||||
return;
|
||||
}
|
||||
@@ -1978,7 +1984,7 @@ void Boiler::process_UBAErrorMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// 0xC2, without clock in system it stores 3 bytes uptime in 11 and 16, with clock date in 10-14, and 15-19
|
||||
// date is marked with 0x80 to year-field
|
||||
void Boiler::process_UBAErrorMessage2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAErrorMessage2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
if (telegram->offset > 0 || telegram->message_length < 20) {
|
||||
return;
|
||||
}
|
||||
@@ -2044,7 +2050,7 @@ void Boiler::process_UBAErrorMessage2(std::shared_ptr<const Telegram> telegram)
|
||||
|
||||
// C6, C7 https://github.com/emsesp/EMS-ESP32/issues/938#issuecomment-1425813815
|
||||
// as C2, but offset shifted one byte
|
||||
void Boiler::process_UBAErrorMessage3(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAErrorMessage3(const std::shared_ptr<const Telegram> & telegram) {
|
||||
if (telegram->offset > 0 || telegram->message_length < 21) {
|
||||
return;
|
||||
}
|
||||
@@ -2109,7 +2115,7 @@ void Boiler::process_UBAErrorMessage3(std::shared_ptr<const Telegram> telegram)
|
||||
}
|
||||
|
||||
// 0x15 maintenance data
|
||||
void Boiler::process_UBAMaintenanceData(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_UBAMaintenanceData(const std::shared_ptr<const Telegram> & telegram) {
|
||||
if (telegram->offset > 0 || telegram->message_length < 5) {
|
||||
return;
|
||||
}
|
||||
@@ -2139,7 +2145,7 @@ void Boiler::process_UBAMaintenanceData(std::shared_ptr<const Telegram> telegram
|
||||
|
||||
// Boiler(0x08) -> All(0x00), ?(0x0484), data: 00 00 14 28 0D 50 00 00 00 02 02 07 28 01 00 02 05 19 0A 0A 03 0D 07 00 0A
|
||||
// Boiler(0x08) -> All(0x00), ?(0x0484), data: 01 90 00 F6 28 14 64 00 00 E1 00 1E 00 1E 01 64 01 64 54 20 00 00 (offset 25)
|
||||
void Boiler::process_HpSilentMode(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpSilentMode(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwAltOpPrioHeat_, 2); // range 20-120 minutes on Buderus WSW196i
|
||||
has_update(telegram, wwAltOpPrioWw_, 3); // range 30-120 minutes on Buderus WSW196i
|
||||
has_update(telegram, silentMode_, 10); // enum off-auto-on
|
||||
@@ -2157,7 +2163,7 @@ void Boiler::process_HpSilentMode(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// Boiler(0x08) -B-> All(0x00), ?(0x0488), data: 8E 00 00 00 00 00 01 03
|
||||
void Boiler::process_HpValve(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpValve(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// has_bitupdate(telegram, auxHeaterStatus_, 0, 2);
|
||||
has_update(telegram, auxHeatMixValve_, 7);
|
||||
has_update(telegram, pc1Rate_, 13); // percent
|
||||
@@ -2165,20 +2171,20 @@ void Boiler::process_HpValve(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// Boiler(0x08) -B-> All(0x00), ?(0x048B), data: 00 00 0A 1E 4E 00 1E 01 2C 00 01 64 55 05 12 50 50 50 00 00 1E 01 2C 00
|
||||
// Boiler(0x08) -B-> All(0x00), ?(0x048B), data: 00 1E 00 96 00 1E (offset 24)
|
||||
void Boiler::process_HpPumps(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpPumps(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, tempDiffHeat_, 4); // is * 10
|
||||
has_update(telegram, tempDiffCool_, 3); // is * 10
|
||||
has_update(telegram, hpPumpMode_, 18);
|
||||
}
|
||||
|
||||
// 0x02D6, https://github.com/emsesp/EMS-ESP32/issues/2001
|
||||
void Boiler::process_HpPump2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpPump2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, pc1On_, 0);
|
||||
has_update(telegram, pc1Flow_, 9);
|
||||
}
|
||||
|
||||
// Boiler(0x08) -> All(0x00), ?(0x0491), data: 03 01 00 00 00 02 64 00 00 14 01 2C 00 0A 00 1E 00 1E 00 00 1E 0A 1E 05 05
|
||||
void Boiler::process_HpAdditionalHeater(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpAdditionalHeater(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, auxHeaterSource_, 0); // https://github.com/emsesp/EMS-ESP32/discussions/2489
|
||||
has_update(telegram, auxHeaterOnly_, model() == EMSdevice::EMS_DEVICE_FLAG_CS6800 ? 3 : 1);
|
||||
has_update(telegram, auxHeaterOff_, 2);
|
||||
@@ -2191,7 +2197,7 @@ void Boiler::process_HpAdditionalHeater(std::shared_ptr<const Telegram> telegram
|
||||
|
||||
// DHW 0x499
|
||||
// Boiler(0x08) -B-> All(0x00), ?(0x0499), data: 31 33 3F 3B 01
|
||||
void Boiler::process_HpDhwSettings(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpDhwSettings(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwComfOffTemp_, 1);
|
||||
has_update(telegram, wwEcoOffTemp_, 0);
|
||||
has_update(telegram, wwEcoPlusOffTemp_, 5);
|
||||
@@ -2207,13 +2213,13 @@ void Boiler::process_HpDhwSettings(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// 0x49C:
|
||||
// Boiler(0x08) -B-> All(0x00), ?(0x049C), data: 00 00 00 00
|
||||
void Boiler::process_HpSettings2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpSettings2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, vp_cooling_, 3);
|
||||
}
|
||||
|
||||
// 0x49D
|
||||
// Boiler(0x08) -B-> All(0x00), ?(0x049D), data: 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
void Boiler::process_HpSettings3(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpSettings3(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, heatCable_, 2);
|
||||
// has_update(telegram, VC0valve_, 3); // read in 48D
|
||||
has_update(telegram, primePump_, 4);
|
||||
@@ -2226,7 +2232,7 @@ void Boiler::process_HpSettings3(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// boiler(0x08) -W-> Me(0x0B), ?(0x04AE), data: 00 00 BD C4 00 00 5B 6A 00 00 00 24 00 00 62 59 00 00 00 00 00 00 00 00
|
||||
// boiler(0x08) -W-> Me(0x0B), ?(0x04AE), data: 00 00 00 00 00 00 00 00 (offset 24)
|
||||
void Boiler::process_HpEnergy(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpEnergy(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, nrgTotal_, 0);
|
||||
has_update(telegram, nrgHeat_, 4);
|
||||
has_update(telegram, nrgWw_, 12);
|
||||
@@ -2236,7 +2242,7 @@ void Boiler::process_HpEnergy(std::shared_ptr<const Telegram> telegram) {
|
||||
// boiler(0x08) -W-> Me(0x0B), ?(0x04AF), data: 00 00 48 B2 00 00 48 55 00 00 00 5D 00 00 01 78 00 00 00 00 00 00 07 61
|
||||
// boiler(0x08) -W-> Me(0x0B), ?(0x04AF), data: 00 00 24 B0 00 00 00 12 00 00 23 A5 00 00 00 4B 00 00 00 00 00 00 00 00 (offset 24)
|
||||
// boiler(0x08) -W-> Me(0x0B), ?(0x04AF), data: 00 00 00 00 00 00 00 00 (offset 48)
|
||||
void Boiler::process_HpMeters(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpMeters(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, meterTotal_, 0);
|
||||
has_update(telegram, meterComp_, 4);
|
||||
has_update(telegram, meterEHeat_, 8);
|
||||
@@ -2245,35 +2251,35 @@ void Boiler::process_HpMeters(std::shared_ptr<const Telegram> telegram) {
|
||||
has_update(telegram, meterCool_, 40);
|
||||
}
|
||||
|
||||
void Boiler::process_HpPressure(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpPressure(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwPrio_, 3);
|
||||
has_update(telegram, hpSetDiffPress_, 9);
|
||||
}
|
||||
|
||||
// boiler(0x08) -W-> Me(0x0B), ?(0x04A5), data: 00 00 3C 1D 09 0A 0A 01 00 28 0A 00 01 00 00
|
||||
void Boiler::process_HpFan(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpFan(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, fan_, 9);
|
||||
}
|
||||
|
||||
// 0x4AA
|
||||
void Boiler::process_HpPower2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpPower2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, hpCurrPower_, 0);
|
||||
}
|
||||
|
||||
// 0x4A7
|
||||
void Boiler::process_HpPowerLimit(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HpPowerLimit(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, hpPowerLimit_, 0);
|
||||
}
|
||||
|
||||
// 0x0EB
|
||||
void Boiler::process_PumpKick(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_PumpKick(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, pumpKickHour_, 0);
|
||||
has_enumupdate(telegram, pumpKickDay_, 1, 1); // 1-mo, ...
|
||||
has_update(telegram, pumpKickDelay_, 2);
|
||||
}
|
||||
|
||||
// Boiler(0x08) -B-> All(0x00), ?(0x2E), data: 00 00 1C CE 00 00 05 E8 00 00 00 18 00 00 00 02
|
||||
void Boiler::process_Meters(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_Meters(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, gasMeterHeat_, 0);
|
||||
has_update(telegram, gasMeterWw_, 4);
|
||||
has_update(telegram, meterHeat_, 8);
|
||||
@@ -2281,7 +2287,7 @@ void Boiler::process_Meters(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// boiler(0x08) -B-> All(0x00), ?(0x3B), data: 00 00 1B D1 00 00 05 7F
|
||||
void Boiler::process_Energy(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_Energy(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, nrgHeat2_, 0);
|
||||
has_update(telegram, nrgWw2_, 4);
|
||||
}
|
||||
@@ -2289,7 +2295,7 @@ void Boiler::process_Energy(std::shared_ptr<const Telegram> telegram) {
|
||||
// HIU unit
|
||||
|
||||
// boiler(0x08) -B-> All(0x00), ?(0x0779), data: 06 05 01 01 AD 02 EF FF FF 00 00 7F FF
|
||||
void Boiler::process_HIUMonitor(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HIUMonitor(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, retTemp_, 3); // is * 10
|
||||
has_update(telegram, netFlowTemp_, 5); // is * 10
|
||||
has_update(telegram, heatValve_, 7); // is %
|
||||
@@ -2298,14 +2304,14 @@ void Boiler::process_HIUMonitor(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// Boiler(0x08) -W-> ME(0x0x), ?(0x0772), data: 00 00 00 00 00
|
||||
void Boiler::process_HIUSettings(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HIUSettings(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, keepWarmTemp_, 1);
|
||||
has_update(telegram, setReturnTemp_, 2);
|
||||
}
|
||||
|
||||
// Weather compensation, #1642
|
||||
// boiler(0x08) -W-> Me(0x0B), ?(0x28), data: 00 3C 32 10 00 05
|
||||
void Boiler::process_WeatherComp(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_WeatherComp(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, curveOn_, 0);
|
||||
has_update(telegram, curveEnd_, 1);
|
||||
has_update(telegram, curveBase_, 2);
|
||||
@@ -2340,7 +2346,7 @@ bool Boiler::set_returnTemp(const char * value, const int8_t id) {
|
||||
*
|
||||
// 0xBB Heatpump optimization
|
||||
// Boiler(0x08) -> Me(0x0B), ?(0xBB), data: 00 00 00 00 00 00 00 00 00 00 00 FF 02 0F 1E 0B 1A 00 14 03
|
||||
void Boiler::process_HybridHp(std::shared_ptr<const Telegram> telegram) {
|
||||
void Boiler::process_HybridHp(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_enumupdate(telegram, hybridStrategy_, 12, 1); // cost = 2, temperature = 3, mix = 4
|
||||
has_update(telegram, switchOverTemp_, 13); // full degrees
|
||||
has_update(telegram, energyCostRatio_, 14); // is *10
|
||||
|
||||
+56
-56
@@ -349,65 +349,65 @@ class Boiler : public EMSdevice {
|
||||
uint8_t delayBoiler_; // minutes
|
||||
uint8_t tempDiffBoiler_; // relative temperature degrees
|
||||
*/
|
||||
void process_UBAFactory(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAParameterWW(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAMonitorFast(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBATotalUptime(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAParameters(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAMonitorWW(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAMonitorFastPlus(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAMonitorSlow(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAMonitorSlowPlus(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAMonitorSlowPlus2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAParametersPlus(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAParameterWWPlus(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAOutdoorTemp(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBASetPoints(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBASetPoints2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAFlags(std::shared_ptr<const Telegram> telegram);
|
||||
void process_MC110Status(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAMaintenanceStatus(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAMaintenanceData(std::shared_ptr<const Telegram> telegram);
|
||||
void process_ErrorMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAErrorMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAErrorMessage2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAErrorMessage3(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAMonitorWWPlus(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAInformation(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAEnergySupplied(std::shared_ptr<const Telegram> telegram);
|
||||
void process_CascadeMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBASettingsWW(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpPower(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpTemperatures(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpPool(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpInput(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpInConfig(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpPressure(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpCooling(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpHeaterConfig(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HybridHp(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpSilentMode(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpAdditionalHeater(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpValve(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpPumps(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpPump2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpDhwSettings(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpSettings2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpSettings3(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpEnergy(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpMeters(std::shared_ptr<const Telegram> telegram);
|
||||
void process_WeatherComp(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpFan(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpPower2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpPowerLimit(std::shared_ptr<const Telegram> telegram);
|
||||
void process_PumpKick(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAFactory(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAParameterWW(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAMonitorFast(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBATotalUptime(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAParameters(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAMonitorWW(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAMonitorFastPlus(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAMonitorSlow(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAMonitorSlowPlus(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAMonitorSlowPlus2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAParametersPlus(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAParameterWWPlus(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAOutdoorTemp(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBASetPoints(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBASetPoints2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAFlags(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_MC110Status(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAMaintenanceStatus(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAMaintenanceData(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_ErrorMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAErrorMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAErrorMessage2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAErrorMessage3(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAMonitorWWPlus(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAInformation(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAEnergySupplied(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_CascadeMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBASettingsWW(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpPower(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpTemperatures(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpPool(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpInput(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpInConfig(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpPressure(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpCooling(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpHeaterConfig(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HybridHp(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpSilentMode(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpAdditionalHeater(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpValve(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpPumps(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpPump2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpDhwSettings(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpSettings2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpSettings3(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpEnergy(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpMeters(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_WeatherComp(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpFan(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpPower2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpPowerLimit(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_PumpKick(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
void process_Meters(std::shared_ptr<const Telegram> telegram);
|
||||
void process_Energy(std::shared_ptr<const Telegram> telegram);
|
||||
void process_Meters(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_Energy(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
// HIU
|
||||
void process_HIUSettings(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HIUMonitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HIUSettings(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HIUMonitor(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
bool set_keepWarmTemp(const char * value, const int8_t id);
|
||||
bool set_returnTemp(const char * value, const int8_t id);
|
||||
|
||||
@@ -59,13 +59,13 @@ Connect::Connect(uint8_t device_type, uint8_t device_id, uint8_t product_id, con
|
||||
/*
|
||||
* OutdoorTemp - type 0xD1 - external temperature
|
||||
*/
|
||||
void Connect::process_OutdoorTemp(std::shared_ptr<const Telegram> telegram) {
|
||||
void Connect::process_OutdoorTemp(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, outdoorTemp_, 0);
|
||||
}
|
||||
|
||||
// sent if thermostat is connected
|
||||
// https://github.com/emsesp/EMS-ESP32/issues/2277
|
||||
void Connect::process_RCTime(std::shared_ptr<const Telegram> telegram) {
|
||||
void Connect::process_RCTime(const std::shared_ptr<const Telegram> & telegram) {
|
||||
if (telegram->offset || telegram->message_length < 10) {
|
||||
return;
|
||||
}
|
||||
@@ -121,7 +121,7 @@ std::shared_ptr<Connect::RoomCircuit> Connect::room_circuit(const uint8_t num, c
|
||||
}
|
||||
|
||||
// gateway(0x50) B all(0x00), ?(0x0BDD), data: 00 E6 36 2A
|
||||
void Connect::process_roomThermostat(std::shared_ptr<const Telegram> telegram) {
|
||||
void Connect::process_roomThermostat(const std::shared_ptr<const Telegram> & telegram) {
|
||||
bool create = telegram->offset == 0 && telegram->message_data[0] < 0x80;
|
||||
auto rc = room_circuit(telegram->type_id - 0xBDD, create);
|
||||
if (rc == nullptr) {
|
||||
@@ -147,7 +147,7 @@ void Connect::process_roomThermostat(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// gateway(0x48) W gateway(0x50), ?(0x0B42), data: 01 // icon in offset 0
|
||||
// gateway(0x48) W gateway(0x50), ?(0x0B42), data: 00 4B 00 FC 00 63 00 68 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (offset 1)
|
||||
void Connect::process_roomThermostatName(std::shared_ptr<const Telegram> telegram) {
|
||||
void Connect::process_roomThermostatName(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto rc = room_circuit(telegram->type_id - 0xB3D);
|
||||
if (rc == nullptr) {
|
||||
return;
|
||||
@@ -163,7 +163,7 @@ void Connect::process_roomThermostatName(std::shared_ptr<const Telegram> telegra
|
||||
|
||||
// settings 0-mode, 1-tempautotemp, 3 - manualtemp, 6 - ?, 7 - childlock
|
||||
// 0x0BB5, ff: data: 00 FF 00 24 01 FF 24 00
|
||||
void Connect::process_roomThermostatSettings(std::shared_ptr<const Telegram> telegram) {
|
||||
void Connect::process_roomThermostatSettings(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto rc = room_circuit(telegram->type_id - 0xBB5);
|
||||
if (rc == nullptr) {
|
||||
return;
|
||||
@@ -176,7 +176,7 @@ void Connect::process_roomThermostatSettings(std::shared_ptr<const Telegram> tel
|
||||
}
|
||||
|
||||
// unknown telegrams, needs fetch
|
||||
void Connect::process_roomThermostatParam(std::shared_ptr<const Telegram> telegram) {
|
||||
void Connect::process_roomThermostatParam(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto rc = room_circuit(telegram->type_id - 0x1230);
|
||||
if (rc == nullptr) {
|
||||
return;
|
||||
@@ -184,7 +184,7 @@ void Connect::process_roomThermostatParam(std::shared_ptr<const Telegram> telegr
|
||||
}
|
||||
|
||||
// unknown broadcasted telegrams
|
||||
void Connect::process_roomThermostatData(std::shared_ptr<const Telegram> telegram) {
|
||||
void Connect::process_roomThermostatData(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto rc = room_circuit(telegram->type_id - 0x1244);
|
||||
if (rc == nullptr) {
|
||||
return;
|
||||
@@ -192,7 +192,7 @@ void Connect::process_roomThermostatData(std::shared_ptr<const Telegram> telegra
|
||||
}
|
||||
|
||||
// schedule for all thermostats
|
||||
void Connect::process_roomSchedule(std::shared_ptr<const Telegram> telegram) {
|
||||
void Connect::process_roomSchedule(const std::shared_ptr<const Telegram> & telegram) {
|
||||
uint8_t length = ((telegram->offset + telegram->message_length) > 126) ? 126 - telegram->offset : telegram->message_length;
|
||||
memcpy(&schedule_[telegram->offset], telegram->message_data, length);
|
||||
for (uint8_t c : schedule_) {
|
||||
|
||||
@@ -56,12 +56,12 @@ class Connect : public EMSdevice {
|
||||
std::shared_ptr<Connect::RoomCircuit> room_circuit(const uint8_t num, const bool create = false);
|
||||
|
||||
void register_device_values_room(std::shared_ptr<Connect::RoomCircuit> room);
|
||||
void process_roomThermostat(std::shared_ptr<const Telegram> telegram);
|
||||
void process_roomThermostatName(std::shared_ptr<const Telegram> telegram);
|
||||
void process_roomThermostatSettings(std::shared_ptr<const Telegram> telegram);
|
||||
void process_roomThermostatParam(std::shared_ptr<const Telegram> telegram);
|
||||
void process_roomThermostatData(std::shared_ptr<const Telegram> telegram);
|
||||
void process_roomSchedule(std::shared_ptr<const Telegram> telegram);
|
||||
void process_roomThermostat(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_roomThermostatName(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_roomThermostatSettings(const std::shared_ptr<const Telegram> & telegram);
|
||||
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);
|
||||
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);
|
||||
@@ -70,8 +70,8 @@ class Connect : public EMSdevice {
|
||||
|
||||
std::vector<std::shared_ptr<Connect::RoomCircuit>, AllocatorPSRAM<std::shared_ptr<Connect::RoomCircuit>>> room_circuits_;
|
||||
|
||||
void process_OutdoorTemp(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RCTime(std::shared_ptr<const Telegram> telegram);
|
||||
void process_OutdoorTemp(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RCTime(const std::shared_ptr<const Telegram> & telegram);
|
||||
int16_t outdoorTemp_;
|
||||
char dateTime_[25]; // date and time stamp
|
||||
uint8_t schedule_[126]; // telegram copy
|
||||
|
||||
@@ -32,7 +32,7 @@ Controller::Controller(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
||||
}
|
||||
|
||||
// process_dateTime - type 0x06 - date and time from a thermostat - 14 bytes long, IVT only
|
||||
void Controller::process_dateTime(std::shared_ptr<const Telegram> telegram) {
|
||||
void Controller::process_dateTime(const std::shared_ptr<const Telegram> & telegram) {
|
||||
if (telegram->offset > 0 || telegram->message_length < 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class Controller : public EMSdevice {
|
||||
public:
|
||||
Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
|
||||
|
||||
void process_dateTime(std::shared_ptr<const Telegram> telegram);
|
||||
void process_dateTime(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
char dateTime_[25];
|
||||
};
|
||||
|
||||
@@ -69,7 +69,7 @@ Extension::Extension(uint8_t device_type, uint8_t device_id, uint8_t product_id,
|
||||
|
||||
// extension(0x15) -W-> Me(0x0B), EM100SetMessage(0x0935), data: 00 00 64 50 14
|
||||
// need to be fetched
|
||||
void Extension::process_EM100SetMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Extension::process_EM100SetMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, minV_, 1); // Input for off, is / 10
|
||||
has_update(telegram, maxV_, 2); // Input for 100%, is / 10
|
||||
has_update(telegram, minT_, 3); // min temp
|
||||
@@ -77,22 +77,22 @@ void Extension::process_EM100SetMessage(std::shared_ptr<const Telegram> telegram
|
||||
}
|
||||
|
||||
// extension(0x15) -B-> All(0x00), ?(0x0936), data: 00 00 00 00 28 00 (offset 1)
|
||||
void Extension::process_EM100OutMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Extension::process_EM100OutMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, outPower_, 5); // power monitor %
|
||||
}
|
||||
|
||||
// extension(0x15) -B-> All(0x00), ?(0x093A), data: 00 00 00 00 00 00 00 00 00 03 01
|
||||
void Extension::process_EM100ConfigMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Extension::process_EM100ConfigMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, dip_, 9);
|
||||
}
|
||||
|
||||
// extension(0x15) -B-> All(0x00), ?(0x0938), data: 01 62
|
||||
void Extension::process_EM100InputMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Extension::process_EM100InputMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, input_, 1);
|
||||
}
|
||||
|
||||
// extension(0x15) -B-> All(0x00), ?(0x0939), data: 64 4E 00 00
|
||||
void Extension::process_EM100MonitorMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Extension::process_EM100MonitorMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, setPower_, 0); // percent
|
||||
has_update(telegram, setPoint_, 1); // °C
|
||||
// has_update(telegram, errorState_, 2); // OE1
|
||||
@@ -100,7 +100,7 @@ void Extension::process_EM100MonitorMessage(std::shared_ptr<const Telegram> tele
|
||||
}
|
||||
|
||||
// extension(0x15) -B-> All(0x00), ?(0x0937), data: 80 00
|
||||
void Extension::process_EM100TempMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Extension::process_EM100TempMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, headerTemp_, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,12 +28,12 @@ class Extension : public EMSdevice {
|
||||
Extension(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
|
||||
|
||||
private:
|
||||
void process_EM100SetMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_EM100OutMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_EM100MonitorMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_EM100TempMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_EM100InputMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_EM100ConfigMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_EM100SetMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_EM100OutMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_EM100MonitorMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_EM100TempMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_EM100InputMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_EM100ConfigMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
bool set_minV(const char * value, const int8_t id);
|
||||
bool set_maxV(const char * value, const int8_t id);
|
||||
|
||||
+13
-13
@@ -204,7 +204,7 @@ Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, c
|
||||
* Type 0x47B - HeatPump Monitor 2
|
||||
* e.g. "38 10 FF 00 03 7B 08 24 00 4B"
|
||||
*/
|
||||
void Heatpump::process_HPMonitor2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatpump::process_HPMonitor2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, dewTemperature_, 0);
|
||||
has_update(telegram, airHumidity_, 1);
|
||||
}
|
||||
@@ -213,13 +213,13 @@ void Heatpump::process_HPMonitor2(std::shared_ptr<const Telegram> telegram) {
|
||||
* Type 0x42B- HeatPump Monitor 1
|
||||
* e.g. "38 10 FF 00 03 2B 00 D1 08 2A 01"
|
||||
*/
|
||||
void Heatpump::process_HPMonitor1(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatpump::process_HPMonitor1(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// still to implement
|
||||
}
|
||||
|
||||
// 0x09A0
|
||||
// Heatpump(0x53) -> All(0x00), ?(0x09A0), data: 02 23 01 3E 01 39 00 5D 01 DE 01 38 00 40 00 5E 00 58 00 3F 01 34 00 02
|
||||
void Heatpump::process_HPTemperature(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatpump::process_HPTemperature(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, hpTc3_, 2); // condenser temp.
|
||||
has_update(telegram, hpTr1_, 8); // compressor temp.
|
||||
has_update(telegram, hpTr3_, 10); // cond. temp. heating
|
||||
@@ -234,7 +234,7 @@ void Heatpump::process_HPTemperature(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// 0x099B
|
||||
// Heatpump(0x53) -> All(0x00), ?(0x099B), data: 80 00 80 00 01 3C 01 38 80 00 80 00 80 00 01 37 00 00 00 00 64
|
||||
void Heatpump::process_HPFlowTemp(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatpump::process_HPFlowTemp(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, flowTemp_, 4);
|
||||
has_update(telegram, retTemp_, 6);
|
||||
has_update(telegram, sysRetTemp_, 14);
|
||||
@@ -243,7 +243,7 @@ void Heatpump::process_HPFlowTemp(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// 0x0998 HPSettings
|
||||
// [emsesp] Heatpump(0x53) -> Me(0x0B), ?(0x0998), data: 00 00 0B 00 00 1F 01 00 01 01 16 06 00 04 02 FF 00 01 7C 01
|
||||
void Heatpump::process_HPSettings(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatpump::process_HPSettings(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, controlStrategy_, 0);
|
||||
has_update(telegram, hybridDHW_, 1);
|
||||
has_update(telegram, energyPriceGas_, 2);
|
||||
@@ -258,14 +258,14 @@ void Heatpump::process_HPSettings(std::shared_ptr<const Telegram> telegram) {
|
||||
// 0x099C HPComp
|
||||
// Broadcast (0x099C), data: 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 76 00 00
|
||||
// data: 00 2B 00 03 04 13 00 00 00 00 00 02 02 02 (offset 24)
|
||||
void Heatpump::process_HPComp(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatpump::process_HPComp(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, hpCompSpd_, 15);
|
||||
has_update(telegram, hpPower_, 17); // https://github.com/emsesp/EMS-ESP32/issues/2883
|
||||
}
|
||||
|
||||
// 0x999 HPFunctionTest
|
||||
// HPFunctionTest(0x0999), data: 00 00 00 32 00 00 00 00 00 00 00
|
||||
void Heatpump::process_HPFunctionTest(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatpump::process_HPFunctionTest(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, airPurgeMode_, 0);
|
||||
has_update(telegram, heatPumpOutput_, 2);
|
||||
has_update(telegram, coolingCircuit_, 6);
|
||||
@@ -276,7 +276,7 @@ void Heatpump::process_HPFunctionTest(std::shared_ptr<const Telegram> telegram)
|
||||
|
||||
// boiler(0x08) -W-> Me(0x0B), ?(0x04AE), data: 00 00 BD C4 00 00 5B 6A 00 00 00 24 00 00 62 59 00 00 00 00 00 00 00 00
|
||||
// boiler(0x08) -W-> Me(0x0B), ?(0x04AE), data: 00 00 00 00 00 00 00 00 (offset 24)
|
||||
void Heatpump::process_HpEnergy(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatpump::process_HpEnergy(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, nrgTotal_, 0);
|
||||
has_update(telegram, nrgHeat_, 4);
|
||||
has_update(telegram, nrgWw_, 12);
|
||||
@@ -285,7 +285,7 @@ void Heatpump::process_HpEnergy(std::shared_ptr<const Telegram> telegram) {
|
||||
// boiler(0x08) -W-> Me(0x0B), ?(0x04AF), data: 00 00 48 B2 00 00 48 55 00 00 00 5D 00 00 01 78 00 00 00 00 00 00 07 61
|
||||
// boiler(0x08) -W-> Me(0x0B), ?(0x04AF), data: 00 00 24 B0 00 00 00 12 00 00 23 A5 00 00 00 4B 00 00 00 00 00 00 00 00 (offset 24)
|
||||
// boiler(0x08) -W-> Me(0x0B), ?(0x04AF), data: 00 00 00 00 00 00 00 00 (offset 48)
|
||||
void Heatpump::process_HpMeters(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatpump::process_HpMeters(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, meterTotal_, 0);
|
||||
has_update(telegram, meterComp_, 4);
|
||||
has_update(telegram, meterEHeat_, 8);
|
||||
@@ -294,14 +294,14 @@ void Heatpump::process_HpMeters(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// Broadcast (0x099A), data: 05 00 00 00 00 00 00 37 00 00 1D 00 00 52 00 00 13 01 00 01 7C
|
||||
void Heatpump::process_HpStarts(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatpump::process_HpStarts(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, hpActivity_, 2); // https://github.com/emsesp/EMS-ESP32/issues/2883
|
||||
has_update(telegram, heatStartsHp_, 11, 3);
|
||||
has_update(telegram, wwStartsHp_, 14, 3);
|
||||
}
|
||||
|
||||
// 0x0112E energy consumption
|
||||
void Heatpump::process_HpEnergy1(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatpump::process_HpEnergy1(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, fuelHeat_, 3);
|
||||
has_update(telegram, fuelDhw_, 7);
|
||||
has_update(telegram, elHeat_, 11);
|
||||
@@ -309,14 +309,14 @@ void Heatpump::process_HpEnergy1(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// 0x013B energy generated
|
||||
void Heatpump::process_HpEnergy2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatpump::process_HpEnergy2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, elGenHeat_, 3);
|
||||
has_update(telegram, elGenDhw_, 7);
|
||||
}
|
||||
|
||||
// 0x04AA power, Broadcast (0x04AA), data: 00 00
|
||||
// see https://github.com/emsesp/EMS-ESP32/issues/2883
|
||||
void Heatpump::process_HpPower(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatpump::process_HpPower(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, hpCurrPower_, 0);
|
||||
}
|
||||
|
||||
|
||||
+13
-13
@@ -89,19 +89,19 @@ class Heatpump : public EMSdevice {
|
||||
uint32_t elGenHeat_;
|
||||
uint32_t elGenDhw_;
|
||||
|
||||
void process_HPMonitor1(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HPMonitor2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HPSettings(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HPFunctionTest(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HPTemperature(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HPFlowTemp(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HPComp(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpEnergy(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpMeters(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpStarts(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpEnergy1(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpEnergy2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpPower(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HPMonitor1(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HPMonitor2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HPSettings(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HPFunctionTest(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HPTemperature(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HPFlowTemp(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HPComp(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpEnergy(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpMeters(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpStarts(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpEnergy1(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpEnergy2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HpPower(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
bool set_controlStrategy(const char * value, const int8_t id);
|
||||
bool set_lowNoiseMode(const char * value, const int8_t id);
|
||||
|
||||
@@ -96,14 +96,14 @@ Heatsource::Heatsource(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
||||
*/
|
||||
|
||||
// 0x6DC, ff for cascaded heatsources (hs)
|
||||
void Heatsource::process_CascadeMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatsource::process_CascadeMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
telegram->read_value(burnWorkMin_, 3); // this is in seconds
|
||||
burnWorkMin_ /= 60;
|
||||
has_update(burnWorkMin_);
|
||||
}
|
||||
|
||||
// UBAMonitorFastPlus - type 0xE4 - central heating monitor EMS+
|
||||
void Heatsource::process_UBAMonitorFastPlus(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatsource::process_UBAMonitorFastPlus(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, setFlowTemp_, 6);
|
||||
has_update(telegram, curBurnPow_, 10);
|
||||
has_update(telegram, selBurnPow_, 9);
|
||||
@@ -116,7 +116,7 @@ void Heatsource::process_UBAMonitorFastPlus(std::shared_ptr<const Telegram> tele
|
||||
// 0x054D AM200 temperatures
|
||||
// Rx: 60 00 FF 00 04 4D 0103 0108 8000 00C6 0127 0205 8000 0200 0000 8000 6C
|
||||
// TB4 TR2 TA1 TR1 TB1 TB2* TB3
|
||||
void Heatsource::process_amTempMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatsource::process_amTempMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, curFlowTemp_, 0); // TB4
|
||||
has_update(telegram, retTemp_, 2); // TR2
|
||||
has_update(telegram, flueGasTemp_, 4);
|
||||
@@ -129,7 +129,7 @@ void Heatsource::process_amTempMessage(std::shared_ptr<const Telegram> telegram)
|
||||
|
||||
// 0x054E AM200 status (6 bytes long)
|
||||
// Rx: 60 00 FF 00 04 4E 00 00 00 00 00 00 86
|
||||
void Heatsource::process_amStatusMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatsource::process_amStatusMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, aPumpMod_, 0); // PR1
|
||||
// offset 1: bitfield 01-pump on, 02-VR1 opening, 04-VR1 closing, 08-VB1 opening, 10-VB1 closing
|
||||
// actually we dont know the offset of VR2
|
||||
@@ -143,7 +143,7 @@ void Heatsource::process_amStatusMessage(std::shared_ptr<const Telegram> telegra
|
||||
|
||||
// 0x054C AM200 not broadcasted message, 23 bytes long
|
||||
// data: 00 01 01 00 01 00 41 4B 00 5A 00 5A 00 01 05 3C 00 00 5A 00 01 23 00
|
||||
void Heatsource::process_amSettingMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatsource::process_amSettingMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, vr2Config_, 12); // pos 12: off(00)/bypass(01)
|
||||
has_update(telegram, ahsActivated_, 0); // pos 00: Alternate heat source activation: No(00),Yes(01)
|
||||
has_update(telegram, aPumpConfig_, 4); // pos 04: Buffer primary pump->Config pump: No(00),Yes(01)
|
||||
@@ -164,7 +164,7 @@ void Heatsource::process_amSettingMessage(std::shared_ptr<const Telegram> telegr
|
||||
|
||||
// 0x054F AM200 not broadcasted message, 7 bytes long
|
||||
// Boiler(0x60) -> Me(0x0B), amCommand(0x054F), data: 00 00 00 00 00 00 00
|
||||
void Heatsource::process_amCommandMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatsource::process_amCommandMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// pos 0: return pump in percent
|
||||
// pos 3: setValveBuffer VB1 0-off, 1-open, 2-close
|
||||
// pos 2: setValveReturn VR1 0-off, 1-open, 2-close
|
||||
@@ -174,7 +174,7 @@ void Heatsource::process_amCommandMessage(std::shared_ptr<const Telegram> telegr
|
||||
// 0x0550 AM200 broadcasted message, all 27 bytes unkown
|
||||
// Rx: 60 00 FF 00 04 50 00 FF 00 FF FF 00 0D 00 01 00 00 00 00 01 03 01 00 03 00 2D 19 C8 02 94 00 4A
|
||||
// Rx: 60 00 FF 19 04 50 00 FF FF 39
|
||||
void Heatsource::process_amExtraMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Heatsource::process_amExtraMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, blockRemain_, 24); // minutes
|
||||
has_update(telegram, blockRemainWw_, 25); // minutes
|
||||
}
|
||||
|
||||
@@ -72,14 +72,14 @@ class Heatsource : public EMSdevice {
|
||||
int8_t blockHyst_; // pos 14?: Hyst. for bolier block (K)
|
||||
uint8_t releaseWait_; // pos 15: Boiler release wait time (min)
|
||||
|
||||
void process_CascadeMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAMonitorFastPlus(std::shared_ptr<const Telegram> telegram);
|
||||
void process_CascadeMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_UBAMonitorFastPlus(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
void process_amTempMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_amStatusMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_amSettingMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_amCommandMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_amExtraMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_amTempMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_amStatusMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_amSettingMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_amCommandMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_amExtraMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
|
||||
bool set_vr2Config(const char * value, const int8_t id); // pos 12: off(00)/Keelbypass(01)/(hc1pump(02) only standalone)
|
||||
|
||||
@@ -91,7 +91,7 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
||||
// heating circuits 0x02D7, 0x02D8 etc...
|
||||
// e.g. A0 00 FF 00 01 D7 00 00 00 80 00 00 00 00 03 C5
|
||||
// A0 0B FF 00 01 D7 00 00 00 80 00 00 00 00 03 80
|
||||
void Mixer::process_MMPLUSStatusMessage_HC(std::shared_ptr<const Telegram> telegram) {
|
||||
void Mixer::process_MMPLUSStatusMessage_HC(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, flowTempHc_, 3); // is * 10
|
||||
has_update(telegram, flowSetTemp_, 5);
|
||||
has_bitupdate(telegram, pumpStatus_, 0, 0);
|
||||
@@ -102,7 +102,7 @@ void Mixer::process_MMPLUSStatusMessage_HC(std::shared_ptr<const Telegram> teleg
|
||||
// Mixer IPM - 0x010C
|
||||
// e.g. A0 00 FF 00 00 0C 01 00 00 00 00 00 54
|
||||
// A1 00 FF 00 00 0C 02 04 00 01 1D 00 82
|
||||
void Mixer::process_IPMStatusMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Mixer::process_IPMStatusMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// check if circuit is active, 0-off, 1-unmixed, 2-mixed
|
||||
uint8_t ismixed = 0;
|
||||
telegram->read_value(ismixed, 0);
|
||||
@@ -122,14 +122,14 @@ void Mixer::process_IPMStatusMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// Mixer IPM - 0x001E Temperature Message in unmixed circuits
|
||||
// in unmixed circuits FlowTemp in 10C is zero, this is the measured flowtemp in header
|
||||
void Mixer::process_IPMTempMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Mixer::process_IPMTempMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, flowTempVf_, 0); // TC1, is * 10
|
||||
}
|
||||
|
||||
// Mixer on a MM10 - 0xAB
|
||||
// e.g. Mixer Module -> All, type 0xAB, telegram: 21 00 AB 00 2D 01 BE 64 04 01 00 (CRC=15) #data=7
|
||||
// see also https://github.com/emsesp/EMS-ESP/issues/386
|
||||
void Mixer::process_MMStatusMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Mixer::process_MMStatusMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// the heating circuit is determine by which device_id it is, 0x20 - 0x23
|
||||
// 0x21 is position 2. 0x20 is typically reserved for the WM10 switch module
|
||||
// see https://github.com/emsesp/EMS-ESP/issues/270 and https://github.com/emsesp/EMS-ESP/issues/386#issuecomment-629610918
|
||||
@@ -147,14 +147,14 @@ void Mixer::process_MMStatusMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// Mixer on a MM10 - 0xAA
|
||||
// e.g. Thermostat -> Mixer Module, type 0xAA, telegram: 10 21 AA 00 FF 0C 0A 11 0A 32 xx
|
||||
void Mixer::process_MMConfigMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Mixer::process_MMConfigMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, activated_, 0); // on = 0xFF
|
||||
has_update(telegram, setValveTime_, 1); // valve runtime in 10 sec, max 120 s
|
||||
}
|
||||
|
||||
// Mixer Config 0x2CD, ..
|
||||
// mixer(0x20) -W-> Me(0x0B), ?(0x02CD), data: FF 0E 05 FF 1E 00
|
||||
void Mixer::process_MMPLUSConfigMessage_HC(std::shared_ptr<const Telegram> telegram) {
|
||||
void Mixer::process_MMPLUSConfigMessage_HC(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, activated_, 0); // on = 0xFF
|
||||
has_update(telegram, setValveTime_, 1); // valve runtime in 10 sec, default 120 s, max 600 s
|
||||
has_update(telegram, flowTempOffset_, 2); // Mixer increase [0-20 K]
|
||||
@@ -165,14 +165,14 @@ void Mixer::process_MMPLUSConfigMessage_HC(std::shared_ptr<const Telegram> teleg
|
||||
// Thermostat(0x10) -> Mixer(0x20), ?(0x2E1), data: 01 1C 64 00 01
|
||||
// Thermostat(0x10) -> Mixing Module(0x20), (0x2E1), data: 01 00 00 00 01
|
||||
// Thermostat(0x10) -> Mixing Module(0x20), (0x2EB), data: 00
|
||||
// void Mixer::process_MMPLUSSetMessage_HC(std::shared_ptr<const Telegram> telegram) {
|
||||
// void Mixer::process_MMPLUSSetMessage_HC(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// pos 1: setpoint
|
||||
// pos2: pump
|
||||
// }
|
||||
|
||||
// Mixer on a MM10 - 0xAC
|
||||
// e.g. Thermostat -> Mixer Module, type 0xAC, telegram: 10 21 AC 00 1E 64 01 AB
|
||||
void Mixer::process_MMSetMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Mixer::process_MMSetMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// pos 0: flowtemp setpoint 1E = 30°C
|
||||
// pos 1: pump in %
|
||||
// pos 2 flags (mostly 01)
|
||||
@@ -180,7 +180,7 @@ void Mixer::process_MMSetMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// Thermostat(0x10) -> Mixer(0x21), ?(0x23), data: 1A 64 00 90 21 23 00 1A 64 00 89
|
||||
void Mixer::process_IPMSetMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Mixer::process_IPMSetMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// pos 0: flowtemp setpoint 1A = 26°C
|
||||
// pos 1: pump in %?
|
||||
}
|
||||
|
||||
+9
-9
@@ -30,15 +30,15 @@ class Mixer : public EMSdevice {
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void process_MMPLUSStatusMessage_HC(std::shared_ptr<const Telegram> telegram);
|
||||
void process_MMPLUSConfigMessage_HC(std::shared_ptr<const Telegram> telegram);
|
||||
void process_MMPLUSSetMessage_HC(std::shared_ptr<const Telegram> telegram);
|
||||
void process_IPMStatusMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_IPMTempMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_IPMSetMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_MMStatusMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_MMConfigMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_MMSetMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_MMPLUSStatusMessage_HC(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_MMPLUSConfigMessage_HC(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_MMPLUSSetMessage_HC(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_IPMStatusMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_IPMTempMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_IPMSetMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_MMStatusMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_MMConfigMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_MMSetMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
bool set_flowSetTemp(const char * value, const int8_t id);
|
||||
bool set_pump(const char * value, const int8_t id);
|
||||
|
||||
@@ -39,7 +39,7 @@ Pool::Pool(uint8_t device_type, uint8_t device_id, uint8_t product_id, const cha
|
||||
}
|
||||
|
||||
// Mixer MP100 for pools - 0x5BA
|
||||
void Pool::process_HpPoolStatus(std::shared_ptr<const Telegram> telegram) {
|
||||
void Pool::process_HpPoolStatus(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, poolTemp_, 0);
|
||||
has_update(telegram, poolShunt_, 3); // 0-100% how much is the shunt open?
|
||||
telegram->read_value(poolShuntStatus__, 2);
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ class Pool : public EMSdevice {
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void process_HpPoolStatus(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HpPoolStatus(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
private:
|
||||
// MP100 pool
|
||||
|
||||
+24
-20
@@ -26,6 +26,10 @@ uuid::log::Logger Solar::logger_{F_(solar), uuid::log::Facility::CONSOLE};
|
||||
|
||||
Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
// pre-size containers: max in-code ~20 telegrams / ~84 values
|
||||
reserve_telegram_functions(16);
|
||||
reserve_device_values(64);
|
||||
|
||||
// telegram handlers
|
||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM10) {
|
||||
register_telegram_type(0x97, "SM10Monitor", false, MAKE_PF_CB(process_SM10Monitor));
|
||||
@@ -437,7 +441,7 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
||||
|
||||
// SM10Monitor - type 0x96
|
||||
// Solar(0x30) -> All(0x00), (0x96), data: FF 18 19 0A 02 5A 27 0A 05 2D 1E 0F 64 28 0A
|
||||
void Solar::process_SM10Config(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM10Config(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, solarIsEnabled_, 0); // FF on
|
||||
has_update(telegram, setting3_, 3);
|
||||
has_update(telegram, setting4_, 4);
|
||||
@@ -458,7 +462,7 @@ void Solar::process_SM10Config(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// SM10Monitor - type 0x97
|
||||
// Solar(0x30) -> All(0x00), SM10Monitor(0x97), data: 00 00 00 22 00 00 D2 01 00 F6 2A 00 00
|
||||
void Solar::process_SM10Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM10Monitor(const std::shared_ptr<const Telegram> & telegram) {
|
||||
uint8_t solarpumpmod = solarPumpMod_;
|
||||
|
||||
has_update(telegram, data0_, 0);
|
||||
@@ -510,7 +514,7 @@ void Solar::process_SM10Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
* SM100SystemConfig(0x358), data: FF 00 FF 00 FF 00 00 00 00 00 00 FF 00 00 FF 00 00 00 00 FF 00 FF 01 01 00
|
||||
* SM100SystemConfig(0x358), data: 00 00 00 00 00 00 00 (offset 25)
|
||||
*/
|
||||
void Solar::process_SM100SystemConfig(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100SystemConfig(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, heatTransferSystem_, 5, 1);
|
||||
has_update(telegram, externalCyl_, 9, 1);
|
||||
has_update(telegram, thermalDisinfect_, 10, 1);
|
||||
@@ -522,7 +526,7 @@ void Solar::process_SM100SystemConfig(std::shared_ptr<const Telegram> telegram)
|
||||
* process_SM100SolarCircuitConfig - type 0x035A EMS+ - for MS/SM100 and MS/SM200
|
||||
* e.g. B0 0B FF 00 02 5A 64 05 00 58 14 01 01 32 64 00 00 00 5A 0C
|
||||
*/
|
||||
void Solar::process_SM100CircuitConfig(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100CircuitConfig(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, collectorMaxTemp_, 0);
|
||||
has_update(telegram, cylMaxTemp_, 3);
|
||||
has_update(telegram, collectorMinTemp_, 4);
|
||||
@@ -538,7 +542,7 @@ void Solar::process_SM100CircuitConfig(std::shared_ptr<const Telegram> telegram)
|
||||
/*
|
||||
* process_SM100Solar2CircuitConfig - type 0x035D EMS+ - for MS/SM100 and MS/SM200
|
||||
*/
|
||||
void Solar::process_SM100Circuit2Config(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100Circuit2Config(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, solarPump2Kick_, 0);
|
||||
//has_update(telegram, solar2PumpTurnoffDiff_, 3); // is * 10
|
||||
has_update(telegram, solarPump2TurnonDiff_, 4); // is * 10
|
||||
@@ -554,13 +558,13 @@ void Solar::process_SM100Circuit2Config(std::shared_ptr<const Telegram> telegram
|
||||
}
|
||||
|
||||
// type 0x35C Heat assistance
|
||||
void Solar::process_SM100HeatAssist(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100HeatAssist(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, heatAssistOn_, 0); // is *10
|
||||
has_update(telegram, heatAssistOff_, 1); // is *10
|
||||
}
|
||||
|
||||
// type 0x361 differential control
|
||||
void Solar::process_SM100Differential(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100Differential(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, diffControl_, 0); // is *10
|
||||
}
|
||||
|
||||
@@ -577,7 +581,7 @@ void Solar::process_SM100Differential(std::shared_ptr<const Telegram> telegram)
|
||||
// bytes 13..16 = maximum value
|
||||
// bytes 17..20 = current value
|
||||
// e.g. B0 0B F9 00 00 02 5A 00 00 6E
|
||||
void Solar::process_SM100ParamCfg(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100ParamCfg(const std::shared_ptr<const Telegram> & telegram) {
|
||||
uint16_t t_id = EMS_VALUE_UINT16_NOTSET;
|
||||
uint8_t of = EMS_VALUE_UINT8_NOTSET;
|
||||
int32_t min = EMS_VALUE_UINT16_NOTSET;
|
||||
@@ -605,7 +609,7 @@ void Solar::process_SM100ParamCfg(std::shared_ptr<const Telegram> telegram) {
|
||||
* bytes 16+17 = TS5 Temperature sensor 2 cylinder, bottom, or swimming pool
|
||||
* bytes 20+21 = TS6 Temperature sensor external heat exchanger
|
||||
*/
|
||||
void Solar::process_SM100Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100Monitor(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, collectorTemp_, 0); // is *10 - TS1: Temperature sensor for collector array 1
|
||||
has_update(telegram, cylBottomTemp_, 2); // is *10 - TS2: Temperature sensor 1 cylinder, bottom
|
||||
has_update(telegram, cylBottomTemp2_, 16); // is *10 - TS5: Temperature sensor 2 cylinder, bottom, or swimming pool
|
||||
@@ -622,7 +626,7 @@ void Solar::process_SM100Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
// SM100Monitor2 - 0x0363 Heatcounter
|
||||
// e.g. B0 00 FF 00 02 63 80 00 80 00 00 00 80 00 80 00 80 00 00 80 00 5A
|
||||
// Solar(0x30) -> All(0x00), SM100Monitor2(0x363), data: 01 E1 01 6B 00 00 01 5D 02 8E 80 00 0F 80 00
|
||||
void Solar::process_SM100Monitor2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100Monitor2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, heatCntFlowTemp_, 0); // is *10
|
||||
has_update(telegram, heatCntRetTemp_, 2); // is *10
|
||||
has_update(telegram, heatCnt_, 12);
|
||||
@@ -634,7 +638,7 @@ void Solar::process_SM100Monitor2(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// SM100Config - 0x0366
|
||||
// e.g. B0 00 FF 00 02 66 01 62 00 13 40 14
|
||||
void Solar::process_SM100Config(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100Config(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, availabilityFlag_, 0);
|
||||
has_update(telegram, configFlag_, 1);
|
||||
has_update(telegram, userFlag_, 2);
|
||||
@@ -642,7 +646,7 @@ void Solar::process_SM100Config(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// SM100Config1 - 0x035F
|
||||
// e.g. Solar(0x30) -> Me(0x0B), ?(0x35F), data: 00 00 41 01 1E 0A 0C 19 00 3C 19
|
||||
void Solar::process_SM100Config1(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100Config1(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, cylPriority_, 3);
|
||||
}
|
||||
|
||||
@@ -653,7 +657,7 @@ void Solar::process_SM100Config1(std::shared_ptr<const Telegram> telegram) {
|
||||
* e.g. 30 00 FF 09 02 64 64 = 100%
|
||||
* Solar(0x30) -> All(0x00), (0x364), data: 00 64 05 24 00 00 FF 00 00 05 00 14 3C 64 00 00 00 00
|
||||
*/
|
||||
void Solar::process_SM100Status(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100Status(const std::shared_ptr<const Telegram> & telegram) {
|
||||
uint8_t solarpumpmod = solarPumpMod_;
|
||||
uint8_t cylinderpumpmod = cylPumpMod_;
|
||||
telegram->read_value(cylinderpumpmod, 8);
|
||||
@@ -690,7 +694,7 @@ void Solar::process_SM100Status(std::shared_ptr<const Telegram> telegram) {
|
||||
* byte 4 = VS2 3-way valve for cylinder 2 : test=01, on=04 and off=03
|
||||
* byte 10 = PS1 Solar circuit pump for collector array 1: test=b0001(1), on=b0100(4) and off=b0011(3)
|
||||
*/
|
||||
void Solar::process_SM100Status2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100Status2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_bitupdate(telegram, vs1Status_, 0, 2); // on if bit 2 set
|
||||
has_bitupdate(telegram, valveStatus_, 4, 2); // on if bit 2 set
|
||||
has_bitupdate(telegram, solarPump_, 10, 2); // on if bit 2 set
|
||||
@@ -704,7 +708,7 @@ void Solar::process_SM100Status2(std::shared_ptr<const Telegram> telegram) {
|
||||
* e.g. B0 0B FF 00 02 80 50 64 00 00 29 01 00 00 01
|
||||
* SM100CollectorConfig(0x380), data: 5A 3B 00 00 41 02 00 2D 02 (with 2 collectors)
|
||||
*/
|
||||
void Solar::process_SM100CollectorConfig(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100CollectorConfig(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, climateZone_, 0);
|
||||
has_update(telegram, collector1Area_, 3);
|
||||
// has_enumupdate(telegram, collector1Type_, 5, 1);
|
||||
@@ -724,7 +728,7 @@ void Solar::process_SM100CollectorConfig(std::shared_ptr<const Telegram> telegra
|
||||
* e.g. 30 00 FF 00 02 8E 00 00 00 00 00 00 06 C5 00 00 76 35
|
||||
* SM100Energy(0x38E), data: 00 00 01 79 00 00 22 3D 00 00 09 31 (with 2 collectors)
|
||||
*/
|
||||
void Solar::process_SM100Energy(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100Energy(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, energyLastHour_, 0); // last hour / 10 in Wh
|
||||
has_update(telegram, energyToday_, 4); // todays in Wh
|
||||
has_update(telegram, energyTotal_, 8); // total / 10 in kWh
|
||||
@@ -735,7 +739,7 @@ void Solar::process_SM100Energy(std::shared_ptr<const Telegram> telegram) {
|
||||
* SM100Time(0x391), data: 00 00 2A 13 00 00 00 00 00 00 70 13 00 00 00 00 00 00 24 7E 00 00 00 00 00
|
||||
* SM100Time(0x391), data: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 4A 00 (offset 24)
|
||||
*/
|
||||
void Solar::process_SM100Time(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100Time(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, pumpWorkTime_, 1, 3);
|
||||
// has_update(telegram, pumpXWorkTime_, 9, 3);
|
||||
has_update(telegram, pump2WorkTime_, 17, 3);
|
||||
@@ -746,7 +750,7 @@ void Solar::process_SM100Time(std::shared_ptr<const Telegram> telegram) {
|
||||
* Junkers ISM1 Solar Module - type 0x0103 EMS+ for energy readings
|
||||
* e.g. B0 00 FF 00 00 03 32 00 00 00 00 13 00 D6 00 00 00 FB D0 F0
|
||||
*/
|
||||
void Solar::process_ISM1StatusMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_ISM1StatusMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, collectorTemp_, 4); // Collector Temperature
|
||||
has_update(telegram, cylBottomTemp_, 6); // Temperature Bottom of Solar Boiler cyl
|
||||
uint16_t Wh = energyLastHour_ / 10;
|
||||
@@ -768,7 +772,7 @@ void Solar::process_ISM1StatusMessage(std::shared_ptr<const Telegram> telegram)
|
||||
* ?(0x104), data: 01 A9 01 22 27 0F 27 0F 27 0F 27 0F 27 0F 27 0F
|
||||
* ?(0x104), data: 01 01 00 00 00 00 00 27 0F 27 0F (offset 16)
|
||||
*/
|
||||
void Solar::process_ISM2StatusMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_ISM2StatusMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, cylMiddleTemp_, 0); // Temperature Middle of Solar Boiler cyl
|
||||
has_update(telegram, retHeatAssist_, 2); // return temperature from heating T4
|
||||
has_bitupdate(telegram, m1Valve_, 17, 0); // return valve DUW1 (also 16,0)
|
||||
@@ -777,7 +781,7 @@ void Solar::process_ISM2StatusMessage(std::shared_ptr<const Telegram> telegram)
|
||||
/*
|
||||
* Junkers ISM1 Solar Module - type 0x0101 EMS+ for setting values
|
||||
*/
|
||||
void Solar::process_ISM1Set(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_ISM1Set(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, cylMaxTemp_, 6);
|
||||
}
|
||||
|
||||
|
||||
+20
-20
@@ -137,30 +137,30 @@ class Solar : public EMSdevice {
|
||||
|
||||
std::deque<int16_t> energy;
|
||||
|
||||
void process_SM10Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM10Config(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100SystemConfig(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100CircuitConfig(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100Circuit2Config(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100ParamCfg(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100Monitor2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM10Monitor(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM10Config(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100SystemConfig(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100CircuitConfig(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100Circuit2Config(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100ParamCfg(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100Monitor(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100Monitor2(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
void process_SM100Config(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100Config1(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100Config(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100Config1(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
void process_SM100Status(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100Status2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100CollectorConfig(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100Energy(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100Time(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100Status(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100Status2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100CollectorConfig(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100Energy(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100Time(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
void process_SM100HeatAssist(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100Differential(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100HeatAssist(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100Differential(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
void process_ISM1StatusMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_ISM1Set(std::shared_ptr<const Telegram> telegram);
|
||||
void process_ISM2StatusMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_ISM1StatusMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_ISM1Set(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_ISM2StatusMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
// settings
|
||||
bool set_CollectorMaxTemp(const char * value, const int8_t id);
|
||||
|
||||
@@ -41,13 +41,13 @@ Switch::Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const
|
||||
|
||||
// message 0x9D switch on/off
|
||||
// Thermostat(0x10) -> Switch(0x11), ?(0x9D), data: 00
|
||||
void Switch::process_WM10SetMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Switch::process_WM10SetMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, activated_, 0);
|
||||
}
|
||||
|
||||
// message 0x9C holds flowtemp and unknown status value
|
||||
// Switch(0x11) -> All(0x00), ?(0x9C), data: 01 BA 00 01 00
|
||||
void Switch::process_WM10MonitorMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Switch::process_WM10MonitorMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, flowTempHc_, 0); // is * 10
|
||||
has_update(telegram, status_, 2);
|
||||
// has_update(telegram, status2_, 3)); // unknown
|
||||
@@ -55,7 +55,7 @@ void Switch::process_WM10MonitorMessage(std::shared_ptr<const Telegram> telegram
|
||||
|
||||
// message 0x1E flow temperature, same as in 9C, published often, republished also by boiler UBAFast 0x18
|
||||
// Switch(0x11) -> Boiler(0x08), ?(0x1E), data: 01 BA
|
||||
void Switch::process_WM10TempMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Switch::process_WM10TempMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, flowTempHc_, 0); // is * 10
|
||||
}
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@ class Switch : public EMSdevice {
|
||||
Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
|
||||
|
||||
private:
|
||||
void process_WM10SetMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_WM10MonitorMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_WM10TempMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_WM10SetMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_WM10MonitorMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_WM10TempMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
uint16_t flowTempHc_;
|
||||
uint8_t status_;
|
||||
|
||||
+69
-63
@@ -26,6 +26,12 @@ uuid::log::Logger Thermostat::logger_{F_(thermostat), uuid::log::Facility::CONSO
|
||||
|
||||
Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
// pre-size containers; max in-code counts are ~78 telegrams / ~332 values
|
||||
// but real per-instance counts after flag-discriminated branches are
|
||||
// ~40-60 telegrams / ~150-220 values. Reserve generously to avoid realloc.
|
||||
reserve_telegram_functions(64);
|
||||
reserve_device_values(220);
|
||||
|
||||
// RF remote sensor seen at 0x40, maybe this is also for different hc with id 0x40 - 0x47? emsesp.cpp maps only 0x40
|
||||
if (device_id >= 0x40 && device_id <= 0x47) {
|
||||
register_telegram_type(0x0435, "RFTemp", false, MAKE_PF_CB(process_RemoteTemp));
|
||||
@@ -288,7 +294,7 @@ std::shared_ptr<Thermostat::HeatingCircuit> Thermostat::heating_circuit(const in
|
||||
// determine which heating circuit the type ID is referring too
|
||||
// returns pointer to the HeatingCircuit or nullptr if it can't be found
|
||||
// if its a new one, the heating circuit object will be created and also the fetch flags set
|
||||
std::shared_ptr<Thermostat::HeatingCircuit> Thermostat::heating_circuit(std::shared_ptr<const Telegram> telegram) {
|
||||
std::shared_ptr<Thermostat::HeatingCircuit> Thermostat::heating_circuit(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// do not create a hc on empty messages
|
||||
if (telegram->message_length == 0) {
|
||||
return nullptr;
|
||||
@@ -641,7 +647,7 @@ std::shared_ptr<Thermostat::DhwCircuit> Thermostat::dhw_circuit(const uint8_t of
|
||||
|
||||
// type 0xB1 - data from the RC10 thermostat (0x17)
|
||||
// Data: 04 23 00 BA 00 00 00 BA
|
||||
void Thermostat::process_RC10Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC10Monitor(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -658,7 +664,7 @@ void Thermostat::process_RC10Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// type 0xB0 - for reading the mode from the RC10 thermostat (0x17)
|
||||
// Data: 00 FF 00 1C 20 08 01
|
||||
void Thermostat::process_RC10Set(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC10Set(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -675,7 +681,7 @@ void Thermostat::process_RC10Set(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// type 0xB2, mode setting Data: 04 00
|
||||
// not used, we read mode from monitor 0xB1
|
||||
void Thermostat::process_RC10Set_2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC10Set_2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -687,7 +693,7 @@ void Thermostat::process_RC10Set_2(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// 0xA8 - for reading the mode from the RC20 thermostat (0x17)
|
||||
// RC20Set(0xA8), data: 01 00 FF F6 01 06 00 01 0D 01 00 FF FF 01 02 02 02 00 00 05 1E 05 1E 02 1C 00 FF 00 00 26 02
|
||||
void Thermostat::process_RC20Set(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC20Set(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -700,7 +706,7 @@ void Thermostat::process_RC20Set(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// 0x90 - for reading curve temperature from the RC20 thermostat (0x17)
|
||||
//
|
||||
void Thermostat::process_RC20Temp(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC20Temp(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -716,7 +722,7 @@ void Thermostat::process_RC20Temp(std::shared_ptr<const Telegram> telegram) {
|
||||
// data: 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 (offset 27)
|
||||
// data: E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 90 E7 (offset 54)
|
||||
// data: 90 E7 90 01 00 00 01 01 00 01 01 00 01 01 00 01 01 00 00 (offset 81)
|
||||
void Thermostat::process_RC20Timer(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC20Timer(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -744,7 +750,7 @@ void Thermostat::process_RC20Timer(std::shared_ptr<const Telegram> telegram) {
|
||||
// type 0xAE - data from the RC20 thermostat (0x17) - not for RC20's
|
||||
// 17 00 AE 00 80 12 2E 00 D0 00 00 64 (#data=8)
|
||||
// https://github.com/emsesp/EMS-ESP/issues/361
|
||||
void Thermostat::process_RC20Monitor_2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC20Monitor_2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -763,7 +769,7 @@ void Thermostat::process_RC20Monitor_2(std::shared_ptr<const Telegram> telegram)
|
||||
// offset: 01-nighttemp, 02-daytemp, 03-mode, 0B-program(1-9), 0D-setpoint_roomtemp(temporary)
|
||||
// 17 00 AD 00 01 27 29 01 4B 05 01 FF 28 19 0A 02 00 00
|
||||
// RC25(0x17) -> All(0x00), ?(0xAD), data: 01 27 2D 00 44 05 01 FF 28 19 0A 07 00 00 F6 12 5A 11 00 28 05 05 00
|
||||
void Thermostat::process_RC20Set_2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC20Set_2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -783,14 +789,14 @@ void Thermostat::process_RC20Set_2(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// 0xAF - for reading the roomtemperature from the RC20/ES72 thermostat (0x18, 0x19, ..)
|
||||
void Thermostat::process_RC20Remote(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC20Remote(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, tempsensor1_, 0);
|
||||
}
|
||||
|
||||
// 0x42B - for reading the roomtemperature from the RC100H remote thermostat (0x38, 0x39, ..)
|
||||
// e.g. "38 10 FF 00 03 2B 00 D1 08 2A 01"
|
||||
// also RF temp from 0x435
|
||||
void Thermostat::process_RemoteTemp(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RemoteTemp(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, tempsensor1_, 0);
|
||||
if (telegram->type_id >= 0x435) {
|
||||
return;
|
||||
@@ -804,7 +810,7 @@ void Thermostat::process_RemoteTemp(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// 0x47B, ff - for reading humidity from the RC100H remote thermostat (0x38, 0x39, ..)
|
||||
// e.g. "38 10 FF 00 03 7B 08 24 00 4B"
|
||||
void Thermostat::process_RemoteHumidity(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RemoteHumidity(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// has_update(telegram, dewtemperature_, 0); // this is int8
|
||||
has_update(telegram, humidity_, 1);
|
||||
has_update(telegram, dewtemperature_, 2); // this is int16
|
||||
@@ -821,17 +827,17 @@ void Thermostat::process_RemoteHumidity(std::shared_ptr<const Telegram> telegram
|
||||
|
||||
// 0x273 - for reading temperaturcorrection from the RC100H remote thermostat (0x38, 0x39, ..)
|
||||
// Thermostat(0x38) -> Me(0x0B), RemoteCorrection(0x0273), data: 0A 00
|
||||
void Thermostat::process_RemoteCorrection(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RemoteCorrection(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, ibaCalIntTemperature_, 0);
|
||||
}
|
||||
|
||||
// 0xA6A - for reading battery from the RC100H remote thermostat (0x38, 0x39, ..)
|
||||
void Thermostat::process_RemoteBattery(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RemoteBattery(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, battery_, 1);
|
||||
}
|
||||
|
||||
// type 0x0165, ff
|
||||
void Thermostat::process_JunkersSet(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_JunkersSet(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -859,7 +865,7 @@ void Thermostat::process_JunkersSet(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// type 0x0179, ff for Junkers_OLD
|
||||
void Thermostat::process_JunkersSet2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_JunkersSet2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -879,12 +885,12 @@ void Thermostat::process_JunkersSet2(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// type 0x123 - FB10 Junkers remote
|
||||
void Thermostat::process_JunkersRemoteMonitor(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_JunkersRemoteMonitor(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, tempsensor1_, 0); // roomTemp from remote
|
||||
}
|
||||
|
||||
// type 0xA3 - for external temp settings from the the RC* thermostats (e.g. RC35)
|
||||
void Thermostat::process_RCOutdoorTemp(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RCOutdoorTemp(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, dampedoutdoortemp_, 0);
|
||||
has_update(telegram, tempsensor1_, 3); // sensor 1 - is * 10
|
||||
has_update(telegram, tempsensor2_, 5); // sensor 2 - is * 10
|
||||
@@ -893,7 +899,7 @@ void Thermostat::process_RCOutdoorTemp(std::shared_ptr<const Telegram> telegram)
|
||||
// 0x91 - data from the RC20 thermostat (0x17) - 15 bytes long
|
||||
// RC20Monitor(0x91), data: 90 2A 00 D5 1A 00 00 05 00 5A 04 00 D6 00
|
||||
// offset 8: setburnpower to boiler, offset 9: setflowtemp to boiler (thermostat: targetflowtemp) send via 0x1A
|
||||
void Thermostat::process_RC20Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC20Monitor(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -906,7 +912,7 @@ void Thermostat::process_RC20Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// type 0x0A - data from the Nefit Easy/TC100 thermostat (0x18) - 31 bytes long
|
||||
void Thermostat::process_EasyMonitor(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_EasyMonitor(const std::shared_ptr<const Telegram> & telegram) {
|
||||
monitor_typeids[0] = telegram->type_id;
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
@@ -936,7 +942,7 @@ void Thermostat::process_EasyMonitor(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// Settings Parameters - 0xA5 - RC30_1
|
||||
void Thermostat::process_IBASettings(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_IBASettings(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// 22 - display line on RC35
|
||||
|
||||
// display on Thermostat: 0 int. temp, 1 int. setpoint, 2 ext. temp., 3 burner temp., 4 ww temp, 5 functioning mode, 6 time, 7 data, 8 smoke temp
|
||||
@@ -950,7 +956,7 @@ void Thermostat::process_IBASettings(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// Settings WW 0x37 - RC35
|
||||
void Thermostat::process_RC35wwSettings(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC35wwSettings(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto dhw = dhw_circuit(0, true);
|
||||
has_bitupdate(telegram, dhw->wwProgMode_, 0, 0); // 0-like hc, 0xFF own prog
|
||||
has_bitupdate(telegram, dhw->wwCircProg_, 1, 0); // 0-like hc, 0xFF own prog
|
||||
@@ -964,7 +970,7 @@ void Thermostat::process_RC35wwSettings(std::shared_ptr<const Telegram> telegram
|
||||
}
|
||||
|
||||
// Settings WW 0x3A - RC30
|
||||
void Thermostat::process_RC30wwSettings(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC30wwSettings(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto dhw = dhw_circuit(0, true);
|
||||
has_update(telegram, dhw->wwMode_, 0); // 0-on, 1-off, 2-auto
|
||||
has_update(telegram, dhw->wwWhenModeOff_, 1); // 0-off, 0xFF on
|
||||
@@ -974,7 +980,7 @@ void Thermostat::process_RC30wwSettings(std::shared_ptr<const Telegram> telegram
|
||||
}
|
||||
|
||||
// type 0x38 (ww) and 0x39 (circ)
|
||||
void Thermostat::process_RC35wwTimer(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC35wwTimer(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto dhw = dhw_circuit(0, true);
|
||||
if ((telegram->message_length == 2 && telegram->offset < 83 && !(telegram->offset & 1))
|
||||
|| (!telegram->offset && telegram->type_id == 0x38 && !strlen(dhw->wwSwitchTime_) && telegram->message_length > 1)
|
||||
@@ -1037,7 +1043,7 @@ void Thermostat::process_RC35wwTimer(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// type 0x6F - FR10/FR50/FR100/FR110/FR120 Junkers
|
||||
void Thermostat::process_JunkersMonitor(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_JunkersMonitor(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// ignore single byte telegram messages
|
||||
if (telegram->message_length <= 1) {
|
||||
return;
|
||||
@@ -1062,7 +1068,7 @@ void Thermostat::process_JunkersMonitor(std::shared_ptr<const Telegram> telegram
|
||||
|
||||
// 0xBB Heatpump optimization
|
||||
// ?(0xBB), data: 00 00 00 00 00 00 00 00 00 00 00 FF 02 0F 1E 0B 1A 00 14 03
|
||||
void Thermostat::process_HybridSettings(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_HybridSettings(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_enumupdate(telegram, hybridStrategy_, 12, 1); // cost = 2, temperature = 3, mix = 4
|
||||
has_update(telegram, switchOverTemp_, 13); // full degrees
|
||||
has_update(telegram, energyCostRatio_, 14); // is *10
|
||||
@@ -1073,18 +1079,18 @@ void Thermostat::process_HybridSettings(std::shared_ptr<const Telegram> telegram
|
||||
}
|
||||
|
||||
// 0x23E PV settings
|
||||
void Thermostat::process_PVSettings(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_PVSettings(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, pvRaiseHeat_, 0);
|
||||
has_update(telegram, pvEnableWw_, 3);
|
||||
has_update(telegram, pvLowerCool_, 5);
|
||||
}
|
||||
|
||||
// 0x16E Absent settings - hc or dhw or device_data? #1957
|
||||
void Thermostat::process_Absent(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_Absent(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, absent_, 0);
|
||||
}
|
||||
|
||||
void Thermostat::process_JunkersSetMixer(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_JunkersSetMixer(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -1093,13 +1099,13 @@ void Thermostat::process_JunkersSetMixer(std::shared_ptr<const Telegram> telegra
|
||||
}
|
||||
|
||||
// Thermostat(0x10) -> All(0x00), ?(0x01D3), data: 01 00 00
|
||||
void Thermostat::process_JunkersWW(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_JunkersWW(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto dhw = dhw_circuit(0, true);
|
||||
has_bitupdate(telegram, dhw->wwCharge_, 0, 3);
|
||||
}
|
||||
|
||||
// 0x11E
|
||||
void Thermostat::process_JunkersDisp(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_JunkersDisp(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_enumupdate(telegram, ibaMainDisplay_, 1, 1);
|
||||
has_update(telegram, ibaLanguage_, 3);
|
||||
has_update(telegram, ibaMinExtTemperature_, 16);
|
||||
@@ -1107,7 +1113,7 @@ void Thermostat::process_JunkersDisp(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// type 0x02A5 - data from Worchester CRF200
|
||||
void Thermostat::process_CRFMonitor(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_CRFMonitor(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -1123,7 +1129,7 @@ void Thermostat::process_CRFMonitor(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// type 0x02A5 - data from CR11
|
||||
void Thermostat::process_CR11Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_CR11Monitor(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -1144,7 +1150,7 @@ void Thermostat::process_CR11Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// type 0x02A5 - data from the Nefit RC1010/3000 thermostat (0x18) and RC300/310s on 0x10
|
||||
// Rx: 10 0B FF 00 01 A5 80 00 01 30 23 00 30 28 01 E7 03 03 01 01 E7 02 33 00 00 11 01 03 FF FF 00 04
|
||||
void Thermostat::process_RC300Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC300Monitor(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -1185,7 +1191,7 @@ void Thermostat::process_RC300Monitor(std::shared_ptr<const Telegram> telegram)
|
||||
|
||||
// type 0x02B9 EMS+ for reading from RC300/RC310 thermostat
|
||||
// Thermostat(0x10) -> Me(0x0B), RC300Set(0x2B9), data: FF 2E 2A 26 1E 02 4E FF FF 00 1C 01 E1 20 01 0F 05 00 00 02 1F
|
||||
void Thermostat::process_RC300Set(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC300Set(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr || model() == EMSdevice::EMS_DEVICE_FLAG_CR11) {
|
||||
return;
|
||||
@@ -1236,7 +1242,7 @@ void Thermostat::process_RC300Set(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// types 0x2AF ff
|
||||
// RC300Summer(0x02AF), data: 00 28 00 00 3C 26 00 00 19 0F 00 (from a heatpump)
|
||||
void Thermostat::process_RC300Summer(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC300Summer(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -1266,7 +1272,7 @@ void Thermostat::process_RC300Summer(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// types 0x471 ff summer2_typeids
|
||||
// (0x473), data: 00 11 04 01 01 1C 08 04
|
||||
void Thermostat::process_RC300Summer2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC300Summer2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
// telegram 0x470 see https://github.com/emsesp/EMS-ESP32/issues/2686
|
||||
@@ -1295,7 +1301,7 @@ void Thermostat::process_RC300Summer2(std::shared_ptr<const Telegram> telegram)
|
||||
|
||||
// types 0x29B ff
|
||||
// Thermostat(0x10) -> Me(0x0B), RC300Curves(0x29B), data: 01 01 00 FF FF 01 05 30 52
|
||||
void Thermostat::process_RC300Curve(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC300Curve(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -1315,7 +1321,7 @@ void Thermostat::process_RC300Curve(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// types 0x31B
|
||||
void Thermostat::process_RC300WWtemp(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC300WWtemp(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto dhw = dhw_circuit(0, true);
|
||||
has_update(telegram, dhw->wwSetTemp_, 0);
|
||||
has_update(telegram, dhw->wwSetTempLow_, 1);
|
||||
@@ -1324,7 +1330,7 @@ void Thermostat::process_RC300WWtemp(std::shared_ptr<const Telegram> telegram) {
|
||||
// type 02F5
|
||||
// RC300WWmode(0x2F5), data: 01 FF 04 00 00 00 08 05 00 08 04 00 00 00 00 00 00 00 00 00 01
|
||||
// RC300WWmode(0x2F6), data: 02 FF 04 00 00 00 08 05 00 08 04 00 00 00 00 00 00 00 00 00 01
|
||||
void Thermostat::process_RC300WWmode(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC300WWmode(const std::shared_ptr<const Telegram> & telegram) {
|
||||
uint8_t circuit = 0;
|
||||
telegram->read_value(circuit, 0); // 00-no circuit, 01-boiler, 02-mixer
|
||||
auto dhw = dhw_circuit(telegram->type_id - 0x2F5, circuit != 0);
|
||||
@@ -1358,7 +1364,7 @@ void Thermostat::process_RC300WWmode(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// types 0x31D and 0x31E
|
||||
// RC300WWmode2(0x31D), data: 00 00 09 07
|
||||
void Thermostat::process_RC300WWmode2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC300WWmode2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto dhw = dhw_circuit(telegram->type_id - 0x31D);
|
||||
if (dhw == nullptr) {
|
||||
return;
|
||||
@@ -1372,13 +1378,13 @@ void Thermostat::process_RC300WWmode2(std::shared_ptr<const Telegram> telegram)
|
||||
}
|
||||
|
||||
// 0x23A damped outdoor temp
|
||||
void Thermostat::process_RC300OutdoorTemp(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC300OutdoorTemp(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, dampedoutdoortemp2_, 0); // is *10
|
||||
}
|
||||
|
||||
// 0x240 RC300 parameter, 0x0241 for CW100, see https://github.com/emsesp/EMS-ESP32/issues/2290
|
||||
// RC300Settings(0x240), data: 26 00 03 00 00 00 00 00 FF 01 F6 06 FF 00 00 00 00 00 00 00 00 00 00
|
||||
void Thermostat::process_RC300Settings(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC300Settings(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, ibaCalIntTemperature_, 7);
|
||||
has_update(telegram, ibaDamping_, 8);
|
||||
has_enumupdate(telegram, ibaBuildingType_, 9, 1); // 1=light, 2=medium, 3=heavy
|
||||
@@ -1387,7 +1393,7 @@ void Thermostat::process_RC300Settings(std::shared_ptr<const Telegram> telegram)
|
||||
}
|
||||
|
||||
// 0x2CC - e.g. wwprio for RC310 hcx parameter
|
||||
void Thermostat::process_RC300Set2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC300Set2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// typeids are not in a row. hc:0x2CC, hc2: 0x2CE for RC310
|
||||
// telegram is either offset 3 with data length of 1 and values 0/1 (radiators) - 10 0B FF 03 01 CC 01 F6
|
||||
// or offset 0 with data length of 6 bytes - offset 3 values are 0x00 or 0xFF - 10 0B FF 00 01 CE FF 13 0A FF 1E 00 20
|
||||
@@ -1400,14 +1406,14 @@ void Thermostat::process_RC300Set2(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// 0x267 RC300 floordrying
|
||||
void Thermostat::process_RC300Floordry(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC300Floordry(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, floordrystatus_, 0);
|
||||
has_update(telegram, floordrytemp_, 1);
|
||||
}
|
||||
|
||||
// 0x269 - 0x26D RC300 EMS+ holidaymodes 1 to 5
|
||||
// special case R3000 only date in 0x269, CR50 only 0x043F
|
||||
void Thermostat::process_RC300Holiday(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC300Holiday(const std::shared_ptr<const Telegram> & telegram) {
|
||||
if (telegram->offset || telegram->message_length < 6) {
|
||||
return;
|
||||
}
|
||||
@@ -1425,7 +1431,7 @@ void Thermostat::process_RC300Holiday(std::shared_ptr<const Telegram> telegram)
|
||||
}
|
||||
|
||||
// https://github.com/emsesp/EMS-ESP32/issues/2735#issuecomment-3520124647
|
||||
void Thermostat::process_PID(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_PID(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -1445,7 +1451,7 @@ void Thermostat::process_PID(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// 0x291 ff. HP mode
|
||||
// thermostat(0x10) -W-> Me(0x0B), HPMode(0x0291), data: 01 00 00 03 FF 00
|
||||
void Thermostat::process_HPMode(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_HPMode(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -1455,7 +1461,7 @@ void Thermostat::process_HPMode(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// 0x467 ff HP settings
|
||||
void Thermostat::process_HPSet(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_HPSet(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -1467,7 +1473,7 @@ void Thermostat::process_HPSet(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// type 0x41 - data from the RC30 thermostat(0x10) - 14 bytes long
|
||||
// RC30Monitor(0x41), data: 80 20 00 AC 00 00 00 02 00 05 09 00 AC 00
|
||||
void Thermostat::process_RC30Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC30Monitor(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -1482,7 +1488,7 @@ void Thermostat::process_RC30Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
// type 0xA7 - for reading the mode from the RC30 thermostat (0x10) and all the installation settings
|
||||
// RC30Set(0xA7), data: 01 00 FF F6 01 06 00 01 0D 00 00 FF FF 01 02 02 02 00 00 05 1F 05 1F 01 0E 00 FF
|
||||
// RC30Set(0xA7), data: 00 00 20 02 (offset 27)
|
||||
void Thermostat::process_RC30Set(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC30Set(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -1505,7 +1511,7 @@ void Thermostat::process_RC30Set(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// type 0x40 (HC1) - for reading the operating mode from the RC30 thermostat (0x10)
|
||||
// RC30Temp(0x40), data: 01 01 02 20 24 28 2A 1E 0E 00 01 5A 32 05 4B 2D 00 28 00 3C FF 11 00 05 00
|
||||
void Thermostat::process_RC30Temp(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC30Temp(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// check to see we have a valid type. heating: 1 radiator, 2 convectors, 3 floors
|
||||
if (telegram->offset == 0 && telegram->message_data[0] == 0x00) {
|
||||
return;
|
||||
@@ -1526,7 +1532,7 @@ void Thermostat::process_RC30Temp(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// type 0x3E (HC1), 0x48 (HC2), 0x52 (HC3), 0x5C (HC4) - data from the RC35 thermostat (0x10) - 16 bytes
|
||||
void Thermostat::process_RC35Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC35Monitor(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// Check if heatingciruit is active, see https://github.com/emsesp/EMS-ESP32/issues/786
|
||||
// roomtemp is measured value or 7D00 on active hc's, zero on inactive
|
||||
uint16_t active = 0;
|
||||
@@ -1552,7 +1558,7 @@ void Thermostat::process_RC35Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// type 0x3D (HC1), 0x47 (HC2), 0x51 (HC3), 0x5B (HC4) - Working Mode Heating - for reading the mode from the RC35 thermostat (0x10)
|
||||
void Thermostat::process_RC35Set(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC35Set(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// check to see we have a valid type. heating: 1 radiator, 2 convectors, 3 floors, 4 room supply
|
||||
if (telegram->offset == 0 && telegram->message_data[0] == 0x00) {
|
||||
return;
|
||||
@@ -1600,7 +1606,7 @@ void Thermostat::process_RC35Set(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// type 0x3F (HC1), 0x49 (HC2), 0x53 (HC3), 0x5D (HC4) - timer setting
|
||||
void Thermostat::process_RC35Timer(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC35Timer(const std::shared_ptr<const Telegram> & telegram) {
|
||||
auto hc = heating_circuit(telegram);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
@@ -1671,7 +1677,7 @@ void Thermostat::process_RC35Timer(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// type 0x9A (HC1)
|
||||
void Thermostat::process_RC30Vacation(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RC30Vacation(const std::shared_ptr<const Telegram> & telegram) {
|
||||
if ((telegram->offset + telegram->message_length) > 57) {
|
||||
return;
|
||||
}
|
||||
@@ -1695,7 +1701,7 @@ void Thermostat::process_RC30Vacation(std::shared_ptr<const Telegram> telegram)
|
||||
}
|
||||
|
||||
// process_RCTime - type 0x06 - date and time from a thermostat - 12 or 15 bytes long
|
||||
void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RCTime(const std::shared_ptr<const Telegram> & telegram) {
|
||||
if (telegram->offset > 0 || telegram->message_length < 8) {
|
||||
return;
|
||||
}
|
||||
@@ -1779,7 +1785,7 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
|
||||
// process_RCError - type 0xA2 - error message - 14 bytes long
|
||||
// 10 00 A2 00 41 32 32 03 30 00 02 00 00 00 00 00 00 02 CRC
|
||||
// A 2 2 816
|
||||
void Thermostat::process_RCError(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RCError(const std::shared_ptr<const Telegram> & telegram) {
|
||||
if (telegram->offset > 0 || telegram->message_length < 5) {
|
||||
return;
|
||||
}
|
||||
@@ -1796,7 +1802,7 @@ void Thermostat::process_RCError(std::shared_ptr<const Telegram> telegram) {
|
||||
// 0x12 and 0x13 error log
|
||||
// RCErrorMessage(0x12), data: 32 32 03 30 95 0A 0A 15 18 00 01 19 32 32 03 30 95 0A 09 05 18 00 01 19 31 38 03
|
||||
// RCErrorMessage(0x12), data: 39 95 08 09 0F 19 00 01 17 64 31 03 34 95 07 10 08 00 00 01 70 (offset 27)
|
||||
void Thermostat::process_RCErrorMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RCErrorMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
if (telegram->offset > 0 || telegram->message_length < 11) {
|
||||
return;
|
||||
}
|
||||
@@ -1828,12 +1834,12 @@ void Thermostat::process_RCErrorMessage(std::shared_ptr<const Telegram> telegram
|
||||
}
|
||||
|
||||
// 0xBF
|
||||
void Thermostat::process_ErrorMessageBF(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_ErrorMessageBF(const std::shared_ptr<const Telegram> & telegram) {
|
||||
EMSESP::send_read_request(0xC0, device_id(), 0, 20); // read last errorcode
|
||||
}
|
||||
|
||||
// 0xC0 error log for RC300
|
||||
void Thermostat::process_RCErrorMessage2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Thermostat::process_RCErrorMessage2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
if (telegram->offset > 0 || telegram->message_length < 20) {
|
||||
return;
|
||||
}
|
||||
@@ -5037,8 +5043,8 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
|
||||
MAKE_CF_CB(set_redthreshold),
|
||||
12,
|
||||
22);
|
||||
register_device_value(tag, &hc->solarInfl, DeviceValueType::UINT8, FL_(solarinfl), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_solarinfl), -5, -1);
|
||||
register_device_value(tag, &hc->currSolarInfl, DeviceValueType::UINT8, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(currsolarinfl), DeviceValueUOM::DEGREES);
|
||||
register_device_value(tag, &hc->solarInfl, DeviceValueType::INT8, FL_(solarinfl), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_solarinfl), -5, 0);
|
||||
register_device_value(tag, &hc->currSolarInfl, DeviceValueType::INT8, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(currsolarinfl), DeviceValueUOM::DEGREES);
|
||||
register_device_value(tag, &hc->heatingpid, DeviceValueType::ENUM, FL_(enum_PID), FL_(heatingPID), DeviceValueUOM::NONE, MAKE_CF_CB(set_heatingpid));
|
||||
register_device_value(tag, &hc->pumpopt, DeviceValueType::BOOL, FL_(pumpopt), DeviceValueUOM::NONE, MAKE_CF_CB(set_pumpopt));
|
||||
register_device_value(tag,
|
||||
|
||||
+61
-61
@@ -408,7 +408,7 @@ class Thermostat : public EMSdevice {
|
||||
static constexpr uint8_t EMS_TYPE_RC30wwSettings = 0x3A; // RC30 ww settings
|
||||
static constexpr uint8_t EMS_TYPE_time = 0x06; // time
|
||||
|
||||
std::shared_ptr<Thermostat::HeatingCircuit> heating_circuit(std::shared_ptr<const Telegram> telegram);
|
||||
std::shared_ptr<Thermostat::HeatingCircuit> heating_circuit(const std::shared_ptr<const Telegram> & telegram);
|
||||
std::shared_ptr<Thermostat::HeatingCircuit> heating_circuit(const int8_t id);
|
||||
std::shared_ptr<Thermostat::DhwCircuit> dhw_circuit(const uint8_t offset, const bool create = false);
|
||||
|
||||
@@ -417,66 +417,66 @@ class Thermostat : public EMSdevice {
|
||||
|
||||
void add_ha_climate(std::shared_ptr<HeatingCircuit> hc) const;
|
||||
|
||||
void process_RCOutdoorTemp(std::shared_ptr<const Telegram> telegram);
|
||||
void process_IBASettings(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RCTime(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RCError(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RCErrorMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RCErrorMessage2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_ErrorMessageBF(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC35wwSettings(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC35wwTimer(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC35Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC35Set(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC35Timer(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC30Vacation(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC30Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC30Set(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC30Temp(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC30wwSettings(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC20Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC20Set(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC20Temp(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC20Timer(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC20Remote(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC20Monitor_2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC20Set_2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC10Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC10Set(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC10Set_2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_CRFMonitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_CR11Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC300Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC300Set(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC300Set2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC300Summer(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC300Summer2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC300WWmode(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC300WWmode2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC300WWtemp(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC300OutdoorTemp(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC300Settings(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC300Floordry(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC300Holiday(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC300Curve(std::shared_ptr<const Telegram> telegram);
|
||||
void process_JunkersMonitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_JunkersSet(std::shared_ptr<const Telegram> telegram);
|
||||
void process_JunkersSet2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_EasyMonitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_JunkersRemoteMonitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HybridSettings(std::shared_ptr<const Telegram> telegram);
|
||||
void process_PVSettings(std::shared_ptr<const Telegram> telegram);
|
||||
void process_Absent(std::shared_ptr<const Telegram> telegram);
|
||||
void process_JunkersSetMixer(std::shared_ptr<const Telegram> telegram);
|
||||
void process_JunkersWW(std::shared_ptr<const Telegram> telegram);
|
||||
void process_JunkersDisp(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RemoteTemp(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RemoteHumidity(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RemoteCorrection(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RemoteBattery(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HPSet(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HPMode(std::shared_ptr<const Telegram> telegram);
|
||||
void process_PID(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RCOutdoorTemp(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_IBASettings(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RCTime(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RCError(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RCErrorMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RCErrorMessage2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_ErrorMessageBF(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC35wwSettings(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC35wwTimer(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC35Monitor(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC35Set(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC35Timer(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC30Vacation(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC30Monitor(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC30Set(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC30Temp(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC30wwSettings(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC20Monitor(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC20Set(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC20Temp(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC20Timer(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC20Remote(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC20Monitor_2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC20Set_2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC10Monitor(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC10Set(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC10Set_2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_CRFMonitor(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_CR11Monitor(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC300Monitor(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC300Set(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC300Set2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC300Summer(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC300Summer2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC300WWmode(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC300WWmode2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC300WWtemp(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC300OutdoorTemp(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC300Settings(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC300Floordry(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC300Holiday(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RC300Curve(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_JunkersMonitor(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_JunkersSet(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_JunkersSet2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_EasyMonitor(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_JunkersRemoteMonitor(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HybridSettings(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_PVSettings(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_Absent(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_JunkersSetMixer(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_JunkersWW(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_JunkersDisp(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RemoteTemp(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RemoteHumidity(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RemoteCorrection(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_RemoteBattery(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HPSet(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_HPMode(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_PID(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
// internal helper functions
|
||||
bool set_mode_n(const uint8_t mode, const int8_t id);
|
||||
|
||||
@@ -51,12 +51,12 @@ Ventilation::Ventilation(uint8_t device_type, uint8_t device_id, uint8_t product
|
||||
}
|
||||
|
||||
// message 0x055C, data: 08 01 11 17
|
||||
void Ventilation::process_SetMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Ventilation::process_SetMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, bypass_, 1);
|
||||
}
|
||||
|
||||
// message 583
|
||||
void Ventilation::process_MonitorMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Ventilation::process_MonitorMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, outEx_, 0); // Fortluft
|
||||
has_update(telegram, inEx_, 7); // Abluft
|
||||
has_update(telegram, outFresh_, 13); // Außenluft
|
||||
@@ -69,25 +69,25 @@ void Ventilation::process_MonitorMessage(std::shared_ptr<const Telegram> telegra
|
||||
|
||||
// message 585 26 bytes long
|
||||
// Data: 46 46 00 00 00 77 00 03 F4 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
void Ventilation::process_BlowerMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Ventilation::process_BlowerMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, ventOutSpeed_, 0);
|
||||
has_update(telegram, ventInSpeed_, 1);
|
||||
}
|
||||
|
||||
// message 0x05D9, data: 03 9C FF
|
||||
void Ventilation::process_VOCMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Ventilation::process_VOCMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, voc_, 0);
|
||||
has_update(telegram, humidity_, 2);
|
||||
}
|
||||
|
||||
// message 0x56B
|
||||
// level 0=0, 1=1, 2=2, 3=3, 4= 4, Auto 0xFF, demand 5, sleep 6, intense 7, bypass-8, party 9, fireplace 0A
|
||||
void Ventilation::process_ModeMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Ventilation::process_ModeMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_enumupdate(telegram, mode_, 0, -1);
|
||||
}
|
||||
|
||||
// message 0x0587, data: 00 00 64 00 64 0A 00 01 54 01 00 01 00 00 00 46 00 00 00 02 00 A3 00 A3
|
||||
void Ventilation::process_BypassMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
void Ventilation::process_BypassMessage(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// has_update(telegram, bypass_closing, 0);
|
||||
// has_update(telegram, bypass_opening, 1);
|
||||
}
|
||||
|
||||
@@ -41,12 +41,12 @@ class Ventilation : public EMSdevice {
|
||||
uint8_t ventOutSpeed_;
|
||||
|
||||
// handlers: 0x056B 0x0575 0x0583 0x0585 0x0586 0x0587 0x0588 0x058D 0x058E 0x058F 0x0590 0x05CF 0x05D9 0x05E3
|
||||
void process_SetMessage(std::shared_ptr<const Telegram> telegram); // 0x55C
|
||||
void process_MonitorMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_ModeMessage(std::shared_ptr<const Telegram> telegram); // 0x56B
|
||||
void process_BlowerMessage(std::shared_ptr<const Telegram> telegram); // 0x56B
|
||||
void process_VOCMessage(std::shared_ptr<const Telegram> telegram); // 0x56B
|
||||
void process_BypassMessage(std::shared_ptr<const Telegram> telegram); // 0x56B
|
||||
void process_SetMessage(const std::shared_ptr<const Telegram> & telegram); // 0x55C
|
||||
void process_MonitorMessage(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_ModeMessage(const std::shared_ptr<const Telegram> & telegram); // 0x56B
|
||||
void process_BlowerMessage(const std::shared_ptr<const Telegram> & telegram); // 0x56B
|
||||
void process_VOCMessage(const std::shared_ptr<const Telegram> & telegram); // 0x56B
|
||||
void process_BypassMessage(const std::shared_ptr<const Telegram> & telegram); // 0x56B
|
||||
|
||||
bool set_ventMode(const char * value, const int8_t id);
|
||||
bool set_bypass(const char * value, const int8_t id);
|
||||
|
||||
+15
-15
@@ -107,7 +107,7 @@ Water::Water(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
||||
|
||||
// SM100wwTemperature - 0x07D6, dhw4: 0x07D7
|
||||
// Solar Module(0x2A) -> (0x00), (0x7D6), data: 01 C1 00 00 02 5B 01 AF 01 AD 80 00 01 90
|
||||
void Water::process_SM100wwTemperature(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_SM100wwTemperature(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwTemp_, 0); // is *10 TS17
|
||||
has_update(telegram, wwFlow_, 2); // is *10 l/min
|
||||
has_update(telegram, wwTemp2_, 4); // is *10 TS21
|
||||
@@ -120,13 +120,13 @@ void Water::process_SM100wwTemperature(std::shared_ptr<const Telegram> telegram)
|
||||
|
||||
// SM100wwStatus - 0x07AA
|
||||
// Solar Module(0x2A) -> (0x00), (0x7AA), data: 64 00 04 00 03 00 28 01 0F
|
||||
void Water::process_SM100wwStatus(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_SM100wwStatus(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwPump_, 0);
|
||||
}
|
||||
|
||||
// SM100wwParam - 0x07A6, Solar Module(0x2A) -> (0x00)
|
||||
// data: FF 05 0F 5F 00 01 3C 3C 3C 3C 28 12 46 01 3C 1E 03 07 3C 00 0F 00 05
|
||||
void Water::process_SM100wwParam(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_SM100wwParam(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwDailyTemp_, 6);
|
||||
has_update(telegram, wwHotTemp_, 7);
|
||||
has_update(telegram, wwMaxTemp_, 8);
|
||||
@@ -137,13 +137,13 @@ void Water::process_SM100wwParam(std::shared_ptr<const Telegram> telegram) {
|
||||
has_update(telegram, errorDisp_, 19);
|
||||
}
|
||||
// SM100wwParam2 - 0x07AC, Solar Module(0x2A) -> (0x00)
|
||||
void Water::process_SM100wwParam2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_SM100wwParam2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwDeltaTRet_, 1);
|
||||
}
|
||||
|
||||
// SM100wwCirc - 0x07A5
|
||||
// Solar Module(0x2A) -> (0x00), (0x7A5), data:
|
||||
void Water::process_SM100wwCirc(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_SM100wwCirc(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwCirc_, 0);
|
||||
has_update(telegram, wwCircMode_, 3);
|
||||
has_update(telegram, wwCircTc_, 4); // time controlled on/off
|
||||
@@ -151,13 +151,13 @@ void Water::process_SM100wwCirc(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// SM100wwKeepWarm - 0x7AE, keepWarm
|
||||
// Thermostat(0x10) -> Solar(0x2A), ?(0x7AE), data: FF
|
||||
void Water::process_SM100wwKeepWarm(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_SM100wwKeepWarm(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwKeepWarm_, 0);
|
||||
}
|
||||
|
||||
// SM100ValveStatus - 0x7AD, valveStatus
|
||||
// Thermostat(0x10) -> Solar(0x2A), ?(0x7AD), data:
|
||||
void Water::process_SM100ValveStatus(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_SM100ValveStatus(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwRetValve_, 1);
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ void Water::process_SM100ValveStatus(std::shared_ptr<const Telegram> telegram) {
|
||||
// data: 00 00 46 00 00 01 06 0E 06 0E 00 00 00 00 00 03 03 03 03
|
||||
// publishes single values offset 1/2(16bit), offset 5, offset 6, offset 7, offset 8, offset 9,
|
||||
// status2 = 03:"no heat", 06:"heat request", 08:"disinfecting", 09:"hold"
|
||||
void Water::process_SM100wwStatus2(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_SM100wwStatus2(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// has_update(telegram, wwFlow_, 7); // single byte, wrong see #1387
|
||||
has_update(telegram, wwStatus2_, 8);
|
||||
has_update(telegram, wwPumpMod_, 9);
|
||||
@@ -174,7 +174,7 @@ void Water::process_SM100wwStatus2(std::shared_ptr<const Telegram> telegram) {
|
||||
// SM100wwCommand - 0x07AB
|
||||
// Thermostat(0x10) -> Solar Module(0x2A), (0x7AB), data: 01 00 01
|
||||
// or dhw3 module (0x2A) -> dhw4 module(0x2B), (0x7C3), data: 01 01 00
|
||||
void Water::process_SM100wwCommand(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_SM100wwCommand(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// not implemented yet
|
||||
}
|
||||
|
||||
@@ -185,14 +185,14 @@ void Water::process_SM100wwCommand(std::shared_ptr<const Telegram> telegram) {
|
||||
// Mixer warm water loading/DHW - 0x0331, 0x0332
|
||||
// e.g. A9 00 FF 00 02 32 02 6C 00 3C 00 3C 3C 46 02 03 03 00 3C // on 0x28
|
||||
// A8 00 FF 00 02 31 02 35 00 3C 00 3C 3C 46 02 03 03 00 3C // in 0x29
|
||||
void Water::process_MMPLUSStatusMessage_WWC(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_MMPLUSStatusMessage_WWC(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwTemp_, 0); // is * 10
|
||||
has_bitupdate(telegram, wwPump_, 2, 0);
|
||||
has_update(telegram, wwStatus_, 11); // temp status
|
||||
}
|
||||
|
||||
// Config message 0x313, has to be fetched
|
||||
void Water::process_MMPLUSConfigMessage_WWC(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_MMPLUSConfigMessage_WWC(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwRequiredTemp_, 4);
|
||||
has_update(telegram, wwRedTemp_, 5);
|
||||
has_update(telegram, wwDiffTemp_, 7);
|
||||
@@ -203,7 +203,7 @@ void Water::process_MMPLUSConfigMessage_WWC(std::shared_ptr<const Telegram> tele
|
||||
// unknown, 2 examples from older threads
|
||||
// Thermostat(0x10) -> Mixer(0x28), ?(0x33B), data: 01 01 00
|
||||
// Thermostat -> Mixing Module, type 0x023B, telegram: 90 28 FF 00 02 3B 00 02 00 (CRC=68)
|
||||
void Water::process_MMPLUSSetMessage_WWC(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_MMPLUSSetMessage_WWC(const std::shared_ptr<const Telegram> & telegram) {
|
||||
}
|
||||
|
||||
// MMPLUS telegram 0x345 unknown
|
||||
@@ -216,7 +216,7 @@ void Water::process_MMPLUSSetMessage_WWC(std::shared_ptr<const Telegram> telegra
|
||||
|
||||
// 0x34 only 8 bytes long
|
||||
// Mixer(0x41) -> All(0x00), UBAMonitorWW(0x34), data: 37 02 1E 02 1E 00 00 00 00
|
||||
void Water::process_IPMMonitorWW(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_IPMMonitorWW(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, wwSelTemp_, 0);
|
||||
has_update(telegram, wwTemp_, 1);
|
||||
has_update(telegram, wwTemp2_, 3);
|
||||
@@ -224,7 +224,7 @@ void Water::process_IPMMonitorWW(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
// Mixer(0x41) -> Me(0x0B), UBAParameterWW(0x33), data: 08 FF 46 FB FF 28 FF 07 46 00 FF 00
|
||||
void Water::process_IPMParameterWW(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_IPMParameterWW(const std::shared_ptr<const Telegram> & telegram) {
|
||||
// has_update(telegram, wwActivated_, 1); // 0xFF means on
|
||||
// has_update(telegram, wwSelTemp_, 2);
|
||||
has_update(telegram, wwHystOn_, 3); // Hyst on (default -5)
|
||||
@@ -239,7 +239,7 @@ void Water::process_IPMParameterWW(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// 0x1E, only16 bit temperature
|
||||
// Mixer(0x41) -> Boiler(0x08), HydrTemp(0x1E), data: 01 D8
|
||||
void Water::process_IPMHydrTemp(std::shared_ptr<const Telegram> telegram) {
|
||||
void Water::process_IPMHydrTemp(const std::shared_ptr<const Telegram> & telegram) {
|
||||
has_update(telegram, HydrTemp_, 0);
|
||||
}
|
||||
|
||||
|
||||
+15
-15
@@ -82,23 +82,23 @@ class Water : public EMSdevice {
|
||||
uint8_t wwFlowTempOffset_; // default 40
|
||||
|
||||
|
||||
void process_SM100wwTemperature(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100wwStatus(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100wwStatus2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100wwCommand(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100wwCirc(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100wwParam(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100wwParam2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100wwKeepWarm(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100ValveStatus(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100wwTemperature(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100wwStatus(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100wwStatus2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100wwCommand(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100wwCirc(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100wwParam(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100wwParam2(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100wwKeepWarm(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_SM100ValveStatus(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
void process_MMPLUSStatusMessage_WWC(std::shared_ptr<const Telegram> telegram);
|
||||
void process_MMPLUSSetMessage_WWC(std::shared_ptr<const Telegram> telegram);
|
||||
void process_MMPLUSConfigMessage_WWC(std::shared_ptr<const Telegram> telegram);
|
||||
void process_MMPLUSStatusMessage_WWC(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_MMPLUSSetMessage_WWC(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_MMPLUSConfigMessage_WWC(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
void process_IPMMonitorWW(std::shared_ptr<const Telegram> telegram);
|
||||
void process_IPMHydrTemp(std::shared_ptr<const Telegram> telegram);
|
||||
void process_IPMParameterWW(std::shared_ptr<const Telegram> telegram);
|
||||
void process_IPMMonitorWW(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_IPMHydrTemp(const std::shared_ptr<const Telegram> & telegram);
|
||||
void process_IPMParameterWW(const std::shared_ptr<const Telegram> & telegram);
|
||||
|
||||
|
||||
bool set_wwSelTemp(const char * value, const int8_t id);
|
||||
|
||||
@@ -25,10 +25,14 @@ uint16_t WebAPIService::api_fails_ = 0;
|
||||
|
||||
WebAPIService::WebAPIService(AsyncWebServer * server, SecurityManager * securityManager)
|
||||
: _securityManager(securityManager) {
|
||||
AsyncCallbackJsonWebHandler * jsonHandler = new AsyncCallbackJsonWebHandler(EMSESP_API_SERVICE_PATH);
|
||||
jsonHandler->setMethod(HTTP_POST | HTTP_GET);
|
||||
jsonHandler->onRequest([this](AsyncWebServerRequest * request, JsonVariant json) { webAPIService(request, json); });
|
||||
server->addHandler(jsonHandler);
|
||||
// parse() does its own per-request admin check (with notoken_api), so no predicate.
|
||||
// /api also matches /api/<device>/<entity> via the route's backward-compatible URI matcher.
|
||||
securityManager->addEndpoint(
|
||||
server,
|
||||
EMSESP_API_SERVICE_PATH,
|
||||
AuthenticationPredicates::NONE_REQUIRED,
|
||||
[this](AsyncWebServerRequest * request, JsonVariant json) { webAPIService(request, json); },
|
||||
HTTP_POST | HTTP_GET);
|
||||
}
|
||||
|
||||
// POST|GET api/
|
||||
@@ -108,7 +112,7 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject input) {
|
||||
EMSESP::system_.refreshHeapMem();
|
||||
|
||||
// output json buffer
|
||||
auto response = new AsyncJsonResponse();
|
||||
auto response = new PsramAsyncJsonResponse();
|
||||
|
||||
// add more mem if needed - won't be needed in ArduinoJson 7
|
||||
// while (!response->getSize()) {
|
||||
|
||||
@@ -27,7 +27,7 @@ WebActivityService::WebActivityService(AsyncWebServer * server, SecurityManager
|
||||
}
|
||||
|
||||
void WebActivityService::webActivityService(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new PsramAsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
JsonArray statsJson = root["stats"].to<JsonArray>();
|
||||
|
||||
@@ -69,7 +69,7 @@ void WebCustomEntity::read(WebCustomEntity & webEntity, JsonObject root) {
|
||||
StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & webCustomEntity) {
|
||||
// reset everything to start fresh
|
||||
Command::erase_device_commands(EMSdevice::DeviceType::CUSTOM);
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
for (CustomEntityItem & entityItem : webCustomEntity.customEntityItems) {
|
||||
if (entityItem.raw) {
|
||||
delete[] entityItem.raw;
|
||||
@@ -453,7 +453,7 @@ void WebCustomEntityService::publish_single(CustomEntityItem & entity) {
|
||||
snprintf(topic, sizeof(topic), "%s_data/%s", F_(custom), entity.name);
|
||||
}
|
||||
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
JsonObject output = doc.to<JsonObject>();
|
||||
render_value(output, entity, true);
|
||||
Mqtt::queue_publish(topic, output["value"].as<std::string>());
|
||||
@@ -475,7 +475,7 @@ void WebCustomEntityService::publish(const bool force) {
|
||||
}
|
||||
}
|
||||
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
JsonObject output = doc.to<JsonObject>();
|
||||
bool ha_created = ha_configdone_;
|
||||
|
||||
@@ -486,7 +486,7 @@ void WebCustomEntityService::publish(const bool force) {
|
||||
render_value(output, entityItem);
|
||||
// create HA config
|
||||
if (Mqtt::ha_enabled() && !ha_configdone_) {
|
||||
JsonDocument config;
|
||||
JsonDocument config(PSRAM_DOC);
|
||||
config["~"] = Mqtt::base();
|
||||
|
||||
char stat_t[50];
|
||||
@@ -566,7 +566,7 @@ uint8_t WebCustomEntityService::count_entities() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
JsonObject output = doc.to<JsonObject>();
|
||||
uint8_t count = 0;
|
||||
|
||||
@@ -705,7 +705,7 @@ void WebCustomEntityService::fetch() {
|
||||
}
|
||||
|
||||
// called on process telegram, read from telegram
|
||||
bool WebCustomEntityService::get_value(std::shared_ptr<const Telegram> telegram) {
|
||||
bool WebCustomEntityService::get_value(const std::shared_ptr<const Telegram> & telegram) {
|
||||
bool has_change = false;
|
||||
// read-length of BOOL, INT8, UINT8, INT16, UINT16, UINT24, TIME, UINT32
|
||||
const uint8_t len[] = {1, 1, 1, 2, 2, 3, 3, 4};
|
||||
|
||||
@@ -62,7 +62,7 @@ class WebCustomEntityService : public StatefulService<WebCustomEntity> {
|
||||
bool command_setvalue(const char * value, const int8_t id, const char * name);
|
||||
bool get_value_info(JsonObject output, const char * cmd);
|
||||
void get_value_json(JsonObject output, CustomEntityItem const & entity);
|
||||
bool get_value(std::shared_ptr<const Telegram> telegram);
|
||||
bool get_value(const std::shared_ptr<const Telegram> & telegram);
|
||||
void fetch();
|
||||
void render_value(JsonObject output, CustomEntityItem const & entity, const bool useVal = false, const bool web = false, const bool add_uom = false);
|
||||
void show_values(JsonObject output);
|
||||
|
||||
@@ -212,7 +212,7 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request) {
|
||||
JsonArray output = response->getRoot();
|
||||
emsdevice->generate_values_web_customization(output);
|
||||
#else
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
JsonArray output = doc.to<JsonArray>();
|
||||
emsdevice->generate_values_web_customization(output);
|
||||
#endif
|
||||
|
||||
@@ -58,7 +58,7 @@ WebDataService::WebDataService(AsyncWebServer * server, SecurityManager * securi
|
||||
// this is used in the Devices page and contains all EMS device information
|
||||
// /coreData endpoint
|
||||
void WebDataService::core_data(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new PsramAsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
// list is already sorted by device type
|
||||
@@ -70,7 +70,7 @@ void WebDataService::core_data(AsyncWebServerRequest * request) {
|
||||
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
|
||||
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
|
||||
@@ -104,7 +104,7 @@ void WebDataService::core_data(AsyncWebServerRequest * request) {
|
||||
// sensor data - sends back to web
|
||||
// /sensorData endpoint
|
||||
void WebDataService::sensor_data(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new PsramAsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
// temperature sensors
|
||||
@@ -176,7 +176,7 @@ void WebDataService::device_data(AsyncWebServerRequest * request) {
|
||||
if (request->hasParam(F_(id))) {
|
||||
id = Helpers::atoint(request->getParam(F_(id))->value().c_str()); // get id from url
|
||||
|
||||
auto * response = new AsyncMessagePackResponse();
|
||||
auto * response = new PsramAsyncMessagePackResponse();
|
||||
|
||||
// check size
|
||||
// while (!response) {
|
||||
@@ -217,6 +217,9 @@ void WebDataService::device_data(AsyncWebServerRequest * request) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// no matching device and not CUSTOM_UID: we never called request->send(response),
|
||||
// so AsyncWebServer never took ownership. Delete it ourselves to avoid leaking.
|
||||
delete response;
|
||||
}
|
||||
|
||||
// invalid
|
||||
@@ -269,7 +272,7 @@ void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVar
|
||||
return;
|
||||
}
|
||||
// create JSON for output
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new PsramAsyncJsonResponse(false);
|
||||
JsonObject output = response->getRoot();
|
||||
// the data could be in any format, but we need string
|
||||
// authenticated is always true
|
||||
|
||||
+16
-15
@@ -32,9 +32,6 @@ WebLogService::WebLogService(AsyncWebServer * server, SecurityManager * security
|
||||
[this](AsyncWebServerRequest * request, JsonVariant json) { getSetValues(request, json); },
|
||||
HTTP_ANY);
|
||||
|
||||
// Add authentication filter to EventSource
|
||||
// EventSource (SSE) cannot use custom headers, so authentication is done via URL parameter
|
||||
// events_.setFilter(securityManager->filterRequest(AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
server->addHandler(&events_);
|
||||
}
|
||||
|
||||
@@ -168,32 +165,34 @@ char * WebLogService::messagetime(char * out, const uint64_t t, const size_t buf
|
||||
|
||||
// send to web eventsource
|
||||
void WebLogService::transmit(const QueuedLogMessage & message) {
|
||||
JsonDocument jsonDocument;
|
||||
// JsonDocument is PSRAM-backed so its internal node/string pool is on PSRAM
|
||||
JsonDocument jsonDocument(PSRAM_DOC);
|
||||
|
||||
JsonObject logEvent = jsonDocument.to<JsonObject>();
|
||||
char time_string[25];
|
||||
|
||||
logEvent["t"] = messagetime(time_string, message.uptime_, sizeof(time_string));
|
||||
logEvent["l"] = message.level_; // .content_->level;
|
||||
logEvent["l"] = message.level_;
|
||||
logEvent["i"] = message.id_;
|
||||
logEvent["n"] = message.name_; // content_->name;
|
||||
logEvent["m"] = message.text_; // content_->text;
|
||||
logEvent["n"] = message.name_;
|
||||
logEvent["m"] = message.text_;
|
||||
|
||||
size_t len = measureJson(jsonDocument) + 1;
|
||||
char * buffer = new char[len];
|
||||
if (buffer) {
|
||||
serializeJson(jsonDocument, buffer, len);
|
||||
events_.send(buffer, "message", message.id_);
|
||||
log_message_id_tail_ = message.id_;
|
||||
// Reuse a PSRAM-backed scratch buffer
|
||||
const size_t len = measureJson(jsonDocument);
|
||||
if (scratch_buf_.capacity() < len + 1) {
|
||||
scratch_buf_.reserve(len + 1);
|
||||
}
|
||||
delete[] buffer;
|
||||
scratch_buf_.resize(len);
|
||||
serializeJson(jsonDocument, scratch_buf_.data(), len + 1);
|
||||
events_.send(scratch_buf_.c_str(), "message", message.id_);
|
||||
log_message_id_tail_ = message.id_;
|
||||
}
|
||||
|
||||
// sets the values after a POST
|
||||
void WebLogService::getSetValues(AsyncWebServerRequest * request, JsonVariant json) {
|
||||
if ((request->method() == HTTP_GET) || (!json.is<JsonObject>())) {
|
||||
// GET - return the values
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new PsramAsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
root["level"] = level_;
|
||||
root["max_messages"] = maximum_log_messages_;
|
||||
@@ -209,6 +208,7 @@ void WebLogService::getSetValues(AsyncWebServerRequest * request, JsonVariant js
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// POST - write the settings
|
||||
level_ = json["level"];
|
||||
maximum_log_messages_ = json["max_messages"];
|
||||
@@ -232,6 +232,7 @@ void WebLogService::getSetValues(AsyncWebServerRequest * request, JsonVariant js
|
||||
settings.weblog_buffer = maximum_log_messages_;
|
||||
return StateUpdateResult::CHANGED;
|
||||
});
|
||||
|
||||
request->send(200); // OK
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,9 @@ class WebLogService : public uuid::log::Handler {
|
||||
unsigned long log_message_id_tail_ = 0; // last event shown on the screen after fetch
|
||||
bool compact_ = true;
|
||||
uuid::log::Level level_ = uuid::log::Level::INFO;
|
||||
|
||||
// PSRAM-backed scratch buffer reused across every SSE log event
|
||||
stringPSRAM scratch_buf_;
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -50,7 +50,7 @@ void WebModulesService::loop() {
|
||||
// it adds data to an empty 'root' json object
|
||||
// and also calls when the Modules web page is refreshed/loaded
|
||||
void WebModules::read(WebModules & webModules, JsonObject root) {
|
||||
JsonDocument doc_modules;
|
||||
JsonDocument doc_modules(PSRAM_DOC);
|
||||
auto root_modules = doc_modules.to<JsonObject>();
|
||||
moduleLibrary.list(root_modules); // get list the external library modules, put in a json object
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ void WebSchedulerService::publish(const bool force) {
|
||||
}
|
||||
}
|
||||
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
JsonObject output = doc.to<JsonObject>();
|
||||
bool ha_created = ha_configdone_;
|
||||
for (const ScheduleItem & scheduleItem : *scheduleItems_) {
|
||||
@@ -275,7 +275,7 @@ void WebSchedulerService::publish(const bool force) {
|
||||
|
||||
// create HA config
|
||||
if (Mqtt::ha_enabled() && !ha_configdone_) {
|
||||
JsonDocument config;
|
||||
JsonDocument config(PSRAM_DOC);
|
||||
config["~"] = Mqtt::base();
|
||||
|
||||
char stat_t[50];
|
||||
|
||||
@@ -414,7 +414,7 @@ void WebSettingsService::board_profile(AsyncWebServerRequest * request) {
|
||||
if (request->hasParam("boardProfile")) {
|
||||
std::string board_profile = request->getParam("boardProfile")->value().c_str();
|
||||
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new PsramAsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
// 0=led, 1=dallas, 2=rx, 3=tx, 4=button, 5=phy_type, 6=eth_power, 7=eth_phy_addr, 8=eth_clock_mode, 9=led_type
|
||||
|
||||
@@ -47,7 +47,7 @@ WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * se
|
||||
void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
|
||||
EMSESP::system_.refreshHeapMem(); // refresh free heap and max alloc heap
|
||||
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
auto * response = new PsramAsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
//
|
||||
@@ -187,7 +187,7 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
|
||||
|
||||
// generic action handler - as a POST
|
||||
void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json) {
|
||||
auto * response = new AsyncJsonResponse();
|
||||
auto * response = new PsramAsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
// param is optional - https://arduinojson.org/news/2024/09/18/arduinojson-7-2/
|
||||
@@ -433,7 +433,7 @@ bool WebStatusService::refresh_versions_cache() {
|
||||
return false;
|
||||
}
|
||||
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
DeserializationError err = deserializeJson(doc, http.getStream());
|
||||
http.end();
|
||||
if (err) {
|
||||
@@ -539,7 +539,7 @@ bool WebStatusService::exportData(JsonObject root, std::string & type) {
|
||||
// action = getCustomSupport
|
||||
// reads any upload customSupport.json file and sends to to Help page to be shown as Guest
|
||||
bool WebStatusService::getCustomSupport(JsonObject root) {
|
||||
JsonDocument doc;
|
||||
JsonDocument doc(PSRAM_DOC);
|
||||
|
||||
#if defined(EMSESP_STANDALONE)
|
||||
// dummy test data for "test api3"
|
||||
|
||||
Reference in New Issue
Block a user