mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 16:29:51 +03:00
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
||||||
- Translations in Web UI and all device entity names (DE, NL, SE, PL, NO, ...) [#22](https://github.com/emsesp/EMS-ESP32/issues/22)
|
- Translations in Web UI and all device entity names (DE, NL, SE, PL, NO) [#22](https://github.com/emsesp/EMS-ESP32/issues/22)
|
||||||
- Add support for Lolin C3 mini [#620](https://github.com/emsesp/EMS-ESP32/pull/620)
|
- Add support for Lolin C3 mini [#620](https://github.com/emsesp/EMS-ESP32/pull/620)
|
||||||
- Add support for ESP32-S2 [#667](https://github.com/emsesp/EMS-ESP32/pull/667)
|
- Add support for ESP32-S2 [#667](https://github.com/emsesp/EMS-ESP32/pull/667)
|
||||||
- Add devices: Greenstar 30Ri boiler, Junkers FW500 thermostat, Buderus BC30 controller
|
- Add devices: Greenstar 30Ri boiler, Junkers FW500 thermostat, Buderus BC30 controller
|
||||||
@@ -17,8 +17,9 @@
|
|||||||
- Add min/max to customization table [#686](https://github.com/emsesp/EMS-ESP32/issues/686)
|
- Add min/max to customization table [#686](https://github.com/emsesp/EMS-ESP32/issues/686)
|
||||||
- Add MD5 check [#637](https://github.com/emsesp/EMS-ESP32/issues/637)
|
- Add MD5 check [#637](https://github.com/emsesp/EMS-ESP32/issues/637)
|
||||||
- Add more bus-ids [#673](https://github.com/emsesp/EMS-ESP32/issues/673)
|
- Add more bus-ids [#673](https://github.com/emsesp/EMS-ESP32/issues/673)
|
||||||
- Use HA connectivity device class for Status [#751](https://github.com/emsesp/EMS-ESP32/issues/751)
|
- Use HA connectivity device class for Status, added boot time [#751](https://github.com/emsesp/EMS-ESP32/issues/751)
|
||||||
- Add commands for analog sensors outputs
|
- Add commands for analog sensors outputs
|
||||||
|
- Support for multiple EMS-ESPs with MQTT and HA [[#759](https://github.com/emsesp/EMS-ESP32/issues/759)]
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
@@ -29,11 +30,13 @@
|
|||||||
- 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 `_`
|
- 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
|
- RF room temperature sensor are shown as thermostat
|
||||||
- render mqtt float json values with trailing zero
|
- render mqtt float json values with trailing zero
|
||||||
- removed flash strings
|
- removed flash strings, to increase available heap memory
|
||||||
- reload page after restart button is pressed
|
- reload page after restart button is pressed
|
||||||
- analog/dallas values command as list like ems-devices
|
- analog/dallas values command as list like ems-devices
|
||||||
- analog/dallas HA-entities based on id
|
- analog/dallas HA-entities based on id
|
||||||
|
- MQTT Base is a mandatory field. Removed MQTT topic length from settings.
|
||||||
|
|
||||||
## **BREAKING CHANGES:**
|
## **BREAKING CHANGES:**
|
||||||
|
|
||||||
- When upgrading from 3.4.x you may need to erase the flash on the ESP32 before uploading the firmware. Make sure you make a backup of the settings and customizations via the WebUI (System->Upload/Download)
|
- When upgrading for the first time from 3.4.x on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases). Make sure you make a backup of the settings and customizations via the WebUI (System->Upload/Download).
|
||||||
|
- Because of #759 the Home Assistant entity IDs have been renamed
|
||||||
|
|||||||
106
interface/package-lock.json
generated
106
interface/package-lock.json
generated
@@ -14,9 +14,9 @@
|
|||||||
"@mui/icons-material": "^5.10.16",
|
"@mui/icons-material": "^5.10.16",
|
||||||
"@mui/material": "^5.10.16",
|
"@mui/material": "^5.10.16",
|
||||||
"@table-library/react-table-library": "4.0.23",
|
"@table-library/react-table-library": "4.0.23",
|
||||||
"@types/lodash": "^4.14.190",
|
"@types/lodash": "^4.14.191",
|
||||||
"@types/node": "^18.11.9",
|
"@types/node": "^18.11.10",
|
||||||
"@types/react": "^18.0.25",
|
"@types/react": "^18.0.26",
|
||||||
"@types/react-dom": "^18.0.9",
|
"@types/react-dom": "^18.0.9",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"async-validator": "^4.2.5",
|
"async-validator": "^4.2.5",
|
||||||
@@ -30,8 +30,8 @@
|
|||||||
"react-app-rewired": "^2.2.1",
|
"react-app-rewired": "^2.2.1",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-dropzone": "^14.2.3",
|
"react-dropzone": "^14.2.3",
|
||||||
"react-icons": "^4.6.0",
|
"react-icons": "^4.7.1",
|
||||||
"react-router-dom": "^6.4.3",
|
"react-router-dom": "^6.4.4",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"sockette": "^2.0.6",
|
"sockette": "^2.0.6",
|
||||||
"typesafe-i18n": "^5.17.1",
|
"typesafe-i18n": "^5.17.1",
|
||||||
@@ -3458,9 +3458,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@remix-run/router": {
|
"node_modules/@remix-run/router": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.4.tgz",
|
||||||
"integrity": "sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q==",
|
"integrity": "sha512-gTL8H5USTAKOyVA4xczzDJnC3HMssdFa3tRlwBicXynx9XfiXwneHnYQogwSKpdCkjXISrEKSTtX62rLpNEVQg==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
@@ -4007,9 +4007,9 @@
|
|||||||
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
|
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/lodash": {
|
"node_modules/@types/lodash": {
|
||||||
"version": "4.14.190",
|
"version": "4.14.191",
|
||||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.190.tgz",
|
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz",
|
||||||
"integrity": "sha512-5iJ3FBJBvQHQ8sFhEhJfjUP+G+LalhavTkYyrAYqz5MEJG+erSv0k9KJLb6q7++17Lafk1scaTIFXcMJlwK8Mw=="
|
"integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/mime": {
|
"node_modules/@types/mime": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
@@ -4017,9 +4017,9 @@
|
|||||||
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
|
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "18.11.9",
|
"version": "18.11.10",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz",
|
||||||
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg=="
|
"integrity": "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/parse-json": {
|
"node_modules/@types/parse-json": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
@@ -4052,9 +4052,9 @@
|
|||||||
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
|
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/react": {
|
"node_modules/@types/react": {
|
||||||
"version": "18.0.25",
|
"version": "18.0.26",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.25.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz",
|
||||||
"integrity": "sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g==",
|
"integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/prop-types": "*",
|
"@types/prop-types": "*",
|
||||||
"@types/scheduler": "*",
|
"@types/scheduler": "*",
|
||||||
@@ -14540,9 +14540,9 @@
|
|||||||
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
|
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
|
||||||
},
|
},
|
||||||
"node_modules/react-icons": {
|
"node_modules/react-icons": {
|
||||||
"version": "4.6.0",
|
"version": "4.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.7.1.tgz",
|
||||||
"integrity": "sha512-rR/L9m9340yO8yv1QT1QurxWQvWpbNHqVX0fzMln2HEb9TEIrQRGsqiNFQfiv9/JEUbyHmHPlNTB2LWm2Ttz0g==",
|
"integrity": "sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "*"
|
"react": "*"
|
||||||
}
|
}
|
||||||
@@ -14561,11 +14561,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "6.4.3",
|
"version": "6.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.4.tgz",
|
||||||
"integrity": "sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA==",
|
"integrity": "sha512-SA6tSrUCRfuLWeYsTJDuriRqfFIsrSvuH7SqAJHegx9ZgxadE119rU8oOX/rG5FYEthpdEaEljdjDlnBxvfr+Q==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/router": "1.0.3"
|
"@remix-run/router": "1.0.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
@@ -14575,12 +14575,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router-dom": {
|
"node_modules/react-router-dom": {
|
||||||
"version": "6.4.3",
|
"version": "6.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.4.tgz",
|
||||||
"integrity": "sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ==",
|
"integrity": "sha512-0Axverhw5d+4SBhLqLpzPhNkmv7gahUwlUVIOrRLGJ4/uwt30JVajVJXqv2Qr/LCwyvHhQc7YyK1Do8a9Jj7qA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/router": "1.0.3",
|
"@remix-run/router": "1.0.4",
|
||||||
"react-router": "6.4.3"
|
"react-router": "6.4.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
@@ -19816,9 +19816,9 @@
|
|||||||
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw=="
|
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw=="
|
||||||
},
|
},
|
||||||
"@remix-run/router": {
|
"@remix-run/router": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.4.tgz",
|
||||||
"integrity": "sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q=="
|
"integrity": "sha512-gTL8H5USTAKOyVA4xczzDJnC3HMssdFa3tRlwBicXynx9XfiXwneHnYQogwSKpdCkjXISrEKSTtX62rLpNEVQg=="
|
||||||
},
|
},
|
||||||
"@rollup/plugin-babel": {
|
"@rollup/plugin-babel": {
|
||||||
"version": "5.3.1",
|
"version": "5.3.1",
|
||||||
@@ -20220,9 +20220,9 @@
|
|||||||
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
|
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
|
||||||
},
|
},
|
||||||
"@types/lodash": {
|
"@types/lodash": {
|
||||||
"version": "4.14.190",
|
"version": "4.14.191",
|
||||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.190.tgz",
|
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz",
|
||||||
"integrity": "sha512-5iJ3FBJBvQHQ8sFhEhJfjUP+G+LalhavTkYyrAYqz5MEJG+erSv0k9KJLb6q7++17Lafk1scaTIFXcMJlwK8Mw=="
|
"integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ=="
|
||||||
},
|
},
|
||||||
"@types/mime": {
|
"@types/mime": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
@@ -20230,9 +20230,9 @@
|
|||||||
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
|
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
|
||||||
},
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "18.11.9",
|
"version": "18.11.10",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz",
|
||||||
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg=="
|
"integrity": "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ=="
|
||||||
},
|
},
|
||||||
"@types/parse-json": {
|
"@types/parse-json": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
@@ -20265,9 +20265,9 @@
|
|||||||
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
|
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
|
||||||
},
|
},
|
||||||
"@types/react": {
|
"@types/react": {
|
||||||
"version": "18.0.25",
|
"version": "18.0.26",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.25.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz",
|
||||||
"integrity": "sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g==",
|
"integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/prop-types": "*",
|
"@types/prop-types": "*",
|
||||||
"@types/scheduler": "*",
|
"@types/scheduler": "*",
|
||||||
@@ -27705,9 +27705,9 @@
|
|||||||
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
|
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
|
||||||
},
|
},
|
||||||
"react-icons": {
|
"react-icons": {
|
||||||
"version": "4.6.0",
|
"version": "4.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.7.1.tgz",
|
||||||
"integrity": "sha512-rR/L9m9340yO8yv1QT1QurxWQvWpbNHqVX0fzMln2HEb9TEIrQRGsqiNFQfiv9/JEUbyHmHPlNTB2LWm2Ttz0g==",
|
"integrity": "sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==",
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
"react-is": {
|
"react-is": {
|
||||||
@@ -27721,20 +27721,20 @@
|
|||||||
"integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A=="
|
"integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A=="
|
||||||
},
|
},
|
||||||
"react-router": {
|
"react-router": {
|
||||||
"version": "6.4.3",
|
"version": "6.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.4.tgz",
|
||||||
"integrity": "sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA==",
|
"integrity": "sha512-SA6tSrUCRfuLWeYsTJDuriRqfFIsrSvuH7SqAJHegx9ZgxadE119rU8oOX/rG5FYEthpdEaEljdjDlnBxvfr+Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@remix-run/router": "1.0.3"
|
"@remix-run/router": "1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-router-dom": {
|
"react-router-dom": {
|
||||||
"version": "6.4.3",
|
"version": "6.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.4.tgz",
|
||||||
"integrity": "sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ==",
|
"integrity": "sha512-0Axverhw5d+4SBhLqLpzPhNkmv7gahUwlUVIOrRLGJ4/uwt30JVajVJXqv2Qr/LCwyvHhQc7YyK1Do8a9Jj7qA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@remix-run/router": "1.0.3",
|
"@remix-run/router": "1.0.4",
|
||||||
"react-router": "6.4.3"
|
"react-router": "6.4.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-scripts": {
|
"react-scripts": {
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
"@mui/icons-material": "^5.10.16",
|
"@mui/icons-material": "^5.10.16",
|
||||||
"@mui/material": "^5.10.16",
|
"@mui/material": "^5.10.16",
|
||||||
"@table-library/react-table-library": "4.0.23",
|
"@table-library/react-table-library": "4.0.23",
|
||||||
"@types/lodash": "^4.14.190",
|
"@types/lodash": "^4.14.191",
|
||||||
"@types/node": "^18.11.9",
|
"@types/node": "^18.11.10",
|
||||||
"@types/react": "^18.0.25",
|
"@types/react": "^18.0.26",
|
||||||
"@types/react-dom": "^18.0.9",
|
"@types/react-dom": "^18.0.9",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"async-validator": "^4.2.5",
|
"async-validator": "^4.2.5",
|
||||||
@@ -26,8 +26,8 @@
|
|||||||
"react-app-rewired": "^2.2.1",
|
"react-app-rewired": "^2.2.1",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-dropzone": "^14.2.3",
|
"react-dropzone": "^14.2.3",
|
||||||
"react-icons": "^4.6.0",
|
"react-icons": "^4.7.1",
|
||||||
"react-router-dom": "^6.4.3",
|
"react-router-dom": "^6.4.4",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"sockette": "^2.0.6",
|
"sockette": "^2.0.6",
|
||||||
"typesafe-i18n": "^5.17.1",
|
"typesafe-i18n": "^5.17.1",
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const de: Translation = {
|
|||||||
PRODUCT: 'Produkt',
|
PRODUCT: 'Produkt',
|
||||||
VERSION: 'Version',
|
VERSION: 'Version',
|
||||||
ENTITY_NAME: 'Entitätsname',
|
ENTITY_NAME: 'Entitätsname',
|
||||||
VALUE: 'Wert',
|
VALUE: '{{Wert|wert}}',
|
||||||
SHOW_FAV: 'nur Favoriten anzeigen',
|
SHOW_FAV: 'nur Favoriten anzeigen',
|
||||||
DEVICE_SENSOR_DATA: 'Geräte- und Sensordaten',
|
DEVICE_SENSOR_DATA: 'Geräte- und Sensordaten',
|
||||||
DEVICES_SENSORS: 'Geräte & Sensoren',
|
DEVICES_SENSORS: 'Geräte & Sensoren',
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const en: Translation = {
|
|||||||
VERSION: 'Version',
|
VERSION: 'Version',
|
||||||
BRAND: 'Brand',
|
BRAND: 'Brand',
|
||||||
ENTITY_NAME: 'Entity Name',
|
ENTITY_NAME: 'Entity Name',
|
||||||
VALUE: 'Value',
|
VALUE: '{{Value|value}}',
|
||||||
SHOW_FAV: 'only show favorites',
|
SHOW_FAV: 'only show favorites',
|
||||||
DEVICE_SENSOR_DATA: 'Device and Sensor Data',
|
DEVICE_SENSOR_DATA: 'Device and Sensor Data',
|
||||||
DEVICES_SENSORS: 'Devices & Sensors',
|
DEVICES_SENSORS: 'Devices & Sensors',
|
||||||
|
|||||||
@@ -100,8 +100,8 @@ const nl: Translation = {
|
|||||||
NUM_ANALOG_SENSORS: '{num} Analoge sensor{{en}}',
|
NUM_ANALOG_SENSORS: '{num} Analoge sensor{{en}}',
|
||||||
NUM_DAYS: '{num} dag{{en}}',
|
NUM_DAYS: '{num} dag{{en}}',
|
||||||
NUM_SECONDS: '{num} second{{en}}',
|
NUM_SECONDS: '{num} second{{en}}',
|
||||||
NUM_HOURS: '{num} uur{{en}}',
|
NUM_HOURS: '{num} {{uur|uren}}',
|
||||||
NUM_MINUTES: '{num} minuut{{en}}',
|
NUM_MINUTES: '{num} minute{{n}}',
|
||||||
APPLICATION_SETTINGS: 'Applicatieinstellingen',
|
APPLICATION_SETTINGS: 'Applicatieinstellingen',
|
||||||
CUSTOMIZATION: 'Custom aanpassingen',
|
CUSTOMIZATION: 'Custom aanpassingen',
|
||||||
APPLICATION_RESTARTING: 'EMS-ESP herstarten',
|
APPLICATION_RESTARTING: 'EMS-ESP herstarten',
|
||||||
|
|||||||
@@ -72,11 +72,11 @@ export const createSettingsValidator = (settings: Settings) =>
|
|||||||
syslog_host: [{ required: true, message: 'Host is required' }, IP_OR_HOSTNAME_VALIDATOR],
|
syslog_host: [{ required: true, message: 'Host is required' }, IP_OR_HOSTNAME_VALIDATOR],
|
||||||
syslog_port: [
|
syslog_port: [
|
||||||
{ required: true, message: 'Port is required' },
|
{ required: true, message: 'Port is required' },
|
||||||
{ type: 'number', min: 0, max: 65535, message: 'Port must be between 0 and 65535' }
|
{ type: 'number', min: 0, max: 65535, message: 'Invalid Port' }
|
||||||
],
|
],
|
||||||
syslog_mark_interval: [
|
syslog_mark_interval: [
|
||||||
{ required: true, message: 'Mark interval is required' },
|
{ required: true, message: 'Mark interval is required' },
|
||||||
{ type: 'number', min: 0, max: 10, message: 'Port must be between 0 and 10' }
|
{ type: 'number', min: 0, max: 10, message: ' must be between 0 and 10' }
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
...(settings.shower_alert && {
|
...(settings.shower_alert && {
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ export interface MqttSettings {
|
|||||||
client_id: string;
|
client_id: string;
|
||||||
keep_alive: number;
|
keep_alive: number;
|
||||||
clean_session: boolean;
|
clean_session: boolean;
|
||||||
max_topic_length: number;
|
|
||||||
publish_time_boiler: number;
|
publish_time_boiler: number;
|
||||||
publish_time_thermostat: number;
|
publish_time_thermostat: number;
|
||||||
publish_time_solar: number;
|
publish_time_solar: number;
|
||||||
|
|||||||
@@ -3,16 +3,13 @@ import { IP_OR_HOSTNAME_VALIDATOR } from './shared';
|
|||||||
|
|
||||||
export const MQTT_SETTINGS_VALIDATOR = new Schema({
|
export const MQTT_SETTINGS_VALIDATOR = new Schema({
|
||||||
host: [{ required: true, message: 'Host is required' }, IP_OR_HOSTNAME_VALIDATOR],
|
host: [{ required: true, message: 'Host is required' }, IP_OR_HOSTNAME_VALIDATOR],
|
||||||
|
base: { required: true, message: 'Base is required' },
|
||||||
port: [
|
port: [
|
||||||
{ required: true, message: 'Port is required' },
|
{ required: true, message: 'Port is required' },
|
||||||
{ type: 'number', min: 0, max: 65535, message: 'Port must be between 0 and 65535' }
|
{ type: 'number', min: 0, max: 65535, message: 'Invalid Port' }
|
||||||
],
|
],
|
||||||
keep_alive: [
|
keep_alive: [
|
||||||
{ required: true, message: 'Keep alive is required' },
|
{ required: true, message: 'Keep alive is required' },
|
||||||
{ type: 'number', min: 1, max: 86400, message: 'Keep alive must be between 1 and 86400' }
|
{ type: 'number', min: 1, max: 86400, message: 'Keep alive must be between 1 and 86400' }
|
||||||
],
|
|
||||||
max_topic_length: [
|
|
||||||
{ required: true, message: 'Max topic length is required' },
|
|
||||||
{ type: 'number', min: 16, max: 1024, message: 'Max topic length must be between 16 and 1024' }
|
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -145,16 +145,15 @@ void MqttSettingsService::configureMqtt() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MqttSettings::read(MqttSettings & settings, JsonObject & root) {
|
void MqttSettings::read(MqttSettings & settings, JsonObject & root) {
|
||||||
root["enabled"] = settings.enabled;
|
root["enabled"] = settings.enabled;
|
||||||
root["host"] = settings.host;
|
root["host"] = settings.host;
|
||||||
root["port"] = settings.port;
|
root["port"] = settings.port;
|
||||||
root["base"] = settings.base;
|
root["base"] = settings.base;
|
||||||
root["username"] = settings.username;
|
root["username"] = settings.username;
|
||||||
root["password"] = settings.password;
|
root["password"] = settings.password;
|
||||||
root["client_id"] = settings.clientId;
|
root["client_id"] = settings.clientId;
|
||||||
root["keep_alive"] = settings.keepAlive;
|
root["keep_alive"] = settings.keepAlive;
|
||||||
root["clean_session"] = settings.cleanSession;
|
root["clean_session"] = settings.cleanSession;
|
||||||
root["max_topic_length"] = settings.maxTopicLength;
|
|
||||||
|
|
||||||
// added by proddy for EMS-ESP
|
// added by proddy for EMS-ESP
|
||||||
root["publish_time_boiler"] = settings.publish_time_boiler;
|
root["publish_time_boiler"] = settings.publish_time_boiler;
|
||||||
@@ -177,18 +176,19 @@ StateUpdateResult MqttSettings::update(JsonObject & root, MqttSettings & setting
|
|||||||
MqttSettings newSettings = {};
|
MqttSettings newSettings = {};
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
newSettings.enabled = root["enabled"] | FACTORY_MQTT_ENABLED;
|
newSettings.enabled = root["enabled"] | FACTORY_MQTT_ENABLED;
|
||||||
newSettings.host = root["host"] | FACTORY_MQTT_HOST;
|
newSettings.host = root["host"] | FACTORY_MQTT_HOST;
|
||||||
newSettings.port = root["port"] | FACTORY_MQTT_PORT;
|
newSettings.port = root["port"] | FACTORY_MQTT_PORT;
|
||||||
newSettings.base = root["base"] | FACTORY_MQTT_BASE;
|
newSettings.base = root["base"] | FACTORY_MQTT_BASE;
|
||||||
newSettings.username = root["username"] | FACTORY_MQTT_USERNAME;
|
newSettings.username = root["username"] | FACTORY_MQTT_USERNAME;
|
||||||
newSettings.password = root["password"] | FACTORY_MQTT_PASSWORD;
|
newSettings.password = root["password"] | FACTORY_MQTT_PASSWORD;
|
||||||
newSettings.clientId = root["client_id"] | FACTORY_MQTT_CLIENT_ID;
|
newSettings.clientId = root["client_id"] | FACTORY_MQTT_CLIENT_ID;
|
||||||
newSettings.keepAlive = root["keep_alive"] | FACTORY_MQTT_KEEP_ALIVE;
|
newSettings.keepAlive = root["keep_alive"] | FACTORY_MQTT_KEEP_ALIVE;
|
||||||
newSettings.cleanSession = root["clean_session"] | FACTORY_MQTT_CLEAN_SESSION;
|
newSettings.cleanSession = root["clean_session"] | FACTORY_MQTT_CLEAN_SESSION;
|
||||||
newSettings.maxTopicLength = root["max_topic_length"] | FACTORY_MQTT_MAX_TOPIC_LENGTH;
|
newSettings.mqtt_qos = root["mqtt_qos"] | EMSESP_DEFAULT_MQTT_QOS;
|
||||||
newSettings.mqtt_qos = root["mqtt_qos"] | EMSESP_DEFAULT_MQTT_QOS;
|
newSettings.mqtt_retain = root["mqtt_retain"] | EMSESP_DEFAULT_MQTT_RETAIN;
|
||||||
newSettings.mqtt_retain = root["mqtt_retain"] | EMSESP_DEFAULT_MQTT_RETAIN;
|
|
||||||
|
newSettings.maxTopicLength = FACTORY_MQTT_MAX_TOPIC_LENGTH; // hardcode. We don't take this from the settings anymore.
|
||||||
|
|
||||||
newSettings.publish_time_boiler = root["publish_time_boiler"] | EMSESP_DEFAULT_PUBLISH_TIME;
|
newSettings.publish_time_boiler = root["publish_time_boiler"] | EMSESP_DEFAULT_PUBLISH_TIME;
|
||||||
newSettings.publish_time_thermostat = root["publish_time_thermostat"] | EMSESP_DEFAULT_PUBLISH_TIME;
|
newSettings.publish_time_thermostat = root["publish_time_thermostat"] | EMSESP_DEFAULT_PUBLISH_TIME;
|
||||||
|
|||||||
@@ -83,5 +83,5 @@ void NTPSettingsService::configureTime(AsyncWebServerRequest * request, JsonVari
|
|||||||
void NTPSettingsService::ntp_received(struct timeval * tv) {
|
void NTPSettingsService::ntp_received(struct timeval * tv) {
|
||||||
// emsesp::EMSESP::logger().info("NTP sync to %d sec", tv->tv_sec);
|
// emsesp::EMSESP::logger().info("NTP sync to %d sec", tv->tv_sec);
|
||||||
emsesp::EMSESP::system_.ntp_connected(true);
|
emsesp::EMSESP::system_.ntp_connected(true);
|
||||||
emsesp::EMSESP::system_.send_info_mqtt("connected");
|
emsesp::EMSESP::system_.send_info_mqtt("connected", true); // send info topic with NTP time
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,9 +29,12 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
|
|||||||
std::string extension = fname.substr(position + 1);
|
std::string extension = fname.substr(position + 1);
|
||||||
size_t fsize = request->contentLength();
|
size_t fsize = request->contentLength();
|
||||||
|
|
||||||
|
#ifdef EMSESP_DEBUG
|
||||||
#if defined(EMSESP_USE_SERIAL)
|
#if defined(EMSESP_USE_SERIAL)
|
||||||
|
Serial.println();
|
||||||
Serial.printf("Received filename: %s, len: %d, index: %d, ext: %s, fsize: %d", filename.c_str(), len, index, extension.c_str(), fsize);
|
Serial.printf("Received filename: %s, len: %d, index: %d, ext: %s, fsize: %d", filename.c_str(), len, index, extension.c_str(), fsize);
|
||||||
Serial.println();
|
Serial.println();
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
is_firmware = false;
|
is_firmware = false;
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class DummySettings {
|
|||||||
String base = "ems-esp";
|
String base = "ems-esp";
|
||||||
bool publish_single = false;
|
bool publish_single = false;
|
||||||
bool publish_single2cmd = false;
|
bool publish_single2cmd = false;
|
||||||
bool send_response = true;
|
bool send_response = false; // don't send response
|
||||||
String host = "192.168.1.4";
|
String host = "192.168.1.4";
|
||||||
uint16_t port = 1883;
|
uint16_t port = 1883;
|
||||||
String clientId = "ems-esp";
|
String clientId = "ems-esp";
|
||||||
|
|||||||
@@ -219,7 +219,6 @@ mqtt_settings = {
|
|||||||
client_id: 'ems-esp',
|
client_id: 'ems-esp',
|
||||||
keep_alive: 60,
|
keep_alive: 60,
|
||||||
clean_session: true,
|
clean_session: true,
|
||||||
max_topic_length: 128,
|
|
||||||
publish_time_boiler: 10,
|
publish_time_boiler: 10,
|
||||||
publish_time_thermostat: 10,
|
publish_time_thermostat: 10,
|
||||||
publish_time_solar: 10,
|
publish_time_solar: 10,
|
||||||
|
|||||||
6
package-lock.json
generated
Normal file
6
package-lock.json
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "EMS-ESP32",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {}
|
||||||
|
}
|
||||||
@@ -451,16 +451,13 @@ void AnalogSensor::publish_values(const bool force) {
|
|||||||
}
|
}
|
||||||
config["val_tpl"] = str;
|
config["val_tpl"] = str;
|
||||||
|
|
||||||
// snprintf(str, sizeof(str), "%s_analog_sensor_%s", Mqtt::basename().c_str(), sensor.name().c_str());
|
snprintf(str, sizeof(str), "%s_analog_sensor_%s", Mqtt::basename().c_str(), sensor.name().c_str());
|
||||||
snprintf(str, sizeof(str), "analog_sensor_%d", sensor.gpio());
|
|
||||||
config["object_id"] = str;
|
config["object_id"] = str;
|
||||||
|
config["uniq_id"] = str; // same as object_id
|
||||||
|
|
||||||
snprintf(str, sizeof(str), "%s", sensor.name().c_str());
|
snprintf(str, sizeof(str), "%s", sensor.name().c_str());
|
||||||
config["name"] = str;
|
config["name"] = str;
|
||||||
|
|
||||||
snprintf(str, sizeof(str), "analogsensor_%d", sensor.gpio());
|
|
||||||
config["uniq_id"] = str;
|
|
||||||
|
|
||||||
if (sensor.uom() != DeviceValueUOM::NONE) {
|
if (sensor.uom() != DeviceValueUOM::NONE) {
|
||||||
config["unit_of_meas"] = EMSdevice::uom_to_string(sensor.uom());
|
config["unit_of_meas"] = EMSdevice::uom_to_string(sensor.uom());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,8 +52,10 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EMSESP_DEBUG
|
||||||
#if defined(EMSESP_USE_SERIAL)
|
#if defined(EMSESP_USE_SERIAL)
|
||||||
// Serial.println(p.path().c_str()); // dump paths, for debugging
|
// Serial.println(p.path().c_str()); // dump paths, for debugging
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// re-calculate new path
|
// re-calculate new path
|
||||||
@@ -179,6 +181,8 @@ std::string Command::return_code_string(const uint8_t return_code) {
|
|||||||
return "Not Authorized";
|
return "Not Authorized";
|
||||||
case CommandRet::FAIL:
|
case CommandRet::FAIL:
|
||||||
return "Failed";
|
return "Failed";
|
||||||
|
case CommandRet::INVALID:
|
||||||
|
return "Invalid";
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -270,18 +274,22 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto description = Helpers::translated_word(cf->description_);
|
auto description = Helpers::translated_word(cf->description_);
|
||||||
|
char info_s[100];
|
||||||
|
if (strlen(description)) {
|
||||||
|
snprintf(info_s, sizeof(info_s), "'%s/%s' (%s)", dname, cmd, description);
|
||||||
|
} else {
|
||||||
|
snprintf(info_s, sizeof(info_s), "'%s/%s'", dname, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ro = EMSESP::system_.readonly_mode() ? "[readonly] " : "";
|
||||||
|
|
||||||
if ((value == nullptr) || (strlen(value) == 0)) {
|
if ((value == nullptr) || (strlen(value) == 0)) {
|
||||||
if (EMSESP::system_.readonly_mode()) {
|
LOG_INFO(("%sCalling command %s"), ro.c_str(), info_s);
|
||||||
LOG_INFO(("[readonly] Calling command '%s/%s' (%s)"), dname, cmd, description);
|
|
||||||
} else {
|
|
||||||
LOG_DEBUG(("Calling command '%s/%s' (%s)"), dname, cmd, description);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (EMSESP::system_.readonly_mode()) {
|
if (id > 0) {
|
||||||
LOG_INFO(("[readonly] Calling command '%s/%s' (%s) with value %s"), dname, cmd, description, value);
|
LOG_INFO(("%sCalling command %s with value %s and id %d"), ro.c_str(), info_s, value, id);
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG(("Calling command '%s/%s' (%s) with value %s"), dname, cmd, description, value);
|
LOG_INFO(("%sCalling command %s with value %s"), ro.c_str(), info_s, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,8 +298,13 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
|||||||
return_code = ((cf->cmdfunction_json_)(value, id, output)) ? CommandRet::OK : CommandRet::ERROR;
|
return_code = ((cf->cmdfunction_json_)(value, id, output)) ? CommandRet::OK : CommandRet::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cf->cmdfunction_ && !EMSESP::cmd_is_readonly(device_type, cmd, id)) {
|
// check if read-only. This also checks for valid tags (e.g. heating circuits)
|
||||||
return_code = ((cf->cmdfunction_)(value, id)) ? CommandRet::OK : CommandRet::ERROR;
|
if (cf->cmdfunction_) {
|
||||||
|
if (EMSESP::cmd_is_readonly(device_type, cmd, id)) {
|
||||||
|
return_code = CommandRet::INVALID; // readonly or invalid hc
|
||||||
|
} else {
|
||||||
|
return_code = ((cf->cmdfunction_)(value, id)) ? CommandRet::OK : CommandRet::ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// report back
|
// report back
|
||||||
|
|||||||
@@ -40,12 +40,12 @@ enum CommandFlag : uint8_t {
|
|||||||
|
|
||||||
// return status after calling a Command
|
// return status after calling a Command
|
||||||
enum CommandRet : uint8_t {
|
enum CommandRet : uint8_t {
|
||||||
FAIL = 0, // 0 or FALSE
|
FAIL = 0, // 0 or FALSE
|
||||||
OK, // 1 or TRUE
|
OK, // 1 or TRUE
|
||||||
NOT_FOUND, // 2
|
NOT_FOUND, // 2
|
||||||
ERROR, // 3
|
ERROR, // 3
|
||||||
NOT_ALLOWED // needs authentication
|
NOT_ALLOWED, // 4 - needs authentication
|
||||||
|
INVALID // 5 - invalid (tag)
|
||||||
};
|
};
|
||||||
|
|
||||||
using cmd_function_p = std::function<bool(const char * data, const int8_t id)>;
|
using cmd_function_p = std::function<bool(const char * data, const int8_t id)>;
|
||||||
|
|||||||
@@ -518,18 +518,15 @@ void DallasSensor::publish_values(const bool force) {
|
|||||||
}
|
}
|
||||||
config["val_tpl"] = str;
|
config["val_tpl"] = str;
|
||||||
|
|
||||||
// snprintf(str, sizeof(str), "%s_temperature_sensor_%s", Mqtt::basename().c_str(), sensor.id().c_str());
|
snprintf(str, sizeof(str), "%s_temperature_sensor_%s", Mqtt::basename().c_str(), sensor.id().c_str());
|
||||||
snprintf(str, sizeof(str), "temperature_sensor_%s", sensor.id().c_str());
|
|
||||||
config["object_id"] = str;
|
config["object_id"] = str;
|
||||||
|
config["uniq_id"] = str; // same as object_id
|
||||||
|
|
||||||
snprintf(str, sizeof(str), "%s", sensor.name().c_str());
|
snprintf(str, sizeof(str), "%s", sensor.name().c_str());
|
||||||
config["name"] = str;
|
config["name"] = str;
|
||||||
|
|
||||||
snprintf(str, sizeof(str), "dallasensor_%s", sensor.id().c_str());
|
JsonObject dev = config.createNestedObject("dev");
|
||||||
config["uniq_id"] = str;
|
JsonArray ids = dev.createNestedArray("ids");
|
||||||
|
|
||||||
JsonObject dev = config.createNestedObject("dev");
|
|
||||||
JsonArray ids = dev.createNestedArray("ids");
|
|
||||||
ids.add("ems-esp");
|
ids.add("ems-esp");
|
||||||
|
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
|
|||||||
@@ -623,6 +623,7 @@ bool EMSdevice::is_readable(const void * value_p) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if value/command is readonly
|
// check if value/command is readonly
|
||||||
|
// matches valid tags too
|
||||||
bool EMSdevice::is_readonly(const std::string & cmd, const int8_t id) const {
|
bool EMSdevice::is_readonly(const std::string & cmd, const int8_t id) const {
|
||||||
uint8_t tag = id > 0 ? DeviceValueTAG::TAG_HC1 + id - 1 : DeviceValueTAG::TAG_NONE;
|
uint8_t tag = id > 0 ? DeviceValueTAG::TAG_HC1 + id - 1 : DeviceValueTAG::TAG_NONE;
|
||||||
for (const auto & dv : devicevalues_) {
|
for (const auto & dv : devicevalues_) {
|
||||||
|
|||||||
@@ -589,7 +589,7 @@ void EMSESP::publish_response(std::shared_ptr<const Telegram> telegram) {
|
|||||||
doc["value"] = value;
|
doc["value"] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mqtt::publish(F_(response), doc.as<JsonObject>());
|
Mqtt::publish("response", doc.as<JsonObject>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// builds json with the detail of each value, for a specific EMS device type or the dallas sensor
|
// builds json with the detail of each value, for a specific EMS device type or the dallas sensor
|
||||||
|
|||||||
112
src/mqtt.cpp
112
src/mqtt.cpp
@@ -280,6 +280,7 @@ void Mqtt::on_message(const char * topic, const char * payload, size_t len) cons
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for misconfigured mqtt servers and publish2command ignore echos
|
// for misconfigured mqtt servers and publish2command ignore echos
|
||||||
if (publish_single_ && publish_single2cmd_ && lasttopic_ == topic && lastpayload_ == message) {
|
if (publish_single_ && publish_single2cmd_ && lasttopic_ == topic && lastpayload_ == message) {
|
||||||
LOG_DEBUG("Received echo message %s: %s", topic, message);
|
LOG_DEBUG("Received echo message %s: %s", topic, message);
|
||||||
@@ -291,11 +292,12 @@ void Mqtt::on_message(const char * topic, const char * payload, size_t len) cons
|
|||||||
// add the base back
|
// add the base back
|
||||||
char full_topic[MQTT_TOPIC_MAX_SIZE];
|
char full_topic[MQTT_TOPIC_MAX_SIZE];
|
||||||
snprintf(full_topic, sizeof(full_topic), "%s/%s", mqtt_base_.c_str(), mf.topic_.c_str());
|
snprintf(full_topic, sizeof(full_topic), "%s/%s", mqtt_base_.c_str(), mf.topic_.c_str());
|
||||||
|
|
||||||
if ((!strcmp(topic, full_topic)) && (mf.mqtt_subfunction_)) {
|
if ((!strcmp(topic, full_topic)) && (mf.mqtt_subfunction_)) {
|
||||||
if (!(mf.mqtt_subfunction_)(message)) {
|
if (!(mf.mqtt_subfunction_)(message)) {
|
||||||
LOG_ERROR("error: invalid payload %s for this topic %s", message, topic);
|
LOG_ERROR("error: invalid payload %s for this topic %s", message, topic);
|
||||||
if (send_response_) {
|
if (send_response_) {
|
||||||
Mqtt::publish(F_(response), "error: invalid data");
|
Mqtt::publish("response", "error: invalid data");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -330,12 +332,12 @@ void Mqtt::on_message(const char * topic, const char * payload, size_t len) cons
|
|||||||
}
|
}
|
||||||
LOG_ERROR(error);
|
LOG_ERROR(error);
|
||||||
if (send_response_) {
|
if (send_response_) {
|
||||||
Mqtt::publish(F_(response), error);
|
Mqtt::publish("response", error);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// all good, send back json output from call
|
// all good, send back json output from call
|
||||||
if (send_response_) {
|
if (send_response_) {
|
||||||
Mqtt::publish(F_(response), output);
|
Mqtt::publish("response", output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -591,12 +593,12 @@ void Mqtt::on_connect() {
|
|||||||
void Mqtt::ha_status() {
|
void Mqtt::ha_status() {
|
||||||
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
||||||
|
|
||||||
doc["uniq_id"] = "ems-esp-system";
|
doc["uniq_id"] = "ems-esp-system";
|
||||||
doc["~"] = mqtt_base_; // default ems-esp
|
doc["object_id"] = "ems_esp_status";
|
||||||
|
doc["~"] = mqtt_base_; // default ems-esp
|
||||||
// doc["avty_t"] = "~/status"; // commented out, as it causes errors in HA sometimes
|
// doc["avty_t"] = "~/status"; // commented out, as it causes errors in HA sometimes
|
||||||
// doc["json_attr_t"] = "~/heartbeat"; // store also as HA attributes
|
// doc["json_attr_t"] = "~/heartbeat"; // store also as HA attributes
|
||||||
doc["stat_t"] = "~/status";
|
doc["stat_t"] = "~/status";
|
||||||
doc["object_id"] = "ems_esp_status";
|
|
||||||
doc["name"] = "EMS-ESP status";
|
doc["name"] = "EMS-ESP status";
|
||||||
doc["payload_on"] = "online";
|
doc["payload_on"] = "online";
|
||||||
doc["payload_off"] = "offline";
|
doc["payload_off"] = "offline";
|
||||||
@@ -904,7 +906,6 @@ void Mqtt::publish_ha_sensor_config(DeviceValue & dv, const std::string & model,
|
|||||||
publish_ha_sensor_config(dv.type,
|
publish_ha_sensor_config(dv.type,
|
||||||
dv.tag,
|
dv.tag,
|
||||||
dv.get_fullname().c_str(),
|
dv.get_fullname().c_str(),
|
||||||
(dv.fullname ? dv.fullname[0] : nullptr), // EN name
|
|
||||||
dv.device_type,
|
dv.device_type,
|
||||||
dv.short_name,
|
dv.short_name,
|
||||||
dv.uom,
|
dv.uom,
|
||||||
@@ -925,7 +926,7 @@ void Mqtt::publish_system_ha_sensor_config(uint8_t type, const char * name, cons
|
|||||||
JsonArray ids = dev_json.createNestedArray("ids");
|
JsonArray ids = dev_json.createNestedArray("ids");
|
||||||
ids.add("ems-esp");
|
ids.add("ems-esp");
|
||||||
|
|
||||||
publish_ha_sensor_config(type, DeviceValueTAG::TAG_HEARTBEAT, name, name, EMSdevice::DeviceType::SYSTEM, entity, uom, false, false, nullptr, 0, 0, 0, dev_json);
|
publish_ha_sensor_config(type, DeviceValueTAG::TAG_HEARTBEAT, name, EMSdevice::DeviceType::SYSTEM, entity, uom, false, false, nullptr, 0, 0, 0, dev_json);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MQTT discovery configs
|
// MQTT discovery configs
|
||||||
@@ -934,7 +935,6 @@ void Mqtt::publish_system_ha_sensor_config(uint8_t type, const char * name, cons
|
|||||||
void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdevice::DeviceValueType
|
void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdevice::DeviceValueType
|
||||||
uint8_t tag, // EMSdevice::DeviceValueTAG
|
uint8_t tag, // EMSdevice::DeviceValueTAG
|
||||||
const char * const fullname, // fullname, already translated
|
const char * const fullname, // fullname, already translated
|
||||||
const char * const en_name, // original name
|
|
||||||
const uint8_t device_type, // EMSdevice::DeviceType
|
const uint8_t device_type, // EMSdevice::DeviceType
|
||||||
const char * const entity, // same as shortname
|
const char * const entity, // same as shortname
|
||||||
const uint8_t uom, // EMSdevice::DeviceValueUOM (0=NONE)
|
const uint8_t uom, // EMSdevice::DeviceValueUOM (0=NONE)
|
||||||
@@ -946,25 +946,29 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
const int16_t dv_set_max,
|
const int16_t dv_set_max,
|
||||||
const JsonObject & dev_json) {
|
const JsonObject & dev_json) {
|
||||||
// ignore if name (fullname) is empty
|
// ignore if name (fullname) is empty
|
||||||
if (fullname == nullptr || en_name == nullptr) {
|
if (!fullname) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the device name
|
// create the device name
|
||||||
auto device_name = EMSdevice::device_type_2_device_name(device_type);
|
auto device_name = EMSdevice::device_type_2_device_name(device_type);
|
||||||
|
|
||||||
// create entity by add the hc/wwc tag if present, separating with a .
|
// create entity by add the hc/wwc tag if present, separating with a _
|
||||||
char new_entity[50];
|
char entity_with_tag[50];
|
||||||
if (tag >= DeviceValueTAG::TAG_HC1) {
|
if (tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
snprintf(new_entity, sizeof(new_entity), "%s.%s", EMSdevice::tag_to_mqtt(tag).c_str(), entity);
|
snprintf(entity_with_tag, sizeof(entity_with_tag), "%s_%s", EMSdevice::tag_to_mqtt(tag).c_str(), entity);
|
||||||
} else {
|
} else {
|
||||||
snprintf(new_entity, sizeof(new_entity), "%s", entity);
|
snprintf(entity_with_tag, sizeof(entity_with_tag), "%s", entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// build unique identifier which will be used in the topic, replacing all . with _ as not to break HA
|
// build unique identifier which will be used in the topic, also used as object_id
|
||||||
char uniq[101];
|
char uniq_id[70];
|
||||||
snprintf(uniq, sizeof(uniq), "%s_%s", device_name, new_entity);
|
snprintf(uniq_id, sizeof(uniq_id), "%s_%s_%s", mqtt_basename_.c_str(), device_name, entity_with_tag);
|
||||||
Helpers::replace_char(uniq, '.', '_');
|
|
||||||
|
// build a config topic that will be prefix onto a HA type (e.g. number, switch)
|
||||||
|
// e.g. homeassistant/number/ems-esp/thermostat_hc1_manualtemp
|
||||||
|
char config_topic[70];
|
||||||
|
snprintf(config_topic, sizeof(config_topic), "%s/%s_%s/config", mqtt_basename_.c_str(), device_name, entity_with_tag);
|
||||||
|
|
||||||
bool set_ha_classes = false; // set to true if we want to set the state class and device class
|
bool set_ha_classes = false; // set to true if we want to set the state class and device class
|
||||||
|
|
||||||
@@ -981,46 +985,43 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
case DeviceValueType::ULONG:
|
case DeviceValueType::ULONG:
|
||||||
// number - https://www.home-assistant.io/integrations/number.mqtt
|
// number - https://www.home-assistant.io/integrations/number.mqtt
|
||||||
// https://developers.home-assistant.io/docs/core/entity/number
|
// https://developers.home-assistant.io/docs/core/entity/number
|
||||||
snprintf(topic, sizeof(topic), "number/%s/%s/config", mqtt_basename_.c_str(), uniq);
|
snprintf(topic, sizeof(topic), "number/%s", config_topic);
|
||||||
break;
|
break;
|
||||||
case DeviceValueType::BOOL:
|
case DeviceValueType::BOOL:
|
||||||
// switch - https://www.home-assistant.io/integrations/switch.mqtt
|
// switch - https://www.home-assistant.io/integrations/switch.mqtt
|
||||||
snprintf(topic, sizeof(topic), "switch/%s/%s/config", mqtt_basename_.c_str(), uniq);
|
snprintf(topic, sizeof(topic), "switch/%s", config_topic);
|
||||||
break;
|
break;
|
||||||
case DeviceValueType::ENUM:
|
case DeviceValueType::ENUM:
|
||||||
// select - https://www.home-assistant.io/integrations/select.mqtt
|
// select - https://www.home-assistant.io/integrations/select.mqtt
|
||||||
snprintf(topic, sizeof(topic), "select/%s/%s/config", mqtt_basename_.c_str(), uniq);
|
snprintf(topic, sizeof(topic), "select/%s", config_topic);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// plain old sensor
|
// plain old sensor
|
||||||
snprintf(topic, sizeof(topic), "sensor/%s/%s/config", mqtt_basename_.c_str(), uniq);
|
snprintf(topic, sizeof(topic), "sensor/%s", config_topic);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// these are Read only sensors. We can set the device class and state class
|
set_ha_classes = true; // these are Read only sensors. We can set the device class and state class
|
||||||
set_ha_classes = true;
|
|
||||||
// plain old read only device entity
|
// plain old read only device entity
|
||||||
if (type == DeviceValueType::BOOL) {
|
if (type == DeviceValueType::BOOL) {
|
||||||
snprintf(topic, sizeof(topic), "binary_sensor/%s/%s/config", mqtt_basename_.c_str(), uniq); // binary sensor (for booleans)
|
snprintf(topic, sizeof(topic), "binary_sensor/%s", config_topic); // binary sensor (for booleans)
|
||||||
} else {
|
} else {
|
||||||
snprintf(topic, sizeof(topic), "sensor/%s/%s/config", mqtt_basename_.c_str(), uniq); // normal HA sensor
|
snprintf(topic, sizeof(topic), "sensor/%s", config_topic); // normal HA sensor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we're asking to remove this topic, send an empty payload and exit
|
// if we're asking to remove this topic, send an empty payload and exit
|
||||||
// https://github.com/emsesp/EMS-ESP32/issues/196
|
// https://github.com/emsesp/EMS-ESP32/issues/196
|
||||||
if (remove) {
|
if (remove) {
|
||||||
LOG_DEBUG("Removing HA config for %s", uniq);
|
LOG_DEBUG("Removing HA config for %s", uniq_id);
|
||||||
publish_ha(topic);
|
publish_ha(topic);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool have_tag = !EMSdevice::tag_to_string(tag).empty();
|
|
||||||
|
|
||||||
// build the payload
|
// build the payload
|
||||||
DynamicJsonDocument doc(EMSESP_JSON_SIZE_HA_CONFIG);
|
DynamicJsonDocument doc(EMSESP_JSON_SIZE_HA_CONFIG);
|
||||||
doc["~"] = mqtt_base_;
|
doc["uniq_id"] = uniq_id;
|
||||||
doc["uniq_id"] = uniq;
|
doc["object_id"] = uniq_id; // same as unique_id
|
||||||
|
|
||||||
const char * ic_ha = "ic"; // icon - only set this if there is no device class
|
const char * ic_ha = "ic"; // icon - only set this if there is no device class
|
||||||
const char * sc_ha = "state_class"; // state class
|
const char * sc_ha = "state_class"; // state class
|
||||||
@@ -1031,9 +1032,12 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
// note: there is no way to handle strings in HA so datetimes (e.g. set_datetime, set_holiday, set_wwswitchtime etc) are excluded
|
// note: there is no way to handle strings in HA so datetimes (e.g. set_datetime, set_holiday, set_wwswitchtime etc) are excluded
|
||||||
if (has_cmd) {
|
if (has_cmd) {
|
||||||
// command topic back to EMS-ESP
|
// command topic back to EMS-ESP
|
||||||
char command_topic[105];
|
char command_topic[MQTT_TOPIC_MAX_SIZE];
|
||||||
snprintf(command_topic, sizeof(command_topic), "~/%s", uniq);
|
if (tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
Helpers::replace_char(command_topic, '_', '/');
|
snprintf(command_topic, sizeof(command_topic), "%s/%s/%s/%s", mqtt_basename_.c_str(), device_name, EMSdevice::tag_to_mqtt(tag).c_str(), entity);
|
||||||
|
} else {
|
||||||
|
snprintf(command_topic, sizeof(command_topic), "%s/%s/%s", mqtt_basename_.c_str(), device_name, entity);
|
||||||
|
}
|
||||||
doc["command_topic"] = command_topic;
|
doc["command_topic"] = command_topic;
|
||||||
|
|
||||||
// for enums, add options
|
// for enums, add options
|
||||||
@@ -1075,38 +1079,30 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
|
|
||||||
// state topic
|
// state topic
|
||||||
char stat_t[MQTT_TOPIC_MAX_SIZE];
|
char stat_t[MQTT_TOPIC_MAX_SIZE];
|
||||||
snprintf(stat_t, sizeof(stat_t), "~/%s", tag_to_topic(device_type, tag).c_str());
|
snprintf(stat_t, sizeof(stat_t), "%s/%s", mqtt_basename_.c_str(), tag_to_topic(device_type, tag).c_str());
|
||||||
doc["stat_t"] = stat_t;
|
doc["stat_t"] = stat_t;
|
||||||
|
|
||||||
// friendly name = <tag> <name>
|
// friendly name = <tag> <name>
|
||||||
char ha_name[70];
|
char ha_name[70];
|
||||||
char * F_name = strdup(fullname);
|
char * F_name = strdup(fullname);
|
||||||
F_name[0] = toupper(F_name[0]); // capitalize first letter
|
F_name[0] = toupper(F_name[0]); // capitalize first letter
|
||||||
if (have_tag) {
|
if (EMSdevice::tag_to_string(tag).empty()) {
|
||||||
snprintf(ha_name, sizeof(ha_name), "%s %s", EMSdevice::tag_to_string(tag).c_str(), F_name);
|
snprintf(ha_name, sizeof(ha_name), "%s", F_name); // no tag
|
||||||
} else {
|
} else {
|
||||||
snprintf(ha_name, sizeof(ha_name), "%s", F_name);
|
snprintf(ha_name, sizeof(ha_name), "%s %s", EMSdevice::tag_to_string(tag).c_str(), F_name);
|
||||||
}
|
}
|
||||||
free(F_name);
|
free(F_name); // very important!
|
||||||
doc["name"] = ha_name;
|
doc["name"] = ha_name;
|
||||||
|
|
||||||
// entity id is generated from the name, see https://www.home-assistant.io/docs/mqtt/discovery/#use-object_id-to-influence-the-entity-id
|
|
||||||
// so we override it to make it unique using entity_id
|
|
||||||
// See https://github.com/emsesp/EMS-ESP32/issues/596
|
|
||||||
// keep it compatible to v3.4, use english fullname, no prefix (basename prefix commented out)
|
|
||||||
char object_id[130];
|
|
||||||
if (have_tag) {
|
|
||||||
snprintf(object_id, sizeof(object_id), "%s_%s_%s", device_name, EMSdevice::tag_to_string(tag, false).c_str(), en_name);
|
|
||||||
} else {
|
|
||||||
snprintf(object_id, sizeof(object_id), "%s_%s", device_name, en_name);
|
|
||||||
}
|
|
||||||
doc["object_id"] = object_id;
|
|
||||||
|
|
||||||
// value template
|
// value template
|
||||||
// if its nested mqtt format then use the appended entity name, otherwise take the original
|
// if its nested mqtt format then use the appended entity name, otherwise take the original name
|
||||||
char val_tpl[75];
|
char val_tpl[75];
|
||||||
if (is_nested()) {
|
if (is_nested()) {
|
||||||
snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", new_entity);
|
if (tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
|
snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s.%s}}", EMSdevice::tag_to_mqtt(tag).c_str(), entity);
|
||||||
|
} else {
|
||||||
|
snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", entity);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", entity);
|
snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", entity);
|
||||||
}
|
}
|
||||||
@@ -1230,8 +1226,7 @@ void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp,
|
|||||||
char currtemp_s[30];
|
char currtemp_s[30];
|
||||||
char mode_str_tpl[400];
|
char mode_str_tpl[400];
|
||||||
char name_s[10];
|
char name_s[10];
|
||||||
char id_s[20];
|
char uniq_id_s[60];
|
||||||
char uniq_id_s[30];
|
|
||||||
char temp_cmd_s[30];
|
char temp_cmd_s[30];
|
||||||
char mode_cmd_s[30];
|
char mode_cmd_s[30];
|
||||||
char min_s[10];
|
char min_s[10];
|
||||||
@@ -1269,18 +1264,17 @@ void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp,
|
|||||||
hc_mode_s,
|
hc_mode_s,
|
||||||
hc_mode_s);
|
hc_mode_s);
|
||||||
|
|
||||||
snprintf(id_s, sizeof(id_s), "thermostat_hc%d", hc_num);
|
|
||||||
snprintf(name_s, sizeof(name_s), "Hc%d", hc_num);
|
snprintf(name_s, sizeof(name_s), "Hc%d", hc_num);
|
||||||
snprintf(uniq_id_s, sizeof(uniq_id_s), "thermostat_hc%d", hc_num);
|
snprintf(uniq_id_s, sizeof(uniq_id_s), "%s_thermostat_hc%d", mqtt_basename_.c_str(), hc_num); // add basename
|
||||||
snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/seltemp", hc_num);
|
snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/seltemp", hc_num);
|
||||||
snprintf(mode_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/mode", hc_num);
|
snprintf(mode_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/mode", hc_num);
|
||||||
|
|
||||||
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
||||||
|
|
||||||
doc["~"] = mqtt_base_;
|
doc["~"] = mqtt_base_;
|
||||||
doc["object_id"] = id_s;
|
|
||||||
doc["name"] = name_s;
|
|
||||||
doc["uniq_id"] = uniq_id_s;
|
doc["uniq_id"] = uniq_id_s;
|
||||||
|
doc["object_id"] = uniq_id_s; // same as uniq_id
|
||||||
|
doc["name"] = name_s;
|
||||||
doc["mode_stat_t"] = topic_t;
|
doc["mode_stat_t"] = topic_t;
|
||||||
doc["mode_stat_tpl"] = mode_str_tpl;
|
doc["mode_stat_tpl"] = mode_str_tpl;
|
||||||
doc["temp_cmd_t"] = temp_cmd_s;
|
doc["temp_cmd_t"] = temp_cmd_s;
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ class Mqtt {
|
|||||||
static void publish_ha_sensor_config(uint8_t type,
|
static void publish_ha_sensor_config(uint8_t type,
|
||||||
uint8_t tag,
|
uint8_t tag,
|
||||||
const char * const fullname,
|
const char * const fullname,
|
||||||
const char * const en_name,
|
|
||||||
const uint8_t device_type,
|
const uint8_t device_type,
|
||||||
const char * const entity,
|
const char * const entity,
|
||||||
const uint8_t uom,
|
const uint8_t uom,
|
||||||
|
|||||||
@@ -151,10 +151,13 @@ void Shower::set_shower_state(bool state, bool force) {
|
|||||||
ha_configdone_ = true;
|
ha_configdone_ = true;
|
||||||
|
|
||||||
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
||||||
doc["name"] = "Shower Active";
|
doc["name"] = "Shower Active";
|
||||||
doc["uniq_id"] = "shower_active";
|
char str[70];
|
||||||
doc["~"] = Mqtt::base();
|
snprintf(str, sizeof(str), "%s_shower_active", Mqtt::basename().c_str());
|
||||||
doc["stat_t"] = "~/shower_active";
|
doc["uniq_id"] = str;
|
||||||
|
doc["object_id"] = str;
|
||||||
|
doc["~"] = Mqtt::base();
|
||||||
|
doc["stat_t"] = "~/shower_active";
|
||||||
|
|
||||||
// always render boolean as strings for HA
|
// always render boolean as strings for HA
|
||||||
char result[12];
|
char result[12];
|
||||||
|
|||||||
@@ -536,23 +536,23 @@ void System::loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send MQTT info topic appended with the version information as JSON, as a retained flag
|
// send MQTT info topic appended with the version information as JSON, as a retained flag
|
||||||
void System::send_info_mqtt(const char * event_str) {
|
void System::send_info_mqtt(const char * event_str, bool send_ntp) {
|
||||||
StaticJsonDocument<EMSESP_JSON_SIZE_MEDIUM> doc;
|
StaticJsonDocument<EMSESP_JSON_SIZE_MEDIUM> doc;
|
||||||
doc["event"] = event_str;
|
doc["event"] = event_str;
|
||||||
doc["version"] = EMSESP_APP_VERSION;
|
doc["version"] = EMSESP_APP_VERSION;
|
||||||
|
|
||||||
// if NTP is enabled send the boot_time in local time in ISO 8601 format (eg: 2022-11-15 20:46:38)
|
// if NTP is enabled send the boot_time in local time in ISO 8601 format (eg: 2022-11-15 20:46:38)
|
||||||
// https://github.com/emsesp/EMS-ESP32/issues/751
|
// https://github.com/emsesp/EMS-ESP32/issues/751
|
||||||
if (ntp_connected()) {
|
if (send_ntp) {
|
||||||
char time_string[25];
|
char time_string[25];
|
||||||
time_t now = time(nullptr); // grab the current instant in unix seconds
|
time_t now = time(nullptr) - uuid::get_uptime_sec();
|
||||||
strftime(time_string, 25, "%F %T", localtime(&now));
|
strftime(time_string, 25, "%FT%T%z", localtime(&now));
|
||||||
doc["boot_time"] = time_string;
|
doc["boot time"] = time_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
if (EMSESP::system_.ethernet_connected()) {
|
if (EMSESP::system_.ethernet_connected()) {
|
||||||
doc["connection"] = "ethernet";
|
doc["network"] = "ethernet";
|
||||||
doc["hostname"] = ETH.getHostname();
|
doc["hostname"] = ETH.getHostname();
|
||||||
doc["MAC"] = ETH.macAddress();
|
doc["MAC"] = ETH.macAddress();
|
||||||
doc["IPv4 address"] = uuid::printable_to_string(ETH.localIP()) + "/" + uuid::printable_to_string(ETH.subnetMask());
|
doc["IPv4 address"] = uuid::printable_to_string(ETH.localIP()) + "/" + uuid::printable_to_string(ETH.subnetMask());
|
||||||
@@ -562,7 +562,7 @@ void System::send_info_mqtt(const char * event_str) {
|
|||||||
doc["IPv6 address"] = uuid::printable_to_string(ETH.localIPv6());
|
doc["IPv6 address"] = uuid::printable_to_string(ETH.localIPv6());
|
||||||
}
|
}
|
||||||
} else if (WiFi.status() == WL_CONNECTED) {
|
} else if (WiFi.status() == WL_CONNECTED) {
|
||||||
doc["connection"] = "wifi";
|
doc["network"] = "wifi";
|
||||||
doc["hostname"] = WiFi.getHostname();
|
doc["hostname"] = WiFi.getHostname();
|
||||||
doc["SSID"] = WiFi.SSID();
|
doc["SSID"] = WiFi.SSID();
|
||||||
doc["BSSID"] = WiFi.BSSIDstr();
|
doc["BSSID"] = WiFi.BSSIDstr();
|
||||||
@@ -896,19 +896,19 @@ void System::show_system(uuid::console::Shell & shell) {
|
|||||||
shell.println("Network:");
|
shell.println("Network:");
|
||||||
switch (WiFi.status()) {
|
switch (WiFi.status()) {
|
||||||
case WL_IDLE_STATUS:
|
case WL_IDLE_STATUS:
|
||||||
shell.printfln(" Network: Idle");
|
shell.printfln(" Status: Idle");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WL_NO_SSID_AVAIL:
|
case WL_NO_SSID_AVAIL:
|
||||||
shell.printfln(" Network: Network not found");
|
shell.printfln(" Status: Network not found");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WL_SCAN_COMPLETED:
|
case WL_SCAN_COMPLETED:
|
||||||
shell.printfln(" Network: Network scan complete");
|
shell.printfln(" Status: Network scan complete");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WL_CONNECTED:
|
case WL_CONNECTED:
|
||||||
shell.printfln(" Network: connected");
|
shell.printfln(" Status: connected");
|
||||||
shell.printfln(" SSID: %s", WiFi.SSID().c_str());
|
shell.printfln(" SSID: %s", WiFi.SSID().c_str());
|
||||||
shell.printfln(" BSSID: %s", WiFi.BSSIDstr().c_str());
|
shell.printfln(" BSSID: %s", WiFi.BSSIDstr().c_str());
|
||||||
shell.printfln(" RSSI: %d dBm (%d %%)", WiFi.RSSI(), wifi_quality(WiFi.RSSI()));
|
shell.printfln(" RSSI: %d dBm (%d %%)", WiFi.RSSI(), wifi_quality(WiFi.RSSI()));
|
||||||
@@ -943,7 +943,7 @@ void System::show_system(uuid::console::Shell & shell) {
|
|||||||
// show Ethernet if connected
|
// show Ethernet if connected
|
||||||
if (ethernet_connected_) {
|
if (ethernet_connected_) {
|
||||||
shell.println();
|
shell.println();
|
||||||
shell.printfln(" Ethernet Network: connected");
|
shell.printfln(" Status: Ethernet connected");
|
||||||
shell.printfln(" MAC address: %s", ETH.macAddress().c_str());
|
shell.printfln(" MAC address: %s", ETH.macAddress().c_str());
|
||||||
shell.printfln(" Hostname: %s", ETH.getHostname());
|
shell.printfln(" Hostname: %s", ETH.getHostname());
|
||||||
shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(ETH.localIP()).c_str(), uuid::printable_to_string(ETH.subnetMask()).c_str());
|
shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(ETH.localIP()).c_str(), uuid::printable_to_string(ETH.subnetMask()).c_str());
|
||||||
@@ -1071,9 +1071,9 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
|
|||||||
node["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
|
node["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
|
||||||
// node["uptime (seconds)"] = uuid::get_uptime_sec();
|
// node["uptime (seconds)"] = uuid::get_uptime_sec();
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
node["freemem"] = ESP.getFreeHeap() / 1024; // kilobytes
|
node["free mem"] = ESP.getFreeHeap() / 1024; // kilobytes
|
||||||
node["maxalloc"] = ESP.getMaxAllocHeap() / 1024; // kilobytes
|
node["max alloc"] = ESP.getMaxAllocHeap() / 1024; // kilobytes
|
||||||
node["free_app"] = EMSESP::system_.appFree(); // kilobytes
|
node["free app"] = EMSESP::system_.appFree(); // kilobytes
|
||||||
#endif
|
#endif
|
||||||
node["reset reason"] = EMSESP::system_.reset_reason(0) + " / " + EMSESP::system_.reset_reason(1);
|
node["reset reason"] = EMSESP::system_.reset_reason(0) + " / " + EMSESP::system_.reset_reason(1);
|
||||||
|
|
||||||
@@ -1081,7 +1081,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
|
|||||||
// Network Status
|
// Network Status
|
||||||
node = output.createNestedObject("Network Info");
|
node = output.createNestedObject("Network Info");
|
||||||
if (EMSESP::system_.ethernet_connected()) {
|
if (EMSESP::system_.ethernet_connected()) {
|
||||||
node["connection"] = "Ethernet";
|
node["network"] = "Ethernet";
|
||||||
node["hostname"] = ETH.getHostname();
|
node["hostname"] = ETH.getHostname();
|
||||||
node["MAC"] = ETH.macAddress();
|
node["MAC"] = ETH.macAddress();
|
||||||
node["IPv4 address"] = uuid::printable_to_string(ETH.localIP()) + "/" + uuid::printable_to_string(ETH.subnetMask());
|
node["IPv4 address"] = uuid::printable_to_string(ETH.localIP()) + "/" + uuid::printable_to_string(ETH.subnetMask());
|
||||||
@@ -1091,8 +1091,8 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
|
|||||||
node["IPv6 address"] = uuid::printable_to_string(ETH.localIPv6());
|
node["IPv6 address"] = uuid::printable_to_string(ETH.localIPv6());
|
||||||
}
|
}
|
||||||
} else if (WiFi.status() == WL_CONNECTED) {
|
} else if (WiFi.status() == WL_CONNECTED) {
|
||||||
node["connection"] = "WiFi";
|
node["network"] = "WiFi";
|
||||||
node["hostname"] = WiFi.getHostname();
|
node["hostname"] = WiFi.getHostname();
|
||||||
// node["SSID"] = WiFi.SSID();
|
// node["SSID"] = WiFi.SSID();
|
||||||
// node["BSSID"] = WiFi.BSSIDstr();
|
// node["BSSID"] = WiFi.BSSIDstr();
|
||||||
node["RSSI"] = WiFi.RSSI();
|
node["RSSI"] = WiFi.RSSI();
|
||||||
@@ -1150,7 +1150,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
|
|||||||
}
|
}
|
||||||
EMSESP::esp8266React.getMqttSettingsService()->read([&](MqttSettings & settings) {
|
EMSESP::esp8266React.getMqttSettingsService()->read([&](MqttSettings & settings) {
|
||||||
node["enabled"] = settings.enabled;
|
node["enabled"] = settings.enabled;
|
||||||
node["client_id"] = settings.clientId;
|
node["client id"] = settings.clientId;
|
||||||
node["keep alive"] = settings.keepAlive;
|
node["keep alive"] = settings.keepAlive;
|
||||||
node["clean session"] = settings.cleanSession;
|
node["clean session"] = settings.cleanSession;
|
||||||
node["base"] = settings.base;
|
node["base"] = settings.base;
|
||||||
@@ -1245,7 +1245,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
|
|||||||
node["phy type"] = settings.phy_type;
|
node["phy type"] = settings.phy_type;
|
||||||
if (settings.phy_type != PHY_type::PHY_TYPE_NONE) {
|
if (settings.phy_type != PHY_type::PHY_TYPE_NONE) {
|
||||||
node["eth power"] = settings.eth_power;
|
node["eth power"] = settings.eth_power;
|
||||||
node["eth phy_addr"] = settings.eth_phy_addr;
|
node["eth phy addr"] = settings.eth_phy_addr;
|
||||||
node["eth clock_mode"] = settings.eth_clock_mode;
|
node["eth clock_mode"] = settings.eth_clock_mode;
|
||||||
}
|
}
|
||||||
node["rx gpio"] = settings.rx_gpio;
|
node["rx gpio"] = settings.rx_gpio;
|
||||||
@@ -1264,6 +1264,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
|
|||||||
node["enum format"] = settings.enum_format;
|
node["enum format"] = settings.enum_format;
|
||||||
node["analog enabled"] = settings.analog_enabled;
|
node["analog enabled"] = settings.analog_enabled;
|
||||||
node["telnet enabled"] = settings.telnet_enabled;
|
node["telnet enabled"] = settings.telnet_enabled;
|
||||||
|
node["web log buffer"] = settings.weblog_buffer;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Devices - show EMS devices if we have any
|
// Devices - show EMS devices if we have any
|
||||||
@@ -1416,6 +1417,7 @@ void System::ntp_connected(bool b) {
|
|||||||
if (b != ntp_connected_) {
|
if (b != ntp_connected_) {
|
||||||
LOG_INFO(b ? "NTP connected" : "NTP disconnected"); // if changed report it
|
LOG_INFO(b ? "NTP connected" : "NTP disconnected"); // if changed report it
|
||||||
}
|
}
|
||||||
|
|
||||||
ntp_connected_ = b;
|
ntp_connected_ = b;
|
||||||
ntp_last_check_ = b ? uuid::get_uptime_sec() : 0;
|
ntp_last_check_ = b ? uuid::get_uptime_sec() : 0;
|
||||||
}
|
}
|
||||||
@@ -1426,6 +1428,7 @@ bool System::ntp_connected() {
|
|||||||
if ((uuid::get_uptime_sec() - ntp_last_check_ > 7201) && ntp_connected_) {
|
if ((uuid::get_uptime_sec() - ntp_last_check_ > 7201) && ntp_connected_) {
|
||||||
ntp_connected(false);
|
ntp_connected(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ntp_connected_;
|
return ntp_connected_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ class System {
|
|||||||
bool check_upgrade();
|
bool check_upgrade();
|
||||||
bool heartbeat_json(JsonObject & output);
|
bool heartbeat_json(JsonObject & output);
|
||||||
void send_heartbeat();
|
void send_heartbeat();
|
||||||
void send_info_mqtt(const char * event_str);
|
void send_info_mqtt(const char * event_str, bool send_ntp = false);
|
||||||
|
|
||||||
bool syslog_enabled() {
|
bool syslog_enabled() {
|
||||||
return syslog_enabled_;
|
return syslog_enabled_;
|
||||||
|
|||||||
@@ -1397,9 +1397,21 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
// add a boiler
|
// add a boiler
|
||||||
add_device(0x08, 123); // Nefit Trendline
|
add_device(0x08, 123); // Nefit Trendline
|
||||||
|
|
||||||
// add a thermostat
|
// add some boiler data
|
||||||
add_device(0x18, 157); // Bosch CR100 - https://github.com/emsesp/EMS-ESP/issues/355
|
// Boiler -> Me, UBAMonitorFast(0x18), telegram: 08 00 18 00 00 02 5A 73 3D 0A 10 65 40 02 1A 80 00 01 E1 01 76 0E 3D 48 00 C9 44 02 00 (#data=25)
|
||||||
|
uart_telegram({0x08, 0x00, 0x18, 0x00, 0x00, 0x02, 0x5A, 0x73, 0x3D, 0x0A, 0x10, 0x65, 0x40, 0x02, 0x1A,
|
||||||
|
0x80, 0x00, 0x01, 0xE1, 0x01, 0x76, 0x0E, 0x3D, 0x48, 0x00, 0xC9, 0x44, 0x02, 0x00});
|
||||||
|
|
||||||
|
// Boiler -> Thermostat, UBAParameterWW(0x33), telegram: 08 97 33 00 23 24 (#data=2)
|
||||||
|
uart_telegram({0x08, 0x98, 0x33, 0x00, 0x23, 0x24});
|
||||||
|
|
||||||
|
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
||||||
|
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
||||||
|
|
||||||
|
// add a thermostat
|
||||||
|
add_device(0x18, 157); // Bosch CR100
|
||||||
|
|
||||||
|
// add some thermostat data
|
||||||
// RCPLUSStatusMessage_HC1(0x01A5) - HC1
|
// RCPLUSStatusMessage_HC1(0x01A5) - HC1
|
||||||
uart_telegram({0x98, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xCF, 0x21, 0x2E, 0x00, 0x00, 0x2E, 0x24,
|
uart_telegram({0x98, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xCF, 0x21, 0x2E, 0x00, 0x00, 0x2E, 0x24,
|
||||||
0x03, 0x25, 0x03, 0x03, 0x01, 0x03, 0x25, 0x00, 0xC8, 0x00, 0x00, 0x11, 0x01, 0x03});
|
0x03, 0x25, 0x03, 0x03, 0x01, 0x03, 0x25, 0x00, 0xC8, 0x00, 0x00, 0x11, 0x01, 0x03});
|
||||||
@@ -1412,11 +1424,13 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
|
|
||||||
char boiler_topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char boiler_topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
char thermostat_topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char thermostat_topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
|
char thermostat_topic_hc1[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
char system_topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char system_topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
Mqtt::show_mqtt(shell); // show queue
|
Mqtt::show_mqtt(shell); // show queue
|
||||||
|
|
||||||
strlcpy(boiler_topic, "ems-esp/boiler", sizeof(boiler_topic));
|
strlcpy(boiler_topic, "ems-esp/boiler", sizeof(boiler_topic));
|
||||||
strlcpy(thermostat_topic, "ems-esp/thermostat", sizeof(thermostat_topic));
|
strlcpy(thermostat_topic, "ems-esp/thermostat", sizeof(thermostat_topic));
|
||||||
|
strlcpy(thermostat_topic_hc1, "ems-esp/thermostat/hc1", sizeof(thermostat_topic));
|
||||||
strlcpy(system_topic, "ems-esp/system", sizeof(system_topic));
|
strlcpy(system_topic, "ems-esp/system", sizeof(system_topic));
|
||||||
|
|
||||||
// test publishing
|
// test publishing
|
||||||
@@ -1425,11 +1439,13 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
// test receiving
|
// test receiving
|
||||||
EMSESP::mqtt_.incoming(boiler_topic, ""); // test if ignore empty payloads, should return values
|
EMSESP::mqtt_.incoming(boiler_topic, ""); // test if ignore empty payloads, should return values
|
||||||
|
|
||||||
EMSESP::mqtt_.incoming(boiler_topic, "12345"); // error: invalid format
|
// these all should fail
|
||||||
EMSESP::mqtt_.incoming("bad_topic", "123456"); // error: no matching topic
|
EMSESP::mqtt_.incoming(boiler_topic, "12345"); // error: invalid format
|
||||||
EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"garbage\",\"data\":22.52}"); // error: should report error
|
EMSESP::mqtt_.incoming("bad_topic", "123456"); // error: no matching topic
|
||||||
|
EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"garbage\",\"data\":22.52}"); // error: should report error
|
||||||
|
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"control\",\"data\":\"1\"}"); // RC35 only, should error
|
||||||
|
|
||||||
EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"comfort\",\"data\":\"eco\"}");
|
// these all should pass
|
||||||
EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"wwactivated\",\"data\":\"1\"}"); // with quotes
|
EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"wwactivated\",\"data\":\"1\"}"); // with quotes
|
||||||
EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"wwactivated\",\"data\":1}"); // without quotes
|
EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"wwactivated\",\"data\":1}"); // without quotes
|
||||||
EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"selflowtemp\",\"data\":55}");
|
EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"selflowtemp\",\"data\":55}");
|
||||||
@@ -1437,20 +1453,23 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
// test direct commands
|
// test direct commands
|
||||||
EMSESP::mqtt_.incoming("ems-esp/boiler/selflowtemp", "56");
|
EMSESP::mqtt_.incoming("ems-esp/boiler/selflowtemp", "56");
|
||||||
|
|
||||||
EMSESP::mqtt_.incoming(system_topic, "{\"cmd\":\"send\",\"data\":\"01 02 03 04 05\"}");
|
EMSESP::mqtt_.incoming(system_topic, "{\"cmd\":\"send\",\"data\":\"01 02 03 04 05\"}"); // TODO check if works
|
||||||
EMSESP::mqtt_.incoming(system_topic, "{\"cmd\":\"pin\",\"id\":12,\"data\":\"1\"}");
|
// EMSESP::mqtt_.incoming(system_topic, "{\"cmd\":\"pin\",\"id\":12,\"data\":\"1\"}");
|
||||||
|
|
||||||
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"wwmode\",\"data\":\"auto\"}");
|
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"wwmode\",\"data\":\"auto\"}");
|
||||||
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"control\",\"data\":\"1\"}"); // RC35 only, should error
|
|
||||||
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"typo\",\"id\":2}"); // invalid mode
|
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"typo\",\"id\":2}"); // invalid mode
|
||||||
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"auto\",\"id\":2}");
|
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"auto\",\"id\":2}");
|
||||||
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"auto\",\"hc\":2}"); // hc as number
|
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"auto\",\"hc\":2}"); // hc as number
|
||||||
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"temp\",\"data\":19.5,\"hc\":1}"); // data as number
|
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"seltemp\",\"data\":19.5,\"hc\":1}"); // data as number
|
||||||
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"auto\",\"hc\":\"2\"}"); // hc as string. should error as no hc2
|
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"seltemp\",\"data\":\"auto\",\"hc\":\"2\"}"); // hc as string. should error as no hc2
|
||||||
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"temp\",\"data\":22.56}");
|
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"seltemp\",\"data\":22.56}");
|
||||||
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"temp\",\"data\":22}");
|
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"seltemp\",\"data\":22}");
|
||||||
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"temp\",\"data\":\"22.56\"}");
|
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"seltemp\",\"data\":\"22.56\"}");
|
||||||
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"temp\",\"id\":2,\"data\":22}");
|
EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"seltemp\",\"id\":2,\"data\":22}");
|
||||||
|
|
||||||
|
// test with hc
|
||||||
|
EMSESP::mqtt_.incoming("ems-esp/thermostat/hc1/seltemp", "30");
|
||||||
|
EMSESP::mqtt_.incoming("ems-esp/thermostat/hc2/seltemp", "32");
|
||||||
|
|
||||||
// test single commands
|
// test single commands
|
||||||
EMSESP::mqtt_.incoming(thermostat_topic, "auto");
|
EMSESP::mqtt_.incoming(thermostat_topic, "auto");
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ namespace emsesp {
|
|||||||
// #define EMSESP_DEBUG_DEFAULT "solar"
|
// #define EMSESP_DEBUG_DEFAULT "solar"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "mixer"
|
// #define EMSESP_DEBUG_DEFAULT "mixer"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "web"
|
// #define EMSESP_DEBUG_DEFAULT "web"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "mqtt"
|
#define EMSESP_DEBUG_DEFAULT "mqtt"
|
||||||
#define EMSESP_DEBUG_DEFAULT "general"
|
// #define EMSESP_DEBUG_DEFAULT "general"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "boiler"
|
// #define EMSESP_DEBUG_DEFAULT "boiler"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "mqtt2"
|
// #define EMSESP_DEBUG_DEFAULT "mqtt2"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "mqtt_nested"
|
// #define EMSESP_DEBUG_DEFAULT "mqtt_nested"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#define EMSESP_APP_VERSION "3.5.0b10"
|
#define EMSESP_APP_VERSION "3.5.0b11"
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32C3
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
#define EMSESP_PLATFORM "ESP32-C3";
|
#define EMSESP_PLATFORM "ESP32-C3";
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) {
|
|||||||
|
|
||||||
// send the json that came back from the command call
|
// send the json that came back from the command call
|
||||||
// FAIL, OK, NOT_FOUND, ERROR, NOT_ALLOWED = 400 (bad request), 200 (OK), 400 (not found), 400 (bad request), 401 (unauthorized)
|
// FAIL, OK, NOT_FOUND, ERROR, NOT_ALLOWED = 400 (bad request), 200 (OK), 400 (not found), 400 (bad request), 401 (unauthorized)
|
||||||
int ret_codes[5] = {400, 200, 400, 400, 401};
|
int ret_codes[6] = {400, 200, 400, 400, 401, 400};
|
||||||
response->setCode(ret_codes[return_code]);
|
response->setCode(ret_codes[return_code]);
|
||||||
response->setLength();
|
response->setLength();
|
||||||
response->setContentType("application/json; charset=utf-8");
|
response->setContentType("application/json; charset=utf-8");
|
||||||
|
|||||||
Reference in New Issue
Block a user