Merge pull request #1991 from proddy/dev

some minor fixes
This commit is contained in:
Proddy
2024-09-11 15:04:15 +02:00
committed by GitHub
60 changed files with 1045 additions and 903 deletions

View File

@@ -10,6 +10,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
- name: GitHub Releases To Discord
uses: SethCohen/github-releases-to-discord@v1.13.1
with:

View File

@@ -11,25 +11,33 @@ jobs:
name: 'Automatic pre-release build'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Checkout repository
uses: actions/checkout@v4
- name: Enable Corepack
run: corepack enable
- uses: actions/setup-python@v5
- name: Install python 3.11
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Use Node.js 20.x
- name: Install Node.js 20
uses: actions/setup-node@v4
with:
node-version: '20.x'
- name: Get EMS-ESP source code and version
- name: Get EMS-ESP version
id: build_info
run: |
version=`grep -E '^#define EMSESP_APP_VERSION' ./src/version.h | awk -F'"' '{print $2}'`
echo "VERSION=$version" >> $GITHUB_OUTPUT
- name: Install PlatformIO
run: |
python -m pip install --upgrade pip
pip install -U platformio
- name: Build WebUI
run: |
cd interface
@@ -38,9 +46,11 @@ jobs:
sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts
yarn build
yarn webUI
- name: Build all target environments from default_envs
- name: Build all PIO target environments from default_envs
run: |
platformio run
- name: Create GitHub Release
id: 'automatic_releases'
uses: emsesp/action-automatic-releases@v1.0.0

View File

@@ -16,13 +16,17 @@ jobs:
env:
BUILD_WRAPPER_OUT_DIR: bw-output
steps:
- uses: actions/checkout@v4
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install sonar-scanner and build-wrapper
uses: SonarSource/sonarcloud-github-c-cpp@v2
- name: Run build-wrapper
run: build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make all
- name: Run sonar-scanner
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -11,22 +11,27 @@ jobs:
name: 'Tagged Release'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Checkout repository
uses: actions/checkout@v4
- name: Enable Corepack
run: corepack enable
- uses: actions/setup-python@v5
- name: Install python 3.11
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Use Node.js 20.x
- name: Install Node.js 20
uses: actions/setup-node@v4
with:
node-version: '20.x'
- name: Install PlatformIO
run: |
python -m pip install --upgrade pip
pip install -U platformio
platformio upgrade
pio pkg update
- name: Build WebUI
run: |
cd interface
@@ -35,9 +40,11 @@ jobs:
sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts
yarn build
yarn webUI
- name: Build all target environments from default_envs
- name: Build all PIO target environments from default_envs
run: |
platformio run
- name: Create GitHub Release
uses: emsesp/action-automatic-releases@v1.0.0
with:

2
.gitignore vendored
View File

@@ -2,7 +2,7 @@
.vscode/c_cpp_properties.json
.vscode/extensions.json
.vscode/launch.json
#.vscode/settings.json
.vscode/settings.json
# c++ compiling
.clang_complete

View File

@@ -89,7 +89,8 @@
"**/ArduinoJson/**"
],
"cSpell.enableFiletypes": [
"!typescript"
"ini",
"makefile"
],
"typescript.preferences.preferTypeOnlyAutoImports": true
}

View File

