This commit is contained in:
MichaelDvP
2023-09-19 14:31:25 +02:00
43 changed files with 320 additions and 248 deletions

View File

@@ -36,7 +36,7 @@ There are breaking changes between 3.5.x and earlier versions of 3.6.0. Please r
## Added ## Added
- Workaround for better Domoticz MQTT intergration? [#904](https://github.com/emsesp/EMS-ESP32/issues/904) - Workaround for better Domoticz MQTT integration? [#904](https://github.com/emsesp/EMS-ESP32/issues/904)
- Show MAC address without connecting to network enhancement [#933](https://github.com/emsesp/EMS-ESP32/issues/933) - Show MAC address without connecting to network enhancement [#933](https://github.com/emsesp/EMS-ESP32/issues/933)
- Warn user in WebUI of unsaved changes [#911](https://github.com/emsesp/EMS-ESP32/issues/911) - Warn user in WebUI of unsaved changes [#911](https://github.com/emsesp/EMS-ESP32/issues/911)
- Detect old Tado thermostat, device-id 0x19, no entities - Detect old Tado thermostat, device-id 0x19, no entities
@@ -202,7 +202,7 @@ There are breaking changes between 3.5.x and earlier versions of 3.6.0. Please r
- WebUI optimizations, updated look&feel and better performance [#124](https://github.com/emsesp/EMS-ESP32/issues/124) - WebUI optimizations, updated look&feel and better performance [#124](https://github.com/emsesp/EMS-ESP32/issues/124)
- Auto refresh of WebUI after successful firmware upload [#178](https://github.com/emsesp/EMS-ESP32/issues/178) - Auto refresh of WebUI after successful firmware upload [#178](https://github.com/emsesp/EMS-ESP32/issues/178)
- New Customization Service in WebUI. First feature is the ability to enable/disabled Enitites (device values) from EMS devices [#206](https://github.com/emsesp/EMS-ESP32/issues/206) - New Customization Service in WebUI. First feature is the ability to enable/disabled Entities (device values) from EMS devices [#206](https://github.com/emsesp/EMS-ESP32/issues/206)
- Option to disable Telnet Console [#209](https://github.com/emsesp/EMS-ESP32/issues/209) - Option to disable Telnet Console [#209](https://github.com/emsesp/EMS-ESP32/issues/209)
- Added Hide SSID, Max Clients and Preferred Channel to Access Point - Added Hide SSID, Max Clients and Preferred Channel to Access Point
- Merged in MichaelDvP's changes like Fahrenheit conversion, publish single (for IOBroker) and a few other critical optimizations - Merged in MichaelDvP's changes like Fahrenheit conversion, publish single (for IOBroker) and a few other critical optimizations

View File

@@ -1583,8 +1583,8 @@ Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,bo
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,mintempsilent,min outside temp for silent mode,int (>=-126<=126),C,true,number.boiler_min_outside_temp_for_silent_mode,number.boiler_mintempsilent Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,mintempsilent,min outside temp for silent mode,int (>=-126<=126),C,true,number.boiler_min_outside_temp_for_silent_mode,number.boiler_mintempsilent
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,tempparmode,outside temp parallel mode,int (>=-126<=126),C,true,number.boiler_outside_temp_parallel_mode,number.boiler_tempparmode Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,tempparmode,outside temp parallel mode,int (>=-126<=126),C,true,number.boiler_outside_temp_parallel_mode,number.boiler_tempparmode
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,auxheatmix,aux heater mixing valve,int (>=-100<=100),%,false,sensor.boiler_aux_heater_mixing_valve,sensor.boiler_auxheatmix Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,auxheatmix,aux heater mixing valve,int (>=-100<=100),%,false,sensor.boiler_aux_heater_mixing_valve,sensor.boiler_auxheatmix
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,tempdiffheat,temp diff TC3/TC0 heat,uint (>=3<=10),K,true,number.boiler_temp_diff_TC3/TC0_heat,number.boiler_tempdiffheat Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,tempdiffheat,temp diff TC3/TC0 heat,uint (>=2<=10),K,true,number.boiler_temp_diff_TC3/TC0_heat,number.boiler_tempdiffheat
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,tempdiffcool,temp diff TC3/TC0 cool,uint (>=3<=10),K,true,number.boiler_temp_diff_TC3/TC0_cool,number.boiler_tempdiffcool Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,tempdiffcool,temp diff TC3/TC0 cool,uint (>=2<=10),K,true,number.boiler_temp_diff_TC3/TC0_cool,number.boiler_tempdiffcool
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,vpcooling,valve/pump cooling,boolean, ,true,switch.boiler_valve/pump_cooling,switch.boiler_vpcooling Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,vpcooling,valve/pump cooling,boolean, ,true,switch.boiler_valve/pump_cooling,switch.boiler_vpcooling
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,heatcable,heating cable,boolean, ,true,switch.boiler_heating_cable,switch.boiler_heatcable Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,heatcable,heating cable,boolean, ,true,switch.boiler_heating_cable,switch.boiler_heatcable
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,vc0valve,VC0 valve,boolean, ,true,switch.boiler_VC0_valve,switch.boiler_vc0valve Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,vc0valve,VC0 valve,boolean, ,true,switch.boiler_VC0_valve,switch.boiler_vc0valve
@@ -1768,8 +1768,8 @@ Geo 5xx,boiler,173,silentto,silent mode to,uint (>=0<=3810),minutes,true,number.
Geo 5xx,boiler,173,mintempsilent,min outside temp for silent mode,int (>=-126<=126),C,true,number.boiler_min_outside_temp_for_silent_mode,number.boiler_mintempsilent Geo 5xx,boiler,173,mintempsilent,min outside temp for silent mode,int (>=-126<=126),C,true,number.boiler_min_outside_temp_for_silent_mode,number.boiler_mintempsilent
Geo 5xx,boiler,173,tempparmode,outside temp parallel mode,int (>=-126<=126),C,true,number.boiler_outside_temp_parallel_mode,number.boiler_tempparmode Geo 5xx,boiler,173,tempparmode,outside temp parallel mode,int (>=-126<=126),C,true,number.boiler_outside_temp_parallel_mode,number.boiler_tempparmode
Geo 5xx,boiler,173,auxheatmix,aux heater mixing valve,int (>=-100<=100),%,false,sensor.boiler_aux_heater_mixing_valve,sensor.boiler_auxheatmix Geo 5xx,boiler,173,auxheatmix,aux heater mixing valve,int (>=-100<=100),%,false,sensor.boiler_aux_heater_mixing_valve,sensor.boiler_auxheatmix
Geo 5xx,boiler,173,tempdiffheat,temp diff TC3/TC0 heat,uint (>=3<=10),K,true,number.boiler_temp_diff_TC3/TC0_heat,number.boiler_tempdiffheat Geo 5xx,boiler,173,tempdiffheat,temp diff TC3/TC0 heat,uint (>=2<=10),K,true,number.boiler_temp_diff_TC3/TC0_heat,number.boiler_tempdiffheat
Geo 5xx,boiler,173,tempdiffcool,temp diff TC3/TC0 cool,uint (>=3<=10),K,true,number.boiler_temp_diff_TC3/TC0_cool,number.boiler_tempdiffcool Geo 5xx,boiler,173,tempdiffcool,temp diff TC3/TC0 cool,uint (>=2<=10),K,true,number.boiler_temp_diff_TC3/TC0_cool,number.boiler_tempdiffcool
Geo 5xx,boiler,173,vpcooling,valve/pump cooling,boolean, ,true,switch.boiler_valve/pump_cooling,switch.boiler_vpcooling Geo 5xx,boiler,173,vpcooling,valve/pump cooling,boolean, ,true,switch.boiler_valve/pump_cooling,switch.boiler_vpcooling
Geo 5xx,boiler,173,heatcable,heating cable,boolean, ,true,switch.boiler_heating_cable,switch.boiler_heatcable Geo 5xx,boiler,173,heatcable,heating cable,boolean, ,true,switch.boiler_heating_cable,switch.boiler_heatcable
Geo 5xx,boiler,173,vc0valve,VC0 valve,boolean, ,true,switch.boiler_VC0_valve,switch.boiler_vc0valve Geo 5xx,boiler,173,vc0valve,VC0 valve,boolean, ,true,switch.boiler_VC0_valve,switch.boiler_vc0valve
@@ -2635,8 +2635,9 @@ UI800,thermostat,4,noreducetemp,no reduce below temperature,int (>=-126<=126),C,
UI800,thermostat,4,reducetemp,off/reduce switch temperature,int (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp UI800,thermostat,4,reducetemp,off/reduce switch temperature,int (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp
UI800,thermostat,4,wwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_wwprio UI800,thermostat,4,wwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_wwprio
UI800,thermostat,4,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling UI800,thermostat,4,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling
UI800,thermostat,4,coolingon,cooling,boolean, ,false,binary_sensor.thermostat_hc1_cooling,binary_sensor.thermostat_hc1_coolingon
UI800,thermostat,4,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode UI800,thermostat,4,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode
UI800,thermostat,4,dewoffset,dew point offset,uint (>=0<=254),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset UI800,thermostat,4,dewoffset,dew point offset,uint (>=2<=10),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset
UI800,thermostat,4,roomtempdiff,room temp difference,uint (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff UI800,thermostat,4,roomtempdiff,room temp difference,uint (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff
UI800,thermostat,4,hpminflowtemp,HP min. flow temp.,uint (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp UI800,thermostat,4,hpminflowtemp,HP min. flow temp.,uint (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp
RC10,thermostat,65,errorcode,error code,string, ,false,sensor.thermostat_error_code,sensor.thermostat_errorcode RC10,thermostat,65,errorcode,error code,string, ,false,sensor.thermostat_error_code,sensor.thermostat_errorcode
@@ -2987,8 +2988,9 @@ RC200/CW100,thermostat,157,noreducetemp,no reduce below temperature,int (>=-126<
RC200/CW100,thermostat,157,reducetemp,off/reduce switch temperature,int (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp RC200/CW100,thermostat,157,reducetemp,off/reduce switch temperature,int (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp
RC200/CW100,thermostat,157,wwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_wwprio RC200/CW100,thermostat,157,wwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_wwprio
RC200/CW100,thermostat,157,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling RC200/CW100,thermostat,157,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling
RC200/CW100,thermostat,157,coolingon,cooling,boolean, ,false,binary_sensor.thermostat_hc1_cooling,binary_sensor.thermostat_hc1_coolingon
RC200/CW100,thermostat,157,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode RC200/CW100,thermostat,157,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode
RC200/CW100,thermostat,157,dewoffset,dew point offset,uint (>=0<=254),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset RC200/CW100,thermostat,157,dewoffset,dew point offset,uint (>=2<=10),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset
RC200/CW100,thermostat,157,roomtempdiff,room temp difference,uint (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff RC200/CW100,thermostat,157,roomtempdiff,room temp difference,uint (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff
RC200/CW100,thermostat,157,hpminflowtemp,HP min. flow temp.,uint (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp RC200/CW100,thermostat,157,hpminflowtemp,HP min. flow temp.,uint (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,errorcode,error code,string, ,false,sensor.thermostat_error_code,sensor.thermostat_errorcode RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,errorcode,error code,string, ,false,sensor.thermostat_error_code,sensor.thermostat_errorcode
@@ -3057,8 +3059,9 @@ RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,noreducetem
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,reducetemp,off/reduce switch temperature,int (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,reducetemp,off/reduce switch temperature,int (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,wwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_wwprio RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,wwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_wwprio
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,coolingon,cooling,boolean, ,false,binary_sensor.thermostat_hc1_cooling,binary_sensor.thermostat_hc1_coolingon
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,dewoffset,dew point offset,uint (>=0<=254),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,dewoffset,dew point offset,uint (>=2<=10),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,roomtempdiff,room temp difference,uint (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,roomtempdiff,room temp difference,uint (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,hpminflowtemp,HP min. flow temp.,uint (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,hpminflowtemp,HP min. flow temp.,uint (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp
RC100/Moduline 1000/1010,thermostat,165,errorcode,error code,string, ,false,sensor.thermostat_error_code,sensor.thermostat_errorcode RC100/Moduline 1000/1010,thermostat,165,errorcode,error code,string, ,false,sensor.thermostat_error_code,sensor.thermostat_errorcode
@@ -3127,8 +3130,9 @@ RC100/Moduline 1000/1010,thermostat,165,noreducetemp,no reduce below temperature
RC100/Moduline 1000/1010,thermostat,165,reducetemp,off/reduce switch temperature,int (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp RC100/Moduline 1000/1010,thermostat,165,reducetemp,off/reduce switch temperature,int (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp
RC100/Moduline 1000/1010,thermostat,165,wwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_wwprio RC100/Moduline 1000/1010,thermostat,165,wwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_wwprio
RC100/Moduline 1000/1010,thermostat,165,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling RC100/Moduline 1000/1010,thermostat,165,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling
RC100/Moduline 1000/1010,thermostat,165,coolingon,cooling,boolean, ,false,binary_sensor.thermostat_hc1_cooling,binary_sensor.thermostat_hc1_coolingon
RC100/Moduline 1000/1010,thermostat,165,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode RC100/Moduline 1000/1010,thermostat,165,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode
RC100/Moduline 1000/1010,thermostat,165,dewoffset,dew point offset,uint (>=0<=254),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset RC100/Moduline 1000/1010,thermostat,165,dewoffset,dew point offset,uint (>=2<=10),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset
RC100/Moduline 1000/1010,thermostat,165,roomtempdiff,room temp difference,uint (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff RC100/Moduline 1000/1010,thermostat,165,roomtempdiff,room temp difference,uint (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff
RC100/Moduline 1000/1010,thermostat,165,hpminflowtemp,HP min. flow temp.,uint (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp RC100/Moduline 1000/1010,thermostat,165,hpminflowtemp,HP min. flow temp.,uint (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp
Rego 2000/3000,thermostat,172,errorcode,error code,string, ,false,sensor.thermostat_error_code,sensor.thermostat_errorcode Rego 2000/3000,thermostat,172,errorcode,error code,string, ,false,sensor.thermostat_error_code,sensor.thermostat_errorcode
@@ -3197,8 +3201,9 @@ Rego 2000/3000,thermostat,172,noreducetemp,no reduce below temperature,int (>=-1
Rego 2000/3000,thermostat,172,reducetemp,off/reduce switch temperature,int (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp Rego 2000/3000,thermostat,172,reducetemp,off/reduce switch temperature,int (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp
Rego 2000/3000,thermostat,172,wwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_wwprio Rego 2000/3000,thermostat,172,wwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_wwprio
Rego 2000/3000,thermostat,172,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling Rego 2000/3000,thermostat,172,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling
Rego 2000/3000,thermostat,172,coolingon,cooling,boolean, ,false,binary_sensor.thermostat_hc1_cooling,binary_sensor.thermostat_hc1_coolingon
Rego 2000/3000,thermostat,172,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode Rego 2000/3000,thermostat,172,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode
Rego 2000/3000,thermostat,172,dewoffset,dew point offset,uint (>=0<=254),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset Rego 2000/3000,thermostat,172,dewoffset,dew point offset,uint (>=2<=10),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset
Rego 2000/3000,thermostat,172,roomtempdiff,room temp difference,uint (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff Rego 2000/3000,thermostat,172,roomtempdiff,room temp difference,uint (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff
Rego 2000/3000,thermostat,172,hpminflowtemp,HP min. flow temp.,uint (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp Rego 2000/3000,thermostat,172,hpminflowtemp,HP min. flow temp.,uint (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp
Comfort RF,thermostat,215,errorcode,error code,string, ,false,sensor.thermostat_error_code,sensor.thermostat_errorcode Comfort RF,thermostat,215,errorcode,error code,string, ,false,sensor.thermostat_error_code,sensor.thermostat_errorcode
@@ -3294,8 +3299,9 @@ Rego 3000/UI800,thermostat,253,noreducetemp,no reduce below temperature,int (>=-
Rego 3000/UI800,thermostat,253,reducetemp,off/reduce switch temperature,int (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp Rego 3000/UI800,thermostat,253,reducetemp,off/reduce switch temperature,int (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp
Rego 3000/UI800,thermostat,253,wwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_wwprio Rego 3000/UI800,thermostat,253,wwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_wwprio
Rego 3000/UI800,thermostat,253,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling Rego 3000/UI800,thermostat,253,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling
Rego 3000/UI800,thermostat,253,coolingon,cooling,boolean, ,false,binary_sensor.thermostat_hc1_cooling,binary_sensor.thermostat_hc1_coolingon
Rego 3000/UI800,thermostat,253,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode Rego 3000/UI800,thermostat,253,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode
Rego 3000/UI800,thermostat,253,dewoffset,dew point offset,uint (>=0<=254),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset Rego 3000/UI800,thermostat,253,dewoffset,dew point offset,uint (>=2<=10),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset
Rego 3000/UI800,thermostat,253,roomtempdiff,room temp difference,uint (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff Rego 3000/UI800,thermostat,253,roomtempdiff,room temp difference,uint (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff
Rego 3000/UI800,thermostat,253,hpminflowtemp,HP min. flow temp.,uint (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp Rego 3000/UI800,thermostat,253,hpminflowtemp,HP min. flow temp.,uint (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp
ES72/RC20,thermostat,66,errorcode,error code,string, ,false,sensor.thermostat_error_code,sensor.thermostat_errorcode ES72/RC20,thermostat,66,errorcode,error code,string, ,false,sensor.thermostat_error_code,sensor.thermostat_errorcode
Can't render this file because it is too large.

View File

@@ -23,16 +23,16 @@
"@emotion/react": "^11.11.1", "@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0", "@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.14.9", "@mui/icons-material": "^5.14.9",
"@mui/material": "^5.14.9", "@mui/material": "^5.14.10",
"@preact/compat": "^17.1.2", "@preact/compat": "^17.1.2",
"@prefresh/vite": "^2.4.1", "@prefresh/vite": "^2.4.1",
"@table-library/react-table-library": "4.1.7", "@table-library/react-table-library": "4.1.7",
"@types/lodash-es": "^4.17.9", "@types/lodash-es": "^4.17.9",
"@types/node": "^20.6.2", "@types/node": "^20.6.2",
"@types/react": "^18.2.21", "@types/react": "^18.2.22",
"@types/react-dom": "^18.2.7", "@types/react-dom": "^18.2.7",
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",
"alova": "^2.11.1", "alova": "^2.12.0",
"async-validator": "^4.2.5", "async-validator": "^4.2.5",
"history": "^5.3.0", "history": "^5.3.0",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
@@ -53,8 +53,8 @@
"@babel/core": "^7.22.20", "@babel/core": "^7.22.20",
"@preact/preset-vite": "^2.5.0", "@preact/preset-vite": "^2.5.0",
"@types/babel__core": "^7", "@types/babel__core": "^7",
"@typescript-eslint/eslint-plugin": "^6.7.0", "@typescript-eslint/eslint-plugin": "^6.7.2",
"@typescript-eslint/parser": "^6.7.0", "@typescript-eslint/parser": "^6.7.2",
"eslint": "^8.49.0", "eslint": "^8.49.0",
"eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^17.1.0", "eslint-config-airbnb-typescript": "^17.1.0",

View File

@@ -65,7 +65,9 @@ const SettingsCustomization: FC = () => {
const { data: devices } = useRequest(EMSESP.readDevices); const { data: devices } = useRequest(EMSESP.readDevices);
const { send: writeCustomEntities } = useRequest((data) => EMSESP.writeCustomEntities(data), { immediate: false }); const { send: writeCustomizationEntities } = useRequest((data) => EMSESP.writeCustomizationEntities(data), {
immediate: false
});
const { send: readDeviceEntities, onSuccess: onSuccess } = useRequest((data) => EMSESP.readDeviceEntities(data), { const { send: readDeviceEntities, onSuccess: onSuccess } = useRequest((data) => EMSESP.readDeviceEntities(data), {
initialData: [], initialData: [],
@@ -312,7 +314,7 @@ const SettingsCustomization: FC = () => {
return; return;
} }
await writeCustomEntities({ id: devices?.devices[selectedDevice].i, entity_ids: masked_entities }).catch( await writeCustomizationEntities({ id: devices?.devices[selectedDevice].i, entity_ids: masked_entities }).catch(
(error) => { (error) => {
if (error.message === 'Reboot required') { if (error.message === 'Reboot required') {
setRestartNeeded(true); setRestartNeeded(true);

View File

@@ -33,12 +33,12 @@ const SettingsEntities: FC = () => {
data: entities, data: entities,
send: fetchEntities, send: fetchEntities,
error error
} = useRequest(EMSESP.readEntities, { } = useRequest(EMSESP.readCustomEntities, {
initialData: [], initialData: [],
force: true force: true
}); });
const { send: writeEntities } = useRequest((data) => EMSESP.writeEntities(data), { immediate: false }); const { send: writeEntities } = useRequest((data) => EMSESP.writeCustomEntities(data), { immediate: false });
function hasEntityChanged(ei: EntityItem) { function hasEntityChanged(ei: EntityItem) {
return ( return (

View File

@@ -62,7 +62,7 @@ export const readDeviceEntities = (id: number) =>
}); });
export const readDevices = () => alovaInstance.Get<Devices>('/rest/devices'); export const readDevices = () => alovaInstance.Get<Devices>('/rest/devices');
export const resetCustomizations = () => alovaInstance.Post('/rest/resetCustomizations'); export const resetCustomizations = () => alovaInstance.Post('/rest/resetCustomizations');
export const writeCustomEntities = (data: any) => alovaInstance.Post('/rest/customEntities', data); export const writeCustomizationEntities = (data: any) => alovaInstance.Post('/rest/customizationEntities', data);
// SettingsScheduler // SettingsScheduler
export const readSchedule = () => export const readSchedule = () =>
@@ -85,8 +85,8 @@ export const readSchedule = () =>
export const writeSchedule = (data: any) => alovaInstance.Post('/rest/schedule', data); export const writeSchedule = (data: any) => alovaInstance.Post('/rest/schedule', data);
// SettingsEntities // SettingsEntities
export const readEntities = () => export const readCustomEntities = () =>
alovaInstance.Get<EntityItem[]>('/rest/entities', { alovaInstance.Get<EntityItem[]>('/rest/customentities', {
name: 'entities', name: 'entities',
transformData(data: any) { transformData(data: any) {
return data.entities.map((ei: EntityItem) => ({ return data.entities.map((ei: EntityItem) => ({
@@ -104,4 +104,4 @@ export const readEntities = () =>
})); }));
} }
}); });
export const writeEntities = (data: any) => alovaInstance.Post('/rest/entities', data); export const writeCustomEntities = (data: any) => alovaInstance.Post('/rest/customentities', data);

View File

@@ -1022,14 +1022,14 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@mui/base@npm:5.0.0-beta.15": "@mui/base@npm:5.0.0-beta.16":
version: 5.0.0-beta.15 version: 5.0.0-beta.16
resolution: "@mui/base@npm:5.0.0-beta.15" resolution: "@mui/base@npm:5.0.0-beta.16"
dependencies: dependencies:
"@babel/runtime": ^7.22.15 "@babel/runtime": ^7.22.15
"@floating-ui/react-dom": ^2.0.2 "@floating-ui/react-dom": ^2.0.2
"@mui/types": ^7.2.4 "@mui/types": ^7.2.4
"@mui/utils": ^5.14.9 "@mui/utils": ^5.14.10
"@popperjs/core": ^2.11.8 "@popperjs/core": ^2.11.8
clsx: ^2.0.0 clsx: ^2.0.0
prop-types: ^15.8.1 prop-types: ^15.8.1
@@ -1040,14 +1040,14 @@ __metadata:
peerDependenciesMeta: peerDependenciesMeta:
"@types/react": "@types/react":
optional: true optional: true
checksum: 95f6bc53333635cba0046d74ef73cef1103dfa845d8c6ba461443ea5408739d5c9f300aa5bf0c1e63fc7ad4f6170e7854588557b7491a60c53b29a88710c12ad checksum: 035cdb9bba59394d2f937d3f17a0a5d5121a269542129cc99f5b82e4e773d5b31dc6b7fbe1fcacf8b744ff7a8ad9640fb30c27e283f89770f802147fd9d50962
languageName: node languageName: node
linkType: hard linkType: hard
"@mui/core-downloads-tracker@npm:^5.14.9": "@mui/core-downloads-tracker@npm:^5.14.10":
version: 5.14.9 version: 5.14.10
resolution: "@mui/core-downloads-tracker@npm:5.14.9" resolution: "@mui/core-downloads-tracker@npm:5.14.10"
checksum: aaf8575c65d34bae8c97cb7fe612c7d26b2fff6c09a71241008f92883173c6a9ac5b2beb5003b565594e0ce618c1d81083ef4da18c62c50ab909984e17526a33 checksum: 165751152a5fa490cee7d5919030e12a489c4e23ba253ecd14d78dcda07fea49d715ee656976854716f95d37fd89fa68f34e115f73e6bfed872bd1ba153ecd31
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1067,16 +1067,16 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@mui/material@npm:^5.14.9": "@mui/material@npm:^5.14.10":
version: 5.14.9 version: 5.14.10
resolution: "@mui/material@npm:5.14.9" resolution: "@mui/material@npm:5.14.10"
dependencies: dependencies:
"@babel/runtime": ^7.22.15 "@babel/runtime": ^7.22.15
"@mui/base": 5.0.0-beta.15 "@mui/base": 5.0.0-beta.16
"@mui/core-downloads-tracker": ^5.14.9 "@mui/core-downloads-tracker": ^5.14.10
"@mui/system": ^5.14.9 "@mui/system": ^5.14.10
"@mui/types": ^7.2.4 "@mui/types": ^7.2.4
"@mui/utils": ^5.14.9 "@mui/utils": ^5.14.10
"@types/react-transition-group": ^4.4.6 "@types/react-transition-group": ^4.4.6
clsx: ^2.0.0 clsx: ^2.0.0
csstype: ^3.1.2 csstype: ^3.1.2
@@ -1096,16 +1096,16 @@ __metadata:
optional: true optional: true
"@types/react": "@types/react":
optional: true optional: true
checksum: 92366b60600986e5fdbc6f788e7c3f9855da1ab92635a93f81e217126f057fbe095a34b956e56dded3bdaf98fddc2bfad0a32ccd8292a287d8dde80bd604876c checksum: 82500d343c71ae22f8e9bfe5632cdf71092d15502574f20c42d44c33828f87dbb864be84f31d0dadc0f304d70fc8854581e2b4779b23cd2d753208e497acfc3d
languageName: node languageName: node
linkType: hard linkType: hard
"@mui/private-theming@npm:^5.14.9": "@mui/private-theming@npm:^5.14.10":
version: 5.14.9 version: 5.14.10
resolution: "@mui/private-theming@npm:5.14.9" resolution: "@mui/private-theming@npm:5.14.10"
dependencies: dependencies:
"@babel/runtime": ^7.22.15 "@babel/runtime": ^7.22.15
"@mui/utils": ^5.14.9 "@mui/utils": ^5.14.10
prop-types: ^15.8.1 prop-types: ^15.8.1
peerDependencies: peerDependencies:
"@types/react": ^17.0.0 || ^18.0.0 "@types/react": ^17.0.0 || ^18.0.0
@@ -1113,19 +1113,18 @@ __metadata:
peerDependenciesMeta: peerDependenciesMeta:
"@types/react": "@types/react":
optional: true optional: true
checksum: 30eec37e14d46d763c5c307e8b51b89d93222fda4cf6a82500dce28c65932155cade59e47aaa0c1c6e407ab7acdf1956e438be6a36c4343d36af4c62270f1295 checksum: 0ef27687f575f09d8167db5dbc6bda0a0e19d603a3d00c8ff9d3f2544e5c55292b01be0317782640e0072bb19916015920c01e693bd36bd28068775a05a54b6d
languageName: node languageName: node
linkType: hard linkType: hard
"@mui/styled-engine@npm:^5.14.9": "@mui/styled-engine@npm:^5.14.10":
version: 5.14.9 version: 5.14.10
resolution: "@mui/styled-engine@npm:5.14.9" resolution: "@mui/styled-engine@npm:5.14.10"
dependencies: dependencies:
"@babel/runtime": ^7.22.15 "@babel/runtime": ^7.22.15
"@emotion/cache": ^11.11.0 "@emotion/cache": ^11.11.0
csstype: ^3.1.2 csstype: ^3.1.2
prop-types: ^15.8.1 prop-types: ^15.8.1
react: ^18.2.0
peerDependencies: peerDependencies:
"@emotion/react": ^11.4.1 "@emotion/react": ^11.4.1
"@emotion/styled": ^11.3.0 "@emotion/styled": ^11.3.0
@@ -1135,19 +1134,19 @@ __metadata:
optional: true optional: true
"@emotion/styled": "@emotion/styled":
optional: true optional: true
checksum: 6ca263d1fcbc604898113f5e3d7b7f0a5592a30a0ca4e40d60ddcf8cf300bed6a042aff9140264da99f71a6661a412810a60fe8f28221e33d69fe34b9914e4b4 checksum: 0f7184abfc81ed7a82c2256d3bab3efdf202d4e761e4cd98e67bafc7fe7d96176a6cac3c54b156fc4e161ca830294356eef28970f584b62c1a4d6ec3d6256dfe
languageName: node languageName: node
linkType: hard linkType: hard
"@mui/system@npm:^5.14.9": "@mui/system@npm:^5.14.10":
version: 5.14.9 version: 5.14.10
resolution: "@mui/system@npm:5.14.9" resolution: "@mui/system@npm:5.14.10"
dependencies: dependencies:
"@babel/runtime": ^7.22.15 "@babel/runtime": ^7.22.15
"@mui/private-theming": ^5.14.9 "@mui/private-theming": ^5.14.10
"@mui/styled-engine": ^5.14.9 "@mui/styled-engine": ^5.14.10
"@mui/types": ^7.2.4 "@mui/types": ^7.2.4
"@mui/utils": ^5.14.9 "@mui/utils": ^5.14.10
clsx: ^2.0.0 clsx: ^2.0.0
csstype: ^3.1.2 csstype: ^3.1.2
prop-types: ^15.8.1 prop-types: ^15.8.1
@@ -1163,7 +1162,7 @@ __metadata:
optional: true optional: true
"@types/react": "@types/react":
optional: true optional: true
checksum: cd74cfcb8f5e3f3344d1791a18aad22df03d966ee1ae1dd590ed291eeb0d474622d48a272695b9570e4eac399e6004291ef83313d4084212e60409361a0913bd checksum: daf86070f786dbb70b997b0dbe11485634407bb60b18219d2929649e92486f9097c3c17d658ca3cd266d5708b658fc8bead6d6b53d63995c25bf76445d3d4919
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1179,21 +1178,21 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@mui/utils@npm:^5.14.9": "@mui/utils@npm:^5.14.10":
version: 5.14.9 version: 5.14.10
resolution: "@mui/utils@npm:5.14.9" resolution: "@mui/utils@npm:5.14.10"
dependencies: dependencies:
"@babel/runtime": ^7.22.15 "@babel/runtime": ^7.22.15
"@types/prop-types": ^15.7.5
prop-types: ^15.8.1 prop-types: ^15.8.1
react-is: ^18.2.0 react-is: ^18.2.0
peerDependencies: peerDependencies:
"@types/react": ^17.0.0 || ^18.0.0 "@types/react": ^17.0.0 || ^18.0.0
react: ^17.0.0 || ^18.0.0 react: ^17.0.0 || ^18.0.0
react-dom: ^17.0.0 || ^18.0.0
peerDependenciesMeta: peerDependenciesMeta:
"@types/react": "@types/react":
optional: true optional: true
checksum: b78fd9aaf49967a117fcb398198ef7a18eff23a92b6529982bb0fe913a3dd6545371c995bd4b8376eed425e9de36157091c5211a7e6d141429d8651d6e9184af checksum: fb778e1a5fb97920b9457667d910f6055bb0a22bec26f011b4e269e9646e46f6c4800e00b80feab8f8ec79242afd4c342437671a0389b6ac807e14a32338dd24
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1613,6 +1612,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@types/prop-types@npm:^15.7.5":
version: 15.7.6
resolution: "@types/prop-types@npm:15.7.6"
checksum: 2871c61f662b91c7366204ae6801bc0a88e1e7e8d48962f7f2143cf0f0f4dbbe9a57978063729d15ffd7fad13bd648cc70ff019b7a3fc8f4b84f72fb259b4dfb
languageName: node
linkType: hard
"@types/react-dom@npm:^18.2.7": "@types/react-dom@npm:^18.2.7":
version: 18.2.7 version: 18.2.7
resolution: "@types/react-dom@npm:18.2.7" resolution: "@types/react-dom@npm:18.2.7"
@@ -1652,7 +1658,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@types/react@npm:*, @types/react@npm:^18.2.21": "@types/react@npm:*":
version: 18.2.21 version: 18.2.21
resolution: "@types/react@npm:18.2.21" resolution: "@types/react@npm:18.2.21"
dependencies: dependencies:
@@ -1663,6 +1669,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@types/react@npm:^18.2.22":
version: 18.2.22
resolution: "@types/react@npm:18.2.22"
dependencies:
"@types/prop-types": "*"
"@types/scheduler": "*"
csstype: ^3.0.2
checksum: ac481c8a85c95cf1eb0a09c3c7e609428f12ff61d57ac0e9c8dd94b6dcfde44306c4f41d98f83e9554ed33a66e605ba35687c0a38d367e7d77dd2bdea9d6145e
languageName: node
linkType: hard
"@types/scheduler@npm:*": "@types/scheduler@npm:*":
version: 0.16.3 version: 0.16.3
resolution: "@types/scheduler@npm:0.16.3" resolution: "@types/scheduler@npm:0.16.3"
@@ -1677,15 +1694,15 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/eslint-plugin@npm:^6.7.0": "@typescript-eslint/eslint-plugin@npm:^6.7.2":
version: 6.7.0 version: 6.7.2
resolution: "@typescript-eslint/eslint-plugin@npm:6.7.0" resolution: "@typescript-eslint/eslint-plugin@npm:6.7.2"
dependencies: dependencies:
"@eslint-community/regexpp": ^4.5.1 "@eslint-community/regexpp": ^4.5.1
"@typescript-eslint/scope-manager": 6.7.0 "@typescript-eslint/scope-manager": 6.7.2
"@typescript-eslint/type-utils": 6.7.0 "@typescript-eslint/type-utils": 6.7.2
"@typescript-eslint/utils": 6.7.0 "@typescript-eslint/utils": 6.7.2
"@typescript-eslint/visitor-keys": 6.7.0 "@typescript-eslint/visitor-keys": 6.7.2
debug: ^4.3.4 debug: ^4.3.4
graphemer: ^1.4.0 graphemer: ^1.4.0
ignore: ^5.2.4 ignore: ^5.2.4
@@ -1698,44 +1715,44 @@ __metadata:
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
checksum: f78a8de1311776bb3dd614f4a7d9cb098601ea0ccc1bec2317518794c473a813ccc58262304b999170720c16c280b56b928ba98aaa1c6a2ff9e73b7a7f9a831a checksum: ce0c1f0cc56cdf0d442439288a8d3530fff224b93840d7bd862da38521865f60516aa6a006d77e48dc91c296915e27c1b9131bff5d7495c9e848280f53e4dd03
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/parser@npm:^6.7.0": "@typescript-eslint/parser@npm:^6.7.2":
version: 6.7.0 version: 6.7.2
resolution: "@typescript-eslint/parser@npm:6.7.0" resolution: "@typescript-eslint/parser@npm:6.7.2"
dependencies: dependencies:
"@typescript-eslint/scope-manager": 6.7.0 "@typescript-eslint/scope-manager": 6.7.2
"@typescript-eslint/types": 6.7.0 "@typescript-eslint/types": 6.7.2
"@typescript-eslint/typescript-estree": 6.7.0 "@typescript-eslint/typescript-estree": 6.7.2
"@typescript-eslint/visitor-keys": 6.7.0 "@typescript-eslint/visitor-keys": 6.7.2
debug: ^4.3.4 debug: ^4.3.4
peerDependencies: peerDependencies:
eslint: ^7.0.0 || ^8.0.0 eslint: ^7.0.0 || ^8.0.0
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
checksum: 2b15d9b1624b68ea0e17f401809d1a6e5f212ff922c45a0e63bf9bc584c1a5608a461f1c5f3d781f2060556ec512b7d957d5162848c957b96f54f485e128a93b checksum: dde49a291d15e4eba0f286de40bd6ebcec4167979220bba5c30ff94a3c5f6f36ce2d04e7df94204a84b8cb99c261252b972500e2c46733a55d8c8c325937eeca
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/scope-manager@npm:6.7.0": "@typescript-eslint/scope-manager@npm:6.7.2":
version: 6.7.0 version: 6.7.2
resolution: "@typescript-eslint/scope-manager@npm:6.7.0" resolution: "@typescript-eslint/scope-manager@npm:6.7.2"
dependencies: dependencies:
"@typescript-eslint/types": 6.7.0 "@typescript-eslint/types": 6.7.2
"@typescript-eslint/visitor-keys": 6.7.0 "@typescript-eslint/visitor-keys": 6.7.2
checksum: c4cfb790c61eec7e1b6309eb6cc7d863b4d3dfc84e844dfee9fe21ddc86e68b4fde1f70ef5f26ce7c0f66b73f410d51c2f80b97dc697b77aef1f54b9fbbd23c4 checksum: 806cc2c10edb3324763bbedfa922147bf38b114da432c5feb11886f1b7f9f498b014cb1c26fbd9ea18ead3245abe268e29ea120962fd463de0a950ca69f620c4
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/type-utils@npm:6.7.0": "@typescript-eslint/type-utils@npm:6.7.2":
version: 6.7.0 version: 6.7.2
resolution: "@typescript-eslint/type-utils@npm:6.7.0" resolution: "@typescript-eslint/type-utils@npm:6.7.2"
dependencies: dependencies:
"@typescript-eslint/typescript-estree": 6.7.0 "@typescript-eslint/typescript-estree": 6.7.2
"@typescript-eslint/utils": 6.7.0 "@typescript-eslint/utils": 6.7.2
debug: ^4.3.4 debug: ^4.3.4
ts-api-utils: ^1.0.1 ts-api-utils: ^1.0.1
peerDependencies: peerDependencies:
@@ -1743,23 +1760,23 @@ __metadata:
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
checksum: 40eff7625ae7a9d32cf3e413891196ab32ef6472eef563e191fa388b3f717515e43395de34e80c763a9e4e36e71494df19a04ad3d0bb4db1df5e8833c5c6b337 checksum: 4ca831cbeeb221ed318d9761b1e3652bc55c391029cfc588ff5535b43542fb454684ef62f21f7c27c60dd75daea6c79320c177a501646b78bee5403c67027df3
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/types@npm:6.7.0": "@typescript-eslint/types@npm:6.7.2":
version: 6.7.0 version: 6.7.2
resolution: "@typescript-eslint/types@npm:6.7.0" resolution: "@typescript-eslint/types@npm:6.7.2"
checksum: 7d79d5dafa8003de00721e0c6983dc24bfee249b9d2e072044f3a4ec5d85aa90c7d095531dc081f4da607e2ad8aa67a6f401fa840b5a3b3eea05d8ac6bb6a006 checksum: d5daf0051609b1bbe5a0d43a130647c23e2951f2443307d3b5dd323a71e3bedd32f3263a4bb5fdfaa8ad8a78c865ba3d5b606695cb27d85c412d2a8931c5d9a6
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/typescript-estree@npm:6.7.0": "@typescript-eslint/typescript-estree@npm:6.7.2":
version: 6.7.0 version: 6.7.2
resolution: "@typescript-eslint/typescript-estree@npm:6.7.0" resolution: "@typescript-eslint/typescript-estree@npm:6.7.2"
dependencies: dependencies:
"@typescript-eslint/types": 6.7.0 "@typescript-eslint/types": 6.7.2
"@typescript-eslint/visitor-keys": 6.7.0 "@typescript-eslint/visitor-keys": 6.7.2
debug: ^4.3.4 debug: ^4.3.4
globby: ^11.1.0 globby: ^11.1.0
is-glob: ^4.0.3 is-glob: ^4.0.3
@@ -1768,34 +1785,34 @@ __metadata:
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
checksum: 61a9a6988e706c23796bb2a3dce063c216c78cdca62a54268c54a8ebe784794791fde52cf07204f1c026e4d06dee3efd732138a93bd5e6f6d87bc51c0c9c13ca checksum: 80205c23807ea0d508189de4326ec18dccfcaf4bccd4304c9fc8b49504083df3d001af16733272487197ffd5d499e6c8d0e0f2eb9d2d61423e163b6d4787a7bb
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/utils@npm:6.7.0": "@typescript-eslint/utils@npm:6.7.2":
version: 6.7.0 version: 6.7.2
resolution: "@typescript-eslint/utils@npm:6.7.0" resolution: "@typescript-eslint/utils@npm:6.7.2"
dependencies: dependencies:
"@eslint-community/eslint-utils": ^4.4.0 "@eslint-community/eslint-utils": ^4.4.0
"@types/json-schema": ^7.0.12 "@types/json-schema": ^7.0.12
"@types/semver": ^7.5.0 "@types/semver": ^7.5.0
"@typescript-eslint/scope-manager": 6.7.0 "@typescript-eslint/scope-manager": 6.7.2
"@typescript-eslint/types": 6.7.0 "@typescript-eslint/types": 6.7.2
"@typescript-eslint/typescript-estree": 6.7.0 "@typescript-eslint/typescript-estree": 6.7.2
semver: ^7.5.4 semver: ^7.5.4
peerDependencies: peerDependencies:
eslint: ^7.0.0 || ^8.0.0 eslint: ^7.0.0 || ^8.0.0
checksum: c8ca9c3c078d7adc2da241046821627c6283a23aece46ee9f6c2464217190efb7838e6a669ca8b194693a6975c2dcbbda45e1376959c30a6be6953ab19d1268d checksum: c1e5af3efc47bb5bff0d48fc73bf87e951b1393144e4ea072c3eec4346fe425a22c3261ede4ab9c9115bf15ad6c26c7c645522a12163e71d3df910e5005a87ba
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/visitor-keys@npm:6.7.0": "@typescript-eslint/visitor-keys@npm:6.7.2":
version: 6.7.0 version: 6.7.2
resolution: "@typescript-eslint/visitor-keys@npm:6.7.0" resolution: "@typescript-eslint/visitor-keys@npm:6.7.2"
dependencies: dependencies:
"@typescript-eslint/types": 6.7.0 "@typescript-eslint/types": 6.7.2
eslint-visitor-keys: ^3.4.1 eslint-visitor-keys: ^3.4.1
checksum: 44405ba105d91f47387346c025bfbbefec111b3d7effcb97e47ac179bbc8717ccb3f129d9fa0545c3f56916706362f1b6f0c2ff2bad73b58cfdf2c71ed8cf982 checksum: e6b35338a98fcf6719388a2dce7ae476622f6fa37b0d5e3607de260100a72b8cb86e76b73b16a9a3c434e8386e1ea394cd946add1e4ce712d3b8a7fd0e221830
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1808,7 +1825,7 @@ __metadata:
"@emotion/react": ^11.11.1 "@emotion/react": ^11.11.1
"@emotion/styled": ^11.11.0 "@emotion/styled": ^11.11.0
"@mui/icons-material": ^5.14.9 "@mui/icons-material": ^5.14.9
"@mui/material": ^5.14.9 "@mui/material": ^5.14.10
"@preact/compat": ^17.1.2 "@preact/compat": ^17.1.2
"@preact/preset-vite": ^2.5.0 "@preact/preset-vite": ^2.5.0
"@prefresh/vite": ^2.4.1 "@prefresh/vite": ^2.4.1
@@ -1816,12 +1833,12 @@ __metadata:
"@types/babel__core": ^7 "@types/babel__core": ^7
"@types/lodash-es": ^4.17.9 "@types/lodash-es": ^4.17.9
"@types/node": ^20.6.2 "@types/node": ^20.6.2
"@types/react": ^18.2.21 "@types/react": ^18.2.22
"@types/react-dom": ^18.2.7 "@types/react-dom": ^18.2.7
"@types/react-router-dom": ^5.3.3 "@types/react-router-dom": ^5.3.3
"@typescript-eslint/eslint-plugin": ^6.7.0 "@typescript-eslint/eslint-plugin": ^6.7.2
"@typescript-eslint/parser": ^6.7.0 "@typescript-eslint/parser": ^6.7.2
alova: ^2.11.1 alova: ^2.12.0
async-validator: ^4.2.5 async-validator: ^4.2.5
eslint: ^8.49.0 eslint: ^8.49.0
eslint-config-airbnb: ^19.0.4 eslint-config-airbnb: ^19.0.4
@@ -1923,10 +1940,10 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"alova@npm:^2.11.1": "alova@npm:^2.12.0":
version: 2.11.1 version: 2.12.0
resolution: "alova@npm:2.11.1" resolution: "alova@npm:2.12.0"
checksum: 1ef0cc44985495611728c9b9326d9c40382e45d3e0ba1c5aa87634e58b75f7b66f0b7bdb77fa60e0d57450db91dc31ed0cfe2cbd42dc707811ef3ae97bc3b374 checksum: a08f829d9d4ab8ca3bea2bd619a7c0a8a027cc1178096425bd97f74de2c495f8d70a795276976506702a749cb8c170df9436f45f6f4a524d9e20e90bf098099b
languageName: node languageName: node
linkType: hard linkType: hard
@@ -5302,7 +5319,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"react@npm:^18.2.0, react@npm:latest": "react@npm:latest":
version: 18.2.0 version: 18.2.0
resolution: "react@npm:18.2.0" resolution: "react@npm:18.2.0"
dependencies: dependencies:

View File

@@ -347,7 +347,7 @@ const EMSESP_BOARDPROFILE_ENDPOINT = REST_ENDPOINT_ROOT + 'boardProfile';
const EMSESP_WRITE_VALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeDeviceValue'; const EMSESP_WRITE_VALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeDeviceValue';
const EMSESP_WRITE_SENSOR_ENDPOINT = REST_ENDPOINT_ROOT + 'writeTemperatureSensor'; const EMSESP_WRITE_SENSOR_ENDPOINT = REST_ENDPOINT_ROOT + 'writeTemperatureSensor';
const EMSESP_WRITE_ANALOG_ENDPOINT = REST_ENDPOINT_ROOT + 'writeAnalogSensor'; const EMSESP_WRITE_ANALOG_ENDPOINT = REST_ENDPOINT_ROOT + 'writeAnalogSensor';
const EMSESP_CUSTOM_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'customEntities'; const EMSESP_CUSTOMIZATION_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'customizationEntities';
const EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT = REST_ENDPOINT_ROOT + 'resetCustomizations'; const EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT = REST_ENDPOINT_ROOT + 'resetCustomizations';
const EMSESP_WRITE_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule'; const EMSESP_WRITE_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule';
const EMSESP_WRITE_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'entities'; const EMSESP_WRITE_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'entities';
@@ -2355,7 +2355,7 @@ function updateMask(entity, de, dd) {
} }
} }
rest_server.post(EMSESP_CUSTOM_ENTITIES_ENDPOINT, (req, res) => { rest_server.post(EMSESP_CUSTOMIZATION_ENTITIES_ENDPOINT, (req, res) => {
const id = req.body.id; const id = req.body.id;
console.log('customization id = ' + id); console.log('customization id = ' + id);
console.log(req.body.entity_ids); console.log(req.body.entity_ids);

0
scripts/api_test.http Normal file → Executable file
View File

0
scripts/app-tls-size.py Normal file → Executable file
View File

0
scripts/boot_app0.bin Normal file → Executable file
View File

0
scripts/bootloader_dio_40m.bin Normal file → Executable file
View File

0
scripts/build_interface.py Normal file → Executable file
View File

0
scripts/clang-format.py Normal file → Executable file
View File

0
scripts/clang-tidy.py Normal file → Executable file
View File

View File

3
scripts/dump_entities.py Normal file → Executable file
View File

@@ -1,6 +1,7 @@
# strips out lines between two markers # strips out lines between two markers
# pipe a file into, for example: # pipe a file into, for example:
# make clean; make; echo "test dump" | ./emsesp | python3 ./scripts/dump_entities.py # make clean; make; echo "test entity_dump" | ./emsesp | python3 ./scripts/dump_entities.py > dump_entities.csv
# see dump_entities.sh
import fileinput import fileinput
with fileinput.input() as f_input: with fileinput.input() as f_input:

0
scripts/dump_entities.sh Normal file → Executable file
View File

0
scripts/espota.py Normal file → Executable file
View File

0
scripts/esptool.py Normal file → Executable file
View File

0
scripts/helpers.py Normal file → Executable file
View File

0
scripts/partitions.bin Normal file → Executable file
View File

0
scripts/rename_fw.py Normal file → Executable file
View File

0
scripts/run_memory_test.py Normal file → Executable file
View File

0
scripts/run_sonar.sh Normal file → Executable file
View File

0
scripts/upload_esp32.py Normal file → Executable file
View File

0
scripts/upload_fw.py Normal file → Executable file
View File

View File

@@ -300,7 +300,7 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
// see if there is a command registered // see if there is a command registered
auto cf = find_command(device_type, device_id, cmd); auto cf = find_command(device_type, device_id, cmd);
// check if its a call to and end-point to a device // check if its a call to an end-point of a device
// this is used to fetch the attributes of the device entity, or call a command directly // this is used to fetch the attributes of the device entity, or call a command directly
bool single_command = (!value || !strlen(value)); bool single_command = (!value || !strlen(value));
if (single_command) { if (single_command) {
@@ -546,8 +546,9 @@ bool Command::device_has_commands(const uint8_t device_type) {
} }
if (device_type == EMSdevice::DeviceType::CUSTOM) { if (device_type == EMSdevice::DeviceType::CUSTOM) {
return true; // we always have info // if there are no custom entities, don't error but return a message
// return (EMSESP::webEntityService.count_entities() != 0); return true;
// return (EMSESP::webCustomEntityService.count_entities() != 0);
} }
if (device_type == EMSdevice::DeviceType::TEMPERATURESENSOR) { if (device_type == EMSdevice::DeviceType::TEMPERATURESENSOR) {
@@ -612,7 +613,7 @@ void Command::show_all(uuid::console::Shell & shell) {
show(shell, EMSdevice::DeviceType::SYSTEM, true); show(shell, EMSdevice::DeviceType::SYSTEM, true);
// show Custom // show Custom
// if (EMSESP::webEntityService.has_commands()) { // if (EMSESP::webCustomEntityService.has_commands()) {
shell.print(COLOR_BOLD_ON); shell.print(COLOR_BOLD_ON);
shell.print(COLOR_YELLOW); shell.print(COLOR_YELLOW);
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::CUSTOM)); shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::CUSTOM));

View File

@@ -1074,7 +1074,7 @@ void EMSdevice::set_climate_minmax(uint8_t tag, int16_t min, uint32_t max) {
// set mask per device entity based on the id which is prefixed with the 2 char hex mask value // set mask per device entity based on the id which is prefixed with the 2 char hex mask value
// returns true if the entity has a mask set (not 0 the default) // returns true if the entity has a mask set (not 0 the default)
void EMSdevice::setCustomEntity(const std::string & entity_id) { void EMSdevice::setCustomizationEntity(const std::string & entity_id) {
for (auto & dv : devicevalues_) { for (auto & dv : devicevalues_) {
char entity_name[70]; char entity_name[70];
if (dv.tag < DeviceValueTAG::TAG_HC1) { if (dv.tag < DeviceValueTAG::TAG_HC1) {
@@ -1126,7 +1126,7 @@ void EMSdevice::setCustomEntity(const std::string & entity_id) {
} }
// populate a string vector with entities that have masks set or have a custom name // populate a string vector with entities that have masks set or have a custom name
void EMSdevice::getCustomEntities(std::vector<std::string> & entity_ids) { void EMSdevice::getCustomizationEntities(std::vector<std::string> & entity_ids) {
for (const auto & dv : devicevalues_) { for (const auto & dv : devicevalues_) {
char name[100]; char name[100];
name[0] = '\0'; name[0] = '\0';

View File

@@ -207,8 +207,8 @@ class EMSdevice {
void add_handlers_ignored(const uint16_t handler); void add_handlers_ignored(const uint16_t handler);
void set_climate_minmax(uint8_t tag, int16_t min, uint32_t max); void set_climate_minmax(uint8_t tag, int16_t min, uint32_t max);
void setCustomEntity(const std::string & entity_id); void setCustomizationEntity(const std::string & entity_id);
void getCustomEntities(std::vector<std::string> & entity_ids); 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); void register_telegram_type(const uint16_t telegram_type_id, const char * telegram_type_name, bool fetch, const process_function_p cb);
bool handle_telegram(std::shared_ptr<const Telegram> telegram); bool handle_telegram(std::shared_ptr<const Telegram> telegram);

View File

@@ -32,13 +32,13 @@ ESP8266React EMSESP::esp8266React(&webServer, &dummyFS);
WebSettingsService EMSESP::webSettingsService = WebSettingsService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager()); WebSettingsService EMSESP::webSettingsService = WebSettingsService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
WebCustomizationService EMSESP::webCustomizationService = WebCustomizationService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager()); WebCustomizationService EMSESP::webCustomizationService = WebCustomizationService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
WebSchedulerService EMSESP::webSchedulerService = WebSchedulerService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager()); WebSchedulerService EMSESP::webSchedulerService = WebSchedulerService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
WebEntityService EMSESP::webEntityService = WebEntityService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager()); WebCustomEntityService EMSESP::webCustomEntityService = WebCustomEntityService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
#else #else
ESP8266React EMSESP::esp8266React(&webServer, &LittleFS); ESP8266React EMSESP::esp8266React(&webServer, &LittleFS);
WebSettingsService EMSESP::webSettingsService = WebSettingsService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager()); WebSettingsService EMSESP::webSettingsService = WebSettingsService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
WebCustomizationService EMSESP::webCustomizationService = WebCustomizationService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager()); WebCustomizationService EMSESP::webCustomizationService = WebCustomizationService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
WebSchedulerService EMSESP::webSchedulerService = WebSchedulerService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager()); WebSchedulerService EMSESP::webSchedulerService = WebSchedulerService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
WebEntityService EMSESP::webEntityService = WebEntityService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager()); WebCustomEntityService EMSESP::webCustomEntityService = WebCustomEntityService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
#endif #endif
WebStatusService EMSESP::webStatusService = WebStatusService(&webServer, EMSESP::esp8266React.getSecurityManager()); WebStatusService EMSESP::webStatusService = WebStatusService(&webServer, EMSESP::esp8266React.getSecurityManager());
@@ -482,7 +482,7 @@ void EMSESP::publish_all(bool force) {
publish_device_values(EMSdevice::DeviceType::MIXER); publish_device_values(EMSdevice::DeviceType::MIXER);
publish_other_values(); // switch and heat pump, ... publish_other_values(); // switch and heat pump, ...
webSchedulerService.publish(); webSchedulerService.publish();
webEntityService.publish(); webCustomEntityService.publish();
publish_sensor_values(true); // includes temperature and analog sensors publish_sensor_values(true); // includes temperature and analog sensors
system_.send_heartbeat(); system_.send_heartbeat();
} }
@@ -515,7 +515,7 @@ void EMSESP::publish_all_loop() {
case 5: case 5:
publish_other_values(); // switch and heat pump publish_other_values(); // switch and heat pump
webSchedulerService.publish(true); webSchedulerService.publish(true);
webEntityService.publish(true); webCustomEntityService.publish(true);
break; break;
case 6: case 6:
publish_sensor_values(true, true); publish_sensor_values(true, true);
@@ -606,7 +606,7 @@ void EMSESP::publish_other_values() {
// publish_device_values(EMSdevice::DeviceType::ALERT); // publish_device_values(EMSdevice::DeviceType::ALERT);
// publish_device_values(EMSdevice::DeviceType::PUMP); // publish_device_values(EMSdevice::DeviceType::PUMP);
// publish_device_values(EMSdevice::DeviceType::GENERIC); // publish_device_values(EMSdevice::DeviceType::GENERIC);
webEntityService.publish(); webCustomEntityService.publish();
} }
// publish both the temperature and analog sensor values // publish both the temperature and analog sensor values
@@ -658,7 +658,8 @@ void EMSESP::publish_response(std::shared_ptr<const Telegram> telegram) {
buffer = nullptr; buffer = nullptr;
} }
// builds json with the detail of each value, for a specific EMS device type or the temperature sensor // builds json with the detail of each value,
// for a specific EMS device type or the sensors, scheduler and custom entities
bool EMSESP::get_device_value_info(JsonObject & root, const char * cmd, const int8_t id, const uint8_t devicetype) { bool EMSESP::get_device_value_info(JsonObject & root, const char * cmd, const int8_t id, const uint8_t devicetype) {
for (const auto & emsdevice : emsdevices) { for (const auto & emsdevice : emsdevices) {
if (emsdevice->device_type() == devicetype) { if (emsdevice->device_type() == devicetype) {
@@ -685,7 +686,7 @@ bool EMSESP::get_device_value_info(JsonObject & root, const char * cmd, const in
// own entities // own entities
if (devicetype == DeviceType::CUSTOM) { if (devicetype == DeviceType::CUSTOM) {
return EMSESP::webEntityService.get_value_info(root, cmd); return EMSESP::webCustomEntityService.get_value_info(root, cmd);
} }
char error[100]; char error[100];
@@ -896,7 +897,7 @@ bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
} }
// Check for custom entities reding this telegram // Check for custom entities reding this telegram
webEntityService.get_value(telegram); webCustomEntityService.get_value(telegram);
// check for common types, like the Version(0x02) // check for common types, like the Version(0x02)
if (telegram->type_id == EMSdevice::EMS_TYPE_VERSION) { if (telegram->type_id == EMSdevice::EMS_TYPE_VERSION) {
@@ -1415,7 +1416,7 @@ void EMSESP::scheduled_fetch_values() {
return; return;
} }
} }
webEntityService.fetch(); webCustomEntityService.fetch();
no = 0; no = 0;
} }
} }
@@ -1499,7 +1500,7 @@ void EMSESP::start() {
webCustomizationService.begin(); // load the customizations webCustomizationService.begin(); // load the customizations
webSchedulerService.begin(); // load the scheduler events webSchedulerService.begin(); // load the scheduler events
webEntityService.begin(); // load the custom telegram reads webCustomEntityService.begin(); // load the custom telegram reads
// start telnet service if it's enabled // start telnet service if it's enabled
// default idle is 10 minutes, default write timeout is 0 (automatic) // default idle is 10 minutes, default write timeout is 0 (automatic)

View File

@@ -47,7 +47,7 @@
#include "web/WebSchedulerService.h" #include "web/WebSchedulerService.h"
#include "web/WebAPIService.h" #include "web/WebAPIService.h"
#include "web/WebLogService.h" #include "web/WebLogService.h"
#include "web/WebEntityService.h" #include "web/WebCustomEntityService.h"
#include "emsdevicevalue.h" #include "emsdevicevalue.h"
#include "emsdevice.h" #include "emsdevice.h"
@@ -237,7 +237,7 @@ class EMSESP {
static WebLogService webLogService; static WebLogService webLogService;
static WebCustomizationService webCustomizationService; static WebCustomizationService webCustomizationService;
static WebSchedulerService webSchedulerService; static WebSchedulerService webSchedulerService;
static WebEntityService webEntityService; static WebCustomEntityService webCustomEntityService;
private: private:
static std::string device_tostring(const uint8_t device_id); static std::string device_tostring(const uint8_t device_id);

View File

@@ -1037,7 +1037,7 @@ bool System::check_restore() {
saveSettings(EMSESP_SCHEDULER_FILE, "Schedule", input); saveSettings(EMSESP_SCHEDULER_FILE, "Schedule", input);
} else if (settings_type == "entities") { } else if (settings_type == "entities") {
// it's a entity file, just replace it and there's no need to reboot // it's a entity file, just replace it and there's no need to reboot
saveSettings(EMSESP_ENTITY_FILE, "Entities", input); saveSettings(EMSESP_CUSTOMENTITY_FILE, "Entities", input);
} else { } else {
LOG_ERROR("Unrecognized file uploaded"); LOG_ERROR("Unrecognized file uploaded");
} }

View File

@@ -280,6 +280,21 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
ok = true; ok = true;
} }
if (command == "custom_entities") {
shell.printfln("custom entities...");
run_test("general");
#ifdef EMSESP_STANDALONE
AsyncWebServerRequest request;
request.method(HTTP_GET);
request.url("/api/custom");
request.url("/api/custom/boiler_flowtemp");
request.url("/api/custom/boiler_flowtemp2");
EMSESP::webAPIService.webAPIService_get(&request);
#endif
ok = true;
}
if (command == "coldshot") { if (command == "coldshot") {
shell.printfln("Testing coldshot..."); shell.printfln("Testing coldshot...");
run_test("general"); run_test("general");
@@ -734,7 +749,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
if (emsdevice->unique_id() == 1) { // thermostat if (emsdevice->unique_id() == 1) { // thermostat
std::string a = "00hc1/seltemp|new name>5<52"; std::string a = "00hc1/seltemp|new name>5<52";
emsdevice->setCustomEntity(a); emsdevice->setCustomizationEntity(a);
break; break;
} }
} }
@@ -760,7 +775,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
for (const auto & emsdevice : EMSESP::emsdevices) { for (const auto & emsdevice : EMSESP::emsdevices) {
if (emsdevice->unique_id() == 1) { // boiler if (emsdevice->unique_id() == 1) { // boiler
std::string a = "07wwseltemp"; std::string a = "07wwseltemp";
emsdevice->setCustomEntity(a); emsdevice->setCustomizationEntity(a);
break; break;
} }
} }

View File

@@ -54,7 +54,9 @@ namespace emsesp {
// #define EMSESP_DEBUG_DEFAULT "custom" // #define EMSESP_DEBUG_DEFAULT "custom"
// #define EMSESP_DEBUG_DEFAULT "entity_dump" // #define EMSESP_DEBUG_DEFAULT "entity_dump"
// #define EMSESP_DEBUG_DEFAULT "memory" // #define EMSESP_DEBUG_DEFAULT "memory"
#define EMSESP_DEBUG_DEFAULT "coldshot" // #define EMSESP_DEBUG_DEFAULT "coldshot"
#define EMSESP_DEBUG_DEFAULT "custom_entities"
class Test { class Test {
public: public:

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.6.2-dev.0b" #define EMSESP_APP_VERSION "3.6.2-dev.1a"

View File

@@ -216,7 +216,7 @@ void WebAPIService::getEntities(AsyncWebServerRequest * request) {
root["type"] = "entities"; root["type"] = "entities";
System::extractSettings(EMSESP_ENTITY_FILE, "Entities", root); System::extractSettings(EMSESP_CUSTOMENTITY_FILE, "Entities", root);
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@@ -22,13 +22,19 @@ namespace emsesp {
using namespace std::placeholders; // for `_1` etc using namespace std::placeholders; // for `_1` etc
WebEntityService::WebEntityService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager) WebCustomEntityService::WebCustomEntityService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
: _httpEndpoint(WebEntity::read, WebEntity::update, this, server, EMSESP_ENTITY_SERVICE_PATH, securityManager, AuthenticationPredicates::IS_AUTHENTICATED) : _httpEndpoint(WebCustomEntity::read,
, _fsPersistence(WebEntity::read, WebEntity::update, this, fs, EMSESP_ENTITY_FILE, FS_BUFFER_SIZE) { WebCustomEntity::update,
this,
server,
EMSESP_CUSTOMENTITY_SERVICE_PATH,
securityManager,
AuthenticationPredicates::IS_AUTHENTICATED)
, _fsPersistence(WebCustomEntity::read, WebCustomEntity::update, this, fs, EMSESP_CUSTOMENTITY_FILE, FS_BUFFER_SIZE) {
} }
// load the settings when the service starts // load the settings when the service starts
void WebEntityService::begin() { void WebCustomEntityService::begin() {
_fsPersistence.readFromFS(); _fsPersistence.readFromFS();
EMSESP::logger().info("Starting Custom entity service"); EMSESP::logger().info("Starting Custom entity service");
Mqtt::subscribe(EMSdevice::DeviceType::CUSTOM, "custom/#", nullptr); // use empty function callback Mqtt::subscribe(EMSdevice::DeviceType::CUSTOM, "custom/#", nullptr); // use empty function callback
@@ -36,10 +42,10 @@ void WebEntityService::begin() {
// this creates the entity file, saving it to the FS // this creates the entity file, saving it to the FS
// and also calls when the Entity web page is refreshed // and also calls when the Entity web page is refreshed
void WebEntity::read(WebEntity & webEntity, JsonObject & root) { void WebCustomEntity::read(WebCustomEntity & webEntity, JsonObject & root) {
JsonArray entity = root.createNestedArray("entities"); JsonArray entity = root.createNestedArray("entities");
uint8_t counter = 0; uint8_t counter = 0;
for (const EntityItem & entityItem : webEntity.entityItems) { for (const CustomEntityItem & entityItem : webEntity.customEntityItems) {
JsonObject ei = entity.createNestedObject(); JsonObject ei = entity.createNestedObject();
ei["id"] = counter++; // id is only used to render the table and must be unique ei["id"] = counter++; // id is only used to render the table and must be unique
ei["device_id"] = entityItem.device_id; ei["device_id"] = entityItem.device_id;
@@ -50,22 +56,38 @@ void WebEntity::read(WebEntity & webEntity, JsonObject & root) {
ei["uom"] = entityItem.uom; ei["uom"] = entityItem.uom;
ei["value_type"] = entityItem.value_type; ei["value_type"] = entityItem.value_type;
ei["writeable"] = entityItem.writeable; ei["writeable"] = entityItem.writeable;
EMSESP::webEntityService.render_value(ei, entityItem, true, true); EMSESP::webCustomEntityService.render_value(ei, entityItem, true, true);
} }
} }
// call on initialization and also when the Entity web page is updated // call on initialization and also when the Entity web page is updated
// this loads the data into the internal class // this loads the data into the internal class
StateUpdateResult WebEntity::update(JsonObject & root, WebEntity & webEntity) { StateUpdateResult WebCustomEntity::update(JsonObject & root, WebCustomEntity & webCustomEntity) {
for (EntityItem & entityItem : webEntity.entityItems) { #ifdef EMSESP_STANDALONE
// invoke some fake data for testing
// clang-format off
/* prettier-ignore */
const char * json =
"{\"entities\": [{\"id\":0,\"device_id\":8,\"type_id\":24,\"offset\":0,\"factor\":1,\"name\":\"boiler_flowtemp\",\"uom\":1,\"value_type\":1,\"writeable\":true}]}";
// clang-format on
StaticJsonDocument<500> doc;
deserializeJson(doc, json);
root = doc.as<JsonObject>();
Serial.println(COLOR_BRIGHT_MAGENTA);
Serial.print(" Using fake custom entity file: ");
serializeJson(root, Serial);
Serial.println(COLOR_RESET);
#endif
for (CustomEntityItem & entityItem : webCustomEntity.customEntityItems) {
Command::erase_command(EMSdevice::DeviceType::CUSTOM, entityItem.name.c_str()); Command::erase_command(EMSdevice::DeviceType::CUSTOM, entityItem.name.c_str());
} }
webEntity.entityItems.clear(); webCustomEntity.customEntityItems.clear();
EMSESP::webEntityService.ha_reset(); EMSESP::webCustomEntityService.ha_reset();
if (root["entities"].is<JsonArray>()) { if (root["entities"].is<JsonArray>()) {
for (const JsonObject ei : root["entities"].as<JsonArray>()) { for (const JsonObject ei : root["entities"].as<JsonArray>()) {
auto entityItem = EntityItem(); auto entityItem = CustomEntityItem();
entityItem.device_id = ei["device_id"]; // send as numeric, will be converted to string in web entityItem.device_id = ei["device_id"]; // send as numeric, will be converted to string in web
entityItem.type_id = ei["type_id"]; entityItem.type_id = ei["type_id"];
entityItem.offset = ei["offset"]; entityItem.offset = ei["offset"];
@@ -91,13 +113,13 @@ StateUpdateResult WebEntity::update(JsonObject & root, WebEntity & webEntity) {
if (entityItem.factor == 0) { if (entityItem.factor == 0) {
entityItem.factor = 1; entityItem.factor = 1;
} }
webEntity.entityItems.push_back(entityItem); // add to list webCustomEntity.customEntityItems.push_back(entityItem); // add to list
if (entityItem.writeable) { if (entityItem.writeable) {
Command::add( Command::add(
EMSdevice::DeviceType::CUSTOM, EMSdevice::DeviceType::CUSTOM,
webEntity.entityItems.back().name.c_str(), webCustomEntity.customEntityItems.back().name.c_str(),
[webEntity](const char * value, const int8_t id) { [webCustomEntity](const char * value, const int8_t id) {
return EMSESP::webEntityService.command_setvalue(value, webEntity.entityItems.back().name); return EMSESP::webCustomEntityService.command_setvalue(value, webCustomEntity.customEntityItems.back().name);
}, },
FL_(entity_cmd), FL_(entity_cmd),
CommandFlag::ADMIN_ONLY); CommandFlag::ADMIN_ONLY);
@@ -108,9 +130,9 @@ StateUpdateResult WebEntity::update(JsonObject & root, WebEntity & webEntity) {
} }
// set value by api command // set value by api command
bool WebEntityService::command_setvalue(const char * value, const std::string name) { bool WebCustomEntityService::command_setvalue(const char * value, const std::string name) {
EMSESP::webEntityService.read([&](WebEntity & webEntity) { entityItems = &webEntity.entityItems; }); EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; });
for (EntityItem & entityItem : *entityItems) { for (CustomEntityItem & entityItem : *customEntityItems) {
if (Helpers::toLower(entityItem.name) == Helpers::toLower(name)) { if (Helpers::toLower(entityItem.name) == Helpers::toLower(name)) {
if (entityItem.value_type == DeviceValueType::STRING) { if (entityItem.value_type == DeviceValueType::STRING) {
char telegram[84]; char telegram[84];
@@ -160,7 +182,7 @@ bool WebEntityService::command_setvalue(const char * value, const std::string na
} }
// output of a single value // output of a single value
void WebEntityService::render_value(JsonObject & output, EntityItem entity, const bool useVal, const bool web) { void WebCustomEntityService::render_value(JsonObject & output, CustomEntityItem entity, const bool useVal, const bool web) {
char payload[12]; char payload[12];
std::string name = useVal ? "value" : entity.name; std::string name = useVal ? "value" : entity.name;
switch (entity.value_type) { switch (entity.value_type) {
@@ -215,27 +237,30 @@ void WebEntityService::render_value(JsonObject & output, EntityItem entity, cons
} }
// process json output for info/commands and value_info // process json output for info/commands and value_info
bool WebEntityService::get_value_info(JsonObject & output, const char * cmd) { bool WebCustomEntityService::get_value_info(JsonObject & output, const char * cmd) {
EMSESP::webEntityService.read([&](WebEntity & webEntity) { entityItems = &webEntity.entityItems; }); EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; });
if (Helpers::toLower(cmd) == F_(commands)) { if (Helpers::toLower(cmd) == F_(commands)) {
output[F_(info)] = Helpers::translated_word(FL_(info_cmd)); output[F_(info)] = Helpers::translated_word(FL_(info_cmd));
output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd)); output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd));
for (const auto & entity : *entityItems) { for (const auto & entity : *customEntityItems) {
output[entity.name] = "custom entitiy"; output[entity.name] = "custom entitiy";
} }
return true; return true;
} }
if (entityItems->size() == 0) { // if no entries, return a message instead of an error
// https://github.com/emsesp/EMS-ESP32/issues/1297
if (customEntityItems->size() == 0) {
output["message"] = "no entries"; output["message"] = "no entries";
return true; return true;
} }
if (strlen(cmd) == 0 || Helpers::toLower(cmd) == F_(values) || Helpers::toLower(cmd) == F_(info)) { if (strlen(cmd) == 0 || Helpers::toLower(cmd) == F_(values) || Helpers::toLower(cmd) == F_(info)) {
// list all names // list all names
for (const EntityItem & entity : *entityItems) { for (const CustomEntityItem & entity : *customEntityItems) {
render_value(output, entity); render_value(output, entity);
} }
return (output.size() != 0); return (output.size() != 0);
} }
char command_s[30]; char command_s[30];
strlcpy(command_s, cmd, sizeof(command_s)); strlcpy(command_s, cmd, sizeof(command_s));
char * attribute_s = nullptr; char * attribute_s = nullptr;
@@ -245,7 +270,8 @@ bool WebEntityService::get_value_info(JsonObject & output, const char * cmd) {
*breakp = '\0'; *breakp = '\0';
attribute_s = breakp + 1; attribute_s = breakp + 1;
} }
for (const auto & entity : *entityItems) {
for (const auto & entity : *customEntityItems) {
if (Helpers::toLower(entity.name) == Helpers::toLower(command_s)) { if (Helpers::toLower(entity.name) == Helpers::toLower(command_s)) {
output["name"] = entity.name; output["name"] = entity.name;
if (entity.uom > 0) { if (entity.uom > 0) {
@@ -279,16 +305,18 @@ bool WebEntityService::get_value_info(JsonObject & output, const char * cmd) {
} }
} }
} }
if (output.size()) { if (output.size()) {
return true; return true;
} }
} }
output["message"] = "unknown command"; output["message"] = "unknown command";
return false; return false;
} }
// publish single value // publish single value
void WebEntityService::publish_single(const EntityItem & entity) { void WebCustomEntityService::publish_single(const CustomEntityItem & entity) {
if (!Mqtt::enabled() || !Mqtt::publish_single()) { if (!Mqtt::enabled() || !Mqtt::publish_single()) {
return; return;
} }
@@ -305,19 +333,19 @@ void WebEntityService::publish_single(const EntityItem & entity) {
} }
// publish to Mqtt // publish to Mqtt
void WebEntityService::publish(const bool force) { void WebCustomEntityService::publish(const bool force) {
if (force) { if (force) {
ha_registered_ = false; ha_registered_ = false;
} }
if (!Mqtt::enabled()) { if (!Mqtt::enabled()) {
return; return;
} }
EMSESP::webEntityService.read([&](WebEntity & webEntity) { entityItems = &webEntity.entityItems; }); EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; });
if (entityItems->size() == 0) { if (customEntityItems->size() == 0) {
return; return;
} }
if (Mqtt::publish_single() && force) { if (Mqtt::publish_single() && force) {
for (const EntityItem & entityItem : *entityItems) { for (const CustomEntityItem & entityItem : *customEntityItems) {
publish_single(entityItem); publish_single(entityItem);
} }
} }
@@ -325,7 +353,7 @@ void WebEntityService::publish(const bool force) {
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE); DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE);
JsonObject output = doc.to<JsonObject>(); JsonObject output = doc.to<JsonObject>();
bool ha_created = ha_registered_; bool ha_created = ha_registered_;
for (const EntityItem & entityItem : *entityItems) { for (const CustomEntityItem & entityItem : *customEntityItems) {
render_value(output, entityItem); render_value(output, entityItem);
// create HA config // create HA config
if (Mqtt::ha_enabled() && !ha_registered_) { if (Mqtt::ha_enabled() && !ha_registered_) {
@@ -399,39 +427,39 @@ void WebEntityService::publish(const bool force) {
} }
// count only entities with valid value or command to show in dashboard // count only entities with valid value or command to show in dashboard
uint8_t WebEntityService::count_entities() { uint8_t WebCustomEntityService::count_entities() {
EMSESP::webEntityService.read([&](WebEntity & webEntity) { entityItems = &webEntity.entityItems; }); EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; });
if (entityItems->size() == 0) { if (customEntityItems->size() == 0) {
return 0; return 0;
} }
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE); DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE);
JsonObject output = doc.to<JsonObject>(); JsonObject output = doc.to<JsonObject>();
uint8_t count = 0; uint8_t count = 0;
for (const EntityItem & entity : *entityItems) { for (const CustomEntityItem & entity : *customEntityItems) {
render_value(output, entity); render_value(output, entity);
count += (output.containsKey(entity.name) || entity.writeable) ? 1 : 0; count += (output.containsKey(entity.name) || entity.writeable) ? 1 : 0;
} }
return count; return count;
} }
uint8_t WebEntityService::has_commands() { uint8_t WebCustomEntityService::has_commands() {
EMSESP::webEntityService.read([&](WebEntity & webEntity) { entityItems = &webEntity.entityItems; }); EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; });
uint8_t count = 0; uint8_t count = 0;
for (const EntityItem & entity : *entityItems) { for (const CustomEntityItem & entity : *customEntityItems) {
count += entity.writeable ? 1 : 0; count += entity.writeable ? 1 : 0;
} }
return count; return count;
} }
// send to dashboard, msgpack don't like serialized, use number // send to dashboard, msgpack don't like serialized, use number
void WebEntityService::generate_value_web(JsonObject & output) { void WebCustomEntityService::generate_value_web(JsonObject & output) {
EMSESP::webEntityService.read([&](WebEntity & webEntity) { entityItems = &webEntity.entityItems; }); EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; });
output["label"] = (std::string) "Custom Entities"; output["label"] = (std::string) "Custom Entities";
JsonArray data = output.createNestedArray("data"); JsonArray data = output.createNestedArray("data");
uint8_t index = 0; uint8_t index = 0;
for (const EntityItem & entity : *entityItems) { for (const CustomEntityItem & entity : *customEntityItems) {
JsonObject obj = data.createNestedObject(); // create the object, we know there is a value JsonObject obj = data.createNestedObject(); // create the object, we know there is a value
obj["id"] = "00" + entity.name; obj["id"] = "00" + entity.name;
obj["u"] = entity.uom; obj["u"] = entity.uom;
@@ -496,10 +524,10 @@ void WebEntityService::generate_value_web(JsonObject & output) {
} }
// fetch telegram, called from emsesp::fetch // fetch telegram, called from emsesp::fetch
void WebEntityService::fetch() { void WebCustomEntityService::fetch() {
EMSESP::webEntityService.read([&](WebEntity & webEntity) { entityItems = &webEntity.entityItems; }); EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; });
const uint8_t len[] = {1, 1, 1, 2, 2, 3, 3}; const uint8_t len[] = {1, 1, 1, 2, 2, 3, 3};
for (auto & entity : *entityItems) { for (auto & entity : *customEntityItems) {
EMSESP::send_read_request(entity.type_id, EMSESP::send_read_request(entity.type_id,
entity.device_id, entity.device_id,
entity.offset, entity.offset,
@@ -509,12 +537,12 @@ void WebEntityService::fetch() {
} }
// called on process telegram, read from telegram // called on process telegram, read from telegram
bool WebEntityService::get_value(std::shared_ptr<const Telegram> telegram) { bool WebCustomEntityService::get_value(std::shared_ptr<const Telegram> telegram) {
bool has_change = false; bool has_change = false;
EMSESP::webEntityService.read([&](WebEntity & webEntity) { entityItems = &webEntity.entityItems; }); EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; });
// read-length of BOOL, INT, UINT, SHORT, USHORT, ULONG, TIME // read-length of BOOL, INT, UINT, SHORT, USHORT, ULONG, TIME
const uint8_t len[] = {1, 1, 1, 2, 2, 3, 3}; const uint8_t len[] = {1, 1, 1, 2, 2, 3, 3};
for (auto & entity : *entityItems) { for (auto & entity : *customEntityItems) {
if (entity.value_type == DeviceValueType::STRING && telegram->type_id == entity.type_id && telegram->src == entity.device_id if (entity.value_type == DeviceValueType::STRING && telegram->type_id == entity.type_id && telegram->src == entity.device_id
&& telegram->offset == entity.offset) { && telegram->offset == entity.offset) {
auto data = Helpers::data_to_hex(telegram->message_data, telegram->message_length); auto data = Helpers::data_to_hex(telegram->message_data, telegram->message_length);

View File

@@ -17,15 +17,15 @@
*/ */
#include "../telegram.h" #include "../telegram.h"
#ifndef WebEntityService_h #ifndef WebCustomEntityService_h
#define WebEntityService_h #define WebCustomEntityService_h
#define EMSESP_ENTITY_FILE "/config/emsespEntity.json" #define EMSESP_CUSTOMENTITY_FILE "/config/emsespEntity.json"
#define EMSESP_ENTITY_SERVICE_PATH "/rest/entities" // GET and POST #define EMSESP_CUSTOMENTITY_SERVICE_PATH "/rest/customentities" // GET and POST
namespace emsesp { namespace emsesp {
class EntityItem { class CustomEntityItem {
public: public:
uint8_t id; uint8_t id;
uint8_t device_id; uint8_t device_id;
@@ -40,26 +40,26 @@ class EntityItem {
std::string data; std::string data;
}; };
class WebEntity { class WebCustomEntity {
public: public:
std::list<EntityItem> entityItems; std::list<CustomEntityItem> customEntityItems;
static void read(WebEntity & webEntity, JsonObject & root); static void read(WebCustomEntity & webEntity, JsonObject & root);
static StateUpdateResult update(JsonObject & root, WebEntity & webEntity); static StateUpdateResult update(JsonObject & root, WebCustomEntity & webEntity);
}; };
class WebEntityService : public StatefulService<WebEntity> { class WebCustomEntityService : public StatefulService<WebCustomEntity> {
public: public:
WebEntityService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager); WebCustomEntityService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager);
void begin(); void begin();
void publish_single(const EntityItem & entity); void publish_single(const CustomEntityItem & entity);
void publish(const bool force = false); void publish(const bool force = false);
bool command_setvalue(const char * value, const std::string name); bool command_setvalue(const char * value, const std::string name);
bool get_value_info(JsonObject & output, const char * cmd); bool get_value_info(JsonObject & output, const char * cmd);
bool get_value(std::shared_ptr<const Telegram> telegram); bool get_value(std::shared_ptr<const Telegram> telegram);
void fetch(); void fetch();
void render_value(JsonObject & output, EntityItem entity, const bool useVal = false, const bool web = false); void render_value(JsonObject & output, CustomEntityItem entity, const bool useVal = false, const bool web = false);
uint8_t count_entities(); uint8_t count_entities();
uint8_t has_commands(); uint8_t has_commands();
void generate_value_web(JsonObject & output); void generate_value_web(JsonObject & output);
@@ -69,10 +69,10 @@ class WebEntityService : public StatefulService<WebEntity> {
private: private:
HttpEndpoint<WebEntity> _httpEndpoint; HttpEndpoint<WebCustomEntity> _httpEndpoint;
FSPersistence<WebEntity> _fsPersistence; FSPersistence<WebCustomEntity> _fsPersistence;
std::list<EntityItem> * entityItems; // pointer to the list of entity items std::list<CustomEntityItem> * customEntityItems; // pointer to the list of entity items
bool ha_registered_ = false; bool ha_registered_ = false;
}; };

View File

@@ -31,8 +31,8 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
securityManager, securityManager,
AuthenticationPredicates::IS_AUTHENTICATED) AuthenticationPredicates::IS_AUTHENTICATED)
, _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE) , _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE)
, _masked_entities_handler(CUSTOM_ENTITIES_PATH, , _masked_entities_handler(CUSTOMIZATION_ENTITIES_PATH,
securityManager->wrapCallback(std::bind(&WebCustomizationService::custom_entities, this, _1, _2), securityManager->wrapCallback(std::bind(&WebCustomizationService::customization_entities, this, _1, _2),
AuthenticationPredicates::IS_AUTHENTICATED)) { AuthenticationPredicates::IS_AUTHENTICATED)) {
server->on(DEVICE_ENTITIES_PATH, server->on(DEVICE_ENTITIES_PATH,
HTTP_GET, HTTP_GET,
@@ -54,10 +54,10 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
} }
// this creates the customization file, saving it to the FS // this creates the customization file, saving it to the FS
void WebCustomization::read(WebCustomization & settings, JsonObject & root) { void WebCustomization::read(WebCustomization & customizations, JsonObject & root) {
// Temperature Sensor customization // Temperature Sensor customization
JsonArray sensorsJson = root.createNestedArray("ts"); JsonArray sensorsJson = root.createNestedArray("ts");
for (const SensorCustomization & sensor : settings.sensorCustomizations) { for (const SensorCustomization & sensor : customizations.sensorCustomizations) {
JsonObject sensorJson = sensorsJson.createNestedObject(); JsonObject sensorJson = sensorsJson.createNestedObject();
sensorJson["id"] = sensor.id; // ID of chip sensorJson["id"] = sensor.id; // ID of chip
sensorJson["name"] = sensor.name; // n sensorJson["name"] = sensor.name; // n
@@ -66,7 +66,7 @@ void WebCustomization::read(WebCustomization & settings, JsonObject & root) {
// Analog Sensor customization // Analog Sensor customization
JsonArray analogJson = root.createNestedArray("as"); JsonArray analogJson = root.createNestedArray("as");
for (const AnalogCustomization & sensor : settings.analogCustomizations) { for (const AnalogCustomization & sensor : customizations.analogCustomizations) {
JsonObject sensorJson = analogJson.createNestedObject(); JsonObject sensorJson = analogJson.createNestedObject();
sensorJson["gpio"] = sensor.gpio; // g sensorJson["gpio"] = sensor.gpio; // g
sensorJson["name"] = sensor.name; // n sensorJson["name"] = sensor.name; // n
@@ -78,7 +78,7 @@ void WebCustomization::read(WebCustomization & settings, JsonObject & root) {
// Masked entities customization // Masked entities customization
JsonArray masked_entitiesJson = root.createNestedArray("masked_entities"); JsonArray masked_entitiesJson = root.createNestedArray("masked_entities");
for (const EntityCustomization & entityCustomization : settings.entityCustomizations) { for (const EntityCustomization & entityCustomization : customizations.entityCustomizations) {
JsonObject entityJson = masked_entitiesJson.createNestedObject(); JsonObject entityJson = masked_entitiesJson.createNestedObject();
entityJson["product_id"] = entityCustomization.product_id; entityJson["product_id"] = entityCustomization.product_id;
entityJson["device_id"] = entityCustomization.device_id; entityJson["device_id"] = entityCustomization.device_id;
@@ -93,24 +93,22 @@ void WebCustomization::read(WebCustomization & settings, JsonObject & root) {
// call on initialization and also when the page is saved via web UI // call on initialization and also when the page is saved via web UI
// this loads the data into the internal class // this loads the data into the internal class
StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization & settings) { StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization & customizations) {
#ifdef EMSESP_STANDALONE #ifdef EMSESP_STANDALONE
// invoke some fake data for testing // invoke some fake data for testing
const char * json = "{\"ts\":[],\"as\":[],\"masked_entities\":[{\"product_id\":123,\"device_id\":8,\"entity_ids\":[\"08heatingactive|my custom " const char * json = "{\"ts\":[],\"as\":[],\"masked_entities\":[{\"product_id\":123,\"device_id\":8,\"entity_ids\":[\"08heatingactive|my custom "
"name for heating active\",\"08tapwateractive\"]}]}"; "name for heating active\",\"08tapwateractive\"]}]}";
StaticJsonDocument<500> doc; StaticJsonDocument<500> doc;
deserializeJson(doc, json); deserializeJson(doc, json);
root = doc.as<JsonObject>(); root = doc.as<JsonObject>();
Serial.println(COLOR_BRIGHT_MAGENTA); Serial.println(COLOR_BRIGHT_MAGENTA);
Serial.print("Using custom file: "); Serial.print(" Using fake customization file: ");
serializeJson(root, Serial); serializeJson(root, Serial);
Serial.println(COLOR_RESET); Serial.println(COLOR_RESET);
#endif #endif
// Temperature Sensor customization // Temperature Sensor customization
settings.sensorCustomizations.clear(); customizations.sensorCustomizations.clear();
if (root["ts"].is<JsonArray>()) { if (root["ts"].is<JsonArray>()) {
for (const JsonObject sensorJson : root["ts"].as<JsonArray>()) { for (const JsonObject sensorJson : root["ts"].as<JsonArray>()) {
// create each of the sensor, overwriting any previous settings // create each of the sensor, overwriting any previous settings
@@ -118,12 +116,12 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization &
sensor.id = sensorJson["id"].as<std::string>(); sensor.id = sensorJson["id"].as<std::string>();
sensor.name = sensorJson["name"].as<std::string>(); sensor.name = sensorJson["name"].as<std::string>();
sensor.offset = sensorJson["offset"]; sensor.offset = sensorJson["offset"];
settings.sensorCustomizations.push_back(sensor); // add to list customizations.sensorCustomizations.push_back(sensor); // add to list
} }
} }
// Analog Sensor customization // Analog Sensor customization
settings.analogCustomizations.clear(); customizations.analogCustomizations.clear();
if (root["as"].is<JsonArray>()) { if (root["as"].is<JsonArray>()) {
for (const JsonObject analogJson : root["as"].as<JsonArray>()) { for (const JsonObject analogJson : root["as"].as<JsonArray>()) {
// create each of the sensor, overwriting any previous settings // create each of the sensor, overwriting any previous settings
@@ -134,12 +132,12 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization &
sensor.factor = analogJson["factor"]; sensor.factor = analogJson["factor"];
sensor.uom = analogJson["uom"]; sensor.uom = analogJson["uom"];
sensor.type = analogJson["type"]; sensor.type = analogJson["type"];
settings.analogCustomizations.push_back(sensor); // add to list customizations.analogCustomizations.push_back(sensor); // add to list
} }
} }
// load array of entities id's with masks, building up the object class // load array of entities id's with masks, building up the object class
settings.entityCustomizations.clear(); customizations.entityCustomizations.clear();
if (root["masked_entities"].is<JsonArray>()) { if (root["masked_entities"].is<JsonArray>()) {
for (const JsonObject masked_entities : root["masked_entities"].as<JsonArray>()) { for (const JsonObject masked_entities : root["masked_entities"].as<JsonArray>()) {
auto new_entry = EntityCustomization(); auto new_entry = EntityCustomization();
@@ -152,7 +150,7 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization &
} }
} }
settings.entityCustomizations.push_back(new_entry); // save the new object customizations.entityCustomizations.push_back(new_entry); // save the new object
} }
} }
@@ -236,7 +234,7 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request) {
// takes a list of updated entities with new masks from the web UI // takes a list of updated entities with new masks from the web UI
// saves it in the customization service // saves it in the customization service
// and updates the entity list real-time // and updates the entity list real-time
void WebCustomizationService::custom_entities(AsyncWebServerRequest * request, JsonVariant & json) { void WebCustomizationService::customization_entities(AsyncWebServerRequest * request, JsonVariant & json) {
bool need_reboot = false; bool need_reboot = false;
if (json.is<JsonObject>()) { if (json.is<JsonObject>()) {
// find the device using the unique_id // find the device using the unique_id
@@ -256,7 +254,7 @@ void WebCustomizationService::custom_entities(AsyncWebServerRequest * request, J
entity_ids.push_back(id_s); entity_ids.push_back(id_s);
need_reboot = true; need_reboot = true;
} else { } else {
emsdevice->setCustomEntity(id_s); emsdevice->setCustomizationEntity(id_s);
} }
// emsesp::EMSESP::logger().info(id.as<const char *>()); // emsesp::EMSESP::logger().info(id.as<const char *>());
} }
@@ -287,7 +285,7 @@ void WebCustomizationService::custom_entities(AsyncWebServerRequest * request, J
} }
}); });
// get list of entities that have masks set or a custom fullname // get list of entities that have masks set or a custom fullname
emsdevice->getCustomEntities(entity_ids); emsdevice->getCustomizationEntities(entity_ids);
// Save the list to the customization file // Save the list to the customization file
EMSESP::webCustomizationService.update( EMSESP::webCustomizationService.update(

View File

@@ -27,7 +27,7 @@
#define DEVICE_ENTITIES_PATH "/rest/deviceEntities" #define DEVICE_ENTITIES_PATH "/rest/deviceEntities"
// POST // POST
#define CUSTOM_ENTITIES_PATH "/rest/customEntities" #define CUSTOMIZATION_ENTITIES_PATH "/rest/customizationEntities"
#define RESET_CUSTOMIZATION_SERVICE_PATH "/rest/resetCustomizations" #define RESET_CUSTOMIZATION_SERVICE_PATH "/rest/resetCustomizations"
namespace emsesp { namespace emsesp {
@@ -71,8 +71,8 @@ class WebCustomization {
std::list<SensorCustomization> sensorCustomizations; // for sensor names and offsets std::list<SensorCustomization> sensorCustomizations; // for sensor names and offsets
std::list<AnalogCustomization> analogCustomizations; // for analog sensors std::list<AnalogCustomization> analogCustomizations; // for analog sensors
std::list<EntityCustomization> entityCustomizations; // for a list of entities that have a special mask set std::list<EntityCustomization> entityCustomizations; // for a list of entities that have a special mask set
static void read(WebCustomization & settings, JsonObject & root); static void read(WebCustomization & customizations, JsonObject & root);
static StateUpdateResult update(JsonObject & root, WebCustomization & settings); static StateUpdateResult update(JsonObject & root, WebCustomization & customizations);
}; };
class WebCustomizationService : public StatefulService<WebCustomization> { class WebCustomizationService : public StatefulService<WebCustomization> {
@@ -94,7 +94,7 @@ class WebCustomizationService : public StatefulService<WebCustomization> {
void device_entities(AsyncWebServerRequest * request); void device_entities(AsyncWebServerRequest * request);
// POST // POST
void custom_entities(AsyncWebServerRequest * request, JsonVariant & json); void customization_entities(AsyncWebServerRequest * request, JsonVariant & json);
void reset_customization(AsyncWebServerRequest * request); // command void reset_customization(AsyncWebServerRequest * request); // command
AsyncCallbackJsonWebHandler _masked_entities_handler; AsyncCallbackJsonWebHandler _masked_entities_handler;

View File

@@ -92,7 +92,7 @@ void WebDataService::core_data(AsyncWebServerRequest * request) {
} }
// add any custom entities // add any custom entities
if (EMSESP::webEntityService.count_entities()) { if (EMSESP::webCustomEntityService.count_entities()) {
JsonObject obj = devices.createNestedObject(); JsonObject obj = devices.createNestedObject();
obj["id"] = 99; // the last unique id obj["id"] = 99; // the last unique id
obj["tn"] = Helpers::translated_word(FL_(custom_device)); // translated device type name obj["tn"] = Helpers::translated_word(FL_(custom_device)); // translated device type name
@@ -210,7 +210,7 @@ void WebDataService::device_data(AsyncWebServerRequest * request) {
#ifndef EMSESP_STANDALONE #ifndef EMSESP_STANDALONE
if (id == 99) { if (id == 99) {
JsonObject output = response->getRoot(); JsonObject output = response->getRoot();
EMSESP::webEntityService.generate_value_web(output); EMSESP::webCustomEntityService.generate_value_web(output);
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;

View File

@@ -57,12 +57,13 @@ StateUpdateResult WebScheduler::update(JsonObject & root, WebScheduler & webSche
#ifdef EMSESP_STANDALONE #ifdef EMSESP_STANDALONE
// invoke some fake data for testing // invoke some fake data for testing
const char * json = const char * json =
"{[{\"id\":1,\"active\":true,\"flags\":31,\"time\": \"07:30\",\"cmd\": \"hc1/mode\",\"value\": \"day\",\"name\": \"turn on central heating\"}]}"; "{\"schedule\": [{\"id\":1,\"active\":true,\"flags\":31,\"time\": \"07:30\",\"cmd\": \"hc1mode\",\"value\": \"day\",\"name\": \"turn on "
"central heating\"}]}";
StaticJsonDocument<500> doc; StaticJsonDocument<500> doc;
deserializeJson(doc, json); deserializeJson(doc, json);
root = doc.as<JsonObject>(); root = doc.as<JsonObject>();
Serial.println(COLOR_BRIGHT_MAGENTA); Serial.println(COLOR_BRIGHT_MAGENTA);
Serial.print("Using custom file: "); Serial.print(" Using fake scheduler file: ");
serializeJson(root, Serial); serializeJson(root, Serial);
Serial.println(COLOR_RESET); Serial.println(COLOR_RESET);
#endif #endif