This commit is contained in:
Proddy
2023-02-04 14:25:29 +01:00
parent 6dc63907f1
commit 6c46770330
25 changed files with 506 additions and 410 deletions

View File

@@ -5,7 +5,6 @@
## **IMPORTANT! BREAKING CHANGES**
- When upgrading to v3.5 for the first time from v3.4 on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases) to correctly re-partition the flash. Make sure you backup the settings and customizations from the WebUI (System->Upload/Download) and restore after the upgrade.
- Support for multiple EMS-ESPs [#759] has been added as an optional setting for MQTT. When enabled, which is now the default, all MQTT Discovery Entity IDs will include the MQTT base name and the shortname of the EMS-ESP device entity. For example what was previously `sensor.boiler_actual_boiler_temperature` will now become `sensor.ems_esp_boiler_boiltemp`. If you still want to use the old format and retain the history and script compatibility in Home Assistant then set this back to the old format.
## Added
@@ -32,7 +31,8 @@
- Add Rego 3000, TR120RF thermostats [#917](https://github.com/emsesp/EMS-ESP32/issues/917)
- Add config for ESP32-S3
- Add heatpump silent mode and other entities [#896](https://github.com/emsesp/EMS-ESP32/issues/896)
- Allow reboot to other partition (factory or asymmetric OTA)
- Allow reboot to other partition (factory or asymetric OTA)
- Blacklist entities to remove from memory [#891](https://github.com/emsesp/EMS-ESP32/issues/891)
## Fixed
@@ -41,20 +41,21 @@
- Commands for multiple thermostats [#826](https://github.com/emsesp/EMS-ESP32/issues/826)
- API queries for multiple devices [#865](https://github.com/emsesp/EMS-ESP32/issues/865)
- Console crash when using call with command `hcx` only. [#841](https://github.com/emsesp/EMS-ESP32/issues/841)
- heatingPump2Mod was wrong, changed to absBurnPow [[#908](https://github.com/emsesp/EMS-ESP32/issues/908)
- rounding of web input values
- analog sensor with single gpio number [#915](https://github.com/emsesp/EMS-ESP32/issues/915)
- `heatingPump2Mod` was wrong, changed to absBurnPow [[#908](https://github.com/emsesp/EMS-ESP32/issues/908)
- Rounding of web input values
- Analog sensor with single gpio number [#915](https://github.com/emsesp/EMS-ESP32/issues/915)
- HA dallas and analog configs: remove/rebuild on change [#888](https://github.com/emsesp/EMS-ESP32/issues/888)
- Modes and set seltemp for RC30 and RC20 [#932](https://github.com/emsesp/EMS-ESP32/issues/932)
## Changed
- Discovery in HomeAssistant don't work with custom base topic. [#596](https://github.com/emsesp/EMS-ESP32/issues/596) Base topic containing `/` are changed to `_`
- RF room temperature sensor are shown as thermostat
- render mqtt float json values with trailing zero
- removed flash strings, to increase available heap memory
- reload page after restart button is pressed
- analog/dallas values command as list like ems-devices
- analog/dallas HA-entities based on id
- Render mqtt float json values with trailing zero
- Removed flash strings, to increase available heap memory
- Reload page after restart button is pressed
- Analog/dallas values command as list like ems-devices
- Analog/dallas HA-entities based on id
- MQTT Base is a mandatory field. Removed MQTT topic length from settings
- HA duration class for time entities [[#822](https://github.com/emsesp/EMS-ESP32/issues/822)
- AM200 alternative heatsource as class heatsource [[#857](https://github.com/emsesp/EMS-ESP32/issues/857)

View File

@@ -1,5 +1,5 @@
{
"adapter": "react",
"baseLocale": "pl",
"$schema": "https://unpkg.com/typesafe-i18n@5.21.0/schema/typesafe-i18n.json"
"$schema": "https://unpkg.com/typesafe-i18n@5.22.0/schema/typesafe-i18n.json"
}

View File

@@ -12,15 +12,15 @@
"@emotion/styled": "^11.10.5",
"@msgpack/msgpack": "^2.8.0",
"@mui/icons-material": "^5.11.0",
"@mui/material": "^5.11.6",
"@table-library/react-table-library": "4.0.23",
"@mui/material": "^5.11.7",
"@table-library/react-table-library": "4.0.24",
"@types/lodash": "^4.14.191",
"@types/node": "^18.11.18",
"@types/react": "^18.0.27",
"@types/react-dom": "^18.0.10",
"@types/react-router-dom": "^5.3.3",
"async-validator": "^4.2.5",
"axios": "^1.2.6",
"axios": "^1.3.2",
"jwt-decode": "^3.1.2",
"lodash": "^4.17.21",
"notistack": "^2.0.8",
@@ -32,8 +32,8 @@
"react-router-dom": "^6.8.0",
"react-scripts": "^5.0.1",
"sockette": "^2.0.6",
"typesafe-i18n": "^5.21.0",
"typescript": "^4.9.4"
"typesafe-i18n": "^5.22.0",
"typescript": "^4.9.5"
},
"devDependencies": {
"http-proxy-middleware": "^2.0.6",
@@ -3082,14 +3082,14 @@
}
},
"node_modules/@mui/base": {
"version": "5.0.0-alpha.115",
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.115.tgz",
"integrity": "sha512-OGQ84whT/yNYd6xKCGGS6MxqEfjVjk5esXM7HP6bB2Rim7QICUapxZt4nm8q39fpT08rNDkv3xPVqDDwRdRg1g==",
"version": "5.0.0-alpha.116",
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.116.tgz",
"integrity": "sha512-VwhifWdrfHc4/ZdqRZ4Gf+7P39sovNN24By1YVZdvJ9fvp0Sr8sNftGUCjYXXz+xCXVBQDXvhfxMwZrj2MvJvA==",
"dependencies": {
"@babel/runtime": "^7.20.7",
"@emotion/is-prop-valid": "^1.2.0",
"@mui/types": "^7.2.3",
"@mui/utils": "^5.11.2",
"@mui/utils": "^5.11.7",
"@popperjs/core": "^2.11.6",
"clsx": "^1.2.1",
"prop-types": "^15.8.1",
@@ -3114,9 +3114,9 @@
}
},
"node_modules/@mui/core-downloads-tracker": {
"version": "5.11.6",
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.11.6.tgz",
"integrity": "sha512-lbD3qdafBOf2dlqKhOcVRxaPAujX+9UlPC6v8iMugMeAXe0TCgU3QbGXY3zrJsu6ex64WYDpH4y1+WOOBmWMuA==",
"version": "5.11.7",
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.11.7.tgz",
"integrity": "sha512-lZgX7XQTk0zVcpwEa80r+T4y09dosnUxWvFPSikU/2Hh5wnyNOek8WfJwGCNsaRiXJHMi5eHY+z8oku4u5lgNw==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui"
@@ -3148,16 +3148,16 @@
}
},
"node_modules/@mui/material": {
"version": "5.11.6",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.11.6.tgz",
"integrity": "sha512-MzkkL5KC2PCkFiv8cLpkzgLUPXSrAtnvJBR0emV7mLVWbkwV3n5832vjBx154B6R032fHjFTziTh7YEb50nK6Q==",
"version": "5.11.7",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.11.7.tgz",
"integrity": "sha512-wDv7Pc6kMe9jeWkmCLt4JChd1lPc2u23JQHpB35L2VwQowpNFoDfIwqi0sYCnZTMKlRc7lza8LqwSwHl2G52Rw==",
"dependencies": {
"@babel/runtime": "^7.20.7",
"@mui/base": "5.0.0-alpha.115",
"@mui/core-downloads-tracker": "^5.11.6",
"@mui/system": "^5.11.5",
"@mui/base": "5.0.0-alpha.116",
"@mui/core-downloads-tracker": "^5.11.7",
"@mui/system": "^5.11.7",
"@mui/types": "^7.2.3",
"@mui/utils": "^5.11.2",
"@mui/utils": "^5.11.7",
"@types/react-transition-group": "^4.4.5",
"clsx": "^1.2.1",
"csstype": "^3.1.1",
@@ -3192,12 +3192,12 @@
}
},
"node_modules/@mui/private-theming": {
"version": "5.11.2",
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.2.tgz",
"integrity": "sha512-qZwMaqRFPwlYmqwVKblKBGKtIjJRAj3nsvX93pOmatsXyorW7N/0IPE/swPgz1VwChXhHO75DwBEx8tB+aRMNg==",
"version": "5.11.7",
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.7.tgz",
"integrity": "sha512-XzRTSZdc8bhuUdjablTNv3kFkZ/XIMlKkOqqJCU0G8W3tWGXpau2DXkafPd1ddjPhF9zF3qLKNGgKCChYItjgA==",
"dependencies": {
"@babel/runtime": "^7.20.7",
"@mui/utils": "^5.11.2",
"@mui/utils": "^5.11.7",
"prop-types": "^15.8.1"
},
"engines": {
@@ -3249,15 +3249,15 @@
}
},
"node_modules/@mui/system": {
"version": "5.11.5",
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.5.tgz",
"integrity": "sha512-KNVsJ0sgRRp2XBqhh4wPS5aacteqjwxgiYTVwVnll2fgkgunZKo3DsDiGMrFlCg25ZHA3Ax58txWGE9w58zp0w==",
"version": "5.11.7",
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.7.tgz",
"integrity": "sha512-uGB6hBxGlAdlmbLdTtUZYNPXkgQGGnKxHdkRATqsu7UlCxNsc/yS5NCEWy/3c4pnelD1LDLD39WrntP9mwhfkQ==",
"dependencies": {
"@babel/runtime": "^7.20.7",
"@mui/private-theming": "^5.11.2",
"@mui/private-theming": "^5.11.7",
"@mui/styled-engine": "^5.11.0",
"@mui/types": "^7.2.3",
"@mui/utils": "^5.11.2",
"@mui/utils": "^5.11.7",
"clsx": "^1.2.1",
"csstype": "^3.1.1",
"prop-types": "^15.8.1"
@@ -3301,9 +3301,9 @@
}
},
"node_modules/@mui/utils": {
"version": "5.11.2",
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.2.tgz",
"integrity": "sha512-AyizuHHlGdAtH5hOOXBW3kriuIwUIKUIgg0P7LzMvzf6jPhoQbENYqY6zJqfoZ7fAWMNNYT8mgN5EftNGzwE2w==",
"version": "5.11.7",
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.7.tgz",
"integrity": "sha512-8uyNDeVHZA804Ego20Erv8TpxlbqTe/EbhTI2H1UYr4/RiIbBprat8W4Qqr2UQIsC/b3DLz+0RQ6R/E5BxEcLA==",
"dependencies": {
"@babel/runtime": "^7.20.7",
"@types/prop-types": "^15.7.5",
@@ -3775,9 +3775,9 @@
}
},
"node_modules/@table-library/react-table-library": {
"version": "4.0.23",
"resolved": "https://registry.npmjs.org/@table-library/react-table-library/-/react-table-library-4.0.23.tgz",
"integrity": "sha512-o2L/fqhwQNxsNbbm3LIiyZzEwaTslhG1tY9ArkYdS0xJyRhJxcOLfbJ3+dcnOOn+aIJpmPmQH+gr7RYJC0P8uw==",
"version": "4.0.24",
"resolved": "https://registry.npmjs.org/@table-library/react-table-library/-/react-table-library-4.0.24.tgz",
"integrity": "sha512-tOeKermNhSDKGVvzBlF8gtLVWl+lWbCHk0XH/7s1ybZ9XI8TXpogzXavyRfObGFAIyeazr7Qy5bWGWnE4uueUg==",
"dependencies": {
"clsx": "1.1.1",
"react-virtualized-auto-sizer": "1.0.6",
@@ -5076,9 +5076,9 @@
}
},
"node_modules/axios": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.6.tgz",
"integrity": "sha512-rC/7F08XxZwjMV4iuWv+JpD3E0Ksqg9nac4IIg6RwNuF0JTeWoCo/mBNG54+tNhhI11G3/VDRbdDQTs9hGp4pQ==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.2.tgz",
"integrity": "sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
@@ -16789,9 +16789,9 @@
}
},
"node_modules/typesafe-i18n": {
"version": "5.21.0",
"resolved": "https://registry.npmjs.org/typesafe-i18n/-/typesafe-i18n-5.21.0.tgz",
"integrity": "sha512-hfJQ7j0jvz21s2Iiv92Nx7rGyEQZJnVaQ64ek6Bn3IDaADiGFoUbSc7ZPYqeI9iTO8mOe35ACJ9MTn2cEp1ECA==",
"version": "5.22.0",
"resolved": "https://registry.npmjs.org/typesafe-i18n/-/typesafe-i18n-5.22.0.tgz",
"integrity": "sha512-I6dH/lmBEOOMdLmHbxOZK4x7wQrf7ZrgT2ynTzcJZAIJIfj0QdU8ncKOfrMOuTf3ddpe/MLSH1NKLxfPS7l2dQ==",
"bin": {
"typesafe-i18n": "cli/typesafe-i18n.mjs"
},
@@ -16804,9 +16804,9 @@
}
},
"node_modules/typescript": {
"version": "4.9.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
"version": "4.9.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -20033,14 +20033,14 @@
"integrity": "sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ=="
},
"@mui/base": {
"version": "5.0.0-alpha.115",
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.115.tgz",
"integrity": "sha512-OGQ84whT/yNYd6xKCGGS6MxqEfjVjk5esXM7HP6bB2Rim7QICUapxZt4nm8q39fpT08rNDkv3xPVqDDwRdRg1g==",
"version": "5.0.0-alpha.116",
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.116.tgz",
"integrity": "sha512-VwhifWdrfHc4/ZdqRZ4Gf+7P39sovNN24By1YVZdvJ9fvp0Sr8sNftGUCjYXXz+xCXVBQDXvhfxMwZrj2MvJvA==",
"requires": {
"@babel/runtime": "^7.20.7",
"@emotion/is-prop-valid": "^1.2.0",
"@mui/types": "^7.2.3",
"@mui/utils": "^5.11.2",
"@mui/utils": "^5.11.7",
"@popperjs/core": "^2.11.6",
"clsx": "^1.2.1",
"prop-types": "^15.8.1",
@@ -20048,9 +20048,9 @@
}
},
"@mui/core-downloads-tracker": {
"version": "5.11.6",
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.11.6.tgz",
"integrity": "sha512-lbD3qdafBOf2dlqKhOcVRxaPAujX+9UlPC6v8iMugMeAXe0TCgU3QbGXY3zrJsu6ex64WYDpH4y1+WOOBmWMuA=="
"version": "5.11.7",
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.11.7.tgz",
"integrity": "sha512-lZgX7XQTk0zVcpwEa80r+T4y09dosnUxWvFPSikU/2Hh5wnyNOek8WfJwGCNsaRiXJHMi5eHY+z8oku4u5lgNw=="
},
"@mui/icons-material": {
"version": "5.11.0",
@@ -20061,16 +20061,16 @@
}
},
"@mui/material": {
"version": "5.11.6",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.11.6.tgz",
"integrity": "sha512-MzkkL5KC2PCkFiv8cLpkzgLUPXSrAtnvJBR0emV7mLVWbkwV3n5832vjBx154B6R032fHjFTziTh7YEb50nK6Q==",
"version": "5.11.7",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.11.7.tgz",
"integrity": "sha512-wDv7Pc6kMe9jeWkmCLt4JChd1lPc2u23JQHpB35L2VwQowpNFoDfIwqi0sYCnZTMKlRc7lza8LqwSwHl2G52Rw==",
"requires": {
"@babel/runtime": "^7.20.7",
"@mui/base": "5.0.0-alpha.115",
"@mui/core-downloads-tracker": "^5.11.6",
"@mui/system": "^5.11.5",
"@mui/base": "5.0.0-alpha.116",
"@mui/core-downloads-tracker": "^5.11.7",
"@mui/system": "^5.11.7",
"@mui/types": "^7.2.3",
"@mui/utils": "^5.11.2",
"@mui/utils": "^5.11.7",
"@types/react-transition-group": "^4.4.5",
"clsx": "^1.2.1",
"csstype": "^3.1.1",
@@ -20080,12 +20080,12 @@
}
},
"@mui/private-theming": {
"version": "5.11.2",
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.2.tgz",
"integrity": "sha512-qZwMaqRFPwlYmqwVKblKBGKtIjJRAj3nsvX93pOmatsXyorW7N/0IPE/swPgz1VwChXhHO75DwBEx8tB+aRMNg==",
"version": "5.11.7",
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.7.tgz",
"integrity": "sha512-XzRTSZdc8bhuUdjablTNv3kFkZ/XIMlKkOqqJCU0G8W3tWGXpau2DXkafPd1ddjPhF9zF3qLKNGgKCChYItjgA==",
"requires": {
"@babel/runtime": "^7.20.7",
"@mui/utils": "^5.11.2",
"@mui/utils": "^5.11.7",
"prop-types": "^15.8.1"
}
},
@@ -20101,15 +20101,15 @@
}
},
"@mui/system": {
"version": "5.11.5",
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.5.tgz",
"integrity": "sha512-KNVsJ0sgRRp2XBqhh4wPS5aacteqjwxgiYTVwVnll2fgkgunZKo3DsDiGMrFlCg25ZHA3Ax58txWGE9w58zp0w==",
"version": "5.11.7",
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.7.tgz",
"integrity": "sha512-uGB6hBxGlAdlmbLdTtUZYNPXkgQGGnKxHdkRATqsu7UlCxNsc/yS5NCEWy/3c4pnelD1LDLD39WrntP9mwhfkQ==",
"requires": {
"@babel/runtime": "^7.20.7",
"@mui/private-theming": "^5.11.2",
"@mui/private-theming": "^5.11.7",
"@mui/styled-engine": "^5.11.0",
"@mui/types": "^7.2.3",
"@mui/utils": "^5.11.2",
"@mui/utils": "^5.11.7",
"clsx": "^1.2.1",
"csstype": "^3.1.1",
"prop-types": "^15.8.1"
@@ -20122,9 +20122,9 @@
"requires": {}
},
"@mui/utils": {
"version": "5.11.2",
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.2.tgz",
"integrity": "sha512-AyizuHHlGdAtH5hOOXBW3kriuIwUIKUIgg0P7LzMvzf6jPhoQbENYqY6zJqfoZ7fAWMNNYT8mgN5EftNGzwE2w==",
"version": "5.11.7",
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.7.tgz",
"integrity": "sha512-8uyNDeVHZA804Ego20Erv8TpxlbqTe/EbhTI2H1UYr4/RiIbBprat8W4Qqr2UQIsC/b3DLz+0RQ6R/E5BxEcLA==",
"requires": {
"@babel/runtime": "^7.20.7",
"@types/prop-types": "^15.7.5",
@@ -20408,9 +20408,9 @@
}
},
"@table-library/react-table-library": {
"version": "4.0.23",
"resolved": "https://registry.npmjs.org/@table-library/react-table-library/-/react-table-library-4.0.23.tgz",
"integrity": "sha512-o2L/fqhwQNxsNbbm3LIiyZzEwaTslhG1tY9ArkYdS0xJyRhJxcOLfbJ3+dcnOOn+aIJpmPmQH+gr7RYJC0P8uw==",
"version": "4.0.24",
"resolved": "https://registry.npmjs.org/@table-library/react-table-library/-/react-table-library-4.0.24.tgz",
"integrity": "sha512-tOeKermNhSDKGVvzBlF8gtLVWl+lWbCHk0XH/7s1ybZ9XI8TXpogzXavyRfObGFAIyeazr7Qy5bWGWnE4uueUg==",
"requires": {
"clsx": "1.1.1",
"react-virtualized-auto-sizer": "1.0.6",
@@ -21434,9 +21434,9 @@
"integrity": "sha512-b1WlTV8+XKLj9gZy2DZXgQiyDp9xkkoe2a6U6UbYccScq2wgH/YwCeI2/Jq2mgo0HzQxqJOjWZBLeA/mqsk5Mg=="
},
"axios": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.6.tgz",
"integrity": "sha512-rC/7F08XxZwjMV4iuWv+JpD3E0Ksqg9nac4IIg6RwNuF0JTeWoCo/mBNG54+tNhhI11G3/VDRbdDQTs9hGp4pQ==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.2.tgz",
"integrity": "sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==",
"requires": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
@@ -29785,15 +29785,15 @@
}
},
"typesafe-i18n": {
"version": "5.21.0",
"resolved": "https://registry.npmjs.org/typesafe-i18n/-/typesafe-i18n-5.21.0.tgz",
"integrity": "sha512-hfJQ7j0jvz21s2Iiv92Nx7rGyEQZJnVaQ64ek6Bn3IDaADiGFoUbSc7ZPYqeI9iTO8mOe35ACJ9MTn2cEp1ECA==",
"version": "5.22.0",
"resolved": "https://registry.npmjs.org/typesafe-i18n/-/typesafe-i18n-5.22.0.tgz",
"integrity": "sha512-I6dH/lmBEOOMdLmHbxOZK4x7wQrf7ZrgT2ynTzcJZAIJIfj0QdU8ncKOfrMOuTf3ddpe/MLSH1NKLxfPS7l2dQ==",
"requires": {}
},
"typescript": {
"version": "4.9.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg=="
"version": "4.9.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g=="
},
"unbox-primitive": {
"version": "1.0.2",

View File

@@ -8,8 +8,8 @@
"@emotion/styled": "^11.10.5",
"@msgpack/msgpack": "^2.8.0",
"@mui/icons-material": "^5.11.0",
"@mui/material": "^5.11.6",
"@table-library/react-table-library": "4.0.23",
"@mui/material": "^5.11.7",
"@table-library/react-table-library": "4.0.24",
"@types/lodash": "^4.14.191",
"@types/node": "^18.11.18",
"@types/react": "^18.0.27",
@@ -26,9 +26,9 @@
"react-icons": "^4.7.1",
"react-scripts": "^5.0.1",
"sockette": "^2.0.6",
"typesafe-i18n": "^5.21.0",
"typescript": "^4.9.4",
"axios": "^1.2.6",
"typesafe-i18n": "^5.22.0",
"typescript": "^4.9.5",
"axios": "^1.3.2",
"react-router-dom": "^6.8.0"
},
"scripts": {

View File

@@ -157,6 +157,7 @@ const de: Translation = {
CUSTOMIZATIONS_HELP_3: 'Schreibaktion deaktivieren',
CUSTOMIZATIONS_HELP_4: 'von MQTT und API ausschließen',
CUSTOMIZATIONS_HELP_5: 'Aus dem Kontrollzentrum ausblenden',
CUSTOMIZATIONS_HELP_6: 'Aus dem Speicher löschen',
SELECT_DEVICE: 'Wählen Sie ein Gerät aus',
SET_ALL: 'setzen Sie alle',
OPTIONS: 'Optionen',

View File

@@ -157,6 +157,7 @@ const en: Translation = {
CUSTOMIZATIONS_HELP_3: 'disable write action',
CUSTOMIZATIONS_HELP_4: 'exclude from MQTT and API',
CUSTOMIZATIONS_HELP_5: 'hide from Dashboard',
CUSTOMIZATIONS_HELP_6: 'remove from memory',
SELECT_DEVICE: 'Select a device',
SET_ALL: 'set all',
OPTIONS: 'Options',

View File

@@ -157,6 +157,7 @@ const fr: Translation = {
CUSTOMIZATIONS_HELP_3: 'désactiver l\'action d\'écriture',
CUSTOMIZATIONS_HELP_4: 'exclure de MQTT et de l\'API',
CUSTOMIZATIONS_HELP_5: 'cacher du Tableau de bord',
CUSTOMIZATIONS_HELP_6: 'remove from memory', // TODO translate
SELECT_DEVICE: 'Sélectionnez un appareil',
SET_ALL: 'tout régler',
OPTIONS: 'Options',

View File

@@ -157,6 +157,7 @@ const nl: Translation = {
CUSTOMIZATIONS_HELP_3: 'Zet schrijfacties uit',
CUSTOMIZATIONS_HELP_4: 'Uitsluiten van MQTT en API',
CUSTOMIZATIONS_HELP_5: 'verberg van het Dashboard',
CUSTOMIZATIONS_HELP_6: 'remove from memory', // TODO translate
SELECT_DEVICE: 'Selecteer een apparaat',
SET_ALL: 'Alles aanzetten',
OPTIONS: 'Opties',

View File

@@ -157,6 +157,7 @@ const no: Translation = {
CUSTOMIZATIONS_HELP_3: 'inaktiviser skriving',
CUSTOMIZATIONS_HELP_4: 'ekskludere fra MQTT og API',
CUSTOMIZATIONS_HELP_5: 'gjemme fra Dashboard',
CUSTOMIZATIONS_HELP_6: 'remove from memory', // TODO translate
SELECT_DEVICE: 'Velg en enhet',
SET_ALL: 'sett alle',
OPTIONS: 'Alternativ',

View File

@@ -157,6 +157,7 @@ const pl: BaseTranslation = {
CUSTOMIZATIONS_HELP_3: 'zablokuj akcje zapisu',
CUSTOMIZATIONS_HELP_4: 'wyklucz z MQTT i API',
CUSTOMIZATIONS_HELP_5: 'ukryj na pulpicie',
CUSTOMIZATIONS_HELP_6: 'remove from memory', // TODO translate
SELECT_DEVICE: 'wybierz urządzenie',
SET_ALL: 'Ustaw wszystko jako',
OPTIONS: 'Opcje',

View File

@@ -157,6 +157,7 @@ const sv: Translation = {
CUSTOMIZATIONS_HELP_3: 'Inaktivera skrivningar',
CUSTOMIZATIONS_HELP_4: 'Exkludera från MQTT & API',
CUSTOMIZATIONS_HELP_5: 'Göm från Kontrollpanel',
CUSTOMIZATIONS_HELP_6: 'remove from memory', // TODO translate
SELECT_DEVICE: 'Välj en enhet',
SET_ALL: 'ställ in alla',
OPTIONS: 'Alternativ',

View File

@@ -13,9 +13,13 @@ 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';
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
import DeleteForeverIcon from '@mui/icons-material/DeleteForever';
type OptionType = 'deleted' | 'readonly' | 'web_exclude' | 'api_mqtt_exclude' | 'favorite';
const OPTION_ICONS: { [type in OptionType]: [React.ComponentType<SvgIconProps>, React.ComponentType<SvgIconProps>] } = {
deleted: [DeleteForeverIcon, DeleteOutlineIcon],
readonly: [EditOffOutlinedIcon, EditOutlinedIcon],
web_exclude: [VisibilityOffOutlinedIcon, VisibilityOutlinedIcon],
api_mqtt_exclude: [CommentsDisabledOutlinedIcon, InsertCommentOutlinedIcon],

View File

@@ -25,14 +25,16 @@ import { useSnackbar } from 'notistack';
import WarningIcon from '@mui/icons-material/Warning';
import CancelIcon from '@mui/icons-material/Cancel';
import DoneIcon from '@mui/icons-material/Done';
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
import SearchIcon from '@mui/icons-material/Search';
import FilterListIcon from '@mui/icons-material/FilterList';
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
import OptionIcon from './OptionIcon';
import { ButtonRow, FormLoader, ValidatedTextField, SectionContent } from '../components';
import { ButtonRow, FormLoader, ValidatedTextField, SectionContent, MessageBox } from '../components';
import * as EMSESP from './api';
@@ -42,15 +44,18 @@ import { DeviceShort, Devices, DeviceEntity, DeviceEntityMask } from './types';
import { useI18nContext } from '../i18n/i18n-react';
import RestartMonitor from '../framework/system/RestartMonitor';
export const APIURL = window.location.origin + '/api/';
const SettingsCustomization: FC = () => {
const { LL } = useI18nContext();
const { enqueueSnackbar } = useSnackbar();
const emptyDeviceEntity = { id: '', v: 0, n: '', cn: '', m: 0, w: false };
const [restarting, setRestarting] = useState<boolean>(false);
const [restartNeeded, setRestartNeeded] = useState<boolean>(false);
const [deviceEntities, setDeviceEntities] = useState<DeviceEntity[]>([emptyDeviceEntity]);
const [devices, setDevices] = useState<Devices>();
const [errorMessage, setErrorMessage] = useState<string>();
@@ -58,15 +63,13 @@ const SettingsCustomization: FC = () => {
const [confirmReset, setConfirmReset] = useState<boolean>(false);
const [selectedFilters, setSelectedFilters] = useState<number>(0);
const [search, setSearch] = useState('');
const [deviceEntity, setDeviceEntity] = useState<DeviceEntity>();
// eslint-disable-next-line
const [masks, setMasks] = useState(() => ['']);
const entities_theme = useTheme({
Table: `
--data-table-library_grid-template-columns: 120px repeat(1, minmax(80px, 1fr)) 45px 45px 120px;
--data-table-library_grid-template-columns: 150px repeat(1, minmax(80px, 1fr)) 45px 45px 120px;
`,
BaseRow: `
font-size: 14px;
@@ -210,6 +213,9 @@ const SettingsCustomization: FC = () => {
if ((m & 8) === 8) {
new_masks.push('8');
}
if ((m & 128) === 128) {
new_masks.push('128');
}
return new_masks;
};
@@ -235,6 +241,7 @@ const SettingsCustomization: FC = () => {
const selected_device = parseInt(event.target.value, 10);
setSelectedDevice(selected_device);
fetchDeviceEntities(devices?.devices[selected_device].i);
setRestartNeeded(false);
}
};
@@ -271,6 +278,15 @@ const SettingsCustomization: FC = () => {
);
};
const restart = async () => {
try {
await EMSESP.restart();
setRestarting(true);
} catch (error) {
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
}
};
const saveCustomization = async () => {
if (devices && deviceEntities && selectedDevice !== -1) {
const masked_entities = getChanges();
@@ -289,6 +305,8 @@ const SettingsCustomization: FC = () => {
});
if (response.status === 200) {
enqueueSnackbar(LL.CUSTOMIZATIONS_SAVED(), { variant: 'success' });
} else if (response.status === 201) {
setRestartNeeded(true);
} else {
enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' });
}
@@ -312,7 +330,8 @@ const SettingsCustomization: FC = () => {
<OptionIcon type="favorite" isSet={true} />={LL.CUSTOMIZATIONS_HELP_2()}&nbsp;&nbsp;
<OptionIcon type="readonly" isSet={true} />={LL.CUSTOMIZATIONS_HELP_3()}&nbsp;&nbsp;
<OptionIcon type="api_mqtt_exclude" isSet={true} />={LL.CUSTOMIZATIONS_HELP_4()}&nbsp;&nbsp;
<OptionIcon type="web_exclude" isSet={true} />={LL.CUSTOMIZATIONS_HELP_5()}
<OptionIcon type="web_exclude" isSet={true} />={LL.CUSTOMIZATIONS_HELP_5()}&nbsp;&nbsp;
<OptionIcon type="deleted" isSet={true} />={LL.CUSTOMIZATIONS_HELP_6()}
</Typography>
</Box>
<ValidatedTextField
@@ -425,6 +444,9 @@ const SettingsCustomization: FC = () => {
<ToggleButton value="1">
<OptionIcon type="web_exclude" isSet={true} />
</ToggleButton>
<ToggleButton value="128">
<OptionIcon type="deleted" isSet={true} />
</ToggleButton>
</ToggleButtonGroup>
</Grid>
@@ -479,6 +501,7 @@ const SettingsCustomization: FC = () => {
{tableList.map((de: DeviceEntity) => (
<Row key={de.id} item={de} onClick={() => editEntity(de)}>
<Cell stiff>
{!deviceEntity && (
<ToggleButtonGroup
size="small"
color="secondary"
@@ -488,25 +511,26 @@ const SettingsCustomization: FC = () => {
if (de.n === '' && de.m & DeviceEntityMask.DV_READONLY) {
de.m = de.m | DeviceEntityMask.DV_WEB_EXCLUDE;
}
if (de.m & DeviceEntityMask.DV_WEB_EXCLUDE) {
de.m = de.m & ~DeviceEntityMask.DV_FAVORITE;
}
setMasks(['']);
}}
>
<ToggleButton value="8" disabled={(de.m & 1) !== 0 || de.n === undefined}>
<ToggleButton value="8" disabled={(de.m & 0x81) !== 0 || de.n === undefined}>
<OptionIcon
type="favorite"
isSet={(de.m & DeviceEntityMask.DV_FAVORITE) === DeviceEntityMask.DV_FAVORITE}
/>
</ToggleButton>
<ToggleButton value="4" disabled={!de.w || (de.m & 3) === 3}>
<ToggleButton value="4" disabled={!de.w || (de.m & 0x83) >= 3}>
<OptionIcon
type="readonly"
isSet={(de.m & DeviceEntityMask.DV_READONLY) === DeviceEntityMask.DV_READONLY}
/>
</ToggleButton>
<ToggleButton value="2" disabled={de.n === ''}>
<ToggleButton value="2" disabled={de.n === '' || (de.m & 0x80) !== 0}>
<OptionIcon
type="api_mqtt_exclude"
isSet={
@@ -514,18 +538,26 @@ const SettingsCustomization: FC = () => {
}
/>
</ToggleButton>
<ToggleButton value="1" disabled={de.n === undefined}>
<ToggleButton value="1" disabled={de.n === undefined || (de.m & 0x80) !== 0}>
<OptionIcon
type="web_exclude"
isSet={(de.m & DeviceEntityMask.DV_WEB_EXCLUDE) === DeviceEntityMask.DV_WEB_EXCLUDE}
/>
</ToggleButton>
<ToggleButton value="128">
<OptionIcon
type="deleted"
isSet={(de.m & DeviceEntityMask.DV_DELETED) === DeviceEntityMask.DV_DELETED}
/>
</ToggleButton>
</ToggleButtonGroup>
)}
</Cell>
<Cell>{formatName(de)}</Cell>
<Cell>{!(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.mi)}</Cell>
<Cell>{!(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.ma)}</Cell>
<Cell>{formatValue(de.v)}</Cell>
<Cell>{!deviceEntity && formatName(de)}</Cell>
<Cell>{!deviceEntity && !(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.mi)}</Cell>
<Cell>{!deviceEntity && !(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.ma)}</Cell>
<Cell>{!deviceEntity && formatValue(de.v)}</Cell>
</Row>
))}
</Body>
@@ -567,10 +599,18 @@ const SettingsCustomization: FC = () => {
</Typography>
{renderDeviceList()}
{renderDeviceData()}
{restartNeeded && (
<MessageBox my={2} level="warning" message={LL.RESTART_TEXT()}>
<Button startIcon={<PowerSettingsNewIcon />} variant="contained" color="error" onClick={restart}>
{LL.RESTART()}
</Button>
</MessageBox>
)}
{!restartNeeded && (
<Box display="flex" flexWrap="wrap">
<Box flexGrow={1}>
<ButtonRow>
{num_changes !== 0 && (
<ButtonRow>
<Button
startIcon={<WarningIcon color="warning" />}
variant="contained"
@@ -579,8 +619,8 @@ const SettingsCustomization: FC = () => {
>
{LL.APPLY_CHANGES(num_changes)}
</Button>
)}
</ButtonRow>
)}
</Box>
<ButtonRow>
<Button
@@ -593,6 +633,7 @@ const SettingsCustomization: FC = () => {
</Button>
</ButtonRow>
</Box>
)}
{renderResetDialog()}
</>
);
@@ -655,11 +696,11 @@ const SettingsCustomization: FC = () => {
{LL.CANCEL()}
</Button>
<Button
startIcon={<WarningIcon color="warning" />}
variant="contained"
startIcon={<DoneIcon />}
variant="outlined"
type="submit"
onClick={() => updateEntity()}
color="info"
color="primary"
>
{LL.UPDATE()}
</Button>
@@ -671,7 +712,7 @@ const SettingsCustomization: FC = () => {
return (
<SectionContent title={LL.CUSTOMIZATIONS()} titleGutter>
{renderContent()}
{restarting ? <RestartMonitor /> : renderContent()}
{renderEditDialog()}
</SectionContent>
);

View File

@@ -298,5 +298,6 @@ export enum DeviceEntityMask {
DV_WEB_EXCLUDE = 1,
DV_API_MQTT_EXCLUDE = 2,
DV_READONLY = 4,
DV_FAVORITE = 8
DV_FAVORITE = 8,
DV_DELETED = 128
}

View File

@@ -30,7 +30,7 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
size_t fsize = request->contentLength();
is_firmware = false;
if ((extension == "bin") && (fsize > 1500000)) {
if ((extension == "bin") && (fsize > 1000000)) {
is_firmware = true;
} else if (extension == "json") {
md5[0] = '\0'; // clear md5

View File

@@ -942,7 +942,10 @@ rest_server.post(EMSESP_DEVICEENTITIES_ENDPOINT, (req, res) => {
function updateMask(entity, de, dd) {
const current_mask = parseInt(entity.slice(0, 2), 16)
const shortname_with_customname = entity.slice(2)
// strip of any min/max ranges
const shortname_with_customname = entity.slice(2).split('>')[0]
const shortname = shortname_with_customname.split('|')[0]
const new_custom_name = shortname_with_customname.split('|')[1]

View File

@@ -184,11 +184,6 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
// register device values for common values (not heating circuit)
register_device_values();
if (System::test_set_all_active()) {
// if we're just dumping out values, create a single dummy hc1
register_device_values_hc(std::make_shared<emsesp::Thermostat::HeatingCircuit>(1, model)); // hc=1
}
// query all the heating circuits. This is only done once.
// The automatic fetch will from now on only update the active heating circuits
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
@@ -429,7 +424,7 @@ uint8_t Thermostat::HeatingCircuit::get_mode() const {
} else if (mode == 0) {
return HeatingCircuit::Mode::OFF;
}
} else if (model == EMSdevice::EMS_DEVICE_FLAG_RC20) {
} else if (model == EMSdevice::EMS_DEVICE_FLAG_RC20 || model == EMSdevice::EMS_DEVICE_FLAG_RC30) {
if (mode == 0) {
return HeatingCircuit::Mode::OFF;
} else if (mode == 1) {
@@ -566,7 +561,7 @@ void Thermostat::process_RC20Set(std::shared_ptr<const Telegram> telegram) {
return;
}
has_update(telegram, hc->mode, 23); // 0:off, 1:manual, 2:auto
// has_update(telegram, hc->nofrosttemp, 24); // guess, not confirmed yet, maybe nighttemp?
has_update(telegram, hc->nofrosttemp, 24); // for mode off
// has_update(telegram, hc->tempautotemp, 28); // no need to read this
has_update(telegram, hc->manualtemp, 29);
}
@@ -578,7 +573,7 @@ void Thermostat::process_RC20Temp(std::shared_ptr<const Telegram> telegram) {
if (hc == nullptr) {
return;
}
has_update(telegram, hc->nighttemp, 3); // 0:off, 1:manual, 2:auto
has_update(telegram, hc->nighttemp, 3);
has_update(telegram, hc->daylowtemp, 4);
has_update(telegram, hc->daymidtemp, 5);
has_update(telegram, hc->daytemp, 6);
@@ -1136,6 +1131,7 @@ void Thermostat::process_RC300Floordry(std::shared_ptr<const Telegram> telegram)
}
// type 0x41 - data from the RC30 thermostat(0x10) - 14 bytes long
// RC30Monitor(0x41), data: 80 20 00 AC 00 00 00 02 00 05 09 00 AC 00
void Thermostat::process_RC30Monitor(std::shared_ptr<const Telegram> telegram) {
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(telegram);
if (hc == nullptr) {
@@ -1149,6 +1145,8 @@ void Thermostat::process_RC30Monitor(std::shared_ptr<const Telegram> telegram) {
}
// type 0xA7 - for reading the mode from the RC30 thermostat (0x10) and all the installation settings
// RC30Set(0xA7), data: 01 00 FF F6 01 06 00 01 0D 00 00 FF FF 01 02 02 02 00 00 05 1F 05 1F 01 0E 00 FF
// RC30Set(0xA7), data: 00 00 20 02 (offset 27)
void Thermostat::process_RC30Set(std::shared_ptr<const Telegram> telegram) {
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(telegram);
if (hc == nullptr) {
@@ -1163,12 +1161,15 @@ void Thermostat::process_RC30Set(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, mixingvalves_, 17); // Number of Mixing Valves: (0x00=0, 0x01=1, 0x02=2)
has_update(telegram, brightness_, 18); // Screen brightness 0F=dark F1=light
has_update(telegram, hc->mode, 23);
has_update(telegram, offtemp_, 24); // Set Temperature when mode is Off / 10 (e.g.: 0x0F = 7.5 degrees Celsius)
has_update(telegram, hc->nofrosttemp, 24); // Set Temperature when mode is Off / 10 (e.g.: 0x0F = 7.5 degrees Celsius)
has_update(telegram, heatingpid_, 25); // PID setting 00=1 01=2 02=3
has_update(telegram, preheating_, 26); // Preheating in the clock program: (0x00 = off, 0xFF = on)
has_update(telegram, hc->tempautotemp, 28); // is * 2
has_update(telegram, hc->manualtemp, 29); // manualtemp is * 2
}
// type 0x40 (HC1) - for reading the operating mode from the RC30 thermostat (0x10)
// RC30Temp(0x40), data: 01 01 02 20 24 28 2A 1E 0E 00 01 5A 32 05 4B 2D 00 28 00 3C FF 11 00 05 00
void Thermostat::process_RC30Temp(std::shared_ptr<const Telegram> telegram) {
// check to see we have a valid type. heating: 1 radiator, 2 convectors, 3 floors
if (telegram->offset == 0 && telegram->message_data[0] == 0x00) {
@@ -2037,18 +2038,6 @@ bool Thermostat::set_preheating(const char * value, const int8_t id) {
return true;
}
bool Thermostat::set_offtemp(const char * value, const int8_t id) {
int ot;
if (!Helpers::value2temperature(value, ot, true)) {
return false;
}
auto t = (int8_t)(ot * 2);
write_command(EMS_TYPE_RC30Settings, 24, t, EMS_TYPE_RC30Settings);
return true;
}
bool Thermostat::set_mixingvalves(const char * value, const int8_t id) {
int m;
if (!Helpers::value2number(value, m, 0, 2)) {
@@ -2261,11 +2250,11 @@ bool Thermostat::set_mode(const char * value, const int8_t id) {
mode_list = FL_(enum_mode6);
break;
case EMSdevice::EMS_DEVICE_FLAG_RC20:
case EMSdevice::EMS_DEVICE_FLAG_RC20_N:
case EMSdevice::EMS_DEVICE_FLAG_RC30:
mode_list = FL_(enum_mode2);
break;
case EMSdevice::EMS_DEVICE_FLAG_RC20_N:
case EMSdevice::EMS_DEVICE_FLAG_RC25:
case EMSdevice::EMS_DEVICE_FLAG_RC30:
case EMSdevice::EMS_DEVICE_FLAG_RC35:
case EMSdevice::EMS_DEVICE_FLAG_RC30_N:
mode_list = FL_(enum_mode3);
@@ -2286,14 +2275,7 @@ bool Thermostat::set_mode(const char * value, const int8_t id) {
uint8_t enum_index = 0;
// check for a mode number as a string with a single digit (0..9)
if (value[0] >= '0' && value[0] <= '9') {
enum_index = value[0] - '0';
if (enum_index >= Helpers::count_items(mode_list)) {
return false; // invalid number, not in enum
}
} else {
// check for the mode being a full string name
// check for the mode being a full string name or single digit
if (!Helpers::value2enum(value, enum_index, mode_list)) {
mode_list = FL_(enum_mode_ha);
if (Mqtt::ha_enabled() && !Helpers::value2enum(value, enum_index, mode_list)) {
@@ -2301,7 +2283,6 @@ bool Thermostat::set_mode(const char * value, const int8_t id) {
return false; // not found
}
}
}
uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id; // heating circuit
@@ -2916,6 +2897,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
default:
break;
}
} else if (model == EMS_DEVICE_FLAG_RC20) {
switch (mode) {
case HeatingCircuit::Mode::NIGHT:
@@ -2940,9 +2922,16 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
break;
case HeatingCircuit::Mode::MANUAL:
offset = EMS_OFFSET_RC20Set_temp_manual;
validate_typeid = set_typeid;
break;
case HeatingCircuit::Mode::OFF:
offset = EMS_OFFSET_RC20Set_temp_off;
validate_typeid = set_typeid;
break;
case HeatingCircuit::Mode::AUTO:
if (hc->get_mode() == HeatingCircuit::Mode::MANUAL) {
if (hc->get_mode() == HeatingCircuit::Mode::OFF) {
offset = EMS_OFFSET_RC20Set_temp_off;
} else if (hc->get_mode() == HeatingCircuit::Mode::MANUAL) {
offset = EMS_OFFSET_RC20Set_temp_manual;
} else {
offset = EMS_OFFSET_RC20Set_temp_auto;
@@ -2954,28 +2943,51 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
} else if (model == EMS_DEVICE_FLAG_RC30) {
switch (mode) {
case HeatingCircuit::Mode::NIGHT: // change the night temp
case HeatingCircuit::Mode::OFF:
offset = EMS_OFFSET_RC30Set_temp_off;
validate_typeid = set_typeid;
break;
case HeatingCircuit::Mode::MANUAL:
offset = EMS_OFFSET_RC30Set_temp_manual;
validate_typeid = set_typeid;
break;
case HeatingCircuit::Mode::TEMPAUTO:
offset = EMS_OFFSET_RC30Set_temp_auto;
validate_typeid = set_typeid;
break;
case HeatingCircuit::Mode::NIGHT:
set_typeid = curve_typeids[hc->hc()];
offset = EMS_OFFSET_RC30Temp_temp_night;
validate_typeid = set_typeid;
break;
case HeatingCircuit::Mode::DAYLOW: // change the offset temp
case HeatingCircuit::Mode::DAYLOW:
set_typeid = curve_typeids[hc->hc()];
offset = EMS_OFFSET_RC30Temp_temp_daylow;
validate_typeid = set_typeid;
break;
case HeatingCircuit::Mode::DAYMID: // change the offset of flowtemp
case HeatingCircuit::Mode::DAYMID:
set_typeid = curve_typeids[hc->hc()];
offset = EMS_OFFSET_RC30Temp_temp_daymid;
validate_typeid = set_typeid;
break;
case HeatingCircuit::Mode::DAY: // change the day temp
case HeatingCircuit::Mode::DAY:
set_typeid = curve_typeids[hc->hc()];
offset = EMS_OFFSET_RC30Temp_temp_day;
validate_typeid = set_typeid;
break;
case HeatingCircuit::Mode::HOLIDAY: // change the holiday temp
case HeatingCircuit::Mode::HOLIDAY:
set_typeid = curve_typeids[hc->hc()];
offset = EMS_OFFSET_RC30Temp_temp_holiday;
validate_typeid = set_typeid;
break;
default:
offset = EMS_OFFSET_RC30Set_temp;
if (hc->get_mode() == HeatingCircuit::Mode::OFF) {
offset = EMS_OFFSET_RC30Set_temp_off;
} else if (hc->get_mode() == HeatingCircuit::Mode::MANUAL) {
offset = EMS_OFFSET_RC30Set_temp_manual;
} else {
offset = EMS_OFFSET_RC30Set_temp_auto;
}
break;
}
@@ -3298,102 +3310,9 @@ bool Thermostat::set_temperature_value(const char * value, const int8_t id, cons
uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id;
if (Helpers::value2temperature(value, f, relative)) {
return set_temperature(f, mode, hc_num);
} else {
}
return false;
}
}
bool Thermostat::set_temp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::AUTO);
}
bool Thermostat::set_nighttemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::NIGHT);
}
bool Thermostat::set_daytemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::DAY);
}
bool Thermostat::set_daylowtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::DAYLOW);
}
bool Thermostat::set_daymidtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::DAYMID);
}
bool Thermostat::set_comforttemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::COMFORT);
}
bool Thermostat::set_nofrosttemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::NOFROST);
}
bool Thermostat::set_ecotemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::ECO);
}
bool Thermostat::set_heattemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::HEAT);
}
bool Thermostat::set_summertemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::SUMMER);
}
bool Thermostat::set_designtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::DESIGN);
}
bool Thermostat::set_offsettemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::OFFSET);
}
bool Thermostat::set_holidaytemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::HOLIDAY);
}
bool Thermostat::set_manualtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::MANUAL);
}
bool Thermostat::set_tempautotemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::TEMPAUTO);
}
bool Thermostat::set_noreducetemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::NOREDUCE);
}
bool Thermostat::set_reducetemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::REDUCE);
}
bool Thermostat::set_vacreducetemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::VACREDUCE);
}
bool Thermostat::set_flowtempoffset(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::FLOWOFFSET, true);
}
bool Thermostat::set_maxflowtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::MAXFLOW);
}
bool Thermostat::set_minflowtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::MINFLOW);
}
bool Thermostat::set_roominfluence(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::ROOMINFLUENCE, true);
}
bool Thermostat::set_remoteseltemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::REMOTESELTEMP);
}
// register main device values, top level for all thermostats (excluding heating circuits)
// as these are done in void Thermostat::register_device_values_hc()
@@ -3657,15 +3576,6 @@ void Thermostat::register_device_values() {
FL_(ibaCalIntTemperature),
DeviceValueUOM::DEGREES_R,
MAKE_CF_CB(set_calinttemp));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&offtemp_,
DeviceValueType::UINT,
DeviceValueNumOp::DV_NUMOP_DIV2,
FL_(offtemp),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_offtemp),
5,
30);
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwMode_, DeviceValueType::ENUM, FL_(enum_wwMode3), FL_(wwMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwmode));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW,
@@ -4055,6 +3965,11 @@ void Thermostat::register_device_values() {
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dateTime_, DeviceValueType::STRING, FL_(dateTime), DeviceValueUOM::NONE); // can't set datetime
break;
}
#if defined(EMSESP_STANDALONE_DUMP)
// if we're just dumping out values, create a single dummy hc
register_device_values_hc(std::make_shared<emsesp::Thermostat::HeatingCircuit>(1, this->model())); // hc=1
#endif
}
// registers the values for a heating circuit
@@ -4180,6 +4095,8 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode));
register_device_value(
tag, &hc->manualtemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(manualtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_manualtemp));
register_device_value(
tag, &hc->nofrosttemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(offtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_offtemp));
register_device_value(
tag, &hc->daylowtemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(daylowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_daylowtemp));
register_device_value(
@@ -4192,7 +4109,7 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
tag, &hc->switchtime1, DeviceValueType::STRING, FL_(tpl_switchtime1), FL_(switchtime), DeviceValueUOM::NONE, MAKE_CF_CB(set_switchtime1));
break;
case EMS_DEVICE_FLAG_RC20_N:
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode));
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode3), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode));
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype3), FL_(modetype), DeviceValueUOM::NONE);
register_device_value(
tag, &hc->daytemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(daytemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_daytemp));
@@ -4237,7 +4154,7 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
register_device_value(tag, &hc->summermode, DeviceValueType::ENUM, FL_(enum_summer), FL_(summermode), DeviceValueUOM::NONE);
break;
case EMS_DEVICE_FLAG_RC30:
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode3), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode));
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode2), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode));
register_device_value(tag, &hc->holiday, DeviceValueType::STRING, FL_(tpl_holidays), FL_(holidays), DeviceValueUOM::NONE, MAKE_CF_CB(set_holiday));
register_device_value(tag, &hc->vacation, DeviceValueType::STRING, FL_(tpl_holidays), FL_(vacations), DeviceValueUOM::NONE, MAKE_CF_CB(set_vacation));
register_device_value(tag, &hc->program, DeviceValueType::ENUM, FL_(enum_progMode2), FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program));
@@ -4264,6 +4181,10 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
tag, &hc->daymidtemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(daymidtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_daymidtemp));
register_device_value(
tag, &hc->daytemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(dayhightemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_daytemp));
register_device_value(
tag, &hc->manualtemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(manualtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_manualtemp));
register_device_value(
tag, &hc->nofrosttemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(offtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_offtemp));
break;
case EMS_DEVICE_FLAG_RC30_N:
case EMS_DEVICE_FLAG_RC35:

View File

@@ -191,7 +191,6 @@ class Thermostat : public EMSdevice {
int8_t brightness_; // Screen brightness 0F=dark F1=light
uint8_t preheating_; // Preheating in the clock program: (0x00 = off, 0xFF = on)
uint8_t autodst_; // Automatic change Daylight Saving time: (0x00 = off, 0xFF = on)
uint8_t offtemp_; // Set Temperature when mode is Off / 10 (e.g.: 0x0F = 7.5 degrees Celsius)
uint8_t mixingvalves_; // Number of Mixing Valves: (0x00=0, 0x01=1, 0x02=2)
int8_t dampedoutdoortemp_;
@@ -255,6 +254,7 @@ class Thermostat : public EMSdevice {
static constexpr uint8_t EMS_OFFSET_RC20StatusMessage_setpoint = 1; // setpoint temp
static constexpr uint8_t EMS_OFFSET_RC20StatusMessage_curr = 2; // current temp
static constexpr uint8_t EMS_OFFSET_RC20Set_mode = 23; // position of thermostat mode
static constexpr uint8_t EMS_OFFSET_RC20Set_temp_off = 24; // position of thermostat setpoint mode:off
static constexpr uint8_t EMS_OFFSET_RC20Set_temp_auto = 28; // position of thermostat setpoint temperature
static constexpr uint8_t EMS_OFFSET_RC20Set_temp_manual = 29; // position of thermostat setpoint temperature
@@ -265,7 +265,9 @@ class Thermostat : public EMSdevice {
static constexpr uint8_t EMS_OFFSET_RC30StatusMessage_setpoint = 1; // setpoint temp
static constexpr uint8_t EMS_OFFSET_RC30StatusMessage_curr = 2; // current temp
static constexpr uint8_t EMS_OFFSET_RC30Set_mode = 23; // position of thermostat mode
static constexpr uint8_t EMS_OFFSET_RC30Set_temp = 28; // position of thermostat setpoint temperature
static constexpr uint8_t EMS_OFFSET_RC30Set_temp_off = 24; // position of thermostat setpoint mode:off
static constexpr uint8_t EMS_OFFSET_RC30Set_temp_auto = 28; // position of thermostat setpoint temperature
static constexpr uint8_t EMS_OFFSET_RC30Set_temp_manual = 29; // position of thermostat setpoint temperature for manual mode
static constexpr uint8_t EMS_OFFSET_RC30Temp_temp_night = 3; // position of thermostat setpoint temperature for night time (T1)
static constexpr uint8_t EMS_OFFSET_RC30Temp_temp_daylow = 4; // position of thermostat setpoint temperature for daylow time (T2)
static constexpr uint8_t EMS_OFFSET_RC30Temp_temp_daymid = 5; // position of thermostat setpoint temperature for daymid time (T3)
@@ -408,33 +410,10 @@ class Thermostat : public EMSdevice {
bool set_pause(const char * value, const int8_t id);
bool set_party(const char * value, const int8_t id);
bool set_summermode(const char * value, const int8_t id);
bool set_temp(const char * value, const int8_t id);
bool set_nighttemp(const char * value, const int8_t id);
bool set_daytemp(const char * value, const int8_t id);
bool set_daylowtemp(const char * value, const int8_t id);
bool set_daymidtemp(const char * value, const int8_t id);
bool set_comforttemp(const char * value, const int8_t id);
bool set_nofrosttemp(const char * value, const int8_t id);
bool set_ecotemp(const char * value, const int8_t id);
bool set_heattemp(const char * value, const int8_t id);
bool set_summertemp(const char * value, const int8_t id);
bool set_designtemp(const char * value, const int8_t id);
bool set_offsettemp(const char * value, const int8_t id);
bool set_holidaytemp(const char * value, const int8_t id);
bool set_manualtemp(const char * value, const int8_t id);
bool set_tempautotemp(const char * value, const int8_t id);
bool set_noreducetemp(const char * value, const int8_t id);
bool set_reducetemp(const char * value, const int8_t id);
bool set_vacreducetemp(const char * value, const int8_t id);
bool set_vacreducemode(const char * value, const int8_t id);
bool set_nofrostmode(const char * value, const int8_t id);
bool set_remotetemp(const char * value, const int8_t id);
bool set_roominfluence(const char * value, const int8_t id);
bool set_roominfl_factor(const char * value, const int8_t id);
bool set_flowtempoffset(const char * value, const int8_t id);
bool set_minflowtemp(const char * value, const int8_t id);
bool set_maxflowtemp(const char * value, const int8_t id);
bool set_reducemode(const char * value, const int8_t id);
bool set_switchtime1(const char * value, const int8_t id);
bool set_switchtime2(const char * value, const int8_t id);
@@ -443,7 +422,79 @@ class Thermostat : public EMSdevice {
bool set_wwprio(const char * value, const int8_t id);
bool set_fastheatup(const char * value, const int8_t id);
bool set_switchonoptimization(const char * value, const int8_t id);
bool set_remoteseltemp(const char * value, const int8_t id);
inline bool set_temp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::AUTO);
}
inline bool set_nighttemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::NIGHT);
}
inline bool set_daytemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::DAY);
}
inline bool set_daylowtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::DAYLOW);
}
inline bool set_daymidtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::DAYMID);
}
inline bool set_comforttemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::COMFORT);
}
inline bool set_nofrosttemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::NOFROST);
}
inline bool set_ecotemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::ECO);
}
inline bool set_heattemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::HEAT);
}
inline bool set_summertemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::SUMMER);
}
inline bool set_designtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::DESIGN);
}
inline bool set_offsettemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::OFFSET);
}
inline bool set_holidaytemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::HOLIDAY);
}
inline bool set_offtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::OFF);
}
inline bool set_manualtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::MANUAL);
}
inline bool set_tempautotemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::TEMPAUTO);
}
inline bool set_noreducetemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::NOREDUCE);
}
inline bool set_reducetemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::REDUCE);
}
inline bool set_vacreducetemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::VACREDUCE);
}
inline bool set_flowtempoffset(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::FLOWOFFSET, true);
}
inline bool set_maxflowtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::MAXFLOW);
}
inline bool set_minflowtemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::MINFLOW);
}
inline bool set_roominfluence(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::ROOMINFLUENCE, true);
}
inline bool set_remoteseltemp(const char * value, const int8_t id) {
return set_temperature_value(value, id, HeatingCircuit::Mode::REMOTESELTEMP);
}
// set functions - these don't use the id/hc, the parameters are ignored
bool set_wwmode(const char * value, const int8_t id);
@@ -487,7 +538,6 @@ class Thermostat : public EMSdevice {
bool set_autodst(const char * value, const int8_t id);
bool set_preheating(const char * value, const int8_t id);
bool set_mixingvalves(const char * value, const int8_t id);
bool set_offtemp(const char * value, const int8_t id);
bool set_hybridStrategy(const char * value, const int8_t id);
bool set_switchOverTemp(const char * value, const int8_t id);

View File

@@ -40,7 +40,17 @@ bool EMSdevice::has_entities() const {
return true;
}
}
return false;
bool found = false;
EMSESP::webCustomizationService.read([&](WebCustomization & settings) {
for (EntityCustomization entityCustomization : settings.entityCustomizations) {
if (entityCustomization.device_id == device_id() && entityCustomization.entity_ids.size()) {
found = true;
break;
}
}
});
return found;
}
const char * EMSdevice::tag_to_string(uint8_t tag, const bool translate) {
@@ -521,14 +531,9 @@ void EMSdevice::add_device_value(uint8_t tag,
for (std::string entity_id : entityCustomization.entity_ids) {
// if there is an appended custom name, strip it to get the true entity name
// and extract the new custom name
std::string shortname;
auto custom_name_pos = entity_id.find('|');
bool has_custom_name = (custom_name_pos != std::string::npos);
if (has_custom_name) {
shortname = entity_id.substr(2, custom_name_pos - 2);
} else {
shortname = entity_id.substr(2);
}
std::string shortname = has_custom_name ? entity_id.substr(2, custom_name_pos - 2) : entity_id.substr(2);
// we found the device entity
if (shortname == entity) {
@@ -1029,6 +1034,23 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) {
}
}
}
EMSESP::webCustomizationService.read([&](WebCustomization & settings) {
for (EntityCustomization entityCustomization : settings.entityCustomizations) {
if ((entityCustomization.device_id == device_id())) {
for (std::string entity_id : entityCustomization.entity_ids) {
uint8_t mask = Helpers::hextoint(entity_id.substr(0, 2).c_str());
if (mask & 0x80) {
JsonObject obj = output.createNestedObject();
obj["id"] = DeviceValue::get_name(entity_id);
obj["m"] = mask;
obj["w"] = false;
}
}
break;
}
}
});
}
void EMSdevice::set_climate_minmax(uint8_t tag, int16_t min, uint16_t max) {
@@ -1057,14 +1079,9 @@ void EMSdevice::setCustomEntity(const std::string & entity_id) {
}
// extra shortname
std::string shortname;
auto custom_name_pos = entity_id.find('|');
bool has_custom_name = (custom_name_pos != std::string::npos);
if (has_custom_name) {
shortname = entity_id.substr(2, custom_name_pos - 2);
} else {
shortname = entity_id.substr(2);
}
std::string shortname = has_custom_name ? entity_id.substr(2, custom_name_pos - 2) : entity_id.substr(2);
if (entity_name == shortname) {
// check the masks
@@ -1106,10 +1123,25 @@ void EMSdevice::setCustomEntity(const std::string & entity_id) {
// populate a string vector with entities that have masks set or have a custom name
void EMSdevice::getCustomEntities(std::vector<std::string> & entity_ids) {
for (const auto & dv : devicevalues_) {
std::string entity_name = dv.tag < DeviceValueTAG::TAG_HC1 ? dv.short_name : std::string(tag_to_mqtt(dv.tag)) + "/" + dv.short_name;
uint8_t mask = dv.state >> 4;
char name[100];
name[0] = '\0';
if (dv.has_tag()) {
// prefix tag
strcpy(name, tag_to_mqtt(dv.tag));
strcat(name, "/");
}
strcat(name, dv.short_name);
std::string entity_name = name;
if (mask || !dv.custom_fullname.empty()) {
uint8_t mask = dv.state >> 4;
bool is_set = false;
for (auto & eid : entity_ids) {
if (DeviceValue::get_name(eid) == entity_name) {
is_set = true;
break;
}
}
if (!is_set && (mask || !dv.custom_fullname.empty())) {
if (dv.custom_fullname.empty()) {
entity_ids.push_back(Helpers::hextoa(mask, false) + entity_name);
} else {

View File

@@ -379,4 +379,12 @@ std::string DeviceValue::get_fullname() const {
return customname;
}
std::string DeviceValue::get_name(std::string & entity) {
auto pos = entity.find('|');
if (pos != std::string::npos) {
return entity.substr(2, pos - 2);
}
return entity.substr(2);
}
} // namespace emsesp

View File

@@ -191,6 +191,7 @@ class DeviceValue {
bool get_custom_max(uint16_t & val);
std::string get_custom_fullname() const;
std::string get_fullname() const;
static std::string get_name(std::string & entity);
// dv state flags
void add_state(uint8_t s) {

View File

@@ -268,8 +268,8 @@ MAKE_PSTR_ENUM(enum_summer, FL_(winter), FL_(summer))
MAKE_PSTR_ENUM(enum_operatingstate, FL_(heating), FL_(off), FL_(cooling))
MAKE_PSTR_ENUM(enum_mode, FL_(manual), FL_(auto)) // RC100, RC300, RC310
MAKE_PSTR_ENUM(enum_mode2, FL_(off), FL_(manual), FL_(auto)) // RC20
MAKE_PSTR_ENUM(enum_mode3, FL_(night), FL_(day), FL_(auto)) // RC35, RC30, RC25
MAKE_PSTR_ENUM(enum_mode2, FL_(off), FL_(manual), FL_(auto)) // RC20, RC30
MAKE_PSTR_ENUM(enum_mode3, FL_(night), FL_(day), FL_(auto)) // RC35, RC30_N, RC25, RC20_N
MAKE_PSTR_ENUM(enum_mode4, FL_(nofrost), FL_(eco), FL_(heat), FL_(auto)) // JUNKERS
MAKE_PSTR_ENUM(enum_mode5, FL_(auto), FL_(off)) // CRF
MAKE_PSTR_ENUM(enum_mode6, FL_(nofrost), FL_(night), FL_(day)) // RC10

View File

@@ -635,10 +635,7 @@ void Mqtt::ha_status() {
dev["mf"] = "proddy";
dev["mdl"] = "EMS-ESP";
#ifndef EMSESP_STANDALONE
if (EMSESP::system_.ethernet_connected())
dev["cu"] = "http://" + ETH.localIP().toString();
else
dev["cu"] = "http://" + WiFi.localIP().toString();
dev["cu"] = "http://" + (EMSESP::system_.ethernet_connected() ? ETH.localIP().toString() : WiFi.localIP().toString());
#endif
JsonArray ids = dev.createNestedArray("ids");
ids.add("ems-esp");

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.5.0-tec.1"
#define EMSESP_APP_VERSION "3.5.0-tec.2"

View File

@@ -235,6 +235,7 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request, J
// saves it in the customization service
// and updates the entity list real-time
void WebCustomizationService::custom_entities(AsyncWebServerRequest * request, JsonVariant & json) {
bool need_reboot = false;
if (json.is<JsonObject>()) {
// find the device using the unique_id
for (const auto & emsdevice : EMSESP::emsdevices) {
@@ -246,9 +247,45 @@ void WebCustomizationService::custom_entities(AsyncWebServerRequest * request, J
// and set the mask and custom names immediately for any listed entities
JsonArray entity_ids_json = json["entity_ids"];
std::vector<std::string> entity_ids;
for (const JsonVariant id : entity_ids_json) {
emsdevice->setCustomEntity(id.as<std::string>());
std::string id_s = id.as<std::string>();
if (id_s[0] == '8') {
entity_ids.push_back(id_s);
need_reboot = true;
} else {
emsdevice->setCustomEntity(id_s);
}
// emsesp::EMSESP::logger().info(id.as<const char *>());
}
// add deleted entities from file
EMSESP::webCustomizationService.read([&](WebCustomization & settings) {
for (EntityCustomization entityCustomization : settings.entityCustomizations) {
if (entityCustomization.device_id == device_id) {
for (std::string entity_id : entityCustomization.entity_ids) {
uint8_t mask = Helpers::hextoint(entity_id.substr(0, 2).c_str());
std::string name = DeviceValue::get_name(entity_id);
if (mask & 0x80) {
bool is_set = false;
for (const JsonVariant id : entity_ids_json) {
std::string id_s = id.as<std::string>();
if (name == DeviceValue::get_name(id_s)) {
is_set = true;
need_reboot = true;
break;
}
}
if (!is_set) {
entity_ids.push_back(entity_id);
}
}
}
break;
}
}
});
// get list of entities that have masks set or a custom fullname
emsdevice->getCustomEntities(entity_ids);
// Save the list to the customization file
EMSESP::webCustomizationService.update(
@@ -263,18 +300,11 @@ void WebCustomizationService::custom_entities(AsyncWebServerRequest * request, J
}
}
if (!entity_ids_json.size()) {
return StateUpdateResult::UNCHANGED; // nothing to add
}
// create a new entry for this device if there are values
EntityCustomization new_entry;
new_entry.product_id = product_id;
new_entry.device_id = device_id;
// get list of entities that have masks set or a custom fullname
std::vector<std::string> entity_ids;
emsdevice->getCustomEntities(entity_ids);
new_entry.entity_ids = entity_ids;
// add the record and save
@@ -289,7 +319,7 @@ void WebCustomizationService::custom_entities(AsyncWebServerRequest * request, J
}
}
AsyncWebServerResponse * response = request->beginResponse(200); // OK
AsyncWebServerResponse * response = request->beginResponse(need_reboot ? 201 : 200); // OK
request->send(response);
}