Merge branch 'dev' into dev

This commit is contained in:
Proddy
2022-05-29 16:28:15 +02:00
committed by GitHub
22 changed files with 440 additions and 322 deletions

View File

@@ -9,9 +9,10 @@ jobs:
build: build:
name: Build name: Build
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository_owner == 'emsesp'
# if: github.repository == 'emsesp/EMS-ESP32'
env: env:
# https://binaries.sonarsource.com/?prefix=Distribution/sonar-scanner-cli/ # https://binaries.sonarsource.com/?prefix=Distribution/sonar-scanner-cli/
# SONAR_SCANNER_VERSION: 4.6.1.2450
SONAR_SCANNER_VERSION: 4.7.0.2747 SONAR_SCANNER_VERSION: 4.7.0.2747
SONAR_SERVER_URL: "https://sonarcloud.io" SONAR_SERVER_URL: "https://sonarcloud.io"
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory

View File

@@ -5,6 +5,108 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
# [3.4.1] May 29 2022
## Fixed
- Fix memory leak in api [#524](https://github.com/emsesp/EMS-ESP32/issues/524)
## Changed
- Controller data in web-ui only for IVT [#522](https://github.com/emsesp/EMS-ESP32/issues/522)
- Rename hidden `climate` to a more explaining name [#523](https://github.com/emsesp/EMS-ESP32/issues/523)
- Minor changes to the Customizations web page [#527](https://github.com/emsesp/EMS-ESP32/pull/527)
# [3.4.0] May 23 2022
## Added
- WebUI optimizations, updated look&feel and better performance [#124](https://github.com/emsesp/EMS-ESP32/issues/124)
- Auto refresh of WebUI after successful firmware upload [#178](https://github.com/emsesp/EMS-ESP32/issues/178)
- New Customization Service in WebUI. First feature is the ability to enable/disabled Enitites (device values) from EMS devices [#206](https://github.com/emsesp/EMS-ESP32/issues/206)
- Option to disable Telnet Console [#209](https://github.com/emsesp/EMS-ESP32/issues/209)
- Added Hide SSID, Max Clients and Preferred Channel to Access Point
- Merged in MichaelDvP's changes like Fahrenheit conversion, publish single (for IOBroker) and a few other critical optimizations
- Enabled bi-directional read/write with Home Assistant, so values can be changed automatically from the UI without scripting [#265](https://github.com/emsesp/EMS-ESP32/issues/265)
- Added GC7000F Boiler [#270](https://github.com/emsesp/EMS-ESP32/issues/270)
- Revised LED flash sequence on boot up to show system health (1 flash=no ems, 2 flashes=no wifi) [#224](https://github.com/emsesp/EMS-ESP32/issues/224)
- Analog Sensor support [#271](https://github.com/emsesp/EMS-ESP32/issues/271)
- Solar cylinder priority [#247](https://github.com/emsesp/EMS-ESP32/issues/247)
- Read only mode in Settings, where EMS Tx/Write commands are blocked [#286](https://github.com/emsesp/EMS-ESP32/issues/286)
- Added 8700i Boiler device
- Added Cascade CM10 Controller device
- Add Olimex ESP32-POE-ISO to board profiles plus settings to customize Ethernet modules [#301](https://github.com/emsesp/EMS-ESP32/issues/301)
- Help text for string commands in WebUI [#320](https://github.com/emsesp/EMS-ESP32/issues/320)
- Germany translations (at compile time)
- #entities added to system/info` endpoint [#322](https://github.com/emsesp/EMS-ESP32/issues/322)
- analog outputs digital/pwm/dac
- remove MQTT retained configs if discovery is disabled
- timeout 10 min for MQTT-QoS wait
- Moduline 300 auto-temperatures T1-T4, RC300 romminfluencefactor
- RC35 parameters [#392](https://github.com/emsesp/EMS-ESP32/issues/392), [#398](https://github.com/emsesp/EMS-ESP32/issues/398)
- sync time with thermostat [#386](https://github.com/emsesp/EMS-ESP32/issues/386), [#408](https://github.com/emsesp/EMS-ESP32/issues/408)
- set mode has immediate effect [#395](https://github.com/emsesp/EMS-ESP32/issues/395)
- min/max in web value setting
- Extend customization to select if an entity is to be shown in the WebUI or forced as read-only [#317](https://github.com/emsesp/EMS-ESP32/issues/317)
- Added Moduline 400 installation parameters [PR #449 by @kwertie01](https://github.com/emsesp/EMS-ESP32/pull/449)
- Read time from IVT-controller [#439](https://github.com/emsesp/EMS-ESP32/issues/439)
- Hybrid Heatpump product-id 168 [#459](https://github.com/emsesp/EMS-ESP32/issues/459), thermostat settings
- Junkers ISM2 and IPM in warm water mode [#437](https://github.com/emsesp/EMS-ESP32/issues/437)
- Added Shower Alert trigger time and cold shot time [#436](https://github.com/emsesp/EMS-ESP32/issues/436)
- Improved Table layout in Web UI (searching, filtering, sorting, exporting to CSV)
- API fetch individual attributes from an entity [#462](https://github.com/emsesp/EMS-ESP32/issues/462)
- Option to disable mDNS
- Option for rendering booleans on dashboard [#456](https://github.com/emsesp/EMS-ESP32/issues/456)
- Upload customization settings from a file [#256](https://github.com/emsesp/EMS-ESP32/issues/256)
## Fixed
- lastcode broke MQTT JSON structure [#228](https://github.com/emsesp/EMS-ESP32/issues/228)
- fixed issue with overlapping while reading sequence of EMS1.0 telegrams
- fixed redundant telegram readings (because of offset overflow)
- added missing RC30/Moduline 400 [#243](https://github.com/emsesp/EMS-ESP32/issues/243)
- Correct modes for RC25 [#106](https://github.com/emsesp/EMS-ESP32/issues/106)
- Clean up old HA config's in MQTT before publishing data. This will prevent HA giving the 'dict' warnings [#229](https://github.com/emsesp/EMS-ESP32/issues/229)
- RC25 temperature setting [#272](https://github.com/emsesp/EMS-ESP32/issues/272)
- Buderus RC25 - "hc1 mode type" incorrect value [#273](https://github.com/emsesp/EMS-ESP32/issues/273)
- Increased number of Mixers and Heating Circuits [#294](https://github.com/emsesp/EMS-ESP32/issues/294)
- Check receive status before removing a telegram fetch [#268](https://github.com/emsesp/EMS-ESP32/issues/268), [#282](https://github.com/emsesp/EMS-ESP32/issues/282)
- Fix uploading firmware on OSX [#345](https://github.com/emsesp/EMS-ESP32/issues/345)
- Non-nested MQTT would corrupt the json [#354](https://github.com/emsesp/EMS-ESP32/issues/354)
- Burner selected max power can have a value higher than 100% [#314](https://github.com/emsesp/EMS-ESP32/issues/314)
- some missing fahrenheit calculations
- limited number of exclusions [#339](https://github.com/emsesp/EMS-ESP32/issues/339)
- MQTT sometimes would not reconnect after a WiFi outage
## Changed
- Use flash system to show system health (1 flash=no ems, 2 flashes=no wifi) [#224](https://github.com/emsesp/EMS-ESP32/issues/224)
- Renamed Dallas Sensor to Temperature Sensor in UI
- Dallas Format removed. Use the name to give each sensor an alias
- No longer MQTT subscribes to topic `/thermostat_hc<n>` as it supports a path similar to the API endpoint construct
- Show Sensors quality in WebUI
- Controller not shown in WebUI dashboard
- renamed "Home Assistant Integration" to "MQTT Discovery" in MQTT Settings [#290](https://github.com/emsesp/EMS-ESP32/issues/290)
- Show ems tx reads and writes separately
- Show ems device handlers separated for received, fetched and pending handlers.
- Wired renamed to Ethernet
- removed system/pin command, new commands in analogsensors
- system/info device-info split to name/version/brand
- exclude list uses short-names, possible flags for web/api/mqtt excludes, readonly and favorite (selection not yet implemented)
- thermostat clock formate date-time: dd.mm.yyyy hh:mm
- RC300 summermode as other thermostats `winter/summer` instead of `off/on`
## **BREAKING CHANGES:**
- Settings:
- order of Boolean Format has changed in Application Settings - check your settings
- Dallas Format setting removed. Now customize name of each Dallas sensor via the UI
- MQTT/API
- Boiler `wwheat` renamed to `ww3wayon` [#211](https://github.com/emsesp/EMS-ESP32/issues/211)
- Boiler `ww` tag renamed to `dhw`. Any custom Home Assistant lovelace dashboards will need updating.
- Renamed description of `wwtapactivated` to "turn on/off DHW". Otherwise would have looked like "boiler_dhw_turn_on_off_dhw" in HA.
- `/api/system/info` endpoint has updated keys. Now lowercase, no underscores and not capitalized. Replace "handlers" with "handlers received", "handlers fetched" and "handlers pending".
# [3.3.1] January 20 2022 # [3.3.1] January 20 2022
- lastcode broke MQTT JSON structure [#228](https://github.com/emsesp/EMS-ESP32/issues/228) - lastcode broke MQTT JSON structure [#228](https://github.com/emsesp/EMS-ESP32/issues/228)

View File

@@ -1,97 +1,19 @@
# Changelog # Changelog
## [3.4.0] # [3.4.2]
### Added ## Added
- Added damping for RC310 - RC310 additions [#520](https://github.com/emsesp/EMS-ESP32/pull/520)
- Added wwprio for RC310 heating circuits - damping
- Added switchonoptimization for RC310 heating circuits - wwprio for RC310 heating circuits
- Added enum_controlmode for RC310 (new enum list) - switchonoptimization for RC310 heating circuits
- Added nofrostmode, reducemode, reducetemp & noreducetemp for RC310 - enum_controlmode for RC310 (new enum list)
- Added emergencyops and emergencytemp, wwmaxtemp, wwflowtempoffset and wwcomfort1 for RC310 - nofrostmode, reducemode, reducetemp & noreducetemp for RC310
- WebUI optimizations, updated look&feel and better performance [#124](https://github.com/emsesp/EMS-ESP32/issues/124) - emergencyops and emergencytemp, wwmaxtemp, wwflowtempoffset and wwcomfort1 for RC310
- Auto refresh of WebUI after successful firmware upload [#178](https://github.com/emsesp/EMS-ESP32/issues/178)
- New Customization Service in WebUI. First feature is the ability to enable/disabled Enitites (device values) from EMS devices [#206](https://github.com/emsesp/EMS-ESP32/issues/206)
- Option to disable Telnet Console [#209](https://github.com/emsesp/EMS-ESP32/issues/209)
- Added Hide SSID, Max Clients and Preferred Channel to Access Point
- Merged in MichaelDvP's changes like Fahrenheit conversion, publish single (for IOBroker) and a few other critical optimizations
- Enabled bi-directional read/write with Home Assistant, so values can be changed automatically from the UI without scripting [#265](https://github.com/emsesp/EMS-ESP32/issues/265)
- Added GC7000F Boiler [#270](https://github.com/emsesp/EMS-ESP32/issues/270)
- Revised LED flash sequence on boot up to show system health (1 flash=no ems, 2 flashes=no wifi) [#224](https://github.com/emsesp/EMS-ESP32/issues/224)
- Analog Sensor support [#271](https://github.com/emsesp/EMS-ESP32/issues/271)
- Solar cylinder priority [#247](https://github.com/emsesp/EMS-ESP32/issues/247)
- Read only mode in Settings, where EMS Tx/Write commands are blocked [#286](https://github.com/emsesp/EMS-ESP32/issues/286)
- Added 8700i Boiler device
- Added Cascade CM10 Controller device
- Add Olimex ESP32-POE-ISO to board profiles plus settings to customize Ethernet modules [#301](https://github.com/emsesp/EMS-ESP32/issues/301)
- Help text for string commands in WebUI [#320](https://github.com/emsesp/EMS-ESP32/issues/320)
- Germany translations (at compile time)
- #entities added to system/info` endpoint [#322](https://github.com/emsesp/EMS-ESP32/issues/322)
- analog outputs digital/pwm/dac
- remove MQTT retained configs if discovery is disabled
- timeout 10 min for MQTT-QoS wait
- Moduline 300 auto-temperatures T1-T4, RC300 romminfluencefactor
- RC35 parameters [#392](https://github.com/emsesp/EMS-ESP32/issues/392), [#398](https://github.com/emsesp/EMS-ESP32/issues/398)
- sync time with thermostat [#386](https://github.com/emsesp/EMS-ESP32/issues/386), [#408](https://github.com/emsesp/EMS-ESP32/issues/408)
- set mode has immediate effect [#395](https://github.com/emsesp/EMS-ESP32/issues/395)
- min/max in web value setting
- Extend customization to select if an entity is to be shown in the WebUI or forced as read-only [#317](https://github.com/emsesp/EMS-ESP32/issues/317)
- Added Moduline 400 installation parameters [PR #449 by @kwertie01](https://github.com/emsesp/EMS-ESP32/pull/449)
- Read time from IVT-controller [#439](https://github.com/emsesp/EMS-ESP32/issues/439)
- Hybrid Heatpump product-id 168 [#459](https://github.com/emsesp/EMS-ESP32/issues/459), thermostat settings
- Junkers ISM2 and IPM in warm water mode [#437](https://github.com/emsesp/EMS-ESP32/issues/437)
- Added Shower Alert trigger time and cold shot time [#436](https://github.com/emsesp/EMS-ESP32/issues/436)
- Improved Table layout in Web UI (searching, filtering, sorting, exporting to CSV)
- API fetch individual attributes from an entity [#462](https://github.com/emsesp/EMS-ESP32/issues/462)
- Option to disable mDNS
- Option for rendering booleans on dashboard [#456](https://github.com/emsesp/EMS-ESP32/issues/456)
- Upload customization settings from a file [#256](https://github.com/emsesp/EMS-ESP32/issues/256)
### Fixed ## Fixed
- lastcode broke MQTT JSON structure [#228](https://github.com/emsesp/EMS-ESP32/issues/228) ## Changed
- fixed issue with overlapping while reading sequence of EMS1.0 telegrams
- fixed redundant telegram readings (because of offset overflow)
- added missing RC30/Moduline 400 [#243](https://github.com/emsesp/EMS-ESP32/issues/243)
- Correct modes for RC25 [#106](https://github.com/emsesp/EMS-ESP32/issues/106)
- Clean up old HA config's in MQTT before publishing data. This will prevent HA giving the 'dict' warnings [#229](https://github.com/emsesp/EMS-ESP32/issues/229)
- RC25 temperature setting [#272](https://github.com/emsesp/EMS-ESP32/issues/272)
- Buderus RC25 - "hc1 mode type" incorrect value [#273](https://github.com/emsesp/EMS-ESP32/issues/273)
- Increased number of Mixers and Heating Circuits [#294](https://github.com/emsesp/EMS-ESP32/issues/294)
- Check receive status before removing a telegram fetch [#268](https://github.com/emsesp/EMS-ESP32/issues/268), [#282](https://github.com/emsesp/EMS-ESP32/issues/282)
- Fix uploading firmware on OSX [#345](https://github.com/emsesp/EMS-ESP32/issues/345)
- Non-nested MQTT would corrupt the json [#354](https://github.com/emsesp/EMS-ESP32/issues/354)
- Burner selected max power can have a value higher than 100% [#314](https://github.com/emsesp/EMS-ESP32/issues/314)
- some missing fahrenheit calculations
- limited number of exclusions [#339](https://github.com/emsesp/EMS-ESP32/issues/339)
- MQTT sometimes would not reconnect after a WiFi outage
### Changed
- Use flash system to show system health (1 flash=no ems, 2 flashes=no wifi) [#224](https://github.com/emsesp/EMS-ESP32/issues/224)
- Renamed Dallas Sensor to Temperature Sensor in UI
- Dallas Format removed. Use the name to give each sensor an alias
- No longer MQTT subscribes to topic `/thermostat_hc<n>` as it supports a path similar to the API endpoint construct
- Show Sensors quality in WebUI
- Controller not shown in WebUI dashboard
- renamed "Home Assistant Integration" to "MQTT Discovery" in MQTT Settings [#290](https://github.com/emsesp/EMS-ESP32/issues/290)
- Show ems tx reads and writes separately
- Show ems device handlers separated for received, fetched and pending handlers.
- Wired renamed to Ethernet
- removed system/pin command, new commands in analogsensors
- system/info device-info split to name/version/brand
- exclude list uses short-names, possible flags for web/api/mqtt excludes, readonly and favorite (selection not yet implemented)
- thermostat clock formate date-time: dd.mm.yyyy hh:mm
- RC300 summermode as other thermostats `winter/summer` instead of `off/on`
## **BREAKING CHANGES:** ## **BREAKING CHANGES:**
- Settings:
- order of Boolean Format has changed in Application Settings - check your settings
- Dallas Format setting removed. Now customize name of each Dallas sensor via the UI
- MQTT/API
- Boiler `wwheat` renamed to `ww3wayon` [#211](https://github.com/emsesp/EMS-ESP32/issues/211)
- Boiler `ww` tag renamed to `dhw`. Any custom Home Assistant lovelace dashboards will need updating.
- Renamed description of `wwtapactivated` to "turn on/off DHW". Otherwise would have looked like "boiler_dhw_turn_on_off_dhw" in HA.
- `/api/system/info` endpoint has updated keys. Now lowercase, no underscores and not capitalized. Replace "handlers" with "handlers received", "handlers fetched" and "handlers pending".

View File

@@ -13,9 +13,9 @@
"@msgpack/msgpack": "^2.7.2", "@msgpack/msgpack": "^2.7.2",
"@mui/icons-material": "^5.8.0", "@mui/icons-material": "^5.8.0",
"@mui/material": "^5.8.1", "@mui/material": "^5.8.1",
"@table-library/react-table-library": "^3.1.2", "@table-library/react-table-library": "^3.1.4",
"@types/lodash": "^4.14.182", "@types/lodash": "^4.14.182",
"@types/node": "^17.0.35", "@types/node": "^17.0.36",
"@types/react": "^18.0.9", "@types/react": "^18.0.9",
"@types/react-dom": "^18.0.5", "@types/react-dom": "^18.0.5",
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",
@@ -3689,16 +3689,15 @@
} }
}, },
"node_modules/@table-library/react-table-library": { "node_modules/@table-library/react-table-library": {
"version": "3.1.2", "version": "3.1.4",
"resolved": "https://registry.npmjs.org/@table-library/react-table-library/-/react-table-library-3.1.2.tgz", "resolved": "https://registry.npmjs.org/@table-library/react-table-library/-/react-table-library-3.1.4.tgz",
"integrity": "sha512-zfjIvcEP114KFh5WyZzbPQHtaxiSr0LHHgm+A8El6YG/SQ7D+i88RUdwiBu3uuKXTY7OV+5v/GESEiioZo150w==", "integrity": "sha512-6JgQJLWgkMkdVzB/gGU/7BuMRGhQkkbg150YXiq+2U2ICyV773JPW5oxE5QaQJZUsDGlcS1FuaK/UFJVLZWs4A==",
"dependencies": { "dependencies": {
"clsx": "1.1.1", "clsx": "1.1.1",
"react-virtualized-auto-sizer": "1.0.6", "react-virtualized-auto-sizer": "1.0.6",
"react-window": "1.8.6" "react-window": "1.8.7"
}, },
"peerDependencies": { "peerDependencies": {
"@emotion/react": ">= 11",
"react": ">=16.8.0", "react": ">=16.8.0",
"react-dom": ">=16.8.0" "react-dom": ">=16.8.0"
} }
@@ -3715,22 +3714,6 @@
"react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0" "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0"
} }
}, },
"node_modules/@table-library/react-table-library/node_modules/react-window": {
"version": "1.8.6",
"resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.6.tgz",
"integrity": "sha512-8VwEEYyjz6DCnGBsd+MgkD0KJ2/OXFULyDtorIiTz+QzwoP94tBoA7CnbtyXMm+cCeAUER5KJcPtWl9cpKbOBg==",
"dependencies": {
"@babel/runtime": "^7.0.0",
"memoize-one": ">=3.1.1 <6"
},
"engines": {
"node": ">8.0.0"
},
"peerDependencies": {
"react": "^15.0.0 || ^16.0.0 || ^17.0.0",
"react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0"
}
},
"node_modules/@tootallnate/once": { "node_modules/@tootallnate/once": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
@@ -3930,9 +3913,9 @@
"integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw=="
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "17.0.35", "version": "17.0.36",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.36.tgz",
"integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==" "integrity": "sha512-V3orv+ggDsWVHP99K3JlwtH20R7J4IhI1Kksgc+64q5VxgfRkQG8Ws3MFm/FZOKDYGy9feGFlZ70/HpCNe9QaA=="
}, },
"node_modules/@types/parse-json": { "node_modules/@types/parse-json": {
"version": "4.0.0", "version": "4.0.0",
@@ -15026,6 +15009,22 @@
"react-dom": ">=16.6.0" "react-dom": ">=16.6.0"
} }
}, },
"node_modules/react-window": {
"version": "1.8.7",
"resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.7.tgz",
"integrity": "sha512-JHEZbPXBpKMmoNO1bNhoXOOLg/ujhL/BU4IqVU9r8eQPcy5KQnGHIHDRkJ0ns9IM5+Aq5LNwt3j8t3tIrePQzA==",
"dependencies": {
"@babel/runtime": "^7.0.0",
"memoize-one": ">=3.1.1 <6"
},
"engines": {
"node": ">8.0.0"
},
"peerDependencies": {
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/read-pkg": { "node_modules/read-pkg": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
@@ -20452,13 +20451,13 @@
} }
}, },
"@table-library/react-table-library": { "@table-library/react-table-library": {
"version": "3.1.2", "version": "3.1.4",
"resolved": "https://registry.npmjs.org/@table-library/react-table-library/-/react-table-library-3.1.2.tgz", "resolved": "https://registry.npmjs.org/@table-library/react-table-library/-/react-table-library-3.1.4.tgz",
"integrity": "sha512-zfjIvcEP114KFh5WyZzbPQHtaxiSr0LHHgm+A8El6YG/SQ7D+i88RUdwiBu3uuKXTY7OV+5v/GESEiioZo150w==", "integrity": "sha512-6JgQJLWgkMkdVzB/gGU/7BuMRGhQkkbg150YXiq+2U2ICyV773JPW5oxE5QaQJZUsDGlcS1FuaK/UFJVLZWs4A==",
"requires": { "requires": {
"clsx": "1.1.1", "clsx": "1.1.1",
"react-virtualized-auto-sizer": "1.0.6", "react-virtualized-auto-sizer": "1.0.6",
"react-window": "1.8.6" "react-window": "1.8.7"
}, },
"dependencies": { "dependencies": {
"react-virtualized-auto-sizer": { "react-virtualized-auto-sizer": {
@@ -20466,15 +20465,6 @@
"resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.6.tgz", "resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.6.tgz",
"integrity": "sha512-7tQ0BmZqfVF6YYEWcIGuoR3OdYe8I/ZFbNclFlGOC3pMqunkYF/oL30NCjSGl9sMEb17AnzixDz98Kqc3N76HQ==", "integrity": "sha512-7tQ0BmZqfVF6YYEWcIGuoR3OdYe8I/ZFbNclFlGOC3pMqunkYF/oL30NCjSGl9sMEb17AnzixDz98Kqc3N76HQ==",
"requires": {} "requires": {}
},
"react-window": {
"version": "1.8.6",
"resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.6.tgz",
"integrity": "sha512-8VwEEYyjz6DCnGBsd+MgkD0KJ2/OXFULyDtorIiTz+QzwoP94tBoA7CnbtyXMm+cCeAUER5KJcPtWl9cpKbOBg==",
"requires": {
"@babel/runtime": "^7.0.0",
"memoize-one": ">=3.1.1 <6"
}
} }
} }
}, },
@@ -20671,9 +20661,9 @@
"integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw=="
}, },
"@types/node": { "@types/node": {
"version": "17.0.35", "version": "17.0.36",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.36.tgz",
"integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==" "integrity": "sha512-V3orv+ggDsWVHP99K3JlwtH20R7J4IhI1Kksgc+64q5VxgfRkQG8Ws3MFm/FZOKDYGy9feGFlZ70/HpCNe9QaA=="
}, },
"@types/parse-json": { "@types/parse-json": {
"version": "4.0.0", "version": "4.0.0",
@@ -28628,6 +28618,15 @@
"prop-types": "^15.6.2" "prop-types": "^15.6.2"
} }
}, },
"react-window": {
"version": "1.8.7",
"resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.7.tgz",
"integrity": "sha512-JHEZbPXBpKMmoNO1bNhoXOOLg/ujhL/BU4IqVU9r8eQPcy5KQnGHIHDRkJ0ns9IM5+Aq5LNwt3j8t3tIrePQzA==",
"requires": {
"@babel/runtime": "^7.0.0",
"memoize-one": ">=3.1.1 <6"
}
},
"read-pkg": { "read-pkg": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",

View File

@@ -9,9 +9,9 @@
"@msgpack/msgpack": "^2.7.2", "@msgpack/msgpack": "^2.7.2",
"@mui/icons-material": "^5.8.0", "@mui/icons-material": "^5.8.0",
"@mui/material": "^5.8.1", "@mui/material": "^5.8.1",
"@table-library/react-table-library": "^3.1.2", "@table-library/react-table-library": "^3.1.4",
"@types/lodash": "^4.14.182", "@types/lodash": "^4.14.182",
"@types/node": "^17.0.35", "@types/node": "^17.0.36",
"@types/react": "^18.0.9", "@types/react": "^18.0.9",
"@types/react-dom": "^18.0.5", "@types/react-dom": "^18.0.5",
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",

View File

@@ -384,7 +384,10 @@ const DashboardData: FC = () => {
const handleDownloadCsv = () => { const handleDownloadCsv = () => {
const columns = [ const columns = [
{ accessor: (dv: any) => dv.id.slice(2), name: 'Entity' }, { accessor: (dv: any) => dv.id.slice(2), name: 'Entity' },
{ accessor: (dv: any) => (typeof dv.v === 'number') ? new Intl.NumberFormat().format(dv.v) : dv.v, name: 'Value' }, {
accessor: (dv: any) => (typeof dv.v === 'number' ? new Intl.NumberFormat().format(dv.v) : dv.v),
name: 'Value'
},
{ accessor: (dv: any) => DeviceValueUOM_s[dv.u], name: 'UoM' } { accessor: (dv: any) => DeviceValueUOM_s[dv.u], name: 'UoM' }
]; ];
downloadAsCsv( downloadAsCsv(
@@ -449,7 +452,7 @@ const DashboardData: FC = () => {
} }
}; };
const isCmdOnly = (dv: DeviceValue) => dv.v === undefined && dv.c; const isCmdOnly = (dv: DeviceValue) => dv.v === '' && dv.c;
function formatValue(value: any, uom: number) { function formatValue(value: any, uom: number) {
if (value === undefined) { if (value === undefined) {

View File

@@ -0,0 +1,39 @@
import { FC } from 'react';
import { SvgIconProps } from '@mui/material';
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
import StarIcon from '@mui/icons-material/Star';
import StarOutlineIcon from '@mui/icons-material/StarOutline';
import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
import InsertCommentOutlinedIcon from '@mui/icons-material/InsertCommentOutlined';
type OptionType = 'readonly' | 'web_exclude' | 'api_mqtt_exclude' | 'favorite';
const OPTION_ICONS: { [type in OptionType]: [React.ComponentType<SvgIconProps>, React.ComponentType<SvgIconProps>] } = {
readonly: [EditOffOutlinedIcon, EditOutlinedIcon],
web_exclude: [VisibilityOffOutlinedIcon, VisibilityOutlinedIcon],
api_mqtt_exclude: [CommentsDisabledOutlinedIcon, InsertCommentOutlinedIcon],
favorite: [StarIcon, StarOutlineIcon]
};
interface OptionIconProps {
type: OptionType;
isSet: boolean;
}
const OptionIcon: FC<OptionIconProps> = ({ type, isSet }) => {
const Icon = OPTION_ICONS[type][isSet ? 0 : 1];
return isSet ? (
<Icon color="primary" sx={{ fontSize: 14, verticalAlign: 'middle' }} />
) : (
<Icon sx={{ fontSize: 14, verticalAlign: 'middle' }} />
);
};
export default OptionIcon;

View File

@@ -25,10 +25,12 @@ import { useSnackbar } from 'notistack';
import SaveIcon from '@mui/icons-material/Save'; import SaveIcon from '@mui/icons-material/Save';
import CancelIcon from '@mui/icons-material/Cancel'; import CancelIcon from '@mui/icons-material/Cancel';
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
import StarIcon from '@mui/icons-material/Star'; // import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined'; // import StarIcon from '@mui/icons-material/Star';
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined'; // import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
// import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore'; import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined'; import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined';
import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined'; import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
@@ -36,6 +38,8 @@ import UnfoldMoreOutlinedIcon from '@mui/icons-material/UnfoldMoreOutlined';
import SearchIcon from '@mui/icons-material/Search'; import SearchIcon from '@mui/icons-material/Search';
import FilterListIcon from '@mui/icons-material/FilterList'; import FilterListIcon from '@mui/icons-material/FilterList';
import OptionIcon from './OptionIcon';
import { ButtonRow, FormLoader, ValidatedTextField, SectionContent } from '../components'; import { ButtonRow, FormLoader, ValidatedTextField, SectionContent } from '../components';
import * as EMSESP from './api'; import * as EMSESP from './api';
@@ -47,7 +51,7 @@ import { DeviceShort, Devices, DeviceEntity, DeviceEntityMask } from './types';
const SettingsCustomization: FC = () => { const SettingsCustomization: FC = () => {
const { enqueueSnackbar } = useSnackbar(); const { enqueueSnackbar } = useSnackbar();
const [deviceEntities, setDeviceEntities] = useState<DeviceEntity[]>([{ id: '', v: 0, s: '', m: 0, w: false }]); const [deviceEntities, setDeviceEntities] = useState<DeviceEntity[]>([{ id: '', v: 0, n: '', m: 0, w: false }]);
const [devices, setDevices] = useState<Devices>(); const [devices, setDevices] = useState<Devices>();
const [errorMessage, setErrorMessage] = useState<string>(); const [errorMessage, setErrorMessage] = useState<string>();
const [selectedDevice, setSelectedDevice] = useState<number>(0); const [selectedDevice, setSelectedDevice] = useState<number>(0);
@@ -199,6 +203,15 @@ const SettingsCustomization: FC = () => {
return value; return value;
} }
function formatName(de: DeviceEntity) {
if (de.n === undefined || de.n === de.id) {
return de.id;
} else if (de.n === '') {
return 'Command: ' + de.id;
}
return de.n + ' (' + de.id + ')';
}
const getMaskNumber = (newMask: string[]) => { const getMaskNumber = (newMask: string[]) => {
var new_mask = 0; var new_mask = 0;
for (let entry of newMask) { for (let entry of newMask) {
@@ -272,7 +285,7 @@ const SettingsCustomization: FC = () => {
if (deviceEntities && selectedDevice) { if (deviceEntities && selectedDevice) {
const masked_entities = deviceEntities const masked_entities = deviceEntities
.filter((de) => de.m !== de.om) .filter((de) => de.m !== de.om)
.map((new_de) => new_de.m.toString(16).padStart(2, '0') + new_de.s); .map((new_de) => new_de.m.toString(16).padStart(2, '0') + new_de.id);
if (masked_entities.length > 60) { if (masked_entities.length > 60) {
enqueueSnackbar('Selected entities exceeded limit of 60. Please Save in batches', { variant: 'warning' }); enqueueSnackbar('Selected entities exceeded limit of 60. Please Save in batches', { variant: 'warning' });
@@ -303,8 +316,18 @@ const SettingsCustomization: FC = () => {
return ( return (
<> <>
<Box color="warning.main"> <Box mb={2} color="warning.main">
<Typography variant="body2">Select a device and customize each of its entities using the options.</Typography> <Typography variant="body2">Select a device and customize each of its entities using the options:</Typography>
<Typography variant="body2">
<OptionIcon type="favorite" isSet={true} />
=mark as a favorite&nbsp;&nbsp;
<OptionIcon type="readonly" isSet={true} />
=disable write action&nbsp;&nbsp;
<OptionIcon type="api_mqtt_exclude" isSet={true} />
=exclude from MQTT and API outputs&nbsp;&nbsp;
<OptionIcon type="web_exclude" isSet={true} />
=hide from Web Dashboard
</Typography>
</Box> </Box>
<ValidatedTextField <ValidatedTextField
name="device" name="device"
@@ -363,9 +386,11 @@ const SettingsCustomization: FC = () => {
}} }}
/> />
</Grid> </Grid>
<Grid item> <Tooltip arrow placement="top" title="apply filter">
<FilterListIcon color="primary" sx={{ fontSize: 14, verticalAlign: 'middle' }} />: <Grid item>
</Grid> <FilterListIcon color="primary" sx={{ fontSize: 14, verticalAlign: 'middle' }} />:
</Grid>
</Tooltip>
<Grid item> <Grid item>
<ToggleButtonGroup <ToggleButtonGroup
size="small" size="small"
@@ -376,34 +401,22 @@ const SettingsCustomization: FC = () => {
}} }}
> >
<ToggleButton value="8"> <ToggleButton value="8">
<Tooltip arrow placement="top" title="filter favorites"> <OptionIcon type="favorite" isSet={true} />
<StarIcon sx={{ fontSize: 14 }} />
</Tooltip>
</ToggleButton> </ToggleButton>
<ToggleButton value="4"> <ToggleButton value="4">
<Tooltip arrow placement="top" title="filter entities with write action disabled"> <OptionIcon type="readonly" isSet={true} />
<EditOffOutlinedIcon sx={{ fontSize: 14 }} />
</Tooltip>
</ToggleButton> </ToggleButton>
<ToggleButton value="2"> <ToggleButton value="2">
<Tooltip arrow placement="top" title="filter entities excluded from MQTT and API outputs"> <OptionIcon type="api_mqtt_exclude" isSet={true} />
<CommentsDisabledOutlinedIcon sx={{ fontSize: 14 }} />
</Tooltip>
</ToggleButton> </ToggleButton>
<ToggleButton value="1"> <ToggleButton value="1">
<Tooltip arrow placement="top" title="filter entities hidden from Web Dashboard"> <OptionIcon type="web_exclude" isSet={true} />
<VisibilityOffOutlinedIcon sx={{ fontSize: 14 }} />
</Tooltip>
</ToggleButton> </ToggleButton>
</ToggleButtonGroup> </ToggleButtonGroup>
</Grid> </Grid>
<Grid item> <Grid item>
<CommentsDisabledOutlinedIcon color="primary" sx={{ fontSize: 14, verticalAlign: 'middle' }} /> <Tooltip arrow placement="top" title="set selected entities to be both visible and output">
<VisibilityOffOutlinedIcon color="primary" sx={{ fontSize: 14, verticalAlign: 'middle' }} />:
</Grid>
<Grid item>
<Tooltip arrow placement="top" title="mark shown entities to be all visible and output ">
<Button <Button
size="small" size="small"
sx={{ fontSize: 10 }} sx={{ fontSize: 10 }}
@@ -411,12 +424,14 @@ const SettingsCustomization: FC = () => {
color="inherit" color="inherit"
onClick={() => maskDisabled(false)} onClick={() => maskDisabled(false)}
> >
enable set all&nbsp;
<OptionIcon type="api_mqtt_exclude" isSet={false} />
<OptionIcon type="web_exclude" isSet={false} />
</Button> </Button>
</Tooltip> </Tooltip>
</Grid> </Grid>
<Grid item> <Grid item>
<Tooltip arrow placement="top" title="mark shown entities to be not visible or output "> <Tooltip arrow placement="top" title="set selected entities to be not visible and not output">
<Button <Button
size="small" size="small"
sx={{ fontSize: 10 }} sx={{ fontSize: 10 }}
@@ -424,7 +439,9 @@ const SettingsCustomization: FC = () => {
color="inherit" color="inherit"
onClick={() => maskDisabled(true)} onClick={() => maskDisabled(true)}
> >
disable set all&nbsp;
<OptionIcon type="api_mqtt_exclude" isSet={true} />
<OptionIcon type="web_exclude" isSet={true} />
</Button> </Button>
</Tooltip> </Tooltip>
</Grid> </Grid>
@@ -458,29 +475,44 @@ const SettingsCustomization: FC = () => {
value={getMaskString(de.m)} value={getMaskString(de.m)}
onChange={(event, mask) => { onChange={(event, mask) => {
de.m = getMaskNumber(mask); de.m = getMaskNumber(mask);
if (de.n === '' && de.m & DeviceEntityMask.DV_READONLY) {
de.m = de.m | DeviceEntityMask.DV_WEB_EXCLUDE;
}
if (de.m & DeviceEntityMask.DV_WEB_EXCLUDE) { if (de.m & DeviceEntityMask.DV_WEB_EXCLUDE) {
de.m = de.m & ~DeviceEntityMask.DV_FAVORITE; de.m = de.m & ~DeviceEntityMask.DV_FAVORITE;
} }
setMasks(['']); setMasks(['']);
}} }}
> >
<ToggleButton value="8" disabled={(de.m & 1) !== 0 || de.id === ''}> <ToggleButton value="8" disabled={(de.m & 1) !== 0 || de.n === undefined}>
<StarIcon sx={{ fontSize: 14 }} /> <OptionIcon
type="favorite"
isSet={(de.m & DeviceEntityMask.DV_FAVORITE) === DeviceEntityMask.DV_FAVORITE}
/>
</ToggleButton> </ToggleButton>
<ToggleButton value="4" disabled={!de.w || (de.m & 3) === 3}> <ToggleButton value="4" disabled={!de.w || (de.m & 3) === 3}>
<EditOffOutlinedIcon sx={{ fontSize: 14 }} /> <OptionIcon
type="readonly"
isSet={(de.m & DeviceEntityMask.DV_READONLY) === DeviceEntityMask.DV_READONLY}
/>
</ToggleButton> </ToggleButton>
<ToggleButton value="2"> <ToggleButton value="2" disabled={de.n === ''}>
<CommentsDisabledOutlinedIcon sx={{ fontSize: 14 }} /> <OptionIcon
type="api_mqtt_exclude"
isSet={
(de.m & DeviceEntityMask.DV_API_MQTT_EXCLUDE) === DeviceEntityMask.DV_API_MQTT_EXCLUDE
}
/>
</ToggleButton> </ToggleButton>
<ToggleButton value="1"> <ToggleButton value="1" disabled={de.n === undefined}>
<VisibilityOffOutlinedIcon sx={{ fontSize: 14 }} /> <OptionIcon
type="web_exclude"
isSet={(de.m & DeviceEntityMask.DV_WEB_EXCLUDE) === DeviceEntityMask.DV_WEB_EXCLUDE}
/>
</ToggleButton> </ToggleButton>
</ToggleButtonGroup> </ToggleButtonGroup>
</Cell> </Cell>
<Cell> <Cell>{formatName(de)}</Cell>
{de.id}&nbsp;({de.s})
</Cell>
<Cell>{formatValue(de.v)}</Cell> <Cell>{formatValue(de.v)}</Cell>
</Row> </Row>
))} ))}

View File

@@ -132,9 +132,9 @@ export interface DeviceData {
} }
export interface DeviceEntity { export interface DeviceEntity {
id: string; // name id: string; // shortname
v: any; // value, in any format v?: any; // value, in any format, optional
s: string; // shortname n?: string; // fullname, optional
m: number; // mask m: number; // mask
om?: number; // original mask before edits om?: number; // original mask before edits
w: boolean; // writeable w: boolean; // writeable

View File

@@ -14,7 +14,7 @@
"express": "^4.18.1", "express": "^4.18.1",
"express-sse": "^0.5.3", "express-sse": "^0.5.3",
"nodemon": "^2.0.16", "nodemon": "^2.0.16",
"ws": "^8.6.0" "ws": "^8.7.0"
} }
}, },
"node_modules/@msgpack/msgpack": { "node_modules/@msgpack/msgpack": {
@@ -1811,9 +1811,9 @@
} }
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "8.6.0", "version": "8.7.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz",
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==",
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
}, },
@@ -3169,9 +3169,9 @@
} }
}, },
"ws": { "ws": {
"version": "8.6.0", "version": "8.7.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz",
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==",
"requires": {} "requires": {}
}, },
"xdg-basedir": { "xdg-basedir": {

View File

@@ -16,6 +16,6 @@
"express": "^4.18.1", "express": "^4.18.1",
"express-sse": "^0.5.3", "express-sse": "^0.5.3",
"nodemon": "^2.0.16", "nodemon": "^2.0.16",
"ws": "^8.6.0" "ws": "^8.7.0"
} }
} }

View File

@@ -337,6 +337,7 @@ settings = {
pbutton_gpio: 0, pbutton_gpio: 0,
board_profile: 'S32', board_profile: 'S32',
bool_format: 1, bool_format: 1,
bool_dashboard: 1,
enum_format: 1, enum_format: 1,
} }
@@ -473,7 +474,7 @@ const emsesp_devicedata_1 = {
const emsesp_devicedata_2 = { const emsesp_devicedata_2 = {
label: 'Boiler: Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i', label: 'Boiler: Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i',
data: [ data: [
{ v: 0, u: 0, id: '08reset', c: 'reset', l: ['-', 'maintenance', 'error'] }, { v: '', u: 0, id: '08reset', c: 'reset', l: ['-', 'maintenance', 'error'] },
{ v: 'false', u: 0, id: '08heating active' }, { v: 'false', u: 0, id: '08heating active' },
{ v: 'false', u: 0, id: '04tapwater active' }, { v: 'false', u: 0, id: '04tapwater active' },
{ v: 5, u: 1, id: '04selected flow temperature', c: 'selflowtemp' }, { v: 5, u: 1, id: '04selected flow temperature', c: 'selflowtemp' },
@@ -575,145 +576,161 @@ const emsesp_devicedata_4 = {
], ],
} }
// CUSTOMIZATION
const emsesp_deviceentities_1 = [ const emsesp_deviceentities_1 = [
{ {
v: '(0)', v: '(0)',
id: 'error code', n: 'error code',
s: 'errorcode', id: 'errorcode',
m: 0, m: 0,
w: false, w: false,
}, },
{ {
v: '14:54:39 06/06/2021', v: '14:54:39 06/06/2021',
id: 'date/time', n: 'date/time',
s: 'datetime', id: 'datetime',
m: 0,
w: false,
},
{
v: 'test data',
n: 'test',
id: 'test',
m: 0,
w: false,
},
{
v: 'roomTemp',
id: 'hc1/HA climate config creation',
m: 0, m: 0,
w: false, w: false,
}, },
{ {
v: 18.2, v: 18.2,
id: 'hc1 selected room temperature', n: 'hc1 selected room temperature',
s: 'hc1/seltemp', id: 'hc1/seltemp',
m: 0, m: 0,
w: true, w: true,
}, },
{ {
v: 22.6, v: 22.6,
id: 'hc1 current room temperature', n: 'hc1 current room temperature',
s: 'hc1/curtemp', id: 'hc1/curtemp',
m: 0, m: 0,
w: false, w: false,
}, },
{ {
v: 'auto', v: 'auto',
id: 'hc1 mode', n: 'hc1 mode',
s: 'hc1/mode', id: 'hc1/mode',
m: 0, m: 0,
w: true, w: true,
}, },
] ]
const emsesp_deviceentities_2 = [ const emsesp_deviceentities_2 = [
{ v: false, id: 'heating active', s: 'heatingactive', m: 0, w: false }, { u: 0, n: '', id: 'reset', m: 8, w: false },
{ v: false, id: 'tapwater active', s: 'tapwateractive', m: 0, w: false }, { v: false, n: 'heating active', id: 'heatingactive', m: 8, w: false },
{ v: 5, id: 'selected flow temperature', s: 'selflowtemp', m: 0, w: true }, { v: false, n: 'tapwater active', id: 'tapwateractive', m: 4, w: false },
{ v: 0, id: 'burner selected max power', s: 'selburnpow', m: 0, w: true }, { v: 5, n: 'selected flow temperature', id: 'selflowtemp', m: 4, w: true },
{ v: 0, id: 'heating pump modulation', s: 'heatingpumpmod', m: 0, w: false }, { v: 0, n: 'burner selected max power', id: 'selburnpow', m: 14, w: true },
{ id: 'heating pump 2 modulation', s: 'heatingpump2mod', m: 0, w: false }, { v: 0, n: 'heating pump modulation', id: 'heatingpumpmod', m: 0, w: false },
{ id: 'outside temperature', s: 'outdoortemp', m: 0, w: false }, { n: 'heating pump 2 modulation', id: 'heatingpump2mod', m: 0, w: false },
{ v: 53, id: 'current flow temperature', s: 'curflowtemp', m: 0, w: false }, { n: 'outside temperature', id: 'outdoortemp', m: 0, w: false },
{ v: 51.8, id: 'return temperature', s: 'rettemp', m: 0, w: false }, { v: 53, n: 'current flow temperature', id: 'curflowtemp', m: 0, w: false },
{ id: 'mixing switch temperature', s: 'switchtemp', m: 0, w: false }, { v: 51.8, n: 'return temperature', id: 'rettemp', m: 0, w: false },
{ v: 1.3, id: 'system pressure', s: 'syspress', m: 0, w: false }, { n: 'mixing switch temperature', id: 'switchtemp', m: 0, w: false },
{ v: 54.6, id: 'actual boiler temperature', s: 'boiltemp', m: 0, w: false }, { v: 1.3, n: 'system pressure', id: 'syspress', m: 0, w: false },
{ id: 'exhaust temperature', s: 'exhausttemp', m: 0, w: false }, { v: 54.6, n: 'actual boiler temperature', id: 'boiltemp', m: 0, w: false },
{ v: false, id: 'gas', s: 'burngas', m: 0, w: false }, { n: 'exhaust temperature', id: 'exhausttemp', m: 0, w: false },
{ v: false, id: 'gas stage 2', s: 'burngas2', m: 0, w: false }, { v: false, n: 'gas', id: 'burngas', m: 0, w: false },
{ v: 0, id: 'flame current', s: 'flamecurr', m: 0, w: false }, { v: false, n: 'gas stage 2', id: 'burngas2', m: 0, w: false },
{ v: false, id: 'heating pump', s: 'heatingpump', m: 0, w: false }, { v: 0, n: 'flame current', id: 'flamecurr', m: 0, w: false },
{ v: false, id: 'fan', s: 'fanwork', m: 0, w: false }, { v: false, n: 'heating pump', id: 'heatingpump', m: 0, w: false },
{ v: false, id: 'ignition', s: 'ignwork', m: 0, w: false }, { v: false, n: 'fan', id: 'fanwork', m: 0, w: false },
{ v: false, id: 'oil preheating', s: 'oilpreheat', m: 0, w: false }, { v: false, n: 'ignition', id: 'ignwork', m: 0, w: false },
{ v: true, id: 'heating activated', s: 'heatingactivated', m: 0, w: false }, { v: false, n: 'oil preheating', id: 'oilpreheat', m: 0, w: false },
{ v: 80, id: 'heating temperature', s: 'heatingtemp', m: 0, w: false }, { v: true, n: 'heating activated', id: 'heatingactivated', m: 0, w: false },
{ v: 70, id: 'burner pump max power', s: 'pumpmodmax', m: 0, w: false }, { v: 80, n: 'heating temperature', id: 'heatingtemp', m: 0, w: false },
{ v: 30, id: 'burner pump min power', s: 'pumpmodmin', m: 0, w: false }, { v: 70, n: 'burner pump max power', id: 'pumpmodmax', m: 0, w: false },
{ v: 1, id: 'pump delay', s: 'pumpdelay', m: 0, w: false }, { v: 30, n: 'burner pump min power', id: 'pumpmodmin', m: 0, w: false },
{ v: 10, id: 'burner min period', s: 'burnminperiod', m: 0, w: false }, { v: 1, n: 'pump delay', id: 'pumpdelay', m: 0, w: false },
{ v: 0, id: 'burner min power', s: 'burnminpower', m: 0, w: false }, { v: 10, n: 'burner min period', id: 'burnminperiod', m: 0, w: false },
{ v: 50, id: 'burner max power', s: 'burnmaxpower', m: 0, w: false }, { v: 0, n: 'burner min power', id: 'burnminpower', m: 0, w: false },
{ v: -6, id: 'hysteresis on temperature', s: 'boilhyston', m: 0, w: false }, { v: 50, n: 'burner max power', id: 'burnmaxpower', m: 0, w: false },
{ v: 6, id: 'hysteresis off temperature', s: 'boilhystoff', m: 0, w: false }, { v: -6, n: 'hysteresis on temperature', id: 'boilhyston', m: 0, w: false },
{ v: 0, id: 'set flow temperature', s: 'setflowtemp', m: 0, w: true }, { v: 6, n: 'hysteresis off temperature', id: 'boilhystoff', m: 0, w: false },
{ v: 0, id: 'burner set power', s: 'setburnpow', m: 0, w: false }, { v: 0, n: 'set flow temperature', id: 'setflowtemp', m: 0, w: true },
{ v: 0, id: 'burner current power', s: 'curburnpow', m: 0, w: false }, { v: 0, n: 'burner set power', id: 'setburnpow', m: 0, w: false },
{ v: 326323, id: 'burner starts', s: 'burnstarts', m: 0, w: false }, { v: 0, n: 'burner current power', id: 'curburnpow', m: 0, w: false },
{ v: 553437, id: 'total burner operating time', s: 'burnworkmin', m: 0, w: false }, { v: 326323, n: 'burner starts', id: 'burnstarts', m: 0, w: false },
{ v: 451286, id: 'total heat operating time', s: 'heatworkmin', m: 0, w: false }, { v: 553437, n: 'total burner operating time', id: 'burnworkmin', m: 0, w: false },
{ v: 4672175, id: 'total UBA operating time', s: 'ubauptime', m: 0, w: false }, { v: 451286, n: 'total heat operating time', id: 'heatworkmin', m: 0, w: false },
{ v: '1C(210) 06.06.2020 12:07 (0 min)', id: 'last error code', s: 'lastcode', m: 0, w: false }, { v: 4672175, n: 'total UBA operating time', id: 'ubauptime', m: 0, w: false },
{ v: '0H', id: 'service code', s: 'servicecode', m: 0, w: false }, { v: '1C(210) 06.06.2020 12:07 (0 min)', n: 'last error code', id: 'lastcode', m: 0, w: false },
{ v: 203, id: 'service code number', s: 'servicecodenumber', m: 0, w: false }, { v: '0H', n: 'service code', id: 'servicecode', m: 0, w: false },
{ v: 'H00', id: 'maintenance message', s: 'maintenancemessage', m: 0, w: false }, { v: 203, n: 'service code number', id: 'servicecodenumber', m: 0, w: false },
{ v: 'manual', id: 'maintenance scheduled', s: 'maintenance', m: 0, w: false }, { v: 'H00', n: 'maintenance message', id: 'maintenancemessage', m: 0, w: false },
{ v: 6000, id: 'time to next maintenance', s: 'maintenancetime', m: 0, w: false }, { v: 'manual', n: 'maintenance scheduled', id: 'maintenance', m: 0, w: false },
{ v: '01.01.2012', id: 'next maintenance date', s: 'maintenancedate', m: 0, w: false }, { v: 6000, n: 'time to next maintenance', id: 'maintenancetime', m: 0, w: false },
{ v: true, id: 'dhw turn on/off', s: 'wwtapactivated', m: 0, w: false }, { v: '01.01.2012', n: 'next maintenance date', id: 'maintenancedate', m: 0, w: false },
{ v: 62, id: 'dhw set temperature', s: 'wwsettemp', m: 0, w: false }, { v: true, n: 'dhw turn on/off', id: 'wwtapactivated', m: 0, w: false },
{ v: 60, id: 'dhw selected temperature', s: 'wwseltemp', m: 0, w: true }, { v: 62, n: 'dhw set temperature', id: 'wwsettemp', m: 0, w: false },
{ id: 'dhw selected lower temperature', s: 'wwseltemplow', m: 2 }, { v: 60, n: 'dhw selected temperature', id: 'wwseltemp', m: 0, w: true },
{ id: 'dhw selected temperature for off', s: 'wwseltempoff', m: 2 }, { n: 'dhw selected lower temperature', id: 'wwseltemplow', m: 2 },
{ id: 'dhw single charge temperature', s: 'wwseltempsingle', m: 2 }, { n: 'dhw selected temperature for off', id: 'wwseltempoff', m: 2 },
{ v: 'flow', id: 'dhw type', s: 'wwtype', m: 0, w: false }, { n: 'dhw single charge temperature', id: 'wwseltempsingle', m: 2 },
{ v: 'hot', id: 'dhw comfort', s: 'wwcomfort', m: 0, w: false }, { v: 'flow', n: 'dhw type', id: 'wwtype', m: 0, w: false },
{ v: 40, id: 'dhw flow temperature offset', s: 'wwflowtempoffset', m: 0, w: false }, { v: 'hot', n: 'dhw comfort', id: 'wwcomfort', m: 0, w: false },
{ v: 100, id: 'dhw max power', s: 'wwmaxpower', m: 0, w: false }, { v: 40, n: 'dhw flow temperature offset', id: 'wwflowtempoffset', m: 0, w: false },
{ v: false, id: 'dhw circulation pump available', s: 'wwcircpump', m: 0, w: false }, { v: 100, n: 'dhw max power', id: 'wwmaxpower', m: 0, w: false },
{ v: '3-way valve', id: 'dhw charging type', s: 'wwchargetype', m: 0, w: false }, { v: false, n: 'dhw circulation pump available', id: 'wwcircpump', m: 0, w: false },
{ v: -5, id: 'dhw hysteresis on temperature', s: 'wwhyston', m: 0, w: false }, { v: '3-way valve', n: 'dhw charging type', id: 'wwchargetype', m: 0, w: false },
{ v: 0, id: 'dhw hysteresis off temperature', s: 'wwhystoff', m: 0, w: false }, { v: -5, n: 'dhw hysteresis on temperature', id: 'wwhyston', m: 0, w: false },
{ v: 70, id: 'dhw disinfection temperature', s: 'wwdisinfectiontemp', m: 0, w: false }, { v: 0, n: 'dhw hysteresis off temperature', id: 'wwhystoff', m: 0, w: false },
{ v: 'off', id: 'dhw circulation pump mode', s: 'wwcircmode', m: 0, w: false }, { v: 70, n: 'dhw disinfection temperature', id: 'wwdisinfectiontemp', m: 0, w: false },
{ v: false, id: 'dhw circulation active', s: 'wwcirc', m: 0, w: false }, { v: 'off', n: 'dhw circulation pump mode', id: 'wwcircmode', m: 0, w: false },
{ v: 46.4, id: 'dhw current intern temperature', s: 'wwcurtemp', m: 0, w: false }, { v: false, n: 'dhw circulation active', id: 'wwcirc', m: 0, w: false },
{ id: 'dhw current extern temperature', s: 'wwcurtemp2', m: 2 }, { v: 46.4, n: 'dhw current intern temperature', id: 'wwcurtemp', m: 0, w: false },
{ v: 0, id: 'dhw current tap water flow', s: 'wwcurflow', m: 0, w: false }, { n: 'dhw current extern temperature', id: 'wwcurtemp2', m: 2 },
{ v: 46.3, id: 'dhw storage intern temperature', s: 'wwstoragetemp1', m: 0, w: false }, { v: 0, n: 'dhw current tap water flow', id: 'wwcurflow', m: 0, w: false },
{ id: 'dhw storage extern temperature', s: 'wwstoragetemp2', m: 2 }, { v: 46.3, n: 'dhw storage intern temperature', id: 'wwstoragetemp1', m: 0, w: false },
{ v: true, id: 'dhw activated', s: 'wwactivated', m: 0, w: false }, { n: 'dhw storage extern temperature', id: 'wwstoragetemp2', m: 2 },
{ v: false, id: 'dhw one time charging', s: 'wwonetime', m: 0, w: false }, { v: true, n: 'dhw activated', id: 'wwactivated', m: 0, w: false },
{ v: false, id: 'dhw disinfecting', s: 'wwdisinfecting', m: 0, w: false }, { v: false, n: 'dhw one time charging', id: 'wwonetime', m: 0, w: false },
{ v: false, id: 'dhw charging', s: 'wwcharging', m: 0, w: false }, { v: false, n: 'dhw disinfecting', id: 'wwdisinfecting', m: 0, w: false },
{ v: false, id: 'dhw recharging', s: 'wwrecharging', m: 0, w: false }, { v: false, n: 'dhw charging', id: 'wwcharging', m: 0, w: false },
{ v: true, id: 'dhw temperature ok', s: 'wwtempok', m: 0, w: false }, { v: false, n: 'dhw recharging', id: 'wwrecharging', m: 0, w: false },
{ v: false, id: 'dhw active', s: 'wwactive', m: 0, w: false }, { v: true, n: 'dhw temperature ok', id: 'wwtempok', m: 0, w: false },
{ v: true, id: 'dhw 3way valve active', s: 'ww3wayvalve', m: 0, w: false }, { v: false, n: 'dhw active', id: 'wwactive', m: 0, w: false },
{ v: 0, id: 'dhw set pump power', s: 'wwsetpumppower', m: 0, w: true }, { v: true, n: 'dhw 3way valve active', id: 'ww3wayvalve', m: 0, w: false },
{ id: 'dhw mixer temperature', s: 'wwmixertemp', m: 2 }, { v: 0, n: 'dhw set pump power', id: 'wwsetpumppower', m: 0, w: true },
{ id: 'dhw cylinder middle temperature (TS3)', s: 'wwcylmiddletemp', m: 2 }, { n: 'dhw mixer temperature', id: 'wwmixertemp', m: 2 },
{ v: 288768, id: 'dhw starts', s: 'wwstarts', m: 0, w: false }, { n: 'dhw cylinder middle temperature (TS3)', id: 'wwcylmiddletemp', m: 2 },
{ v: 102151, id: 'dhw active time', s: 'wwworkm', m: 0, w: false }, { v: 288768, n: 'dhw starts', id: 'wwstarts', m: 0, w: false },
{ v: 102151, n: 'dhw active time', id: 'wwworkm', m: 0, w: false },
] ]
const emsesp_deviceentities_4 = [ const emsesp_deviceentities_4 = [
{ {
v: 16, v: 16,
id: 'hc2 selected room temperature', n: 'hc2 selected room temperature',
s: 'hc2/seltemp', id: 'hc2/seltemp',
m: 8, m: 8,
w: true, w: true,
}, },
{ {
v: 18.5, v: 18.5,
id: 'hc2 current room temperature', n: 'hc2 current room temperature',
s: 'hc2/curtemp', id: 'hc2/curtemp',
m: 2, m: 2,
w: false, w: false,
}, },
{ {
v: 'off', v: 'off',
id: 'hc2 mode', n: 'hc2 mode',
s: 'hc2/mode', id: 'hc2/mode',
m: 2, m: 2,
w: true, w: true,
}, },
@@ -912,13 +929,13 @@ rest_server.post(EMSESP_DEVICEENTITIES_ENDPOINT, (req, res) => {
}) })
function updateMask(entity, de, dd) { function updateMask(entity, de, dd) {
const name = entity.slice(2) const shortname = entity.slice(2)
const new_mask = parseInt(entity.slice(0, 2), 16) const new_mask = parseInt(entity.slice(0, 2), 16)
objIndex = de.findIndex((obj) => obj.s == name) objIndex = de.findIndex((obj) => obj.id == shortname)
if (objIndex !== -1) { if (objIndex !== -1) {
de[objIndex].m = new_mask de[objIndex].m = new_mask
const fullname = de[objIndex].id const fullname = de[objIndex].n
objIndex = dd.data.findIndex((obj) => obj.id.slice(2) == fullname) objIndex = dd.data.findIndex((obj) => obj.id.slice(2) == fullname)
if (objIndex !== -1) { if (objIndex !== -1) {
// see if the mask has changed // see if the mask has changed
@@ -930,7 +947,7 @@ function updateMask(entity, de, dd) {
} }
} }
} else { } else {
console.log("can't locate record for id " + id) console.log("can't locate record for name " + shortname)
} }
} }

View File

@@ -32,5 +32,5 @@ build_type = debug
monitor_filters = esp32_exception_decoder monitor_filters = esp32_exception_decoder
debug_tool = esp-prog debug_tool = esp-prog
debug_init_break = tbreak setup debug_init_break = tbreak setup
build_flags = ${factory_settings.build_flags} ${common.debug_flags} -DONEWIRE_CRC16=0 -DNO_GLOBAL_ARDUINOOTA -DARDUINOJSON_ENABLE_STD_STRING=1 -DESP32=1 -DARDUINO_ARCH_ESP32=1 build_flags = ${factory_settings.build_flags} -DONEWIRE_CRC16=0 -DNO_GLOBAL_ARDUINOOTA -DARDUINOJSON_ENABLE_STD_STRING=1 -DESP32=1 -DARDUINO_ARCH_ESP32=1
extra_scripts = pre:scripts/build_interface.py extra_scripts = pre:scripts/build_interface.py

View File

@@ -68,7 +68,7 @@
{224, DeviceType::CONTROLLER, F("9000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {224, DeviceType::CONTROLLER, F("9000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{229, DeviceType::CONTROLLER, F("8700i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {229, DeviceType::CONTROLLER, F("8700i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{230, DeviceType::CONTROLLER, F("BC Base"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {230, DeviceType::CONTROLLER, F("BC Base"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{240, DeviceType::CONTROLLER, F("Rego 3000"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {240, DeviceType::CONTROLLER, F("Rego 3000"), DeviceFlags::EMS_DEVICE_FLAG_IVT}, // 0x09
{241, DeviceType::CONTROLLER, F("Condens 5000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {241, DeviceType::CONTROLLER, F("Condens 5000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
// Thermostat - not currently supporting write operations, like the Easy/100 types - 0x18 // Thermostat - not currently supporting write operations, like the Easy/100 types - 0x18

View File

@@ -25,8 +25,10 @@ REGISTER_FACTORY(Controller, EMSdevice::DeviceType::CONTROLLER);
Controller::Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand) Controller::Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) { : EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
// IVT broadcasts Thermostat time from controller (0x09) if display is off. // IVT broadcasts Thermostat time from controller (0x09) if display is off.
register_telegram_type(0x06, F("RCTime"), false, MAKE_PF_CB(process_dateTime)); if ((flags & 0x0F) == EMS_DEVICE_FLAG_IVT) {
register_device_value(DeviceValueTAG::TAG_NONE, &dateTime_, DeviceValueType::STRING, nullptr, FL_(dateTime), DeviceValueUOM::NONE); register_telegram_type(0x06, F("RCTime"), false, MAKE_PF_CB(process_dateTime));
register_device_value(DeviceValueTAG::TAG_NONE, &dateTime_, DeviceValueType::STRING, nullptr, FL_(dateTime), DeviceValueUOM::NONE);
}
} }
// process_dateTime - type 0x06 - date and time from a thermostat - 14 bytes long, IVT only // process_dateTime - type 0x06 - date and time from a thermostat - 14 bytes long, IVT only
@@ -35,7 +37,7 @@ void Controller::process_dateTime(std::shared_ptr<const Telegram> telegram) {
return; return;
} }
char newdatetime[sizeof(dateTime_)]; char newdatetime[sizeof(dateTime_)];
// publich as dd.mm.yyyy hh:mmF // publish as dd.mm.yyyy hh:mmF
snprintf(newdatetime, snprintf(newdatetime,
sizeof(dateTime_), sizeof(dateTime_),
"%02d.%02d.%04d %02d:%02d", "%02d.%02d.%04d %02d:%02d",
@@ -47,5 +49,4 @@ void Controller::process_dateTime(std::shared_ptr<const Telegram> telegram) {
has_update(dateTime_, newdatetime, sizeof(dateTime_)); has_update(dateTime_, newdatetime, sizeof(dateTime_));
} }
} // namespace emsesp } // namespace emsesp

View File

@@ -716,11 +716,9 @@ void EMSdevice::generate_values_web(JsonObject & output) {
auto mask = Helpers::hextoa((uint8_t)(dv.state >> 4), false); // create mask to a 2-char string auto mask = Helpers::hextoa((uint8_t)(dv.state >> 4), false); // create mask to a 2-char string
// add name, prefixing the tag if it exists. This is the id used for the table sorting // add name, prefixing the tag if it exists. This is the id used in the WebUI table and must be unique
if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) { if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) {
obj["id"] = mask + read_flash_string(dv.full_name); obj["id"] = mask + read_flash_string(dv.full_name);
} else if (dv.tag < DeviceValueTAG::TAG_HC1) {
obj["id"] = mask + tag_to_string(dv.tag) + " " + read_flash_string(dv.full_name);
} else { } else {
obj["id"] = mask + tag_to_string(dv.tag) + " " + read_flash_string(dv.full_name); obj["id"] = mask + tag_to_string(dv.tag) + " " + read_flash_string(dv.full_name);
} }
@@ -775,7 +773,7 @@ void EMSdevice::generate_values_web(JsonObject & output) {
// as generate_values_web() but stripped down to only show all entities and their state // as generate_values_web() but stripped down to only show all entities and their state
// this is used only for WebCustomizationService::device_entities() // this is used only for WebCustomizationService::device_entities()
void EMSdevice::generate_values_web_all(JsonArray & output) { void EMSdevice::generate_values_web_customization(JsonArray & output) {
for (const auto & dv : devicevalues_) { for (const auto & dv : devicevalues_) {
// also show commands and entities that have an empty full name // also show commands and entities that have an empty full name
JsonObject obj = output.createNestedObject(); JsonObject obj = output.createNestedObject();
@@ -831,29 +829,29 @@ void EMSdevice::generate_values_web_all(JsonArray & output) {
obj["v"] = (divider > 0) ? time_value / divider : time_value * factor; // sometimes we need to divide by 60 obj["v"] = (divider > 0) ? time_value / divider : time_value * factor; // sometimes we need to divide by 60
} }
} }
} else {
// must always have v for sorting to work in web
obj["v"] = "";
} }
// add name, prefixing the tag if it exists as the id (key for table sorting) // id holds the shortname and must always have a value for the WebUI table to work
if (dv.full_name) { if (dv.tag >= DeviceValueTAG::TAG_HC1) {
if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) { obj["id"] = tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name);
obj["id"] = dv.full_name; } else {
} else { obj["id"] = read_flash_string(dv.short_name);
char name[50]; }
snprintf(name, sizeof(name), "%s %s", tag_to_string(dv.tag).c_str(), read_flash_string(dv.full_name).c_str());
obj["id"] = name; // n is the fullname, and can be optional
// don't add the fullname if its a command
if (dv.type != DeviceValueType::CMD) {
if (dv.full_name) {
if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) {
obj["n"] = dv.full_name;
} else {
char name[50];
snprintf(name, sizeof(name), "%s %s", tag_to_string(dv.tag).c_str(), read_flash_string(dv.full_name).c_str());
obj["n"] = name;
}
} }
} else { } else {
obj["id"] = ""; obj["n"] = "";
}
// shortname
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
obj["s"] = tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name);
} else {
obj["s"] = dv.short_name;
} }
obj["m"] = dv.state >> 4; // send back the mask state. We're only interested in the high nibble obj["m"] = dv.state >> 4; // send back the mask state. We're only interested in the high nibble

View File

@@ -200,7 +200,7 @@ class EMSdevice {
enum OUTPUT_TARGET : uint8_t { API_VERBOSE, API_SHORTNAMES, MQTT, CONSOLE }; enum OUTPUT_TARGET : uint8_t { API_VERBOSE, API_SHORTNAMES, MQTT, CONSOLE };
bool generate_values(JsonObject & output, const uint8_t tag_filter, const bool nested, const uint8_t output_target); bool generate_values(JsonObject & output, const uint8_t tag_filter, const bool nested, const uint8_t output_target);
void generate_values_web(JsonObject & output); void generate_values_web(JsonObject & output);
void generate_values_web_all(JsonArray & output); void generate_values_web_customization(JsonArray & output);
void register_device_value(uint8_t tag, void register_device_value(uint8_t tag,
void * value_p, void * value_p,
@@ -315,6 +315,9 @@ class EMSdevice {
// device flags: The lower 4 bits hold the unique identifier, the upper 4 bits are used for specific flags // device flags: The lower 4 bits hold the unique identifier, the upper 4 bits are used for specific flags
static constexpr uint8_t EMS_DEVICE_FLAG_NONE = 0; static constexpr uint8_t EMS_DEVICE_FLAG_NONE = 0;
// Controller
static constexpr uint8_t EMS_DEVICE_FLAG_IVT = 1;
// Boiler // Boiler
static constexpr uint8_t EMS_DEVICE_FLAG_EMS = 1; static constexpr uint8_t EMS_DEVICE_FLAG_EMS = 1;
static constexpr uint8_t EMS_DEVICE_FLAG_EMSPLUS = 2; static constexpr uint8_t EMS_DEVICE_FLAG_EMSPLUS = 2;

View File

@@ -620,7 +620,7 @@ MAKE_PSTR_LIST(wwDailyHeating, F("wwdailyheating"), F("daily heating"))
MAKE_PSTR_LIST(wwDailyHeatTime, F("wwdailyheattime"), F("daily heating time")) MAKE_PSTR_LIST(wwDailyHeatTime, F("wwdailyheattime"), F("daily heating time"))
MAKE_PSTR_LIST(wwWhenModeOff, F("wwwhenmodeoff"), F("when thermostat mode off")) MAKE_PSTR_LIST(wwWhenModeOff, F("wwwhenmodeoff"), F("when thermostat mode off"))
// thermostat hc // thermostat hc
MAKE_PSTR_LIST(climate, F("climate")) MAKE_PSTR_LIST(climate, F("HA climate config creation")) // no full-name, hidden, only for creation
MAKE_PSTR_LIST(selRoomTemp, F("seltemp"), F("selected room temperature")) MAKE_PSTR_LIST(selRoomTemp, F("seltemp"), F("selected room temperature"))
MAKE_PSTR_LIST(roomTemp, F("currtemp"), F("current room temperature")) MAKE_PSTR_LIST(roomTemp, F("currtemp"), F("current room temperature"))
MAKE_PSTR_LIST(mode, F("mode"), F("mode")) MAKE_PSTR_LIST(mode, F("mode"), F("mode"))

View File

@@ -418,7 +418,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
// emsdevice->generate_values_web(root); // emsdevice->generate_values_web(root);
JsonArray output = doc.to<JsonArray>(); JsonArray output = doc.to<JsonArray>();
emsdevice->generate_values_web_all(output); emsdevice->generate_values_web_customization(output);
Serial.print(COLOR_BRIGHT_MAGENTA); Serial.print(COLOR_BRIGHT_MAGENTA);
serializeJson(doc, Serial); serializeJson(doc, Serial);

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.4.1b0" #define EMSESP_APP_VERSION "3.4.2b1"

View File

@@ -132,6 +132,7 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) {
JsonVariant data = output["api_data"]; JsonVariant data = output["api_data"];
request->send(200, "text/plain; charset=utf-8", data.as<String>()); request->send(200, "text/plain; charset=utf-8", data.as<String>());
api_count_++; api_count_++;
delete response;
return; return;
} }

View File

@@ -196,7 +196,7 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request, J
if (emsdevice->unique_id() == json["id"]) { if (emsdevice->unique_id() == json["id"]) {
#ifndef EMSESP_STANDALONE #ifndef EMSESP_STANDALONE
JsonArray output = response->getRoot(); JsonArray output = response->getRoot();
emsdevice->generate_values_web_all(output); emsdevice->generate_values_web_customization(output);
#endif #endif
response->setLength(); response->setLength();
request->send(response); request->send(response);