@@ -35,12 +35,17 @@
- RC310 cooling parameters [#1857](https://github.com/emsesp/EMS-ESP32/issues/1857)
- command `api/device/entities` [#1897](https://github.com/emsesp/EMS-ESP32/issues/1897)
- switchprogmode [#1903]<https://github.com/emsesp/EMS-ESP32/discussions/1903>
- Autodetect and download firmware upgrades
- Autodetect and download firmware upgrades via the WebUI
- command 'show log' that lists out the current weblog buffer, showing last messages.
- default web log buffer to 25 lines for ESP32s with no PSRAM
- Try and determine correct board profile if none is set
## Fixed
- remote thermostat emulation for RC200 on Rego2000/3000 thermostats [#1691](https://github.com/emsesp/EMS-ESP32/discussions/1691)
- log shows data for F7/F9 requests
- Detection of LittleFS for factory setting wasn't working
- Check for bad GPIOs with Ethernet before the ethernet is initialized
## Changed
@@ -58,4 +63,5 @@
- Change key-names in JSON to be compliant and consistent [#1860](https://github.com/emsesp/EMS-ESP32/issues/1860)
- Updates to webUI [#1920](https://github.com/emsesp/EMS-ESP32/issues/1920)
- Correct firmware naming #1933 [#1933](https://github.com/emsesp/EMS-ESP32/issues/1933)
- Don't start Serial console if not connected to a Serial port. Will initiate manually after a CTRL-C
- WebLog UI matches color schema of the terminal console correctly

View File

@@ -81,8 +81,8 @@ CPPFLAGS += -g3
CPPFLAGS += -Os
CFLAGS += $(CPPFLAGS)
CFLAGS += -Wall -Wextra -Werror -Wswitch-enum -Wno-unused-parameter -Wno-inconsistent-missing-override -Wno-missing-braces -Wno-unused-lambda-capture -Wno-sign-compare
CFLAGS += -Wall -Wextra -Werror -Wswitch-enum
CFLAGS += -Wno-tautological-constant-out-of-range-compare -Wno-unused-parameter -Wno-inconsistent-missing-override -Wno-missing-braces -Wno-unused-lambda-capture -Wno-sign-compare
CXXFLAGS += $(CFLAGS) -MMD
#----------------------------------------------------------------------

View File

@@ -23,9 +23,13 @@
- Easy first-time configuration via a web Captive Portal
- Support for more than [120+ EMS devices](https://emsesp.org/All-Devices/) (boilers, thermostats, solar modules, mixer modules, heat pumps, gateways, switches, heat sources)
## **Installing**
Go to [install.emsesp.org](https://install.emsesp.org) or look at the documentation link below on the different ways to install EMS-ESP.
## **Documentation**
For the complete documentation on how to install, configure and get support visit the [EMS-ESP Wiki](https://emsesp.org).
For the complete documentation on how to install, configure and get support visit the [documentation at emsesp.org](https://emsesp.org).
## **Support**
@@ -35,7 +39,7 @@ If you like **EMS-ESP**, please give it a star, or fork it and contribute or off
## **Demo**
For a live demo of the Web UI click [here](https://demo.emsesp.org) and log in with any username/password.
For a live demo of the Web UI click [demo.emsesp.org](https://demo.emsesp.org) and log in with any username/password, and change the language to English.
## **Contributors ✨**
@@ -67,6 +71,6 @@ This program is licensed under GPL-3.0
![Console](media/console0.png)
### In Home Assistant
### Home Assistant
![Home Assistant](media/ha_lovelace.png)

View File

@@ -40,12 +40,12 @@ CS6800i/WLW176i,boiler,8,emergencytemp,emergency temperature,uint8 (>=15<=70),C,
CS6800i/WLW176i,boiler,8,nrgtotal,total energy,uint24 (>=0<=167772),kWh,false,sensor.boiler_total_energy,sensor.boiler_nrgtotal,5,0,1/100,80,2
CS6800i/WLW176i,boiler,8,nrg,energy,uint24 (>=0<=167772),kWh,false,sensor.boiler_dhw_energy,sensor.boiler_dhw_nrg,5,9,1/100,0,2
CS6800i/WLW176i,boiler,8,nrgheat,energy heating,uint24 (>=0<=167772),kWh,false,sensor.boiler_energy_heating,sensor.boiler_nrgheat,5,0,1/100,82,2
CS6800i/WLW176i,boiler,8,nrgcool,energy cooling,uint24 (>=0<=167772),kWh,false,sensor.boiler_energy_cooling,sensor.boiler_nrgcool,5,0,1/100,-1,2
CS6800i/WLW176i,boiler,8,nrgcool,energy cooling,uint24 (>=0<=167772),kWh,false,sensor.boiler_energy_cooling,sensor.boiler_nrgcool,5,0,1/100,264,2
CS6800i/WLW176i,boiler,8,metertotal,meter total,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_total,sensor.boiler_metertotal,5,0,1/100,84,2
CS6800i/WLW176i,boiler,8,metercomp,meter compressor,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_compressor,sensor.boiler_metercomp,5,0,1/100,86,2
CS6800i/WLW176i,boiler,8,metereheat,meter e-heater,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_e-heater,sensor.boiler_metereheat,5,0,1/100,88,2
CS6800i/WLW176i,boiler,8,meterheat,meter heating,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_heating,sensor.boiler_meterheat,5,0,1/100,90,2
CS6800i/WLW176i,boiler,8,metercool,meter cooling,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_cooling,sensor.boiler_metercool,5,0,1/100,-1,2
CS6800i/WLW176i,boiler,8,metercool,meter cooling,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_cooling,sensor.boiler_metercool,5,0,1/100,266,2
CS6800i/WLW176i,boiler,8,meter,meter,uint24 (>=0<=167772),kWh,false,sensor.boiler_dhw_meter,sensor.boiler_dhw_meter,5,9,1/100,2,2
CS6800i/WLW176i,boiler,8,uptimetotal,heatpump total uptime,time (>=0<=279620),minutes,false,sensor.boiler_heatpump_total_uptime,sensor.boiler_uptimetotal,5,0,1/60,92,2
CS6800i/WLW176i,boiler,8,uptimecontrol,total operating time heat,time (>=0<=279620),minutes,false,sensor.boiler_total_operating_time_heat,sensor.boiler_uptimecontrol,5,0,1/60,94,2
@@ -2090,12 +2090,12 @@ 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,nrgtotal,total energy,uint24 (>=0<=167772),kWh,false,sensor.boiler_total_energy,sensor.boiler_nrgtotal,5,0,1/100,80,2
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,nrg,energy,uint24 (>=0<=167772),kWh,false,sensor.boiler_dhw_energy,sensor.boiler_dhw_nrg,5,9,1/100,0,2
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,nrgheat,energy heating,uint24 (>=0<=167772),kWh,false,sensor.boiler_energy_heating,sensor.boiler_nrgheat,5,0,1/100,82,2
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,nrgcool,energy cooling,uint24 (>=0<=167772),kWh,false,sensor.boiler_energy_cooling,sensor.boiler_nrgcool,5,0,1/100,-1,2
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,nrgcool,energy cooling,uint24 (>=0<=167772),kWh,false,sensor.boiler_energy_cooling,sensor.boiler_nrgcool,5,0,1/100,264,2
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,metertotal,meter total,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_total,sensor.boiler_metertotal,5,0,1/100,84,2
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,metercomp,meter compressor,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_compressor,sensor.boiler_metercomp,5,0,1/100,86,2
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,metereheat,meter e-heater,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_e-heater,sensor.boiler_metereheat,5,0,1/100,88,2
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,meterheat,meter heating,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_heating,sensor.boiler_meterheat,5,0,1/100,90,2
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,metercool,meter cooling,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_cooling,sensor.boiler_metercool,5,0,1/100,-1,2
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,metercool,meter cooling,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_cooling,sensor.boiler_metercool,5,0,1/100,266,2
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,meter,meter,uint24 (>=0<=167772),kWh,false,sensor.boiler_dhw_meter,sensor.boiler_dhw_meter,5,9,1/100,2,2
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,uptimetotal,heatpump total uptime,time (>=0<=279620),minutes,false,sensor.boiler_heatpump_total_uptime,sensor.boiler_uptimetotal,5,0,1/60,92,2
Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i/WSW196i,boiler,172,uptimecontrol,total operating time heat,time (>=0<=279620),minutes,false,sensor.boiler_total_operating_time_heat,sensor.boiler_uptimecontrol,5,0,1/60,94,2
@@ -2287,12 +2287,12 @@ Geo 5xx,boiler,173,emergencytemp,emergency temperature,uint8 (>=15<=70),C,true,n
Geo 5xx,boiler,173,nrgtotal,total energy,uint24 (>=0<=167772),kWh,false,sensor.boiler_total_energy,sensor.boiler_nrgtotal,5,0,1/100,80,2
Geo 5xx,boiler,173,nrg,energy,uint24 (>=0<=167772),kWh,false,sensor.boiler_dhw_energy,sensor.boiler_dhw_nrg,5,9,1/100,0,2
Geo 5xx,boiler,173,nrgheat,energy heating,uint24 (>=0<=167772),kWh,false,sensor.boiler_energy_heating,sensor.boiler_nrgheat,5,0,1/100,82,2
Geo 5xx,boiler,173,nrgcool,energy cooling,uint24 (>=0<=167772),kWh,false,sensor.boiler_energy_cooling,sensor.boiler_nrgcool,5,0,1/100,-1,2
Geo 5xx,boiler,173,nrgcool,energy cooling,uint24 (>=0<=167772),kWh,false,sensor.boiler_energy_cooling,sensor.boiler_nrgcool,5,0,1/100,264,2
Geo 5xx,boiler,173,metertotal,meter total,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_total,sensor.boiler_metertotal,5,0,1/100,84,2
Geo 5xx,boiler,173,metercomp,meter compressor,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_compressor,sensor.boiler_metercomp,5,0,1/100,86,2
Geo 5xx,boiler,173,metereheat,meter e-heater,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_e-heater,sensor.boiler_metereheat,5,0,1/100,88,2
Geo 5xx,boiler,173,meterheat,meter heating,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_heating,sensor.boiler_meterheat,5,0,1/100,90,2
Geo 5xx,boiler,173,metercool,meter cooling,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_cooling,sensor.boiler_metercool,5,0,1/100,-1,2
Geo 5xx,boiler,173,metercool,meter cooling,uint24 (>=0<=167772),kWh,false,sensor.boiler_meter_cooling,sensor.boiler_metercool,5,0,1/100,266,2
Geo 5xx,boiler,173,meter,meter,uint24 (>=0<=167772),kWh,false,sensor.boiler_dhw_meter,sensor.boiler_dhw_meter,5,9,1/100,2,2
Geo 5xx,boiler,173,uptimetotal,heatpump total uptime,time (>=0<=279620),minutes,false,sensor.boiler_heatpump_total_uptime,sensor.boiler_uptimetotal,5,0,1/60,92,2
Geo 5xx,boiler,173,uptimecontrol,total operating time heat,time (>=0<=279620),minutes,false,sensor.boiler_total_operating_time_heat,sensor.boiler_uptimecontrol,5,0,1/60,94,2
@@ -3355,16 +3355,16 @@ UI800/BC400,thermostat,4,hpoperatingstate,heatpump operating state,enum [heating
UI800/BC400,thermostat,4,controlmode,control mode,enum [weather compensated\|outside basepoint\|n/a\|room\|power\|constant], ,true,select.thermostat_hc1_control_mode,select.thermostat_hc1_controlmode,6,1,1,24,1
UI800/BC400,thermostat,4,program,program,enum [prog 1\|prog 2], ,true,select.thermostat_hc1_program,select.thermostat_hc1_program,6,1,1,25,1
UI800/BC400,thermostat,4,tempautotemp,temporary set temperature automode,int8 (>=-1<=30),C,true,number.thermostat_hc1_temporary_set_temperature_automode,number.thermostat_hc1_tempautotemp,6,1,1/2,26,1
UI800/BC400,thermostat,4,remoteseltemp,temporary set temperature from remote,int8 (>=-63<=63),C,false,sensor.thermostat_hc1_temporary_set_temperature_from_remote,sensor.thermostat_hc1_remoteseltemp,6,1,1/2,27,1
UI800/BC400,thermostat,4,remoteseltemp,temporary set temperature from remote,int8 (>=-1<=30),C,true,number.thermostat_hc1_temporary_set_temperature_from_remote,number.thermostat_hc1_remoteseltemp,6,1,1/2,27,1
UI800/BC400,thermostat,4,fastheatup,fast heatup,uint8 (>=0<=100),%,true,number.thermostat_hc1_fast_heatup,number.thermostat_hc1_fastheatup,6,1,1,28,1
UI800/BC400,thermostat,4,switchonoptimization,switch-on optimization,boolean, ,true,switch.thermostat_hc1_switch-on_optimization,switch.thermostat_hc1_switchonoptimization,6,1,1,29,1
UI800/BC400,thermostat,4,reducemode,reduce mode,enum [outdoor\|room\|reduce], ,true,select.thermostat_hc1_reduce_mode,select.thermostat_hc1_reducemode,6,1,1,30,1
UI800/BC400,thermostat,4,noreducetemp,no reduce below temperature,int8 (>=-126<=126),C,true,number.thermostat_hc1_no_reduce_below_temperature,number.thermostat_hc1_noreducetemp,6,1,1,31,1
UI800/BC400,thermostat,4,reducetemp,off/reduce switch temperature,int8 (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp,6,1,1,32,1
UI800/BC400,thermostat,4,dhwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_dhwprio,6,1,1,33,1
UI800/BC400,thermostat,4,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling,6,1,1,34,1
UI800/BC400,thermostat,4,coolingon,cooling,boolean, ,false,binary_sensor.thermostat_hc1_cooling,binary_sensor.thermostat_hc1_coolingon,6,1,1,35,1
UI800/BC400,thermostat,4,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode,6,1,1,36,1
UI800/BC400,thermostat,4,hpcooling,hp cooling,boolean, ,true,switch.thermostat_hc1_hp_cooling,switch.thermostat_hc1_hpcooling,6,1,1,34,1
UI800/BC400,thermostat,4,coolingon,cooling on,boolean, ,false,binary_sensor.thermostat_hc1_cooling_on,binary_sensor.thermostat_hc1_coolingon,6,1,1,35,1
UI800/BC400,thermostat,4,hpmode,HP Mode,enum [heating\|cooling\|heating & cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode,6,1,1,36,1
UI800/BC400,thermostat,4,dewoffset,dew point offset,uint8 (>=2<=10),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset,6,1,1,37,1
UI800/BC400,thermostat,4,roomtempdiff,room temp difference,uint8 (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff,6,1,1,38,1
UI800/BC400,thermostat,4,hpminflowtemp,HP min. flow temp.,uint8 (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp,6,1,1,39,1
@@ -3376,10 +3376,10 @@ UI800/BC400,thermostat,4,heatoffdelay,heat-off delay,uint8 (>=1<=48),hours,true,
UI800/BC400,thermostat,4,instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,45,1
UI800/BC400,thermostat,4,boost,boost mode,boolean, ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,46,1
UI800/BC400,thermostat,4,boosttime,boost time,uint8 (>=0<=254),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,47,1
UI800/BC400,thermostat,4,coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,-1,1
UI800/BC400,thermostat,4,coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,-1,1
UI800/BC400,thermostat,4,cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,-1,1
UI800/BC400,thermostat,4,switchprogmode,switch program mode,enum [level\|absolute], ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,-1,1
UI800/BC400,thermostat,4,coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,193,1
UI800/BC400,thermostat,4,coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,194,1
UI800/BC400,thermostat,4,cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,195,1
UI800/BC400,thermostat,4,switchprogmode,switch program mode,enum [level\|absolute], ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,196,1
UI800/BC400,thermostat,4,mode,mode,enum [off\|eco+\|eco\|comfort\|auto], ,true,select.thermostat_dhw_mode,select.thermostat_dhw_mode,6,9,1,0,1
UI800/BC400,thermostat,4,settemp,set temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_set_temperature,number.thermostat_dhw_settemp,6,9,1,1,1
UI800/BC400,thermostat,4,settemplow,set low temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_set_low_temperature,number.thermostat_dhw_settemplow,6,9,1,2,1
@@ -3471,7 +3471,7 @@ RC30,thermostat,67,disinfectday,disinfection day,enum [mo\|tu\|we\|th\|fr\|sa\|s
RC30,thermostat,67,disinfecthour,disinfection hour,uint8 (>=0<=23), ,true,number.thermostat_dhw_disinfection_hour,number.thermostat_dhw_disinfecthour,6,9,1,14,1
RC30,thermostat,67,maxtemp,maximum temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_maximum_temperature,number.thermostat_dhw_maxtemp,6,9,1,15,1
RC30,thermostat,67,onetimekey,one time key function,boolean, ,true,switch.thermostat_dhw_one_time_key_function,switch.thermostat_dhw_onetimekey,6,9,1,16,1
RC30,thermostat,67,switchtime,program switchtime,string, ,true,sensor.thermostat_dhw_program_switchtime,sensor.thermostat_dhw_switchtime,6,9,1,17,8
RC30,thermostat,67,switchtimeWW,program switchtime warm water,string, ,true,sensor.thermostat_dhw_program_switchtime_warm_water,sensor.thermostat_dhw_switchtimeWW,6,9,1,17,8
RC30,thermostat,67,circswitchtime,circulation program switchtime,string, ,true,sensor.thermostat_dhw_circulation_program_switchtime,sensor.thermostat_dhw_circswitchtime,6,9,1,25,8
RC30,thermostat,67,holidays,holiday dates,string, ,true,sensor.thermostat_dhw_holiday_dates,sensor.thermostat_dhw_holidays,6,9,1,33,13
RC30,thermostat,67,vacations,vacation dates,string, ,true,sensor.thermostat_dhw_vacation_dates,sensor.thermostat_dhw_vacations,6,9,1,46,13
@@ -3488,7 +3488,7 @@ RC20/Moduline 300,thermostat,77,daytemp2,day temperature T2,uint8 (>=0<=127),C,t
RC20/Moduline 300,thermostat,77,daytemp3,day temperature T3,uint8 (>=0<=127),C,true,number.thermostat_hc1_day_temperature_T3,number.thermostat_hc1_daytemp3,6,1,1/2,101,1
RC20/Moduline 300,thermostat,77,daytemp4,day temperature T4,uint8 (>=0<=127),C,true,number.thermostat_hc1_day_temperature_T4,number.thermostat_hc1_daytemp4,6,1,1/2,102,1
RC20/Moduline 300,thermostat,77,nighttemp,night temperature T1,uint8 (>=0<=127),C,true,number.thermostat_hc1_night_temperature_T1,number.thermostat_hc1_nighttemp,6,1,1/2,49,1
RC20/Moduline 300,thermostat,77,switchtime,program switchtime,string, ,true,sensor.thermostat_hc1_program_switchtime,sensor.thermostat_hc1_switchtime,6,1,1,103,8
RC20/Moduline 300,thermostat,77,switchtime,program switchtime,string, ,true,sensor.thermostat_hc1_program_switchtime,sensor.thermostat_hc1_switchtime,6,1,1,197,8
Moduline 400,thermostat,78,errorcode,error code,string, ,false,sensor.thermostat_error_code,sensor.thermostat_errorcode,6,0,1,0,8
Moduline 400,thermostat,78,lastcode,last error code,string, ,false,sensor.thermostat_last_error_code,sensor.thermostat_lastcode,6,0,1,8,25
Moduline 400,thermostat,78,datetime,date/time,string, ,false,sensor.thermostat_date/time,sensor.thermostat_datetime,6,0,1,33,13
@@ -3617,7 +3617,7 @@ RC35,thermostat,86,disinfectday,disinfection day,enum [mo\|tu\|we\|th\|fr\|sa\|s
RC35,thermostat,86,disinfecthour,disinfection hour,uint8 (>=0<=23), ,true,number.thermostat_dhw_disinfection_hour,number.thermostat_dhw_disinfecthour,6,9,1,14,1
RC35,thermostat,86,maxtemp,maximum temperature,uint8 (>=60<=80),C,true,number.thermostat_dhw_maximum_temperature,number.thermostat_dhw_maxtemp,6,9,1,15,1
RC35,thermostat,86,onetimekey,one time key function,boolean, ,true,switch.thermostat_dhw_one_time_key_function,switch.thermostat_dhw_onetimekey,6,9,1,16,1
RC35,thermostat,86,switchtime,program switchtime,string, ,true,sensor.thermostat_dhw_program_switchtime,sensor.thermostat_dhw_switchtime,6,9,1,17,8
RC35,thermostat,86,switchtimeWW,program switchtime warm water,string, ,true,sensor.thermostat_dhw_program_switchtime_warm_water,sensor.thermostat_dhw_switchtimeWW,6,9,1,17,8
RC35,thermostat,86,circswitchtime,circulation program switchtime,string, ,true,sensor.thermostat_dhw_circulation_program_switchtime,sensor.thermostat_dhw_circswitchtime,6,9,1,25,8
RC35,thermostat,86,holidays,holiday dates,string, ,true,sensor.thermostat_dhw_holiday_dates,sensor.thermostat_dhw_holidays,6,9,1,33,13
RC35,thermostat,86,vacations,vacation dates,string, ,true,sensor.thermostat_dhw_vacation_dates,sensor.thermostat_dhw_vacations,6,9,1,46,13
@@ -3652,7 +3652,7 @@ RC20RF,thermostat,93,daytemp2,day temperature T2,uint8 (>=0<=127),C,true,number.
RC20RF,thermostat,93,daytemp3,day temperature T3,uint8 (>=0<=127),C,true,number.thermostat_hc1_day_temperature_T3,number.thermostat_hc1_daytemp3,6,1,1/2,101,1
RC20RF,thermostat,93,daytemp4,day temperature T4,uint8 (>=0<=127),C,true,number.thermostat_hc1_day_temperature_T4,number.thermostat_hc1_daytemp4,6,1,1/2,102,1
RC20RF,thermostat,93,nighttemp,night temperature T1,uint8 (>=0<=127),C,true,number.thermostat_hc1_night_temperature_T1,number.thermostat_hc1_nighttemp,6,1,1/2,49,1
RC20RF,thermostat,93,switchtime,program switchtime,string, ,true,sensor.thermostat_hc1_program_switchtime,sensor.thermostat_hc1_switchtime,6,1,1,103,8
RC20RF,thermostat,93,switchtime,program switchtime,string, ,true,sensor.thermostat_hc1_program_switchtime,sensor.thermostat_hc1_switchtime,6,1,1,197,8
RFM20 Remote,thermostat,94,errorcode,error code,string, ,false,sensor.thermostat_error_code,sensor.thermostat_errorcode,6,0,1,0,8
RFM20 Remote,thermostat,94,lastcode,last error code,string, ,false,sensor.thermostat_last_error_code,sensor.thermostat_lastcode,6,0,1,8,25
RFM20 Remote,thermostat,94,datetime,date/time,string, ,false,sensor.thermostat_date/time,sensor.thermostat_datetime,6,0,1,33,13
@@ -3724,16 +3724,16 @@ RC200/CW100/CR120,thermostat,157,hpoperatingstate,heatpump operating state,enum
RC200/CW100/CR120,thermostat,157,controlmode,control mode,enum [optimized\|simple\|n/a\|room\|power], ,true,select.thermostat_hc1_control_mode,select.thermostat_hc1_controlmode,6,1,1,24,1
RC200/CW100/CR120,thermostat,157,program,program,enum [prog 1\|prog 2], ,true,select.thermostat_hc1_program,select.thermostat_hc1_program,6,1,1,25,1
RC200/CW100/CR120,thermostat,157,tempautotemp,temporary set temperature automode,int8 (>=-1<=30),C,true,number.thermostat_hc1_temporary_set_temperature_automode,number.thermostat_hc1_tempautotemp,6,1,1/2,26,1
RC200/CW100/CR120,thermostat,157,remoteseltemp,temporary set temperature from remote,int8 (>=-63<=63),C,false,sensor.thermostat_hc1_temporary_set_temperature_from_remote,sensor.thermostat_hc1_remoteseltemp,6,1,1/2,27,1
RC200/CW100/CR120,thermostat,157,remoteseltemp,temporary set temperature from remote,int8 (>=-1<=30),C,true,number.thermostat_hc1_temporary_set_temperature_from_remote,number.thermostat_hc1_remoteseltemp,6,1,1/2,27,1
RC200/CW100/CR120,thermostat,157,fastheatup,fast heatup,uint8 (>=0<=100),%,true,number.thermostat_hc1_fast_heatup,number.thermostat_hc1_fastheatup,6,1,1,28,1
RC200/CW100/CR120,thermostat,157,switchonoptimization,switch-on optimization,boolean, ,true,switch.thermostat_hc1_switch-on_optimization,switch.thermostat_hc1_switchonoptimization,6,1,1,29,1
RC200/CW100/CR120,thermostat,157,reducemode,reduce mode,enum [outdoor\|room\|reduce], ,true,select.thermostat_hc1_reduce_mode,select.thermostat_hc1_reducemode,6,1,1,30,1
RC200/CW100/CR120,thermostat,157,noreducetemp,no reduce below temperature,int8 (>=-126<=126),C,true,number.thermostat_hc1_no_reduce_below_temperature,number.thermostat_hc1_noreducetemp,6,1,1,31,1
RC200/CW100/CR120,thermostat,157,reducetemp,off/reduce switch temperature,int8 (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp,6,1,1,32,1
RC200/CW100/CR120,thermostat,157,dhwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_dhwprio,6,1,1,33,1
RC200/CW100/CR120,thermostat,157,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling,6,1,1,34,1
RC200/CW100/CR120,thermostat,157,coolingon,cooling,boolean, ,false,binary_sensor.thermostat_hc1_cooling,binary_sensor.thermostat_hc1_coolingon,6,1,1,35,1
RC200/CW100/CR120,thermostat,157,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode,6,1,1,36,1
RC200/CW100/CR120,thermostat,157,hpcooling,hp cooling,boolean, ,true,switch.thermostat_hc1_hp_cooling,switch.thermostat_hc1_hpcooling,6,1,1,34,1
RC200/CW100/CR120,thermostat,157,coolingon,cooling on,boolean, ,false,binary_sensor.thermostat_hc1_cooling_on,binary_sensor.thermostat_hc1_coolingon,6,1,1,35,1
RC200/CW100/CR120,thermostat,157,hpmode,HP Mode,enum [heating\|cooling\|heating & cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode,6,1,1,36,1
RC200/CW100/CR120,thermostat,157,dewoffset,dew point offset,uint8 (>=2<=10),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset,6,1,1,37,1
RC200/CW100/CR120,thermostat,157,roomtempdiff,room temp difference,uint8 (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff,6,1,1,38,1
RC200/CW100/CR120,thermostat,157,hpminflowtemp,HP min. flow temp.,uint8 (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp,6,1,1,39,1
@@ -3745,10 +3745,10 @@ RC200/CW100/CR120,thermostat,157,heatoffdelay,heat-off delay,uint8 (>=1<=48),hou
RC200/CW100/CR120,thermostat,157,instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,45,1
RC200/CW100/CR120,thermostat,157,boost,boost mode,boolean, ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,46,1
RC200/CW100/CR120,thermostat,157,boosttime,boost time,uint8 (>=0<=254),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,47,1
RC200/CW100/CR120,thermostat,157,coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,-1,1
RC200/CW100/CR120,thermostat,157,coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,-1,1
RC200/CW100/CR120,thermostat,157,cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,-1,1
RC200/CW100/CR120,thermostat,157,switchprogmode,switch program mode,enum [level\|absolute], ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,-1,1
RC200/CW100/CR120,thermostat,157,coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,193,1
RC200/CW100/CR120,thermostat,157,coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,194,1
RC200/CW100/CR120,thermostat,157,cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,195,1
RC200/CW100/CR120,thermostat,157,switchprogmode,switch program mode,enum [level\|absolute], ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,196,1
RC200/CW100/CR120,thermostat,157,mode,mode,enum [off\|normal\|comfort\|auto\|own prog], ,true,select.thermostat_dhw_mode,select.thermostat_dhw_mode,6,9,1,0,1
RC200/CW100/CR120,thermostat,157,settemp,set temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_set_temperature,number.thermostat_dhw_settemp,6,9,1,1,1
RC200/CW100/CR120,thermostat,157,settemplow,set low temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_set_low_temperature,number.thermostat_dhw_settemplow,6,9,1,2,1
@@ -3808,16 +3808,16 @@ RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,hpoperating
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,controlmode,control mode,enum [weather compensated\|outside basepoint\|n/a\|room\|power\|constant], ,true,select.thermostat_hc1_control_mode,select.thermostat_hc1_controlmode,6,1,1,24,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,program,program,enum [prog 1\|prog 2], ,true,select.thermostat_hc1_program,select.thermostat_hc1_program,6,1,1,25,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,tempautotemp,temporary set temperature automode,int8 (>=-1<=30),C,true,number.thermostat_hc1_temporary_set_temperature_automode,number.thermostat_hc1_tempautotemp,6,1,1/2,26,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,remoteseltemp,temporary set temperature from remote,int8 (>=-63<=63),C,false,sensor.thermostat_hc1_temporary_set_temperature_from_remote,sensor.thermostat_hc1_remoteseltemp,6,1,1/2,27,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,remoteseltemp,temporary set temperature from remote,int8 (>=-1<=30),C,true,number.thermostat_hc1_temporary_set_temperature_from_remote,number.thermostat_hc1_remoteseltemp,6,1,1/2,27,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,fastheatup,fast heatup,uint8 (>=0<=100),%,true,number.thermostat_hc1_fast_heatup,number.thermostat_hc1_fastheatup,6,1,1,28,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,switchonoptimization,switch-on optimization,boolean, ,true,switch.thermostat_hc1_switch-on_optimization,switch.thermostat_hc1_switchonoptimization,6,1,1,29,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,reducemode,reduce mode,enum [outdoor\|room\|reduce], ,true,select.thermostat_hc1_reduce_mode,select.thermostat_hc1_reducemode,6,1,1,30,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,noreducetemp,no reduce below temperature,int8 (>=-126<=126),C,true,number.thermostat_hc1_no_reduce_below_temperature,number.thermostat_hc1_noreducetemp,6,1,1,31,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,reducetemp,off/reduce switch temperature,int8 (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp,6,1,1,32,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,dhwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_dhwprio,6,1,1,33,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling,6,1,1,34,1
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,6,1,1,35,1
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,6,1,1,36,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,hpcooling,hp cooling,boolean, ,true,switch.thermostat_hc1_hp_cooling,switch.thermostat_hc1_hpcooling,6,1,1,34,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,coolingon,cooling on,boolean, ,false,binary_sensor.thermostat_hc1_cooling_on,binary_sensor.thermostat_hc1_coolingon,6,1,1,35,1
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,6,1,1,36,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,dewoffset,dew point offset,uint8 (>=2<=10),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset,6,1,1,37,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,roomtempdiff,room temp difference,uint8 (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff,6,1,1,38,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,hpminflowtemp,HP min. flow temp.,uint8 (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp,6,1,1,39,1
@@ -3829,10 +3829,10 @@ RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,heatoffdela
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,45,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,boost,boost mode,boolean, ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,46,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,boosttime,boost time,uint8 (>=0<=254),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,47,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,-1,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,-1,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,-1,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,switchprogmode,switch program mode,enum [level\|absolute], ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,-1,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,193,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,194,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,195,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,switchprogmode,switch program mode,enum [level\|absolute], ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,196,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,mode,mode,enum [off\|normal\|comfort\|auto\|own prog], ,true,select.thermostat_dhw_mode,select.thermostat_dhw_mode,6,9,1,0,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,settemp,set temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_set_temperature,number.thermostat_dhw_settemp,6,9,1,1,1
RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410,thermostat,158,settemplow,set low temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_set_low_temperature,number.thermostat_dhw_settemplow,6,9,1,2,1
@@ -3892,16 +3892,16 @@ RC100/Moduline 1000/1010,thermostat,165,hpoperatingstate,heatpump operating stat
RC100/Moduline 1000/1010,thermostat,165,controlmode,control mode,enum [optimized\|simple\|n/a\|room\|power], ,true,select.thermostat_hc1_control_mode,select.thermostat_hc1_controlmode,6,1,1,24,1
RC100/Moduline 1000/1010,thermostat,165,program,program,enum [prog 1\|prog 2], ,true,select.thermostat_hc1_program,select.thermostat_hc1_program,6,1,1,25,1
RC100/Moduline 1000/1010,thermostat,165,tempautotemp,temporary set temperature automode,int8 (>=-1<=30),C,true,number.thermostat_hc1_temporary_set_temperature_automode,number.thermostat_hc1_tempautotemp,6,1,1/2,26,1
RC100/Moduline 1000/1010,thermostat,165,remoteseltemp,temporary set temperature from remote,int8 (>=-63<=63),C,false,sensor.thermostat_hc1_temporary_set_temperature_from_remote,sensor.thermostat_hc1_remoteseltemp,6,1,1/2,27,1
RC100/Moduline 1000/1010,thermostat,165,remoteseltemp,temporary set temperature from remote,int8 (>=-1<=30),C,true,number.thermostat_hc1_temporary_set_temperature_from_remote,number.thermostat_hc1_remoteseltemp,6,1,1/2,27,1
RC100/Moduline 1000/1010,thermostat,165,fastheatup,fast heatup,uint8 (>=0<=100),%,true,number.thermostat_hc1_fast_heatup,number.thermostat_hc1_fastheatup,6,1,1,28,1
RC100/Moduline 1000/1010,thermostat,165,switchonoptimization,switch-on optimization,boolean, ,true,switch.thermostat_hc1_switch-on_optimization,switch.thermostat_hc1_switchonoptimization,6,1,1,29,1
RC100/Moduline 1000/1010,thermostat,165,reducemode,reduce mode,enum [outdoor\|room\|reduce], ,true,select.thermostat_hc1_reduce_mode,select.thermostat_hc1_reducemode,6,1,1,30,1
RC100/Moduline 1000/1010,thermostat,165,noreducetemp,no reduce below temperature,int8 (>=-126<=126),C,true,number.thermostat_hc1_no_reduce_below_temperature,number.thermostat_hc1_noreducetemp,6,1,1,31,1
RC100/Moduline 1000/1010,thermostat,165,reducetemp,off/reduce switch temperature,int8 (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp,6,1,1,32,1
RC100/Moduline 1000/1010,thermostat,165,dhwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_dhwprio,6,1,1,33,1
RC100/Moduline 1000/1010,thermostat,165,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling,6,1,1,34,1
RC100/Moduline 1000/1010,thermostat,165,coolingon,cooling,boolean, ,false,binary_sensor.thermostat_hc1_cooling,binary_sensor.thermostat_hc1_coolingon,6,1,1,35,1
RC100/Moduline 1000/1010,thermostat,165,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode,6,1,1,36,1
RC100/Moduline 1000/1010,thermostat,165,hpcooling,hp cooling,boolean, ,true,switch.thermostat_hc1_hp_cooling,switch.thermostat_hc1_hpcooling,6,1,1,34,1
RC100/Moduline 1000/1010,thermostat,165,coolingon,cooling on,boolean, ,false,binary_sensor.thermostat_hc1_cooling_on,binary_sensor.thermostat_hc1_coolingon,6,1,1,35,1
RC100/Moduline 1000/1010,thermostat,165,hpmode,HP Mode,enum [heating\|cooling\|heating & cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode,6,1,1,36,1
RC100/Moduline 1000/1010,thermostat,165,dewoffset,dew point offset,uint8 (>=2<=10),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset,6,1,1,37,1
RC100/Moduline 1000/1010,thermostat,165,roomtempdiff,room temp difference,uint8 (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff,6,1,1,38,1
RC100/Moduline 1000/1010,thermostat,165,hpminflowtemp,HP min. flow temp.,uint8 (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp,6,1,1,39,1
@@ -3913,10 +3913,10 @@ RC100/Moduline 1000/1010,thermostat,165,heatoffdelay,heat-off delay,uint8 (>=1<=
RC100/Moduline 1000/1010,thermostat,165,instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,45,1
RC100/Moduline 1000/1010,thermostat,165,boost,boost mode,boolean, ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,46,1
RC100/Moduline 1000/1010,thermostat,165,boosttime,boost time,uint8 (>=0<=254),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,47,1
RC100/Moduline 1000/1010,thermostat,165,coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,-1,1
RC100/Moduline 1000/1010,thermostat,165,coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,-1,1
RC100/Moduline 1000/1010,thermostat,165,cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,-1,1
RC100/Moduline 1000/1010,thermostat,165,switchprogmode,switch program mode,enum [level\|absolute], ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,-1,1
RC100/Moduline 1000/1010,thermostat,165,coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,193,1
RC100/Moduline 1000/1010,thermostat,165,coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,194,1
RC100/Moduline 1000/1010,thermostat,165,cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,195,1
RC100/Moduline 1000/1010,thermostat,165,switchprogmode,switch program mode,enum [level\|absolute], ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,196,1
RC100/Moduline 1000/1010,thermostat,165,mode,mode,enum [off\|normal\|comfort\|auto\|own prog], ,true,select.thermostat_dhw_mode,select.thermostat_dhw_mode,6,9,1,0,1
RC100/Moduline 1000/1010,thermostat,165,settemp,set temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_set_temperature,number.thermostat_dhw_settemp,6,9,1,1,1
RC100/Moduline 1000/1010,thermostat,165,settemplow,set low temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_set_low_temperature,number.thermostat_dhw_settemplow,6,9,1,2,1
@@ -3977,16 +3977,16 @@ Rego 2000/3000,thermostat,172,hpoperatingstate,heatpump operating state,enum [he
Rego 2000/3000,thermostat,172,controlmode,control mode,enum [weather compensated\|outside basepoint\|n/a\|room\|power\|constant], ,true,select.thermostat_hc1_control_mode,select.thermostat_hc1_controlmode,6,1,1,24,1
Rego 2000/3000,thermostat,172,program,program,enum [prog 1\|prog 2], ,true,select.thermostat_hc1_program,select.thermostat_hc1_program,6,1,1,25,1
Rego 2000/3000,thermostat,172,tempautotemp,temporary set temperature automode,int8 (>=-1<=30),C,true,number.thermostat_hc1_temporary_set_temperature_automode,number.thermostat_hc1_tempautotemp,6,1,1/2,26,1
Rego 2000/3000,thermostat,172,remoteseltemp,temporary set temperature from remote,int8 (>=-63<=63),C,false,sensor.thermostat_hc1_temporary_set_temperature_from_remote,sensor.thermostat_hc1_remoteseltemp,6,1,1/2,27,1
Rego 2000/3000,thermostat,172,remoteseltemp,temporary set temperature from remote,int8 (>=-1<=30),C,true,number.thermostat_hc1_temporary_set_temperature_from_remote,number.thermostat_hc1_remoteseltemp,6,1,1/2,27,1
Rego 2000/3000,thermostat,172,fastheatup,fast heatup,uint8 (>=0<=100),%,true,number.thermostat_hc1_fast_heatup,number.thermostat_hc1_fastheatup,6,1,1,28,1
Rego 2000/3000,thermostat,172,switchonoptimization,switch-on optimization,boolean, ,true,switch.thermostat_hc1_switch-on_optimization,switch.thermostat_hc1_switchonoptimization,6,1,1,29,1
Rego 2000/3000,thermostat,172,reducemode,reduce mode,enum [outdoor\|room\|reduce], ,true,select.thermostat_hc1_reduce_mode,select.thermostat_hc1_reducemode,6,1,1,30,1
Rego 2000/3000,thermostat,172,noreducetemp,no reduce below temperature,int8 (>=-126<=126),C,true,number.thermostat_hc1_no_reduce_below_temperature,number.thermostat_hc1_noreducetemp,6,1,1,31,1
Rego 2000/3000,thermostat,172,reducetemp,off/reduce switch temperature,int8 (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp,6,1,1,32,1
Rego 2000/3000,thermostat,172,dhwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_dhwprio,6,1,1,33,1
Rego 2000/3000,thermostat,172,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling,6,1,1,34,1
Rego 2000/3000,thermostat,172,coolingon,cooling,boolean, ,false,binary_sensor.thermostat_hc1_cooling,binary_sensor.thermostat_hc1_coolingon,6,1,1,35,1
Rego 2000/3000,thermostat,172,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode,6,1,1,36,1
Rego 2000/3000,thermostat,172,hpcooling,hp cooling,boolean, ,true,switch.thermostat_hc1_hp_cooling,switch.thermostat_hc1_hpcooling,6,1,1,34,1
Rego 2000/3000,thermostat,172,coolingon,cooling on,boolean, ,false,binary_sensor.thermostat_hc1_cooling_on,binary_sensor.thermostat_hc1_coolingon,6,1,1,35,1
Rego 2000/3000,thermostat,172,hpmode,HP Mode,enum [heating\|cooling\|heating & cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode,6,1,1,36,1
Rego 2000/3000,thermostat,172,dewoffset,dew point offset,uint8 (>=2<=10),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset,6,1,1,37,1
Rego 2000/3000,thermostat,172,roomtempdiff,room temp difference,uint8 (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff,6,1,1,38,1
Rego 2000/3000,thermostat,172,hpminflowtemp,HP min. flow temp.,uint8 (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp,6,1,1,39,1
@@ -3998,10 +3998,10 @@ Rego 2000/3000,thermostat,172,heatoffdelay,heat-off delay,uint8 (>=1<=48),hours,
Rego 2000/3000,thermostat,172,instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,45,1
Rego 2000/3000,thermostat,172,boost,boost mode,boolean, ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,46,1
Rego 2000/3000,thermostat,172,boosttime,boost time,uint8 (>=0<=254),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,47,1
Rego 2000/3000,thermostat,172,coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,-1,1
Rego 2000/3000,thermostat,172,coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,-1,1
Rego 2000/3000,thermostat,172,cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,-1,1
Rego 2000/3000,thermostat,172,switchprogmode,switch program mode,enum [level\|absolute], ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,-1,1
Rego 2000/3000,thermostat,172,coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,193,1
Rego 2000/3000,thermostat,172,coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,194,1
Rego 2000/3000,thermostat,172,cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,195,1
Rego 2000/3000,thermostat,172,switchprogmode,switch program mode,enum [level\|absolute], ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,196,1
Rego 2000/3000,thermostat,172,mode,mode,enum [normal\|comfort\|eco+], ,true,select.thermostat_dhw_mode,select.thermostat_dhw_mode,6,9,1,0,1
Rego 2000/3000,thermostat,172,settemp,set temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_set_temperature,number.thermostat_dhw_settemp,6,9,1,1,1
Rego 2000/3000,thermostat,172,settemplow,set low temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_set_low_temperature,number.thermostat_dhw_settemplow,6,9,1,2,1
@@ -4088,16 +4088,16 @@ Rego 3000/UI800/WSW196i/BC400,thermostat,253,hpoperatingstate,heatpump operating
Rego 3000/UI800/WSW196i/BC400,thermostat,253,controlmode,control mode,enum [weather compensated\|outside basepoint\|n/a\|room\|power\|constant], ,true,select.thermostat_hc1_control_mode,select.thermostat_hc1_controlmode,6,1,1,24,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,program,program,enum [prog 1\|prog 2], ,true,select.thermostat_hc1_program,select.thermostat_hc1_program,6,1,1,25,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,tempautotemp,temporary set temperature automode,int8 (>=-1<=30),C,true,number.thermostat_hc1_temporary_set_temperature_automode,number.thermostat_hc1_tempautotemp,6,1,1/2,26,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,remoteseltemp,temporary set temperature from remote,int8 (>=-63<=63),C,false,sensor.thermostat_hc1_temporary_set_temperature_from_remote,sensor.thermostat_hc1_remoteseltemp,6,1,1/2,27,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,remoteseltemp,temporary set temperature from remote,int8 (>=-1<=30),C,true,number.thermostat_hc1_temporary_set_temperature_from_remote,number.thermostat_hc1_remoteseltemp,6,1,1/2,27,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,fastheatup,fast heatup,uint8 (>=0<=100),%,true,number.thermostat_hc1_fast_heatup,number.thermostat_hc1_fastheatup,6,1,1,28,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,switchonoptimization,switch-on optimization,boolean, ,true,switch.thermostat_hc1_switch-on_optimization,switch.thermostat_hc1_switchonoptimization,6,1,1,29,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,reducemode,reduce mode,enum [outdoor\|room\|reduce], ,true,select.thermostat_hc1_reduce_mode,select.thermostat_hc1_reducemode,6,1,1,30,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,noreducetemp,no reduce below temperature,int8 (>=-126<=126),C,true,number.thermostat_hc1_no_reduce_below_temperature,number.thermostat_hc1_noreducetemp,6,1,1,31,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,reducetemp,off/reduce switch temperature,int8 (>=-126<=126),C,true,number.thermostat_hc1_off/reduce_switch_temperature,number.thermostat_hc1_reducetemp,6,1,1,32,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,dhwprio,dhw priority,boolean, ,true,switch.thermostat_hc1_dhw_priority,switch.thermostat_hc1_dhwprio,6,1,1,33,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,cooling,cooling,boolean, ,true,switch.thermostat_hc1_cooling,switch.thermostat_hc1_cooling,6,1,1,34,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,coolingon,cooling,boolean, ,false,binary_sensor.thermostat_hc1_cooling,binary_sensor.thermostat_hc1_coolingon,6,1,1,35,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,hpmode,HP Mode,enum [heating\|cooling\|heating&cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode,6,1,1,36,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,hpcooling,hp cooling,boolean, ,true,switch.thermostat_hc1_hp_cooling,switch.thermostat_hc1_hpcooling,6,1,1,34,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,coolingon,cooling on,boolean, ,false,binary_sensor.thermostat_hc1_cooling_on,binary_sensor.thermostat_hc1_coolingon,6,1,1,35,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,hpmode,HP Mode,enum [heating\|cooling\|heating & cooling], ,true,select.thermostat_hc1_HP_Mode,select.thermostat_hc1_hpmode,6,1,1,36,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,dewoffset,dew point offset,uint8 (>=2<=10),K,true,number.thermostat_hc1_dew_point_offset,number.thermostat_hc1_dewoffset,6,1,1,37,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,roomtempdiff,room temp difference,uint8 (>=0<=254),K,true,number.thermostat_hc1_room_temp_difference,number.thermostat_hc1_roomtempdiff,6,1,1,38,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,hpminflowtemp,HP min. flow temp.,uint8 (>=0<=254),C,true,number.thermostat_hc1_HP_min._flow_temp.,number.thermostat_hc1_hpminflowtemp,6,1,1,39,1
@@ -4109,10 +4109,10 @@ Rego 3000/UI800/WSW196i/BC400,thermostat,253,heatoffdelay,heat-off delay,uint8 (
Rego 3000/UI800/WSW196i/BC400,thermostat,253,instantstart,instant start,uint8 (>=1<=10),K,true,number.thermostat_hc1_instant_start,number.thermostat_hc1_instantstart,6,1,1,45,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,boost,boost mode,boolean, ,true,switch.thermostat_hc1_boost_mode,switch.thermostat_hc1_boost,6,1,1,46,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,boosttime,boost time,uint8 (>=0<=254),hours,true,number.thermostat_hc1_boost_time,number.thermostat_hc1_boosttime,6,1,1,47,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,-1,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,-1,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,-1,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,switchprogmode,switch program mode,enum [level\|absolute], ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,-1,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,coolstart,cooling starttemp,uint8 (>=20<=35),C,true,number.thermostat_hc1_cooling_starttemp,number.thermostat_hc1_coolstart,6,1,1,193,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,coolondelay,cooling on delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_on_delay,number.thermostat_hc1_coolondelay,6,1,1,194,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,cooloffdelay,cooling off delay,uint8 (>=1<=48),hours,true,number.thermostat_hc1_cooling_off_delay,number.thermostat_hc1_cooloffdelay,6,1,1,195,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,switchprogmode,switch program mode,enum [level\|absolute], ,true,select.thermostat_hc1_switch_program_mode,select.thermostat_hc1_switchprogmode,6,1,1,196,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,mode,mode,enum [off\|eco+\|eco\|comfort\|auto], ,true,select.thermostat_dhw_mode,select.thermostat_dhw_mode,6,9,1,0,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,settemp,set temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_set_temperature,number.thermostat_dhw_settemp,6,9,1,1,1
Rego 3000/UI800/WSW196i/BC400,thermostat,253,settemplow,set low temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_set_low_temperature,number.thermostat_dhw_settemplow,6,9,1,2,1
@@ -4204,7 +4204,7 @@ ES73,thermostat,76,disinfectday,disinfection day,enum [mo\|tu\|we\|th\|fr\|sa\|s
ES73,thermostat,76,disinfecthour,disinfection hour,uint8 (>=0<=23), ,true,number.thermostat_dhw_disinfection_hour,number.thermostat_dhw_disinfecthour,6,9,1,14,1
ES73,thermostat,76,maxtemp,maximum temperature,uint8 (>=0<=254),C,true,number.thermostat_dhw_maximum_temperature,number.thermostat_dhw_maxtemp,6,9,1,15,1
ES73,thermostat,76,onetimekey,one time key function,boolean, ,true,switch.thermostat_dhw_one_time_key_function,switch.thermostat_dhw_onetimekey,6,9,1,16,1
ES73,thermostat,76,switchtime,program switchtime,string, ,true,sensor.thermostat_dhw_program_switchtime,sensor.thermostat_dhw_switchtime,6,9,1,17,8
ES73,thermostat,76,switchtimeWW,program switchtime warm water,string, ,true,sensor.thermostat_dhw_program_switchtime_warm_water,sensor.thermostat_dhw_switchtimeWW,6,9,1,17,8
ES73,thermostat,76,circswitchtime,circulation program switchtime,string, ,true,sensor.thermostat_dhw_circulation_program_switchtime,sensor.thermostat_dhw_circswitchtime,6,9,1,25,8
ES73,thermostat,76,holidays,holiday dates,string, ,true,sensor.thermostat_dhw_holiday_dates,sensor.thermostat_dhw_holidays,6,9,1,33,13
ES73,thermostat,76,vacations,vacation dates,string, ,true,sensor.thermostat_dhw_vacation_dates,sensor.thermostat_dhw_vacations,6,9,1,46,13
@@ -4284,7 +4284,7 @@ ES79,thermostat,156,disinfectday,disinfection day,enum [mo\|tu\|we\|th\|fr\|sa\|
ES79,thermostat,156,disinfecthour,disinfection hour,uint8 (>=0<=23), ,true,number.thermostat_dhw_disinfection_hour,number.thermostat_dhw_disinfecthour,6,9,1,14,1
ES79,thermostat,156,maxtemp,maximum temperature,uint8 (>=60<=80),C,true,number.thermostat_dhw_maximum_temperature,number.thermostat_dhw_maxtemp,6,9,1,15,1
ES79,thermostat,156,onetimekey,one time key function,boolean, ,true,switch.thermostat_dhw_one_time_key_function,switch.thermostat_dhw_onetimekey,6,9,1,16,1
ES79,thermostat,156,switchtime,program switchtime,string, ,true,sensor.thermostat_dhw_program_switchtime,sensor.thermostat_dhw_switchtime,6,9,1,17,8
ES79,thermostat,156,switchtimeWW,program switchtime warm water,string, ,true,sensor.thermostat_dhw_program_switchtime_warm_water,sensor.thermostat_dhw_switchtimeWW,6,9,1,17,8
ES79,thermostat,156,circswitchtime,circulation program switchtime,string, ,true,sensor.thermostat_dhw_circulation_program_switchtime,sensor.thermostat_dhw_circswitchtime,6,9,1,25,8
ES79,thermostat,156,holidays,holiday dates,string, ,true,sensor.thermostat_dhw_holiday_dates,sensor.thermostat_dhw_holidays,6,9,1,33,13
ES79,thermostat,156,vacations,vacation dates,string, ,true,sensor.thermostat_dhw_vacation_dates,sensor.thermostat_dhw_vacations,6,9,1,46,13
@@ -4808,8 +4808,8 @@ SM50,solar,162,externalcyl,external cylinder,boolean, ,true,switch.solar_externa
SM50,solar,162,thermaldisinfect,thermal disinfection,boolean, ,true,switch.solar_thermal_disinfection,switch.solar_thermaldisinfect,8,0,1,41,1
SM50,solar,162,heatmetering,heatmetering,boolean, ,true,switch.solar_heatmetering,switch.solar_heatmetering,8,0,1,42,1
SM50,solar,162,activated,activated,boolean, ,true,switch.solar_activated,switch.solar_activated,8,0,1,43,1
SM50,solar,162,solarpumpmode,pump mode,enum [constant\|pwm\|analog], ,true,select.solar_pump_mode,select.solar_solarpumpmode,8,0,1,44,1
SM50,solar,162,pumpkick,pump kick,boolean, ,true,switch.solar_pump_kick,switch.solar_pumpkick,8,0,1,45,1
SM50,solar,162,solarpumpmode,solar pump mode,enum [constant\|pwm\|analog], ,true,select.solar_solar_pump_mode,select.solar_solarpumpmode,8,0,1,44,1
SM50,solar,162,solarpumpkick,solar pump kick,boolean, ,true,switch.solar_solar_pump_kick,switch.solar_solarpumpkick,8,0,1,45,1
SM50,solar,162,plainwatermode,plain water mode,boolean, ,true,switch.solar_plain_water_mode,switch.solar_plainwatermode,8,0,1,46,1
SM50,solar,162,doublematchflow,doublematchflow,boolean, ,true,switch.solar_doublematchflow,switch.solar_doublematchflow,8,0,1,47,1
SM50,solar,162,pump2minmod,minimum pump 2 modulation,uint8 (>=0<=100),%,true,number.solar_minimum_pump_2_modulation,number.solar_pump2minmod,8,0,1,48,1
@@ -4862,8 +4862,8 @@ SM100/MS100,solar,163,externalcyl,external cylinder,boolean, ,true,switch.solar_
SM100/MS100,solar,163,thermaldisinfect,thermal disinfection,boolean, ,true,switch.solar_thermal_disinfection,switch.solar_thermaldisinfect,8,0,1,41,1
SM100/MS100,solar,163,heatmetering,heatmetering,boolean, ,true,switch.solar_heatmetering,switch.solar_heatmetering,8,0,1,42,1
SM100/MS100,solar,163,activated,activated,boolean, ,true,switch.solar_activated,switch.solar_activated,8,0,1,43,1
SM100/MS100,solar,163,solarpumpmode,pump mode,enum [constant\|pwm\|analog], ,true,select.solar_pump_mode,select.solar_solarpumpmode,8,0,1,44,1
SM100/MS100,solar,163,pumpkick,pump kick,boolean, ,true,switch.solar_pump_kick,switch.solar_pumpkick,8,0,1,45,1
SM100/MS100,solar,163,solarpumpmode,solar pump mode,enum [constant\|pwm\|analog], ,true,select.solar_solar_pump_mode,select.solar_solarpumpmode,8,0,1,44,1
SM100/MS100,solar,163,solarpumpkick,solar pump kick,boolean, ,true,switch.solar_solar_pump_kick,switch.solar_solarpumpkick,8,0,1,45,1
SM100/MS100,solar,163,plainwatermode,plain water mode,boolean, ,true,switch.solar_plain_water_mode,switch.solar_plainwatermode,8,0,1,46,1
SM100/MS100,solar,163,doublematchflow,doublematchflow,boolean, ,true,switch.solar_doublematchflow,switch.solar_doublematchflow,8,0,1,47,1
SM100/MS100,solar,163,pump2minmod,minimum pump 2 modulation,uint8 (>=0<=100),%,true,number.solar_minimum_pump_2_modulation,number.solar_pump2minmod,8,0,1,48,1
@@ -4916,8 +4916,8 @@ SM200/MS200,solar,164,externalcyl,external cylinder,boolean, ,true,switch.solar_
SM200/MS200,solar,164,thermaldisinfect,thermal disinfection,boolean, ,true,switch.solar_thermal_disinfection,switch.solar_thermaldisinfect,8,0,1,41,1
SM200/MS200,solar,164,heatmetering,heatmetering,boolean, ,true,switch.solar_heatmetering,switch.solar_heatmetering,8,0,1,42,1
SM200/MS200,solar,164,activated,activated,boolean, ,true,switch.solar_activated,switch.solar_activated,8,0,1,43,1
SM200/MS200,solar,164,solarpumpmode,pump mode,enum [constant\|pwm\|analog], ,true,select.solar_pump_mode,select.solar_solarpumpmode,8,0,1,44,1
SM200/MS200,solar,164,pumpkick,pump kick,boolean, ,true,switch.solar_pump_kick,switch.solar_pumpkick,8,0,1,45,1
SM200/MS200,solar,164,solarpumpmode,solar pump mode,enum [constant\|pwm\|analog], ,true,select.solar_solar_pump_mode,select.solar_solarpumpmode,8,0,1,44,1
SM200/MS200,solar,164,solarpumpkick,solar pump kick,boolean, ,true,switch.solar_solar_pump_kick,switch.solar_solarpumpkick,8,0,1,45,1
SM200/MS200,solar,164,plainwatermode,plain water mode,boolean, ,true,switch.solar_plain_water_mode,switch.solar_plainwatermode,8,0,1,46,1
SM200/MS200,solar,164,doublematchflow,doublematchflow,boolean, ,true,switch.solar_doublematchflow,switch.solar_doublematchflow,8,0,1,47,1
SM200/MS200,solar,164,pump2minmod,minimum pump 2 modulation,uint8 (>=0<=100),%,true,number.solar_minimum_pump_2_modulation,number.solar_pump2minmod,8,0,1,48,1
Can't render this file because it is too large.

View File

@@ -105,10 +105,10 @@ telegram_type_id,name,is_fetched,is_cmd
0x02A0,RC300Curves, ,cmd
0x02A1,RC300Curves, ,cmd
0x02A2,RC300Curves, ,cmd
0x02A5,CRFMonitor, ,cmd
0x02A5,RC300Monitor, ,cmd
0x02A6,RC300Monitor, ,cmd
0x02A7,RC300Monitor, ,cmd
0x02A8,RC300Monitor, ,cmd
0x02A8,CRFMonitor, ,cmd
0x02A9,RC300Monitor, ,cmd
0x02AA,RC300Monitor, ,cmd
0x02AB,RC300Monitor, ,cmd
@@ -129,7 +129,7 @@ telegram_type_id,name,is_fetched,is_cmd
0x02BE,RC300Set, ,cmd
0x02BF,RC300Set, ,cmd
0x02C0,RC300Set, ,cmd
0x02CC,RC300Set2, ,cmd
0x02CC,HPPressure,fetched,cmd
0x02CD,MMPLUSConfigMessage,fetched,cmd
0x02CE,RC300Set2, ,cmd
0x02D0,RC300Set2, ,cmd
1 telegram_type_id name is_fetched is_cmd
105 0x02A0 RC300Curves cmd
106 0x02A1 RC300Curves cmd
107 0x02A2 RC300Curves cmd
108 0x02A5 CRFMonitor RC300Monitor cmd
109 0x02A6 RC300Monitor cmd
110 0x02A7 RC300Monitor cmd
111 0x02A8 RC300Monitor CRFMonitor cmd
112 0x02A9 RC300Monitor cmd
113 0x02AA RC300Monitor cmd
114 0x02AB RC300Monitor cmd
129 0x02BE RC300Set cmd
130 0x02BF RC300Set cmd
131 0x02C0 RC300Set cmd
132 0x02CC RC300Set2 HPPressure fetched cmd
133 0x02CD MMPLUSConfigMessage fetched cmd
134 0x02CE RC300Set2 cmd
135 0x02D0 RC300Set2 cmd

View File

@@ -35,10 +35,10 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",
"react-router-dom": "^6.26.1",
"react-router-dom": "^6.26.2",
"react-toastify": "^10.0.5",
"typesafe-i18n": "^5.26.2",
"typescript": "^5.5.4"
"typescript": "^5.6.2"
},
"devDependencies": {
"@babel/core": "^7.25.2",
@@ -52,15 +52,15 @@
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"@types/react-router-dom": "^5.3.3",
"concurrently": "^8.2.2",
"concurrently": "^9.0.0",
"eslint": "^9.10.0",
"eslint-config-prettier": "^9.1.0",
"formidable": "^3.5.1",
"prettier": "^3.3.3",
"rollup-plugin-visualizer": "^5.12.0",
"terser": "^5.31.6",
"typescript-eslint": "8.4.0",
"vite": "^5.4.3",
"terser": "^5.32.0",
"typescript-eslint": "8.5.0",
"vite": "^5.4.4",
"vite-plugin-imagemin": "^0.6.1",
"vite-tsconfig-paths": "^5.0.1"
},

View File

@@ -102,7 +102,7 @@ const Help = () => {
color="primary"
onClick={() => callAPI('system', 'info')}
>
{LL.SUPPORT_INFORMATION(0)}
{LL.DOWNLOAD(1)}&nbsp;{LL.SUPPORT_INFORMATION(0)}
</Button>
</Box>
@@ -113,24 +113,24 @@ const Help = () => {
color="primary"
onClick={() => callAPI('system', 'allvalues')}
>
{LL.ALLVALUES()}
{LL.DOWNLOAD(1)}&nbsp;{LL.ALLVALUES()}
</Button>
<Box border={1} p={1} mt={4}>
<Typography align="center" variant="subtitle1" color="orange">
<b>{LL.HELP_INFORMATION_5()}</b>
<Box sx={{ p: 2, mt: 4, border: '1px dashed orange' }}>
<Typography align="center" variant="subtitle1">
{LL.HELP_INFORMATION_5()}
</Typography>
<Typography align="center">
<Typography align="center" mt={1}>
<Link
target="_blank"
href="https://github.com/emsesp/EMS-ESP32"
color="primary"
>
{'github.com/emsesp/EMS-ESP32'}
{'https://github.com/emsesp/EMS-ESP32'}
</Link>
</Typography>
<Typography color="white" variant="subtitle2" align="center">
@proddy @MichaelDvP
<Typography color="white" variant="subtitle1" align="center">
&copy;&nbsp;emsesp.org
</Typography>
</Box>
</SectionContent>

View File

@@ -613,10 +613,10 @@ const ApplicationSettings = () => {
name="tx_mode"
label={LL.TX_MODE()}
value={data.tx_mode}
fullWidth
variant="outlined"
onChange={updateFormValue}
margin="normal"
sx={{ width: '15ch' }}
select
>
<MenuItem value={1}>EMS</MenuItem>

View File

@@ -15,6 +15,7 @@ import {
Link,
Typography
} from '@mui/material';
import Grid from '@mui/material/Grid2';
import * as SystemApi from 'api/system';
import {
@@ -291,34 +292,11 @@ const DownloadUpload = () => {
<Typography sx={{ pb: 2 }} variant="h6" color="primary">
{LL.DOWNLOAD(0)}
</Typography>
<Box color="warning.main">
<Typography mb={1} variant="body2">
{LL.HELP_INFORMATION_4()}
</Typography>
<Button
sx={{ ml: 2 }}
startIcon={<DownloadIcon />}
variant="outlined"
color="primary"
onClick={() => callAPIandSave('system', 'info')}
>
{LL.SUPPORT_INFORMATION(0)}
</Button>
<Button
sx={{ ml: 2 }}
startIcon={<DownloadIcon />}
variant="outlined"
color="primary"
onClick={() => callAPIandSave('system', 'allvalues')}
>
{LL.ALLVALUES()}
</Button>
</Box>
<Box color="warning.main">
<Typography mt={2} mb={1} variant="body2">
{LL.DOWNLOAD_SETTINGS_TEXT()}
</Typography>
<Typography mb={1} variant="body2" color="warning">
{LL.DOWNLOAD_SETTINGS_TEXT()}
</Typography>
<Grid container spacing={1}>
<Button
sx={{ ml: 2 }}
startIcon={<DownloadIcon />}
@@ -326,14 +304,9 @@ const DownloadUpload = () => {
color="primary"
onClick={downloadSettings}
>
{LL.SETTINGS_OF('')}
{LL.DOWNLOAD(1)}&nbsp;{LL.SETTINGS_OF(LL.APPLICATION())}
</Button>
</Box>
<Box color="warning.main">
<Typography mt={2} mb={1} variant="body2">
{LL.DOWNLOAD_CUSTOMIZATION_TEXT()}
</Typography>
<Button
sx={{ ml: 2 }}
startIcon={<DownloadIcon />}
@@ -341,7 +314,7 @@ const DownloadUpload = () => {
color="primary"
onClick={downloadCustomizations}
>
{LL.CUSTOMIZATIONS()}
{LL.DOWNLOAD(1)}&nbsp;{LL.CUSTOMIZATIONS()}
</Button>
<Button
sx={{ ml: 2 }}
@@ -350,13 +323,8 @@ const DownloadUpload = () => {
color="primary"
onClick={downloadEntities}
>
{LL.CUSTOM_ENTITIES(0)}
{LL.DOWNLOAD(1)}&nbsp;{LL.CUSTOM_ENTITIES(0)}
</Button>
<Box color="warning.main">
<Typography mt={2} mb={1} variant="body2">
{LL.DOWNLOAD_SCHEDULE_TEXT()}
</Typography>
</Box>
<Button
sx={{ ml: 2 }}
startIcon={<DownloadIcon />}
@@ -364,15 +332,24 @@ const DownloadUpload = () => {
color="primary"
onClick={downloadSchedule}
>
{LL.SCHEDULE(0)}
{LL.DOWNLOAD(1)}&nbsp;{LL.SCHEDULE(0)}
</Button>
</Grid>
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
{LL.UPLOAD()}
</Typography>
<Box color="warning.main" sx={{ pb: 2 }}>
<Typography variant="body2">{LL.UPLOAD_TEXT()}</Typography>
</Box>
<Box color="warning.main">
<Typography mt={2} variant="body2">
{LL.EMS_ESP_VER()}
</Typography>
</Box>
<SingleUpload doRestart={doRestart} />
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
{LL.EMS_ESP_VER()}
</Typography>
<Box p={2} mt={2} border="1px solid grey" borderRadius={2}>
<Typography>
<b>{LL.VERSION() + ':'}</b>&nbsp;{data.emsesp_version}
@@ -430,16 +407,6 @@ const DownloadUpload = () => {
{renderUploadDialog()}
</Box>
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
{LL.UPLOAD()}
</Typography>
<Box color="warning.main" sx={{ pb: 2 }}>
<Typography variant="body2">{LL.UPLOAD_TEXT()}</Typography>
</Box>
<SingleUpload doRestart={doRestart} />
</>
);
};

View File

@@ -59,9 +59,10 @@ const RestartMonitor = () => {
: data?.status === 'ready'
? LL.RESTARTING_PRE()
: LL.RESTARTING_POST()}
&hellip;
</Typography>
<Typography mt={2} variant="h6" fontWeight={400} textAlign="center">
{LL.PLEASE_WAIT()}&hellip;
{LL.PLEASE_WAIT()}
</Typography>
{errorMessage ? (

View File

@@ -6,8 +6,12 @@ import WarningIcon from '@mui/icons-material/Warning';
import { Box, Button, Checkbox, MenuItem, TextField, styled } from '@mui/material';
import Grid from '@mui/material/Grid2';
import * as SystemApi from 'api/system';
import { fetchLogES } from 'api/system';
import {
fetchLog,
fetchLogES,
readLogSettings,
updateLogSettings
} from 'api/system';
import { useRequest, useSSE } from 'alova/client';
import {
@@ -22,20 +26,18 @@ import type { LogEntry, LogSettings } from 'types';
import { LogLevel } from 'types';
import { updateValueDirty, useRest } from 'utils';
const ButtonTextColors = {
const TextColors = {
[LogLevel.ERROR]: '#ff0000', // red
[LogLevel.WARNING]: '#ffcc00', // yellow
[LogLevel.WARNING]: '#ff0000', // red
[LogLevel.NOTICE]: '#ffffff', // white
[LogLevel.INFO]: '#ffffff', // yellow
[LogLevel.INFO]: '#ffcc00', // yellow
[LogLevel.DEBUG]: '#00ffff', // cyan
[LogLevel.TRACE]: '#00ffff' // cyan
};
const LogEntryLine = styled('div')(
const LogEntryLine = styled('span')(
({ details: { level } }: { details: { level: LogLevel } }) => ({
color: ButtonTextColors[level],
font: '14px monospace',
whiteSpace: 'nowrap'
color: TextColors[level]
})
);
@@ -79,8 +81,8 @@ const SystemLog = () => {
saveData,
errorMessage
} = useRest<LogSettings>({
read: SystemApi.readLogSettings,
update: SystemApi.updateLogSettings
read: readLogSettings,
update: updateLogSettings
});
const [logEntries, setLogEntries] = useState<LogEntry[]>([]);
@@ -114,7 +116,7 @@ const SystemLog = () => {
});
// called on page load to reset pointer and fetch all log entries
useRequest(SystemApi.fetchLog());
useRequest(fetchLog());
const paddedLevelLabel = (level: LogLevel) => {
const label = levelLabel(level);
@@ -190,23 +192,25 @@ const SystemLog = () => {
<MenuItem value={9}>ALL</MenuItem>
</TextField>
</Grid>
<Grid size={2}>
<TextField
name="max_messages"
label={LL.BUFFER_SIZE()}
value={data.max_messages}
fullWidth
variant="outlined"
onChange={updateFormValue}
margin="normal"
select
>
<MenuItem value={25}>25</MenuItem>
<MenuItem value={50}>50</MenuItem>
<MenuItem value={75}>75</MenuItem>
<MenuItem value={100}>100</MenuItem>
</TextField>
</Grid>
{data.psram && (
<Grid size={2}>
<TextField
name="max_messages"
label={LL.BUFFER_SIZE()}
value={data.max_messages}
fullWidth
variant="outlined"
onChange={updateFormValue}
margin="normal"
select
>
<MenuItem value={25}>25</MenuItem>
<MenuItem value={50}>50</MenuItem>
<MenuItem value={75}>75</MenuItem>
<MenuItem value={100}>100</MenuItem>
</TextField>
</Grid>
)}
<Grid>
<BlockFormControlLabel
control={
@@ -251,14 +255,17 @@ const SystemLog = () => {
}}
>
{logEntries.map((e) => (
<LogEntryLine details={{ level: e.l }} key={e.i}>
<div style={{ font: '14px monospace', whiteSpace: 'nowrap' }}>
<span>{e.t}</span>
<span>{paddedLevelLabel(e.l)}&nbsp;</span>
<span>{paddedIDLabel(e.i)} </span>
<span>{paddedNameLabel(e.n)} </span>
<span>{e.m}</span>
</LogEntryLine>
<LogEntryLine details={{ level: e.l }} key={e.i}>
{e.m}
</LogEntryLine>
</div>
))}
<div ref={ref} />
</Box>
</>

View File

@@ -44,7 +44,7 @@ const SingleUpload = ({ doRestart }) => {
abort: cancelUpload
} = useRequest(SystemApi.uploadFile, {
immediate: false
}).onComplete(({ data }) => {
}).onSuccess(({ data }) => {
if (data) {
setMd5(data.md5 as string);
toast.success(LL.UPLOAD() + ' MD5 ' + LL.SUCCESSFUL());
@@ -59,10 +59,8 @@ const SingleUpload = ({ doRestart }) => {
await sendUpload(file).catch((error: Error) => {
if (error.message === 'The user aborted a request') {
toast.warning(LL.UPLOAD() + ' ' + LL.ABORTED());
} else if (error.message === 'Network Error') {
toast.warning('Invalid file extension or incompatible bin file');
} else {
toast.error(error.message);
toast.warning('Invalid file extension or incompatible bin file');
}
});
}

View File

@@ -177,7 +177,7 @@ const de: Translation = {
STABLE: 'Stabil',
DEVELOPMENT: 'Entwicklung',
RELEASE_NOTES: 'Versionshinweise',
EMS_ESP_VER: 'EMS-ESP Version',
EMS_ESP_VER: 'Firmware Version', // TODO translate
UPTIME: 'Systembetriebszeit',
FREE_MEMORY: 'Freier RAM Speicher',
PSRAM: 'PSRAM (Größe / Frei)',
@@ -186,10 +186,8 @@ const de: Translation = {
FILESYSTEM: 'Dateisystem (Genutzt / Frei)',
BUFFER_SIZE: 'max. Puffergröße',
COMPACT: 'Kompakte Darstellung',
DOWNLOAD_CUSTOMIZATION_TEXT: 'Herunterladen der individuellen Entitätsanpassungen',
DOWNLOAD_SCHEDULE_TEXT: 'Herunterladen geplanter Befehle',
DOWNLOAD_SETTINGS_TEXT: 'Herunterladen der Anwendungseinstellungen. Vorsicht beim Teilen der Einstellungen, da sie Passwörter und andere sensible Daten enthalten',
UPLOAD_TEXT: 'Hochladen von neuer Firmware (.bin), Geräte- oder Entitätseinstellungen (.json), zur optionalen Validitätsprüfung zuerst die (.md5) Datei hochladen',
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
UPLOAD_TEXT: 'Upload a new firmware (.bin) file or a backup file (.json)', // TODO translate
UPLOAD_DROP_TEXT: 'Klicken Sie hier, oder ziehen Sie eine Datei hierher',
ERROR: 'Unerwarteter Fehler, bitte versuchen Sie es erneut',
TIME_SET: 'Zeit gesetzt',
@@ -340,7 +338,7 @@ const de: Translation = {
LATEST_VERSION: 'Sie verwenden die neueste Firmware-Version.',
PLEASE_WAIT: 'Bitte warten',
RESTARTING_PRE: 'Initialisierung',
RESTARTING_POST: 'Neuladen'
RESTARTING_POST: 'Vorbereitung'
};
export default de;

View File

@@ -177,7 +177,7 @@ const en: Translation = {
STABLE: 'Stable',
DEVELOPMENT: 'Development',
RELEASE_NOTES: 'release notes',
EMS_ESP_VER: 'EMS-ESP Version',
EMS_ESP_VER: 'Firmware Version', // TODO translate
UPTIME: 'System Uptime',
FREE_MEMORY: 'Free Memory',
PSRAM: 'PSRAM (Size / Free)',
@@ -186,10 +186,8 @@ const en: Translation = {
FILESYSTEM: 'File System (Used / Free)',
BUFFER_SIZE: 'Max Buffer Size',
COMPACT: 'Compact',
DOWNLOAD_CUSTOMIZATION_TEXT: 'Download the entity customizations',
DOWNLOAD_SCHEDULE_TEXT: 'Download Scheduler Events',
DOWNLOAD_SETTINGS_TEXT: 'Download the application settings. Be careful when sharing your settings as this file contains passwords and other sensitive system information',
UPLOAD_TEXT: 'Upload a new firmware (.bin) file, settings or customizations (.json) file below, for optional validation upload (.md5) first',
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
UPLOAD_TEXT: 'Upload a new firmware (.bin) file or a backup file (.json)',
UPLOAD_DROP_TEXT: 'Drop file or click here',
ERROR: 'Unexpected Error, please try again',
TIME_SET: 'Time set',
@@ -334,13 +332,13 @@ const en: Translation = {
ALLVALUES: 'All Values',
SPECIAL_FUNCTIONS: 'Special Functions',
WAIT_FIRMWARE: 'Firmware is uploading and installing',
INSTALL_VERSION: 'This will install vesion {0}. Are you sure?',
INSTALL_VERSION: 'This will install version {0}. Are you sure?',
SWITCH_DEV: 'switch to the development version',
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!',
LATEST_VERSION: 'You are using the latest firmware version.',
PLEASE_WAIT: 'Please wait',
RESTARTING_PRE: 'Initializing',
RESTARTING_POST: 'Reloading'
RESTARTING_POST: 'Preparing'
};
export default en;

View File

@@ -177,7 +177,7 @@ const fr: Translation = {
STABLE: 'Stable', // TODO translate
DEVELOPMENT: 'Développement',
RELEASE_NOTES: 'notes de version',
EMS_ESP_VER: 'Version EMS-ESP',
EMS_ESP_VER: 'Firmware Version', // TODO translate
UPTIME: 'Durée de fonctionnement du système',
FREE_MEMORY: 'Libre Memory',
PSRAM: 'PSRAM (Taille / Libre)',
@@ -186,10 +186,8 @@ const fr: Translation = {
FILESYSTEM: 'File System (Utilisée / Libre)',
BUFFER_SIZE: 'Max taille du buffer',
COMPACT: 'Compact',
DOWNLOAD_CUSTOMIZATION_TEXT: "Télécharger les personnalisations d'entités",
DOWNLOAD_SCHEDULE_TEXT: 'Download Scheduler Events', // TODO translate
DOWNLOAD_SETTINGS_TEXT: "Téléchargez les paramètres de l'application. Soyez prudent lorsque vous partagez vos paramètres car ce fichier contient des mots de passe et d'autres informations système sensibles.",
UPLOAD_TEXT: "Téléchargez un nouveau fichier de firmware (.bin), un fichier de paramètres ou de personnalisations (.json) ci-dessous, pour une validation optionnelle téléchargez d'abord un fichier (.md5)",
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
UPLOAD_TEXT: 'Upload a new firmware (.bin) file or a backup file (.json)', // TODO translate
UPLOAD_DROP_TEXT: 'Déposer le fichier ou cliquer ici',
ERROR: 'Erreur inattendue, veuillez réessayer',
TIME_SET: 'Time set',
@@ -334,13 +332,13 @@ const fr: Translation = {
ALLVALUES: 'All Values', // TODO translate
SPECIAL_FUNCTIONS: 'Special Functions',
WAIT_FIRMWARE: 'Firmware is uploading and installing', // TODO translate
INSTALL_VERSION: 'This will install vesion {0}. Are you sure?', // TODO translate
INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate
SWITCH_DEV: 'switch to the development version', // TODO translate
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate
LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate // TODO translate
PLEASE_WAIT: 'Please wait', // TODO translate
RESTARTING_PRE: 'Initializing', // TODO translate
RESTARTING_POST: 'Reloading' // TODO translate
RESTARTING_POST: 'Preparing' // TODO translate
};
export default fr;

View File

@@ -177,7 +177,7 @@ const it: Translation = {
STABLE: 'Stable', // TODO translate
DEVELOPMENT: 'Sviluppo',
RELEASE_NOTES: 'note rilascio',
EMS_ESP_VER: 'Versione EMS-ESP',
EMS_ESP_VER: 'Versione Firmware',
UPTIME: 'Tempo di attività del sistema',
FREE_MEMORY: 'Free Memory',
PSRAM: 'PSRAM (Size / Free)',
@@ -186,10 +186,8 @@ const it: Translation = {
FILESYSTEM: 'Memoria Sistema (Usata / Libera)',
BUFFER_SIZE: 'Max Buffer Size',
COMPACT: 'Compact',
DOWNLOAD_CUSTOMIZATION_TEXT: 'Scarica personalizzazioni entità',
DOWNLOAD_SCHEDULE_TEXT: 'Download Scheduler Events',
DOWNLOAD_SETTINGS_TEXT: 'Scarica le impostazioni dell applicazione. Fai attenzione quando condividi le tue impostazioni poiché questo file contiene password e altre informazioni di sistema riservate',
UPLOAD_TEXT: 'Carica un nuovo file firmware (.bin) , file delle impostazioni o delle personalizzazioni (.json) di seguito, per un opzione di convalida scaricare dapprima un file "*.MD5" ',
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
UPLOAD_TEXT: 'Upload a new firmware (.bin) file or a backup file (.json)', // TODO translate
UPLOAD_DROP_TEXT: 'Trascina il file o clicca qui',
ERROR: 'Errore Inaspettato, prego tenta ancora',
TIME_SET: 'Imposta Ora',
@@ -334,13 +332,13 @@ const it: Translation = {
ALLVALUES: 'All Values', // TODO translate
SPECIAL_FUNCTIONS: 'Special Functions', // TODO translate
WAIT_FIRMWARE: 'Firmware is uploading and installing', // TODO translate
INSTALL_VERSION: 'This will install vesion {0}. Are you sure?', // TODO translate
INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate
SWITCH_DEV: 'switch to the development version', // TODO translate
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate
LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate
PLEASE_WAIT: 'Please wait', // TODO translate
RESTARTING_PRE: 'Initializing', // TODO translate
RESTARTING_POST: 'Reloading' // TODO translate
RESTARTING_POST: 'Preparing' // TODO translate
};
export default it;

View File

@@ -177,7 +177,7 @@ const nl: Translation = {
STABLE: 'Stable',
DEVELOPMENT: 'Development',
RELEASE_NOTES: 'release notes',
EMS_ESP_VER: 'EMS-ESP Versie',
EMS_ESP_VER: 'Firmware Versie',
UPTIME: 'Systeem Uptime',
FREE_MEMORY: 'Free Memory',
PSRAM: 'PSRAM (Size / Free)',
@@ -186,10 +186,8 @@ const nl: Translation = {
FILESYSTEM: 'File System (Used / Free)',
BUFFER_SIZE: 'Max Buffer Size',
COMPACT: 'Compact',
DOWNLOAD_CUSTOMIZATION_TEXT: 'Download alle custom instellingen',
DOWNLOAD_SCHEDULE_TEXT: 'Download Scheduler Events',
DOWNLOAD_SETTINGS_TEXT: 'Download de applicatie settings. Wees voorzichting met het delen van dit bestand want het bevat o.a. de wachtwoorden in plain text',
UPLOAD_TEXT: 'Upload een nieuwe firmware (.bin) file, instellingen of custom instellingen (.json) bestand hieronder',
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
UPLOAD_TEXT: 'Upload a new firmware (.bin) file or a backup file (.json)', // TODO translate
UPLOAD_DROP_TEXT: 'Sleep bestand hierheen of klik hier',
ERROR: 'Onverwachte fout, probeer opnieuw',
TIME_SET: 'Tijd ingesteld',
@@ -334,13 +332,13 @@ const nl: Translation = {
ALLVALUES: 'All Values', // TODO translate
SPECIAL_FUNCTIONS: 'Special Functions', // TODO translate
WAIT_FIRMWARE: 'Firmware is uploading and installing', // TODO translate
INSTALL_VERSION: 'This will install vesion {0}. Are you sure?', // TODO translate
INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate
SWITCH_DEV: 'switch to the development version', // TODO translate
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate
LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate
PLEASE_WAIT: 'Please wait', // TODO translate
RESTARTING_PRE: 'Initializing', // TODO translate
RESTARTING_POST: 'Reloading' // TODO translate
RESTARTING_POST: 'Preparing' // TODO translate
};
export default nl;

View File

@@ -177,7 +177,7 @@ const no: Translation = {
STABLE: 'Stable', // TODO translate
DEVELOPMENT: 'Development',
RELEASE_NOTES: 'release notes',
EMS_ESP_VER: 'EMS-ESP Version',
EMS_ESP_VER: 'Firmware Version', // TODO translate
UPTIME: 'System Oppetid',
FREE_MEMORY: 'Ledig Memory',
PSRAM: 'PSRAM (Størrelse / Ledig)',
@@ -186,10 +186,8 @@ const no: Translation = {
FILESYSTEM: 'File System (Brukt / Ledig)',
BUFFER_SIZE: 'Max Buffer Størrelse',
COMPACT: 'Komprimere',
DOWNLOAD_CUSTOMIZATION_TEXT: 'Last ned objektstilpasninger',
DOWNLOAD_SCHEDULE_TEXT: 'Last ned planlagte oppgaver',
DOWNLOAD_SETTINGS_TEXT: 'Last ned applikasjonskonfigurasjon. Vær varsom med å dele fila da den inneholder passord og annen sensitiv system informasjon',
UPLOAD_TEXT: 'Last opp en ny firmware (.bin) fil, innstillinger eller tilpassninger (.json) fil nedenfor',
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
UPLOAD_TEXT: 'Upload a new firmware (.bin) file or a backup file (.json)', // TODO translate
UPLOAD_DROP_TEXT: 'Slipp fil eller klikk her',
ERROR: 'Ukjent feil, prøv igjen',
TIME_SET: 'Still in tid',
@@ -334,13 +332,13 @@ const no: Translation = {
ALLVALUES: 'All Values', // TODO translate
SPECIAL_FUNCTIONS: 'Special Functions', // TODO translate
WAIT_FIRMWARE: 'Firmware is uploading and installing', // TODO translate
INSTALL_VERSION: 'This will install vesion {0}. Are you sure?', // TODO translate
INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate
SWITCH_DEV: 'switch to the development version', // TODO translate
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate
LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate
PLEASE_WAIT: 'Please wait', // TODO translate
RESTARTING_PRE: 'Initializing', // TODO translate
RESTARTING_POST: 'Reloading' // TODO translate
RESTARTING_POST: 'Preparing' // TODO translate
};
export default no;

View File

@@ -177,7 +177,7 @@ const pl: BaseTranslation = {
STABLE: 'Stable', // TODO translate
DEVELOPMENT: 'Testowe',
RELEASE_NOTES: 'lista zmian',
EMS_ESP_VER: 'Wersja EMS-ESP',
EMS_ESP_VER: 'Wersja Firmware',
UPTIME: 'Czas działania systemu',
FREE_MEMORY: 'Wolne Memory', // TODO translate
PSRAM: 'PSRAM (rozmiar / wolne)',
@@ -186,10 +186,8 @@ const pl: BaseTranslation = {
FILESYSTEM: 'System plików (wykorzystane / wolne)',
BUFFER_SIZE: 'Maksymalna pojemność bufora (ilość wpisów)',
COMPACT: 'Kompaktowy',
DOWNLOAD_CUSTOMIZATION_TEXT: 'Pobierz personalizacje.',
DOWNLOAD_SCHEDULE_TEXT: 'Pobierz harmonogram zdarzeń.',
DOWNLOAD_SETTINGS_TEXT: 'Pobierz ustawienia aplikacji. Uwaga! Plik z ustawieniami zawiera hasła oraz inne wrażliwe informacje systemowe! Nie udostepniaj go pochopnie!',
UPLOAD_TEXT: 'Wyślij firmware (.bin), ustawienia lub personalizacje (.json). Opcjonalnie, wyślij wcześniej plik walidacji z sumą kontrolną (.md5).',
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
UPLOAD_TEXT: 'Upload a new firmware (.bin) file or a backup file (.json)', // TODO translate
UPLOAD_DROP_TEXT: 'Przeciągnij tutaj plik lub kliknij',
ERROR: 'Nieoczekiwany błąd, spróbuj ponownie!',
TIME_SET: 'Zegar został ustawiony.',
@@ -334,13 +332,13 @@ const pl: BaseTranslation = {
ALLVALUES: 'All Values', // TODO translate
SPECIAL_FUNCTIONS: 'Special Functions', // TODO translate
WAIT_FIRMWARE: 'Firmware is uploading and installing', // TODO translate
INSTALL_VERSION: 'This will install vesion {0}. Are you sure?', // TODO translate
INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate
SWITCH_DEV: 'switch to the development version', // TODO translate
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate
LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate
PLEASE_WAIT: 'Please wait', // TODO translate
RESTARTING_PRE: 'Initializing', // TODO translate
RESTARTING_POST: 'Reloading' // TODO translate
RESTARTING_POST: 'Preparing' // TODO translate
};
export default pl;

View File

@@ -177,19 +177,17 @@ const sk: Translation = {
STABLE: 'Stabilná', // TODO translate
DEVELOPMENT: 'Vývojárska',
RELEASE_NOTES: 'poznámky k verzii',
EMS_ESP_VER: 'EMS-ESP verzia',
EMS_ESP_VER: 'Firmware verzia',
UPTIME: 'Beh systému',
FREE_MEMORY: 'Voľná pamäť', // TODO translate
FREE_MEMORY: 'Voľné Memory',
PSRAM: 'PSRAM (Veľkosť / Voľné)',
FLASH: 'Flash chip (Veľkosť , Rýchlosť)',
APPSIZE: 'Applikácia (Oddiel: Použité / Voľné)',
FILESYSTEM: 'Súborový systém (Použité / Voľné)',
BUFFER_SIZE: 'Buffer-max.veľkosť',
COMPACT: 'Kompaktné',
DOWNLOAD_CUSTOMIZATION_TEXT: 'Stiahnutie prispôsobení entity',
DOWNLOAD_SCHEDULE_TEXT: 'Stiahnutie plánovača udalostí',
DOWNLOAD_SETTINGS_TEXT: 'Stiahnite si nastavenia aplikácie. Pri zdieľaní nastavení buďte opatrní, pretože tento súbor obsahuje heslá a iné citlivé systémové informácie.',
UPLOAD_TEXT: 'Najskôr nahrajte nový súbor firmvéru (.bin), nastavenia alebo prispôsobenia (.json), pre voliteľné overenie nahrajte súbor (.md5)',
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
UPLOAD_TEXT: 'Upload a new firmware (.bin) file or a backup file (.json)', // TODO translate
UPLOAD_DROP_TEXT: 'Potiahnúť a pripnúť súbor alebo kliknúť sem',
ERROR: 'Neočakávaná chyba, prosím skúste to znova',
TIME_SET: 'Nastavený čas',

View File

@@ -177,7 +177,7 @@ const sv: Translation = {
STABLE: 'Stable', // TODO translate
DEVELOPMENT: 'Utveckling',
RELEASE_NOTES: 'release-logg',
EMS_ESP_VER: 'EMS-ESP Version',
EMS_ESP_VER: 'Firmware Version', // TODO translate
UPTIME: 'Systemets Upptid',
FREE_MEMORY: 'Ledigt Memory',
PSRAM: 'PSRAM (Storlek / Ledigt)',
@@ -186,10 +186,8 @@ const sv: Translation = {
FILESYSTEM: 'Filsystem (Använt / Ledigt)',
BUFFER_SIZE: 'Max Bufferstorlek',
COMPACT: 'Komprimera',
DOWNLOAD_CUSTOMIZATION_TEXT: 'Ladda ner entitetsanpassningar',
DOWNLOAD_SCHEDULE_TEXT: 'Download Scheduler Events', // TODO translate
DOWNLOAD_SETTINGS_TEXT: 'Ladda ner applikationsinställningar. Var försiktig om du delar dina iställlningar då de innehåller lösenord och annan känslig systeminformation',
UPLOAD_TEXT: 'Ladda upp ett nytt firmware (.bin), inställningar eller anpassningar (.json) nedan',
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
UPLOAD_TEXT: 'Upload a new firmware (.bin) file or a backup file (.json)', // TODO translate
UPLOAD_DROP_TEXT: 'Släpp fil eller klicka här',
ERROR: 'Okänt Fel, var god försök igen',
TIME_SET: 'Ställ in tid',
@@ -334,13 +332,13 @@ const sv: Translation = {
ALLVALUES: 'All Values', // TODO translate
SPECIAL_FUNCTIONS: 'Special Functions', // TODO translate
WAIT_FIRMWARE: 'Firmware is uploading and installing', // TODO translate
INSTALL_VERSION: 'This will install vesion {0}. Are you sure?', // TODO translate
INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate
SWITCH_DEV: 'switch to the development version', // TODO translate
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate
LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate
PLEASE_WAIT: 'Please wait', // TODO translate
RESTARTING_PRE: 'Initializing', // TODO translate
RESTARTING_POST: 'Reloading' // TODO translate
RESTARTING_POST: 'Preparing' // TODO translate
};
export default sv;

View File

@@ -177,19 +177,17 @@ const tr: Translation = {
STABLE: 'Stable', // TODO translate
DEVELOPMENT: 'Geliştirme',
RELEASE_NOTES: 'yayınlanma notları',
EMS_ESP_VER: 'EMS-ESP Sürümü',
EMS_ESP_VER: 'Firmware Sürümü',
UPTIME: 'Sistem Çalışma Süresi',
FREE_MEMORY: 'Yığın Memory', // TODO translate
FREE_MEMORY: 'Yığın Memory',
PSRAM: 'PSRAM (Boyut / Boş)',
FLASH: 'Flash Çipi (Boyut , Hız)',
APPSIZE: 'Uygulama (Bölme: Kullanılmış / Boş)',
FILESYSTEM: 'Dosya Sistemi (Kullanılmış / Boş)',
BUFFER_SIZE: 'En fazla bellek boyutu',
COMPACT: 'Sıkışık',
DOWNLOAD_CUSTOMIZATION_TEXT: 'Varlık özelleştirmelerini indir',
DOWNLOAD_SCHEDULE_TEXT: 'Download Scheduler Events', // TODO translate
DOWNLOAD_SETTINGS_TEXT: 'Uygulama ayarlarını indir. Bu dosya hassas sistem bilgileri ve şifrelerinizi içerdiğinden ayarlarınızı paylaşırken dikkatli olun',
UPLOAD_TEXT: 'Yeni bir bellenim(.bin) dosyası yükleyin, ayarlar ve özelleştirmeler(.json) dosyası aşağıda, sçenekli denetim yüklemesi(.md5) için önce',
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
UPLOAD_TEXT: 'Upload a new firmware (.bin) file or a backup file (.json)', // TODO translate
UPLOAD_DROP_TEXT: 'Buraya tıklayın yada dosyayı sürükleyip bırakın',
ERROR: 'Beklenemedik hata, lütfen tekrar deneyin.',
TIME_SET: 'Zaman ayarı',
@@ -334,13 +332,13 @@ const tr: Translation = {
ALLVALUES: 'All Values', // TODO translate
SPECIAL_FUNCTIONS: 'Special Functions', // TODO translate
WAIT_FIRMWARE: 'Firmware is uploading and installing', // TODO translate
INSTALL_VERSION: 'This will install vesion {0}. Are you sure?', // TODO translate
INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate
SWITCH_DEV: 'switch to the development version', // TODO translate
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate
LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate
PLEASE_WAIT: 'Please wait', // TODO translate
RESTARTING_PRE: 'Initializing', // TODO translate
RESTARTING_POST: 'Reloading' // TODO translate
RESTARTING_POST: 'Preparing' // TODO translate
};
export default tr;

View File

@@ -70,4 +70,5 @@ export interface LogSettings {
level: number;
max_messages: number;
compact: boolean;
psram: boolean;
}

View File

@@ -287,7 +287,7 @@ __metadata:
languageName: node
linkType: hard
"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7":
"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7":
version: 7.25.0
resolution: "@babel/runtime@npm:7.25.0"
dependencies:
@@ -1145,10 +1145,10 @@ __metadata:
languageName: node
linkType: hard
"@remix-run/router@npm:1.19.1":
version: 1.19.1
resolution: "@remix-run/router@npm:1.19.1"
checksum: 10c0/9101fc96646e5107b6b0ef248d4c93bd965590c37ac02d35bcc57d1902467db7fc6eeec0a1fb97d0ce5bc96fae58e75239555e44a983239a61badba18e82d3b8
"@remix-run/router@npm:1.19.2":
version: 1.19.2
resolution: "@remix-run/router@npm:1.19.2"
checksum: 10c0/ac7fc813350686705f2c29219e70e1e299d9a8e3b301e9e81f7e84f578c40c6462b590cf0d78863bac40dbc325b68c71ae070f4a1465793d1d1971b619618295
languageName: node
linkType: hard
@@ -1595,15 +1595,15 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/eslint-plugin@npm:8.4.0":
version: 8.4.0
resolution: "@typescript-eslint/eslint-plugin@npm:8.4.0"
"@typescript-eslint/eslint-plugin@npm:8.5.0":
version: 8.5.0
resolution: "@typescript-eslint/eslint-plugin@npm:8.5.0"
dependencies:
"@eslint-community/regexpp": "npm:^4.10.0"
"@typescript-eslint/scope-manager": "npm:8.4.0"
"@typescript-eslint/type-utils": "npm:8.4.0"
"@typescript-eslint/utils": "npm:8.4.0"
"@typescript-eslint/visitor-keys": "npm:8.4.0"
"@typescript-eslint/scope-manager": "npm:8.5.0"
"@typescript-eslint/type-utils": "npm:8.5.0"
"@typescript-eslint/utils": "npm:8.5.0"
"@typescript-eslint/visitor-keys": "npm:8.5.0"
graphemer: "npm:^1.4.0"
ignore: "npm:^5.3.1"
natural-compare: "npm:^1.4.0"
@@ -1614,66 +1614,66 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
checksum: 10c0/c75e9bb176e9e0277c9f9c4c006bc2c31ac91984e555de1390a9bbe876e3b6787d59d96015b3f0cd083fd22c814aea4ed4858910d3afdd24d64ab79815da31e5
checksum: 10c0/69ae7067e03d2d8d442e69d668235bdafd63b07229d0be27025eaad8aa468b5af8ac54627021e0e3a060df04ed1c39d1327a0b11469ac72405b52b74a79f402b
languageName: node
linkType: hard
"@typescript-eslint/parser@npm:8.4.0":
version: 8.4.0
resolution: "@typescript-eslint/parser@npm:8.4.0"
"@typescript-eslint/parser@npm:8.5.0":
version: 8.5.0
resolution: "@typescript-eslint/parser@npm:8.5.0"
dependencies:
"@typescript-eslint/scope-manager": "npm:8.4.0"
"@typescript-eslint/types": "npm:8.4.0"
"@typescript-eslint/typescript-estree": "npm:8.4.0"
"@typescript-eslint/visitor-keys": "npm:8.4.0"
"@typescript-eslint/scope-manager": "npm:8.5.0"
"@typescript-eslint/types": "npm:8.5.0"
"@typescript-eslint/typescript-estree": "npm:8.5.0"
"@typescript-eslint/visitor-keys": "npm:8.5.0"
debug: "npm:^4.3.4"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
peerDependenciesMeta:
typescript:
optional: true
checksum: 10c0/19f3358e5bc4bbad693183eefe1a90ea64be054a934bc2c8a972ff4738b94580b55ad4955af5797db42298628caa59b3ba3f9fd960582b5fc2c836da3a4578a5
checksum: 10c0/509fdd605b86c7d025928f20e1035712c2fc268c34b1af84248ed0b53d699034f19caf98e085c5c758d3025e29939dd12eea427c72cae9e5ea79274364851f0a
languageName: node
linkType: hard
"@typescript-eslint/scope-manager@npm:8.4.0":
version: 8.4.0
resolution: "@typescript-eslint/scope-manager@npm:8.4.0"
"@typescript-eslint/scope-manager@npm:8.5.0":
version: 8.5.0
resolution: "@typescript-eslint/scope-manager@npm:8.5.0"
dependencies:
"@typescript-eslint/types": "npm:8.4.0"
"@typescript-eslint/visitor-keys": "npm:8.4.0"
checksum: 10c0/95188c663df7db106529c6b93c4c7c61647ed34ab6dd48114e41ddf49140ff606c5501ce2ae451a988ec49b5d3874ea96ff212fc102802327b10affd2ff80a37
"@typescript-eslint/types": "npm:8.5.0"
"@typescript-eslint/visitor-keys": "npm:8.5.0"
checksum: 10c0/868602f9324a6e15fcae017acd3b0832e9f2c8c8cd315667df37c2e7c765cda5fba7c4bede931f32cc04819ba97cf74a5fddb085c6f1c7993f1fb085ba126422
languageName: node
linkType: hard
"@typescript-eslint/type-utils@npm:8.4.0":
version: 8.4.0
resolution: "@typescript-eslint/type-utils@npm:8.4.0"
"@typescript-eslint/type-utils@npm:8.5.0":
version: 8.5.0
resolution: "@typescript-eslint/type-utils@npm:8.5.0"
dependencies:
"@typescript-eslint/typescript-estree": "npm:8.4.0"
"@typescript-eslint/utils": "npm:8.4.0"
"@typescript-eslint/typescript-estree": "npm:8.5.0"
"@typescript-eslint/utils": "npm:8.5.0"
debug: "npm:^4.3.4"
ts-api-utils: "npm:^1.3.0"
peerDependenciesMeta:
typescript:
optional: true
checksum: 10c0/ae51100594d9ca61c7577b5aed0bd10c1959725df5c38cd9653eed1fd3dbdfff9146b6e48f3409994b4c8d781b9d95025c36b30f73a5a1b3dbdee6d142cecc87
checksum: 10c0/675d3e41f938d16e9268fd33764a4e16b12a4a9817e61d5e2508a07fe6783c69ce9d05facc61822b5647c71d767929618ed37b8b93f423f7c2ccb62cfeb4343b
languageName: node
linkType: hard
"@typescript-eslint/types@npm:8.4.0":
version: 8.4.0
resolution: "@typescript-eslint/types@npm:8.4.0"
checksum: 10c0/15e09ced84827c349553530a31822f06ae5bad456c03d561b7d0c64b6ad9b5d7ca795e030bd93e65d5a2cd41bfde36ed08dcd2ff9feaa8b60a67080827f47ecb
"@typescript-eslint/types@npm:8.5.0":
version: 8.5.0
resolution: "@typescript-eslint/types@npm:8.5.0"
checksum: 10c0/f0b666b5c001b9779bfd9e4c7d031843d07264429d5bcf5d636f26f96cd5d949a33f5d6a645b8d74b93daf565a468476a6a4935dd7135a200250fb03acbe4988
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:8.4.0":
version: 8.4.0
resolution: "@typescript-eslint/typescript-estree@npm:8.4.0"
"@typescript-eslint/typescript-estree@npm:8.5.0":
version: 8.5.0
resolution: "@typescript-eslint/typescript-estree@npm:8.5.0"
dependencies:
"@typescript-eslint/types": "npm:8.4.0"
"@typescript-eslint/visitor-keys": "npm:8.4.0"
"@typescript-eslint/types": "npm:8.5.0"
"@typescript-eslint/visitor-keys": "npm:8.5.0"
debug: "npm:^4.3.4"
fast-glob: "npm:^3.3.2"
is-glob: "npm:^4.0.3"
@@ -1683,31 +1683,31 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
checksum: 10c0/170702b024121cff9268f53de8054796b0ce025f9a78d6f2bc850a360e5f3f7032ba3ee9d4b7392726308273a5f3ade5ab31b1788b504b514bc15afc07302b37
checksum: 10c0/f62f03d0c5dc57b2b54dbe1cbd027966f774f241279655f46c64145abb54b765176a0cd40447583ba56ada306181da9a82e39b777c78128e105e4ea98c609350
languageName: node
linkType: hard
"@typescript-eslint/utils@npm:8.4.0":
version: 8.4.0
resolution: "@typescript-eslint/utils@npm:8.4.0"
"@typescript-eslint/utils@npm:8.5.0":
version: 8.5.0
resolution: "@typescript-eslint/utils@npm:8.5.0"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.4.0"
"@typescript-eslint/scope-manager": "npm:8.4.0"
"@typescript-eslint/types": "npm:8.4.0"
"@typescript-eslint/typescript-estree": "npm:8.4.0"
"@typescript-eslint/scope-manager": "npm:8.5.0"
"@typescript-eslint/types": "npm:8.5.0"
"@typescript-eslint/typescript-estree": "npm:8.5.0"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
checksum: 10c0/8c9c36b3aa23f9bcc28cc4b10f0fa2996f1bc6cdd75135f08c2ef734baa30dbd2a8b92f344b90518e1fd07a486936734789fc7e90b780221a7707dad8e9c9364
checksum: 10c0/0cb0bfdaf0da79d13c0d0379478eb14b5825d235873bc7181e70c4f6297fa1c74431ef730cbc2912fe1814dd8d46c6515ce22b39c57e8f03c337aa152fd49a4e
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:8.4.0":
version: 8.4.0
resolution: "@typescript-eslint/visitor-keys@npm:8.4.0"
"@typescript-eslint/visitor-keys@npm:8.5.0":
version: 8.5.0
resolution: "@typescript-eslint/visitor-keys@npm:8.5.0"
dependencies:
"@typescript-eslint/types": "npm:8.4.0"
"@typescript-eslint/types": "npm:8.5.0"
eslint-visitor-keys: "npm:^3.4.3"
checksum: 10c0/339199b7fbb9ac83b530d03ab25f6bc5ceb688c9cd0ae460112cd14ee78ca7284a845aef5620cdf70170980123475ec875e85ebf595c60255ba3c0d6fe48c714
checksum: 10c0/8b9e81968ad36e8af18ac17b63c4e0764612451ca085676c939b723549052243f63577d2706bc2da48174f11bf47587ab47e6e0b7c5b28d9f3c1ef7b9aad322d
languageName: node
linkType: hard
@@ -1734,7 +1734,7 @@ __metadata:
"@types/react-router-dom": "npm:^5.3.3"
alova: "npm:3.0.16"
async-validator: "npm:^4.2.5"
concurrently: "npm:^8.2.2"
concurrently: "npm:^9.0.0"
eslint: "npm:^9.10.0"
eslint-config-prettier: "npm:^9.1.0"
formidable: "npm:^3.5.1"
@@ -1745,14 +1745,14 @@ __metadata:
react: "npm:^18.3.1"
react-dom: "npm:^18.3.1"
react-icons: "npm:^5.3.0"
react-router-dom: "npm:^6.26.1"
react-router-dom: "npm:^6.26.2"
react-toastify: "npm:^10.0.5"
rollup-plugin-visualizer: "npm:^5.12.0"
terser: "npm:^5.31.6"
terser: "npm:^5.32.0"
typesafe-i18n: "npm:^5.26.2"
typescript: "npm:^5.5.4"
typescript-eslint: "npm:8.4.0"
vite: "npm:^5.4.3"
typescript: "npm:^5.6.2"
typescript-eslint: "npm:8.5.0"
vite: "npm:^5.4.4"
vite-plugin-imagemin: "npm:^0.6.1"
vite-tsconfig-paths: "npm:^5.0.1"
languageName: unknown
@@ -2340,23 +2340,21 @@ __metadata:
languageName: node
linkType: hard
"concurrently@npm:^8.2.2":
version: 8.2.2
resolution: "concurrently@npm:8.2.2"
"concurrently@npm:^9.0.0":
version: 9.0.0
resolution: "concurrently@npm:9.0.0"
dependencies:
chalk: "npm:^4.1.2"
date-fns: "npm:^2.30.0"
lodash: "npm:^4.17.21"
rxjs: "npm:^7.8.1"
shell-quote: "npm:^1.8.1"
spawn-command: "npm:0.0.2"
supports-color: "npm:^8.1.1"
tree-kill: "npm:^1.2.2"
yargs: "npm:^17.7.2"
bin:
conc: dist/bin/concurrently.js
concurrently: dist/bin/concurrently.js
checksum: 10c0/0e9683196fe9c071d944345d21d8f34aa6c0cc50c0dd897e95619f2f1c9eb4871dca851b2569da17888235b7335b4c821ca19deed35bebcd9a131ee5d247f34c
checksum: 10c0/65251009f4540c25eda0d5b2f367ba8755eac83db2ce562802132160e9241c5cd755228b18c330ea29ccd5b0a033302da8a670d724e89fe462c26253e3046f2e
languageName: node
linkType: hard
@@ -2535,15 +2533,6 @@ __metadata:
languageName: node
linkType: hard
"date-fns@npm:^2.30.0":
version: 2.30.0
resolution: "date-fns@npm:2.30.0"
dependencies:
"@babel/runtime": "npm:^7.21.0"
checksum: 10c0/e4b521fbf22bc8c3db332bbfb7b094fd3e7627de0259a9d17c7551e2d2702608a7307a449206065916538e384f37b181565447ce2637ae09828427aed9cb5581
languageName: node
linkType: hard
"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4":
version: 4.3.6
resolution: "debug@npm:4.3.6"
@@ -5831,27 +5820,27 @@ __metadata:
languageName: node
linkType: hard
"react-router-dom@npm:^6.26.1":
version: 6.26.1
resolution: "react-router-dom@npm:6.26.1"
"react-router-dom@npm:^6.26.2":
version: 6.26.2
resolution: "react-router-dom@npm:6.26.2"
dependencies:
"@remix-run/router": "npm:1.19.1"
react-router: "npm:6.26.1"
"@remix-run/router": "npm:1.19.2"
react-router: "npm:6.26.2"
peerDependencies:
react: ">=16.8"
react-dom: ">=16.8"
checksum: 10c0/9d9d8ed54d1c95497c6fa35a6ab46992efeccf1cfc6f0f6089c6c9b040af3eae09568fbb80c690bae08051a955d92d7aa3a0e730f626eb69285114993d31d430
checksum: 10c0/7515128a98eef0a6b2bf354ef9dfefad03556a06be00fa9220eda6526aaada8a42f294911083473d7ced6d7128c3088bd193218bbb3d62593f9f4f7053781c23
languageName: node
linkType: hard
"react-router@npm:6.26.1":
version: 6.26.1
resolution: "react-router@npm:6.26.1"
"react-router@npm:6.26.2":
version: 6.26.2
resolution: "react-router@npm:6.26.2"
dependencies:
"@remix-run/router": "npm:1.19.1"
"@remix-run/router": "npm:1.19.2"
peerDependencies:
react: ">=16.8"
checksum: 10c0/463078e740462b42bb5ba8004448f33fc9e63778f432a4ed55c57b93c5b519e25fb17913ee8435b0fda33c6b9f75df8ef6fcb2c3a4f8db84fb546d202e29aa51
checksum: 10c0/0d15a39b419c99fb5ccad76388bfc4ee2b01323b3b1b694595a9f9ea28e1fbeea25486b5398f5d3d93922f5c6a9aa751b6bb27419488d85279f6ca5ff9e0a6bb
languageName: node
linkType: hard
@@ -6395,13 +6384,6 @@ __metadata:
languageName: node
linkType: hard
"spawn-command@npm:0.0.2":
version: 0.0.2
resolution: "spawn-command@npm:0.0.2"
checksum: 10c0/b22f2d71239e6e628a400831861ba747750bbb40c0a53323754cf7b84330b73d81e40ff1f9055e6d1971818679510208a9302e13d9ff3b32feb67e74d7a1b3ef
languageName: node
linkType: hard
"spdx-correct@npm:^3.0.0":
version: 3.2.0
resolution: "spdx-correct@npm:3.2.0"
@@ -6719,9 +6701,9 @@ __metadata:
languageName: node
linkType: hard
"terser@npm:^5.31.6":
version: 5.31.6
resolution: "terser@npm:5.31.6"
"terser@npm:^5.32.0":
version: 5.32.0
resolution: "terser@npm:5.32.0"
dependencies:
"@jridgewell/source-map": "npm:^0.3.3"
acorn: "npm:^8.8.2"
@@ -6729,7 +6711,7 @@ __metadata:
source-map-support: "npm:~0.5.20"
bin:
terser: bin/terser
checksum: 10c0/b17d02b65a52a5041430572b3c514475820f5e7590fa93773c0f5b4be601ccf3f6d745bf5a79f3ee58187cf85edf61c24ddf4345783839fccb44c9c8fa9b427e
checksum: 10c0/94daae4881258eb7d09abd46378e23d11ee46caa507b2fb26c5595c7e490914be734e0de38c50041dc38fae5fca24de11badf042dfbbfc1d336ed117335c420a
languageName: node
linkType: hard
@@ -6868,37 +6850,37 @@ __metadata:
languageName: node
linkType: hard
"typescript-eslint@npm:8.4.0":
version: 8.4.0
resolution: "typescript-eslint@npm:8.4.0"
"typescript-eslint@npm:8.5.0":
version: 8.5.0
resolution: "typescript-eslint@npm:8.5.0"
dependencies:
"@typescript-eslint/eslint-plugin": "npm:8.4.0"
"@typescript-eslint/parser": "npm:8.4.0"
"@typescript-eslint/utils": "npm:8.4.0"
"@typescript-eslint/eslint-plugin": "npm:8.5.0"
"@typescript-eslint/parser": "npm:8.5.0"
"@typescript-eslint/utils": "npm:8.5.0"
peerDependenciesMeta:
typescript:
optional: true
checksum: 10c0/266ef73fdc1f7fa19228b8653d61ad143261ccd35f7d5d647092ed0e1512de2d4e3d1b9e1f2520658708cc0c1d7925c4ec97f23440c180a3bf1716e81d65123f
checksum: 10c0/dd92e8f5fb50bb05810a1a37a4bbb6f60761295b121f6118bc027686ebc1b3ba9e4248ab5223ed4753e1320ef6329dd2e53e8160fa4463264277f307fefefd62
languageName: node
linkType: hard
"typescript@npm:^5.5.4":
version: 5.5.4
resolution: "typescript@npm:5.5.4"
"typescript@npm:^5.6.2":
version: 5.6.2
resolution: "typescript@npm:5.6.2"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10c0/422be60f89e661eab29ac488c974b6cc0a660fb2228003b297c3d10c32c90f3bcffc1009b43876a082515a3c376b1eefcce823d6e78982e6878408b9a923199c
checksum: 10c0/3ed8297a8c7c56b7fec282532503d1ac795239d06e7c4966b42d4330c6cf433a170b53bcf93a130a7f14ccc5235de5560df4f1045eb7f3550b46ebed16d3c5e5
languageName: node
linkType: hard
"typescript@patch:typescript@npm%3A^5.5.4#optional!builtin<compat/typescript>":
version: 5.5.4
resolution: "typescript@patch:typescript@npm%3A5.5.4#optional!builtin<compat/typescript>::version=5.5.4&hash=379a07"
"typescript@patch:typescript@npm%3A^5.6.2#optional!builtin<compat/typescript>":
version: 5.6.2
resolution: "typescript@patch:typescript@npm%3A5.6.2#optional!builtin<compat/typescript>::version=5.6.2&hash=74658d"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10c0/73409d7b9196a5a1217b3aaad929bf76294d3ce7d6e9766dd880ece296ee91cf7d7db6b16c6c6c630ee5096eccde726c0ef17c7dfa52b01a243e57ae1f09ef07
checksum: 10c0/e6c1662e4852e22fe4bbdca471dca3e3edc74f6f1df043135c44a18a7902037023ccb0abdfb754595ca9028df8920f2f8492c00fc3cbb4309079aae8b7de71cd
languageName: node
linkType: hard
@@ -7074,9 +7056,9 @@ __metadata:
languageName: node
linkType: hard
"vite@npm:^5.4.3":
version: 5.4.3
resolution: "vite@npm:5.4.3"
"vite@npm:^5.4.4":
version: 5.4.4
resolution: "vite@npm:5.4.4"
dependencies:
esbuild: "npm:^0.21.3"
fsevents: "npm:~2.3.3"
@@ -7113,7 +7095,7 @@ __metadata:
optional: true
bin:
vite: bin/vite.js
checksum: 10c0/7afe601bcba82f81980c718fc171ba8f0c45e3bffaeb7ef831b64b84e396f963c3c87818b74da4c8e817d1bce1c179f1efae3bcb14d2e94b4eb635071722c8f2
checksum: 10c0/2752e7dd5584ea7cc057742e8f5cbf2f2bd3a2bceb8794fbd3d52f1e88d362b5ac7f1c70be7a3d01b3d768320c8a8ad0df287fd72f253bf040423c36c67a3e89
languageName: node
linkType: hard

View File

@@ -7,210 +7,213 @@
// #undef LOCAL_LOG_LEVEL
#include "Logging.h"
ModbusClientTCPasync::ModbusClientTCPasync(IPAddress address, uint16_t port, uint16_t queueLimit) :
ModbusClient(),
txQueue(),
rxQueue(),
MTA_client(),
MTA_timeout(DEFAULTTIMEOUT),
MTA_idleTimeout(DEFAULTIDLETIME),
MTA_qLimit(queueLimit),
MTA_maxInflightRequests(queueLimit),
MTA_lastActivity(0),
MTA_state(DISCONNECTED),
MTA_host(address),
MTA_port(port)
{
// attach all handlers on async tcp events
MTA_client.onConnect([](void* i, AsyncClient* c) { (static_cast<ModbusClientTCPasync*>(i))->onConnected(); }, this);
MTA_client.onDisconnect([](void* i, AsyncClient* c) { (static_cast<ModbusClientTCPasync*>(i))->onDisconnected(); }, this);
MTA_client.onError([](void* i, AsyncClient* c, int8_t error) { (static_cast<ModbusClientTCPasync*>(i))->onACError(c, error); }, this);
// MTA_client.onTimeout([](void* i, AsyncClient* c, uint32_t time) { (static_cast<ModbusClientTCPasync*>(i))->onTimeout(time); }, this);
// MTA_client.onAck([](void* i, AsyncClient* c, size_t len, uint32_t time) { (static_cast<ModbusClientTCPasync*>(i))->onAck(len, time); }, this);
MTA_client.onData([](void* i, AsyncClient* c, void* data, size_t len) { (static_cast<ModbusClientTCPasync*>(i))->onPacket(static_cast<uint8_t*>(data), len); }, this);
MTA_client.onPoll([](void* i, AsyncClient* c) { (static_cast<ModbusClientTCPasync*>(i))->onPoll(); }, this);
ModbusClientTCPasync::ModbusClientTCPasync(IPAddress address, uint16_t port, uint16_t queueLimit)
: ModbusClient()
, txQueue()
, rxQueue()
, MTA_client()
, MTA_timeout(DEFAULTTIMEOUT)
, MTA_idleTimeout(DEFAULTIDLETIME)
, MTA_qLimit(queueLimit)
, MTA_maxInflightRequests(queueLimit)
, MTA_lastActivity(0)
, MTA_state(DISCONNECTED)
, MTA_host(address)
, MTA_port(port) {
// attach all handlers on async tcp events
MTA_client.onConnect([](void * i, AsyncClient * c) { (static_cast<ModbusClientTCPasync *>(i))->onConnected(); }, this);
MTA_client.onDisconnect([](void * i, AsyncClient * c) { (static_cast<ModbusClientTCPasync *>(i))->onDisconnected(); }, this);
MTA_client.onError([](void * i, AsyncClient * c, int8_t error) { (static_cast<ModbusClientTCPasync *>(i))->onACError(c, error); }, this);
// MTA_client.onTimeout([](void* i, AsyncClient* c, uint32_t time) { (static_cast<ModbusClientTCPasync*>(i))->onTimeout(time); }, this);
// MTA_client.onAck([](void* i, AsyncClient* c, size_t len, uint32_t time) { (static_cast<ModbusClientTCPasync*>(i))->onAck(len, time); }, this);
MTA_client.onData([](void * i,
AsyncClient * c,
void * data,
size_t len) { (static_cast<ModbusClientTCPasync *>(i))->onPacket(static_cast<uint8_t *>(data), len); },
this);
MTA_client.onPoll([](void * i, AsyncClient * c) { (static_cast<ModbusClientTCPasync *>(i))->onPoll(); }, this);
// disable nagle algorithm ref Modbus spec
MTA_client.setNoDelay(true);
}
// disable nagle algorithm ref Modbus spec
MTA_client.setNoDelay(true);
}
// Destructor: clean up queue, task etc.
ModbusClientTCPasync::~ModbusClientTCPasync() {
// Clean up queue
{
// Safely lock access
LOCK_GUARD(lock1, qLock);
LOCK_GUARD(lock2, sLock);
// Delete all elements from queues
while (!txQueue.empty()) {
delete txQueue.front();
txQueue.pop_front();
// Clean up queue
{
// Safely lock access
LOCK_GUARD(lock1, qLock);
LOCK_GUARD(lock2, sLock);
// Delete all elements from queues
while (!txQueue.empty()) {
delete txQueue.front();
txQueue.pop_front();
}
for (auto it = rxQueue.cbegin(); it != rxQueue.cend(); /* no increment */) {
delete it->second;
it = rxQueue.erase(it);
}
}
for (auto it = rxQueue.cbegin(); it != rxQueue.cend();/* no increment */) {
delete it->second;
it = rxQueue.erase(it);
}
}
// force close client
MTA_client.close(true);
// force close client
MTA_client.close(true);
}
// optionally manually connect to modbus server. Otherwise connection will be made upon first request
void ModbusClientTCPasync::connect() {
LOG_D("connecting\n");
LOCK_GUARD(lock1, sLock);
// only connect if disconnected
if (MTA_state == DISCONNECTED) {
MTA_state = CONNECTING;
MTA_client.connect(MTA_host, MTA_port);
}
LOG_D("connecting\n");
LOCK_GUARD(lock1, sLock);
// only connect if disconnected
if (MTA_state == DISCONNECTED) {
MTA_state = CONNECTING;
MTA_client.connect(MTA_host, MTA_port);
}
}
// connect to another modbus server.
void ModbusClientTCPasync::connect(IPAddress host, uint16_t port) {
// First disconnect, if connected
disconnect(true);
// Set new host and port
MTA_host = host;
MTA_port = port;
connect();
// First disconnect, if connected
disconnect(true);
// Set new host and port
MTA_host = host;
MTA_port = port;
connect();
}
// manually disconnect from modbus server. Connection will also auto close after idle time
void ModbusClientTCPasync::disconnect(bool force) {
LOG_D("disconnecting\n");
MTA_client.close(force);
LOG_D("disconnecting\n");
MTA_client.close(force);
}
// Set timeout value
void ModbusClientTCPasync::setTimeout(uint32_t timeout) {
MTA_timeout = timeout;
MTA_timeout = timeout;
}
// Set idle timeout value (time before connection auto closes after being idle)
void ModbusClientTCPasync::setIdleTimeout(uint32_t timeout) {
MTA_idleTimeout = timeout;
MTA_idleTimeout = timeout;
}
void ModbusClientTCPasync::setMaxInflightRequests(uint32_t maxInflightRequests) {
MTA_maxInflightRequests = maxInflightRequests;
MTA_maxInflightRequests = maxInflightRequests;
}
// Remove all pending request from queue
void ModbusClientTCPasync::clearQueue()
{
LOCK_GUARD(lock1, qLock);
LOCK_GUARD(lock2, sLock);
// Delete all elements from queues
while (!txQueue.empty()) {
delete txQueue.front();
txQueue.pop_front();
}
void ModbusClientTCPasync::clearQueue() {
LOCK_GUARD(lock1, qLock);
LOCK_GUARD(lock2, sLock);
// Delete all elements from queues
while (!txQueue.empty()) {
delete txQueue.front();
txQueue.pop_front();
}
}
// Base addRequest for preformatted ModbusMessage and last set target
Error ModbusClientTCPasync::addRequestM(ModbusMessage msg, uint32_t token) {
Error rc = SUCCESS; // Return value
Error rc = SUCCESS; // Return value
// Add it to the queue, if valid
if (msg) {
// Queue add successful?
if (!addToQueue(token, msg)) {
// No. Return error after deleting the allocated request.
rc = REQUEST_QUEUE_FULL;
// Add it to the queue, if valid
if (msg) {
// Queue add successful?
if (!addToQueue(token, msg)) {
// No. Return error after deleting the allocated request.
rc = REQUEST_QUEUE_FULL;
}
}
}
LOG_D("Add TCP request result: %02X\n", rc);
return rc;
LOG_D("Add TCP request result: %02X\n", rc);
return rc;
}
// Base syncRequest follows the same pattern
ModbusMessage ModbusClientTCPasync::syncRequestM(ModbusMessage msg, uint32_t token) {
ModbusMessage response;
ModbusMessage response;
if (msg) {
// Queue add successful?
if (!addToQueue(token, msg, true)) {
// No. Return error after deleting the allocated request.
response.setError(msg.getServerID(), msg.getFunctionCode(), REQUEST_QUEUE_FULL);
if (msg) {
// Queue add successful?
if (!addToQueue(token, msg, true)) {
// No. Return error after deleting the allocated request.
response.setError(msg.getServerID(), msg.getFunctionCode(), REQUEST_QUEUE_FULL);
} else {
// Request is queued - wait for the result.
response = waitSync(msg.getServerID(), msg.getFunctionCode(), token);
}
} else {
// Request is queued - wait for the result.
response = waitSync(msg.getServerID(), msg.getFunctionCode(), token);
response.setError(msg.getServerID(), msg.getFunctionCode(), EMPTY_MESSAGE);
}
} else {
response.setError(msg.getServerID(), msg.getFunctionCode(), EMPTY_MESSAGE);
}
return response;
return response;
}
// addToQueue: send freshly created request to queue
bool ModbusClientTCPasync::addToQueue(int32_t token, ModbusMessage request, bool syncReq) {
// Did we get one?
if (request) {
LOCK_GUARD(lock1, qLock);
if (txQueue.size() + rxQueue.size() < MTA_qLimit) {
HEXDUMP_V("Enqueue", request.data(), request.size());
RequestEntry *re = new RequestEntry(token, request, syncReq);
if (!re) return false; //TODO: proper error returning in case allocation fails
// inject proper transactionID
re->head.transactionID = messageCount++;
re->head.len = request.size();
// if we're already connected, try to send and push to rxQueue
// or else push to txQueue and (re)connect
if (MTA_state == CONNECTED && send(re)) {
re->sentTime = millis();
rxQueue[re->head.transactionID] = re;
} else {
txQueue.push_back(re);
if (MTA_state == DISCONNECTED) {
connect();
// Did we get one?
if (request) {
LOCK_GUARD(lock1, qLock);
if (txQueue.size() + rxQueue.size() < MTA_qLimit) {
HEXDUMP_V("Enqueue", request.data(), request.size());
RequestEntry * re = new RequestEntry(token, request, syncReq);
if (!re)
return false; // TODO proper error returning in case allocation fails
// inject proper transactionID
re->head.transactionID = messageCount++;
re->head.len = request.size();
// if we're already connected, try to send and push to rxQueue
// or else push to txQueue and (re)connect
if (MTA_state == CONNECTED && send(re)) {
re->sentTime = millis();
rxQueue[re->head.transactionID] = re;
} else {
txQueue.push_back(re);
if (MTA_state == DISCONNECTED) {
connect();
}
}
return true;
}
}
return true;
LOG_E("queue is full\n");
}
LOG_E("queue is full\n");
}
return false;
return false;
}
void ModbusClientTCPasync::onConnected() {
LOG_D("connected\n");
LOCK_GUARD(lock1, sLock);
MTA_state = CONNECTED;
MTA_lastActivity = millis();
// from now on onPoll will be called every 500 msec
LOG_D("connected\n");
LOCK_GUARD(lock1, sLock);
MTA_state = CONNECTED;
MTA_lastActivity = millis();
// from now on onPoll will be called every 500 msec
}
void ModbusClientTCPasync::onDisconnected() {
LOG_D("disconnected\n");
LOCK_GUARD(lock1, sLock);
MTA_state = DISCONNECTED;
LOG_D("disconnected\n");
LOCK_GUARD(lock1, sLock);
MTA_state = DISCONNECTED;
// empty queue on disconnect, calling errorcode on every waiting request
LOCK_GUARD(lock2, qLock);
while (!txQueue.empty()) {
RequestEntry* r = txQueue.front();
if (onError) {
onError(IP_CONNECTION_FAILED, r->token);
// empty queue on disconnect, calling errorcode on every waiting request
LOCK_GUARD(lock2, qLock);
while (!txQueue.empty()) {
RequestEntry * r = txQueue.front();
if (onError) {
onError(IP_CONNECTION_FAILED, r->token);
}
delete r;
txQueue.pop_front();
}
delete r;
txQueue.pop_front();
}
while (!rxQueue.empty()) {
RequestEntry *r = rxQueue.begin()->second;
if (onError) {
onError(IP_CONNECTION_FAILED, r->token);
while (!rxQueue.empty()) {
RequestEntry * r = rxQueue.begin()->second;
if (onError) {
onError(IP_CONNECTION_FAILED, r->token);
}
delete r;
rxQueue.erase(rxQueue.begin());
}
delete r;
rxQueue.erase(rxQueue.begin());
}
}
void ModbusClientTCPasync::onACError(AsyncClient* c, int8_t error) {
// onDisconnect will alse be called, so nothing to do here
LOG_W("TCP error: %s\n", c->errorToString(error));
void ModbusClientTCPasync::onACError(AsyncClient * c, int8_t error) {
// onDisconnect will alse be called, so nothing to do here
LOG_W("TCP error: %s\n", c->errorToString(error));
}
/*
@@ -222,180 +225,178 @@ void onAck(size_t len, uint32_t time) {
// assuming we don't need this
}
*/
void ModbusClientTCPasync::onPacket(uint8_t* data, size_t length) {
LOG_D("packet received (len:%d)\n", length);
// reset idle timeout
MTA_lastActivity = millis();
void ModbusClientTCPasync::onPacket(uint8_t * data, size_t length) {
LOG_D("packet received (len:%d)\n", length);
// reset idle timeout
MTA_lastActivity = millis();
if (length) {
LOG_D("parsing (len:%d)\n", length + 1);
}
while (length > 0) {
RequestEntry* request = nullptr;
ModbusMessage* response = nullptr;
uint16_t transactionID = 0;
uint16_t protocolID = 0;
uint16_t messageLength = 0;
bool isOkay = false;
// 1. Check for valid modbus message
// MBAP header is 6 bytes, we can't do anything with less
// total message should fit MBAP plus remaining bytes (in data[4], data[5])
if (length > 6) {
transactionID = (data[0] << 8) | data[1];
protocolID = (data[2] << 8) | data[3];
messageLength = (data[4] << 8) | data[5];
if (protocolID == 0 &&
length >= (uint32_t)messageLength + 6 &&
messageLength < 256) {
response = new ModbusMessage(messageLength);
response->add(&data[6], messageLength);
LOG_D("packet validated (len:%d)\n", messageLength);
// on next iteration: adjust remaining length and pointer to data
length -= 6 + messageLength;
data += 6 + messageLength;
isOkay = true;
}
if (length) {
LOG_D("parsing (len:%d)\n", length + 1);
}
while (length > 0) {
RequestEntry * request = nullptr;
ModbusMessage * response = nullptr;
uint16_t transactionID = 0;
uint16_t protocolID = 0;
uint16_t messageLength = 0;
bool isOkay = false;
if (!isOkay) {
// invalid packet, abort function
LOG_W("packet invalid\n");
return;
} else {
// 2. we got a valid response, match with a request
LOCK_GUARD(lock1, qLock);
auto i = rxQueue.find(transactionID);
if (i != rxQueue.end()) {
// found it, handle it and stop iterating
request = i->second;
i = rxQueue.erase(i);
LOG_D("matched request\n");
} else {
// TCP packet did not yield valid modbus response, abort function
LOG_W("no matching request found\n");
return;
}
}
// 1. Check for valid modbus message
// 3. we have a valid request and a valid response, call appropriate callback
if (request) {
// compare request with response
Error error = SUCCESS;
if (request->msg.getFunctionCode() != (response->getFunctionCode() & 0x7F)) {
error = FC_MISMATCH;
} else if (request->msg.getServerID() != response->getServerID()) {
error = SERVER_ID_MISMATCH;
} else {
error = response->getError();
}
// MBAP header is 6 bytes, we can't do anything with less
// total message should fit MBAP plus remaining bytes (in data[4], data[5])
if (length > 6) {
transactionID = (data[0] << 8) | data[1];
protocolID = (data[2] << 8) | data[3];
messageLength = (data[4] << 8) | data[5];
if (protocolID == 0 && length >= (uint32_t)messageLength + 6 && messageLength < 256) {
response = new ModbusMessage(messageLength);
response->add(&data[6], messageLength);
LOG_D("packet validated (len:%d)\n", messageLength);
if (error != SUCCESS) {
LOCK_GUARD(errorCntLock, countAccessM);
errorCount++;
}
if (request->isSyncRequest) {
{
LOCK_GUARD(sL ,syncRespM);
syncResponse[request->token] = *response;
// on next iteration: adjust remaining length and pointer to data
length -= 6 + messageLength;
data += 6 + messageLength;
isOkay = true;
}
}
} else if (onResponse) {
onResponse(*response, request->token);
} else {
if (error == SUCCESS) {
if (onData) {
onData(*response, request->token);
}
if (!isOkay) {
// invalid packet, abort function
LOG_W("packet invalid\n");
return;
} else {
if (onError) {
onError(response->getError(), request->token);
}
// 2. we got a valid response, match with a request
LOCK_GUARD(lock1, qLock);
auto i = rxQueue.find(transactionID);
if (i != rxQueue.end()) {
// found it, handle it and stop iterating
request = i->second;
i = rxQueue.erase(i);
LOG_D("matched request\n");
} else {
// TCP packet did not yield valid modbus response, abort function
LOG_W("no matching request found\n");
return;
}
}
}
delete request;
}
delete response;
} // end processing of incoming data
// 3. we have a valid request and a valid response, call appropriate callback
if (request) {
// compare request with response
Error error = SUCCESS;
if (request->msg.getFunctionCode() != (response->getFunctionCode() & 0x7F)) {
error = FC_MISMATCH;
} else if (request->msg.getServerID() != response->getServerID()) {
error = SERVER_ID_MISMATCH;
} else {
error = response->getError();
}
// check if we have to send the next request
LOCK_GUARD(lock1, qLock);
handleSendingQueue();
if (error != SUCCESS) {
LOCK_GUARD(errorCntLock, countAccessM);
errorCount++;
}
if (request->isSyncRequest) {
{
LOCK_GUARD(sL, syncRespM);
syncResponse[request->token] = *response;
}
} else if (onResponse) {
onResponse(*response, request->token);
} else {
if (error == SUCCESS) {
if (onData) {
onData(*response, request->token);
}
} else {
if (onError) {
onError(response->getError(), request->token);
}
}
}
delete request;
}
delete response;
} // end processing of incoming data
// check if we have to send the next request
LOCK_GUARD(lock1, qLock);
handleSendingQueue();
}
void ModbusClientTCPasync::onPoll() {
{
LOCK_GUARD(lock1, qLock);
{
LOCK_GUARD(lock1, qLock);
// try to send whatever is waiting
handleSendingQueue();
// try to send whatever is waiting
handleSendingQueue();
// next check if timeout has struck for oldest request
if (!rxQueue.empty()) {
RequestEntry* request = rxQueue.begin()->second;
if (millis() - request->sentTime > MTA_timeout) {
LOG_D("request timeouts (now:%lu-sent:%u)\n", millis(), request->sentTime);
// oldest element timeouts, call onError and clean up
if (onError) {
// Handle timeout error
onError(TIMEOUT, request->token);
}
delete request;
rxQueue.erase(rxQueue.begin());
// next check if timeout has struck for oldest request
if (!rxQueue.empty()) {
RequestEntry * request = rxQueue.begin()->second;
if (millis() - request->sentTime > MTA_timeout) {
LOG_D("request timeouts (now:%lu-sent:%u)\n", millis(), request->sentTime);
// oldest element timeouts, call onError and clean up
if (onError) {
// Handle timeout error
onError(TIMEOUT, request->token);
}
delete request;
rxQueue.erase(rxQueue.begin());
}
}
} // end lockguard scope
// if nothing happened during idle timeout, gracefully close connection
if (millis() - MTA_lastActivity > MTA_idleTimeout) {
disconnect();
}
}
} // end lockguard scope
// if nothing happened during idle timeout, gracefully close connection
if (millis() - MTA_lastActivity > MTA_idleTimeout) {
disconnect();
}
}
void ModbusClientTCPasync::handleSendingQueue() {
// ATTENTION: This method does not have a lock guard.
// Calling sites must assure shared resources are protected
// by mutex.
// ATTENTION: This method does not have a lock guard.
// Calling sites must assure shared resources are protected
// by mutex.
// try to send everything we have waiting
std::list<RequestEntry*>::iterator it = txQueue.begin();
while (it != txQueue.end()) {
// get the actual element
if (send(*it)) {
// after sending, update timeout value, add to other queue and remove from this queue
(*it)->sentTime = millis();
rxQueue[(*it)->head.transactionID] = (*it); // push request to other queue
it = txQueue.erase(it); // remove from toSend queue and point i to next request
} else {
// sending didn't succeed, try next request
++it;
// try to send everything we have waiting
std::list<RequestEntry *>::iterator it = txQueue.begin();
while (it != txQueue.end()) {
// get the actual element
if (send(*it)) {
// after sending, update timeout value, add to other queue and remove from this queue
(*it)->sentTime = millis();
rxQueue[(*it)->head.transactionID] = (*it); // push request to other queue
it = txQueue.erase(it); // remove from toSend queue and point i to next request
} else {
// sending didn't succeed, try next request
++it;
}
}
}
}
bool ModbusClientTCPasync::send(RequestEntry* re) {
// ATTENTION: This method does not have a lock guard.
// Calling sites must assure shared resources are protected
// by mutex.
bool ModbusClientTCPasync::send(RequestEntry * re) {
// ATTENTION: This method does not have a lock guard.
// Calling sites must assure shared resources are protected
// by mutex.
if (rxQueue.size() >= MTA_maxInflightRequests) {
if (rxQueue.size() >= MTA_maxInflightRequests) {
return false;
}
// check if TCP client is able to send
if (MTA_client.space() > ((uint32_t)re->msg.size() + 6)) {
// Write TCP header first
MTA_client.add(reinterpret_cast<const char *>((const uint8_t *)(re->head)), 6, ASYNC_WRITE_FLAG_COPY);
// Request comes next
MTA_client.add(reinterpret_cast<const char *>(re->msg.data()), re->msg.size(), ASYNC_WRITE_FLAG_COPY);
// done
MTA_client.send();
LOG_D("request sent (msgid:%d)\n", re->head.transactionID);
return true;
}
return false;
}
// check if TCP client is able to send
if (MTA_client.space() > ((uint32_t)re->msg.size() + 6)) {
// Write TCP header first
MTA_client.add(reinterpret_cast<const char *>((const uint8_t *)(re->head)), 6, ASYNC_WRITE_FLAG_COPY);
// Request comes next
MTA_client.add(reinterpret_cast<const char*>(re->msg.data()), re->msg.size(), ASYNC_WRITE_FLAG_COPY);
// done
MTA_client.send();
LOG_D("request sent (msgid:%d)\n", re->head.transactionID);
return true;
}
return false;
}

View File

@@ -42,7 +42,7 @@ class FSPersistence {
// hard-coded emergency defaults are now applied.
#ifdef EMSESP_DEBUG
Serial.println();
Serial.printf("Applying defaults to %s ", _filePath);
Serial.printf("Applying defaults to %s", _filePath);
Serial.println();
#endif
applyDefaults();

View File

@@ -354,31 +354,39 @@ void NetworkSettingsService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
setWiFiPowerOnRSSI();
}
#if ESP_IDF_VERSION_MAJOR < 5
WiFi.enableIpV6();
WiFi.enableIpV6(); // force ipv6
#endif
break;
case ARDUINO_EVENT_ETH_CONNECTED:
#if ESP_IDF_VERSION_MAJOR < 5
ETH.enableIpV6();
ETH.enableIpV6(); // force ipv6
#endif
break;
// IPv6 specific
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
case ARDUINO_EVENT_ETH_GOT_IP6:
#if !TASMOTA_SDK && ESP_IDF_VERSION_MAJOR < 5
if (emsesp::EMSESP::system_.ethernet_connected()) {
emsesp::EMSESP::logger().info("Local IPv6=%s", ETH.localIPv6().toString().c_str());
} else {
emsesp::EMSESP::logger().info("Local IPv6=%s", WiFi.localIPv6().toString().c_str());
}
emsesp::EMSESP::logger().info("Local IPv6 (WiFi)=%s", WiFi.localIPv6().toString().c_str());
#else
emsesp::EMSESP::logger().info("Local IPv6=%s", IPAddress(IPv6, (uint8_t *)info.got_ip6.ip6_info.ip.addr, 0).toString().c_str());
#endif
emsesp::EMSESP::system_.has_ipv6(true);
break;
// IPv6 specific
// This a bug in arduino where this is triggered twice, so we prevent it
case ARDUINO_EVENT_ETH_GOT_IP6:
if (!emsesp::EMSESP::system_.has_ipv6()) {
#if !TASMOTA_SDK && ESP_IDF_VERSION_MAJOR < 5
emsesp::EMSESP::logger().info("Local IPv6 (Eth)=%s", ETH.localIPv6().toString().c_str());
#else
emsesp::EMSESP::logger().info("Local IPv6=%s", IPAddress(IPv6, (uint8_t *)info.got_ip6.ip6_info.ip.addr, 0).toString().c_str());
#endif
emsesp::EMSESP::system_.has_ipv6(true);
}
break;
default:
break;
}

View File

@@ -85,11 +85,7 @@ void Shell::stop() {
blocking_data->stop_ = true;
} else {
#if defined(EMSESP_STANDALONE)
if (running()) {
#else
if (running() && !has_flags(CommandFlags::LOCAL)) { // do not close local shell
#endif
stopped_ = true;
stopped();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -1,3 +1,6 @@
// used to simulate
// - file uploads
// - EventSource (SSE) for log messages
import formidable from 'formidable';
function pad(number) {
@@ -81,7 +84,7 @@ export default () => {
})
);
} else {
res.statusCode = 400;
res.statusCode = 406;
console.log('Invalid file extension!');
}
}
@@ -99,15 +102,21 @@ export default () => {
let count = 0;
const interval = setInterval(() => {
let message = 'message #' + count;
if (count % 6 === 1) {
message +=
' with a long message that will be wrapped, to see if it stays one a single line';
}
const data = {
t: new Date().toISOString(),
l: 3 + (count % 6),
i: count,
n: 'system',
m: 'message #' + count++
m: message
};
count++;
res.write(`data: ${JSON.stringify(data)}\n\n`);
}, 1000);
}, 800);
// if client closes connection
res.on('close', () => {

View File

@@ -124,7 +124,8 @@ const LOG_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'logSettings';
let log_settings = {
level: 6,
max_messages: 50,
compact: true
compact: true,
psram: true
};
const FETCH_LOG_ENDPOINT = REST_ENDPOINT_ROOT + 'fetchLog';

View File

@@ -33,11 +33,12 @@ build_flags =
-D CONFIG_ASYNC_TCP_STACK_SIZE=6144
-D CONFIG_ASYNC_TCP_QUEUE=32
-D CONFIG_ASYNC_TCP_TASK_PRIORITY=10
-D CORE_DEBUG_LEVEL=0
unbuild_flags =
${common.core_unbuild_flags}
[espressi32_base]
[espressif32_base]
platform = espressif32@6.8.1
framework = arduino
board_build.filesystem = littlefs
@@ -49,7 +50,7 @@ extra_scripts =
pre:scripts/build_interface.py
scripts/rename_fw.py
[espressi32_base_tasmota]
[espressif32_base_tasmota]
; use Tasmota's library for 4MB variants
; it removes some unused libs (like mbedtsl, so no WiFi_secure.h) and increases available heap
; Tasmota Arduino Core 2.0.18 with IPv6 support, based on IDF 4.4.8
@@ -81,75 +82,72 @@ lib_deps =
;
; builds for GitHub Actions CI
; We don't set EMSESP_DEFAULT_BOARD_PROFILE and let the code determine the board type. e.g. with board_build.extra_flags = '-DEMSESP_DEFAULT_BOARD_PROFILE="S32"'
;
; the Web interface is built seperately during the GH Action so is skipped (not included in extra_scripts)
; the Web interface is built separately during the GH Action script, so skipped on these targets
;
[env:ci_s_4M]
; 4MB ESP32 - using Tasmota - no SSL, no PSRAM - like the BBQKees older S32 models
extends = espressi32_base_tasmota
; 4MB ESP32 - using Tasmota - no SSL, no PSRAM - like the BBQKees older S32 and E32 models
extends = espressif32_base_tasmota
extra_scripts = scripts/rename_fw.py
board = esp32dev
board_upload.flash_size = 4MB
board_build.partitions = esp32_partition_4M.csv
board_build.extra_flags = '-DEMSESP_DEFAULT_BOARD_PROFILE="S32"'
[env:ci_s_16M]
; 16MB ESP32 - using Tasmota - no SSL, no PSRAM - like the BBQKees older S32 models
extends = espressi32_base_tasmota
; 16MB ESP32 - using Tasmota - no SSL, no PSRAM - like the BBQKees some later S32 models
extends = espressif32_base_tasmota
extra_scripts = scripts/rename_fw.py
board = esp32dev
board_upload.flash_size = 16MB
board_build.partitions = esp32_partition_16M.csv
board_build.extra_flags = '-DEMSESP_DEFAULT_BOARD_PROFILE="S32"'
[env:ci_s_16M_P]
; 16MB ESP32 - with PSRAM - like BBQKees E32V2
extends = espressi32_base
extends = espressif32_base
extra_scripts = scripts/rename_fw.py
board = esp32dev
board_upload.flash_size = 16MB
board_build.partitions = esp32_partition_16M.csv
board_build.extra_flags = -DBOARD_HAS_PSRAM '-DEMSESP_DEFAULT_BOARD_PROFILE="E32V2"'
board_build.extra_flags = -DBOARD_HAS_PSRAM
[env:ci_s3_16M_P]
; 16MB ESP32-S3 - with PSRAM - like BBQKees S3
extends = espressi32_base
extends = espressif32_base
extra_scripts = scripts/rename_fw.py
board = lolin_s3
board_build.f_cpu = 240000000L
board_upload.flash_size = 16MB
board_build.partitions = esp32_partition_16M.csv
board_build.extra_flags = -DBOARD_HAS_PSRAM '-DEMSESP_DEFAULT_BOARD_PROFILE="S32S3"'
board_build.extra_flags = -DBOARD_HAS_PSRAM
;
; Direct builds
;
; For board params see jsonb files in https://github.com/platformio/platform-espressif32/tree/master/boards
; For board params see json files in https://github.com/platformio/platform-espressif32/tree/master/boards
;
[env:s_4M]
extends = espressi32_base_tasmota
extends = espressif32_base_tasmota
board = esp32dev
board_upload.flash_size = 4MB
board_build.partitions = esp32_partition_4M.csv
board_build.extra_flags = '-DEMSESP_DEFAULT_BOARD_PROFILE="S32"'
[env:s_asym_4M]
extends = espressi32_base_tasmota
extends = espressif32_base_tasmota
board = esp32dev
board_upload.flash_size = 4MB
board_build.partitions = esp32_asym_partition_4M.csv
board_build.extra_flags = '-DEMSESP_DEFAULT_BOARD_PROFILE="S32"'
[env:s_16M_P]
extends = espressi32_base
extends = espressif32_base
board = esp32dev
board_upload.flash_size = 16MB
board_build.partitions = esp32_partition_16M.csv
board_build.extra_flags = -DBOARD_HAS_PSRAM '-DEMSESP_DEFAULT_BOARD_PROFILE="S32"'
board_build.extra_flags = -DBOARD_HAS_PSRAM
[env:c3_mini_4M]
extends = espressi32_base_tasmota
extends = espressif32_base_tasmota
board = lolin_c3_mini
board_upload.flash_size = 4MB
board_build.partitions = esp32_partition_4M.csv
@@ -158,14 +156,14 @@ board_build.extra_flags = '-DEMSESP_DEFAULT_BOARD_PROFILE="C3MINI"'
; lolin C3 mini v1 needs special wifi init.
; https://www.wemos.cc/en/latest/c3/c3_mini_1_0_0.html#about-wifi
[env:c3_miniv1_4M]
extends = espressi32_base_tasmota
extends = espressif32_base_tasmota
board = lolin_c3_mini
board_upload.flash_size = 4MB
board_build.partitions = esp32_partition_4M.csv
board_build.extra_flags = -DBOARD_C3_MINI_V1 '-DEMSESP_DEFAULT_BOARD_PROFILE="C3MINI"'
[env:s2_4M]
extends = espressi32_base_tasmota
extends = espressif32_base_tasmota
board = lolin_s2_mini
board_upload.flash_size = 4MB
board_build.partitions = esp32_partition_4M.csv
@@ -173,28 +171,28 @@ board_build.extra_flags = '-DEMSESP_DEFAULT_BOARD_PROFILE="S2MINI"'
; https://github.com/platformio/platform-espressif32/blob/master/boards/lolin_s3.json
[env:s3_16M_P]
extends = espressi32_base
extends = espressif32_base
board = lolin_s3
board_upload.use_1200bps_touch = false
board_upload.wait_for_upload_port = false
board_upload.flash_size = 16MB
board_build.partitions = esp32_partition_16M.csv
board_build.extra_flags = -DBOARD_HAS_PSRAM '-DEMSESP_DEFAULT_BOARD_PROFILE="S32S3"'
board_build.extra_flags = -DBOARD_HAS_PSRAM
[env:s3_32M_P]
extends = espressi32_base
extends = espressif32_base
board = lolin_s3
board_build.arduino.memory_type: opi_opi
board_build.flash_mode = opi
board_upload.flash_size = 32MB
board_build.partitions = esp32_partition_32M.csv
board_build.extra_flags = -DBOARD_HAS_PSRAM '-DEMSESP_DEFAULT_BOARD_PROFILE="S32S3"'
board_build.extra_flags = -DBOARD_HAS_PSRAM
;
; Building and testing natively, standalone without an ESP32.
; See https://docs.platformio.org/en/latest/platforms/native.html
;
; It will generate an executbale which when run will show the EMS-ESP Console where you can run tests using the `test` command.
; It will generate an executable which when run will show the EMS-ESP Console where you can run tests using the `test` command.
;
; See https://docs.platformio.org/en/latest/core/installation/shell-commands.html#piocore-install-shell-commands
;
@@ -203,8 +201,8 @@ board_build.extra_flags = -DBOARD_HAS_PSRAM '-DEMSESP_DEFAULT_BOARD_PROFILE="S32
; to build and run on Windows, it needs winsock for the console input so:
; - For the first time, install Msys2 (https://www.msys2.org/) and the GCC compiler with `run pacman -S mingw-w64-ucrt-x86_64-gcc`
; - Then, build with `pio run -e native` to create the program.exe file
; - run by calling the executable from the Mysys shell e.g. `C:/msys64/msys2_shell.cmd -defterm -here -no-start -ucrt64 -c /d/dev/proddy/EMS-ESP32/.pio/build/native/program.exe`
; - or integrate into Windows Terminal https://www.msys2.org/docs/terminals/
; - run by calling the executable from the Mysys shell e.g. `C:/msys64/msys2_shell.cmd -defterm -here -no-start -ucrt64 -c <location>/.pio/build/native/program.exe`
; - or use with Windows Terminal https://www.msys2.org/docs/terminals/
;
[env:native]
platform = native
@@ -243,7 +241,7 @@ lib_ignore = Module EMS-ESP-Modules
; unit tests
; pio run -e native-test -t exec
; works on Linux, Windows, and MacOS
; to auto generate the API exepected test results, compile with -DEMSESP_UNITY_CREATE and capture the output, and paste into the test_api.cpp file
; to update the test results, compile with -DEMSESP_UNITY_CREATE, run and capture the output and then paste this into the test_api.cpp file
[env:native-test]
platform = native
test_build_src = true

View File

@@ -29,6 +29,7 @@ void AnalogSensor::start() {
if (!analog_enabled_) {
return;
}
analogSetAttenuation(ADC_2_5db); // for all channels 1.5V
LOG_INFO("Starting Analog Sensor service");
@@ -135,9 +136,9 @@ void AnalogSensor::reload(bool get_nvs) {
// first check if the GPIO is valid. If not, force set it to disabled
if (!System::is_valid_gpio(sensor.gpio())) {
LOG_WARNING("Bad GPIO %d for Sensor %s", sensor.gpio(), sensor.name().c_str());
LOG_WARNING("Bad GPIO %d for Sensor %s. Disabling.", sensor.gpio(), sensor.name().c_str());
sensor.set_type(AnalogType::NOTUSED);
continue;
continue; // skip this loop pass
}
if (sensor.type() == AnalogType::ADC) {
@@ -260,6 +261,7 @@ void AnalogSensor::measure() {
sensor.sum_ = (sensor.sum_ * 511) / 512 + a;
sensor.analog_ = sensor.sum_ / 512;
}
// detect change with little hysteresis on raw mV value
if (sensor.last_reading_ + 1 < sensor.analog_ || sensor.last_reading_ > sensor.analog_ + 1) {
sensor.set_value(((int32_t)sensor.analog_ - sensor.offset()) * sensor.factor());
@@ -300,6 +302,7 @@ void AnalogSensor::measure() {
sensor.last_polltime_ = sensor.polltime_;
}
}
// see if there is a change and increment # reads
if (old_value != sensor.value()) {
sensorreads_++;
@@ -308,6 +311,7 @@ void AnalogSensor::measure() {
}
}
}
// store counter-values only every hour to reduce flash wear
static uint8_t lastSaveHour = 0;
time_t now = time(nullptr);

View File

@@ -68,7 +68,7 @@ static std::vector<std::string> log_level_autocomplete(Shell & shell, const std:
}
static void setup_commands(std::shared_ptr<Commands> & commands) {
// log, exit, help
// exit, help, log
commands->add_command(ShellContext::MAIN, CommandFlags::USER, {F_(exit)}, EMSESPShell::main_exit_function);
commands->add_command(ShellContext::MAIN, CommandFlags::USER, {F_(help)}, EMSESPShell::main_help_function);
commands->add_command(ShellContext::MAIN, CommandFlags::USER, {F_(log)}, {F_(log_level_optional)}, console_log_level, log_level_autocomplete);
@@ -91,6 +91,10 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
string_vector{F_(show), F_(devices)},
[](Shell & shell, const std::vector<std::string> & arguments) { to_app(shell).show_devices(shell); });
commands->add_command(ShellContext::MAIN, CommandFlags::USER, string_vector{F_(show), F_(log)}, [](Shell & shell, const std::vector<std::string> & arguments) {
to_app(shell).webLogService.show(shell);
});
commands->add_command(ShellContext::MAIN, CommandFlags::USER, string_vector{F_(show), F_(ems)}, [](Shell & shell, const std::vector<std::string> & arguments) {
to_app(shell).show_ems(shell);
@@ -269,7 +273,7 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
ShellContext::MAIN,
CommandFlags::ADMIN,
string_vector{F_(set), F_(board_profile)},
string_vector{F_(name_mandatory), F_(nvs_optional)},
string_vector{F_(name_mandatory)},
[](Shell & shell, const std::vector<std::string> & arguments) {
std::vector<int8_t> data; // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode
std::string board_profile = Helpers::toUpper(arguments.front());
@@ -277,9 +281,7 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
shell.println("Invalid board profile (S32, E32, E32V2, MH-ET, NODEMCU, LOLIN, OLIMEX, OLIMEXPOE, C3MINI, S2MINI, S3MINI, S32S3, CUSTOM)");
return;
}
if (arguments.size() == 2 && Helpers::toLower(arguments.back()) == "nvs") {
to_app(shell).nvs_.putString("boot", board_profile.c_str());
}
to_app(shell).webSettingsService.update([&](WebSettings & settings) {
settings.board_profile = board_profile.c_str();
settings.led_gpio = data[0];
@@ -686,7 +688,11 @@ void EMSESPShell::end_of_transmission() {
void EMSESPShell::main_help_function(Shell & shell, const std::vector<std::string> & arguments) {
shell.println();
#ifndef EMSESP_DEBUG
shell.printfln("%s%sEMS-ESP version %s%s", COLOR_BRIGHT_GREEN, COLOR_BOLD_ON, EMSESP_APP_VERSION, COLOR_RESET);
#else
shell.printfln("%s%sEMS-ESP version %s%s (DEBUG)", COLOR_BRIGHT_GREEN, COLOR_BOLD_ON, EMSESP_APP_VERSION, COLOR_RESET);
#endif
shell.println();
shell.print_all_available_commands();
}
@@ -695,7 +701,7 @@ void EMSESPShell::main_exit_function(Shell & shell, const std::vector<std::strin
shell.stop();
}
// **** EMSESPConsole *****
// **** EMSESPConsole Class *****
#ifndef EMSESP_STANDALONE
std::vector<bool> EMSESPConsole::ptys_;

View File

@@ -1341,7 +1341,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
fetch_device_values(device_id); // go and fetch its device entity data
// Print to LOG showing we've added a new device
LOG_INFO("Recognized new %s with deviceID 0x%02X", EMSdevice::device_type_2_device_name(device_type), device_id);
LOG_INFO("Detected EMS device: %s (0x%02X)", EMSdevice::device_type_2_device_name(device_type), device_id);
// register the MQTT subscribe topic for this device
// except for connect, controller and gateway
@@ -1541,68 +1541,69 @@ void EMSESP::start() {
#ifndef EMSESP_STANDALONE
system_.PSram(ESP.getPsramSize());
#endif
// don't need shell if running unit tests
#ifndef EMSESP_UNITY
// Serial console's shell
serial_console_.begin(SERIAL_CONSOLE_BAUD_RATE);
shell_ = std::make_shared<EMSESPConsole>(*this, serial_console_, true);
shell_->maximum_log_messages(100);
shell_->start();
#if defined(EMSESP_DEBUG)
shell_->log_level(uuid::log::Level::DEBUG);
#else
shell_->log_level(uuid::log::Level::TRACE);
#endif
#if defined(EMSESP_STANDALONE)
shell_->add_flags(CommandFlags::ADMIN); // always start in su/admin mode when running tests
// always start a serial console if we're running standalone, except if we're running unit tests
#if defined(EMSESP_STANDALONE) || defined(EMSESP_DEBUG)
#ifndef EMSESP_UNITY
start_serial_console();
#endif
#endif
// start the file system
#ifndef EMSESP_STANDALONE
if (!LittleFS.begin(true)) {
LOG_INFO("LittleFS Mount Failed. Using default settings.");
LOG_ERROR("LittleFS Mount Failed");
return;
}
#endif
// do a quick scan of the filesystem to see if we have a /config folder
// so we know if this is a new install or not
// do a quick scan of the filesystem to see if we a settings file in the /config folder
// so we know if this is a new factory install or not
#ifndef EMSESP_STANDALONE
File root = LittleFS.open(EMSESP_FS_CONFIG_DIRECTORY);
File root = LittleFS.open(EMSESP_SETTINGS_FILE);
bool factory_settings = !root;
if (!root) {
LOG_INFO("No config found, assuming factory settings");
LOG_WARNING("No settings found on filesystem. Using factory settings.");
}
root.close();
#else
bool factory_settings = false;
#endif
webLogService.begin(); // start web log service. now we can start capturing logs to the web log
// start web log service. now we can start capturing logs to the web log
webLogService.begin();
esp8266React.begin(); // loads core system services settings (network, mqtt, ap, ntp etc)
if (!nvs_.begin("ems-esp", false, "nvs1")) { // try bigger nvs partition on 16M flash first
nvs_.begin("ems-esp", false, "nvs"); // fallback to small nvs
}
LOG_DEBUG("NVS device information: %s", system_.getBBQKeesGatewayDetails().c_str());
// loads core system services settings (network, mqtt, ap, ntp etc)
esp8266React.begin();
#ifndef EMSESP_STANDALONE
LOG_INFO("Booting EMS-ESP version %s from %s partition", EMSESP_APP_VERSION, esp_ota_get_running_partition()->label); // welcome message
LOG_INFO("Booting EMS-ESP version %s from %s/%s partition",
EMSESP_APP_VERSION,
esp_ota_get_boot_partition()->label,
esp_ota_get_running_partition()->label); // welcome message
#else
LOG_INFO("Booting EMS-ESP version %s", EMSESP_APP_VERSION); // welcome message
#endif
LOG_DEBUG("System is running in Debug mode");
LOG_INFO("Last system reset reason Core0: %s, Core1: %s", system_.reset_reason(0).c_str(), system_.reset_reason(1).c_str());
// see if we're restoring a settings file
// see if we're restoring a settings file
#ifndef EMSESP_STANDALONE
if (system_.check_restore()) {
LOG_WARNING("System needs a restart to apply new settings. Please wait.");
LOG_WARNING("EMS-ESP will restart to apply new settings. Please wait.");
system_.system_restart();
};
#endif
webSettingsService.begin(); // load EMS-ESP Application settings...
if (!nvs_.begin("ems-esp", false, "nvs1")) { // try bigger nvs partition on 16M flash first
nvs_.begin("ems-esp", false, "nvs"); // fallback to small nvs
}
LOG_DEBUG("NVS device information: %s", system_.getBBQKeesGatewayDetails().isEmpty() ? "not set" : system_.getBBQKeesGatewayDetails().c_str());
webSettingsService.begin(); // load EMS-ESP Application settings
// do any system upgrades
if (system_.check_upgrade(factory_settings)) {
@@ -1653,11 +1654,11 @@ void EMSESP::start() {
// main loop calling all services
void EMSESP::loop() {
esp8266React.loop(); // web services
system_.loop(); // does LED and checks system health, and syslog service
static bool upload_status = true; // ready for any OTA uploads
esp8266React.loop(); // web services
system_.loop(); // does LED and checks system health, and syslog service
// if we're doing an OTA upload, skip everything except from console refresh
static bool upload_status = true; // ready for any OTA uploads
if (!system_.upload_isrunning()) {
// service loops
webLogService.loop(); // log in Web UI
@@ -1688,13 +1689,54 @@ void EMSESP::loop() {
if (system_.telnet_enabled()) {
telnet_.loop();
}
#else
if (!shell_->running()) {
::exit(0);
}
#endif
Shell::loop_all();
static bool show_prompt = true;
// user has to ctrl-c to create a serial console stream, exit command will close it
// this is to save around 2kb of heap memory
if (shell_) {
if (!shell_->running()) {
shell_.reset();
#ifdef EMSESP_STANDALONE
::exit(0); // kill session
#endif
shell_prompt();
}
} else {
if (show_prompt) {
shell_prompt();
show_prompt = false; // only show it once
}
int c = serial_console_.read();
if (c != -1) {
show_prompt = true;
}
if (c == '\x03' || c == '\x0C') {
start_serial_console();
}
}
}
void EMSESP::start_serial_console() {
shell_ = std::make_shared<EMSESPConsole>(*this, serial_console_, true);
shell_->maximum_log_messages(100);
shell_->add_flags(CommandFlags::ADMIN); // always start in su/admin mode when running tests
shell_->start();
#if defined(EMSESP_DEBUG)
shell_->log_level(uuid::log::Level::DEBUG);
#else
shell_->log_level(uuid::log::Level::TRACE);
#endif
}
void EMSESP::shell_prompt() {
#ifndef EMSESP_STANDALONE
serial_console_.println();
serial_console_.println("Press CTRL-C to activate this serial console");
#endif
}
} // namespace emsesp

View File

@@ -252,6 +252,9 @@ class EMSESP {
static void publish_response(std::shared_ptr<const Telegram> telegram);
static void publish_all_loop();
void shell_prompt();
void start_serial_console();
static constexpr uint32_t EMS_FETCH_FREQUENCY = 60000; // check every minute
static constexpr uint8_t EMS_WAIT_KM_TIMEOUT = 60; // wait one minute

View File

@@ -147,7 +147,6 @@ MAKE_WORD_CUSTOM(sensorid_optional, "[sensor ID]")
MAKE_WORD_CUSTOM(id_optional, "[id|hc]")
MAKE_WORD_CUSTOM(partitionname_optional, "[partitionname]")
MAKE_WORD_CUSTOM(data_optional, "[data]")
MAKE_WORD_CUSTOM(nvs_optional, "[nvs]")
MAKE_WORD_CUSTOM(offset_optional, "[offset]")
MAKE_WORD_CUSTOM(length_optional, "[length]")
MAKE_WORD_CUSTOM(typeid_mandatory, "<type ID>")

View File

@@ -1,6 +1,5 @@
/**
* TODO:
* - verwendete libs in readme hinzufügen
* TODO: verwendete libs in readme hinzufügen
*/
#include "modbus.h"
#include "modbus_entity_parameters.hpp"

View File

@@ -37,8 +37,6 @@ const std::initializer_list<Modbus::EntityModbusInfo> Modbus::modbus_register_ma
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DEVICE_DATA, FL_(pumpMode), 18, 1), // pumpmode
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DEVICE_DATA, FL_(pumpCharacter), 19, 1), // pumpcharacter
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DEVICE_DATA, FL_(pumpDelay), 20, 1), // pumpdelay
// REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DEVICE_DATA, FL_(setFlowTemp), 21, 1), // setflowtemp
// REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DEVICE_DATA, FL_(setBurnPow), 22, 1), // setburnpow
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DEVICE_DATA, FL_(selBurnPow), 23, 1), // selburnpow
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DEVICE_DATA, FL_(curBurnPow), 24, 1), // curburnpow
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DEVICE_DATA, FL_(burnStarts), 25, 2), // burnstarts
@@ -183,6 +181,8 @@ const std::initializer_list<Modbus::EntityModbusInfo> Modbus::modbus_register_ma
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DEVICE_DATA, FL_(keepWarmTemp), 261, 1), // keepwarmtemp
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DEVICE_DATA, FL_(setReturnTemp), 262, 1), // setreturntemp
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DEVICE_DATA, FL_(heatingOn), 263, 1), // heating
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DEVICE_DATA, FL_(nrgCool), 264, 2), // nrgcool
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DEVICE_DATA, FL_(meterCool), 266, 2), // metercool
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DHW, FL_(nrgWw), 0, 2), // nrg
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DHW, FL_(meterWw), 2, 2), // meter
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DHW, FL_(upTimeCompWw), 4, 2), // uptimecomp
@@ -239,7 +239,6 @@ const std::initializer_list<Modbus::EntityModbusInfo> Modbus::modbus_register_ma
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DHW, FL_(wwTempOK), 60, 1), // tempok
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DHW, FL_(wwActive), 61, 1), // active
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DHW, FL_(ww3wayValve), 62, 1), // 3wayvalve
// REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DHW, FL_(wwSetPumpPower), 63, 1), // setpumppower
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DHW, FL_(wwMixerTemp), 64, 1), // mixertemp
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DHW, FL_(cylMiddleTemp), 65, 1), // cylmiddletemp
REGISTER_MAPPING(dt::BOILER, TAG_TYPE_DHW, FL_(wwStarts), 66, 2), // starts
@@ -313,7 +312,7 @@ const std::initializer_list<Modbus::EntityModbusInfo> Modbus::modbus_register_ma
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(noreducetemp), 31, 1), // noreducetemp
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(reducetemp), 32, 1), // reducetemp
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(wwprio), 33, 1), // dhwprio
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(hpcooling), 34, 1), // cooling
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(hpcooling), 34, 1), // hpcooling
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(coolingOn), 35, 1), // coolingon
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(hpmode), 36, 1), // hpmode
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(dewoffset), 37, 1), // dewoffset
@@ -344,7 +343,6 @@ const std::initializer_list<Modbus::EntityModbusInfo> Modbus::modbus_register_ma
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(daylowtemp), 100, 1), // daytemp2
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(daymidtemp), 101, 1), // daytemp3
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(dayhightemp), 102, 1), // daytemp4
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(wwswitchtime), 103, 8), // switchtime
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(vacations1), 111, 11), // vacations1
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(vacations2), 122, 11), // vacations2
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(vacations3), 133, 11), // vacations3
@@ -357,6 +355,11 @@ const std::initializer_list<Modbus::EntityModbusInfo> Modbus::modbus_register_ma
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(heattemp), 190, 1), // heattemp
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(roomsensor), 191, 1), // roomsensor
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(heatup), 192, 1), // heatup
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(coolstart), 193, 1), // coolstart
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(coolondelay), 194, 1), // coolondelay
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(cooloffdelay), 195, 1), // cooloffdelay
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(switchProgMode), 196, 1), // switchprogmode
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_HC, FL_(switchtime), 197, 8), // switchtime
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(mode), 0, 1), // mode
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(wwSetTemp), 1, 1), // settemp
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(wwSetTempLow), 2, 1), // settemplow
@@ -374,7 +377,7 @@ const std::initializer_list<Modbus::EntityModbusInfo> Modbus::modbus_register_ma
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(wwDisinfectHour), 14, 1), // disinfecthour
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(wwMaxTemp), 15, 1), // maxtemp
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(wwOneTimeKey), 16, 1), // onetimekey
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(wwswitchtime), 17, 8), // switchtime
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(wwswitchtime), 17, 8), // switchtimeWW
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(wwcircswitchtime), 25, 8), // circswitchtime
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(holidays), 33, 13), // holidays
REGISTER_MAPPING(dt::THERMOSTAT, TAG_TYPE_DHW, FL_(vacations), 46, 13), // vacations
@@ -433,7 +436,7 @@ const std::initializer_list<Modbus::EntityModbusInfo> Modbus::modbus_register_ma
REGISTER_MAPPING(dt::SOLAR, TAG_TYPE_DEVICE_DATA, FL_(heatMetering), 42, 1), // heatmetering
REGISTER_MAPPING(dt::SOLAR, TAG_TYPE_DEVICE_DATA, FL_(activated), 43, 1), // activated
REGISTER_MAPPING(dt::SOLAR, TAG_TYPE_DEVICE_DATA, FL_(solarPumpMode), 44, 1), // solarpumpmode
REGISTER_MAPPING(dt::SOLAR, TAG_TYPE_DEVICE_DATA, FL_(solarPumpKick), 45, 1), // pumpkick
REGISTER_MAPPING(dt::SOLAR, TAG_TYPE_DEVICE_DATA, FL_(solarPumpKick), 45, 1), // solarpumpkick
REGISTER_MAPPING(dt::SOLAR, TAG_TYPE_DEVICE_DATA, FL_(plainWaterMode), 46, 1), // plainwatermode
REGISTER_MAPPING(dt::SOLAR, TAG_TYPE_DEVICE_DATA, FL_(doubleMatchFlow), 47, 1), // doublematchflow
REGISTER_MAPPING(dt::SOLAR, TAG_TYPE_DEVICE_DATA, FL_(pump2MinMod), 48, 1), // pump2minmod

View File

@@ -106,18 +106,19 @@ void Shower::loop() {
// duration in seconds
doc["duration"] = duration_; // seconds
time_t now = time(nullptr);
// if NTP enabled, publish timestamp
if (now > 1576800000) { // year 2020
// doc["timestamp_s"] = now; // if needed, in seconds
tm * tm_ = localtime(&now);
char dt[25];
strftime(dt, sizeof(dt), "%FT%T%z", tm_);
doc["timestamp"] = dt;
LOG_INFO("shower finished %s (duration %lu s)", dt, duration_);
} else {
LOG_INFO("shower finished (duration %lu s)", duration_);
}
// time_t now = time(nullptr);
// // if NTP enabled, publish timestamp
// if (now > 1576800000) { // year 2020
// // doc["timestamp_s"] = now; // if needed, in seconds
// tm * tm_ = localtime(&now);
// char dt[25];
// strftime(dt, sizeof(dt), "%FT%T%z", tm_);
// doc["timestamp"] = dt;
// LOG_INFO("Shower finished %s (duration %lus)", dt, duration_);
// } else {
// LOG_INFO("Shower finished (duration %lus)", duration_);
// }
LOG_INFO("Shower finished (duration %lus)", duration_);
Mqtt::queue_publish("shower_data", doc.as<JsonObject>());
}
}
@@ -210,7 +211,7 @@ void Shower::set_shower_state(bool state, bool force) {
ha_configdone_ = Mqtt::queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
//
// shower duaration
// shower duration
//
doc.clear();

View File

@@ -466,8 +466,8 @@ bool System::is_valid_gpio(uint8_t pin, bool has_psram) {
return false; // bad pin
}
// extra check for pins 21 and 22 (I2C) when ethernet is enabled
if ((EMSESP::system_.ethernet_connected()) && (pin >= 21 && pin <= 22)) {
// extra check for pins 21 and 22 (I2C) when ethernet is onboard
if ((EMSESP::system_.ethernet_connected() || EMSESP::system_.phy_type_ != PHY_type::PHY_TYPE_NONE) && (pin >= 21 && pin <= 22)) {
return false; // bad pin
}
return true;
@@ -540,6 +540,7 @@ void System::button_init(bool refresh) {
reload_settings();
}
#ifndef EMSESP_STANDALONE
if (!is_valid_gpio(pbutton_gpio_)) {
LOG_WARNING("Invalid button GPIO. Check config.");
myPButton_.init(255, HIGH); // disable
@@ -555,6 +556,7 @@ void System::button_init(bool refresh) {
myPButton_.onDblClick(BUTTON_DblClickDelay, button_OnDblClick);
myPButton_.onLongPress(BUTTON_LongPressDelay, button_OnLongPress);
myPButton_.onVLongPress(BUTTON_VLongPressDelay, button_OnVLongPress);
#endif
}
// set the LED to on or off when in normal operating mode
@@ -997,7 +999,7 @@ void System::show_system(uuid::console::Shell & shell) {
#ifndef EMSESP_STANDALONE
shell.printfln(" Platform: %s (%s)", EMSESP_PLATFORM, ESP.getChipModel());
shell.printfln(" Model: %s", getBBQKeesGatewayDetails().c_str());
shell.printfln(" Partition Boot/Running: %s/%s", esp_ota_get_boot_partition()->label, esp_ota_get_running_partition()->label);
shell.printfln(" Partition boot/running: %s/%s", esp_ota_get_boot_partition()->label, esp_ota_get_running_partition()->label);
#endif
shell.printfln(" Language: %s", locale().c_str());
shell.printfln(" Board profile: %s", board_profile().c_str());
@@ -1022,11 +1024,6 @@ void System::show_system(uuid::console::Shell & shell) {
shell.println();
shell.println("Network:");
// show ethernet mac address if we have an eth controller present
if (eth_present_) {
shell.printfln(" Ethernet MAC address: %s", ETH.macAddress().c_str());
}
switch (WiFi.status()) {
case WL_IDLE_STATUS:
shell.printfln(" Status: Idle");
@@ -1086,7 +1083,7 @@ void System::show_system(uuid::console::Shell & shell) {
// show Ethernet if connected
if (ethernet_connected_) {
shell.println();
shell.printfln(" Status: Ethernet connected");
shell.printfln(" Ethernet Status: connected");
shell.printfln(" Ethernet MAC address: %s", ETH.macAddress().c_str());
shell.printfln(" Hostname: %s", ETH.getHostname());
shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(ETH.localIP()).c_str(), uuid::printable_to_string(ETH.subnetMask()).c_str());
@@ -1196,7 +1193,7 @@ bool System::check_upgrade(bool factory_settings) {
version::Semver200_version settings_version(settingsVersion);
if (!missing_version) {
LOG_DEBUG("Checking version upgrade (settings file is v%d.%d.%d-%s)",
LOG_DEBUG("Checking for version upgrades (settings file has v%d.%d.%d-%s)",
settings_version.major(),
settings_version.minor(),
settings_version.patch(),
@@ -1213,46 +1210,69 @@ bool System::check_upgrade(bool factory_settings) {
// compare versions
if (this_version > settings_version) {
// need upgrade
LOG_NOTICE("Upgrading to version %d.%d.%d-%s", this_version.major(), this_version.minor(), this_version.patch(), this_version.prerelease().c_str());
// we need to do an upgrade
if (missing_version) {
LOG_NOTICE("Upgrading to version %d.%d.%d-%s", this_version.major(), this_version.minor(), this_version.patch(), this_version.prerelease().c_str());
} else {
LOG_NOTICE("Upgrading from version %d.%d.%d-%s to %d.%d.%d-%s",
settings_version.major(),
settings_version.minor(),
settings_version.patch(),
settings_version.prerelease().c_str(),
this_version.major(),
this_version.minor(),
this_version.patch(),
this_version.prerelease().c_str());
}
// if we're coming from 3.4.4 or 3.5.0b14 which had no version stored then we need to apply new settings
if (missing_version) {
LOG_INFO("Upgrade: Setting MQTT Entity ID format to older v3.4 format");
LOG_INFO("Upgrade: Setting MQTT Entity ID format to older v3.4 format (0)");
EMSESP::esp8266React.getMqttSettingsService()->update([&](MqttSettings & mqttSettings) {
mqttSettings.entity_format = Mqtt::entityFormat::SINGLE_LONG; // use old Entity ID format from v3.4
return StateUpdateResult::CHANGED;
});
} else if (settings_version.major() == 3 && settings_version.minor() <= 6) {
LOG_INFO("Upgrade: Setting MQTT Entity ID format to v3.6 format");
EMSESP::esp8266React.getMqttSettingsService()->update([&](MqttSettings & mqttSettings) {
if (mqttSettings.entity_format == 1) {
mqttSettings.entity_format = Mqtt::entityFormat::SINGLE_OLD; // use old Entity ID format from v3.6
LOG_INFO("Upgrade: Setting MQTT Entity ID format to v3.6 format (3)");
return StateUpdateResult::CHANGED;
} else if (mqttSettings.entity_format == 2) {
mqttSettings.entity_format = Mqtt::entityFormat::MULTI_OLD; // use old Entity ID format from v3.6
LOG_INFO("Upgrade: Setting MQTT Entity ID format to v3.6 format (4)");
return StateUpdateResult::CHANGED;
}
return StateUpdateResult::UNCHANGED;
});
}
// force WiFi sleep to off (was default on < 3.7.0-dev-33)
EMSESP::esp8266React.getNetworkSettingsService()->update([&](NetworkSettings & networkSettings) {
networkSettings.nosleep = true;
return StateUpdateResult::CHANGED;
});
// Network Settings Wifi tx_power is now using the value * 4.
// changes to Network
EMSESP::esp8266React.getNetworkSettingsService()->update([&](NetworkSettings & networkSettings) {
// Network Settings Wifi tx_power is now using the value * 4.
if (networkSettings.tx_power == 20) {
networkSettings.tx_power = WIFI_POWER_19_5dBm; // use 19.5 as we don't have 20 anymore
LOG_INFO("Upgrade: Setting WiFi TX Power to Auto");
}
// force WiFi sleep to off (was default on < 3.7.0-dev-33)
networkSettings.nosleep = true;
LOG_INFO("Upgrade: Disabling WiFi nosleep");
return StateUpdateResult::CHANGED;
});
// changes to application settings
EMSESP::webSettingsService.update([&](WebSettings & settings) {
// force web buffer to 25 for those boards without psram
if (EMSESP::system_.PSram() == 0) {
settings.weblog_buffer = 25;
return StateUpdateResult::CHANGED;
}
return StateUpdateResult::UNCHANGED;
});
} else if (this_version < settings_version) {
// need downgrade
LOG_NOTICE("Downgrading to version %d.%d.%d-%s", this_version.major(), this_version.minor(), this_version.patch(), this_version.prerelease().c_str());
@@ -1267,7 +1287,7 @@ bool System::check_upgrade(bool factory_settings) {
settings.version = EMSESP_APP_VERSION;
return StateUpdateResult::CHANGED;
});
LOG_INFO("Upgrade: Setting version to %s", EMSESP_APP_VERSION);
// LOG_INFO("Upgrade: Setting version to %s", EMSESP_APP_VERSION);
return true; // need reboot
}
@@ -1300,7 +1320,7 @@ bool System::saveSettings(const char * filename, const char * section, JsonObjec
if (section_json) {
File section_file = LittleFS.open(filename, "w");
if (section_file) {
LOG_INFO("Applying new %s", section);
LOG_INFO("Applying new uploaded %s data", section);
serializeJson(section_json, section_file);
section_file.close();
return true; // reboot required
@@ -1438,7 +1458,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output
#endif
node["resetReason"] = EMSESP::system_.reset_reason(0) + " / " + EMSESP::system_.reset_reason(1);
#ifndef EMSESP_STANDALONE
node["psram"] = (EMSESP::system_.PSram() > 0); // boolean
node["psram"] = (EMSESP::system_.PSram() > 0); // make boolean
if (EMSESP::system_.PSram()) {
node["psramSize"] = EMSESP::system_.PSram();
node["freePsram"] = ESP.getFreePsram() / 1024;
@@ -1756,10 +1776,11 @@ bool System::load_board_profile(std::vector<int8_t> & data, const std::string &
(int8_t)EMSESP::system_.eth_phy_addr_,
(int8_t)EMSESP::system_.eth_clock_mode_};
} else {
// unknown, return false
return false;
LOG_DEBUG("Couldn't identify board profile %s", board_profile.c_str());
return false; // unknown, return false
}
// LOG_DEBUG("Found data for board profile %s", board_profile.c_str());
return true;
}

View File

@@ -217,6 +217,10 @@ class System {
has_ipv6_ = b;
}
bool has_ipv6() {
return has_ipv6_;
}
void ntp_connected(bool b);
bool ntp_connected();

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.7.0-dev.34"
#define EMSESP_APP_VERSION "3.7.0-dev.35"

View File

@@ -18,6 +18,8 @@
#include "emsesp.h"
using ::uuid::console::Shell;
namespace emsesp {
WebLogService::WebLogService(AsyncWebServer * server, SecurityManager * securityManager)
@@ -75,12 +77,15 @@ size_t WebLogService::maximum_log_messages() const {
void WebLogService::maximum_log_messages(size_t count) {
maximum_log_messages_ = std::max((size_t)1, count);
if (limit_log_messages_ > maximum_log_messages_) {
limit_log_messages_ = maximum_log_messages_;
}
while (log_messages_.size() > maximum_log_messages_) {
log_messages_.pop_front();
}
EMSESP::webSettingsService.update([&](WebSettings & settings) {
settings.weblog_buffer = count;
return StateUpdateResult::CHANGED;
@@ -132,6 +137,42 @@ void WebLogService::operator<<(std::shared_ptr<uuid::log::Message> message) {
});
}
// dumps out the contents of log buffer to shell console
void WebLogService::show(Shell & shell) {
if (log_messages_.empty()) {
return;
}
shell.println();
shell.printfln("Last Log (filtered by WebLog's level %s & buffer %d):", format_level_uppercase(log_level()), maximum_log_messages());
shell.println();
for (const auto & message : log_messages_) {
log_message_id_tail_ = message.id_;
shell.print(uuid::log::format_timestamp_ms(message.content_->uptime_ms, 3));
shell.printf(" %c %lu: [%s] ", uuid::log::format_level_char(message.content_->level), message.id_, message.content_->name);
if ((message.content_->level == uuid::log::Level::ERR) || (message.content_->level == uuid::log::Level::WARNING)) {
shell.print(COLOR_RED);
shell.println(message.content_->text);
shell.print(COLOR_RESET);
} else if (message.content_->level == uuid::log::Level::INFO) {
shell.print(COLOR_YELLOW);
shell.println(message.content_->text);
shell.print(COLOR_RESET);
} else if (message.content_->level == uuid::log::Level::DEBUG) {
shell.print(COLOR_CYAN);
shell.println(message.content_->text);
shell.print(COLOR_RESET);
} else {
shell.println(message.content_->text);
}
}
shell.println();
}
void WebLogService::loop() {
if (!events_.count() || log_messages_.empty()) {
return;
@@ -200,7 +241,7 @@ void WebLogService::fetchLog(AsyncWebServerRequest * request) {
request->send(200);
}
// sets the values like level after a POST
// sets the values after a POST
void WebLogService::getSetValues(AsyncWebServerRequest * request, JsonVariant json) {
if ((request->method() == HTTP_GET) || (!json.is<JsonObject>())) {
// GET - return the values
@@ -209,12 +250,13 @@ void WebLogService::getSetValues(AsyncWebServerRequest * request, JsonVariant js
root["level"] = log_level();
root["max_messages"] = maximum_log_messages();
root["compact"] = compact();
root["psram"] = (EMSESP::system_.PSram() > 0);
response->setLength();
request->send(response);
return;
}
// POST - write the settings
auto && body = json.as<JsonObject>();
uuid::log::Level level = body["level"];

View File

@@ -23,6 +23,8 @@
#define EMSESP_FETCH_LOG_PATH "/rest/fetchLog"
#define EMSESP_LOG_SETTINGS_PATH "/rest/logSettings"
using ::uuid::console::Shell;
namespace emsesp {
class WebLogService : public uuid::log::Handler {
@@ -42,6 +44,7 @@ class WebLogService : public uuid::log::Handler {
bool compact() const;
void compact(bool compact);
void loop();
void show(Shell & shell);
virtual void operator<<(std::shared_ptr<uuid::log::Message> message);

View File

@@ -28,15 +28,16 @@ WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, Securit
server->on(EMSESP_BOARD_PROFILE_SERVICE_PATH,
HTTP_GET,
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { board_profile(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
addUpdateHandler([this] { onUpdate(); }, false);
server->on(EMSESP_GET_SETTINGS_PATH,
HTTP_GET,
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { getSettings(request); }, AuthenticationPredicates::IS_ADMIN));
addUpdateHandler([this] { onUpdate(); }, false);
}
void WebSettings::read(WebSettings & settings, JsonObject root) {
root["version"] = settings.version;
root["board_profile"] = settings.board_profile;
root["platform"] = EMSESP_PLATFORM;
root["locale"] = settings.locale;
root["tx_mode"] = settings.tx_mode;
root["ems_bus_id"] = settings.ems_bus_id;
@@ -67,7 +68,6 @@ void WebSettings::read(WebSettings & settings, JsonObject root) {
root["analog_enabled"] = settings.analog_enabled;
root["pbutton_gpio"] = settings.pbutton_gpio;
root["solar_maxflow"] = settings.solar_maxflow;
root["board_profile"] = settings.board_profile;
root["fahrenheit"] = settings.fahrenheit;
root["bool_format"] = settings.bool_format;
root["bool_dashboard"] = settings.bool_dashboard;
@@ -79,7 +79,6 @@ void WebSettings::read(WebSettings & settings, JsonObject root) {
root["eth_power"] = settings.eth_power;
root["eth_phy_addr"] = settings.eth_phy_addr;
root["eth_clock_mode"] = settings.eth_clock_mode;
root["platform"] = EMSESP_PLATFORM;
root["modbus_enabled"] = settings.modbus_enabled;
root["modbus_port"] = settings.modbus_port;
root["modbus_max_clients"] = settings.modbus_max_clients;
@@ -88,90 +87,116 @@ void WebSettings::read(WebSettings & settings, JsonObject root) {
// call on initialization and also when settings are updated via web or console
StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
// load the version of the settings
// will be picked up in System::check_upgrade()
// load the version from the settings config. This can be blank and later used in System::check_upgrade()
settings.version = root["version"] | EMSESP_DEFAULT_VERSION;
// load default GPIO configuration based on board profile
std::vector<int8_t> data; // // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode
settings.board_profile = root["board_profile"] | EMSESP_DEFAULT_BOARD_PROFILE;
// for -D compile setting store it in NVS
if ((String)EMSESP_DEFAULT_BOARD_PROFILE != "default" && EMSESP::nvs_.getString("boot") == "") {
EMSESP::nvs_.putString("boot", (const char *)EMSESP_DEFAULT_BOARD_PROFILE);
}
#ifndef EMSESP_STANDALONE
bool psram = ESP.getPsramSize() > 0; // System::PSram() is initialized later
#else
bool psram = false;
#endif
if (System::load_board_profile(data, settings.board_profile.c_str())) {
if (settings.board_profile == "CUSTOM") { //read pins, fallback to S32
data = {(int8_t)(root["led_gpio"] | 2),
(int8_t)(root["dallas_gpio"] | 18),
(int8_t)(root["rx_gpio"] | 23),
(int8_t)(root["tx_gpio"] | 5),
(int8_t)(root["pbutton_gpio"] | 0),
(int8_t)(root["phy_type"] | PHY_type::PHY_TYPE_NONE),
(int8_t)(root["eth_power"] | 0),
(int8_t)(root["eth_phy_addr"] | 0),
(int8_t)(root["eth_clock_mode"] | 0)};
#ifdef EMSESP_DEBUG
EMSESP::logger().debug("NVS boot value=[%s], board profile=[%s], EMSESP_DEFAULT_BOARD_PROFILE=[%s]",
EMSESP::nvs_.getString("boot").c_str(),
root["board_profile"] | "",
EMSESP_DEFAULT_BOARD_PROFILE);
#endif
// get the current board profile saved in the settings file
settings.board_profile = root["board_profile"] | EMSESP_DEFAULT_BOARD_PROFILE; // this is set at compile time in platformio.ini, other it's "default"
String old_board_profile = settings.board_profile;
// The optional NVS boot value has priority and overrides any board_profile setting.
// We only do this for BBQKees boards
// Note 1: we never set the NVS boot value in the code - this is done on initial pre-loading
// Note 2: The board profile is dynamically changed for the session, but the value in the settings file on the FS remains untouched
if (!EMSESP::system_.getBBQKeesGatewayDetails().isEmpty()) {
String nvs_boot = EMSESP::nvs_.getString("boot");
if (!nvs_boot.isEmpty()) {
#ifdef EMSESP_DEBUG
EMSESP::logger().debug("Overriding board profile with NVS boot value %s");
#endif
settings.board_profile = nvs_boot;
}
// check valid pins in this board profile
if (!System::is_valid_gpio(data[0], psram) || !System::is_valid_gpio(data[1], psram) || !System::is_valid_gpio(data[2], psram)
|| !System::is_valid_gpio(data[3], psram) || !System::is_valid_gpio(data[4], psram) || !System::is_valid_gpio(data[6], psram)) {
settings.board_profile = ""; // reset to factory default
}
} else {
settings.board_profile = ""; // reset to factory default
}
if (settings.board_profile == "") {
// unknown, check for NVS or scan for ethernet, use default E32/E32V2/S32
settings.board_profile = EMSESP::nvs_.getString("boot");
if (!System::load_board_profile(data, settings.board_profile.c_str())) {
#if defined(EMSESP_STANDALONE)
settings.board_profile = "S32";
#elif CONFIG_IDF_TARGET_ESP32
if (settings.board_profile == "" && !psram) { // empty: new test for E32
#if ESP_ARDUINO_VERSION_MAJOR < 3
if (ETH.begin(1, 16, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_IN)) {
#else
if (ETH.begin(ETH_PHY_LAN8720, 1, 23, 18, 16, ETH_CLOCK_GPIO0_IN)) {
#endif
EMSESP::nvs_.putString("boot", "E32");
} else {
EMSESP::nvs_.putString("boot", "Test");
}
} else if (settings.board_profile == "Test" || psram) { // test E32V2
#if ESP_ARDUINO_VERSION_MAJOR < 3
if (ETH.begin(0, 15, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_OUT)) {
#else
if (ETH.begin(ETH_PHY_LAN8720, 0, 23, 18, 15, ETH_CLOCK_GPIO0_OUT)) {
#endif
EMSESP::nvs_.putString("boot", "E32V2");
} else {
EMSESP::nvs_.putString("boot", "S32");
}
} else {
EMSESP::nvs_.putString("boot", "S32");
// load the board profile from the settings, if it's not "default"
std::vector<int8_t> data; // // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode
if (settings.board_profile != "default") {
if (System::load_board_profile(data, settings.board_profile.c_str())) {
if (settings.board_profile == "CUSTOM") { // read pins, fallback to S32 values
data = {(int8_t)(root["led_gpio"] | 2),
(int8_t)(root["dallas_gpio"] | 18),
(int8_t)(root["rx_gpio"] | 23),
(int8_t)(root["tx_gpio"] | 5),
(int8_t)(root["pbutton_gpio"] | 0),
(int8_t)(root["phy_type"] | PHY_type::PHY_TYPE_NONE),
(int8_t)(root["eth_power"] | 0),
(int8_t)(root["eth_phy_addr"] | 0),
(int8_t)(root["eth_clock_mode"] | 0)};
}
// ESP.restart();
EMSESP::system_.restart_requested(true);
#elif CONFIG_IDF_TARGET_ESP32C3
settings.board_profile = "C3MINI";
#elif CONFIG_IDF_TARGET_ESP32S2
settings.board_profile = "S2MINI";
#elif CONFIG_IDF_TARGET_ESP32S3
settings.board_profile = "S32S3"; // BBQKees Gateway S3
#else
settings.board_profile = "S32";
#endif
System::load_board_profile(data, settings.board_profile.c_str());
// check valid pins in this board profile
if (!System::is_valid_gpio(data[0], psram) || !System::is_valid_gpio(data[1], psram) || !System::is_valid_gpio(data[2], psram)
|| !System::is_valid_gpio(data[3], psram) || !System::is_valid_gpio(data[4], psram) || !System::is_valid_gpio(data[6], psram)) {
settings.board_profile = "default"; // reset to factory default
}
} else {
settings.board_profile = "default"; // can't find profile, use "default"
}
EMSESP::logger().info("No board profile found. Re-setting to %s", settings.board_profile.c_str());
}
// still don't have a valid board profile. Let's see if we can determine one
if (settings.board_profile == "default") {
#ifdef EMSESP_DEBUG
EMSESP::logger().debug("Trying to detect board and set board profile...");
#endif
#if defined(EMSESP_STANDALONE)
settings.board_profile = "S32";
#elif CONFIG_IDF_TARGET_ESP32
// check for no PSRAM, could be a E32 or S32
if (!psram) {
#if ESP_ARDUINO_VERSION_MAJOR < 3
if (ETH.begin(1, 16, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_IN)) {
#else
if (ETH.begin(ETH_PHY_LAN8720, 1, 23, 18, 16, ETH_CLOCK_GPIO0_IN)) {
#endif
settings.board_profile = "E32"; // Ethernet without PSRAM
} else {
settings.board_profile = "S32"; // ESP32 standard WiFi without PSRAM
}
} else {
// check for boards with PSRAM, could be a E32V2 otherwise default back to the S32
#if ESP_ARDUINO_VERSION_MAJOR < 3
if (ETH.begin(0, 15, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_OUT)) {
#else
if (ETH.begin(ETH_PHY_LAN8720, 0, 23, 18, 15, ETH_CLOCK_GPIO0_OUT)) {
#endif
settings.board_profile = "E32V2"; // Ethernet and PSRAM
} else {
settings.board_profile = "S32"; // ESP32 standard WiFi with PSRAM
}
}
// override if we know the target from the build config like C3, S2, S3 etc..
#elif CONFIG_IDF_TARGET_ESP32C3
settings.board_profile = "C3MINI";
#elif CONFIG_IDF_TARGET_ESP32S2
settings.board_profile = "S2MINI";
#elif CONFIG_IDF_TARGET_ESP32S3
settings.board_profile = "S32S3"; // BBQKees Gateway S3
#endif
// apply the new board profile setting
System::load_board_profile(data, settings.board_profile.c_str());
}
if (old_board_profile != settings.board_profile) {
// see if need to override the set board profile (e.g. forced by NVS boot string)
EMSESP::logger().info("Setting new Board profile %s (was %s)", settings.board_profile.c_str(), old_board_profile.c_str());
} else {
EMSESP::logger().info("Loading board profile %s", settings.board_profile.c_str());
EMSESP::logger().info("Board profile set to %s", settings.board_profile.c_str());
}
int prev;
@@ -233,7 +258,7 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
}
#endif
// temperaturesensor
// temperature sensor
prev = settings.dallas_parasite;
settings.dallas_parasite = root["dallas_parasite"] | EMSESP_DEFAULT_DALLAS_PARASITE;
check_flag(prev, settings.dallas_parasite, ChangeFlags::SENSOR);
@@ -343,13 +368,20 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
EMSESP::system_.bool_dashboard(settings.bool_dashboard);
settings.weblog_level = root["weblog_level"] | EMSESP_DEFAULT_WEBLOG_LEVEL;
settings.weblog_buffer = root["weblog_buffer"] | EMSESP_DEFAULT_WEBLOG_BUFFER;
settings.weblog_compact = root["weblog_compact"] | EMSESP_DEFAULT_WEBLOG_COMPACT;
// if no psram limit weblog buffer to 25 messages
if (EMSESP::system_.PSram() > 0) {
settings.weblog_buffer = root["weblog_buffer"] | EMSESP_DEFAULT_WEBLOG_BUFFER;
} else {
settings.weblog_buffer = root["weblog_buffer"] | 25;
}
// save the settings
if (flags_ == WebSettings::ChangeFlags::RESTART) {
if (get_flags() == WebSettings::ChangeFlags::RESTART) {
return StateUpdateResult::CHANGED_RESTART; // tell WebUI that a restart is needed
}
return StateUpdateResult::CHANGED;
}
@@ -377,11 +409,11 @@ void WebSettingsService::onUpdate() {
}
if (WebSettings::has_flags(WebSettings::ChangeFlags::BUTTON)) {
EMSESP::system_.button_init(true); // reload settings
EMSESP::system_.button_init(true);
}
if (WebSettings::has_flags(WebSettings::ChangeFlags::LED)) {
EMSESP::system_.led_init(true); // reload settings
EMSESP::system_.led_init(true);
}
if (WebSettings::has_flags(WebSettings::ChangeFlags::MQTT)) {
@@ -393,6 +425,7 @@ void WebSettingsService::onUpdate() {
void WebSettingsService::begin() {
_fsPersistence.readFromFS();
WebSettings::reset_flags();
}

View File

@@ -3,7 +3,7 @@
// Compile with -DEMSESP_UNITY_CREATE to generate the test functions
// and copy the output and paste below.
//
// TODO: convert output to JSON and compare, showing differences
// TODO convert output to JSON and compare, showing differences
//
// You can also manually compare the differences using https://www.diffchecker.com/text-compare/
//