mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 08:19:52 +03:00
Merge branch 'dev' into dev
This commit is contained in:
@@ -4,13 +4,15 @@
|
|||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
||||||
- Translations in Web UI and all device entity names to German. [#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 Greenstar 30Ri boiler
|
- 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 program memory info
|
- Add program memory info
|
||||||
|
- Add mqtt queue and connection infos
|
||||||
- Add min/max setting to customizations
|
- Add min/max setting to customizations
|
||||||
- Adapt min/max if ems-value is not in this range
|
- Adapt min/max if ems-value is not in this range
|
||||||
- Add heatpump settings for inputs and limits
|
- Add heat pump settings for inputs and limits
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
@@ -20,8 +22,9 @@
|
|||||||
|
|
||||||
- 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
|
||||||
|
- removed flash strings
|
||||||
|
|
||||||
## **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 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)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"adapter": "react",
|
"adapter": "react",
|
||||||
"baseLocale": "en",
|
"baseLocale": "en",
|
||||||
"$schema": "https://unpkg.com/typesafe-i18n@5.13.0/schema/typesafe-i18n.json"
|
"$schema": "https://unpkg.com/typesafe-i18n@5.14.0/schema/typesafe-i18n.json"
|
||||||
}
|
}
|
||||||
|
|||||||
290
interface/package-lock.json
generated
290
interface/package-lock.json
generated
@@ -12,15 +12,15 @@
|
|||||||
"@emotion/styled": "^11.10.4",
|
"@emotion/styled": "^11.10.4",
|
||||||
"@msgpack/msgpack": "^2.8.0",
|
"@msgpack/msgpack": "^2.8.0",
|
||||||
"@mui/icons-material": "^5.10.6",
|
"@mui/icons-material": "^5.10.6",
|
||||||
"@mui/material": "^5.10.7",
|
"@mui/material": "^5.10.8",
|
||||||
"@table-library/react-table-library": "4.0.18",
|
"@table-library/react-table-library": "4.0.23",
|
||||||
"@types/lodash": "^4.14.185",
|
"@types/lodash": "^4.14.186",
|
||||||
"@types/node": "^18.7.23",
|
"@types/node": "^18.8.3",
|
||||||
"@types/react": "^18.0.21",
|
"@types/react": "^18.0.21",
|
||||||
"@types/react-dom": "^18.0.6",
|
"@types/react-dom": "^18.0.6",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"async-validator": "^4.2.5",
|
"async-validator": "^4.2.5",
|
||||||
"axios": "^0.27.2",
|
"axios": "^1.1.2",
|
||||||
"http-proxy-middleware": "^2.0.6",
|
"http-proxy-middleware": "^2.0.6",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
@@ -31,10 +31,10 @@
|
|||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-dropzone": "^14.2.2",
|
"react-dropzone": "^14.2.2",
|
||||||
"react-icons": "^4.4.0",
|
"react-icons": "^4.4.0",
|
||||||
"react-router-dom": "^6.4.1",
|
"react-router-dom": "^6.4.2",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"sockette": "^2.0.6",
|
"sockette": "^2.0.6",
|
||||||
"typesafe-i18n": "^5.13.1",
|
"typesafe-i18n": "^5.14.0",
|
||||||
"typescript": "^4.8.4"
|
"typescript": "^4.8.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -2316,9 +2316,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.10.5",
|
"version": "0.10.7",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz",
|
||||||
"integrity": "sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==",
|
"integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@humanwhocodes/object-schema": "^1.2.1",
|
"@humanwhocodes/object-schema": "^1.2.1",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
@@ -3103,9 +3103,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/base": {
|
"node_modules/@mui/base": {
|
||||||
"version": "5.0.0-alpha.99",
|
"version": "5.0.0-alpha.100",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.99.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.100.tgz",
|
||||||
"integrity": "sha512-D04H6O1c0Jv561yI0SVbpa8MpqpW3G43CwJxV2o6ALfI0DMJ45w07dGafmDchb6aCWTRTdggd3rjgmuzyNwPiQ==",
|
"integrity": "sha512-bSoJEKCENtmJrJDECHUe9PiqztIUACuSskyqw9ypqE7Dz3WxL3e8puFsWBkUsz+WOCjXh4B4Xljn88Ucxxv5HA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.19.0",
|
"@babel/runtime": "^7.19.0",
|
||||||
"@emotion/is-prop-valid": "^1.2.0",
|
"@emotion/is-prop-valid": "^1.2.0",
|
||||||
@@ -3135,9 +3135,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/core-downloads-tracker": {
|
"node_modules/@mui/core-downloads-tracker": {
|
||||||
"version": "5.10.7",
|
"version": "5.10.8",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.8.tgz",
|
||||||
"integrity": "sha512-3N0UYVy3MbrHzM3j6f7fIUCZ+bQ1/sSZq143tLxwSssW3Z4AqE83brpr5flEY1Lx+Aowv/cPyQMmZxzRlFCGqw==",
|
"integrity": "sha512-V5D7OInO4P9PdT/JACg7fwjbOORm3GklaMVgdGomjyxiyetgRND5CC9r35e1LK/DqHdoyDuhbFzdfrqWtpmEIw==",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/mui"
|
"url": "https://opencollective.com/mui"
|
||||||
@@ -3169,14 +3169,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/material": {
|
"node_modules/@mui/material": {
|
||||||
"version": "5.10.7",
|
"version": "5.10.8",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.10.8.tgz",
|
||||||
"integrity": "sha512-o1jcQGii+q7ORrXhBiMmGzFDaboc1qTgOOC3zDW+NR9ryVzWzL7qEeqoORbgDB5zk9OBsXCjB91fUH/ls5xMwg==",
|
"integrity": "sha512-sF/Ka0IJjGXV52zoT4xAWEqXVRjNYbIjATo9L4Q5oQC5iJpGrKJFY16uNtWWB0+vp/nayAuPGZHrxtV+t3ecdQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.19.0",
|
"@babel/runtime": "^7.19.0",
|
||||||
"@mui/base": "5.0.0-alpha.99",
|
"@mui/base": "5.0.0-alpha.100",
|
||||||
"@mui/core-downloads-tracker": "^5.10.7",
|
"@mui/core-downloads-tracker": "^5.10.8",
|
||||||
"@mui/system": "^5.10.7",
|
"@mui/system": "^5.10.8",
|
||||||
"@mui/types": "^7.2.0",
|
"@mui/types": "^7.2.0",
|
||||||
"@mui/utils": "^5.10.6",
|
"@mui/utils": "^5.10.6",
|
||||||
"@types/react-transition-group": "^4.4.5",
|
"@types/react-transition-group": "^4.4.5",
|
||||||
@@ -3239,9 +3239,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/styled-engine": {
|
"node_modules/@mui/styled-engine": {
|
||||||
"version": "5.10.7",
|
"version": "5.10.8",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.10.8.tgz",
|
||||||
"integrity": "sha512-CCrtW+vvCKEm6pOE/QcutQ+ORC/iE6D1ghscN4l7LE2JXPvTXO/z0yu8Wxug1JEDlWm4r1Qa0PzJe1P9bjKzNA==",
|
"integrity": "sha512-w+y8WI18EJV6zM/q41ug19cE70JTeO6sWFsQ7tgePQFpy6ToCVPh0YLrtqxUZXSoMStW5FMw0t9fHTFAqPbngw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.19.0",
|
"@babel/runtime": "^7.19.0",
|
||||||
"@emotion/cache": "^11.10.3",
|
"@emotion/cache": "^11.10.3",
|
||||||
@@ -3270,13 +3270,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/system": {
|
"node_modules/@mui/system": {
|
||||||
"version": "5.10.7",
|
"version": "5.10.8",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.10.8.tgz",
|
||||||
"integrity": "sha512-kwyhjjKGsgtBRFl6vSqidDZcNKU5S1juTgm4Xi2fyWxaEbIQb9Sh9y0iVP2bNCJzgDr0alLaENOZOEaDWHISAQ==",
|
"integrity": "sha512-hRQ354zcrYP/KHqK8FheICSvE9raQaUgQaV+A3oD4JETaFUCVI9Ytt+RcQYgTqx02xlCXIjl8LK1rPjTneySqw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.19.0",
|
"@babel/runtime": "^7.19.0",
|
||||||
"@mui/private-theming": "^5.10.6",
|
"@mui/private-theming": "^5.10.6",
|
||||||
"@mui/styled-engine": "^5.10.7",
|
"@mui/styled-engine": "^5.10.8",
|
||||||
"@mui/types": "^7.2.0",
|
"@mui/types": "^7.2.0",
|
||||||
"@mui/utils": "^5.10.6",
|
"@mui/utils": "^5.10.6",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
@@ -3470,9 +3470,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@remix-run/router": {
|
"node_modules/@remix-run/router": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.2.tgz",
|
||||||
"integrity": "sha512-eBV5rvW4dRFOU1eajN7FmYxjAIVz/mRHgUE9En9mBn6m3mulK3WTR5C3iQhL9MZ14rWAq+xOlEaCkDiW0/heOg==",
|
"integrity": "sha512-GRSOFhJzjGN+d4sKHTMSvNeUPoZiDHWmRnXfzaxrqe7dE/Nzlc8BiMSJdLDESZlndM7jIUrZ/F4yWqVYlI0rwQ==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
@@ -3557,9 +3557,9 @@
|
|||||||
"integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg=="
|
"integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg=="
|
||||||
},
|
},
|
||||||
"node_modules/@sinclair/typebox": {
|
"node_modules/@sinclair/typebox": {
|
||||||
"version": "0.24.43",
|
"version": "0.24.44",
|
||||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.43.tgz",
|
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.44.tgz",
|
||||||
"integrity": "sha512-1orQTvtazZmsPeBroJjysvsOQCYV2yjWlebkSY38pl5vr2tdLjEJ+LoxITlGNZaH2RE19WlAwQMkH/7C14wLfw=="
|
"integrity": "sha512-ka0W0KN5i6LfrSocduwliMMpqVgohtPFidKdMEOUjoOFCHcOOYkKsPRxfs5f15oPNHTm6ERAm0GV/+/LTKeiWg=="
|
||||||
},
|
},
|
||||||
"node_modules/@sinonjs/commons": {
|
"node_modules/@sinonjs/commons": {
|
||||||
"version": "1.8.3",
|
"version": "1.8.3",
|
||||||
@@ -3796,9 +3796,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@table-library/react-table-library": {
|
"node_modules/@table-library/react-table-library": {
|
||||||
"version": "4.0.18",
|
"version": "4.0.23",
|
||||||
"resolved": "https://registry.npmjs.org/@table-library/react-table-library/-/react-table-library-4.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/@table-library/react-table-library/-/react-table-library-4.0.23.tgz",
|
||||||
"integrity": "sha512-3GX5712YuWPFeUilr8UG22SCNR9BylD5Y4xPF+pHhb1QM7WXw6SLgpeGq6UDTQGOtmKtKtwKGWXdkmvVDg8pkA==",
|
"integrity": "sha512-o2L/fqhwQNxsNbbm3LIiyZzEwaTslhG1tY9ArkYdS0xJyRhJxcOLfbJ3+dcnOOn+aIJpmPmQH+gr7RYJC0P8uw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clsx": "1.1.1",
|
"clsx": "1.1.1",
|
||||||
"react-virtualized-auto-sizer": "1.0.6",
|
"react-virtualized-auto-sizer": "1.0.6",
|
||||||
@@ -4019,9 +4019,9 @@
|
|||||||
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
|
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/lodash": {
|
"node_modules/@types/lodash": {
|
||||||
"version": "4.14.185",
|
"version": "4.14.186",
|
||||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.185.tgz",
|
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.186.tgz",
|
||||||
"integrity": "sha512-evMDG1bC4rgQg4ku9tKpuMh5iBNEwNa3tf9zRHdP1qlv+1WUg44xat4IxCE14gIpZRGUUWAx2VhItCZc25NfMA=="
|
"integrity": "sha512-eHcVlLXP0c2FlMPm56ITode2AgLMSa6aJ05JTTbYbI+7EMkCEE5qk2E41d5g2lCVTqRe0GnnRFurmlCsDODrPw=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/mime": {
|
"node_modules/@types/mime": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
@@ -4029,9 +4029,9 @@
|
|||||||
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
|
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "18.7.23",
|
"version": "18.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.23.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.3.tgz",
|
||||||
"integrity": "sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg=="
|
"integrity": "sha512-0os9vz6BpGwxGe9LOhgP/ncvYN5Tx1fNcd2TM3rD/aCGBkysb+ZWpXEocG24h6ZzOi13+VB8HndAQFezsSOw1w=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/parse-json": {
|
"node_modules/@types/parse-json": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
@@ -5008,12 +5008,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "0.27.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.1.2.tgz",
|
||||||
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
|
"integrity": "sha512-bznQyETwElsXl2RK7HLLwb5GPpOLlycxHCtrpDR/4RqqBzjARaOTo3jz4IgtntWUYee7Ne4S8UHd92VCuzPaWA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.14.9",
|
"follow-redirects": "^1.15.0",
|
||||||
"form-data": "^4.0.0"
|
"form-data": "^4.0.0",
|
||||||
|
"proxy-from-env": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axobject-query": {
|
"node_modules/axobject-query": {
|
||||||
@@ -5561,9 +5562,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001412",
|
"version": "1.0.30001414",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001412.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001414.tgz",
|
||||||
"integrity": "sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA==",
|
"integrity": "sha512-t55jfSaWjCdocnFdKQoO+d2ct9C59UZg4dY3OnUlSZ447r8pUtIKdp0hpAzrGFultmTC+Us+KpKi4GZl/LXlFg==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -6755,9 +6756,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.4.266",
|
"version": "1.4.270",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.266.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.270.tgz",
|
||||||
"integrity": "sha512-saJTYECxUSv7eSpnXw0XIEvUkP9x4s/x2mm3TVX7k4rIFS6f5TjBih1B5h437WzIhHQjid+d8ouQzPQskMervQ=="
|
"integrity": "sha512-KNhIzgLiJmDDC444dj9vEOpZEgsV96ult9Iff98Vanumn+ShJHd5se8aX6KeVxdc0YQeqdrezBZv89rleDbvSg=="
|
||||||
},
|
},
|
||||||
"node_modules/emittery": {
|
"node_modules/emittery": {
|
||||||
"version": "0.8.1",
|
"version": "0.8.1",
|
||||||
@@ -11430,9 +11431,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/js-sdsl": {
|
"node_modules/js-sdsl": {
|
||||||
"version": "4.1.4",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz",
|
||||||
"integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw=="
|
"integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q=="
|
||||||
},
|
},
|
||||||
"node_modules/js-tokens": {
|
"node_modules/js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
@@ -12853,9 +12854,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.4.16",
|
"version": "8.4.17",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.17.tgz",
|
||||||
"integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==",
|
"integrity": "sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -14147,6 +14148,11 @@
|
|||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/proxy-from-env": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||||
|
},
|
||||||
"node_modules/psl": {
|
"node_modules/psl": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
||||||
@@ -14545,11 +14551,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "6.4.1",
|
"version": "6.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.2.tgz",
|
||||||
"integrity": "sha512-OJASKp5AykDWFewgWUim1vlLr7yfD4vO/h+bSgcP/ix8Md+LMHuAjovA74MQfsfhQJGGN1nHRhwS5qQQbbBt3A==",
|
"integrity": "sha512-Rb0BAX9KHhVzT1OKhMvCDMw776aTYM0DtkxqUBP8dNBom3mPXlfNs76JNGK8wKJ1IZEY1+WGj+cvZxHVk/GiKw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/router": "1.0.1"
|
"@remix-run/router": "1.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
@@ -14559,12 +14565,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router-dom": {
|
"node_modules/react-router-dom": {
|
||||||
"version": "6.4.1",
|
"version": "6.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.2.tgz",
|
||||||
"integrity": "sha512-MY7NJCrGNVJtGp8ODMOBHu20UaIkmwD2V3YsAOUQoCXFk7Ppdwf55RdcGyrSj+ycSL9Uiwrb3gTLYSnzcRoXww==",
|
"integrity": "sha512-yM1kjoTkpfjgczPrcyWrp+OuQMyB1WleICiiGfstnQYo/S8hPEEnVjr/RdmlH6yKK4Tnj1UGXFSa7uwAtmDoLQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/router": "1.0.1",
|
"@remix-run/router": "1.0.2",
|
||||||
"react-router": "6.4.1"
|
"react-router": "6.4.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
@@ -16420,9 +16426,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typesafe-i18n": {
|
"node_modules/typesafe-i18n": {
|
||||||
"version": "5.13.1",
|
"version": "5.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/typesafe-i18n/-/typesafe-i18n-5.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/typesafe-i18n/-/typesafe-i18n-5.14.0.tgz",
|
||||||
"integrity": "sha512-9Cgikxcj+2LAWQGZ8pOQAf14P+aOOcOel/G1kSAXAObA4Htj8R+qgCx9DqUnxjRfugWzM/19ZqGss7dl8Dw7Gg==",
|
"integrity": "sha512-ZNHysUvZZhmUuMjBvDGtUI8vT3g//4ay5fFOk2sJCsjx4ztippW1Hrhrq59nJ9mV/Q0u4OX80Gyorq8L3rwNLw==",
|
||||||
"bin": {
|
"bin": {
|
||||||
"typesafe-i18n": "cli/typesafe-i18n.mjs"
|
"typesafe-i18n": "cli/typesafe-i18n.mjs"
|
||||||
},
|
},
|
||||||
@@ -19062,9 +19068,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@humanwhocodes/config-array": {
|
"@humanwhocodes/config-array": {
|
||||||
"version": "0.10.5",
|
"version": "0.10.7",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz",
|
||||||
"integrity": "sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==",
|
"integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@humanwhocodes/object-schema": "^1.2.1",
|
"@humanwhocodes/object-schema": "^1.2.1",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
@@ -19643,9 +19649,9 @@
|
|||||||
"integrity": "sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ=="
|
"integrity": "sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ=="
|
||||||
},
|
},
|
||||||
"@mui/base": {
|
"@mui/base": {
|
||||||
"version": "5.0.0-alpha.99",
|
"version": "5.0.0-alpha.100",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.99.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.100.tgz",
|
||||||
"integrity": "sha512-D04H6O1c0Jv561yI0SVbpa8MpqpW3G43CwJxV2o6ALfI0DMJ45w07dGafmDchb6aCWTRTdggd3rjgmuzyNwPiQ==",
|
"integrity": "sha512-bSoJEKCENtmJrJDECHUe9PiqztIUACuSskyqw9ypqE7Dz3WxL3e8puFsWBkUsz+WOCjXh4B4Xljn88Ucxxv5HA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/runtime": "^7.19.0",
|
"@babel/runtime": "^7.19.0",
|
||||||
"@emotion/is-prop-valid": "^1.2.0",
|
"@emotion/is-prop-valid": "^1.2.0",
|
||||||
@@ -19658,9 +19664,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@mui/core-downloads-tracker": {
|
"@mui/core-downloads-tracker": {
|
||||||
"version": "5.10.7",
|
"version": "5.10.8",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.8.tgz",
|
||||||
"integrity": "sha512-3N0UYVy3MbrHzM3j6f7fIUCZ+bQ1/sSZq143tLxwSssW3Z4AqE83brpr5flEY1Lx+Aowv/cPyQMmZxzRlFCGqw=="
|
"integrity": "sha512-V5D7OInO4P9PdT/JACg7fwjbOORm3GklaMVgdGomjyxiyetgRND5CC9r35e1LK/DqHdoyDuhbFzdfrqWtpmEIw=="
|
||||||
},
|
},
|
||||||
"@mui/icons-material": {
|
"@mui/icons-material": {
|
||||||
"version": "5.10.6",
|
"version": "5.10.6",
|
||||||
@@ -19671,14 +19677,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@mui/material": {
|
"@mui/material": {
|
||||||
"version": "5.10.7",
|
"version": "5.10.8",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.10.8.tgz",
|
||||||
"integrity": "sha512-o1jcQGii+q7ORrXhBiMmGzFDaboc1qTgOOC3zDW+NR9ryVzWzL7qEeqoORbgDB5zk9OBsXCjB91fUH/ls5xMwg==",
|
"integrity": "sha512-sF/Ka0IJjGXV52zoT4xAWEqXVRjNYbIjATo9L4Q5oQC5iJpGrKJFY16uNtWWB0+vp/nayAuPGZHrxtV+t3ecdQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/runtime": "^7.19.0",
|
"@babel/runtime": "^7.19.0",
|
||||||
"@mui/base": "5.0.0-alpha.99",
|
"@mui/base": "5.0.0-alpha.100",
|
||||||
"@mui/core-downloads-tracker": "^5.10.7",
|
"@mui/core-downloads-tracker": "^5.10.8",
|
||||||
"@mui/system": "^5.10.7",
|
"@mui/system": "^5.10.8",
|
||||||
"@mui/types": "^7.2.0",
|
"@mui/types": "^7.2.0",
|
||||||
"@mui/utils": "^5.10.6",
|
"@mui/utils": "^5.10.6",
|
||||||
"@types/react-transition-group": "^4.4.5",
|
"@types/react-transition-group": "^4.4.5",
|
||||||
@@ -19700,9 +19706,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@mui/styled-engine": {
|
"@mui/styled-engine": {
|
||||||
"version": "5.10.7",
|
"version": "5.10.8",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.10.8.tgz",
|
||||||
"integrity": "sha512-CCrtW+vvCKEm6pOE/QcutQ+ORC/iE6D1ghscN4l7LE2JXPvTXO/z0yu8Wxug1JEDlWm4r1Qa0PzJe1P9bjKzNA==",
|
"integrity": "sha512-w+y8WI18EJV6zM/q41ug19cE70JTeO6sWFsQ7tgePQFpy6ToCVPh0YLrtqxUZXSoMStW5FMw0t9fHTFAqPbngw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/runtime": "^7.19.0",
|
"@babel/runtime": "^7.19.0",
|
||||||
"@emotion/cache": "^11.10.3",
|
"@emotion/cache": "^11.10.3",
|
||||||
@@ -19711,13 +19717,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@mui/system": {
|
"@mui/system": {
|
||||||
"version": "5.10.7",
|
"version": "5.10.8",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.10.8.tgz",
|
||||||
"integrity": "sha512-kwyhjjKGsgtBRFl6vSqidDZcNKU5S1juTgm4Xi2fyWxaEbIQb9Sh9y0iVP2bNCJzgDr0alLaENOZOEaDWHISAQ==",
|
"integrity": "sha512-hRQ354zcrYP/KHqK8FheICSvE9raQaUgQaV+A3oD4JETaFUCVI9Ytt+RcQYgTqx02xlCXIjl8LK1rPjTneySqw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/runtime": "^7.19.0",
|
"@babel/runtime": "^7.19.0",
|
||||||
"@mui/private-theming": "^5.10.6",
|
"@mui/private-theming": "^5.10.6",
|
||||||
"@mui/styled-engine": "^5.10.7",
|
"@mui/styled-engine": "^5.10.8",
|
||||||
"@mui/types": "^7.2.0",
|
"@mui/types": "^7.2.0",
|
||||||
"@mui/utils": "^5.10.6",
|
"@mui/utils": "^5.10.6",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
@@ -19819,9 +19825,9 @@
|
|||||||
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw=="
|
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw=="
|
||||||
},
|
},
|
||||||
"@remix-run/router": {
|
"@remix-run/router": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.2.tgz",
|
||||||
"integrity": "sha512-eBV5rvW4dRFOU1eajN7FmYxjAIVz/mRHgUE9En9mBn6m3mulK3WTR5C3iQhL9MZ14rWAq+xOlEaCkDiW0/heOg=="
|
"integrity": "sha512-GRSOFhJzjGN+d4sKHTMSvNeUPoZiDHWmRnXfzaxrqe7dE/Nzlc8BiMSJdLDESZlndM7jIUrZ/F4yWqVYlI0rwQ=="
|
||||||
},
|
},
|
||||||
"@rollup/plugin-babel": {
|
"@rollup/plugin-babel": {
|
||||||
"version": "5.3.1",
|
"version": "5.3.1",
|
||||||
@@ -19877,9 +19883,9 @@
|
|||||||
"integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg=="
|
"integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg=="
|
||||||
},
|
},
|
||||||
"@sinclair/typebox": {
|
"@sinclair/typebox": {
|
||||||
"version": "0.24.43",
|
"version": "0.24.44",
|
||||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.43.tgz",
|
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.44.tgz",
|
||||||
"integrity": "sha512-1orQTvtazZmsPeBroJjysvsOQCYV2yjWlebkSY38pl5vr2tdLjEJ+LoxITlGNZaH2RE19WlAwQMkH/7C14wLfw=="
|
"integrity": "sha512-ka0W0KN5i6LfrSocduwliMMpqVgohtPFidKdMEOUjoOFCHcOOYkKsPRxfs5f15oPNHTm6ERAm0GV/+/LTKeiWg=="
|
||||||
},
|
},
|
||||||
"@sinonjs/commons": {
|
"@sinonjs/commons": {
|
||||||
"version": "1.8.3",
|
"version": "1.8.3",
|
||||||
@@ -20018,9 +20024,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@table-library/react-table-library": {
|
"@table-library/react-table-library": {
|
||||||
"version": "4.0.18",
|
"version": "4.0.23",
|
||||||
"resolved": "https://registry.npmjs.org/@table-library/react-table-library/-/react-table-library-4.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/@table-library/react-table-library/-/react-table-library-4.0.23.tgz",
|
||||||
"integrity": "sha512-3GX5712YuWPFeUilr8UG22SCNR9BylD5Y4xPF+pHhb1QM7WXw6SLgpeGq6UDTQGOtmKtKtwKGWXdkmvVDg8pkA==",
|
"integrity": "sha512-o2L/fqhwQNxsNbbm3LIiyZzEwaTslhG1tY9ArkYdS0xJyRhJxcOLfbJ3+dcnOOn+aIJpmPmQH+gr7RYJC0P8uw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"clsx": "1.1.1",
|
"clsx": "1.1.1",
|
||||||
"react-virtualized-auto-sizer": "1.0.6",
|
"react-virtualized-auto-sizer": "1.0.6",
|
||||||
@@ -20223,9 +20229,9 @@
|
|||||||
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
|
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
|
||||||
},
|
},
|
||||||
"@types/lodash": {
|
"@types/lodash": {
|
||||||
"version": "4.14.185",
|
"version": "4.14.186",
|
||||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.185.tgz",
|
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.186.tgz",
|
||||||
"integrity": "sha512-evMDG1bC4rgQg4ku9tKpuMh5iBNEwNa3tf9zRHdP1qlv+1WUg44xat4IxCE14gIpZRGUUWAx2VhItCZc25NfMA=="
|
"integrity": "sha512-eHcVlLXP0c2FlMPm56ITode2AgLMSa6aJ05JTTbYbI+7EMkCEE5qk2E41d5g2lCVTqRe0GnnRFurmlCsDODrPw=="
|
||||||
},
|
},
|
||||||
"@types/mime": {
|
"@types/mime": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
@@ -20233,9 +20239,9 @@
|
|||||||
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
|
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
|
||||||
},
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "18.7.23",
|
"version": "18.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.23.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.3.tgz",
|
||||||
"integrity": "sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg=="
|
"integrity": "sha512-0os9vz6BpGwxGe9LOhgP/ncvYN5Tx1fNcd2TM3rD/aCGBkysb+ZWpXEocG24h6ZzOi13+VB8HndAQFezsSOw1w=="
|
||||||
},
|
},
|
||||||
"@types/parse-json": {
|
"@types/parse-json": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
@@ -20973,12 +20979,13 @@
|
|||||||
"integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w=="
|
"integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w=="
|
||||||
},
|
},
|
||||||
"axios": {
|
"axios": {
|
||||||
"version": "0.27.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.1.2.tgz",
|
||||||
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
|
"integrity": "sha512-bznQyETwElsXl2RK7HLLwb5GPpOLlycxHCtrpDR/4RqqBzjARaOTo3jz4IgtntWUYee7Ne4S8UHd92VCuzPaWA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"follow-redirects": "^1.14.9",
|
"follow-redirects": "^1.15.0",
|
||||||
"form-data": "^4.0.0"
|
"form-data": "^4.0.0",
|
||||||
|
"proxy-from-env": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"axobject-query": {
|
"axobject-query": {
|
||||||
@@ -21399,9 +21406,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"caniuse-lite": {
|
"caniuse-lite": {
|
||||||
"version": "1.0.30001412",
|
"version": "1.0.30001414",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001412.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001414.tgz",
|
||||||
"integrity": "sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA=="
|
"integrity": "sha512-t55jfSaWjCdocnFdKQoO+d2ct9C59UZg4dY3OnUlSZ447r8pUtIKdp0hpAzrGFultmTC+Us+KpKi4GZl/LXlFg=="
|
||||||
},
|
},
|
||||||
"case-sensitive-paths-webpack-plugin": {
|
"case-sensitive-paths-webpack-plugin": {
|
||||||
"version": "2.4.0",
|
"version": "2.4.0",
|
||||||
@@ -22255,9 +22262,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"electron-to-chromium": {
|
"electron-to-chromium": {
|
||||||
"version": "1.4.266",
|
"version": "1.4.270",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.266.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.270.tgz",
|
||||||
"integrity": "sha512-saJTYECxUSv7eSpnXw0XIEvUkP9x4s/x2mm3TVX7k4rIFS6f5TjBih1B5h437WzIhHQjid+d8ouQzPQskMervQ=="
|
"integrity": "sha512-KNhIzgLiJmDDC444dj9vEOpZEgsV96ult9Iff98Vanumn+ShJHd5se8aX6KeVxdc0YQeqdrezBZv89rleDbvSg=="
|
||||||
},
|
},
|
||||||
"emittery": {
|
"emittery": {
|
||||||
"version": "0.8.1",
|
"version": "0.8.1",
|
||||||
@@ -25614,9 +25621,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"js-sdsl": {
|
"js-sdsl": {
|
||||||
"version": "4.1.4",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz",
|
||||||
"integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw=="
|
"integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q=="
|
||||||
},
|
},
|
||||||
"js-tokens": {
|
"js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
@@ -26649,9 +26656,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "8.4.16",
|
"version": "8.4.17",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.17.tgz",
|
||||||
"integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==",
|
"integrity": "sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"nanoid": "^3.3.4",
|
"nanoid": "^3.3.4",
|
||||||
"picocolors": "^1.0.0",
|
"picocolors": "^1.0.0",
|
||||||
@@ -27407,6 +27414,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"proxy-from-env": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||||
|
},
|
||||||
"psl": {
|
"psl": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
||||||
@@ -27692,20 +27704,20 @@
|
|||||||
"integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A=="
|
"integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A=="
|
||||||
},
|
},
|
||||||
"react-router": {
|
"react-router": {
|
||||||
"version": "6.4.1",
|
"version": "6.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.2.tgz",
|
||||||
"integrity": "sha512-OJASKp5AykDWFewgWUim1vlLr7yfD4vO/h+bSgcP/ix8Md+LMHuAjovA74MQfsfhQJGGN1nHRhwS5qQQbbBt3A==",
|
"integrity": "sha512-Rb0BAX9KHhVzT1OKhMvCDMw776aTYM0DtkxqUBP8dNBom3mPXlfNs76JNGK8wKJ1IZEY1+WGj+cvZxHVk/GiKw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@remix-run/router": "1.0.1"
|
"@remix-run/router": "1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-router-dom": {
|
"react-router-dom": {
|
||||||
"version": "6.4.1",
|
"version": "6.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.2.tgz",
|
||||||
"integrity": "sha512-MY7NJCrGNVJtGp8ODMOBHu20UaIkmwD2V3YsAOUQoCXFk7Ppdwf55RdcGyrSj+ycSL9Uiwrb3gTLYSnzcRoXww==",
|
"integrity": "sha512-yM1kjoTkpfjgczPrcyWrp+OuQMyB1WleICiiGfstnQYo/S8hPEEnVjr/RdmlH6yKK4Tnj1UGXFSa7uwAtmDoLQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@remix-run/router": "1.0.1",
|
"@remix-run/router": "1.0.2",
|
||||||
"react-router": "6.4.1"
|
"react-router": "6.4.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-scripts": {
|
"react-scripts": {
|
||||||
@@ -29096,9 +29108,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"typesafe-i18n": {
|
"typesafe-i18n": {
|
||||||
"version": "5.13.1",
|
"version": "5.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/typesafe-i18n/-/typesafe-i18n-5.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/typesafe-i18n/-/typesafe-i18n-5.14.0.tgz",
|
||||||
"integrity": "sha512-9Cgikxcj+2LAWQGZ8pOQAf14P+aOOcOel/G1kSAXAObA4Htj8R+qgCx9DqUnxjRfugWzM/19ZqGss7dl8Dw7Gg==",
|
"integrity": "sha512-ZNHysUvZZhmUuMjBvDGtUI8vT3g//4ay5fFOk2sJCsjx4ztippW1Hrhrq59nJ9mV/Q0u4OX80Gyorq8L3rwNLw==",
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
"typescript": {
|
"typescript": {
|
||||||
|
|||||||
@@ -8,15 +8,15 @@
|
|||||||
"@emotion/styled": "^11.10.4",
|
"@emotion/styled": "^11.10.4",
|
||||||
"@msgpack/msgpack": "^2.8.0",
|
"@msgpack/msgpack": "^2.8.0",
|
||||||
"@mui/icons-material": "^5.10.6",
|
"@mui/icons-material": "^5.10.6",
|
||||||
"@mui/material": "^5.10.7",
|
"@mui/material": "^5.10.8",
|
||||||
"@table-library/react-table-library": "4.0.18",
|
"@table-library/react-table-library": "4.0.23",
|
||||||
"@types/lodash": "^4.14.185",
|
"@types/lodash": "^4.14.186",
|
||||||
"@types/node": "^18.7.23",
|
"@types/node": "^18.8.3",
|
||||||
"@types/react": "^18.0.21",
|
"@types/react": "^18.0.21",
|
||||||
"@types/react-dom": "^18.0.6",
|
"@types/react-dom": "^18.0.6",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"async-validator": "^4.2.5",
|
"async-validator": "^4.2.5",
|
||||||
"axios": "^0.27.2",
|
"axios": "^1.1.2",
|
||||||
"http-proxy-middleware": "^2.0.6",
|
"http-proxy-middleware": "^2.0.6",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
@@ -27,10 +27,10 @@
|
|||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-dropzone": "^14.2.2",
|
"react-dropzone": "^14.2.2",
|
||||||
"react-icons": "^4.4.0",
|
"react-icons": "^4.4.0",
|
||||||
"react-router-dom": "^6.4.1",
|
"react-router-dom": "^6.4.2",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"sockette": "^2.0.6",
|
"sockette": "^2.0.6",
|
||||||
"typesafe-i18n": "^5.13.1",
|
"typesafe-i18n": "^5.14.0",
|
||||||
"typescript": "^4.8.4"
|
"typescript": "^4.8.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import * as AuthenticationApi from './api/authentication';
|
|||||||
import { PROJECT_NAME } from './api/env';
|
import { PROJECT_NAME } from './api/env';
|
||||||
import { AuthenticationContext } from './contexts/authentication';
|
import { AuthenticationContext } from './contexts/authentication';
|
||||||
|
|
||||||
import { AxiosError } from 'axios';
|
|
||||||
|
|
||||||
import { extractErrorMessage, onEnterCallback, updateValue } from './utils';
|
import { extractErrorMessage, onEnterCallback, updateValue } from './utils';
|
||||||
import { SignInRequest } from './types';
|
import { SignInRequest } from './types';
|
||||||
import { ValidatedTextField } from './components';
|
import { ValidatedTextField } from './components';
|
||||||
@@ -24,6 +22,8 @@ import { ReactComponent as NLflag } from './i18n/NL.svg';
|
|||||||
import { ReactComponent as DEflag } from './i18n/DE.svg';
|
import { ReactComponent as DEflag } from './i18n/DE.svg';
|
||||||
import { ReactComponent as GBflag } from './i18n/GB.svg';
|
import { ReactComponent as GBflag } from './i18n/GB.svg';
|
||||||
import { ReactComponent as SEflag } from './i18n/SE.svg';
|
import { ReactComponent as SEflag } from './i18n/SE.svg';
|
||||||
|
import { ReactComponent as PLflag } from './i18n/PL.svg';
|
||||||
|
import { ReactComponent as NOflag } from './i18n/NO.svg';
|
||||||
|
|
||||||
const SignIn: FC = () => {
|
const SignIn: FC = () => {
|
||||||
const authenticationContext = useContext(AuthenticationContext);
|
const authenticationContext = useContext(AuthenticationContext);
|
||||||
@@ -56,8 +56,8 @@ const SignIn: FC = () => {
|
|||||||
try {
|
try {
|
||||||
const { data: loginResponse } = await AuthenticationApi.signIn(signInRequest);
|
const { data: loginResponse } = await AuthenticationApi.signIn(signInRequest);
|
||||||
authenticationContext.signIn(loginResponse.access_token);
|
authenticationContext.signIn(loginResponse.access_token);
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
if (error instanceof AxiosError) {
|
if (error.response) {
|
||||||
if (error.response?.status === 401) {
|
if (error.response?.status === 401) {
|
||||||
enqueueSnackbar(LL.INVALID_LOGIN(), { variant: 'warning' });
|
enqueueSnackbar(LL.INVALID_LOGIN(), { variant: 'warning' });
|
||||||
}
|
}
|
||||||
@@ -125,6 +125,14 @@ const SignIn: FC = () => {
|
|||||||
<SEflag style={{ width: 24 }} />
|
<SEflag style={{ width: 24 }} />
|
||||||
SE
|
SE
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button size="small" variant={locale === 'pl' ? 'contained' : 'outlined'} onClick={() => selectLocale('pl')}>
|
||||||
|
<PLflag style={{ width: 24 }} />
|
||||||
|
PL
|
||||||
|
</Button>
|
||||||
|
<Button size="small" variant={locale === 'no' ? 'contained' : 'outlined'} onClick={() => selectLocale('no')}>
|
||||||
|
<NOflag style={{ width: 24 }} />
|
||||||
|
NO
|
||||||
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import axios, { AxiosPromise, CancelToken } from 'axios';
|
import axios, { AxiosPromise, CancelToken, AxiosProgressEvent } from 'axios';
|
||||||
|
|
||||||
import { decode } from '@msgpack/msgpack';
|
import { decode } from '@msgpack/msgpack';
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ function calculateEventSourceRoot(endpointPath: string) {
|
|||||||
|
|
||||||
export interface FileUploadConfig {
|
export interface FileUploadConfig {
|
||||||
cancelToken?: CancelToken;
|
cancelToken?: CancelToken;
|
||||||
onUploadProgress?: (progressEvent: ProgressEvent) => void;
|
onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const startUploadFile = (url: string, file: File, config?: FileUploadConfig): AxiosPromise<void> => {
|
export const startUploadFile = (url: string, file: File, config?: FileUploadConfig): AxiosPromise<void> => {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ const LayoutAuthMenu: FC = () => {
|
|||||||
<PLflag style={{ width: 16, verticalAlign: 'middle' }} />
|
<PLflag style={{ width: 16, verticalAlign: 'middle' }} />
|
||||||
PL
|
PL
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem key="no" value="no" disabled>
|
<MenuItem key="no" value="no">
|
||||||
<NOflag style={{ width: 16, verticalAlign: 'middle' }} />
|
<NOflag style={{ width: 16, verticalAlign: 'middle' }} />
|
||||||
NO
|
NO
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { FC, Fragment } from 'react';
|
import { FC, Fragment } from 'react';
|
||||||
import { useDropzone, DropzoneState } from 'react-dropzone';
|
import { useDropzone, DropzoneState } from 'react-dropzone';
|
||||||
|
|
||||||
|
import { AxiosProgressEvent } from 'axios';
|
||||||
|
|
||||||
import { Box, Button, LinearProgress, Theme, Typography, useTheme } from '@mui/material';
|
import { Box, Button, LinearProgress, Theme, Typography, useTheme } from '@mui/material';
|
||||||
|
|
||||||
import CloudUploadIcon from '@mui/icons-material/CloudUpload';
|
import CloudUploadIcon from '@mui/icons-material/CloudUpload';
|
||||||
@@ -8,8 +10,6 @@ import CancelIcon from '@mui/icons-material/Cancel';
|
|||||||
|
|
||||||
import { useI18nContext } from '../../i18n/i18n-react';
|
import { useI18nContext } from '../../i18n/i18n-react';
|
||||||
|
|
||||||
const progressPercentage = (progress: ProgressEvent) => Math.round((progress.loaded * 100) / progress.total);
|
|
||||||
|
|
||||||
const getBorderColor = (theme: Theme, props: DropzoneState) => {
|
const getBorderColor = (theme: Theme, props: DropzoneState) => {
|
||||||
if (props.isDragAccept) {
|
if (props.isDragAccept) {
|
||||||
return theme.palette.success.main;
|
return theme.palette.success.main;
|
||||||
@@ -27,7 +27,7 @@ export interface SingleUploadProps {
|
|||||||
onDrop: (acceptedFiles: File[]) => void;
|
onDrop: (acceptedFiles: File[]) => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
uploading: boolean;
|
uploading: boolean;
|
||||||
progress?: ProgressEvent;
|
progress?: AxiosProgressEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, uploading, progress }) => {
|
const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, uploading, progress }) => {
|
||||||
@@ -47,8 +47,8 @@ const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, uploading, prog
|
|||||||
|
|
||||||
const progressText = () => {
|
const progressText = () => {
|
||||||
if (uploading) {
|
if (uploading) {
|
||||||
if (progress?.lengthComputable) {
|
if (progress?.total) {
|
||||||
return LL.UPLOADING() + `: ${progressPercentage(progress)}%`;
|
return LL.UPLOADING() + ': ' + Math.round((progress.loaded * 100) / progress.total) + '%';
|
||||||
}
|
}
|
||||||
return LL.UPLOADING() + `\u2026`;
|
return LL.UPLOADING() + `\u2026`;
|
||||||
}
|
}
|
||||||
@@ -80,8 +80,8 @@ const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, uploading, prog
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<Box width="100%" p={2}>
|
<Box width="100%" p={2}>
|
||||||
<LinearProgress
|
<LinearProgress
|
||||||
variant={!progress || progress.lengthComputable ? 'determinate' : 'indeterminate'}
|
variant={!progress || progress.total ? 'determinate' : 'indeterminate'}
|
||||||
value={!progress ? 0 : progress.lengthComputable ? progressPercentage(progress) : 0}
|
value={!progress ? 0 : progress.total ? Math.round((progress.loaded * 100) / progress.total) : 0}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Button startIcon={<CancelIcon />} variant="outlined" color="secondary" onClick={onCancel}>
|
<Button startIcon={<CancelIcon />} variant="outlined" color="secondary" onClick={onCancel}>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import axios, { AxiosPromise, CancelTokenSource } from 'axios';
|
import axios, { AxiosPromise, CancelTokenSource, AxiosProgressEvent } from 'axios';
|
||||||
import { useSnackbar } from 'notistack';
|
import { useSnackbar } from 'notistack';
|
||||||
|
|
||||||
import { extractErrorMessage } from '../../utils';
|
import { extractErrorMessage } from '../../utils';
|
||||||
@@ -16,7 +16,7 @@ const useFileUpload = ({ upload }: MediaUploadOptions) => {
|
|||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
const [uploading, setUploading] = useState<boolean>(false);
|
const [uploading, setUploading] = useState<boolean>(false);
|
||||||
const [uploadProgress, setUploadProgress] = useState<ProgressEvent>();
|
const [uploadProgress, setUploadProgress] = useState<AxiosProgressEvent>();
|
||||||
const [uploadCancelToken, setUploadCancelToken] = useState<CancelTokenSource>();
|
const [uploadCancelToken, setUploadCancelToken] = useState<CancelTokenSource>();
|
||||||
|
|
||||||
const resetUploadingStates = () => {
|
const resetUploadingStates = () => {
|
||||||
@@ -47,7 +47,7 @@ const useFileUpload = ({ upload }: MediaUploadOptions) => {
|
|||||||
});
|
});
|
||||||
resetUploadingStates();
|
resetUploadingStates();
|
||||||
enqueueSnackbar(LL.UPLOAD() + ' ' + LL.SUCCESSFUL(), { variant: 'success' });
|
enqueueSnackbar(LL.UPLOAD() + ' ' + LL.SUCCESSFUL(), { variant: 'success' });
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
if (axios.isCancel(error)) {
|
if (axios.isCancel(error)) {
|
||||||
enqueueSnackbar(LL.UPLOAD() + ' ' + LL.ABORTED(), { variant: 'warning' });
|
enqueueSnackbar(LL.UPLOAD() + ' ' + LL.ABORTED(), { variant: 'warning' });
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const Authentication: FC<RequiredChildrenProps> = ({ children }) => {
|
|||||||
const decodedMe = AuthenticationApi.decodeMeJWT(accessToken);
|
const decodedMe = AuthenticationApi.decodeMeJWT(accessToken);
|
||||||
setMe(decodedMe);
|
setMe(decodedMe);
|
||||||
enqueueSnackbar(LL.LOGGED_IN({ name: decodedMe.username }), { variant: 'success' });
|
enqueueSnackbar(LL.LOGGED_IN({ name: decodedMe.username }), { variant: 'success' });
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
setMe(undefined);
|
setMe(undefined);
|
||||||
throw new Error('Failed to parse JWT');
|
throw new Error('Failed to parse JWT');
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ const Authentication: FC<RequiredChildrenProps> = ({ children }) => {
|
|||||||
await AuthenticationApi.verifyAuthorization();
|
await AuthenticationApi.verifyAuthorization();
|
||||||
setMe(AuthenticationApi.decodeMeJWT(accessToken));
|
setMe(AuthenticationApi.decodeMeJWT(accessToken));
|
||||||
setInitialized(true);
|
setInitialized(true);
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
setMe(undefined);
|
setMe(undefined);
|
||||||
setInitialized(true);
|
setInitialized(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const FeaturesLoader: FC<RequiredChildrenProps> = (props) => {
|
|||||||
try {
|
try {
|
||||||
const response = await FeaturesApi.readFeatures();
|
const response = await FeaturesApi.readFeatures();
|
||||||
setFeatures(response.data);
|
setFeatures(response.data);
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
setErrorMessage(extractErrorMessage(error, 'Failed to fetch application details.'));
|
setErrorMessage(extractErrorMessage(error, 'Failed to fetch application details.'));
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
|||||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||||
import ReportIcon from '@mui/icons-material/Report';
|
import ReportIcon from '@mui/icons-material/Report';
|
||||||
import SpeakerNotesOffIcon from '@mui/icons-material/SpeakerNotesOff';
|
import SpeakerNotesOffIcon from '@mui/icons-material/SpeakerNotesOff';
|
||||||
|
import AutoAwesomeMotionIcon from '@mui/icons-material/AutoAwesomeMotion';
|
||||||
|
|
||||||
import { ButtonRow, FormLoader, SectionContent } from '../../components';
|
import { ButtonRow, FormLoader, SectionContent } from '../../components';
|
||||||
import { MqttStatus, MqttDisconnectReason } from '../../types';
|
import { MqttStatus, MqttDisconnectReason } from '../../types';
|
||||||
@@ -31,6 +32,12 @@ export const mqttPublishHighlight = ({ mqtt_fails }: MqttStatus, theme: Theme) =
|
|||||||
return theme.palette.error.main;
|
return theme.palette.error.main;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const mqttQueueHighlight = ({ mqtt_queued }: MqttStatus, theme: Theme) => {
|
||||||
|
if (mqtt_queued <= 1) return theme.palette.success.main;
|
||||||
|
|
||||||
|
return theme.palette.warning.main;
|
||||||
|
};
|
||||||
|
|
||||||
const MqttStatusForm: FC = () => {
|
const MqttStatusForm: FC = () => {
|
||||||
const { loadData, data, errorMessage } = useRest<MqttStatus>({ read: MqttApi.readMqttStatus });
|
const { loadData, data, errorMessage } = useRest<MqttStatus>({ read: MqttApi.readMqttStatus });
|
||||||
|
|
||||||
@@ -38,14 +45,14 @@ const MqttStatusForm: FC = () => {
|
|||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const mqttStatus = ({ enabled, connected }: MqttStatus) => {
|
const mqttStatus = ({ enabled, connected, connect_count }: MqttStatus) => {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return LL.NOT_ENABLED();
|
return LL.NOT_ENABLED();
|
||||||
}
|
}
|
||||||
if (connected) {
|
if (connected) {
|
||||||
return LL.CONNECTED();
|
return LL.CONNECTED() + (connect_count > 1 ? ' (' + connect_count + ')' : '');
|
||||||
}
|
}
|
||||||
return LL.DISCONNECTED();
|
return LL.DISCONNECTED() + (connect_count > 1 ? ' (' + connect_count + ')' : '');
|
||||||
};
|
};
|
||||||
|
|
||||||
const disconnectReason = ({ disconnect_reason }: MqttStatus) => {
|
const disconnectReason = ({ disconnect_reason }: MqttStatus) => {
|
||||||
@@ -77,36 +84,44 @@ const MqttStatusForm: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const renderConnectionStatus = () => {
|
const renderConnectionStatus = () => {
|
||||||
if (data.connected) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ListItem>
|
|
||||||
<ListItemAvatar>
|
|
||||||
<Avatar>#</Avatar>
|
|
||||||
</ListItemAvatar>
|
|
||||||
<ListItemText primary="Client ID" secondary={data.client_id} />
|
|
||||||
</ListItem>
|
|
||||||
<Divider variant="inset" component="li" />
|
|
||||||
<ListItem>
|
|
||||||
<ListItemAvatar>
|
|
||||||
<Avatar sx={{ bgcolor: mqttPublishHighlight(data, theme) }}>
|
|
||||||
<SpeakerNotesOffIcon />
|
|
||||||
</Avatar>
|
|
||||||
</ListItemAvatar>
|
|
||||||
<ListItemText primary={'MQTT Publish ' + LL.ERRORS()} secondary={data.mqtt_fails} />
|
|
||||||
</ListItem>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{!data.connected && (
|
||||||
|
<>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar>
|
||||||
|
<ReportIcon />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText primary={LL.DISCONNECT_REASON()} secondary={disconnectReason(data)} />
|
||||||
|
</ListItem>
|
||||||
|
<Divider variant="inset" component="li" />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
<Avatar>
|
<Avatar>#</Avatar>
|
||||||
<ReportIcon />
|
</ListItemAvatar>
|
||||||
|
<ListItemText primary="Client ID" secondary={data.client_id} />
|
||||||
|
</ListItem>
|
||||||
|
<Divider variant="inset" component="li" />
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar sx={{ bgcolor: mqttQueueHighlight(data, theme) }}>
|
||||||
|
<AutoAwesomeMotionIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary={LL.DISCONNECT_REASON()} secondary={disconnectReason(data)} />
|
<ListItemText primary="MQTT Queue" secondary={data.mqtt_queued} />
|
||||||
|
</ListItem>
|
||||||
|
<Divider variant="inset" component="li" />
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar sx={{ bgcolor: mqttPublishHighlight(data, theme) }}>
|
||||||
|
<SpeakerNotesOffIcon />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText primary={'MQTT ' + LL.ERRORS()} secondary={data.mqtt_fails} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { useEffect, FC, useState, useCallback, useRef } from 'react';
|
import { useEffect, FC, useState, useCallback, useRef } from 'react';
|
||||||
import { useSnackbar } from 'notistack';
|
import { useSnackbar } from 'notistack';
|
||||||
|
|
||||||
import { AxiosError } from 'axios';
|
|
||||||
|
|
||||||
import { Button } from '@mui/material';
|
import { Button } from '@mui/material';
|
||||||
import PermScanWifiIcon from '@mui/icons-material/PermScanWifi';
|
import PermScanWifiIcon from '@mui/icons-material/PermScanWifi';
|
||||||
|
|
||||||
@@ -57,8 +55,8 @@ const WiFiNetworkScanner: FC = () => {
|
|||||||
newNetworkList.networks.sort(compareNetworks);
|
newNetworkList.networks.sort(compareNetworks);
|
||||||
setNetworkList(newNetworkList);
|
setNetworkList(newNetworkList);
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
if (error instanceof AxiosError) {
|
if (error.response) {
|
||||||
finishedWithError(LL.PROBLEM_LOADING() + ' ' + error.response?.data.message);
|
finishedWithError(LL.PROBLEM_LOADING() + ' ' + error.response?.data.message);
|
||||||
} else {
|
} else {
|
||||||
finishedWithError(LL.PROBLEM_LOADING());
|
finishedWithError(LL.PROBLEM_LOADING());
|
||||||
@@ -73,8 +71,8 @@ const WiFiNetworkScanner: FC = () => {
|
|||||||
try {
|
try {
|
||||||
await NetworkApi.scanNetworks();
|
await NetworkApi.scanNetworks();
|
||||||
setTimeout(pollNetworkList, POLLING_FREQUENCY);
|
setTimeout(pollNetworkList, POLLING_FREQUENCY);
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
if (error instanceof AxiosError) {
|
if (error.response) {
|
||||||
finishedWithError(LL.PROBLEM_LOADING() + ' ' + error.response?.data.message);
|
finishedWithError(LL.PROBLEM_LOADING() + ' ' + error.response?.data.message);
|
||||||
} else {
|
} else {
|
||||||
finishedWithError(LL.PROBLEM_LOADING());
|
finishedWithError(LL.PROBLEM_LOADING());
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ const NTPStatusForm: FC = () => {
|
|||||||
enqueueSnackbar(LL.TIME_SET(), { variant: 'success' });
|
enqueueSnackbar(LL.TIME_SET(), { variant: 'success' });
|
||||||
setSettingTime(false);
|
setSettingTime(false);
|
||||||
loadData();
|
loadData();
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||||
} finally {
|
} finally {
|
||||||
setProcessing(false);
|
setProcessing(false);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const GenerateToken: FC<GenerateTokenProps> = ({ username, onClose }) => {
|
|||||||
const getToken = useCallback(async () => {
|
const getToken = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
setToken((await SecurityApi.generateToken(username)).data);
|
setToken((await SecurityApi.generateToken(username)).data);
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||||
}
|
}
|
||||||
}, [username, enqueueSnackbar, LL]);
|
}, [username, enqueueSnackbar, LL]);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
|||||||
} else {
|
} else {
|
||||||
saveFile(response.data, 'settings');
|
saveFile(response.data, 'settings');
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -63,7 +63,7 @@ const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
|||||||
} else {
|
} else {
|
||||||
saveFile(response.data, 'customizations');
|
saveFile(response.data, 'customizations');
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const RestartMonitor: FC = () => {
|
|||||||
try {
|
try {
|
||||||
await SystemApi.readSystemStatus(POLL_TIMEOUT);
|
await SystemApi.readSystemStatus(POLL_TIMEOUT);
|
||||||
document.location.href = '/fileUpdated';
|
document.location.href = '/fileUpdated';
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
if (new Date().getTime() < timeoutAt.current) {
|
if (new Date().getTime() < timeoutAt.current) {
|
||||||
setTimeoutId(setTimeout(poll.current, POLL_INTERVAL));
|
setTimeoutId(setTimeout(poll.current, POLL_INTERVAL));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ const SystemLog: FC = () => {
|
|||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' });
|
enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' });
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,7 +163,7 @@ const SystemLog: FC = () => {
|
|||||||
const fetchLog = useCallback(async () => {
|
const fetchLog = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
setLogEntries((await SystemApi.readLogEntries()).data);
|
setLogEntries((await SystemApi.readLogEntries()).data);
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
}
|
}
|
||||||
}, [LL]);
|
}, [LL]);
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ const SystemStatusForm: FC = () => {
|
|||||||
try {
|
try {
|
||||||
await SystemApi.restart();
|
await SystemApi.restart();
|
||||||
enqueueSnackbar(LL.APPLICATION_RESTARTING(), { variant: 'info' });
|
enqueueSnackbar(LL.APPLICATION_RESTARTING(), { variant: 'info' });
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||||
} finally {
|
} finally {
|
||||||
setConfirmRestart(false);
|
setConfirmRestart(false);
|
||||||
@@ -180,7 +180,7 @@ const SystemStatusForm: FC = () => {
|
|||||||
try {
|
try {
|
||||||
await SystemApi.factoryReset();
|
await SystemApi.factoryReset();
|
||||||
enqueueSnackbar(LL.SYSTEM_FACTORY_TEXT(), { variant: 'info' });
|
enqueueSnackbar(LL.SYSTEM_FACTORY_TEXT(), { variant: 'info' });
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||||
} finally {
|
} finally {
|
||||||
setConfirmFactoryReset(false);
|
setConfirmFactoryReset(false);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,270 +1,269 @@
|
|||||||
import type { BaseTranslation } from '../i18n-types';
|
import type { BaseTranslation } from '../i18n-types';
|
||||||
|
|
||||||
const no: BaseTranslation = {
|
const no: BaseTranslation = {
|
||||||
LANGUAGE: 'Language',
|
LANGUAGE: 'Språk',
|
||||||
RETRY: 'Retry',
|
RETRY: 'Forsøk igjen',
|
||||||
LOADING: 'Loading',
|
LOADING: 'Laster',
|
||||||
IS_REQUIRED: 'is required',
|
IS_REQUIRED: 'er nødvendig',
|
||||||
SIGN_IN: 'Sign In',
|
SIGN_IN: 'Logg inn',
|
||||||
SIGN_OUT: 'Sign Out',
|
SIGN_OUT: 'Logg ut',
|
||||||
USERNAME: 'Username',
|
USERNAME: 'Brukernavn',
|
||||||
PASSWORD: 'Password',
|
PASSWORD: 'Passord',
|
||||||
DASHBOARD: 'Dashboard',
|
DASHBOARD: 'Dashboard',
|
||||||
SETTINGS: 'Settings',
|
SETTINGS: 'Innstillinger',
|
||||||
SAVED: 'saved',
|
SAVED: 'lagret',
|
||||||
HELP: 'Help',
|
HELP: 'Hjelp',
|
||||||
LOGGED_IN: 'Logged in as {name}',
|
LOGGED_IN: 'Logget in som {name}',
|
||||||
PLEASE_SIGNIN: 'Please sign in to continue',
|
PLEASE_SIGNIN: 'Venligst logge inn for å fortsetta',
|
||||||
UPLOAD_SUCCESSFUL: 'Upload successful',
|
UPLOAD_SUCCESSFUL: 'Opplasting lykkes',
|
||||||
DOWNLOAD_SUCCESSFUL: 'Download successful',
|
DOWNLOAD_SUCCESSFUL: 'Nedlasting lykkes',
|
||||||
INVALID_LOGIN: 'Invalid login details',
|
INVALID_LOGIN: 'Ugyldig innlogging',
|
||||||
NETWORK: 'Network',
|
NETWORK: 'Nettverk',
|
||||||
SECURITY: 'Security',
|
SECURITY: 'Sikkerhet',
|
||||||
ONOFF_CAP: 'ON/OFF',
|
ONOFF_CAP: 'PÅ/AV',
|
||||||
ONOFF: 'on/off',
|
ONOFF: 'på/av',
|
||||||
TYPE: 'Type',
|
TYPE: 'Type',
|
||||||
DESCRIPTION: 'Description',
|
DESCRIPTION: 'Beskrivelse',
|
||||||
ENTITIES: 'Entities',
|
ENTITIES: 'Ojekter',
|
||||||
REFRESH: 'Refresh',
|
REFRESH: 'Oppdater',
|
||||||
EXPORT: 'Export',
|
EXPORT: 'Eksport',
|
||||||
DEVICE_DETAILS: 'Device Details',
|
DEVICE_DETAILS: 'Enhetsdetaljer',
|
||||||
BRAND: 'Brand',
|
BRAND: 'Fabrikat',
|
||||||
ENTITY_NAME: 'Entity Name',
|
ENTITY_NAME: 'Objektsnavn',
|
||||||
VALUE: 'Value',
|
VALUE: 'Verdi',
|
||||||
SHOW_FAV: 'only show favorites',
|
SHOW_FAV: ' Vis kun favoritter',
|
||||||
DEVICE_SENSOR_DATA: 'Device and Sensor Data',
|
DEVICE_SENSOR_DATA: 'Enheter og Sensordata',
|
||||||
DEVICES_SENSORS: 'Devices & Sensors',
|
DEVICES_SENSORS: 'Enheter og Sensorer',
|
||||||
ATTACHED_SENSORS: 'Attached EMS-ESP Sensors',
|
ATTACHED_SENSORS: 'Tilkoblede EMS-ESP Sensorer',
|
||||||
RUN_COMMAND: 'Call Command',
|
RUN_COMMAND: 'Kjør kommando',
|
||||||
CHANGE_VALUE: 'Change Value',
|
CHANGE_VALUE: 'Endre Verdi',
|
||||||
CANCEL: 'Cancel',
|
CANCEL: 'Avbryt',
|
||||||
RESET: 'Reset',
|
RESET: 'Nullstill',
|
||||||
SEND: 'Send',
|
SEND: 'Send',
|
||||||
SAVE: 'Save',
|
SAVE: 'Lagre',
|
||||||
REMOVE: 'Remove',
|
REMOVE: 'Fjern',
|
||||||
PROBLEM_UPDATING: 'Problem updating',
|
PROBLEM_UPDATING: 'Problem med oppdatering',
|
||||||
PROBLEM_LOADING: 'Problem loading',
|
PROBLEM_LOADING: 'Problem med opplasting',
|
||||||
ACCESS_DENIED: 'Access Denied',
|
ACCESS_DENIED: 'Tilgang nektet',
|
||||||
ANALOG_SENSOR: 'Analog Sensor',
|
ANALOG_SENSOR: 'Analog Sensor',
|
||||||
ANALOG_SENSORS: 'Analog Sensors',
|
ANALOG_SENSORS: 'Analoge Sensorer',
|
||||||
UPDATED: 'Updated',
|
UPDATED: 'Oppdatert',
|
||||||
UPDATE: 'Update',
|
UPDATE: 'Oppdater',
|
||||||
REMOVED: 'Removed',
|
REMOVED: 'Slettet',
|
||||||
DELETION: 'Deletion',
|
DELETION: 'Sletting',
|
||||||
OFFSET: 'Offset',
|
OFFSET: 'Kompensering',
|
||||||
FACTOR: 'Factor',
|
FACTOR: 'Faktor',
|
||||||
FREQ: 'Frequency',
|
FREQ: 'Frekvens',
|
||||||
STARTVALUE: 'Start value',
|
STARTVALUE: 'Startverdi',
|
||||||
WARN_GPIO: 'Warning: be careful when assigning a GPIO!',
|
WARN_GPIO: 'Advarsel: vær forsiktig ved aktivering av GPIO!',
|
||||||
EDIT: 'Edit',
|
EDIT: 'Endre',
|
||||||
TEMP_SENSOR: 'Temperature Sensor',
|
TEMP_SENSOR: 'Temperatursensor',
|
||||||
TEMP_SENSORS: 'Temperature Sensors',
|
TEMP_SENSORS: 'Temperaturesensorer',
|
||||||
WRITE_COMMAND: 'Write command {cmd}',
|
WRITE_COMMAND: 'Skriv kommando {cmd}',
|
||||||
EMS_BUS_WARNING:
|
EMS_BUS_WARNING:
|
||||||
'EMS bus disconnected. If this warning still persists after a few seconds please check settings and board profile',
|
'EMS bussen koblet ned. Hvis denne advarselen fortsetter etter noen f¨sekunder sjekk instillinger og prosessorkort',
|
||||||
EMS_BUS_SCANNING: 'Scanning for EMS devices...',
|
EMS_BUS_SCANNING: 'Søker etter EMS enheter...',
|
||||||
CONNECTED: 'Connected',
|
CONNECTED: 'Tilkoblet',
|
||||||
TX_ISSUES: 'Tx issues - try a different Tx Mode',
|
TX_ISSUES: 'Tx problemer - prøv en annen Tx Modus',
|
||||||
DISCONNECTED: 'Disconnected',
|
DISCONNECTED: 'Frakoblet',
|
||||||
EMS_SCAN: 'Are you sure you want to initiate a full device scan of the EMS bus?',
|
EMS_SCAN: 'Er du sikker på du vil starte full søking av EMS bussen?',
|
||||||
EMS_BUS_STATUS: 'EMS Bus Status',
|
EMS_BUS_STATUS: 'EMS Buss Status',
|
||||||
ACTIVE_DEVICES: 'Active Devices & Sensors',
|
ACTIVE_DEVICES: 'Aktive Enheter og Sensorer',
|
||||||
DEVICE: 'Device',
|
DEVICE: 'Enhet',
|
||||||
SUCCESS: 'SUCCESS',
|
SUCCESS: 'VELLYKKET',
|
||||||
FAIL: 'FAIL',
|
FAIL: 'MISLYKKET',
|
||||||
QUALITY: 'QUALITY',
|
QUALITY: 'KVALITET',
|
||||||
SCAN_DEVICES: 'Scan for new devices',
|
SCAN_DEVICES: 'Søk etter nye enheter',
|
||||||
EMS_BUS_STATUS_TITLE: 'EMS Bus & Activity Status',
|
EMS_BUS_STATUS_TITLE: 'EMS Buss & Aktivitet Status',
|
||||||
SCAN: 'Scan',
|
SCAN: 'Søk',
|
||||||
STATUS_NAMES: [
|
STATUS_NAMES: [
|
||||||
'EMS Telegrams Received (Rx)',
|
'EMS Telegrammer Mottatt (Rx)',
|
||||||
'EMS Reads (Tx)',
|
'EMS Lest (Tx)',
|
||||||
'EMS Writes (Tx)',
|
'EMS Skrevet (Tx)',
|
||||||
'Temperature Sensor Reads',
|
'Temperatur Sensor Lest',
|
||||||
'Analog Sensor Reads',
|
'Analog Sensor Lest',
|
||||||
'MQTT Publishes',
|
'MQTT Publiseringer',
|
||||||
'API Calls',
|
'API Anrop',
|
||||||
'Syslog Messages'
|
'Syslog Meldinger'
|
||||||
],
|
],
|
||||||
NUM_DEVICES: '{num} Device{{s}}',
|
NUM_DEVICES: '{num} Enhet{{er}}',
|
||||||
NUM_TEMP_SENSORS: '{num} Temperature Sensor{{s}}',
|
NUM_TEMP_SENSORS: '{num} Temperatursensor{{er}}',
|
||||||
NUM_ANALOG_SENSORS: '{num} Analog Sensor{{s}}',
|
NUM_ANALOG_SENSORS: '{num} Analogsensor{{er}}',
|
||||||
NUM_DAYS: '{num} Day{{s}}',
|
NUM_DAYS: '{num} Dag{{er}}',
|
||||||
NUM_SECONDS: '{num} Second{{s}}',
|
NUM_SECONDS: '{num} Sekund{{er}}',
|
||||||
NUM_HOURS: '{num} Hour{{s}}',
|
NUM_HOURS: '{num} Time{{r}}',
|
||||||
NUM_MINUTES: '{num} Minute{{s}}',
|
NUM_MINUTES: '{num} Minutt{{er}}',
|
||||||
APPLICATION_SETTINGS: 'Application Settings',
|
APPLICATION_SETTINGS: 'Innstillinger',
|
||||||
CUSTOMIZATION: 'Customization',
|
CUSTOMIZATION: 'Tilpasninger',
|
||||||
APPLICATION_RESTARTING: 'EMS-ESP is restarting',
|
APPLICATION_RESTARTING: 'EMS-ESP restarter',
|
||||||
BOARD_PROFILE_TEXT:
|
BOARD_PROFILE_TEXT:
|
||||||
'Select a pre-configured interface board profile from the list below or choose Custom to configure your own hardware settings',
|
'Velg en pre-konfigurert prosessor profil fra listen under eller velg Tilpasset for å konfigurere dine egne innstillinger',
|
||||||
BOARD_PROFILE: 'Board Profile',
|
BOARD_PROFILE: 'Prosessor Profil',
|
||||||
BUTTON: 'Button',
|
BUTTON: 'Knapp',
|
||||||
TEMPERATURE: 'Temperature',
|
TEMPERATURE: 'Temperatur',
|
||||||
DISABLED: 'disabled',
|
DISABLED: 'avslått',
|
||||||
GENERAL_OPTIONS: 'General Options',
|
GENERAL_OPTIONS: 'Generelle Innstillinger',
|
||||||
LANGUAGE_ENTITIES: 'Language (for device entities)',
|
LANGUAGE_ENTITIES: 'Språk (for objekter)',
|
||||||
HIDE_LED: 'Hide LED',
|
HIDE_LED: 'Skjul LED',
|
||||||
ENABLE_TELNET: 'Enable Telnet Console',
|
ENABLE_TELNET: 'Aktiver Telnet',
|
||||||
ENABLE_ANALOG: 'Enable Analog Sensors',
|
ENABLE_ANALOG: 'Aktiver Analoge Sensorer',
|
||||||
CONVERT_FAHRENHEIT: 'Convert temperature values to Fahrenheit',
|
CONVERT_FAHRENHEIT: 'Konverter temperatur til Fahrenheit',
|
||||||
BYPASS_TOKEN: 'Bypass Access Token authorization on API calls',
|
BYPASS_TOKEN: 'Utelat Aksess Token authorisering av API kall',
|
||||||
READONLY: 'Enable read-only mode (blocks all outgoing EMS Tx Write commands)',
|
READONLY: 'Aktiver read-only modus (blokker all EMS Tx Skriving)',
|
||||||
UNDERCLOCK_CPU: 'Underclock CPU speed',
|
UNDERCLOCK_CPU: 'Underklokking av prosessorhastighet',
|
||||||
ENABLE_SHOWER_TIMER: 'Enable Shower Timer',
|
ENABLE_SHOWER_TIMER: 'Aktiver Dusjtimer',
|
||||||
ENABLE_SHOWER_ALERT: 'Enable Shower Alert',
|
ENABLE_SHOWER_ALERT: 'Aktiver Dusj-varsling',
|
||||||
TRIGGER_TIME: 'Trigger Time',
|
TRIGGER_TIME: 'Aktiveringstid',
|
||||||
COLD_SHOT_DURATION: 'Cold Shot Duration',
|
COLD_SHOT_DURATION: 'Tid på kaldt vann',
|
||||||
FORMATTING_OPTIONS: 'Formatting Options',
|
FORMATTING_OPTIONS: 'Formatteringsalternativs',
|
||||||
BOOLEAN_FORMAT_DASHBOARD: 'Boolean Format Dashboard',
|
BOOLEAN_FORMAT_DASHBOARD: 'Bool Format Dashboard',
|
||||||
BOOLEAN_FORMAT_API: 'Boolean Format API/MQTT',
|
BOOLEAN_FORMAT_API: 'Bool Format API/MQTT',
|
||||||
ENUM_FORMAT: 'Enum Format API/MQTT',
|
ENUM_FORMAT: 'Enum Format API/MQTT',
|
||||||
INDEX: 'Index',
|
INDEX: 'Indeks',
|
||||||
ENABLE_PARASITE: 'Enable parasite power',
|
ENABLE_PARASITE: 'Aktiver parasitt strømforsyning',
|
||||||
LOGGING: 'Logging',
|
LOGGING: 'Logging',
|
||||||
LOG_HEX: 'Log EMS telegrams in hexadecimal',
|
LOG_HEX: 'Logg EMS telegrammer i hexadesimal',
|
||||||
ENABLE_SYSLOG: 'Enable Syslog',
|
ENABLE_SYSLOG: 'Aktiver Syslog',
|
||||||
MARK_INTERVAL: 'Mark Interval',
|
MARK_INTERVAL: 'Oppdateringsintervall',
|
||||||
SECONDS: 'seconds',
|
SECONDS: 'sekunder',
|
||||||
MINUTES: 'minutes',
|
MINUTES: 'minutter',
|
||||||
RESTART: 'Restart',
|
RESTART: 'Omstart',
|
||||||
HOURS: 'hours',
|
HOURS: 'timer',
|
||||||
RESTART_TEXT: 'EMS-ESP needs to be restarted to apply changed system settings',
|
RESTART_TEXT: 'EMS-ESP må omstartes for å iverksette endrede systeminstillinger',
|
||||||
RESTART_CONFIRM: 'Are you sure you want to restart EMS-ESP?',
|
RESTART_CONFIRM: 'Er du sikker på at du vil omstarte EMS-ESP?',
|
||||||
COMMAND: 'Command',
|
COMMAND: 'Kommando',
|
||||||
CUSTOMIZATIONS_RESTART: 'All customizations have been removed. Restarting...',
|
CUSTOMIZATIONS_RESTART: 'Alle tilpasninger har blitt slettet. Restarter...',
|
||||||
CUSTOMIZATIONS_FULL: 'Selected entities exceeded limit. Please save in batches',
|
CUSTOMIZATIONS_FULL: 'Antall valgte objekter for høyt. Largre i mindre antall om gangen',
|
||||||
CUSTOMIZATIONS_SAVED: 'Customizations saved',
|
CUSTOMIZATIONS_SAVED: 'Tilpasninger lagret',
|
||||||
CUSTOMIZATIONS_HELP_1: 'Select a device and customize the entities options or click to rename',
|
CUSTOMIZATIONS_HELP_1: 'Velg en enhet og tilpass underenheter med hjelp av alternativer eller velg å gi nytt navn',
|
||||||
CUSTOMIZATIONS_HELP_2: 'mark as favorite',
|
CUSTOMIZATIONS_HELP_2: 'merk som favoritt',
|
||||||
CUSTOMIZATIONS_HELP_3: 'disable write action',
|
CUSTOMIZATIONS_HELP_3: 'inaktiviser skriving',
|
||||||
CUSTOMIZATIONS_HELP_4: 'exclude from MQTT and API',
|
CUSTOMIZATIONS_HELP_4: 'ekskludere fra MQTT og API',
|
||||||
CUSTOMIZATIONS_HELP_5: 'hide from Dashboard',
|
CUSTOMIZATIONS_HELP_5: 'gjemme fra Dashboard',
|
||||||
SELECT_DEVICE: 'Select a device',
|
SELECT_DEVICE: 'Velg en enhet',
|
||||||
SET_ALL: 'set all',
|
SET_ALL: 'sett alle',
|
||||||
OPTIONS: 'Options',
|
OPTIONS: 'Alternativ',
|
||||||
NAME: 'Name',
|
NAME: 'Navn',
|
||||||
CUSTOMIZATIONS_RESET:
|
CUSTOMIZATIONS_RESET:
|
||||||
'Are you sure you want remove all customizations including the custom settings of the Temperature and Analog sensors?',
|
'Er du sikker på att du vil fjerne tilpassninger inkludert innstillinger for Temperatur og Analoge sensorer?',
|
||||||
DEVICE_ENTITIES: 'Device Entities',
|
DEVICE_ENTITIES: 'Enhets objekter',
|
||||||
USER_CUSTOMIZATION: 'User Customization',
|
USER_CUSTOMIZATION: 'Brukertilpasninger',
|
||||||
SUPPORT_INFORMATION: 'Support Information',
|
SUPPORT_INFORMATION: 'Supportinformasjon',
|
||||||
CLICK_HERE: 'Click Here',
|
CLICK_HERE: 'Klikk her',
|
||||||
HELP_INFORMATION_1: 'Visit the online wiki to get instructions on how to configure EMS-ESP',
|
HELP_INFORMATION_1: 'Besøk wiki for instruksjoner for å konfigurere EMS-ESP',
|
||||||
HELP_INFORMATION_2: 'For live community chat join our Discord server',
|
HELP_INFORMATION_2: 'For community-support besøk vår Discord-server',
|
||||||
HELP_INFORMATION_3: 'To request a feature or report a bug',
|
HELP_INFORMATION_3: 'For å be om en ny funksjon eller melde feil',
|
||||||
HELP_INFORMATION_4:
|
HELP_INFORMATION_4:
|
||||||
'remember to download and attach your system information for a faster response when reporting an issue',
|
'husk å laste ned og legg ved din systeminformasjon for en raskere respons når du rapporterer et problem',
|
||||||
HELP_INFORMATION_5:
|
HELP_INFORMATION_5: 'EMS-ESP er gratis og åpen kildekode. Bidra til utviklingen ved å gi oss en stjerne på GitHub!',
|
||||||
'EMS-ESP is a free and open-source project. Please support its future development by giving it a star on Github!',
|
SUPPORT_INFO: 'Supportinfo',
|
||||||
SUPPORT_INFO: 'Support Info',
|
UPLOAD: 'Opplasning',
|
||||||
UPLOAD: 'Upload',
|
DOWNLOAD: 'Nedlasting',
|
||||||
DOWNLOAD: 'Download',
|
ABORTED: 'avbrutt',
|
||||||
ABORTED: 'aborted',
|
FAILED: 'feilet',
|
||||||
FAILED: 'failed',
|
SUCCESSFUL: 'vellykket',
|
||||||
SUCCESSFUL: 'successful',
|
|
||||||
SYSTEM: 'System',
|
SYSTEM: 'System',
|
||||||
LOG: 'Log',
|
LOG: 'Logg',
|
||||||
STATUS: 'Status',
|
STATUS: 'Status',
|
||||||
UPLOAD_DOWNLOAD: 'Upload/Download',
|
UPLOAD_DOWNLOAD: 'Opp/Nedlasting',
|
||||||
SYSTEM_VERSION_RUNNING: 'You are currently running version',
|
SYSTEM_VERSION_RUNNING: 'Du benytter versjon',
|
||||||
SYSTEM_APPLY_FIRMWARE: 'to apply the new firmware',
|
SYSTEM_APPLY_FIRMWARE: 'for å aktivere ny firmware',
|
||||||
CLOSE: 'Close',
|
CLOSE: 'Steng',
|
||||||
USE: 'Use',
|
USE: 'Bruk',
|
||||||
FACTORY_RESET: 'Factory Reset',
|
FACTORY_RESET: 'Sett tilbake til fabrikkinstilling',
|
||||||
SYSTEM_FACTORY_TEXT: 'Device has been factory reset and will now restart',
|
SYSTEM_FACTORY_TEXT: 'Enhet har blitt satt tilbake til fabrikkinstilling og vil restarte',
|
||||||
SYSTEM_FACTORY_TEXT_DIALOG: 'Are you sure you want to reset the device to its factory defaults?',
|
SYSTEM_FACTORY_TEXT_DIALOG: 'Er du sikker på at du vil resette enheten til fabrikkinstillinger?',
|
||||||
VERSION_CHECK: 'Version Check',
|
VERSION_CHECK: 'Versjonsjekk',
|
||||||
THE_LATEST: 'The latest',
|
THE_LATEST: 'Den nyeste',
|
||||||
VERSION_IS: 'version is',
|
VERSION_IS: 'versjonen er',
|
||||||
PLATFORM: 'Device (Platform / SDK)',
|
PLATFORM: 'Enhet (Platform / SDK)',
|
||||||
UPTIME: 'System Uptime',
|
UPTIME: 'System Oppetid',
|
||||||
CPU_FREQ: 'CPU Frequency',
|
CPU_FREQ: 'CPU Frekvens',
|
||||||
HEAP: 'Heap (Free / Max Alloc)',
|
HEAP: 'Heap (Ledig / Max Allokert)',
|
||||||
PSRAM: 'PSRAM (Size / Free)',
|
PSRAM: 'PSRAM (Størrelse / Ledig)',
|
||||||
FLASH: 'Flash Chip (Size / Speed)',
|
FLASH: 'Flash Chip (Størrelse / Hastighet)',
|
||||||
APPSIZE: 'Application (Used / Free)',
|
APPSIZE: 'Applikasjon (Brukt / Ledig)',
|
||||||
FILESYSTEM: 'File System (Used / Free)',
|
FILESYSTEM: 'File System (Brukt / Ledig)',
|
||||||
BUFFER_SIZE: 'Buffer Size',
|
BUFFER_SIZE: 'Buffer Størrelse',
|
||||||
COMPACT: 'Compact',
|
COMPACT: 'Komprimere',
|
||||||
ENABLE_OTA: 'Enable OTA Updates',
|
ENABLE_OTA: 'Aktiviser OTA oppdateringer',
|
||||||
DOWNLOAD_CUSTOMIZATION_TEXT: 'Download the entity customizations',
|
DOWNLOAD_CUSTOMIZATION_TEXT: 'Last ned objektstilpasninger',
|
||||||
DOWNLOAD_SETTINGS_TEXT:
|
DOWNLOAD_SETTINGS_TEXT:
|
||||||
'Download the application settings. Be careful when sharing your settings as this file contains passwords and other sensitive system information',
|
'Last ned applikasjonskonfigurasjon. Vær varsom med å dele fila da den inneholder passord og annen sensitiv system informasjon',
|
||||||
UPLOAD_TEXT: 'Upload a new firmware (.bin) file, settings or customizations (.json) file below',
|
UPLOAD_TEXT: 'Last opp en ny firmware (.bin) fil, innstillinger eller tilpassninger (.json) fil nedenfor',
|
||||||
UPLOADING: 'Uploading',
|
UPLOADING: 'Opplasting',
|
||||||
UPLOAD_DROP_TEXT: 'Drop file or click here',
|
UPLOAD_DROP_TEXT: 'Slipp fil eller klikk her',
|
||||||
ERROR: 'Unexpected Error, please try again',
|
ERROR: 'Ukjent feil, prøv igjen',
|
||||||
TIME_SET: 'Time set',
|
TIME_SET: 'Still in tid',
|
||||||
MANAGE_USERS: 'Manage Users',
|
MANAGE_USERS: 'Administrer Brukere',
|
||||||
IS_ADMIN: 'is Admin',
|
IS_ADMIN: 'er Admin',
|
||||||
USER_WARNING: 'You must have at least one admin user configured',
|
USER_WARNING: 'Du må ha minst en admin bruker konfigurert',
|
||||||
ADD: 'Add',
|
ADD: 'Legg til',
|
||||||
ACCESS_TOKEN_FOR: 'Access Token for',
|
ACCESS_TOKEN_FOR: 'Aksess Token for',
|
||||||
ACCESS_TOKEN_TEXT:
|
ACCESS_TOKEN_TEXT:
|
||||||
'The token below is used with REST API calls that require authorization. It can be passed either as a Bearer token in the Authorization header or in the access_token URL query parameter.',
|
'Token nedenfor benyttes med REST API-kall som krever autorisering. Den kan sendes med enten som en Bearer token i Authorization-headern eller i access_token URL query-parameter.',
|
||||||
GENERATING_TOKEN: 'Generating token',
|
GENERATING_TOKEN: 'Generer token',
|
||||||
USER: 'User',
|
USER: 'Bruker',
|
||||||
MODIFY: 'Modify',
|
MODIFY: 'Endre',
|
||||||
SU_TEXT:
|
SU_TEXT:
|
||||||
'The su (super user) password is used to sign authentication tokens and also enable admin privileges within the Console.',
|
'su brukeren (super user) passord benyttes for å signere autentiserings token samt å tillate admin privileger i konsoll modus.',
|
||||||
NOT_ENABLED: 'Not enabled',
|
NOT_ENABLED: 'Ikke aktiv',
|
||||||
ERRORS: 'Errors',
|
ERRORS: 'Feil',
|
||||||
DISCONNECT_REASON: 'Disconnect Reason',
|
DISCONNECT_REASON: 'Årsak til nedkobling',
|
||||||
ENABLE_MQTT: 'Enable MQTT',
|
ENABLE_MQTT: 'Aktiver MQTT',
|
||||||
OPTIONAL: 'Optional',
|
OPTIONAL: 'Valgfritt',
|
||||||
FORMATTING: 'Formatting',
|
FORMATTING: 'Formatering',
|
||||||
FORMAT: 'Format',
|
FORMAT: 'Format',
|
||||||
MQTT_NEST_1: 'Nested in a single topic',
|
MQTT_NEST_1: 'Nestet i en topic',
|
||||||
MQTT_NEST_2: 'As individual topics',
|
MQTT_NEST_2: 'Som individuelle topics',
|
||||||
MQTT_RESPONSE: 'Publish command output to a `response` topic',
|
MQTT_RESPONSE: 'Publiser kommandoer til en `response` topic',
|
||||||
MQTT_PUBLISH_TEXT_1: 'Publish single value topics on change',
|
MQTT_PUBLISH_TEXT_1: 'Publiser singel verdi topics ved endringer',
|
||||||
MQTT_PUBLISH_TEXT_2: 'Publish to command topics (ioBroker)',
|
MQTT_PUBLISH_TEXT_2: 'Publiser til kommando topics (ioBroker)',
|
||||||
MQTT_PUBLISH_TEXT_3: 'Enable MQTT Discovery (Home Assistant, Domoticz)',
|
MQTT_PUBLISH_TEXT_3: 'Aktiver MQTT Discovery (Home Assistant, Domoticz)',
|
||||||
MQTT_PUBLISH_TEXT_4: 'Prefix for the Discovery topics',
|
MQTT_PUBLISH_TEXT_4: 'Prefiks for Discovery topics',
|
||||||
MQTT_PUBLISH_INTERVALS: 'Publish Intervals',
|
MQTT_PUBLISH_INTERVALS: 'Publiseringsintervall',
|
||||||
MQTT_INT_BOILER: 'Boilers and Heat Pumps',
|
MQTT_INT_BOILER: 'Fyr/Varmepumpe',
|
||||||
MQTT_INT_THERMOSTATS: 'Thermostats',
|
MQTT_INT_THERMOSTATS: 'Termostat',
|
||||||
MQTT_INT_SOLAR: 'Solar Modules',
|
MQTT_INT_SOLAR: 'Solpaneler',
|
||||||
MQTT_INT_MIXER: 'Mixer Modules',
|
MQTT_INT_MIXER: 'Blandeventil',
|
||||||
DEFAULT: 'Default',
|
DEFAULT: 'Standard',
|
||||||
MQTT_CLEAN_SESSION: 'Set Clean Session',
|
MQTT_CLEAN_SESSION: 'Benytt Clean Session',
|
||||||
MQTT_RETAIN_FLAG: 'Always set Retain flag',
|
MQTT_RETAIN_FLAG: 'Alltid sett Retain flag',
|
||||||
INACTIVE: 'Inactive',
|
INACTIVE: 'Innaktiv',
|
||||||
ACTIVE: 'Active',
|
ACTIVE: 'Aktiv',
|
||||||
UNKNOWN: 'Unknown',
|
UNKNOWN: 'Ukjent',
|
||||||
SET_TIME: 'Set Time',
|
SET_TIME: 'Sett Tid',
|
||||||
SET_TIME_TEXT: 'Enter local date and time below to set the time',
|
SET_TIME_TEXT: 'Skriv inn dato og klokke nedenfor',
|
||||||
LOCAL_TIME: 'Local Time',
|
LOCAL_TIME: 'Lokaltid',
|
||||||
UTC_TIME: 'UTC Time',
|
UTC_TIME: 'UTC Tid',
|
||||||
ENABLE_NTP: 'Enable NTP',
|
ENABLE_NTP: 'Aktiver NTP',
|
||||||
TIME_ZONE: 'Time Zone',
|
TIME_ZONE: 'Tidssone',
|
||||||
ACCESS_POINT: 'Access Point',
|
ACCESS_POINT: 'Aksesspunkt',
|
||||||
AP_PROVIDE: 'Enable Access Point',
|
AP_PROVIDE: 'Aktiver Aksesspunkt',
|
||||||
AP_PROVIDE_TEXT_1: 'always',
|
AP_PROVIDE_TEXT_1: 'alltid',
|
||||||
AP_PROVIDE_TEXT_2: 'when WiFi is disconnected',
|
AP_PROVIDE_TEXT_2: 'når WiFi er utilgjengelig',
|
||||||
AP_PROVIDE_TEXT_3: 'never',
|
AP_PROVIDE_TEXT_3: 'aldri',
|
||||||
AP_PREFERRED_CHANNEL: 'Preferred Channel',
|
AP_PREFERRED_CHANNEL: 'Foretrukket kanal',
|
||||||
AP_HIDE_SSID: 'Hide SSID',
|
AP_HIDE_SSID: 'Skjul SSID',
|
||||||
NETWORK_SCAN: 'Scan WiFi Networks',
|
NETWORK_SCAN: 'Søk etter trådløst nettverk',
|
||||||
IDLE: 'Idle',
|
IDLE: 'Klar',
|
||||||
LOST: 'Lost',
|
LOST: 'Mistet',
|
||||||
SCANNING: 'Scanning',
|
SCANNING: 'Søker',
|
||||||
SCAN_AGAIN: 'Scan again',
|
SCAN_AGAIN: 'Søk igjen',
|
||||||
NETWORK_SCANNER: 'Network Scanner',
|
NETWORK_SCANNER: 'Nettverk Scanner',
|
||||||
NETWORK_NO_WIFI: 'No WiFi networks found',
|
NETWORK_NO_WIFI: 'Ingen trådløse nett funnet',
|
||||||
NETWORK_BLANK_SSID: 'leave blank to disable WiFi',
|
NETWORK_BLANK_SSID: 'la feltet være blankt for å deaktivisere trådløst nettverk',
|
||||||
POWER: 'Power',
|
POWER: 'Effekt',
|
||||||
NETWORK_DISABLE_SLEEP: 'Disable WiFi Sleep Mode',
|
NETWORK_DISABLE_SLEEP: 'Hindre at trådløst nettverk går i Sleep Mode',
|
||||||
NETWORK_LOW_BAND: 'Use Lower WiFi Bandwidth',
|
NETWORK_LOW_BAND: 'Benytt smalere båndbredde på trådløst nettverk',
|
||||||
NETWORK_USE_DNS: 'Enable mDNS Service',
|
NETWORK_USE_DNS: 'Aktiviser mDNS Service',
|
||||||
NETWORK_ENABLE_IPV6: 'Enable IPv6 support',
|
NETWORK_ENABLE_IPV6: 'Aktiviser IPv6 støtte',
|
||||||
NETWORK_FIXED_IP: 'Use Fixed IP address',
|
NETWORK_FIXED_IP: 'Benytt statisk IP adresse',
|
||||||
ADMIN: 'Admin',
|
ADMIN: 'Admin',
|
||||||
GUEST: 'Guest',
|
GUEST: 'Gjest',
|
||||||
NEW: 'New',
|
NEW: 'Ny',
|
||||||
RENAME: 'Rename',
|
RENAME: 'Bytt navn',
|
||||||
ENTITY: 'Entity'
|
ENTITY: 'Entitet'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default no;
|
export default no;
|
||||||
|
|||||||
@@ -96,8 +96,7 @@ const pl: BaseTranslation = {
|
|||||||
APPLICATION_SETTINGS: 'Ustawienia aplikacji',
|
APPLICATION_SETTINGS: 'Ustawienia aplikacji',
|
||||||
CUSTOMIZATION: 'Personalizacja',
|
CUSTOMIZATION: 'Personalizacja',
|
||||||
APPLICATION_RESTARTING: 'Trwa ponowne uruchamianie',
|
APPLICATION_RESTARTING: 'Trwa ponowne uruchamianie',
|
||||||
BOARD_PROFILE_TEXT:
|
BOARD_PROFILE_TEXT: 'Wybierz z listy wstępną konfigurację płytki interfejsu lub stwórz własną konfigurację.',
|
||||||
'Wybierz z listy wstępną konfigurację płytki interfejsu lub stwórz własną konfigurację.',
|
|
||||||
BOARD_PROFILE: 'Profil płytki',
|
BOARD_PROFILE: 'Profil płytki',
|
||||||
BUTTON: 'Przycisk',
|
BUTTON: 'Przycisk',
|
||||||
TEMPERATURE: 'Temperatura',
|
TEMPERATURE: 'Temperatura',
|
||||||
|
|||||||
@@ -364,7 +364,7 @@ const DashboardData: FC = () => {
|
|||||||
const fetchCoreData = useCallback(async () => {
|
const fetchCoreData = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
setCoreData((await EMSESP.readCoreData()).data);
|
setCoreData((await EMSESP.readCoreData()).data);
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||||
}
|
}
|
||||||
}, [enqueueSnackbar, LL]);
|
}, [enqueueSnackbar, LL]);
|
||||||
@@ -385,7 +385,7 @@ const DashboardData: FC = () => {
|
|||||||
const unique_id = parseInt(id);
|
const unique_id = parseInt(id);
|
||||||
try {
|
try {
|
||||||
setDeviceData((await EMSESP.readDeviceData({ id: unique_id })).data);
|
setDeviceData((await EMSESP.readDeviceData({ id: unique_id })).data);
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -393,7 +393,7 @@ const DashboardData: FC = () => {
|
|||||||
const fetchSensorData = async () => {
|
const fetchSensorData = async () => {
|
||||||
try {
|
try {
|
||||||
setSensorData((await EMSESP.readSensorData()).data);
|
setSensorData((await EMSESP.readSensorData()).data);
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -474,7 +474,7 @@ const DashboardData: FC = () => {
|
|||||||
enqueueSnackbar(LL.WRITE_COMMAND({ cmd: 'send' }), { variant: 'success' });
|
enqueueSnackbar(LL.WRITE_COMMAND({ cmd: 'send' }), { variant: 'success' });
|
||||||
}
|
}
|
||||||
setDeviceValue(undefined);
|
setDeviceValue(undefined);
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||||
} finally {
|
} finally {
|
||||||
refreshData();
|
refreshData();
|
||||||
@@ -508,7 +508,7 @@ const DashboardData: FC = () => {
|
|||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
name="v"
|
name="v"
|
||||||
label={deviceValue.id.slice(2)}
|
label={deviceValue.id.slice(2)}
|
||||||
value={deviceValue.u ? numberValue(deviceValue.v) : deviceValue.v}
|
value={typeof deviceValue.v === 'number' ? Math.round(deviceValue.v * 10) / 10 : deviceValue.v}
|
||||||
autoFocus
|
autoFocus
|
||||||
multiline={deviceValue.u ? false : true}
|
multiline={deviceValue.u ? false : true}
|
||||||
sx={{ width: '30ch' }}
|
sx={{ width: '30ch' }}
|
||||||
@@ -566,7 +566,7 @@ const DashboardData: FC = () => {
|
|||||||
enqueueSnackbar(LL.TEMP_SENSOR() + ' ' + LL.UPDATED(), { variant: 'success' });
|
enqueueSnackbar(LL.TEMP_SENSOR() + ' ' + LL.UPDATED(), { variant: 'success' });
|
||||||
}
|
}
|
||||||
setSensor(undefined);
|
setSensor(undefined);
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||||
} finally {
|
} finally {
|
||||||
setSensor(undefined);
|
setSensor(undefined);
|
||||||
@@ -992,7 +992,7 @@ const DashboardData: FC = () => {
|
|||||||
} else {
|
} else {
|
||||||
enqueueSnackbar(LL.ANALOG_SENSOR() + ' ' + LL.REMOVED(), { variant: 'success' });
|
enqueueSnackbar(LL.ANALOG_SENSOR() + ' ' + LL.REMOVED(), { variant: 'success' });
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||||
} finally {
|
} finally {
|
||||||
setAnalog(undefined);
|
setAnalog(undefined);
|
||||||
@@ -1020,7 +1020,7 @@ const DashboardData: FC = () => {
|
|||||||
} else {
|
} else {
|
||||||
enqueueSnackbar(LL.ANALOG_SENSOR() + ' ' + LL.UPDATED(), { variant: 'success' });
|
enqueueSnackbar(LL.ANALOG_SENSOR() + ' ' + LL.UPDATED(), { variant: 'success' });
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||||
} finally {
|
} finally {
|
||||||
setAnalog(undefined);
|
setAnalog(undefined);
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ const DashboardStatus: FC = () => {
|
|||||||
try {
|
try {
|
||||||
await EMSESP.scanDevices();
|
await EMSESP.scanDevices();
|
||||||
enqueueSnackbar(LL.SCANNING() + '...', { variant: 'info' });
|
enqueueSnackbar(LL.SCANNING() + '...', { variant: 'info' });
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||||
} finally {
|
} finally {
|
||||||
setConfirmScan(false);
|
setConfirmScan(false);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ const HelpInformation: FC = () => {
|
|||||||
} else {
|
} else {
|
||||||
saveFile(response.data, endpoint);
|
saveFile(response.data, endpoint);
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ const SettingsApplication: FC = () => {
|
|||||||
eth_clock_mode: response.data.eth_clock_mode
|
eth_clock_mode: response.data.eth_clock_mode
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||||
} finally {
|
} finally {
|
||||||
setProcessingBoard(false);
|
setProcessingBoard(false);
|
||||||
@@ -107,7 +107,7 @@ const SettingsApplication: FC = () => {
|
|||||||
try {
|
try {
|
||||||
await EMSESP.restart();
|
await EMSESP.restart();
|
||||||
enqueueSnackbar(LL.APPLICATION_RESTARTING(), { variant: 'info' });
|
enqueueSnackbar(LL.APPLICATION_RESTARTING(), { variant: 'info' });
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ const SettingsCustomization: FC = () => {
|
|||||||
const fetchDevices = useCallback(async () => {
|
const fetchDevices = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
setDevices((await EMSESP.readDevices()).data);
|
setDevices((await EMSESP.readDevices()).data);
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
}
|
}
|
||||||
}, [LL]);
|
}, [LL]);
|
||||||
@@ -144,7 +144,7 @@ const SettingsCustomization: FC = () => {
|
|||||||
try {
|
try {
|
||||||
const new_deviceEntities = (await EMSESP.readDeviceEntities({ id: unique_id })).data;
|
const new_deviceEntities = (await EMSESP.readDeviceEntities({ id: unique_id })).data;
|
||||||
setInitialMask(new_deviceEntities);
|
setInitialMask(new_deviceEntities);
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -165,17 +165,21 @@ const SettingsCustomization: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formatName(de: DeviceEntity) {
|
function formatName(de: DeviceEntity) {
|
||||||
if (de.n === undefined || de.n === de.id) {
|
if (de.n === undefined) {
|
||||||
return de.id;
|
return (
|
||||||
}
|
<>
|
||||||
|
(
|
||||||
if (de.n[0] === '!') {
|
<Link target="_blank" href={APIURL + devices?.devices[selectedDevice].t + '/' + de.id}>
|
||||||
return LL.COMMAND() + ': ' + de.n.slice(1);
|
{de.id}
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{de.cn !== undefined && de.cn !== '' ? de.cn : de.n}
|
{de.n[0] === '!' ? LL.COMMAND() + ': ' + de.n.slice(1) : de.cn !== undefined && de.cn !== '' ? de.cn : de.n}
|
||||||
(
|
(
|
||||||
<Link target="_blank" href={APIURL + devices?.devices[selectedDevice].t + '/' + de.id}>
|
<Link target="_blank" href={APIURL + devices?.devices[selectedDevice].t + '/' + de.id}>
|
||||||
{de.id}
|
{de.id}
|
||||||
@@ -239,7 +243,7 @@ const SettingsCustomization: FC = () => {
|
|||||||
try {
|
try {
|
||||||
await EMSESP.resetCustomizations();
|
await EMSESP.resetCustomizations();
|
||||||
enqueueSnackbar(LL.CUSTOMIZATIONS_RESTART(), { variant: 'info' });
|
enqueueSnackbar(LL.CUSTOMIZATIONS_RESTART(), { variant: 'info' });
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||||
} finally {
|
} finally {
|
||||||
setConfirmReset(false);
|
setConfirmReset(false);
|
||||||
@@ -250,13 +254,15 @@ const SettingsCustomization: FC = () => {
|
|||||||
if (devices && deviceEntities && selectedDevice !== -1) {
|
if (devices && deviceEntities && selectedDevice !== -1) {
|
||||||
const masked_entities = deviceEntities
|
const masked_entities = deviceEntities
|
||||||
.filter((de) => de.m !== de.o_m || de.cn !== de.o_cn || de.ma !== de.o_ma || de.mi !== de.o_mi)
|
.filter((de) => de.m !== de.o_m || de.cn !== de.o_cn || de.ma !== de.o_ma || de.mi !== de.o_mi)
|
||||||
.map((new_de) =>
|
.map(
|
||||||
new_de.m.toString(16).padStart(2, '0') +
|
(new_de) =>
|
||||||
new_de.id +
|
new_de.m.toString(16).padStart(2, '0') +
|
||||||
((new_de.cn || new_de.mi || new_de.ma) ? '|' : '') +
|
new_de.id +
|
||||||
(new_de.cn ? new_de.cn : '') +
|
(new_de.cn || new_de.mi || new_de.ma ? '|' : '') +
|
||||||
(new_de.mi ? '>' + new_de.mi : '') +
|
(new_de.cn ? new_de.cn : '') +
|
||||||
(new_de.ma ? '<' + new_de.ma : ''));
|
(new_de.mi ? '>' + new_de.mi : '') +
|
||||||
|
(new_de.ma ? '<' + new_de.ma : '')
|
||||||
|
);
|
||||||
|
|
||||||
// check size in bytes to match buffer in CPP, which is 4096
|
// check size in bytes to match buffer in CPP, which is 4096
|
||||||
const bytes = new TextEncoder().encode(JSON.stringify(masked_entities)).length;
|
const bytes = new TextEncoder().encode(JSON.stringify(masked_entities)).length;
|
||||||
@@ -275,7 +281,7 @@ const SettingsCustomization: FC = () => {
|
|||||||
} else {
|
} else {
|
||||||
enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' });
|
enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' });
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||||
}
|
}
|
||||||
setInitialMask(deviceEntities);
|
setInitialMask(deviceEntities);
|
||||||
@@ -322,7 +328,7 @@ const SettingsCustomization: FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const editEntity = (de: DeviceEntity) => {
|
const editEntity = (de: DeviceEntity) => {
|
||||||
if (de.n && de.n[0] === '!') {
|
if (de.n === undefined || (de.n && de.n[0] === '!')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ export interface MqttStatus {
|
|||||||
client_id: string;
|
client_id: string;
|
||||||
disconnect_reason: MqttDisconnectReason;
|
disconnect_reason: MqttDisconnectReason;
|
||||||
mqtt_fails: number;
|
mqtt_fails: number;
|
||||||
|
mqtt_queued: number;
|
||||||
|
connect_count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MqttSettings {
|
export interface MqttSettings {
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { AxiosError } from 'axios';
|
export const extractErrorMessage = (error: any, defaultMessage: string) => {
|
||||||
|
if (error.request) {
|
||||||
export const extractErrorMessage = (error: unknown, defaultMessage: string) => {
|
|
||||||
if (error instanceof AxiosError) {
|
|
||||||
return defaultMessage + ' (' + error.request.statusText + ')';
|
return defaultMessage + ' (' + error.request.statusText + ')';
|
||||||
} else if (error instanceof Error) {
|
} else if (error instanceof Error) {
|
||||||
return defaultMessage + ' (' + error.message + ')';
|
return defaultMessage + ' (' + error.message + ')';
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export const useRest = <D>({ read, update }: RestRequestOptions<D>) => {
|
|||||||
setErrorMessage(undefined);
|
setErrorMessage(undefined);
|
||||||
try {
|
try {
|
||||||
setData((await read()).data);
|
setData((await read()).data);
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
const message = extractErrorMessage(error, LL.PROBLEM_LOADING());
|
const message = extractErrorMessage(error, LL.PROBLEM_LOADING());
|
||||||
enqueueSnackbar(message, { variant: 'error' });
|
enqueueSnackbar(message, { variant: 'error' });
|
||||||
setErrorMessage(message);
|
setErrorMessage(message);
|
||||||
@@ -49,7 +49,7 @@ export const useRest = <D>({ read, update }: RestRequestOptions<D>) => {
|
|||||||
} else {
|
} else {
|
||||||
enqueueSnackbar(LL.SETTINGS() + ' ' + LL.SAVED(), { variant: 'success' });
|
enqueueSnackbar(LL.SETTINGS() + ' ' + LL.SAVED(), { variant: 'success' });
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error) {
|
||||||
const message = extractErrorMessage(error, LL.PROBLEM_UPDATING());
|
const message = extractErrorMessage(error, LL.PROBLEM_UPDATING());
|
||||||
enqueueSnackbar(message, { variant: 'error' });
|
enqueueSnackbar(message, { variant: 'error' });
|
||||||
setErrorMessage(message);
|
setErrorMessage(message);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
|
"useUnknownInCatchVariables": false,
|
||||||
"jsx": "react-jsx"
|
"jsx": "react-jsx"
|
||||||
},
|
},
|
||||||
"include": ["src"]
|
"include": ["src"]
|
||||||
|
|||||||
@@ -49,9 +49,9 @@ void APSettingsService::startAP() {
|
|||||||
WiFi.softAPConfig(_state.localIP, _state.gatewayIP, _state.subnetMask);
|
WiFi.softAPConfig(_state.localIP, _state.gatewayIP, _state.subnetMask);
|
||||||
esp_wifi_set_bandwidth((wifi_interface_t)ESP_IF_WIFI_AP, WIFI_BW_HT20);
|
esp_wifi_set_bandwidth((wifi_interface_t)ESP_IF_WIFI_AP, WIFI_BW_HT20);
|
||||||
WiFi.softAP(_state.ssid.c_str(), _state.password.c_str(), _state.channel, _state.ssidHidden, _state.maxClients);
|
WiFi.softAP(_state.ssid.c_str(), _state.password.c_str(), _state.channel, _state.ssidHidden, _state.maxClients);
|
||||||
#ifdef ARDUINO_LOLIN_C3_MINI
|
#ifdef ARDUINO_LOLIN_C3_MINI
|
||||||
WiFi.setTxPower(WIFI_POWER_8_5dBm); //https://www.wemos.cc/en/latest/c3/c3_mini.html#about-wifi
|
WiFi.setTxPower(WIFI_POWER_8_5dBm); //https://www.wemos.cc/en/latest/c3/c3_mini.html#about-wifi
|
||||||
#endif
|
#endif
|
||||||
if (!_dnsServer) {
|
if (!_dnsServer) {
|
||||||
IPAddress apIp = WiFi.softAPIP();
|
IPAddress apIp = WiFi.softAPIP();
|
||||||
emsesp::EMSESP::logger().info(F("Starting Access Point with captive portal on %s"), apIp.toString().c_str());
|
emsesp::EMSESP::logger().info(F("Starting Access Point with captive portal on %s"), apIp.toString().c_str());
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ void MqttStatus::mqttStatus(AsyncWebServerRequest * request) {
|
|||||||
root["client_id"] = _mqttSettingsService->getClientId();
|
root["client_id"] = _mqttSettingsService->getClientId();
|
||||||
root["disconnect_reason"] = (uint8_t)_mqttSettingsService->getDisconnectReason();
|
root["disconnect_reason"] = (uint8_t)_mqttSettingsService->getDisconnectReason();
|
||||||
|
|
||||||
root["mqtt_fails"] = emsesp::Mqtt::publish_fails(); // proddy added
|
root["mqtt_queued"] = emsesp::Mqtt::publish_queued(); // mdvp added
|
||||||
|
root["mqtt_fails"] = emsesp::Mqtt::publish_fails(); // proddy added
|
||||||
|
root["connect_count"] = emsesp::Mqtt::connect_count(); // mdvp added
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class NTPSettingsService : public StatefulService<NTPSettings> {
|
|||||||
public:
|
public:
|
||||||
NTPSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager);
|
NTPSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager);
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
static void ntp_received(struct timeval * tv);
|
static void ntp_received(struct timeval * tv);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -68,7 +68,6 @@ class NTPSettingsService : public StatefulService<NTPSettings> {
|
|||||||
void WiFiEvent(WiFiEvent_t event);
|
void WiFiEvent(WiFiEvent_t event);
|
||||||
void configureNTP();
|
void configureNTP();
|
||||||
void configureTime(AsyncWebServerRequest * request, JsonVariant & json);
|
void configureTime(AsyncWebServerRequest * request, JsonVariant & json);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -75,9 +75,9 @@ void NetworkSettingsService::manageSTA() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
WiFi.begin(_state.ssid.c_str(), _state.password.c_str()); // attempt to connect to the network
|
WiFi.begin(_state.ssid.c_str(), _state.password.c_str()); // attempt to connect to the network
|
||||||
#ifdef ARDUINO_LOLIN_C3_MINI
|
#ifdef ARDUINO_LOLIN_C3_MINI
|
||||||
WiFi.setTxPower(WIFI_POWER_8_5dBm); //https://www.wemos.cc/en/latest/c3/c3_mini.html#about-wifi
|
WiFi.setTxPower(WIFI_POWER_8_5dBm); //https://www.wemos.cc/en/latest/c3/c3_mini.html#about-wifi
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,8 @@ std::string printable_to_string(const Printable & printable);
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
using flash_string_vector = std::vector<const __FlashStringHelper *>;
|
|
||||||
|
using string_vector = std::vector<const char *>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loop function that must be called regularly to detect a 32-bit
|
* Loop function that must be called regularly to detect a 32-bit
|
||||||
|
|||||||
@@ -42,30 +42,36 @@ namespace uuid {
|
|||||||
|
|
||||||
namespace console {
|
namespace console {
|
||||||
|
|
||||||
void Commands::add_command(const flash_string_vector & name, command_function function) {
|
void Commands::add_command(const string_vector & name, command_function function) {
|
||||||
add_command(0, 0, name, flash_string_vector{}, function, nullptr);
|
add_command(0, 0, name, string_vector{}, function, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Commands::add_command(const flash_string_vector & name, const flash_string_vector & arguments, command_function function) {
|
void Commands::add_command(const string_vector & name, const string_vector & arguments, command_function function) {
|
||||||
add_command(0, 0, name, arguments, function, nullptr);
|
add_command(0, 0, name, arguments, function, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Commands::add_command(const flash_string_vector & name, const flash_string_vector & arguments, command_function function, argument_completion_function arg_function) {
|
void Commands::add_command(const string_vector & name, const string_vector & arguments, command_function function, argument_completion_function arg_function) {
|
||||||
add_command(0, 0, name, arguments, function, arg_function);
|
add_command(0, 0, name, arguments, function, arg_function);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Commands::add_command(unsigned int context, unsigned int flags, const flash_string_vector & name, command_function function) {
|
void Commands::add_command(unsigned int context, unsigned int flags, const string_vector & name, command_function function) {
|
||||||
add_command(context, flags, name, flash_string_vector{}, function, nullptr);
|
add_command(context, flags, name, string_vector{}, function, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Commands::add_command(unsigned int context, unsigned int flags, const flash_string_vector & name, const flash_string_vector & arguments, command_function function) {
|
void Commands::add_command(unsigned int context, unsigned int flags, const string_vector & name, const string_vector & arguments, command_function function) {
|
||||||
add_command(context, flags, name, arguments, function, nullptr);
|
add_command(context, flags, name, arguments, function, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Commands::add_command(unsigned int context, unsigned int flags, const flash_string_vector & name, const flash_string_vector & arguments, command_function function, argument_completion_function arg_function) {
|
void Commands::add_command(unsigned int context,
|
||||||
|
unsigned int flags,
|
||||||
|
const string_vector & name,
|
||||||
|
const string_vector & arguments,
|
||||||
|
command_function function,
|
||||||
|
argument_completion_function arg_function) {
|
||||||
commands_.emplace(std::piecewise_construct, std::forward_as_tuple(context), std::forward_as_tuple(flags, name, arguments, function, arg_function));
|
commands_.emplace(std::piecewise_construct, std::forward_as_tuple(context), std::forward_as_tuple(flags, name, arguments, function, arg_function));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// added by proddy
|
// added by proddy
|
||||||
// note we should really iterate and free up the lambda code and any flashstrings
|
// note we should really iterate and free up the lambda code and any flashstrings
|
||||||
void Commands::remove_all_commands() {
|
void Commands::remove_all_commands() {
|
||||||
@@ -139,7 +145,7 @@ bool Commands::find_longest_common_prefix(const std::multimap<size_t, const Comm
|
|||||||
|
|
||||||
for (size_t length = 0; all_match && length < shortest_match; length++) {
|
for (size_t length = 0; all_match && length < shortest_match; length++) {
|
||||||
for (auto command_it = std::next(commands.begin()); command_it != commands.end(); command_it++) {
|
for (auto command_it = std::next(commands.begin()); command_it != commands.end(); command_it++) {
|
||||||
if (read_flash_string(*std::next(first.begin(), length)) != read_flash_string(*std::next(command_it->second->name_.begin(), length))) {
|
if ((*std::next(first.begin(), length)) != (*std::next(command_it->second->name_.begin(), length))) {
|
||||||
all_match = false;
|
all_match = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -152,7 +158,7 @@ bool Commands::find_longest_common_prefix(const std::multimap<size_t, const Comm
|
|||||||
|
|
||||||
auto name_it = first.begin();
|
auto name_it = first.begin();
|
||||||
for (size_t i = 0; i < component_prefix; i++) {
|
for (size_t i = 0; i < component_prefix; i++) {
|
||||||
longest_name.push_back(std::move(read_flash_string(*name_it)));
|
longest_name.push_back(std::move((*name_it)));
|
||||||
name_it++;
|
name_it++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,7 +173,8 @@ bool Commands::find_longest_common_prefix(const std::multimap<size_t, const Comm
|
|||||||
for (auto command_it = std::next(commands.begin()); command_it != commands.end(); command_it++) {
|
for (auto command_it = std::next(commands.begin()); command_it != commands.end(); command_it++) {
|
||||||
// This relies on the null terminator character limiting the
|
// This relies on the null terminator character limiting the
|
||||||
// length before it becomes longer than any of the strings
|
// length before it becomes longer than any of the strings
|
||||||
if (pgm_read_byte(reinterpret_cast<PGM_P>(first) + length) != pgm_read_byte(reinterpret_cast<PGM_P>(*std::next(command_it->second->name_.begin(), component_prefix)) + length)) {
|
if (pgm_read_byte(reinterpret_cast<PGM_P>(first) + length)
|
||||||
|
!= pgm_read_byte(reinterpret_cast<PGM_P>(*std::next(command_it->second->name_.begin(), component_prefix)) + length)) {
|
||||||
all_match = false;
|
all_match = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -179,7 +186,8 @@ bool Commands::find_longest_common_prefix(const std::multimap<size_t, const Comm
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (chars_prefix > 0) {
|
if (chars_prefix > 0) {
|
||||||
longest_name.push_back(std::move(read_flash_string(first).substr(0, chars_prefix)));
|
// TODO fix, no more PGM
|
||||||
|
longest_name.push_back(std::string(first).substr(0, chars_prefix));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -243,7 +251,7 @@ Commands::Completion Commands::complete_command(Shell & shell, const CommandLine
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!temp_command_name.empty() && command_line.total_size() <= temp_command_name.size()) {
|
if (!temp_command_name.empty() && command_line.total_size() <= temp_command_name.size()) {
|
||||||
temp_command = std::make_unique<Command>(0, flash_string_vector{}, flash_string_vector{}, nullptr, nullptr);
|
temp_command = std::make_unique<Command>(0, string_vector{}, string_vector{}, nullptr, nullptr);
|
||||||
count = 1;
|
count = 1;
|
||||||
match = commands.partial.end();
|
match = commands.partial.end();
|
||||||
result.replacement.trailing_space = whole_components;
|
result.replacement.trailing_space = whole_components;
|
||||||
@@ -259,10 +267,11 @@ Commands::Completion Commands::complete_command(Shell & shell, const CommandLine
|
|||||||
auto & matching_command = match->second;
|
auto & matching_command = match->second;
|
||||||
|
|
||||||
for (auto & name : matching_command->name_) {
|
for (auto & name : matching_command->name_) {
|
||||||
result.replacement->push_back(std::move(read_flash_string(name)));
|
result.replacement->push_back(std::move((name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command_line.total_size() > result.replacement->size() && command_line.total_size() <= matching_command->name_.size() + matching_command->maximum_arguments()) {
|
if (command_line.total_size() > result.replacement->size()
|
||||||
|
&& command_line.total_size() <= matching_command->name_.size() + matching_command->maximum_arguments()) {
|
||||||
// Try to auto-complete arguments
|
// Try to auto-complete arguments
|
||||||
std::vector<std::string> arguments{std::next(command_line->cbegin(), result.replacement->size()), command_line->cend()};
|
std::vector<std::string> arguments{std::next(command_line->cbegin(), result.replacement->size()), command_line->cend()};
|
||||||
|
|
||||||
@@ -332,7 +341,7 @@ Commands::Completion Commands::complete_command(Shell & shell, const CommandLine
|
|||||||
remaining_help.escape_initial_parameters();
|
remaining_help.escape_initial_parameters();
|
||||||
|
|
||||||
for (auto it = std::next(matching_command->arguments_.cbegin(), current_args_count); it != matching_command->arguments_.cend(); it++) {
|
for (auto it = std::next(matching_command->arguments_.cbegin(), current_args_count); it != matching_command->arguments_.cend(); it++) {
|
||||||
remaining_help->push_back(std::move(read_flash_string(*it)));
|
remaining_help->push_back(std::move((*it)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +389,7 @@ Commands::Completion Commands::complete_command(Shell & shell, const CommandLine
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (; flash_name_it != command_it->second->name_.cend(); flash_name_it++) {
|
for (; flash_name_it != command_it->second->name_.cend(); flash_name_it++) {
|
||||||
std::string name = read_flash_string(*flash_name_it);
|
std::string name = (*flash_name_it);
|
||||||
|
|
||||||
// Skip parts of the command name that match the command line
|
// Skip parts of the command name that match the command line
|
||||||
if (line_it != command_line->cend()) {
|
if (line_it != command_line->cend()) {
|
||||||
@@ -403,7 +412,7 @@ Commands::Completion Commands::complete_command(Shell & shell, const CommandLine
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
help->push_back(std::move(read_flash_string(argument)));
|
help->push_back(std::move((argument)));
|
||||||
}
|
}
|
||||||
|
|
||||||
result.help.push_back(std::move(help));
|
result.help.push_back(std::move(help));
|
||||||
@@ -416,7 +425,7 @@ Commands::Completion Commands::complete_command(Shell & shell, const CommandLine
|
|||||||
|
|
||||||
if (commands.exact.count(longest->first) == 1) {
|
if (commands.exact.count(longest->first) == 1) {
|
||||||
for (auto & name : longest->second->name_) {
|
for (auto & name : longest->second->name_) {
|
||||||
result.replacement->push_back(std::move(read_flash_string(name)));
|
result.replacement->push_back(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a space because there are sub-commands for a command that has matched exactly
|
// Add a space because there are sub-commands for a command that has matched exactly
|
||||||
@@ -449,7 +458,7 @@ Commands::Match Commands::find_command(Shell & shell, const CommandLine & comman
|
|||||||
auto line_it = command_line->cbegin();
|
auto line_it = command_line->cbegin();
|
||||||
|
|
||||||
for (; name_it != command.name_.cend() && line_it != command_line->cend(); name_it++, line_it++) {
|
for (; name_it != command.name_.cend() && line_it != command_line->cend(); name_it++, line_it++) {
|
||||||
std::string name = read_flash_string(*name_it);
|
std::string name = (*name_it);
|
||||||
size_t found = name.rfind(*line_it, 0);
|
size_t found = name.rfind(*line_it, 0);
|
||||||
|
|
||||||
if (found == std::string::npos) {
|
if (found == std::string::npos) {
|
||||||
@@ -499,12 +508,12 @@ void Commands::for_each_available_command(Shell & shell, apply_function f) const
|
|||||||
|
|
||||||
name.reserve(command_it->second.name_.size());
|
name.reserve(command_it->second.name_.size());
|
||||||
for (auto flash_name : command_it->second.name_) {
|
for (auto flash_name : command_it->second.name_) {
|
||||||
name.push_back(std::move(read_flash_string(flash_name)));
|
name.push_back(std::move((flash_name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
arguments.reserve(command_it->second.arguments_.size());
|
arguments.reserve(command_it->second.arguments_.size());
|
||||||
for (auto flash_argument : command_it->second.arguments_) {
|
for (auto flash_argument : command_it->second.arguments_) {
|
||||||
arguments.push_back(std::move(read_flash_string(flash_argument)));
|
arguments.push_back(std::move((flash_argument)));
|
||||||
}
|
}
|
||||||
|
|
||||||
f(name, arguments);
|
f(name, arguments);
|
||||||
@@ -512,7 +521,11 @@ void Commands::for_each_available_command(Shell & shell, apply_function f) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands::Command::Command(unsigned int flags, const flash_string_vector name, const flash_string_vector arguments, command_function function, argument_completion_function arg_function)
|
Commands::Command::Command(unsigned int flags,
|
||||||
|
const string_vector name,
|
||||||
|
const string_vector arguments,
|
||||||
|
command_function function,
|
||||||
|
argument_completion_function arg_function)
|
||||||
: flags_(flags)
|
: flags_(flags)
|
||||||
, name_(name)
|
, name_(name)
|
||||||
, arguments_(arguments)
|
, arguments_(arguments)
|
||||||
@@ -524,7 +537,7 @@ Commands::Command::~Command() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t Commands::Command::minimum_arguments() const {
|
size_t Commands::Command::minimum_arguments() const {
|
||||||
return std::count_if(arguments_.cbegin(), arguments_.cend(), [](const __FlashStringHelper * argument) { return pgm_read_byte(argument) == '<'; });
|
return std::count_if(arguments_.cbegin(), arguments_.cend(), [](const char * argument) { return pgm_read_byte(argument) == '<'; });
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace console
|
} // namespace console
|
||||||
|
|||||||
@@ -135,8 +135,8 @@ void Shell::loop_one() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shell::set_command_str(const __FlashStringHelper * str) {
|
void Shell::set_command_str(const char * str) {
|
||||||
line_buffer_ = read_flash_string(str);
|
line_buffer_ = (str);
|
||||||
erase_current_line();
|
erase_current_line();
|
||||||
prompt_displayed_ = false;
|
prompt_displayed_ = false;
|
||||||
display_prompt();
|
display_prompt();
|
||||||
@@ -262,30 +262,30 @@ void Shell::loop_normal() {
|
|||||||
} else if (esc_ == 1) { // pos1
|
} else if (esc_ == 1) { // pos1
|
||||||
cursor_ = line_buffer_.length();
|
cursor_ = line_buffer_.length();
|
||||||
} else if (esc_ == 11) { // F1
|
} else if (esc_ == 11) { // F1
|
||||||
set_command_str(F("help"));
|
set_command_str("help");
|
||||||
} else if (esc_ == 12) { // F2
|
} else if (esc_ == 12) { // F2
|
||||||
set_command_str(F("show"));
|
set_command_str("show");
|
||||||
} else if (esc_ == 13) { // F3
|
} else if (esc_ == 13) { // F3
|
||||||
set_command_str(F("log notice"));
|
set_command_str("log notice");
|
||||||
} else if (esc_ == 14) { // F4
|
} else if (esc_ == 14) { // F4
|
||||||
set_command_str(F("log info"));
|
set_command_str("log info");
|
||||||
} else if (esc_ == 15) { // F5
|
} else if (esc_ == 15) { // F5
|
||||||
set_command_str(F("log debug"));
|
set_command_str("log debug");
|
||||||
} else if (esc_ == 17) { // F6
|
} else if (esc_ == 17) { // F6
|
||||||
set_command_str(F("watch off"));
|
set_command_str("watch off");
|
||||||
} else if (esc_ == 18) { // F7
|
} else if (esc_ == 18) { // F7
|
||||||
set_command_str(F("watch on"));
|
set_command_str("watch on");
|
||||||
} else if (esc_ == 19) { // F8
|
} else if (esc_ == 19) { // F8
|
||||||
set_command_str(F("watch raw"));
|
set_command_str("watch raw");
|
||||||
} else if (esc_ == 20) { // F9
|
} else if (esc_ == 20) { // F9
|
||||||
set_command_str(F("call system info"));
|
set_command_str("call system info");
|
||||||
} else if (esc_ == 21) { // F10
|
} else if (esc_ == 21) { // F10
|
||||||
set_command_str(F("call system settings"));
|
set_command_str("call system settings");
|
||||||
} else if (esc_ == 23) { // F11
|
} else if (esc_ == 23) { // F11
|
||||||
line_buffer_ = read_flash_string(F("call send \"0B \""));
|
line_buffer_ = ("call send \"0B \"");
|
||||||
cursor_ = 1;
|
cursor_ = 1;
|
||||||
} else if (esc_ == 24) { // F12
|
} else if (esc_ == 24) { // F12
|
||||||
set_command_str(F("log debug; watch raw"));
|
set_command_str("log debug; watch raw");
|
||||||
}
|
}
|
||||||
esc_ = 0;
|
esc_ = 0;
|
||||||
} else if (c >= '0' && (c <= '9')) { // numbers
|
} else if (c >= '0' && (c <= '9')) { // numbers
|
||||||
@@ -320,7 +320,7 @@ void Shell::loop_normal() {
|
|||||||
idle_time_ = uuid::get_uptime_ms();
|
idle_time_ = uuid::get_uptime_ms();
|
||||||
}
|
}
|
||||||
|
|
||||||
Shell::PasswordData::PasswordData(const __FlashStringHelper * password_prompt, password_function && password_function)
|
Shell::PasswordData::PasswordData(const char * password_prompt, password_function && password_function)
|
||||||
: password_prompt_(password_prompt)
|
: password_prompt_(password_prompt)
|
||||||
, password_function_(std::move(password_function)) {
|
, password_function_(std::move(password_function)) {
|
||||||
}
|
}
|
||||||
@@ -452,7 +452,7 @@ void Shell::loop_blocking() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shell::enter_password(const __FlashStringHelper * prompt, password_function function) {
|
void Shell::enter_password(const char * prompt, password_function function) {
|
||||||
if (mode_ == Mode::NORMAL) {
|
if (mode_ == Mode::NORMAL) {
|
||||||
mode_ = Mode::PASSWORD;
|
mode_ = Mode::PASSWORD;
|
||||||
mode_data_ = std::make_unique<Shell::PasswordData>(prompt, std::move(function));
|
mode_data_ = std::make_unique<Shell::PasswordData>(prompt, std::move(function));
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ namespace uuid {
|
|||||||
|
|
||||||
namespace console {
|
namespace console {
|
||||||
|
|
||||||
static const char __pstr__logger_name[] __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "shell";
|
static const char __pstr__logger_name[] = "shell";
|
||||||
const uuid::log::Logger Shell::logger_{reinterpret_cast<const __FlashStringHelper *>(__pstr__logger_name), uuid::log::Facility::LPR};
|
const uuid::log::Logger Shell::logger_{(__pstr__logger_name), uuid::log::Facility::LPR};
|
||||||
|
|
||||||
Shell::QueuedLogMessage::QueuedLogMessage(unsigned long id, std::shared_ptr<uuid::log::Message> && content)
|
Shell::QueuedLogMessage::QueuedLogMessage(unsigned long id, std::shared_ptr<uuid::log::Message> && content)
|
||||||
: id_(id)
|
: id_(id)
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ class Shell : public std::enable_shared_from_this<Shell>, public uuid::log::Hand
|
|||||||
* execution.
|
* execution.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
void enter_password(const __FlashStringHelper * prompt, password_function function);
|
void enter_password(const char * prompt, password_function function);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop executing anything on this shell for a period of time.
|
* Stop executing anything on this shell for a period of time.
|
||||||
@@ -682,11 +682,11 @@ class Shell : public std::enable_shared_from_this<Shell>, public uuid::log::Hand
|
|||||||
* execution.
|
* execution.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
PasswordData(const __FlashStringHelper * password_prompt, password_function && password_function);
|
PasswordData(const char * password_prompt, password_function && password_function);
|
||||||
~PasswordData() override = default;
|
~PasswordData() override = default;
|
||||||
|
|
||||||
const __FlashStringHelper * password_prompt_; /*!< Prompt requesting password input. @since 0.1.0 */
|
const char * password_prompt_; /*!< Prompt requesting password input. @since 0.1.0 */
|
||||||
password_function password_function_; /*!< Function to execute after password entry. @since 0.1.0 */
|
password_function password_function_; /*!< Function to execute after password entry. @since 0.1.0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -761,7 +761,7 @@ class Shell : public std::enable_shared_from_this<Shell>, public uuid::log::Hand
|
|||||||
const std::shared_ptr<const uuid::log::Message> content_; /*!< Log message content. @since 0.1.0 */
|
const std::shared_ptr<const uuid::log::Message> content_; /*!< Log message content. @since 0.1.0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
Shell(const Shell &) = delete;
|
Shell(const Shell &) = delete;
|
||||||
Shell & operator=(const Shell &) = delete;
|
Shell & operator=(const Shell &) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -893,7 +893,7 @@ class Shell : public std::enable_shared_from_this<Shell>, public uuid::log::Hand
|
|||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
size_t vprintf(const __FlashStringHelper * format, va_list ap);
|
size_t vprintf(const __FlashStringHelper * format, va_list ap);
|
||||||
void set_command_str(const __FlashStringHelper * str);
|
void set_command_str(const char * str);
|
||||||
|
|
||||||
static const uuid::log::Logger logger_; /*!< uuid::log::Logger instance for shells. @since 0.1.0 */
|
static const uuid::log::Logger logger_; /*!< uuid::log::Logger instance for shells. @since 0.1.0 */
|
||||||
static std::set<std::shared_ptr<Shell>> shells_; /*!< Registered running shells to be executed. @since 0.1.0 */
|
static std::set<std::shared_ptr<Shell>> shells_; /*!< Registered running shells to be executed. @since 0.1.0 */
|
||||||
@@ -906,7 +906,7 @@ class Shell : public std::enable_shared_from_this<Shell>, public uuid::log::Hand
|
|||||||
size_t maximum_log_messages_ = MAX_LOG_MESSAGES; /*!< Maximum command line length in bytes. @since 0.6.0 */
|
size_t maximum_log_messages_ = MAX_LOG_MESSAGES; /*!< Maximum command line length in bytes. @since 0.6.0 */
|
||||||
std::string line_buffer_; /*!< Command line buffer. Limited to maximum_command_line_length() bytes. @since 0.1.0 */
|
std::string line_buffer_; /*!< Command line buffer. Limited to maximum_command_line_length() bytes. @since 0.1.0 */
|
||||||
std::string line_old_[MAX_LINES]; /*!< old Command line buffer.*/
|
std::string line_old_[MAX_LINES]; /*!< old Command line buffer.*/
|
||||||
uint8_t line_no_ = 0;
|
uint8_t line_no_ = 0;
|
||||||
size_t maximum_command_line_length_ = MAX_COMMAND_LINE_LENGTH; /*!< Maximum command line length in bytes. @since 0.6.0 */
|
size_t maximum_command_line_length_ = MAX_COMMAND_LINE_LENGTH; /*!< Maximum command line length in bytes. @since 0.6.0 */
|
||||||
unsigned char previous_ = 0; /*!< Previous character that was entered on the command line. Used to detect CRLF line endings. @since 0.1.0 */
|
unsigned char previous_ = 0; /*!< Previous character that was entered on the command line. Used to detect CRLF line endings. @since 0.1.0 */
|
||||||
uint8_t cursor_ = 0; /*!< cursor position from end of line */
|
uint8_t cursor_ = 0; /*!< cursor position from end of line */
|
||||||
@@ -955,9 +955,9 @@ class CommandLine {
|
|||||||
~CommandLine() = default;
|
~CommandLine() = default;
|
||||||
|
|
||||||
#ifdef UNIT_TEST
|
#ifdef UNIT_TEST
|
||||||
CommandLine(CommandLine &&) = default;
|
CommandLine(CommandLine &&) = default;
|
||||||
CommandLine & operator=(CommandLine &&) = default;
|
CommandLine & operator=(CommandLine &&) = default;
|
||||||
CommandLine(const CommandLine &) __attribute__((deprecated)) = default;
|
CommandLine(const CommandLine &) __attribute__((deprecated)) = default;
|
||||||
CommandLine & operator=(const CommandLine &) __attribute__((deprecated)) = default;
|
CommandLine & operator=(const CommandLine &) __attribute__((deprecated)) = default;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1188,7 +1188,7 @@ class Commands {
|
|||||||
* executed.
|
* executed.
|
||||||
* @since 0.2.0
|
* @since 0.2.0
|
||||||
*/
|
*/
|
||||||
void add_command(const flash_string_vector & name, command_function function);
|
void add_command(const string_vector & name, command_function function);
|
||||||
/**
|
/**
|
||||||
* Add a command with arguments to the list of commands in this
|
* Add a command with arguments to the list of commands in this
|
||||||
* container.
|
* container.
|
||||||
@@ -1205,7 +1205,7 @@ class Commands {
|
|||||||
* executed.
|
* executed.
|
||||||
* @since 0.2.0
|
* @since 0.2.0
|
||||||
*/
|
*/
|
||||||
void add_command(const flash_string_vector & name, const flash_string_vector & arguments, command_function function);
|
void add_command(const string_vector & name, const string_vector & arguments, command_function function);
|
||||||
/**
|
/**
|
||||||
* Add a command with arguments and automatic argument completion
|
* Add a command with arguments and automatic argument completion
|
||||||
* to the list of commands in this container.
|
* to the list of commands in this container.
|
||||||
@@ -1224,7 +1224,7 @@ class Commands {
|
|||||||
* completions for this command.
|
* completions for this command.
|
||||||
* @since 0.2.0
|
* @since 0.2.0
|
||||||
*/
|
*/
|
||||||
void add_command(const flash_string_vector & name, const flash_string_vector & arguments, command_function function, argument_completion_function arg_function);
|
void add_command(const string_vector & name, const string_vector & arguments, command_function function, argument_completion_function arg_function);
|
||||||
/**
|
/**
|
||||||
* Add a command with no arguments to the list of commands in this
|
* Add a command with no arguments to the list of commands in this
|
||||||
* container.
|
* container.
|
||||||
@@ -1239,7 +1239,7 @@ class Commands {
|
|||||||
* executed.
|
* executed.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
void add_command(unsigned int context, unsigned int flags, const flash_string_vector & name, command_function function);
|
void add_command(unsigned int context, unsigned int flags, const string_vector & name, command_function function);
|
||||||
/**
|
/**
|
||||||
* Add a command with arguments to the list of commands in this
|
* Add a command with arguments to the list of commands in this
|
||||||
* container.
|
* container.
|
||||||
@@ -1257,7 +1257,7 @@ class Commands {
|
|||||||
* executed.
|
* executed.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
void add_command(unsigned int context, unsigned int flags, const flash_string_vector & name, const flash_string_vector & arguments, command_function function);
|
void add_command(unsigned int context, unsigned int flags, const string_vector & name, const string_vector & arguments, command_function function);
|
||||||
/**
|
/**
|
||||||
* Add a command with arguments and automatic argument completion
|
* Add a command with arguments and automatic argument completion
|
||||||
* to the list of commands in this container.
|
* to the list of commands in this container.
|
||||||
@@ -1279,8 +1279,8 @@ class Commands {
|
|||||||
*/
|
*/
|
||||||
void add_command(unsigned int context,
|
void add_command(unsigned int context,
|
||||||
unsigned int flags,
|
unsigned int flags,
|
||||||
const flash_string_vector & name,
|
const string_vector & name,
|
||||||
const flash_string_vector & arguments,
|
const string_vector & arguments,
|
||||||
command_function function,
|
command_function function,
|
||||||
argument_completion_function arg_function);
|
argument_completion_function arg_function);
|
||||||
|
|
||||||
@@ -1344,11 +1344,7 @@ class Commands {
|
|||||||
* completions for this command.
|
* completions for this command.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
Command(unsigned int flags,
|
Command(unsigned int flags, const string_vector name, const string_vector arguments, command_function function, argument_completion_function arg_function);
|
||||||
const flash_string_vector name,
|
|
||||||
const flash_string_vector arguments,
|
|
||||||
command_function function,
|
|
||||||
argument_completion_function arg_function);
|
|
||||||
~Command();
|
~Command();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1372,13 +1368,13 @@ class Commands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned int flags_; /*!< Shell flags that must be set for this command to be available. @since 0.1.0 */
|
unsigned int flags_; /*!< Shell flags that must be set for this command to be available. @since 0.1.0 */
|
||||||
const flash_string_vector name_; /*!< Name of the command as a std::vector of flash strings. @since 0.1.0 */
|
const string_vector name_; /*!< Name of the command as a std::vector of flash strings. @since 0.1.0 */
|
||||||
const flash_string_vector arguments_; /*!< Help text for arguments that the command accepts as a std::vector of flash strings. @since 0.1.0 */
|
const string_vector arguments_; /*!< Help text for arguments that the command accepts as a std::vector of flash strings. @since 0.1.0 */
|
||||||
command_function function_; /*!< Function to be used when the command is executed. @since 0.1.0 */
|
command_function function_; /*!< Function to be used when the command is executed. @since 0.1.0 */
|
||||||
argument_completion_function arg_function_; /*!< Function to be used to perform argument completions for this command. @since 0.1.0 */
|
argument_completion_function arg_function_; /*!< Function to be used to perform argument completions for this command. @since 0.1.0 */
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Command(const Command &) = delete;
|
Command(const Command &) = delete;
|
||||||
Command & operator=(const Command &) = delete;
|
Command & operator=(const Command &) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1487,7 +1483,7 @@ class StreamConsole : virtual public Shell {
|
|||||||
explicit StreamConsole(Stream & stream);
|
explicit StreamConsole(Stream & stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StreamConsole(const StreamConsole &) = delete;
|
StreamConsole(const StreamConsole &) = delete;
|
||||||
StreamConsole & operator=(const StreamConsole &) = delete;
|
StreamConsole & operator=(const StreamConsole &) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -26,17 +26,17 @@ namespace uuid {
|
|||||||
|
|
||||||
namespace log {
|
namespace log {
|
||||||
|
|
||||||
static constexpr const char * pstr_level_lowercase_off __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "off";
|
static constexpr const char * pstr_level_lowercase_off = "off";
|
||||||
static constexpr const char * pstr_level_lowercase_emerg __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "emerg";
|
static constexpr const char * pstr_level_lowercase_emerg = "emerg";
|
||||||
static constexpr const char * pstr_level_lowercase_crit __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "crit";
|
static constexpr const char * pstr_level_lowercase_crit = "crit";
|
||||||
static constexpr const char * pstr_level_lowercase_alert __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "alert";
|
static constexpr const char * pstr_level_lowercase_alert = "alert";
|
||||||
static constexpr const char * pstr_level_lowercase_err __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "err";
|
static constexpr const char * pstr_level_lowercase_err = "err";
|
||||||
static constexpr const char * pstr_level_lowercase_warning __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "warning";
|
static constexpr const char * pstr_level_lowercase_warning = "warning";
|
||||||
static constexpr const char * pstr_level_lowercase_notice __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "notice";
|
static constexpr const char * pstr_level_lowercase_notice = "notice";
|
||||||
static constexpr const char * pstr_level_lowercase_info __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "info";
|
static constexpr const char * pstr_level_lowercase_info = "info";
|
||||||
static constexpr const char * pstr_level_lowercase_debug __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "debug";
|
static constexpr const char * pstr_level_lowercase_debug = "debug";
|
||||||
static constexpr const char * pstr_level_lowercase_trace __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "trace";
|
static constexpr const char * pstr_level_lowercase_trace = "trace";
|
||||||
static constexpr const char * pstr_level_lowercase_all __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "all";
|
static constexpr const char * pstr_level_lowercase_all = "all";
|
||||||
|
|
||||||
static const __FlashStringHelper * log_level_lowercase[(int)Level::ALL - (int)Level::OFF + 1] __attribute__((__aligned__(sizeof(uint32_t))))
|
static const __FlashStringHelper * log_level_lowercase[(int)Level::ALL - (int)Level::OFF + 1] __attribute__((__aligned__(sizeof(uint32_t))))
|
||||||
PROGMEM = {reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_off),
|
PROGMEM = {reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_off),
|
||||||
|
|||||||
@@ -26,17 +26,17 @@ namespace uuid {
|
|||||||
|
|
||||||
namespace log {
|
namespace log {
|
||||||
|
|
||||||
static constexpr const char * pstr_level_uppercase_off __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "OFF";
|
static constexpr const char * pstr_level_uppercase_off = "OFF";
|
||||||
static constexpr const char * pstr_level_uppercase_emerg __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "EMERG";
|
static constexpr const char * pstr_level_uppercase_emerg = "EMERG";
|
||||||
static constexpr const char * pstr_level_uppercase_crit __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "CRIT";
|
static constexpr const char * pstr_level_uppercase_crit = "CRIT";
|
||||||
static constexpr const char * pstr_level_uppercase_alert __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "ALERT";
|
static constexpr const char * pstr_level_uppercase_alert = "ALERT";
|
||||||
static constexpr const char * pstr_level_uppercase_err __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "ERR";
|
static constexpr const char * pstr_level_uppercase_err = "ERR";
|
||||||
static constexpr const char * pstr_level_uppercase_warning __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "WARNING";
|
static constexpr const char * pstr_level_uppercase_warning = "WARNING";
|
||||||
static constexpr const char * pstr_level_uppercase_notice __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "NOTICE";
|
static constexpr const char * pstr_level_uppercase_notice = "NOTICE";
|
||||||
static constexpr const char * pstr_level_uppercase_info __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "INFO";
|
static constexpr const char * pstr_level_uppercase_info = "INFO";
|
||||||
static constexpr const char * pstr_level_uppercase_debug __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "DEBUG";
|
static constexpr const char * pstr_level_uppercase_debug = "DEBUG";
|
||||||
static constexpr const char * pstr_level_uppercase_trace __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "TRACE";
|
static constexpr const char * pstr_level_uppercase_trace = "TRACE";
|
||||||
static constexpr const char * pstr_level_uppercase_all __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "ALL";
|
static constexpr const char * pstr_level_uppercase_all = "ALL";
|
||||||
|
|
||||||
static const __FlashStringHelper * log_level_uppercase[(int)Level::ALL - (int)Level::OFF + 1] __attribute__((__aligned__(sizeof(uint32_t))))
|
static const __FlashStringHelper * log_level_uppercase[(int)Level::ALL - (int)Level::OFF + 1] __attribute__((__aligned__(sizeof(uint32_t))))
|
||||||
PROGMEM = {reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_off),
|
PROGMEM = {reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_off),
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ std::string format_timestamp_ms(uint64_t timestamp_ms, unsigned int days_width)
|
|||||||
|
|
||||||
static std::vector<char> text(10 + 1 /* days */ + 2 + 1 /* hours */ + 2 + 1 /* minutes */ + 2 + 1 /* seconds */ + 3 /* milliseconds */ + 1);
|
static std::vector<char> text(10 + 1 /* days */ + 2 + 1 /* hours */ + 2 + 1 /* minutes */ + 2 + 1 /* seconds */ + 3 /* milliseconds */ + 1);
|
||||||
|
|
||||||
snprintf_P(text.data(), text.size(), PSTR("%0*lu+%02u:%02u:%02u.%03u"), std::min(days_width, 10U), days, hours, minutes, seconds, milliseconds);
|
snprintf(text.data(), text.size(), ("%0*lu+%02u:%02u:%02u.%03u"), std::min(days_width, 10U), days, hours, minutes, seconds, milliseconds);
|
||||||
|
|
||||||
return text.data();
|
return text.data();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace log {
|
|||||||
std::map<Handler *, Level> Logger::handlers_;
|
std::map<Handler *, Level> Logger::handlers_;
|
||||||
Level Logger::level_ = Level::OFF;
|
Level Logger::level_ = Level::OFF;
|
||||||
|
|
||||||
Message::Message(uint64_t uptime_ms, Level level, Facility facility, const __FlashStringHelper * name, const std::string && text)
|
Message::Message(uint64_t uptime_ms, Level level, Facility facility, const char * name, const std::string && text)
|
||||||
: uptime_ms(uptime_ms)
|
: uptime_ms(uptime_ms)
|
||||||
, level(level)
|
, level(level)
|
||||||
, facility(facility)
|
, facility(facility)
|
||||||
@@ -44,7 +44,7 @@ Message::Message(uint64_t uptime_ms, Level level, Facility facility, const __Fla
|
|||||||
, text(std::move(text)) {
|
, text(std::move(text)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::Logger(const __FlashStringHelper * name, Facility facility)
|
Logger::Logger(const char * name, Facility facility)
|
||||||
: name_(name)
|
: name_(name)
|
||||||
, facility_(facility){
|
, facility_(facility){
|
||||||
|
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ struct Message {
|
|||||||
* @param[in] text Log message text.
|
* @param[in] text Log message text.
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
Message(uint64_t uptime_ms, Level level, Facility facility, const __FlashStringHelper * name, const std::string && text);
|
Message(uint64_t uptime_ms, Level level, Facility facility, const char * name, const std::string && text);
|
||||||
~Message() = default;
|
~Message() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -261,7 +261,7 @@ struct Message {
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
const __FlashStringHelper * name;
|
const char * name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formatted log message text.
|
* Formatted log message text.
|
||||||
@@ -331,7 +331,7 @@ class Logger {
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
Logger(const __FlashStringHelper * name, Facility facility = Facility::LOCAL0);
|
Logger(const char * name, Facility facility = Facility::LOCAL0);
|
||||||
~Logger() = default;
|
~Logger() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -626,8 +626,8 @@ class Logger {
|
|||||||
static std::map<Handler *, Level> handlers_; /*!< Registered log handlers. @since 1.0.0 */
|
static std::map<Handler *, Level> handlers_; /*!< Registered log handlers. @since 1.0.0 */
|
||||||
static Level level_; /*!< Minimum global log level across all handlers. @since 1.0.0 */
|
static Level level_; /*!< Minimum global log level across all handlers. @since 1.0.0 */
|
||||||
|
|
||||||
const __FlashStringHelper * name_; /*!< Logger name (flash string). @since 1.0.0 */
|
const char * name_; /*!< Logger name (flash string). @since 1.0.0 */
|
||||||
const Facility facility_; /*!< Default logging facility for messages. @since 1.0.0 */
|
const Facility facility_; /*!< Default logging facility for messages. @since 1.0.0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace log
|
} // namespace log
|
||||||
|
|||||||
@@ -82,13 +82,13 @@
|
|||||||
#include <uuid/common.h>
|
#include <uuid/common.h>
|
||||||
#include <uuid/log.h>
|
#include <uuid/log.h>
|
||||||
|
|
||||||
static const char __pstr__logger_name[] __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "syslog";
|
static const char __pstr__logger_name[] = "syslog";
|
||||||
|
|
||||||
namespace uuid {
|
namespace uuid {
|
||||||
|
|
||||||
namespace syslog {
|
namespace syslog {
|
||||||
|
|
||||||
uuid::log::Logger SyslogService::logger_{FPSTR(__pstr__logger_name), uuid::log::Facility::SYSLOG};
|
uuid::log::Logger SyslogService::logger_{__pstr__logger_name, uuid::log::Facility::SYSLOG};
|
||||||
bool SyslogService::QueuedLogMessage::time_good_ = false;
|
bool SyslogService::QueuedLogMessage::time_good_ = false;
|
||||||
|
|
||||||
SyslogService::~SyslogService() {
|
SyslogService::~SyslogService() {
|
||||||
@@ -116,7 +116,7 @@ void SyslogService::remove_queued_messages(uuid::log::Level level) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_message_id_ -= offset;
|
log_message_id_ -= offset;
|
||||||
log_message_fails_ += offset;
|
log_message_fails_ += offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,8 +269,8 @@ void SyslogService::loop() {
|
|||||||
operator<<(std::make_shared<uuid::log::Message>(uuid::get_uptime_ms(),
|
operator<<(std::make_shared<uuid::log::Message>(uuid::get_uptime_ms(),
|
||||||
uuid::log::Level::INFO,
|
uuid::log::Level::INFO,
|
||||||
uuid::log::Facility::SYSLOG,
|
uuid::log::Facility::SYSLOG,
|
||||||
reinterpret_cast<const __FlashStringHelper *>(__pstr__logger_name),
|
(__pstr__logger_name),
|
||||||
uuid::read_flash_string(F("-- MARK --"))));
|
(F("-- MARK --"))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -443,7 +443,7 @@ bool SyslogService::transmit(const QueuedLogMessage & message) {
|
|||||||
udp_.print('-');
|
udp_.print('-');
|
||||||
}
|
}
|
||||||
|
|
||||||
udp_.printf_P(PSTR(" %s %s - - - "), hostname_.c_str(), uuid::read_flash_string(message.content_->name).c_str());
|
udp_.printf_P(PSTR(" %s %s - - - "), hostname_.c_str(), (message.content_->name));
|
||||||
|
|
||||||
char id_c_str[15];
|
char id_c_str[15];
|
||||||
snprintf_P(id_c_str, sizeof(id_c_str), PSTR(" %lu: "), message.id_);
|
snprintf_P(id_c_str, sizeof(id_c_str), PSTR(" %lu: "), message.id_);
|
||||||
|
|||||||
@@ -28,329 +28,322 @@ namespace uuid {
|
|||||||
|
|
||||||
namespace telnet {
|
namespace telnet {
|
||||||
|
|
||||||
TelnetStream::TelnetStream(WiFiClient &client)
|
TelnetStream::TelnetStream(WiFiClient & client)
|
||||||
: client_(client) {
|
: client_(client) {
|
||||||
output_buffer_.reserve(BUFFER_SIZE);
|
output_buffer_.reserve(BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetStream::start() {
|
void TelnetStream::start() {
|
||||||
raw_write({
|
raw_write({IAC, WILL, OPT_ECHO, IAC, WILL, OPT_BINARY, IAC, WILL, OPT_SGA, IAC, DONT, OPT_ECHO, IAC, DO, OPT_BINARY, IAC, DO, OPT_SGA});
|
||||||
IAC, WILL, OPT_ECHO,
|
|
||||||
IAC, WILL, OPT_BINARY,
|
|
||||||
IAC, WILL, OPT_SGA,
|
|
||||||
IAC, DONT, OPT_ECHO,
|
|
||||||
IAC, DO, OPT_BINARY,
|
|
||||||
IAC, DO, OPT_SGA
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TelnetStream::available() {
|
int TelnetStream::available() {
|
||||||
if (peek() == -1) {
|
if (peek() == -1) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int TelnetStream::read() {
|
int TelnetStream::read() {
|
||||||
if (peek_ != -1) {
|
if (peek_ != -1) {
|
||||||
int data = peek_;
|
int data = peek_;
|
||||||
peek_ = -1;
|
peek_ = -1;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_flush();
|
buffer_flush();
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
int data = raw_read();
|
int data = raw_read();
|
||||||
|
|
||||||
if (data == -1) {
|
if (data == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char c = data;
|
unsigned char c = data;
|
||||||
|
|
||||||
if (sub_negotiation_) {
|
if (sub_negotiation_) {
|
||||||
if (previous_raw_in_ == IAC) {
|
if (previous_raw_in_ == IAC) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case SE:
|
case SE:
|
||||||
sub_negotiation_ = false;
|
sub_negotiation_ = false;
|
||||||
previous_raw_in_ = 0;
|
previous_raw_in_ = 0;
|
||||||
goto restart;
|
goto restart;
|
||||||
|
|
||||||
case IAC:
|
case IAC:
|
||||||
previous_raw_in_ = 0;
|
previous_raw_in_ = 0;
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case IAC:
|
case IAC:
|
||||||
previous_raw_in_ = c;
|
previous_raw_in_ = c;
|
||||||
goto restart;
|
goto restart;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
previous_raw_in_ = 0;
|
previous_raw_in_ = 0;
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (previous_raw_in_ == IAC) {
|
if (previous_raw_in_ == IAC) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case IP:
|
case IP:
|
||||||
// Interrupt (^C)
|
// Interrupt (^C)
|
||||||
previous_raw_in_ = 0;
|
previous_raw_in_ = 0;
|
||||||
c = '\x03';
|
c = '\x03';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EC:
|
case EC:
|
||||||
// Backspace (^H)
|
// Backspace (^H)
|
||||||
previous_raw_in_ = 0;
|
previous_raw_in_ = 0;
|
||||||
c = '\x08';
|
c = '\x08';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EL:
|
case EL:
|
||||||
// Delete line (^U)
|
// Delete line (^U)
|
||||||
previous_raw_in_ = 0;
|
previous_raw_in_ = 0;
|
||||||
c = '\x15';
|
c = '\x15';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IAC:
|
case IAC:
|
||||||
previous_raw_in_ = 0;
|
previous_raw_in_ = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SB:
|
case SB:
|
||||||
case WILL:
|
case WILL:
|
||||||
case WONT:
|
case WONT:
|
||||||
case DO:
|
case DO:
|
||||||
case DONT:
|
case DONT:
|
||||||
previous_raw_in_ = c;
|
previous_raw_in_ = c;
|
||||||
goto restart;
|
goto restart;
|
||||||
|
|
||||||
case SE:
|
case SE:
|
||||||
case DM:
|
case DM:
|
||||||
case BRK:
|
case BRK:
|
||||||
case AO:
|
case AO:
|
||||||
case AYT:
|
case AYT:
|
||||||
case GA:
|
case GA:
|
||||||
case NOP:
|
case NOP:
|
||||||
default:
|
default:
|
||||||
previous_raw_in_ = 0;
|
previous_raw_in_ = 0;
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
} else if (previous_raw_in_ == SB) {
|
} else if (previous_raw_in_ == SB) {
|
||||||
sub_negotiation_ = true;
|
sub_negotiation_ = true;
|
||||||
previous_raw_in_ = 0;
|
previous_raw_in_ = 0;
|
||||||
goto restart;
|
goto restart;
|
||||||
} else if (previous_raw_in_ == WILL || previous_raw_in_ == WONT) {
|
} else if (previous_raw_in_ == WILL || previous_raw_in_ == WONT) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case OPT_ECHO:
|
case OPT_ECHO:
|
||||||
// Don't do these
|
// Don't do these
|
||||||
raw_write({IAC, DONT, c});
|
raw_write({IAC, DONT, c});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPT_BINARY:
|
case OPT_BINARY:
|
||||||
case OPT_SGA:
|
case OPT_SGA:
|
||||||
// Do these
|
// Do these
|
||||||
raw_write({IAC, DO, c});
|
raw_write({IAC, DO, c});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Don't do anything else
|
// Don't do anything else
|
||||||
raw_write({IAC, DONT, c});
|
raw_write({IAC, DONT, c});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
previous_raw_in_ = 0;
|
previous_raw_in_ = 0;
|
||||||
goto restart;
|
goto restart;
|
||||||
} else if (previous_raw_in_ == DO) {
|
} else if (previous_raw_in_ == DO) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case OPT_ECHO:
|
case OPT_ECHO:
|
||||||
case OPT_BINARY:
|
case OPT_BINARY:
|
||||||
case OPT_SGA:
|
case OPT_SGA:
|
||||||
// These are always enabled
|
// These are always enabled
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Refuse to do anything else
|
// Refuse to do anything else
|
||||||
raw_write({IAC, WONT, c});
|
raw_write({IAC, WONT, c});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
previous_raw_in_ = 0;
|
previous_raw_in_ = 0;
|
||||||
goto restart;
|
goto restart;
|
||||||
} else if (previous_raw_in_ == DONT) {
|
} else if (previous_raw_in_ == DONT) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case OPT_ECHO:
|
case OPT_ECHO:
|
||||||
case OPT_BINARY:
|
case OPT_BINARY:
|
||||||
case OPT_SGA:
|
case OPT_SGA:
|
||||||
// Insist that we do these
|
// Insist that we do these
|
||||||
raw_write({IAC, WILL, c});
|
raw_write({IAC, WILL, c});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Everything else is always disabled
|
// Everything else is always disabled
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
previous_raw_in_ = 0;
|
previous_raw_in_ = 0;
|
||||||
goto restart;
|
goto restart;
|
||||||
} else {
|
} else {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case IAC:
|
case IAC:
|
||||||
previous_raw_in_ = c;
|
previous_raw_in_ = c;
|
||||||
goto restart;
|
goto restart;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
previous_raw_in_ = 0;
|
previous_raw_in_ = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (previous_in_ == CR) {
|
if (previous_in_ == CR) {
|
||||||
if (c == NUL) {
|
if (c == NUL) {
|
||||||
previous_in_ = 0;
|
previous_in_ = 0;
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
previous_in_ = c;
|
previous_in_ = c;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TelnetStream::peek() {
|
int TelnetStream::peek() {
|
||||||
buffer_flush();
|
buffer_flush();
|
||||||
|
|
||||||
// It's too complicated to implement this by calling peek()
|
// It's too complicated to implement this by calling peek()
|
||||||
// on the original stream, especially if the original stream
|
// on the original stream, especially if the original stream
|
||||||
// doesn't actually support peeking.
|
// doesn't actually support peeking.
|
||||||
if (peek_ == -1) {
|
if (peek_ == -1) {
|
||||||
peek_ = read();
|
peek_ = read();
|
||||||
}
|
}
|
||||||
|
|
||||||
return peek_;
|
return peek_;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TelnetStream::write(uint8_t data) {
|
size_t TelnetStream::write(uint8_t data) {
|
||||||
if (previous_out_ == CR && data != LF) {
|
if (previous_out_ == CR && data != LF) {
|
||||||
previous_out_ = data;
|
previous_out_ = data;
|
||||||
|
|
||||||
if (raw_write({NUL, data}) != 2) {
|
if (raw_write({NUL, data}) != 2) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
previous_out_ = data;
|
previous_out_ = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data == IAC) {
|
if (data == IAC) {
|
||||||
if (raw_write({IAC, IAC}) != 2) {
|
if (raw_write({IAC, IAC}) != 2) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (raw_write(data) != 1) {
|
if (raw_write(data) != 1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TelnetStream::write(const uint8_t *buffer, size_t size) {
|
size_t TelnetStream::write(const uint8_t * buffer, size_t size) {
|
||||||
std::vector<unsigned char> data;
|
std::vector<unsigned char> data;
|
||||||
data.reserve(size);
|
data.reserve(size);
|
||||||
|
|
||||||
while (size-- > 0) {
|
while (size-- > 0) {
|
||||||
unsigned char c = *buffer++;
|
unsigned char c = *buffer++;
|
||||||
|
|
||||||
if (previous_out_ == CR && c != LF) {
|
if (previous_out_ == CR && c != LF) {
|
||||||
data.push_back((unsigned char)NUL);
|
data.push_back((unsigned char)NUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == IAC) {
|
if (c == IAC) {
|
||||||
data.push_back((unsigned char)IAC);
|
data.push_back((unsigned char)IAC);
|
||||||
}
|
}
|
||||||
|
|
||||||
previous_out_ = c;
|
previous_out_ = c;
|
||||||
data.push_back(c);
|
data.push_back(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len = raw_write(data);
|
size_t len = raw_write(data);
|
||||||
if (len < size) {
|
if (len < size) {
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetStream::flush() {
|
void TelnetStream::flush() {
|
||||||
// This is a pure virtual function in Arduino's Stream class, which
|
// This is a pure virtual function in Arduino's Stream class, which
|
||||||
// makes no sense because that class is for input and this is an
|
// makes no sense because that class is for input and this is an
|
||||||
// output function. Later versions move it to Print as an empty
|
// output function. Later versions move it to Print as an empty
|
||||||
// virtual function so this is here for backward compatibility.
|
// virtual function so this is here for backward compatibility.
|
||||||
}
|
}
|
||||||
|
|
||||||
int TelnetStream::raw_available() {
|
int TelnetStream::raw_available() {
|
||||||
return client_.available();
|
return client_.available();
|
||||||
}
|
}
|
||||||
|
|
||||||
int TelnetStream::raw_read() {
|
int TelnetStream::raw_read() {
|
||||||
return client_.read();
|
return client_.read();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TelnetStream::buffer_flush() {
|
void TelnetStream::buffer_flush() {
|
||||||
if (!output_buffer_.empty()) {
|
if (!output_buffer_.empty()) {
|
||||||
size_t len = client_.write(reinterpret_cast<const unsigned char*>(output_buffer_.data()), output_buffer_.size());
|
size_t len = client_.write(reinterpret_cast<const unsigned char *>(output_buffer_.data()), output_buffer_.size());
|
||||||
if (len != output_buffer_.size()) {
|
if (len != output_buffer_.size()) {
|
||||||
client_.stop();
|
client_.stop();
|
||||||
}
|
}
|
||||||
output_buffer_.clear();
|
output_buffer_.clear();
|
||||||
output_buffer_.shrink_to_fit();
|
output_buffer_.shrink_to_fit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TelnetStream::raw_write(unsigned char data) {
|
size_t TelnetStream::raw_write(unsigned char data) {
|
||||||
output_buffer_.push_back(data);
|
output_buffer_.push_back(data);
|
||||||
|
|
||||||
if (output_buffer_.size() >= BUFFER_SIZE) {
|
if (output_buffer_.size() >= BUFFER_SIZE) {
|
||||||
buffer_flush();
|
buffer_flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TelnetStream::raw_write(const std::vector<unsigned char> &data) {
|
size_t TelnetStream::raw_write(const std::vector<unsigned char> & data) {
|
||||||
return raw_write(reinterpret_cast<const unsigned char*>(data.data()), data.size());
|
return raw_write(reinterpret_cast<const unsigned char *>(data.data()), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TelnetStream::raw_write(const uint8_t *buffer, size_t size) {
|
size_t TelnetStream::raw_write(const uint8_t * buffer, size_t size) {
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
size_t remaining = size;
|
size_t remaining = size;
|
||||||
|
|
||||||
if (!output_buffer_.empty()) {
|
if (!output_buffer_.empty()) {
|
||||||
// Fill the rest of the buffer
|
// Fill the rest of the buffer
|
||||||
size_t block = std::min(remaining, BUFFER_SIZE - output_buffer_.size());
|
size_t block = std::min(remaining, BUFFER_SIZE - output_buffer_.size());
|
||||||
|
|
||||||
output_buffer_.insert(output_buffer_.end(), buffer, buffer + block);
|
output_buffer_.insert(output_buffer_.end(), buffer, buffer + block);
|
||||||
offset += block;
|
offset += block;
|
||||||
remaining -= block;
|
remaining -= block;
|
||||||
|
|
||||||
if (output_buffer_.size() >= BUFFER_SIZE) {
|
if (output_buffer_.size() >= BUFFER_SIZE) {
|
||||||
buffer_flush();
|
buffer_flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remaining >= BUFFER_SIZE) {
|
if (remaining >= BUFFER_SIZE) {
|
||||||
// Output directly if it won't fit in the buffer
|
// Output directly if it won't fit in the buffer
|
||||||
size_t len = client_.write(buffer + offset, remaining);
|
size_t len = client_.write(buffer + offset, remaining);
|
||||||
if (len != remaining) {
|
if (len != remaining) {
|
||||||
client_.stop();
|
client_.stop();
|
||||||
return offset + len;
|
return offset + len;
|
||||||
}
|
}
|
||||||
} else if (remaining > 0) {
|
} else if (remaining > 0) {
|
||||||
// Put the rest in the buffer
|
// Put the rest in the buffer
|
||||||
output_buffer_.insert(output_buffer_.end(), buffer + offset, buffer + offset + remaining);
|
output_buffer_.insert(output_buffer_.end(), buffer + offset, buffer + offset + remaining);
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace telnet
|
} // namespace telnet
|
||||||
|
|||||||
@@ -54,22 +54,20 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char __pstr__logger_name[] __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = "telnet";
|
|
||||||
|
|
||||||
namespace uuid {
|
namespace uuid {
|
||||||
|
|
||||||
namespace telnet {
|
namespace telnet {
|
||||||
|
|
||||||
uuid::log::Logger TelnetService::logger_{FPSTR(__pstr__logger_name), uuid::log::Facility::DAEMON};
|
uuid::log::Logger TelnetService::logger_{"telnet", uuid::log::Facility::DAEMON};
|
||||||
|
|
||||||
TelnetService::TelnetService(std::shared_ptr<uuid::console::Commands> commands, unsigned int context, unsigned int flags)
|
TelnetService::TelnetService(std::shared_ptr<uuid::console::Commands> commands, unsigned int context, unsigned int flags)
|
||||||
: TelnetService(DEFAULT_PORT, commands, context, flags) {
|
: TelnetService(DEFAULT_PORT, commands, context, flags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TelnetService::TelnetService(uint16_t port, std::shared_ptr<uuid::console::Commands> commands, unsigned int context, unsigned int flags)
|
TelnetService::TelnetService(uint16_t port, std::shared_ptr<uuid::console::Commands> commands, unsigned int context, unsigned int flags)
|
||||||
: TelnetService(port, [commands, context, flags](Stream & stream, const IPAddress & addr __attribute__((unused)), uint16_t port __attribute__((unused))) -> std::shared_ptr<uuid::console::Shell> {
|
: TelnetService(port,
|
||||||
return std::make_shared<uuid::console::StreamConsole>(commands, stream, context, flags);
|
[commands, context, flags](Stream & stream, const IPAddress & addr __attribute__((unused)), uint16_t port __attribute__((unused)))
|
||||||
}) {
|
-> std::shared_ptr<uuid::console::Shell> { return std::make_shared<uuid::console::StreamConsole>(commands, stream, context, flags); }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TelnetService::TelnetService(shell_factory_function shell_factory)
|
TelnetService::TelnetService(shell_factory_function shell_factory)
|
||||||
@@ -145,7 +143,9 @@ void TelnetService::loop() {
|
|||||||
if (client) {
|
if (client) {
|
||||||
if (connections_.size() >= maximum_connections_) {
|
if (connections_.size() >= maximum_connections_) {
|
||||||
#if UUID_TELNET_HAVE_WIFICLIENT_REMOTE
|
#if UUID_TELNET_HAVE_WIFICLIENT_REMOTE
|
||||||
logger_.info(F("New connection from [%s]:%u rejected (connection limit reached)"), uuid::printable_to_string(client.remoteIP()).c_str(), client.remotePort());
|
logger_.info(F("New connection from [%s]:%u rejected (connection limit reached)"),
|
||||||
|
uuid::printable_to_string(client.remoteIP()).c_str(),
|
||||||
|
client.remotePort());
|
||||||
#else
|
#else
|
||||||
logger_.info(F("New connection rejected (connection limit reached)"));
|
logger_.info(F("New connection rejected (connection limit reached)"));
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -21,9 +21,9 @@
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
# include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#else
|
#else
|
||||||
# include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#endif
|
#endif
|
||||||
#include <WiFiUdp.h>
|
#include <WiFiUdp.h>
|
||||||
|
|
||||||
@@ -51,47 +51,47 @@ namespace telnet {
|
|||||||
*
|
*
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
class TelnetStream: public ::Stream {
|
class TelnetStream : public ::Stream {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Create a new telnet stream wrapper.
|
* Create a new telnet stream wrapper.
|
||||||
*
|
*
|
||||||
* @param[in] client Client connection.
|
* @param[in] client Client connection.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
explicit TelnetStream(WiFiClient &client);
|
explicit TelnetStream(WiFiClient & client);
|
||||||
virtual ~TelnetStream() = default;
|
virtual ~TelnetStream() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform initial negotiation.
|
* Perform initial negotiation.
|
||||||
*
|
*
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
void start();
|
void start();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for available input.
|
* Check for available input.
|
||||||
*
|
*
|
||||||
* @return The number of bytes available to read.
|
* @return The number of bytes available to read.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
int available() override;
|
int available() override;
|
||||||
/**
|
/**
|
||||||
* Read one byte from the available input.
|
* Read one byte from the available input.
|
||||||
*
|
*
|
||||||
* @return An unsigned char if input is available, otherwise -1.
|
* @return An unsigned char if input is available, otherwise -1.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
int read() override;
|
int read() override;
|
||||||
/**
|
/**
|
||||||
* Read one byte from the available input without advancing to the
|
* Read one byte from the available input without advancing to the
|
||||||
* next one.
|
* next one.
|
||||||
*
|
*
|
||||||
* @return An unsigned char if input is available, otherwise -1.
|
* @return An unsigned char if input is available, otherwise -1.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
int peek() override;
|
int peek() override;
|
||||||
/**
|
/**
|
||||||
* Write one byte to the output stream.
|
* Write one byte to the output stream.
|
||||||
*
|
*
|
||||||
* Disconnect the client if the socket buffer is full.
|
* Disconnect the client if the socket buffer is full.
|
||||||
@@ -100,8 +100,8 @@ public:
|
|||||||
* @return The number of bytes that were output.
|
* @return The number of bytes that were output.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
size_t write(uint8_t data) override;
|
size_t write(uint8_t data) override;
|
||||||
/**
|
/**
|
||||||
* Write an array of bytes to the output stream.
|
* Write an array of bytes to the output stream.
|
||||||
*
|
*
|
||||||
* Disconnect the client if the socket buffer is full.
|
* Disconnect the client if the socket buffer is full.
|
||||||
@@ -111,8 +111,8 @@ public:
|
|||||||
* @return The number of bytes that were output.
|
* @return The number of bytes that were output.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
size_t write(const uint8_t *buffer, size_t size) override;
|
size_t write(const uint8_t * buffer, size_t size) override;
|
||||||
/**
|
/**
|
||||||
* Does nothing.
|
* Does nothing.
|
||||||
*
|
*
|
||||||
* This is a pure virtual function in Arduino's Stream class, which
|
* This is a pure virtual function in Arduino's Stream class, which
|
||||||
@@ -122,66 +122,69 @@ public:
|
|||||||
*
|
*
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
void flush() override;
|
void flush() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr const unsigned char NUL = 0; /*!< No operation. @since 0.1.0 */
|
static constexpr const unsigned char NUL = 0; /*!< No operation. @since 0.1.0 */
|
||||||
static constexpr const unsigned char BEL = 7; /*!< Produces an audible or visible signal. @since 0.1.0 */
|
static constexpr const unsigned char BEL = 7; /*!< Produces an audible or visible signal. @since 0.1.0 */
|
||||||
static constexpr const unsigned char BS = 8; /*!< Moves the print head one character position towards the left margin. @since 0.1.0 */
|
static constexpr const unsigned char BS = 8; /*!< Moves the print head one character position towards the left margin. @since 0.1.0 */
|
||||||
static constexpr const unsigned char HT = 9; /*!< Moves the printer to the next horizontal tab stop. @since 0.1.0 */
|
static constexpr const unsigned char HT = 9; /*!< Moves the printer to the next horizontal tab stop. @since 0.1.0 */
|
||||||
static constexpr const unsigned char LF = 10; /*!< Line Feed. @since 0.1.0 */
|
static constexpr const unsigned char LF = 10; /*!< Line Feed. @since 0.1.0 */
|
||||||
static constexpr const unsigned char VT = 11; /*!< Moves the printer to the next vertical tab stop. @since 0.1.0 */
|
static constexpr const unsigned char VT = 11; /*!< Moves the printer to the next vertical tab stop. @since 0.1.0 */
|
||||||
static constexpr const unsigned char FF = 12; /*!< Moves the printer to the top of the next page, keeping the same horizontal position. @since 0.1.0 */
|
static constexpr const unsigned char FF = 12; /*!< Moves the printer to the top of the next page, keeping the same horizontal position. @since 0.1.0 */
|
||||||
static constexpr const unsigned char CR = 13; /*!< Carriage Return. @since 0.1.0 */
|
static constexpr const unsigned char CR = 13; /*!< Carriage Return. @since 0.1.0 */
|
||||||
static constexpr const unsigned char SE = 240; /*!< End of sub-negotiation parameters. @since 0.1.0 */
|
static constexpr const unsigned char SE = 240; /*!< End of sub-negotiation parameters. @since 0.1.0 */
|
||||||
static constexpr const unsigned char NOP = 241; /*!< No operation. @since 0.1.0 */
|
static constexpr const unsigned char NOP = 241; /*!< No operation. @since 0.1.0 */
|
||||||
static constexpr const unsigned char DM = 242; /*!< The data stream portion of a Synch. @since 0.1.0 */
|
static constexpr const unsigned char DM = 242; /*!< The data stream portion of a Synch. @since 0.1.0 */
|
||||||
static constexpr const unsigned char BRK = 243; /*!< NVT character BRK. @since 0.1.0 */
|
static constexpr const unsigned char BRK = 243; /*!< NVT character BRK. @since 0.1.0 */
|
||||||
static constexpr const unsigned char IP = 244; /*!< Interrupt Process function. @since 0.1.0 */
|
static constexpr const unsigned char IP = 244; /*!< Interrupt Process function. @since 0.1.0 */
|
||||||
static constexpr const unsigned char AO = 245; /*!< Abort Output function. @since 0.1.0 */
|
static constexpr const unsigned char AO = 245; /*!< Abort Output function. @since 0.1.0 */
|
||||||
static constexpr const unsigned char AYT = 246; /*!< Are You There function. @since 0.1.0 */
|
static constexpr const unsigned char AYT = 246; /*!< Are You There function. @since 0.1.0 */
|
||||||
static constexpr const unsigned char EC = 247; /*!< Erase Character function. @since 0.1.0 */
|
static constexpr const unsigned char EC = 247; /*!< Erase Character function. @since 0.1.0 */
|
||||||
static constexpr const unsigned char EL = 248; /*!< Erase Line function. @since 0.1.0 */
|
static constexpr const unsigned char EL = 248; /*!< Erase Line function. @since 0.1.0 */
|
||||||
static constexpr const unsigned char GA = 249; /*!< Go Ahead signal. @since 0.1.0 */
|
static constexpr const unsigned char GA = 249; /*!< Go Ahead signal. @since 0.1.0 */
|
||||||
static constexpr const unsigned char SB = 250; /*!< Sub-negotiation of the indicated option. @since 0.1.0 */
|
static constexpr const unsigned char SB = 250; /*!< Sub-negotiation of the indicated option. @since 0.1.0 */
|
||||||
static constexpr const unsigned char WILL = 251; /*!< Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option. @since 0.1.0 */
|
static constexpr const unsigned char WILL =
|
||||||
static constexpr const unsigned char WONT = 252; /*!< Indicates the refusal to perform, or continue performing, the indicated option. @since 0.1.0 */
|
251; /*!< Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option. @since 0.1.0 */
|
||||||
static constexpr const unsigned char DO = 253; /*!< Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option. @since 0.1.0 */
|
static constexpr const unsigned char WONT = 252; /*!< Indicates the refusal to perform, or continue performing, the indicated option. @since 0.1.0 */
|
||||||
static constexpr const unsigned char DONT = 254; /*!< Indicates the demand that the other party stop performing, or confirmation that you are no longer expecting the other party to perform, the indicated option. @since 0.1.0 */
|
static constexpr const unsigned char DO =
|
||||||
static constexpr const unsigned char IAC = 255; /*!< Interpret As Command escape character. @since 0.1.0 */
|
253; /*!< Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option. @since 0.1.0 */
|
||||||
|
static constexpr const unsigned char DONT =
|
||||||
|
254; /*!< Indicates the demand that the other party stop performing, or confirmation that you are no longer expecting the other party to perform, the indicated option. @since 0.1.0 */
|
||||||
|
static constexpr const unsigned char IAC = 255; /*!< Interpret As Command escape character. @since 0.1.0 */
|
||||||
|
|
||||||
static constexpr const unsigned char OPT_BINARY = 0; /*!< Binary (8-bit) transmission mode. (RFC 856). @since 0.1.0 */
|
static constexpr const unsigned char OPT_BINARY = 0; /*!< Binary (8-bit) transmission mode. (RFC 856). @since 0.1.0 */
|
||||||
static constexpr const unsigned char OPT_ECHO = 1; /*!< Remote Echo (RFC 857). @since 0.1.0 */
|
static constexpr const unsigned char OPT_ECHO = 1; /*!< Remote Echo (RFC 857). @since 0.1.0 */
|
||||||
static constexpr const unsigned char OPT_SGA = 3; /*!< Suppress Go Ahead (RFC 858). @since 0.1.0 */
|
static constexpr const unsigned char OPT_SGA = 3; /*!< Suppress Go Ahead (RFC 858). @since 0.1.0 */
|
||||||
|
|
||||||
static constexpr const size_t BUFFER_SIZE = 536; /*!< Output buffer size. @since 0.1.0 */
|
static constexpr const size_t BUFFER_SIZE = 536; /*!< Output buffer size. @since 0.1.0 */
|
||||||
|
|
||||||
TelnetStream(const TelnetStream&) = delete;
|
TelnetStream(const TelnetStream &) = delete;
|
||||||
TelnetStream& operator=(const TelnetStream&) = delete;
|
TelnetStream & operator=(const TelnetStream &) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directly check for available input.
|
* Directly check for available input.
|
||||||
*
|
*
|
||||||
* @return The number of bytes available to read.
|
* @return The number of bytes available to read.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
int raw_available();
|
int raw_available();
|
||||||
/**
|
/**
|
||||||
* Read one byte directly from the available input.
|
* Read one byte directly from the available input.
|
||||||
*
|
*
|
||||||
* @return An unsigned char if input is available, otherwise -1.
|
* @return An unsigned char if input is available, otherwise -1.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
int raw_read();
|
int raw_read();
|
||||||
/**
|
/**
|
||||||
* Flush output stream buffer.
|
* Flush output stream buffer.
|
||||||
*
|
*
|
||||||
* Disconnect the client if the socket buffer is full.
|
* Disconnect the client if the socket buffer is full.
|
||||||
*
|
*
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
void buffer_flush();
|
void buffer_flush();
|
||||||
/**
|
/**
|
||||||
* Write one byte directly to the output stream.
|
* Write one byte directly to the output stream.
|
||||||
*
|
*
|
||||||
* Disconnect the client if the socket buffer is full.
|
* Disconnect the client if the socket buffer is full.
|
||||||
@@ -190,8 +193,8 @@ private:
|
|||||||
* @return The number of bytes that were output.
|
* @return The number of bytes that were output.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
size_t raw_write(unsigned char data);
|
size_t raw_write(unsigned char data);
|
||||||
/**
|
/**
|
||||||
* Write a vector of bytes directly to the output stream.
|
* Write a vector of bytes directly to the output stream.
|
||||||
*
|
*
|
||||||
* Disconnect the client if the socket buffer is full.
|
* Disconnect the client if the socket buffer is full.
|
||||||
@@ -200,8 +203,8 @@ private:
|
|||||||
* @return The number of bytes that were output.
|
* @return The number of bytes that were output.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
size_t raw_write(const std::vector<unsigned char> &data);
|
size_t raw_write(const std::vector<unsigned char> & data);
|
||||||
/**
|
/**
|
||||||
* Write an array of bytes directly to the output stream.
|
* Write an array of bytes directly to the output stream.
|
||||||
*
|
*
|
||||||
* Disconnect the client if the socket buffer is full.
|
* Disconnect the client if the socket buffer is full.
|
||||||
@@ -211,15 +214,15 @@ private:
|
|||||||
* @return The number of bytes that were output.
|
* @return The number of bytes that were output.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
size_t raw_write(const uint8_t *buffer, size_t size);
|
size_t raw_write(const uint8_t * buffer, size_t size);
|
||||||
|
|
||||||
WiFiClient &client_; /*!< Client connection. @since 0.1.0 */
|
WiFiClient & client_; /*!< Client connection. @since 0.1.0 */
|
||||||
unsigned char previous_raw_in_ = 0; /*!< Previous raw character that was received. Used to detect commands. @since 0.1.0 */
|
unsigned char previous_raw_in_ = 0; /*!< Previous raw character that was received. Used to detect commands. @since 0.1.0 */
|
||||||
bool sub_negotiation_ = false; /*!< Sub-negotiation mode. @since 0.1.0 */
|
bool sub_negotiation_ = false; /*!< Sub-negotiation mode. @since 0.1.0 */
|
||||||
unsigned char previous_in_ = 0; /*!< Previous character that was received. Used to detect CR NUL. @since 0.1.0 */
|
unsigned char previous_in_ = 0; /*!< Previous character that was received. Used to detect CR NUL. @since 0.1.0 */
|
||||||
unsigned char previous_out_ = 0; /*!< Previous character that was sent. Used to insert NUL after CR without LF. @since 0.1.0 */
|
unsigned char previous_out_ = 0; /*!< Previous character that was sent. Used to insert NUL after CR without LF. @since 0.1.0 */
|
||||||
int peek_ = -1; /*!< Previously read data cached by peek(). @since 0.1.0 */
|
int peek_ = -1; /*!< Previously read data cached by peek(). @since 0.1.0 */
|
||||||
std::vector<char> output_buffer_; /*!< Buffer data to be output until a read function is called. @since 0.1.0 */
|
std::vector<char> output_buffer_; /*!< Buffer data to be output until a read function is called. @since 0.1.0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -228,13 +231,13 @@ private:
|
|||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
class TelnetService {
|
class TelnetService {
|
||||||
public:
|
public:
|
||||||
static constexpr size_t MAX_CONNECTIONS = 3; /*!< Maximum number of concurrent open connections. @since 0.1.0 */
|
static constexpr size_t MAX_CONNECTIONS = 3; /*!< Maximum number of concurrent open connections. @since 0.1.0 */
|
||||||
static constexpr uint16_t DEFAULT_PORT = 23; /*!< Default TCP port to listen on. @since 0.1.0 */
|
static constexpr uint16_t DEFAULT_PORT = 23; /*!< Default TCP port to listen on. @since 0.1.0 */
|
||||||
static constexpr unsigned long DEFAULT_IDLE_TIMEOUT = 600; /*!< Default initial idle timeout (in seconds). @since 0.1.0 */
|
static constexpr unsigned long DEFAULT_IDLE_TIMEOUT = 600; /*!< Default initial idle timeout (in seconds). @since 0.1.0 */
|
||||||
static constexpr unsigned long DEFAULT_WRITE_TIMEOUT = 0; /*!< Default write timeout (in milliseconds). @ since 0.1.0 */
|
static constexpr unsigned long DEFAULT_WRITE_TIMEOUT = 0; /*!< Default write timeout (in milliseconds). @ since 0.1.0 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to handle the creation of a shell.
|
* Function to handle the creation of a shell.
|
||||||
*
|
*
|
||||||
* @param[in] stream Stream for the telnet connection.
|
* @param[in] stream Stream for the telnet connection.
|
||||||
@@ -242,9 +245,9 @@ public:
|
|||||||
* @param[in] port Remote port.
|
* @param[in] port Remote port.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
using shell_factory_function = std::function<std::shared_ptr<uuid::console::Shell>(Stream &stream, const IPAddress &addr, uint16_t port)>;
|
using shell_factory_function = std::function<std::shared_ptr<uuid::console::Shell>(Stream & stream, const IPAddress & addr, uint16_t port)>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new telnet service listening on the default port.
|
* Create a new telnet service listening on the default port.
|
||||||
*
|
*
|
||||||
* @param[in] commands Commands available for execution in shells.
|
* @param[in] commands Commands available for execution in shells.
|
||||||
@@ -252,9 +255,9 @@ public:
|
|||||||
* @param[in] flags Initial flags for shells.
|
* @param[in] flags Initial flags for shells.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
TelnetService(std::shared_ptr<uuid::console::Commands> commands, unsigned int context = 0, unsigned int flags = 0);
|
TelnetService(std::shared_ptr<uuid::console::Commands> commands, unsigned int context = 0, unsigned int flags = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new telnet service listening on a specific port.
|
* Create a new telnet service listening on a specific port.
|
||||||
*
|
*
|
||||||
* @param[in] port TCP listening port.
|
* @param[in] port TCP listening port.
|
||||||
@@ -263,74 +266,74 @@ public:
|
|||||||
* @param[in] flags Initial flags for shells.
|
* @param[in] flags Initial flags for shells.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
TelnetService(uint16_t port, std::shared_ptr<uuid::console::Commands> commands, unsigned int context = 0, unsigned int flags = 0);
|
TelnetService(uint16_t port, std::shared_ptr<uuid::console::Commands> commands, unsigned int context = 0, unsigned int flags = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new telnet service listening on the default port.
|
* Create a new telnet service listening on the default port.
|
||||||
*
|
*
|
||||||
* @param[in] shell_factory Function to create a shell for new connections.
|
* @param[in] shell_factory Function to create a shell for new connections.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
explicit TelnetService(shell_factory_function shell_factory);
|
explicit TelnetService(shell_factory_function shell_factory);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new telnet service listening on a specific port.
|
* Create a new telnet service listening on a specific port.
|
||||||
*
|
*
|
||||||
* @param[in] port TCP listening port.
|
* @param[in] port TCP listening port.
|
||||||
* @param[in] shell_factory Function to create a shell for new connections.
|
* @param[in] shell_factory Function to create a shell for new connections.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
TelnetService(uint16_t port, shell_factory_function shell_factory);
|
TelnetService(uint16_t port, shell_factory_function shell_factory);
|
||||||
|
|
||||||
~TelnetService() = default;
|
~TelnetService() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start listening for connections on the configured port.
|
* Start listening for connections on the configured port.
|
||||||
*
|
*
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
void start();
|
void start();
|
||||||
/**
|
/**
|
||||||
* Close all connections.
|
* Close all connections.
|
||||||
*
|
*
|
||||||
* The listening status is not affected.
|
* The listening status is not affected.
|
||||||
*
|
*
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
void close_all();
|
void close_all();
|
||||||
/**
|
/**
|
||||||
* Stop listening for connections.
|
* Stop listening for connections.
|
||||||
*
|
*
|
||||||
* Existing connections are not affected.
|
* Existing connections are not affected.
|
||||||
*
|
*
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the maximum number of concurrent open connections.
|
* Get the maximum number of concurrent open connections.
|
||||||
*
|
*
|
||||||
* @return The maximum number of concurrent open connections.
|
* @return The maximum number of concurrent open connections.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
size_t maximum_connections() const;
|
size_t maximum_connections() const;
|
||||||
/**
|
/**
|
||||||
* Set the maximum number of concurrent open connections.
|
* Set the maximum number of concurrent open connections.
|
||||||
*
|
*
|
||||||
* Defaults to TelnetService::MAX_CONNECTIONS.
|
* Defaults to TelnetService::MAX_CONNECTIONS.
|
||||||
*
|
*
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
void maximum_connections(size_t count);
|
void maximum_connections(size_t count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the initial idle timeout for new connections.
|
* Get the initial idle timeout for new connections.
|
||||||
*
|
*
|
||||||
* @return The initial idle timeout in seconds (or 0 for disabled).
|
* @return The initial idle timeout in seconds (or 0 for disabled).
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
unsigned long initial_idle_timeout() const;
|
unsigned long initial_idle_timeout() const;
|
||||||
/**
|
/**
|
||||||
* Set the initial idle timeout for new connections.
|
* Set the initial idle timeout for new connections.
|
||||||
*
|
*
|
||||||
* Defaults to TelnetService::DEFAULT_IDLE_TIMEOUT.
|
* Defaults to TelnetService::DEFAULT_IDLE_TIMEOUT.
|
||||||
@@ -338,17 +341,17 @@ public:
|
|||||||
* @param[in] timeout Idle timeout in seconds (or 0 to disable).
|
* @param[in] timeout Idle timeout in seconds (or 0 to disable).
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
void initial_idle_timeout(unsigned long timeout);
|
void initial_idle_timeout(unsigned long timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the default socket write timeout for new connections.
|
* Get the default socket write timeout for new connections.
|
||||||
*
|
*
|
||||||
* @return The default socket write timeout in seconds (or 0 for
|
* @return The default socket write timeout in seconds (or 0 for
|
||||||
* platform default).
|
* platform default).
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
unsigned long default_write_timeout() const;
|
unsigned long default_write_timeout() const;
|
||||||
/**
|
/**
|
||||||
* Set the default socket write timeout for new connections.
|
* Set the default socket write timeout for new connections.
|
||||||
*
|
*
|
||||||
* Defaults to TelnetService::DEFAULT_WRITE_TIMEOUT (platform
|
* Defaults to TelnetService::DEFAULT_WRITE_TIMEOUT (platform
|
||||||
@@ -358,26 +361,26 @@ public:
|
|||||||
* platform default).
|
* platform default).
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
void default_write_timeout(unsigned long timeout);
|
void default_write_timeout(unsigned long timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accept new connections.
|
* Accept new connections.
|
||||||
*
|
*
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
void loop();
|
void loop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Telnet connection.
|
* Telnet connection.
|
||||||
*
|
*
|
||||||
* Holds the client and stream instance for the lifetime of the shell.
|
* Holds the client and stream instance for the lifetime of the shell.
|
||||||
*
|
*
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
class Connection {
|
class Connection {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Create a telnet connection shell.
|
* Create a telnet connection shell.
|
||||||
*
|
*
|
||||||
* @param[in] shell_factory Function to create a shell for new connections.
|
* @param[in] shell_factory Function to create a shell for new connections.
|
||||||
@@ -386,52 +389,52 @@ private:
|
|||||||
* @param[in] write_timeout Idle timeout in milliseconds.
|
* @param[in] write_timeout Idle timeout in milliseconds.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
Connection(shell_factory_function &shell_factory, WiFiClient &&client, unsigned long idle_timeout, unsigned long write_timeout);
|
Connection(shell_factory_function & shell_factory, WiFiClient && client, unsigned long idle_timeout, unsigned long write_timeout);
|
||||||
~Connection() = default;
|
~Connection() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the shell is still active.
|
* Check if the shell is still active.
|
||||||
*
|
*
|
||||||
* @return Active status of the shell.
|
* @return Active status of the shell.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
bool active();
|
bool active();
|
||||||
/**
|
/**
|
||||||
* Stop the shell if the client is not connected.
|
* Stop the shell if the client is not connected.
|
||||||
*
|
*
|
||||||
* @return Active status of the shell.
|
* @return Active status of the shell.
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
bool loop();
|
bool loop();
|
||||||
/**
|
/**
|
||||||
* Stop the shell.
|
* Stop the shell.
|
||||||
*
|
*
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Connection(const Connection&) = delete;
|
Connection(const Connection &) = delete;
|
||||||
Connection& operator=(const Connection&) = delete;
|
Connection & operator=(const Connection &) = delete;
|
||||||
|
|
||||||
WiFiClient client_; /*!< Client connection. @since 0.1.0 */
|
WiFiClient client_; /*!< Client connection. @since 0.1.0 */
|
||||||
TelnetStream stream_; /*!< Telnet stream for the connection. @since 0.1.0 */
|
TelnetStream stream_; /*!< Telnet stream for the connection. @since 0.1.0 */
|
||||||
std::shared_ptr<uuid::console::Shell> shell_; /*!< Shell for connection. @since 0.1.0 */
|
std::shared_ptr<uuid::console::Shell> shell_; /*!< Shell for connection. @since 0.1.0 */
|
||||||
IPAddress addr_; /*!< Remote address of connection. @since 0.1.0 */
|
IPAddress addr_; /*!< Remote address of connection. @since 0.1.0 */
|
||||||
uint16_t port_; /*!< Remote port of connection. @since 0.1.0 */
|
uint16_t port_; /*!< Remote port of connection. @since 0.1.0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
TelnetService(const TelnetService&) = delete;
|
TelnetService(const TelnetService &) = delete;
|
||||||
TelnetService& operator=(const TelnetService&) = delete;
|
TelnetService & operator=(const TelnetService &) = delete;
|
||||||
|
|
||||||
static uuid::log::Logger logger_; /*!< uuid::log::Logger instance for telnet services. @since 0.1.0 */
|
static uuid::log::Logger logger_; /*!< uuid::log::Logger instance for telnet services. @since 0.1.0 */
|
||||||
|
|
||||||
WiFiServer server_; /*!< TCP server. @since 0.1.0 */
|
WiFiServer server_; /*!< TCP server. @since 0.1.0 */
|
||||||
size_t maximum_connections_ = MAX_CONNECTIONS; /*!< Maximum number of concurrent open connections. @since 0.1.0 */
|
size_t maximum_connections_ = MAX_CONNECTIONS; /*!< Maximum number of concurrent open connections. @since 0.1.0 */
|
||||||
std::list<Connection> connections_; /*!< Open connections. @since 0.1.0 */
|
std::list<Connection> connections_; /*!< Open connections. @since 0.1.0 */
|
||||||
shell_factory_function shell_factory_; /*!< Function to create a shell. @since 0.1.0 */
|
shell_factory_function shell_factory_; /*!< Function to create a shell. @since 0.1.0 */
|
||||||
unsigned long initial_idle_timeout_ = DEFAULT_IDLE_TIMEOUT; /*!< Initial idle timeout (in seconds). @since 0.1.0 */
|
unsigned long initial_idle_timeout_ = DEFAULT_IDLE_TIMEOUT; /*!< Initial idle timeout (in seconds). @since 0.1.0 */
|
||||||
unsigned long write_timeout_ = DEFAULT_WRITE_TIMEOUT; /*!< Write timeout (in milliseconds). @since 0.1.0 */
|
unsigned long write_timeout_ = DEFAULT_WRITE_TIMEOUT; /*!< Write timeout (in milliseconds). @since 0.1.0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace telnet
|
} // namespace telnet
|
||||||
|
|||||||
@@ -68,11 +68,10 @@ void ledcWrite(uint8_t chan, uint32_t duty);
|
|||||||
|
|
||||||
#define PROGMEM
|
#define PROGMEM
|
||||||
#define PGM_P const char *
|
#define PGM_P const char *
|
||||||
#define PSTR(s) s
|
|
||||||
|
|
||||||
class __FlashStringHelper;
|
class __FlashStringHelper;
|
||||||
#define FPSTR(string_literal) (reinterpret_cast<const __FlashStringHelper *>(string_literal))
|
#define FPSTR(string_literal) (reinterpret_cast<const __FlashStringHelper *>(string_literal))
|
||||||
#define F(string_literal) (FPSTR(PSTR(string_literal)))
|
#define F(string_literal) (FPSTR((string_literal)))
|
||||||
|
|
||||||
int snprintf_P(char * str, size_t size, const char * format, ...);
|
int snprintf_P(char * str, size_t size, const char * format, ...);
|
||||||
int vsnprintf_P(char * str, size_t size, const char * format, va_list ap);
|
int vsnprintf_P(char * str, size_t size, const char * format, va_list ap);
|
||||||
@@ -97,7 +96,7 @@ class Print {
|
|||||||
virtual size_t write(uint8_t c) = 0;
|
virtual size_t write(uint8_t c) = 0;
|
||||||
virtual size_t write(const uint8_t * buffer, size_t size) = 0;
|
virtual size_t write(const uint8_t * buffer, size_t size) = 0;
|
||||||
size_t print(char c) {
|
size_t print(char c) {
|
||||||
return write((uint8_t)c);
|
return write((uint8_t)c);
|
||||||
}
|
}
|
||||||
size_t print(const char * data) {
|
size_t print(const char * data) {
|
||||||
return write(reinterpret_cast<const uint8_t *>(data), strlen(data));
|
return write(reinterpret_cast<const uint8_t *>(data), strlen(data));
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ struct AsyncMqttClientMessageProperties {
|
|||||||
|
|
||||||
namespace AsyncMqttClientInternals {
|
namespace AsyncMqttClientInternals {
|
||||||
|
|
||||||
typedef std::function<void(bool sessionPresent)> OnConnectUserCallback;
|
typedef std::function<void(bool sessionPresent)> OnConnectUserCallback;
|
||||||
typedef std::function<void(AsyncMqttClientDisconnectReason reason)> OnDisconnectUserCallback;
|
typedef std::function<void(AsyncMqttClientDisconnectReason reason)> OnDisconnectUserCallback;
|
||||||
typedef std::function<void(uint16_t packetId, uint8_t qos)> OnSubscribeUserCallback;
|
typedef std::function<void(uint16_t packetId, uint8_t qos)> OnSubscribeUserCallback;
|
||||||
typedef std::function<void(uint16_t packetId)> OnUnsubscribeUserCallback;
|
typedef std::function<void(uint16_t packetId)> OnUnsubscribeUserCallback;
|
||||||
typedef std::function<void(char * topic, char * payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total)> OnMessageUserCallback;
|
typedef std::function<void(char * topic, char * payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total)> OnMessageUserCallback;
|
||||||
typedef std::function<void(uint16_t packetId)> OnPublishUserCallback;
|
typedef std::function<void(uint16_t packetId)> OnPublishUserCallback;
|
||||||
}; // namespace AsyncMqttClientInternals
|
}; // namespace AsyncMqttClientInternals
|
||||||
|
|
||||||
class AsyncMqttClient {
|
class AsyncMqttClient {
|
||||||
|
|||||||
@@ -13,120 +13,111 @@
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class HttpGetEndpoint {
|
class HttpGetEndpoint {
|
||||||
public:
|
public:
|
||||||
HttpGetEndpoint(JsonStateReader<T> stateReader,
|
HttpGetEndpoint(JsonStateReader<T> stateReader,
|
||||||
StatefulService<T>* statefulService,
|
StatefulService<T> * statefulService,
|
||||||
AsyncWebServer* server,
|
AsyncWebServer * server,
|
||||||
const String& servicePath,
|
const String & servicePath,
|
||||||
SecurityManager* securityManager,
|
SecurityManager * securityManager,
|
||||||
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
|
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
|
||||||
size_t bufferSize = DEFAULT_BUFFER_SIZE) :
|
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||||
_stateReader(stateReader), _statefulService(statefulService), _bufferSize(bufferSize) {
|
: _stateReader(stateReader)
|
||||||
}
|
, _statefulService(statefulService)
|
||||||
|
, _bufferSize(bufferSize) {
|
||||||
|
}
|
||||||
|
|
||||||
HttpGetEndpoint(JsonStateReader<T> stateReader,
|
HttpGetEndpoint(JsonStateReader<T> stateReader,
|
||||||
StatefulService<T>* statefulService,
|
StatefulService<T> * statefulService,
|
||||||
AsyncWebServer* server,
|
AsyncWebServer * server,
|
||||||
const String& servicePath,
|
const String & servicePath,
|
||||||
size_t bufferSize = DEFAULT_BUFFER_SIZE) :
|
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||||
_stateReader(stateReader), _statefulService(statefulService), _bufferSize(bufferSize) {
|
: _stateReader(stateReader)
|
||||||
}
|
, _statefulService(statefulService)
|
||||||
|
, _bufferSize(bufferSize) {
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
JsonStateReader<T> _stateReader;
|
JsonStateReader<T> _stateReader;
|
||||||
StatefulService<T>* _statefulService;
|
StatefulService<T> * _statefulService;
|
||||||
size_t _bufferSize;
|
size_t _bufferSize;
|
||||||
|
|
||||||
void fetchSettings(AsyncWebServerRequest* request) {
|
void fetchSettings(AsyncWebServerRequest * request) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class HttpPostEndpoint {
|
class HttpPostEndpoint {
|
||||||
public:
|
public:
|
||||||
HttpPostEndpoint(JsonStateReader<T> stateReader,
|
HttpPostEndpoint(JsonStateReader<T> stateReader,
|
||||||
JsonStateUpdater<T> stateUpdater,
|
JsonStateUpdater<T> stateUpdater,
|
||||||
StatefulService<T>* statefulService,
|
StatefulService<T> * statefulService,
|
||||||
AsyncWebServer* server,
|
AsyncWebServer * server,
|
||||||
const String& servicePath,
|
const String & servicePath,
|
||||||
SecurityManager* securityManager,
|
SecurityManager * securityManager,
|
||||||
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
|
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
|
||||||
size_t bufferSize = DEFAULT_BUFFER_SIZE) :
|
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||||
_stateReader(stateReader),
|
: _stateReader(stateReader)
|
||||||
_stateUpdater(stateUpdater),
|
, _stateUpdater(stateUpdater)
|
||||||
_statefulService(statefulService),
|
, _statefulService(statefulService)
|
||||||
_bufferSize(bufferSize) {
|
, _bufferSize(bufferSize) {
|
||||||
}
|
|
||||||
|
|
||||||
HttpPostEndpoint(JsonStateReader<T> stateReader,
|
|
||||||
JsonStateUpdater<T> stateUpdater,
|
|
||||||
StatefulService<T>* statefulService,
|
|
||||||
AsyncWebServer* server,
|
|
||||||
const String& servicePath,
|
|
||||||
size_t bufferSize = DEFAULT_BUFFER_SIZE) :
|
|
||||||
_stateReader(stateReader),
|
|
||||||
_stateUpdater(stateUpdater),
|
|
||||||
_statefulService(statefulService),
|
|
||||||
_bufferSize(bufferSize) {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
JsonStateReader<T> _stateReader;
|
|
||||||
JsonStateUpdater<T> _stateUpdater;
|
|
||||||
StatefulService<T>* _statefulService;
|
|
||||||
size_t _bufferSize;
|
|
||||||
|
|
||||||
void updateSettings(AsyncWebServerRequest* request, JsonVariant& json) {
|
|
||||||
if (!json.is<JsonObject>()) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
JsonObject jsonObject = json.as<JsonObject>();
|
|
||||||
StateUpdateResult outcome = _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater);
|
HttpPostEndpoint(JsonStateReader<T> stateReader,
|
||||||
if (outcome == StateUpdateResult::ERROR) {
|
JsonStateUpdater<T> stateUpdater,
|
||||||
return;
|
StatefulService<T> * statefulService,
|
||||||
|
AsyncWebServer * server,
|
||||||
|
const String & servicePath,
|
||||||
|
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||||
|
: _stateReader(stateReader)
|
||||||
|
, _stateUpdater(stateUpdater)
|
||||||
|
, _statefulService(statefulService)
|
||||||
|
, _bufferSize(bufferSize) {
|
||||||
}
|
}
|
||||||
if (outcome == StateUpdateResult::CHANGED) {
|
|
||||||
|
protected:
|
||||||
|
JsonStateReader<T> _stateReader;
|
||||||
|
JsonStateUpdater<T> _stateUpdater;
|
||||||
|
StatefulService<T> * _statefulService;
|
||||||
|
size_t _bufferSize;
|
||||||
|
|
||||||
|
void updateSettings(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||||
|
if (!json.is<JsonObject>()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JsonObject jsonObject = json.as<JsonObject>();
|
||||||
|
StateUpdateResult outcome = _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater);
|
||||||
|
if (outcome == StateUpdateResult::ERROR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (outcome == StateUpdateResult::CHANGED) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class HttpEndpoint : public HttpGetEndpoint<T>, public HttpPostEndpoint<T> {
|
class HttpEndpoint : public HttpGetEndpoint<T>, public HttpPostEndpoint<T> {
|
||||||
public:
|
public:
|
||||||
HttpEndpoint(JsonStateReader<T> stateReader,
|
HttpEndpoint(JsonStateReader<T> stateReader,
|
||||||
JsonStateUpdater<T> stateUpdater,
|
JsonStateUpdater<T> stateUpdater,
|
||||||
StatefulService<T>* statefulService,
|
StatefulService<T> * statefulService,
|
||||||
AsyncWebServer* server,
|
AsyncWebServer * server,
|
||||||
const String& servicePath,
|
const String & servicePath,
|
||||||
SecurityManager* securityManager,
|
SecurityManager * securityManager,
|
||||||
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
|
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
|
||||||
size_t bufferSize = DEFAULT_BUFFER_SIZE) :
|
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||||
HttpGetEndpoint<T>(stateReader,
|
: HttpGetEndpoint<T>(stateReader, statefulService, server, servicePath, securityManager, authenticationPredicate, bufferSize)
|
||||||
statefulService,
|
, HttpPostEndpoint<T>(stateReader, stateUpdater, statefulService, server, servicePath, securityManager, authenticationPredicate, bufferSize) {
|
||||||
server,
|
}
|
||||||
servicePath,
|
|
||||||
securityManager,
|
|
||||||
authenticationPredicate,
|
|
||||||
bufferSize),
|
|
||||||
HttpPostEndpoint<T>(stateReader,
|
|
||||||
stateUpdater,
|
|
||||||
statefulService,
|
|
||||||
server,
|
|
||||||
servicePath,
|
|
||||||
securityManager,
|
|
||||||
authenticationPredicate,
|
|
||||||
bufferSize) {
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpEndpoint(JsonStateReader<T> stateReader,
|
HttpEndpoint(JsonStateReader<T> stateReader,
|
||||||
JsonStateUpdater<T> stateUpdater,
|
JsonStateUpdater<T> stateUpdater,
|
||||||
StatefulService<T>* statefulService,
|
StatefulService<T> * statefulService,
|
||||||
AsyncWebServer* server,
|
AsyncWebServer * server,
|
||||||
const String& servicePath,
|
const String & servicePath,
|
||||||
size_t bufferSize = DEFAULT_BUFFER_SIZE) :
|
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||||
HttpGetEndpoint<T>(stateReader, statefulService, server, servicePath, bufferSize),
|
: HttpGetEndpoint<T>(stateReader, statefulService, server, servicePath, bufferSize)
|
||||||
HttpPostEndpoint<T>(stateReader, stateUpdater, statefulService, server, servicePath, bufferSize) {
|
, HttpPostEndpoint<T>(stateReader, stateUpdater, statefulService, server, servicePath, bufferSize) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -61,51 +61,51 @@ typedef enum {
|
|||||||
} wifi_auth_mode_t;
|
} wifi_auth_mode_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t status; /**< status of scanning APs: 0 — success, 1 - failure */
|
uint32_t status; /**< status of scanning APs: 0 — success, 1 - failure */
|
||||||
uint8_t number; /**< number of scan results */
|
uint8_t number; /**< number of scan results */
|
||||||
uint8_t scan_id; /**< scan sequence number, used for block scan */
|
uint8_t scan_id; /**< scan sequence number, used for block scan */
|
||||||
} wifi_event_sta_scan_done_t;
|
} wifi_event_sta_scan_done_t;
|
||||||
|
|
||||||
/** Argument structure for WIFI_EVENT_STA_CONNECTED event */
|
/** Argument structure for WIFI_EVENT_STA_CONNECTED event */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t ssid[32]; /**< SSID of connected AP */
|
uint8_t ssid[32]; /**< SSID of connected AP */
|
||||||
uint8_t ssid_len; /**< SSID length of connected AP */
|
uint8_t ssid_len; /**< SSID length of connected AP */
|
||||||
uint8_t bssid[6]; /**< BSSID of connected AP*/
|
uint8_t bssid[6]; /**< BSSID of connected AP*/
|
||||||
uint8_t channel; /**< channel of connected AP*/
|
uint8_t channel; /**< channel of connected AP*/
|
||||||
wifi_auth_mode_t authmode;/**< authentication mode used by AP*/
|
wifi_auth_mode_t authmode; /**< authentication mode used by AP*/
|
||||||
} wifi_event_sta_connected_t;
|
} wifi_event_sta_connected_t;
|
||||||
|
|
||||||
/** Argument structure for WIFI_EVENT_STA_DISCONNECTED event */
|
/** Argument structure for WIFI_EVENT_STA_DISCONNECTED event */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t ssid[32]; /**< SSID of disconnected AP */
|
uint8_t ssid[32]; /**< SSID of disconnected AP */
|
||||||
uint8_t ssid_len; /**< SSID length of disconnected AP */
|
uint8_t ssid_len; /**< SSID length of disconnected AP */
|
||||||
uint8_t bssid[6]; /**< BSSID of disconnected AP */
|
uint8_t bssid[6]; /**< BSSID of disconnected AP */
|
||||||
uint8_t reason; /**< reason of disconnection */
|
uint8_t reason; /**< reason of disconnection */
|
||||||
} wifi_event_sta_disconnected_t;
|
} wifi_event_sta_disconnected_t;
|
||||||
|
|
||||||
/** Argument structure for WIFI_EVENT_STA_AUTHMODE_CHANGE event */
|
/** Argument structure for WIFI_EVENT_STA_AUTHMODE_CHANGE event */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
wifi_auth_mode_t old_mode; /**< the old auth mode of AP */
|
wifi_auth_mode_t old_mode; /**< the old auth mode of AP */
|
||||||
wifi_auth_mode_t new_mode; /**< the new auth mode of AP */
|
wifi_auth_mode_t new_mode; /**< the new auth mode of AP */
|
||||||
} wifi_event_sta_authmode_change_t;
|
} wifi_event_sta_authmode_change_t;
|
||||||
|
|
||||||
/** Argument structure for WIFI_EVENT_STA_WPS_ER_PIN event */
|
/** Argument structure for WIFI_EVENT_STA_WPS_ER_PIN event */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */
|
uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */
|
||||||
} wifi_event_sta_wps_er_pin_t;
|
} wifi_event_sta_wps_er_pin_t;
|
||||||
|
|
||||||
/** Argument structure for WIFI_EVENT_STA_WPS_ER_FAILED event */
|
/** Argument structure for WIFI_EVENT_STA_WPS_ER_FAILED event */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WPS_FAIL_REASON_NORMAL = 0, /**< ESP32 WPS normal fail reason */
|
WPS_FAIL_REASON_NORMAL = 0, /**< ESP32 WPS normal fail reason */
|
||||||
WPS_FAIL_REASON_RECV_M2D, /**< ESP32 WPS receive M2D frame */
|
WPS_FAIL_REASON_RECV_M2D, /**< ESP32 WPS receive M2D frame */
|
||||||
WPS_FAIL_REASON_MAX
|
WPS_FAIL_REASON_MAX
|
||||||
} wifi_event_sta_wps_fail_reason_t;
|
} wifi_event_sta_wps_fail_reason_t;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
wifi_event_sta_scan_done_t wifi_scan_done;
|
wifi_event_sta_scan_done_t wifi_scan_done;
|
||||||
wifi_event_sta_authmode_change_t wifi_sta_authmode_change;
|
wifi_event_sta_authmode_change_t wifi_sta_authmode_change;
|
||||||
wifi_event_sta_connected_t wifi_sta_connected;
|
wifi_event_sta_connected_t wifi_sta_connected;
|
||||||
wifi_event_sta_disconnected_t wifi_sta_disconnected;
|
wifi_event_sta_disconnected_t wifi_sta_disconnected;
|
||||||
} arduino_event_info_t;
|
} arduino_event_info_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -4,139 +4,136 @@
|
|||||||
|
|
||||||
#include "../../src/emsesp_stub.h" // proddy added
|
#include "../../src/emsesp_stub.h" // proddy added
|
||||||
|
|
||||||
SecuritySettingsService::SecuritySettingsService(AsyncWebServer* server, FS* fs) :
|
SecuritySettingsService::SecuritySettingsService(AsyncWebServer * server, FS * fs)
|
||||||
_httpEndpoint(SecuritySettings::read, SecuritySettings::update, this, server, SECURITY_SETTINGS_PATH, this),
|
: _httpEndpoint(SecuritySettings::read, SecuritySettings::update, this, server, SECURITY_SETTINGS_PATH, this)
|
||||||
_fsPersistence(SecuritySettings::read, SecuritySettings::update, this, fs, SECURITY_SETTINGS_FILE),
|
, _fsPersistence(SecuritySettings::read, SecuritySettings::update, this, fs, SECURITY_SETTINGS_FILE)
|
||||||
_jwtHandler(FACTORY_JWT_SECRET) {
|
, _jwtHandler(FACTORY_JWT_SECRET) {
|
||||||
addUpdateHandler([&](const String& originId) { configureJWTHandler(); }, false);
|
addUpdateHandler([&](const String & originId) { configureJWTHandler(); }, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecuritySettingsService::begin() {
|
void SecuritySettingsService::begin() {
|
||||||
_fsPersistence.readFromFS();
|
_fsPersistence.readFromFS();
|
||||||
configureJWTHandler();
|
configureJWTHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerRequest* request) {
|
Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerRequest * request) {
|
||||||
AsyncWebHeader* authorizationHeader = request->getHeader(AUTHORIZATION_HEADER);
|
AsyncWebHeader * authorizationHeader = request->getHeader(AUTHORIZATION_HEADER);
|
||||||
if (authorizationHeader) {
|
if (authorizationHeader) {
|
||||||
String value = authorizationHeader->value();
|
String value = authorizationHeader->value();
|
||||||
if (value.startsWith(AUTHORIZATION_HEADER_PREFIX)) {
|
if (value.startsWith(AUTHORIZATION_HEADER_PREFIX)) {
|
||||||
value = value.substring(AUTHORIZATION_HEADER_PREFIX_LEN);
|
value = value.substring(AUTHORIZATION_HEADER_PREFIX_LEN);
|
||||||
return authenticateJWT(value);
|
return authenticateJWT(value);
|
||||||
|
}
|
||||||
|
} else if (request->hasParam(ACCESS_TOKEN_PARAMATER)) {
|
||||||
|
AsyncWebParameter * tokenParamater = request->getParam(ACCESS_TOKEN_PARAMATER);
|
||||||
|
String value = tokenParamater->value();
|
||||||
|
return authenticateJWT(value);
|
||||||
}
|
}
|
||||||
} else if (request->hasParam(ACCESS_TOKEN_PARAMATER)) {
|
return Authentication();
|
||||||
AsyncWebParameter* tokenParamater = request->getParam(ACCESS_TOKEN_PARAMATER);
|
|
||||||
String value = tokenParamater->value();
|
|
||||||
return authenticateJWT(value);
|
|
||||||
}
|
|
||||||
return Authentication();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecuritySettingsService::configureJWTHandler() {
|
void SecuritySettingsService::configureJWTHandler() {
|
||||||
_jwtHandler.setSecret(_state.jwtSecret);
|
_jwtHandler.setSecret(_state.jwtSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
Authentication SecuritySettingsService::authenticateJWT(String& jwt) {
|
Authentication SecuritySettingsService::authenticateJWT(String & jwt) {
|
||||||
DynamicJsonDocument payloadDocument(MAX_JWT_SIZE);
|
DynamicJsonDocument payloadDocument(MAX_JWT_SIZE);
|
||||||
_jwtHandler.parseJWT(jwt, payloadDocument);
|
_jwtHandler.parseJWT(jwt, payloadDocument);
|
||||||
if (payloadDocument.is<JsonObject>()) {
|
if (payloadDocument.is<JsonObject>()) {
|
||||||
JsonObject parsedPayload = payloadDocument.as<JsonObject>();
|
JsonObject parsedPayload = payloadDocument.as<JsonObject>();
|
||||||
String username = parsedPayload["username"];
|
String username = parsedPayload["username"];
|
||||||
|
for (User _user : _state.users) {
|
||||||
|
if (_user.username == username && validatePayload(parsedPayload, &_user)) {
|
||||||
|
return Authentication(_user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Authentication();
|
||||||
|
}
|
||||||
|
|
||||||
|
Authentication SecuritySettingsService::authenticate(const String & username, const String & password) {
|
||||||
for (User _user : _state.users) {
|
for (User _user : _state.users) {
|
||||||
if (_user.username == username && validatePayload(parsedPayload, &_user)) {
|
if (_user.username == username && _user.password == password) {
|
||||||
return Authentication(_user);
|
return Authentication(_user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return Authentication();
|
||||||
return Authentication();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Authentication SecuritySettingsService::authenticate(const String& username, const String& password) {
|
inline void populateJWTPayload(JsonObject & payload, User * user) {
|
||||||
for (User _user : _state.users) {
|
payload["username"] = user->username;
|
||||||
if (_user.username == username && _user.password == password) {
|
payload["admin"] = user->admin;
|
||||||
return Authentication(_user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Authentication();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void populateJWTPayload(JsonObject& payload, User* user) {
|
boolean SecuritySettingsService::validatePayload(JsonObject & parsedPayload, User * user) {
|
||||||
payload["username"] = user->username;
|
DynamicJsonDocument jsonDocument(MAX_JWT_SIZE);
|
||||||
payload["admin"] = user->admin;
|
JsonObject payload = jsonDocument.to<JsonObject>();
|
||||||
|
populateJWTPayload(payload, user);
|
||||||
|
return payload == parsedPayload;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean SecuritySettingsService::validatePayload(JsonObject& parsedPayload, User* user) {
|
String SecuritySettingsService::generateJWT(User * user) {
|
||||||
DynamicJsonDocument jsonDocument(MAX_JWT_SIZE);
|
DynamicJsonDocument jsonDocument(MAX_JWT_SIZE);
|
||||||
JsonObject payload = jsonDocument.to<JsonObject>();
|
JsonObject payload = jsonDocument.to<JsonObject>();
|
||||||
populateJWTPayload(payload, user);
|
populateJWTPayload(payload, user);
|
||||||
return payload == parsedPayload;
|
return _jwtHandler.buildJWT(payload);
|
||||||
}
|
|
||||||
|
|
||||||
String SecuritySettingsService::generateJWT(User* user) {
|
|
||||||
DynamicJsonDocument jsonDocument(MAX_JWT_SIZE);
|
|
||||||
JsonObject payload = jsonDocument.to<JsonObject>();
|
|
||||||
populateJWTPayload(payload, user);
|
|
||||||
return _jwtHandler.buildJWT(payload);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) {
|
ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) {
|
||||||
return [this, predicate](AsyncWebServerRequest* request) {
|
return [this, predicate](AsyncWebServerRequest * request) {
|
||||||
Authentication authentication = authenticateRequest(request);
|
Authentication authentication = authenticateRequest(request);
|
||||||
return predicate(authentication);
|
return predicate(authentication);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFunction onRequest,
|
ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate) {
|
||||||
AuthenticationPredicate predicate) {
|
return [this, onRequest, predicate](AsyncWebServerRequest * request) {
|
||||||
return [this, onRequest, predicate](AsyncWebServerRequest* request) {
|
Authentication authentication = authenticateRequest(request);
|
||||||
Authentication authentication = authenticateRequest(request);
|
if (!predicate(authentication)) {
|
||||||
if (!predicate(authentication)) {
|
request->send(401);
|
||||||
request->send(401);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
onRequest(request);
|
||||||
onRequest(request);
|
};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest,
|
ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate) {
|
||||||
AuthenticationPredicate predicate) {
|
return [this, onRequest, predicate](AsyncWebServerRequest * request, JsonVariant & json) {
|
||||||
return [this, onRequest, predicate](AsyncWebServerRequest* request, JsonVariant& json) {
|
Authentication authentication = authenticateRequest(request);
|
||||||
Authentication authentication = authenticateRequest(request);
|
if (!predicate(authentication)) {
|
||||||
if (!predicate(authentication)) {
|
request->send(401);
|
||||||
request->send(401);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
onRequest(request, json);
|
||||||
onRequest(request, json);
|
};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
User ADMIN_USER = User(FACTORY_ADMIN_USERNAME, FACTORY_ADMIN_PASSWORD, true);
|
User ADMIN_USER = User(FACTORY_ADMIN_USERNAME, FACTORY_ADMIN_PASSWORD, true);
|
||||||
|
|
||||||
SecuritySettingsService::SecuritySettingsService(AsyncWebServer* server, FS* fs) : SecurityManager() {
|
SecuritySettingsService::SecuritySettingsService(AsyncWebServer * server, FS * fs)
|
||||||
|
: SecurityManager() {
|
||||||
}
|
}
|
||||||
SecuritySettingsService::~SecuritySettingsService() {
|
SecuritySettingsService::~SecuritySettingsService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) {
|
ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) {
|
||||||
return [this, predicate](AsyncWebServerRequest* request) { return true; };
|
return [this, predicate](AsyncWebServerRequest * request) { return true; };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the admin user on all request - disabling security features
|
// Return the admin user on all request - disabling security features
|
||||||
Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerRequest* request) {
|
Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerRequest * request) {
|
||||||
return Authentication(ADMIN_USER);
|
return Authentication(ADMIN_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the function unwrapped
|
// Return the function unwrapped
|
||||||
ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFunction onRequest,
|
ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate) {
|
||||||
AuthenticationPredicate predicate) {
|
return onRequest;
|
||||||
return onRequest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest,
|
ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate) {
|
||||||
AuthenticationPredicate predicate) {
|
return onRequest;
|
||||||
return onRequest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum class StateUpdateResult {
|
enum class StateUpdateResult {
|
||||||
CHANGED = 0, // The update changed the state and propagation should take place if required
|
CHANGED = 0, // The update changed the state and propagation should take place if required
|
||||||
CHANGED_RESTART, // The update changed the state and the service should be restarted
|
CHANGED_RESTART, // The update changed the state and the service should be restarted
|
||||||
UNCHANGED, // The state was unchanged, propagation should not take place
|
UNCHANGED, // The state was unchanged, propagation should not take place
|
||||||
ERROR // There was a problem updating the state, propagation should not take place
|
ERROR // There was a problem updating the state, propagation should not take place
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
@@ -240,6 +240,8 @@ const mqtt_status = {
|
|||||||
client_id: 'ems-esp',
|
client_id: 'ems-esp',
|
||||||
disconnect_reason: 0,
|
disconnect_reason: 0,
|
||||||
mqtt_fails: 0,
|
mqtt_fails: 0,
|
||||||
|
mqtt_queued: 1,
|
||||||
|
connect_count: 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
// SYSTEM
|
// SYSTEM
|
||||||
@@ -592,20 +594,15 @@ const emsesp_deviceentities_1 = [
|
|||||||
m: 0,
|
m: 0,
|
||||||
w: false,
|
w: false,
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// v: 'test data',
|
v: 18.2,
|
||||||
// n: 'test',
|
n: 'hc1 selected room temperature',
|
||||||
// id: 'test',
|
id: 'hc1/seltemp',
|
||||||
// m: 0,
|
m: 0,
|
||||||
// w: false,
|
mi: 5,
|
||||||
// },
|
ma: 52,
|
||||||
// {
|
w: true,
|
||||||
// v: 18.2,
|
},
|
||||||
// n: 'hc1 selected room temperature',
|
|
||||||
// id: 'hc1/seltemp',
|
|
||||||
// m: 0,
|
|
||||||
// w: true,
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
v: 22.6,
|
v: 22.6,
|
||||||
n: 'hc1 current room temperature',
|
n: 'hc1 current room temperature',
|
||||||
|
|||||||
@@ -92,3 +92,14 @@ board_upload.flash_size = 4MB
|
|||||||
board_build.partitions = esp32_partition_4M.csv
|
board_build.partitions = esp32_partition_4M.csv
|
||||||
build_flags = ${common.build_flags}
|
build_flags = ${common.build_flags}
|
||||||
build_unflags = ${common.unbuild_flags}
|
build_unflags = ${common.unbuild_flags}
|
||||||
|
|
||||||
|
[env:lolin_s2_mini]
|
||||||
|
extra_scripts =
|
||||||
|
pre:scripts/build_interface.py
|
||||||
|
scripts/rename_fw.py
|
||||||
|
board = lolin_s2_mini
|
||||||
|
platform = espressif32
|
||||||
|
board_upload.flash_size = 4MB
|
||||||
|
board_build.partitions = esp32_partition_4M.csv
|
||||||
|
build_flags = ${common.build_flags}
|
||||||
|
build_unflags = ${common.unbuild_flags}
|
||||||
|
|||||||
@@ -18,27 +18,29 @@ def bin_copy(source, target, env):
|
|||||||
bag[var] = m.group(1)
|
bag[var] = m.group(1)
|
||||||
|
|
||||||
app_version = bag.get('app_version')
|
app_version = bag.get('app_version')
|
||||||
platform = "ESP32"
|
|
||||||
|
|
||||||
|
platform = "ESP32"
|
||||||
|
chip_target = env.get('PIOENV').upper()
|
||||||
|
|
||||||
|
# this breaks the CI so removed
|
||||||
# flash_size = env["PIOENV"].split('_')[1]
|
# flash_size = env["PIOENV"].split('_')[1]
|
||||||
|
|
||||||
# print(env.Dump())
|
# print(env.Dump())
|
||||||
# my_flags = env.ParseFlags(env['BUILD_FLAGS'])
|
# my_flags = env.ParseFlags(env['BUILD_FLAGS'])
|
||||||
# defines = {k: v for (k, v) in my_flags.get("CPPDEFINES")}
|
# defines = {k: v for (k, v) in my_flags.get("CPPDEFINES")}
|
||||||
# print(my_flags)
|
# print(my_flags)
|
||||||
# print((my_flags.get("CPPDEFINES"))
|
# print(my_flags.get("CPPDEFINES")
|
||||||
|
|
||||||
# alternatively take platform from the pio target
|
# alternatively take platform from the pio target
|
||||||
# platform = str(target[0]).split(os.path.sep)[2]
|
# platform = str(target[0]).split(os.path.sep)[2]
|
||||||
|
chip_target = env.get('PIOENV').upper()
|
||||||
|
|
||||||
print("app version: "+app_version)
|
print("app version: " + app_version)
|
||||||
print("platform: "+platform)
|
print("platform: " + platform)
|
||||||
# print("flash size: "+flash_size)
|
print("chip_target: " + chip_target)
|
||||||
|
|
||||||
# convert . to _ so Windows doesn't complain
|
# convert . to _ so Windows doesn't complain
|
||||||
variant = "EMS-ESP-" + app_version.replace(".", "_") + "-" + platform
|
variant = "EMS-ESP-" + chip_target + "-" + app_version.replace(".", "_")
|
||||||
|
|
||||||
# variant = "EMS-ESP-" + app_version.replace(".", "_") + "-" + platform + "_" + flash_size
|
|
||||||
|
|
||||||
# check if output directories exist and create if necessary
|
# check if output directories exist and create if necessary
|
||||||
if not os.path.isdir(OUTPUT_DIR):
|
if not os.path.isdir(OUTPUT_DIR):
|
||||||
|
|||||||
@@ -31,26 +31,25 @@ void AnalogSensor::start() {
|
|||||||
}
|
}
|
||||||
analogSetAttenuation(ADC_2_5db); // for all channels 1.5V
|
analogSetAttenuation(ADC_2_5db); // for all channels 1.5V
|
||||||
|
|
||||||
|
LOG_INFO("Starting Analog sensor service");
|
||||||
LOG_INFO(F("Starting Analog sensor service"));
|
|
||||||
|
|
||||||
// Add API call for /info
|
// Add API call for /info
|
||||||
Command::add(
|
Command::add(
|
||||||
EMSdevice::DeviceType::ANALOGSENSOR,
|
EMSdevice::DeviceType::ANALOGSENSOR,
|
||||||
F_(info),
|
F_(info),
|
||||||
[&](const char * value, const int8_t id, JsonObject & output) { return command_info(value, id, output); },
|
[&](const char * value, const int8_t id, JsonObject & output) { return command_info(value, id, output); },
|
||||||
F_(info_cmd));
|
FL_(info_cmd));
|
||||||
Command::add(
|
Command::add(
|
||||||
EMSdevice::DeviceType::ANALOGSENSOR,
|
EMSdevice::DeviceType::ANALOGSENSOR,
|
||||||
F_(setvalue),
|
F_(setvalue),
|
||||||
[&](const char * value, const int8_t id) { return command_setvalue(value, id); },
|
[&](const char * value, const int8_t id) { return command_setvalue(value, id); },
|
||||||
F("set io value"), // TODO this needs translating
|
FL_(setiovalue_cmd),
|
||||||
CommandFlag::ADMIN_ONLY);
|
CommandFlag::ADMIN_ONLY);
|
||||||
Command::add(
|
Command::add(
|
||||||
EMSdevice::DeviceType::ANALOGSENSOR,
|
EMSdevice::DeviceType::ANALOGSENSOR,
|
||||||
F_(commands),
|
F_(commands),
|
||||||
[&](const char * value, const int8_t id, JsonObject & output) { return command_commands(value, id, output); },
|
[&](const char * value, const int8_t id, JsonObject & output) { return command_commands(value, id, output); },
|
||||||
F_(commands_cmd));
|
FL_(commands_cmd));
|
||||||
|
|
||||||
Mqtt::subscribe(EMSdevice::DeviceType::ANALOGSENSOR, "analogsensor/#", nullptr); // use empty function callback
|
Mqtt::subscribe(EMSdevice::DeviceType::ANALOGSENSOR, "analogsensor/#", nullptr); // use empty function callback
|
||||||
}
|
}
|
||||||
@@ -123,12 +122,12 @@ void AnalogSensor::reload() {
|
|||||||
for (auto & sensor : sensors_) {
|
for (auto & sensor : sensors_) {
|
||||||
sensor.ha_registered = false; // force HA configs to be re-created
|
sensor.ha_registered = false; // force HA configs to be re-created
|
||||||
if (sensor.type() == AnalogType::ADC) {
|
if (sensor.type() == AnalogType::ADC) {
|
||||||
LOG_DEBUG(F("Adding analog ADC sensor on GPIO%d"), sensor.gpio());
|
LOG_DEBUG("Adding analog ADC sensor on GPIO%d", sensor.gpio());
|
||||||
// analogSetPinAttenuation does not work with analogReadMilliVolts
|
// analogSetPinAttenuation does not work with analogReadMilliVolts
|
||||||
sensor.analog_ = 0; // initialize
|
sensor.analog_ = 0; // initialize
|
||||||
sensor.last_reading_ = 0;
|
sensor.last_reading_ = 0;
|
||||||
} else if (sensor.type() == AnalogType::COUNTER) {
|
} else if (sensor.type() == AnalogType::COUNTER) {
|
||||||
LOG_DEBUG(F("Adding analog I/O Counter sensor on GPIO%d"), sensor.gpio());
|
LOG_DEBUG("Adding analog I/O Counter sensor on GPIO%d", sensor.gpio());
|
||||||
pinMode(sensor.gpio(), INPUT_PULLUP);
|
pinMode(sensor.gpio(), INPUT_PULLUP);
|
||||||
#ifndef ARDUINO_LOLIN_C3_MINI
|
#ifndef ARDUINO_LOLIN_C3_MINI
|
||||||
if (sensor.gpio() == 25 || sensor.gpio() == 26) {
|
if (sensor.gpio() == 25 || sensor.gpio() == 26) {
|
||||||
@@ -139,7 +138,7 @@ void AnalogSensor::reload() {
|
|||||||
sensor.poll_ = digitalRead(sensor.gpio());
|
sensor.poll_ = digitalRead(sensor.gpio());
|
||||||
publish_sensor(sensor);
|
publish_sensor(sensor);
|
||||||
} else if (sensor.type() == AnalogType::TIMER || sensor.type() == AnalogType::RATE) {
|
} else if (sensor.type() == AnalogType::TIMER || sensor.type() == AnalogType::RATE) {
|
||||||
LOG_DEBUG(F("Adding analog Timer/Rate sensor on GPIO%d"), sensor.gpio());
|
LOG_DEBUG("Adding analog Timer/Rate sensor on GPIO%d", sensor.gpio());
|
||||||
pinMode(sensor.gpio(), INPUT_PULLUP);
|
pinMode(sensor.gpio(), INPUT_PULLUP);
|
||||||
sensor.polltime_ = uuid::get_uptime();
|
sensor.polltime_ = uuid::get_uptime();
|
||||||
sensor.last_polltime_ = uuid::get_uptime();
|
sensor.last_polltime_ = uuid::get_uptime();
|
||||||
@@ -148,7 +147,7 @@ void AnalogSensor::reload() {
|
|||||||
sensor.set_value(0);
|
sensor.set_value(0);
|
||||||
publish_sensor(sensor);
|
publish_sensor(sensor);
|
||||||
} else if (sensor.type() == AnalogType::DIGITAL_IN) {
|
} else if (sensor.type() == AnalogType::DIGITAL_IN) {
|
||||||
LOG_DEBUG(F("Adding analog Read sensor on GPIO%d"), sensor.gpio());
|
LOG_DEBUG("Adding analog Read sensor on GPIO%d", sensor.gpio());
|
||||||
pinMode(sensor.gpio(), INPUT_PULLUP);
|
pinMode(sensor.gpio(), INPUT_PULLUP);
|
||||||
sensor.set_value(digitalRead(sensor.gpio())); // initial value
|
sensor.set_value(digitalRead(sensor.gpio())); // initial value
|
||||||
sensor.set_uom(0); // no uom, just for safe measures
|
sensor.set_uom(0); // no uom, just for safe measures
|
||||||
@@ -156,7 +155,7 @@ void AnalogSensor::reload() {
|
|||||||
sensor.poll_ = digitalRead(sensor.gpio());
|
sensor.poll_ = digitalRead(sensor.gpio());
|
||||||
publish_sensor(sensor);
|
publish_sensor(sensor);
|
||||||
} else if (sensor.type() == AnalogType::DIGITAL_OUT) {
|
} else if (sensor.type() == AnalogType::DIGITAL_OUT) {
|
||||||
LOG_DEBUG(F("Adding analog Write sensor on GPIO%d"), sensor.gpio());
|
LOG_DEBUG("Adding analog Write sensor on GPIO%d", sensor.gpio());
|
||||||
pinMode(sensor.gpio(), OUTPUT);
|
pinMode(sensor.gpio(), OUTPUT);
|
||||||
if (sensor.gpio() == 25 || sensor.gpio() == 26) {
|
if (sensor.gpio() == 25 || sensor.gpio() == 26) {
|
||||||
if (sensor.offset() > 255) {
|
if (sensor.offset() > 255) {
|
||||||
@@ -175,7 +174,7 @@ void AnalogSensor::reload() {
|
|||||||
sensor.set_uom(0); // no uom, just for safe measures
|
sensor.set_uom(0); // no uom, just for safe measures
|
||||||
publish_sensor(sensor);
|
publish_sensor(sensor);
|
||||||
} else if (sensor.type() >= AnalogType::PWM_0) {
|
} else if (sensor.type() >= AnalogType::PWM_0) {
|
||||||
LOG_DEBUG(F("Adding PWM output sensor on GPIO%d"), sensor.gpio());
|
LOG_DEBUG("Adding PWM output sensor on GPIO%d", sensor.gpio());
|
||||||
uint channel = sensor.type() - AnalogType::PWM_0;
|
uint channel = sensor.type() - AnalogType::PWM_0;
|
||||||
ledcSetup(channel, sensor.factor(), 13);
|
ledcSetup(channel, sensor.factor(), 13);
|
||||||
ledcAttachPin(sensor.gpio(), channel);
|
ledcAttachPin(sensor.gpio(), channel);
|
||||||
@@ -277,7 +276,7 @@ bool AnalogSensor::update(uint8_t gpio, const std::string & name, float offset,
|
|||||||
found_sensor = true; // found the record
|
found_sensor = true; // found the record
|
||||||
// see if it's marked for deletion
|
// see if it's marked for deletion
|
||||||
if (type == AnalogType::MARK_DELETED) {
|
if (type == AnalogType::MARK_DELETED) {
|
||||||
LOG_DEBUG(F("Removing analog sensor GPIO %d"), gpio);
|
LOG_DEBUG("Removing analog sensor GPIO %d", gpio);
|
||||||
settings.analogCustomizations.remove(AnalogCustomization);
|
settings.analogCustomizations.remove(AnalogCustomization);
|
||||||
} else {
|
} else {
|
||||||
// update existing record
|
// update existing record
|
||||||
@@ -286,7 +285,7 @@ bool AnalogSensor::update(uint8_t gpio, const std::string & name, float offset,
|
|||||||
AnalogCustomization.factor = factor;
|
AnalogCustomization.factor = factor;
|
||||||
AnalogCustomization.uom = uom;
|
AnalogCustomization.uom = uom;
|
||||||
AnalogCustomization.type = type;
|
AnalogCustomization.type = type;
|
||||||
LOG_DEBUG(F("Customizing existing analog GPIO %d"), gpio);
|
LOG_DEBUG("Customizing existing analog GPIO %d", gpio);
|
||||||
}
|
}
|
||||||
return StateUpdateResult::CHANGED; // persist the change
|
return StateUpdateResult::CHANGED; // persist the change
|
||||||
}
|
}
|
||||||
@@ -312,7 +311,7 @@ bool AnalogSensor::update(uint8_t gpio, const std::string & name, float offset,
|
|||||||
newSensor.uom = uom;
|
newSensor.uom = uom;
|
||||||
newSensor.type = type;
|
newSensor.type = type;
|
||||||
settings.analogCustomizations.push_back(newSensor);
|
settings.analogCustomizations.push_back(newSensor);
|
||||||
LOG_DEBUG(F("Adding new customization for analog sensor GPIO %d"), gpio);
|
LOG_DEBUG("Adding new customization for analog sensor GPIO %d", gpio);
|
||||||
return StateUpdateResult::CHANGED; // persist the change
|
return StateUpdateResult::CHANGED; // persist the change
|
||||||
},
|
},
|
||||||
"local");
|
"local");
|
||||||
@@ -338,9 +337,9 @@ void AnalogSensor::publish_sensor(const Sensor & sensor) const {
|
|||||||
if (Mqtt::publish_single()) {
|
if (Mqtt::publish_single()) {
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
if (Mqtt::publish_single2cmd()) {
|
if (Mqtt::publish_single2cmd()) {
|
||||||
snprintf(topic, sizeof(topic), "%s/%s", read_flash_string(F_(analogsensor)).c_str(), sensor.name().c_str());
|
snprintf(topic, sizeof(topic), "%s/%s", (F_(analogsensor)), sensor.name().c_str());
|
||||||
} else {
|
} else {
|
||||||
snprintf(topic, sizeof(topic), "%s%s/%s", read_flash_string(F_(analogsensor)).c_str(), "_data", sensor.name().c_str());
|
snprintf(topic, sizeof(topic), "%s%s/%s", (F_(analogsensor)), "_data", sensor.name().c_str());
|
||||||
}
|
}
|
||||||
char payload[10];
|
char payload[10];
|
||||||
Mqtt::publish(topic, Helpers::render_value(payload, sensor.value(), 2)); // always publish as floats
|
Mqtt::publish(topic, Helpers::render_value(payload, sensor.value(), 2)); // always publish as floats
|
||||||
@@ -353,7 +352,7 @@ void AnalogSensor::remove_ha_topic(const uint8_t gpio) const {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef EMSESP_DEBUG
|
#ifdef EMSESP_DEBUG
|
||||||
LOG_DEBUG(F("Removing HA config for analog sensor GPIO %d"), gpio);
|
LOG_DEBUG("Removing HA config for analog sensor GPIO %d", gpio);
|
||||||
#endif
|
#endif
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
snprintf(topic, sizeof(topic), "sensor/%s/analogsensor_%d/config", Mqtt::basename().c_str(), gpio);
|
snprintf(topic, sizeof(topic), "sensor/%s/analogsensor_%d/config", Mqtt::basename().c_str(), gpio);
|
||||||
@@ -390,7 +389,7 @@ void AnalogSensor::publish_values(const bool force) {
|
|||||||
case AnalogType::PWM_0:
|
case AnalogType::PWM_0:
|
||||||
case AnalogType::PWM_1:
|
case AnalogType::PWM_1:
|
||||||
case AnalogType::PWM_2:
|
case AnalogType::PWM_2:
|
||||||
dataSensor["value"] = sensor.value(); // float
|
dataSensor["value"] = serialized(Helpers::render_value(s, sensor.value(), 2)); // float
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dataSensor["value"] = (uint8_t)sensor.value(); // convert to char for 1 or 0
|
dataSensor["value"] = (uint8_t)sensor.value(); // convert to char for 1 or 0
|
||||||
@@ -403,7 +402,7 @@ void AnalogSensor::publish_values(const bool force) {
|
|||||||
|
|
||||||
// create HA config
|
// create HA config
|
||||||
if (Mqtt::ha_enabled() && (!sensor.ha_registered || force)) {
|
if (Mqtt::ha_enabled() && (!sensor.ha_registered || force)) {
|
||||||
LOG_DEBUG(F("Recreating HA config for analog sensor GPIO %d"), sensor.gpio());
|
LOG_DEBUG("Recreating HA config for analog sensor GPIO %d", sensor.gpio());
|
||||||
|
|
||||||
StaticJsonDocument<EMSESP_JSON_SIZE_MEDIUM> config;
|
StaticJsonDocument<EMSESP_JSON_SIZE_MEDIUM> config;
|
||||||
|
|
||||||
@@ -447,7 +446,7 @@ void AnalogSensor::publish_values(const bool force) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Mqtt::publish(F("analogsensor_data"), doc.as<JsonObject>());
|
Mqtt::publish("analogsensor_data", doc.as<JsonObject>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// called from emsesp.cpp, similar to the emsdevice->get_value_info
|
// called from emsesp.cpp, similar to the emsdevice->get_value_info
|
||||||
|
|||||||
@@ -25,8 +25,10 @@
|
|||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
#include "driver/adc.h"
|
#include "driver/adc.h"
|
||||||
|
#ifndef ARDUINO_LOLIN_S2_MINI
|
||||||
#include <esp_bt.h>
|
#include <esp_bt.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <uuid/log.h>
|
#include <uuid/log.h>
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec
|
|||||||
// validate the device, make sure it exists
|
// validate the device, make sure it exists
|
||||||
uint8_t device_type = EMSdevice::device_name_2_device_type(device_s);
|
uint8_t device_type = EMSdevice::device_name_2_device_type(device_s);
|
||||||
if (!device_has_commands(device_type)) {
|
if (!device_has_commands(device_type)) {
|
||||||
LOG_DEBUG(F("Command failed: unknown device '%s'"), device_s);
|
LOG_DEBUG("Command failed: unknown device '%s'", device_s);
|
||||||
return message(CommandRet::ERROR, "unknown device", output);
|
return message(CommandRet::ERROR, "unknown device", output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,15 +170,15 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec
|
|||||||
std::string Command::return_code_string(const uint8_t return_code) {
|
std::string Command::return_code_string(const uint8_t return_code) {
|
||||||
switch (return_code) {
|
switch (return_code) {
|
||||||
case CommandRet::ERROR:
|
case CommandRet::ERROR:
|
||||||
return read_flash_string(F("Error"));
|
return ("Error");
|
||||||
case CommandRet::OK:
|
case CommandRet::OK:
|
||||||
return read_flash_string(F("OK"));
|
return ("OK");
|
||||||
case CommandRet::NOT_FOUND:
|
case CommandRet::NOT_FOUND:
|
||||||
return read_flash_string(F("Not Found"));
|
return ("Not Found");
|
||||||
case CommandRet::NOT_ALLOWED:
|
case CommandRet::NOT_ALLOWED:
|
||||||
return read_flash_string(F("Not Authorized"));
|
return ("Not Authorized");
|
||||||
case CommandRet::FAIL:
|
case CommandRet::FAIL:
|
||||||
return read_flash_string(F("Failed"));
|
return ("Failed");
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -238,7 +238,7 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
|||||||
uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * value, const bool is_admin, const int8_t id, JsonObject & output) {
|
uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * value, const bool is_admin, const int8_t id, JsonObject & output) {
|
||||||
uint8_t return_code = CommandRet::OK;
|
uint8_t return_code = CommandRet::OK;
|
||||||
|
|
||||||
std::string dname = EMSdevice::device_type_2_device_name(device_type);
|
auto dname = EMSdevice::device_type_2_device_name(device_type);
|
||||||
|
|
||||||
// see if there is a command registered
|
// see if there is a command registered
|
||||||
auto cf = find_command(device_type, cmd);
|
auto cf = find_command(device_type, cmd);
|
||||||
@@ -248,7 +248,7 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
|||||||
if ((device_type > EMSdevice::DeviceType::SYSTEM) && (!value || !strlen(value))) {
|
if ((device_type > EMSdevice::DeviceType::SYSTEM) && (!value || !strlen(value))) {
|
||||||
if (!cf || !cf->cmdfunction_json_) {
|
if (!cf || !cf->cmdfunction_json_) {
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
LOG_DEBUG(F("[DEBUG] Calling %s command '%s' to retrieve attributes"), dname.c_str(), cmd);
|
LOG_DEBUG("[DEBUG] Calling %s command '%s' to retrieve attributes", dname, cmd);
|
||||||
#endif
|
#endif
|
||||||
return EMSESP::get_device_value_info(output, cmd, id, device_type) ? CommandRet::OK : CommandRet::ERROR; // entity = cmd
|
return EMSESP::get_device_value_info(output, cmd, id, device_type) ? CommandRet::OK : CommandRet::ERROR; // entity = cmd
|
||||||
}
|
}
|
||||||
@@ -262,17 +262,19 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
|||||||
return CommandRet::NOT_ALLOWED; // command not allowed
|
return CommandRet::NOT_ALLOWED; // command not allowed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto description = Helpers::translated_word(cf->description_);
|
||||||
|
|
||||||
if ((value == nullptr) || (strlen(value) == 0)) {
|
if ((value == nullptr) || (strlen(value) == 0)) {
|
||||||
if (EMSESP::system_.readonly_mode()) {
|
if (EMSESP::system_.readonly_mode()) {
|
||||||
LOG_INFO(F("[readonly] Calling command '%s/%s' (%s)"), dname.c_str(), cmd, read_flash_string(cf->description_).c_str());
|
LOG_INFO(("[readonly] Calling command '%s/%s' (%s)"), dname, cmd, description);
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG(F("Calling command '%s/%s' (%s)"), dname.c_str(), cmd, read_flash_string(cf->description_).c_str());
|
LOG_DEBUG(("Calling command '%s/%s' (%s)"), dname, cmd, description);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (EMSESP::system_.readonly_mode()) {
|
if (EMSESP::system_.readonly_mode()) {
|
||||||
LOG_INFO(F("[readonly] Calling command '%s/%s' (%s) with value %s"), dname.c_str(), cmd, read_flash_string(cf->description_).c_str(), value);
|
LOG_INFO(("[readonly] Calling command '%s/%s' (%s) with value %s"), dname, cmd, description, value);
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG(F("Calling command '%s/%s' (%s) with value %s"), dname.c_str(), cmd, read_flash_string(cf->description_).c_str(), value);
|
LOG_DEBUG(("Calling command '%s/%s' (%s) with value %s"), dname, cmd, description, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,14 +296,14 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we didn't find the command and its not an endpoint, report error
|
// we didn't find the command and its not an endpoint, report error
|
||||||
LOG_DEBUG(F("Command failed: invalid command '%s'"), cmd);
|
LOG_DEBUG("Command failed: invalid command '%s'", cmd);
|
||||||
return message(CommandRet::NOT_FOUND, "invalid command", output);
|
return message(CommandRet::NOT_FOUND, "invalid command", output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a command to the list, which does not return json
|
// add a command to the list, which does not return json
|
||||||
void Command::add(const uint8_t device_type, const __FlashStringHelper * cmd, const cmd_function_p cb, const __FlashStringHelper * description, uint8_t flags) {
|
void Command::add(const uint8_t device_type, const char * cmd, const cmd_function_p cb, const char * const * description, uint8_t flags) {
|
||||||
// if the command already exists for that device type don't add it
|
// if the command already exists for that device type don't add it
|
||||||
if (find_command(device_type, read_flash_string(cmd).c_str()) != nullptr) {
|
if (find_command(device_type, cmd) != nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,9 +316,9 @@ void Command::add(const uint8_t device_type, const __FlashStringHelper * cmd, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add a command to the list, which does return a json object as output
|
// add a command to the list, which does return a json object as output
|
||||||
void Command::add(const uint8_t device_type, const __FlashStringHelper * cmd, const cmd_json_function_p cb, const __FlashStringHelper * description, uint8_t flags) {
|
void Command::add(const uint8_t device_type, const char * cmd, const cmd_json_function_p cb, const char * const * description, uint8_t flags) {
|
||||||
// if the command already exists for that device type don't add it
|
// if the command already exists for that device type don't add it
|
||||||
if (find_command(device_type, read_flash_string(cmd).c_str()) != nullptr) {
|
if (find_command(device_type, cmd) != nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +340,7 @@ Command::CmdFunction * Command::find_command(const uint8_t device_type, const ch
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto & cf : cmdfunctions_) {
|
for (auto & cf : cmdfunctions_) {
|
||||||
if (!strcmp(lowerCmd, Helpers::toLower(read_flash_string(cf.cmd_)).c_str()) && (cf.device_type_ == device_type)) {
|
if (!strcmp(lowerCmd, cf.cmd_) && (cf.device_type_ == device_type)) {
|
||||||
return &cf;
|
return &cf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,15 +359,15 @@ bool Command::list(const uint8_t device_type, JsonObject & output) {
|
|||||||
std::list<std::string> sorted_cmds;
|
std::list<std::string> sorted_cmds;
|
||||||
for (const auto & cf : cmdfunctions_) {
|
for (const auto & cf : cmdfunctions_) {
|
||||||
if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN)) {
|
if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN)) {
|
||||||
sorted_cmds.push_back(read_flash_string(cf.cmd_));
|
sorted_cmds.push_back((cf.cmd_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sorted_cmds.sort();
|
sorted_cmds.sort();
|
||||||
|
|
||||||
for (const auto & cl : sorted_cmds) {
|
for (const auto & cl : sorted_cmds) {
|
||||||
for (const auto & cf : cmdfunctions_) {
|
for (const auto & cf : cmdfunctions_) {
|
||||||
if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN) && cf.description_ && (cl == read_flash_string(cf.cmd_))) {
|
if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN) && cf.description_ && (cl == std::string(cf.cmd_))) {
|
||||||
output[cl] = cf.description_;
|
output[cl] = Helpers::translated_word(cf.description_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -376,7 +378,7 @@ bool Command::list(const uint8_t device_type, JsonObject & output) {
|
|||||||
// output list of all commands to console for a specific DeviceType
|
// output list of all commands to console for a specific DeviceType
|
||||||
void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbose) {
|
void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbose) {
|
||||||
if (cmdfunctions_.empty()) {
|
if (cmdfunctions_.empty()) {
|
||||||
shell.println(F("No commands available"));
|
shell.println("No commands available");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,7 +386,7 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo
|
|||||||
std::list<std::string> sorted_cmds;
|
std::list<std::string> sorted_cmds;
|
||||||
for (const auto & cf : cmdfunctions_) {
|
for (const auto & cf : cmdfunctions_) {
|
||||||
if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN)) {
|
if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN)) {
|
||||||
sorted_cmds.push_back(read_flash_string(cf.cmd_));
|
sorted_cmds.push_back((cf.cmd_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sorted_cmds.sort();
|
sorted_cmds.sort();
|
||||||
@@ -404,7 +406,7 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo
|
|||||||
for (const auto & cl : sorted_cmds) {
|
for (const auto & cl : sorted_cmds) {
|
||||||
// find and print the description
|
// find and print the description
|
||||||
for (const auto & cf : cmdfunctions_) {
|
for (const auto & cf : cmdfunctions_) {
|
||||||
if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN) && cf.description_ && (cl == read_flash_string(cf.cmd_))) {
|
if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN) && cf.description_ && (cl == std::string(cf.cmd_))) {
|
||||||
uint8_t i = cl.length();
|
uint8_t i = cl.length();
|
||||||
shell.print(" ");
|
shell.print(" ");
|
||||||
if (cf.has_flags(MQTT_SUB_FLAG_HC)) {
|
if (cf.has_flags(MQTT_SUB_FLAG_HC)) {
|
||||||
@@ -424,7 +426,7 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo
|
|||||||
shell.print(EMSdevice::tag_to_string(DeviceValueTAG::TAG_DEVICE_DATA_WW));
|
shell.print(EMSdevice::tag_to_string(DeviceValueTAG::TAG_DEVICE_DATA_WW));
|
||||||
shell.print(' ');
|
shell.print(' ');
|
||||||
}
|
}
|
||||||
shell.print(read_flash_string(cf.description_).c_str());
|
shell.print(Helpers::translated_word(cf.description_));
|
||||||
if (!cf.has_flags(CommandFlag::ADMIN_ONLY)) {
|
if (!cf.has_flags(CommandFlag::ADMIN_ONLY)) {
|
||||||
shell.print(' ');
|
shell.print(' ');
|
||||||
shell.print(COLOR_BRIGHT_RED);
|
shell.print(COLOR_BRIGHT_RED);
|
||||||
@@ -474,19 +476,19 @@ bool Command::device_has_commands(const uint8_t device_type) {
|
|||||||
|
|
||||||
// list sensors and EMS devices
|
// list sensors and EMS devices
|
||||||
void Command::show_devices(uuid::console::Shell & shell) {
|
void Command::show_devices(uuid::console::Shell & shell) {
|
||||||
shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM).c_str());
|
shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM));
|
||||||
|
|
||||||
if (EMSESP::dallassensor_.have_sensors()) {
|
if (EMSESP::dallassensor_.have_sensors()) {
|
||||||
shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::DALLASSENSOR).c_str());
|
shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::DALLASSENSOR));
|
||||||
}
|
}
|
||||||
if (EMSESP::analogsensor_.have_sensors()) {
|
if (EMSESP::analogsensor_.have_sensors()) {
|
||||||
shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::ANALOGSENSOR).c_str());
|
shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::ANALOGSENSOR));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto & device_class : EMSFactory::device_handlers()) {
|
for (const auto & device_class : EMSFactory::device_handlers()) {
|
||||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||||
if (emsdevice && (emsdevice->device_type() == device_class.first) && (device_has_commands(device_class.first))) {
|
if (emsdevice && (emsdevice->device_type() == device_class.first) && (device_has_commands(device_class.first))) {
|
||||||
shell.printf("%s ", EMSdevice::device_type_2_device_name(device_class.first).c_str());
|
shell.printf("%s ", EMSdevice::device_type_2_device_name(device_class.first));
|
||||||
break; // we only want to show one (not multiple of the same device types)
|
break; // we only want to show one (not multiple of the same device types)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -497,12 +499,12 @@ void Command::show_devices(uuid::console::Shell & shell) {
|
|||||||
// output list of all commands to console
|
// output list of all commands to console
|
||||||
// calls show with verbose mode set
|
// calls show with verbose mode set
|
||||||
void Command::show_all(uuid::console::Shell & shell) {
|
void Command::show_all(uuid::console::Shell & shell) {
|
||||||
shell.println(F("Available commands (*=do not need authorization): "));
|
shell.println(("Available commands (*=do not need authorization): "));
|
||||||
|
|
||||||
// show system first
|
// show system first
|
||||||
shell.print(COLOR_BOLD_ON);
|
shell.print(COLOR_BOLD_ON);
|
||||||
shell.print(COLOR_YELLOW);
|
shell.print(COLOR_YELLOW);
|
||||||
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM).c_str());
|
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM));
|
||||||
shell.print(COLOR_RESET);
|
shell.print(COLOR_RESET);
|
||||||
show(shell, EMSdevice::DeviceType::SYSTEM, true);
|
show(shell, EMSdevice::DeviceType::SYSTEM, true);
|
||||||
|
|
||||||
@@ -510,14 +512,14 @@ void Command::show_all(uuid::console::Shell & shell) {
|
|||||||
if (EMSESP::dallassensor_.have_sensors()) {
|
if (EMSESP::dallassensor_.have_sensors()) {
|
||||||
shell.print(COLOR_BOLD_ON);
|
shell.print(COLOR_BOLD_ON);
|
||||||
shell.print(COLOR_YELLOW);
|
shell.print(COLOR_YELLOW);
|
||||||
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::DALLASSENSOR).c_str());
|
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::DALLASSENSOR));
|
||||||
shell.print(COLOR_RESET);
|
shell.print(COLOR_RESET);
|
||||||
show(shell, EMSdevice::DeviceType::DALLASSENSOR, true);
|
show(shell, EMSdevice::DeviceType::DALLASSENSOR, true);
|
||||||
}
|
}
|
||||||
if (EMSESP::analogsensor_.have_sensors()) {
|
if (EMSESP::analogsensor_.have_sensors()) {
|
||||||
shell.print(COLOR_BOLD_ON);
|
shell.print(COLOR_BOLD_ON);
|
||||||
shell.print(COLOR_YELLOW);
|
shell.print(COLOR_YELLOW);
|
||||||
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::ANALOGSENSOR).c_str());
|
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::ANALOGSENSOR));
|
||||||
shell.print(COLOR_RESET);
|
shell.print(COLOR_RESET);
|
||||||
show(shell, EMSdevice::DeviceType::ANALOGSENSOR, true);
|
show(shell, EMSdevice::DeviceType::ANALOGSENSOR, true);
|
||||||
}
|
}
|
||||||
@@ -527,7 +529,7 @@ void Command::show_all(uuid::console::Shell & shell) {
|
|||||||
if (Command::device_has_commands(device_class.first)) {
|
if (Command::device_has_commands(device_class.first)) {
|
||||||
shell.print(COLOR_BOLD_ON);
|
shell.print(COLOR_BOLD_ON);
|
||||||
shell.print(COLOR_YELLOW);
|
shell.print(COLOR_YELLOW);
|
||||||
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(device_class.first).c_str());
|
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(device_class.first));
|
||||||
shell.print(COLOR_RESET);
|
shell.print(COLOR_RESET);
|
||||||
show(shell, device_class.first, true);
|
show(shell, device_class.first, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,19 +54,19 @@ using cmd_json_function_p = std::function<bool(const char * data, const int8_t i
|
|||||||
class Command {
|
class Command {
|
||||||
public:
|
public:
|
||||||
struct CmdFunction {
|
struct CmdFunction {
|
||||||
uint8_t device_type_; // DeviceType::
|
uint8_t device_type_; // DeviceType::
|
||||||
uint8_t flags_; // mqtt flags for command subscriptions
|
uint8_t flags_; // mqtt flags for command subscriptions
|
||||||
const __FlashStringHelper * cmd_;
|
const char * cmd_;
|
||||||
const cmd_function_p cmdfunction_;
|
const cmd_function_p cmdfunction_;
|
||||||
const cmd_json_function_p cmdfunction_json_;
|
const cmd_json_function_p cmdfunction_json_;
|
||||||
const __FlashStringHelper * description_;
|
const char * const * description_;
|
||||||
|
|
||||||
CmdFunction(const uint8_t device_type,
|
CmdFunction(const uint8_t device_type,
|
||||||
const uint8_t flags,
|
const uint8_t flags,
|
||||||
const __FlashStringHelper * cmd,
|
const char * cmd,
|
||||||
const cmd_function_p cmdfunction,
|
const cmd_function_p cmdfunction,
|
||||||
const cmd_json_function_p cmdfunction_json,
|
const cmd_json_function_p cmdfunction_json,
|
||||||
const __FlashStringHelper * description)
|
const char * const * description)
|
||||||
: device_type_(device_type)
|
: device_type_(device_type)
|
||||||
, flags_(flags)
|
, flags_(flags)
|
||||||
, cmd_(cmd)
|
, cmd_(cmd)
|
||||||
@@ -93,24 +93,22 @@ class Command {
|
|||||||
return cmdfunctions_;
|
return cmdfunctions_;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define add_
|
|
||||||
|
|
||||||
static uint8_t call(const uint8_t device_type, const char * cmd, const char * value, const bool is_admin, const int8_t id, JsonObject & output);
|
static uint8_t call(const uint8_t device_type, const char * cmd, const char * value, const bool is_admin, const int8_t id, JsonObject & output);
|
||||||
static uint8_t call(const uint8_t device_type, const char * cmd, const char * value);
|
static uint8_t call(const uint8_t device_type, const char * cmd, const char * value);
|
||||||
|
|
||||||
// with normal call back function taking a value and id
|
// with normal call back function taking a value and id
|
||||||
static void add(const uint8_t device_type,
|
static void add(const uint8_t device_type,
|
||||||
const __FlashStringHelper * cmd,
|
const char * cmd,
|
||||||
const cmd_function_p cb,
|
const cmd_function_p cb,
|
||||||
const __FlashStringHelper * description,
|
const char * const * description,
|
||||||
uint8_t flags = CommandFlag::MQTT_SUB_FLAG_DEFAULT);
|
uint8_t flags = CommandFlag::MQTT_SUB_FLAG_DEFAULT);
|
||||||
|
|
||||||
// callback function taking value, id and a json object for its output
|
// callback function taking value, id and a json object for its output
|
||||||
static void add(const uint8_t device_type,
|
static void add(const uint8_t device_type,
|
||||||
const __FlashStringHelper * cmd,
|
const char * cmd,
|
||||||
const cmd_json_function_p cb,
|
const cmd_json_function_p cb,
|
||||||
const __FlashStringHelper * description,
|
const char * const * description,
|
||||||
uint8_t flags = CommandFlag::MQTT_SUB_FLAG_DEFAULT);
|
uint8_t flags = CommandFlag::MQTT_SUB_FLAG_DEFAULT);
|
||||||
|
|
||||||
static void show_all(uuid::console::Shell & shell);
|
static void show_all(uuid::console::Shell & shell);
|
||||||
static Command::CmdFunction * find_command(const uint8_t device_type, const char * cmd);
|
static Command::CmdFunction * find_command(const uint8_t device_type, const char * cmd);
|
||||||
|
|||||||
20
src/common.h
20
src/common.h
@@ -31,29 +31,23 @@ using uuid::log::Level;
|
|||||||
#define LOG_ERROR(...) logger_.err(__VA_ARGS__)
|
#define LOG_ERROR(...) logger_.err(__VA_ARGS__)
|
||||||
|
|
||||||
// flash strings
|
// flash strings
|
||||||
using uuid::flash_string_vector;
|
using uuid::string_vector;
|
||||||
using uuid::read_flash_string;
|
using string_vector = std::vector<const char *>;
|
||||||
|
|
||||||
#ifdef FPSTR
|
#ifdef FPSTR
|
||||||
#undef FPSTR
|
#undef FPSTR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FJSON(x) x
|
|
||||||
// #define FJSON(x) F(x)
|
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
#define MAKE_STR(string_name, string_literal) static constexpr const char * __str__##string_name = string_literal;
|
#define FPSTR(pstr_pointer) pstr_pointer
|
||||||
|
#define MAKE_PSTR(string_name, string_literal) static const char __pstr__##string_name[] = string_literal;
|
||||||
#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
|
|
||||||
#define F_(string_name) FPSTR(__pstr__##string_name)
|
|
||||||
|
|
||||||
#define MAKE_PSTR(string_name, string_literal) static const char __pstr__##string_name[] __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = string_literal;
|
|
||||||
#define MAKE_PSTR_WORD(string_name) MAKE_PSTR(string_name, #string_name)
|
#define MAKE_PSTR_WORD(string_name) MAKE_PSTR(string_name, #string_name)
|
||||||
|
|
||||||
|
#define F_(string_name) (__pstr__##string_name)
|
||||||
#define FL_(list_name) (__pstr__L_##list_name)
|
#define FL_(list_name) (__pstr__L_##list_name)
|
||||||
#define MAKE_PSTR_LIST(list_name, ...) static const __FlashStringHelper * const __pstr__L_##list_name[] PROGMEM = {__VA_ARGS__, nullptr};
|
#define MAKE_PSTR_LIST(list_name, ...) static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr};
|
||||||
#define MAKE_PSTR_ENUM(enum_name, ...) static const __FlashStringHelper * const * __pstr__L_##enum_name[] PROGMEM = {__VA_ARGS__, nullptr};
|
#define MAKE_PSTR_ENUM(enum_name, ...) static const char * const * __pstr__L_##enum_name[] = {__VA_ARGS__, nullptr};
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
|||||||
195
src/console.cpp
195
src/console.cpp
@@ -45,26 +45,26 @@ EMSESPShell::EMSESPShell()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EMSESPShell::started() {
|
void EMSESPShell::started() {
|
||||||
logger().log(LogLevel::DEBUG, LogFacility::CONSOLE, F("User session opened on console %s"), console_name().c_str());
|
logger().log(LogLevel::DEBUG, LogFacility::CONSOLE, ("User session opened on console %s"), console_name().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EMSESPShell::stopped() {
|
void EMSESPShell::stopped() {
|
||||||
if (has_flags(CommandFlags::ADMIN)) {
|
if (has_flags(CommandFlags::ADMIN)) {
|
||||||
logger().log(LogLevel::DEBUG, LogFacility::AUTH, F("su session closed on console %s"), console_name().c_str());
|
logger().log(LogLevel::DEBUG, LogFacility::AUTH, ("su session closed on console %s"), console_name().c_str());
|
||||||
}
|
}
|
||||||
logger().log(LogLevel::DEBUG, LogFacility::CONSOLE, F("User session closed on console %s"), console_name().c_str());
|
logger().log(LogLevel::DEBUG, LogFacility::CONSOLE, ("User session closed on console %s"), console_name().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// show welcome banner
|
// show welcome banner
|
||||||
// this is one of the first functions called when the shell is started
|
// this is one of the first functions called when the shell is started
|
||||||
void EMSESPShell::display_banner() {
|
void EMSESPShell::display_banner() {
|
||||||
println();
|
println();
|
||||||
printfln(F("┌──────────────────────────────────────┐"));
|
printfln("┌──────────────────────────────────────┐");
|
||||||
printfln(F("│ %sEMS-ESP version %-10s%s │"), COLOR_BOLD_ON, EMSESP_APP_VERSION, COLOR_BOLD_OFF);
|
printfln("│ %sEMS-ESP version %-10s%s │", COLOR_BOLD_ON, EMSESP_APP_VERSION, COLOR_BOLD_OFF);
|
||||||
printfln(F("│ %s%shttps://github.com/emsesp/EMS-ESP32%s │"), COLOR_BRIGHT_GREEN, COLOR_UNDERLINE, COLOR_RESET);
|
printfln("│ %s%shttps://github.com/emsesp/EMS-ESP32%s │", COLOR_BRIGHT_GREEN, COLOR_UNDERLINE, COLOR_RESET);
|
||||||
printfln(F("│ │"));
|
printfln("│ │");
|
||||||
printfln(F("│ type %shelp%s to show available commands │"), COLOR_UNDERLINE, COLOR_RESET);
|
printfln("│ type %shelp%s to show available commands │", COLOR_UNDERLINE, COLOR_RESET);
|
||||||
printfln(F("└──────────────────────────────────────┘"));
|
printfln("└──────────────────────────────────────┘");
|
||||||
println();
|
println();
|
||||||
|
|
||||||
// set console name
|
// set console name
|
||||||
@@ -100,9 +100,9 @@ void EMSESPShell::add_console_commands() {
|
|||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(show)},
|
string_vector{F_(show)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
shell.printfln(F("%s%sEMS-ESP version %s%s"), COLOR_BRIGHT_GREEN, COLOR_BOLD_ON, EMSESP_APP_VERSION, COLOR_RESET);
|
shell.printfln("%s%sEMS-ESP version %s%s", COLOR_BRIGHT_GREEN, COLOR_BOLD_ON, EMSESP_APP_VERSION, COLOR_RESET);
|
||||||
shell.println();
|
shell.println();
|
||||||
EMSESP::show_device_values(shell);
|
EMSESP::show_device_values(shell);
|
||||||
EMSESP::show_sensor_values(shell);
|
EMSESP::show_sensor_values(shell);
|
||||||
@@ -110,36 +110,36 @@ void EMSESPShell::add_console_commands() {
|
|||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(show), F_(devices)},
|
string_vector{F_(show), F_(devices)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { EMSESP::show_devices(shell); });
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { EMSESP::show_devices(shell); });
|
||||||
|
|
||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(show), F_(ems)},
|
string_vector{F_(show), F_(ems)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { EMSESP::show_ems(shell); });
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { EMSESP::show_ems(shell); });
|
||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(show), F_(values)},
|
string_vector{F_(show), F_(values)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { EMSESP::show_device_values(shell); });
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { EMSESP::show_device_values(shell); });
|
||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(show), F_(mqtt)},
|
string_vector{F_(show), F_(mqtt)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { Mqtt::show_mqtt(shell); });
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { Mqtt::show_mqtt(shell); });
|
||||||
|
|
||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(show), F_(commands)},
|
string_vector{F_(show), F_(commands)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { Command::show_all(shell); });
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { Command::show_all(shell); });
|
||||||
|
|
||||||
commands->add_command(
|
commands->add_command(
|
||||||
ShellContext::MAIN,
|
ShellContext::MAIN,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(set), F_(bus_id)},
|
string_vector{F_(set), F_(bus_id)},
|
||||||
flash_string_vector{F_(deviceid_mandatory)},
|
string_vector{F_(deviceid_mandatory)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
uint8_t device_id = Helpers::hextoint(arguments.front().c_str());
|
uint8_t device_id = Helpers::hextoint(arguments.front().c_str());
|
||||||
if ((device_id == 0x0B) || (device_id == 0x0D) || (device_id == 0x0A) || (device_id == 0x0F) || (device_id == 0x12)) {
|
if ((device_id == 0x0B) || (device_id == 0x0D) || (device_id == 0x0A) || (device_id == 0x0F) || (device_id == 0x12)) {
|
||||||
@@ -151,24 +151,24 @@ void EMSESPShell::add_console_commands() {
|
|||||||
},
|
},
|
||||||
"local");
|
"local");
|
||||||
} else {
|
} else {
|
||||||
shell.println(F("Must be 0B, 0D, 0A, 0F or 12"));
|
shell.println("Must be 0B, 0D, 0A, 0F or 12");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> const std::vector<std::string> {
|
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> const std::vector<std::string> {
|
||||||
return std::vector<std::string>{
|
return std::vector<std::string>{
|
||||||
read_flash_string(F("0B")),
|
("0B"),
|
||||||
read_flash_string(F("0D")),
|
("0D"),
|
||||||
read_flash_string(F("0A")),
|
("0A"),
|
||||||
read_flash_string(F("0F")),
|
("0F"),
|
||||||
read_flash_string(F("12")),
|
("12"),
|
||||||
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(set), F_(tx_mode)},
|
string_vector{F_(set), F_(tx_mode)},
|
||||||
flash_string_vector{F_(n_mandatory)},
|
string_vector{F_(n_mandatory)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
uint8_t tx_mode = std::strtol(arguments[0].c_str(), nullptr, 10);
|
uint8_t tx_mode = std::strtol(arguments[0].c_str(), nullptr, 10);
|
||||||
// save the tx_mode
|
// save the tx_mode
|
||||||
@@ -183,13 +183,13 @@ void EMSESPShell::add_console_commands() {
|
|||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(scan), F_(devices)},
|
string_vector{F_(scan), F_(devices)},
|
||||||
flash_string_vector{F_(deep_optional)},
|
string_vector{F_(deep_optional)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
if (arguments.size() == 0) {
|
if (arguments.size() == 0) {
|
||||||
EMSESP::scan_devices();
|
EMSESP::scan_devices();
|
||||||
} else {
|
} else {
|
||||||
shell.printfln(F("Performing a deep scan..."));
|
shell.printfln("Performing a deep scan...");
|
||||||
EMSESP::clear_all_devices();
|
EMSESP::clear_all_devices();
|
||||||
std::vector<uint8_t> Device_Ids;
|
std::vector<uint8_t> Device_Ids;
|
||||||
|
|
||||||
@@ -222,10 +222,10 @@ void EMSESPShell::add_console_commands() {
|
|||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(set)},
|
string_vector{F_(set)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
||||||
shell.printfln(F("Language: %s"), settings.locale.c_str());
|
shell.printfln("Language: %s", settings.locale.c_str());
|
||||||
shell.printfln(F_(tx_mode_fmt), settings.tx_mode);
|
shell.printfln(F_(tx_mode_fmt), settings.tx_mode);
|
||||||
shell.printfln(F_(bus_id_fmt), settings.ems_bus_id);
|
shell.printfln(F_(bus_id_fmt), settings.ems_bus_id);
|
||||||
shell.printfln(F_(board_profile_fmt), settings.board_profile.c_str());
|
shell.printfln(F_(board_profile_fmt), settings.board_profile.c_str());
|
||||||
@@ -234,13 +234,13 @@ void EMSESPShell::add_console_commands() {
|
|||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(read)},
|
string_vector{F_(read)},
|
||||||
flash_string_vector{F_(deviceid_mandatory), F_(typeid_mandatory), F_(offset_optional), F_(length_optional)},
|
string_vector{F_(deviceid_mandatory), F_(typeid_mandatory), F_(offset_optional), F_(length_optional)},
|
||||||
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||||
uint8_t device_id = Helpers::hextoint(arguments.front().c_str());
|
uint8_t device_id = Helpers::hextoint(arguments.front().c_str());
|
||||||
|
|
||||||
if (!EMSESP::valid_device(device_id)) {
|
if (!EMSESP::valid_device(device_id)) {
|
||||||
shell.printfln(F("Invalid deviceID"));
|
shell.printfln("Invalid deviceID");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,31 +261,32 @@ void EMSESPShell::add_console_commands() {
|
|||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(set), F_(timeout)},
|
string_vector{F_(set), F_(timeout)},
|
||||||
flash_string_vector{F_(n_mandatory)},
|
string_vector{F_(n_mandatory)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
uint16_t value = Helpers::atoint(arguments.front().c_str());
|
uint16_t value = Helpers::atoint(arguments.front().c_str());
|
||||||
telnet_.initial_idle_timeout(value * 60);
|
telnet_.initial_idle_timeout(value * 60);
|
||||||
shell.printfln(F("Telnet timeout set to %d minutes"), value);
|
shell.printfln("Telnet timeout set to %d minutes", value);
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(watch)},
|
string_vector{F_(watch)},
|
||||||
flash_string_vector{F_(watch_format_optional), F_(watchid_optional)},
|
string_vector{F_(watch_format_optional), F_(watchid_optional)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
uint16_t watch_id = WATCH_ID_NONE;
|
uint16_t watch_id = WATCH_ID_NONE;
|
||||||
|
|
||||||
|
// only use english commands, not the translations
|
||||||
if (!arguments.empty()) {
|
if (!arguments.empty()) {
|
||||||
// get raw/pretty
|
// get raw/pretty
|
||||||
if (arguments[0] == read_flash_string(F_(raw))) {
|
if (arguments[0] == (F_(raw))) {
|
||||||
EMSESP::watch(EMSESP::WATCH_RAW); // raw
|
EMSESP::watch(EMSESP::WATCH_RAW); // raw
|
||||||
} else if (arguments[0] == Helpers::translated_word(FL_(on), true) || arguments[0] == read_flash_string(FL_(on)[0])) {
|
} else if (arguments[0] == (FL_(on)[0])) {
|
||||||
EMSESP::watch(EMSESP::WATCH_ON); // on
|
EMSESP::watch(EMSESP::WATCH_ON); // on
|
||||||
} else if (arguments[0] == Helpers::translated_word(FL_(off), true) || arguments[0] == read_flash_string(FL_(off)[0])) {
|
} else if (arguments[0] == (FL_(off)[0])) {
|
||||||
EMSESP::watch(EMSESP::WATCH_OFF); // off
|
EMSESP::watch(EMSESP::WATCH_OFF); // off
|
||||||
} else if (arguments[0] == Helpers::translated_word(FL_(unknown), true) || arguments[0] == read_flash_string(FL_(unknown)[0])) {
|
} else if (arguments[0] == (FL_(unknown)[0])) {
|
||||||
EMSESP::watch(EMSESP::WATCH_UNKNOWN); // unknown
|
EMSESP::watch(EMSESP::WATCH_UNKNOWN); // unknown
|
||||||
watch_id = WATCH_ID_NONE;
|
watch_id = WATCH_ID_NONE;
|
||||||
} else {
|
} else {
|
||||||
@@ -305,43 +306,43 @@ void EMSESPShell::add_console_commands() {
|
|||||||
|
|
||||||
EMSESP::watch_id(watch_id);
|
EMSESP::watch_id(watch_id);
|
||||||
} else {
|
} else {
|
||||||
shell.printfln(F("Invalid: use watch raw|on|off|unknown|id [id]"));
|
shell.printfln("Invalid: use watch raw|on|off|unknown|id [id]");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t watch = EMSESP::watch();
|
uint8_t watch = EMSESP::watch();
|
||||||
if (watch == EMSESP::WATCH_OFF) {
|
if (watch == EMSESP::WATCH_OFF) {
|
||||||
shell.printfln(F("Watching telegrams is off"));
|
shell.printfln("Watching telegrams is off");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if logging is off, the watch won't show anything, show force it back to NOTICE
|
// if logging is off, the watch won't show anything, show force it back to NOTICE
|
||||||
if (shell.log_level() < Level::NOTICE) {
|
if (shell.log_level() < Level::NOTICE) {
|
||||||
shell.log_level(Level::NOTICE);
|
shell.log_level(Level::NOTICE);
|
||||||
shell.printfln(F("Setting log level to Notice"));
|
shell.printfln("Setting log level to Notice");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (watch == EMSESP::WATCH_ON) {
|
if (watch == EMSESP::WATCH_ON) {
|
||||||
shell.printfln(F("Watching incoming telegrams, displayed in decoded format"));
|
shell.printfln("Watching incoming telegrams, displayed in decoded format");
|
||||||
} else if (watch == EMSESP::WATCH_RAW) {
|
} else if (watch == EMSESP::WATCH_RAW) {
|
||||||
shell.printfln(F("Watching incoming telegrams, displayed as raw bytes")); // WATCH_RAW
|
shell.printfln("Watching incoming telegrams, displayed as raw bytes"); // WATCH_RAW
|
||||||
} else {
|
} else {
|
||||||
shell.printfln(F("Watching unknown telegrams")); // WATCH_UNKNOWN
|
shell.printfln("Watching unknown telegrams"); // WATCH_UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
watch_id = EMSESP::watch_id();
|
watch_id = EMSESP::watch_id();
|
||||||
if (watch_id > 0x80) {
|
if (watch_id > 0x80) {
|
||||||
shell.printfln(F("Filtering only telegrams that match a telegram type of 0x%02X"), watch_id);
|
shell.printfln("Filtering only telegrams that match a telegram type of 0x%02X", watch_id);
|
||||||
} else if (watch_id != WATCH_ID_NONE) {
|
} else if (watch_id != WATCH_ID_NONE) {
|
||||||
shell.printfln(F("Filtering only telegrams that match a deviceID or telegram type of 0x%02X"), watch_id);
|
shell.printfln("Filtering only telegrams that match a deviceID or telegram type of 0x%02X", watch_id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
commands->add_command(
|
commands->add_command(
|
||||||
ShellContext::MAIN,
|
ShellContext::MAIN,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(call)},
|
string_vector{F_(call)},
|
||||||
flash_string_vector{F_(device_type_optional), F_(cmd_optional), F_(data_optional), F_(id_optional)},
|
string_vector{F_(device_type_optional), F_(cmd_optional), F_(data_optional), F_(id_optional)},
|
||||||
[&](Shell & shell, const std::vector<std::string> & arguments) {
|
[&](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
if (arguments.empty()) {
|
if (arguments.empty()) {
|
||||||
Command::show_all(shell); // list options
|
Command::show_all(shell); // list options
|
||||||
@@ -351,7 +352,7 @@ void EMSESPShell::add_console_commands() {
|
|||||||
// validate the device_type
|
// validate the device_type
|
||||||
uint8_t device_type = EMSdevice::device_name_2_device_type(arguments[0].c_str());
|
uint8_t device_type = EMSdevice::device_name_2_device_type(arguments[0].c_str());
|
||||||
if (!Command::device_has_commands(device_type)) {
|
if (!Command::device_has_commands(device_type)) {
|
||||||
shell.print(F("Invalid device. Available devices are: "));
|
shell.print("Invalid device. Available devices are: ");
|
||||||
Command::show_devices(shell);
|
Command::show_devices(shell);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -359,7 +360,7 @@ void EMSESPShell::add_console_commands() {
|
|||||||
|
|
||||||
// validate that a command is present
|
// validate that a command is present
|
||||||
if (arguments.size() < 2) {
|
if (arguments.size() < 2) {
|
||||||
shell.print(F("Missing command. Available commands are: "));
|
shell.print("Missing command. Available commands are: ");
|
||||||
Command::show(shell, device_type, false); // non-verbose mode
|
Command::show(shell, device_type, false); // non-verbose mode
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -399,11 +400,11 @@ void EMSESPShell::add_console_commands() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (return_code == CommandRet::NOT_FOUND) {
|
if (return_code == CommandRet::NOT_FOUND) {
|
||||||
shell.println(F("Unknown command"));
|
shell.println("Unknown command");
|
||||||
shell.print(F("Available commands are: "));
|
shell.print("Available commands are: ");
|
||||||
Command::show(shell, device_type, false); // non-verbose mode
|
Command::show(shell, device_type, false); // non-verbose mode
|
||||||
} else if (return_code != CommandRet::OK) {
|
} else if (return_code != CommandRet::OK) {
|
||||||
shell.printfln(F("Bad syntax (error code %d)"), return_code);
|
shell.printfln(("Bad syntax (error code %d)"), return_code);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[&](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) -> std::vector<std::string> {
|
[&](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) -> std::vector<std::string> {
|
||||||
@@ -424,7 +425,7 @@ void EMSESPShell::add_console_commands() {
|
|||||||
if (Command::device_has_commands(device_type)) {
|
if (Command::device_has_commands(device_type)) {
|
||||||
for (const auto & cf : Command::commands()) {
|
for (const auto & cf : Command::commands()) {
|
||||||
if (cf.device_type_ == device_type) {
|
if (cf.device_type_ == device_type) {
|
||||||
command_list.emplace_back(read_flash_string(cf.cmd_));
|
command_list.emplace_back((cf.cmd_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return command_list;
|
return command_list;
|
||||||
@@ -448,8 +449,8 @@ void Console::load_standard_commands(unsigned int context) {
|
|||||||
// create commands test and t
|
// create commands test and t
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F("test")},
|
string_vector{("test")},
|
||||||
flash_string_vector{F_(name_optional), F_(data_optional)},
|
string_vector{F_(name_optional), F_(data_optional)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
if (arguments.empty()) {
|
if (arguments.empty()) {
|
||||||
Test::run_test(shell, "default");
|
Test::run_test(shell, "default");
|
||||||
@@ -460,7 +461,7 @@ void Console::load_standard_commands(unsigned int context) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
EMSESPShell::commands->add_command(context, CommandFlags::USER, flash_string_vector{F("t")}, [](Shell & shell, const std::vector<std::string> & arguments) {
|
EMSESPShell::commands->add_command(context, CommandFlags::USER, string_vector{("t")}, [](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
Test::run_test(shell, "default");
|
Test::run_test(shell, "default");
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
@@ -468,8 +469,8 @@ void Console::load_standard_commands(unsigned int context) {
|
|||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(debug)},
|
string_vector{F_(debug)},
|
||||||
flash_string_vector{F_(name_optional)},
|
string_vector{F_(name_optional)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
if (arguments.empty()) {
|
if (arguments.empty()) {
|
||||||
Test::debug(shell, "default");
|
Test::debug(shell, "default");
|
||||||
@@ -482,8 +483,8 @@ void Console::load_standard_commands(unsigned int context) {
|
|||||||
EMSESPShell::commands->add_command(
|
EMSESPShell::commands->add_command(
|
||||||
context,
|
context,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(log)},
|
string_vector{F_(log)},
|
||||||
flash_string_vector{F_(log_level_optional)},
|
string_vector{F_(log_level_optional)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
if (!arguments.empty()) {
|
if (!arguments.empty()) {
|
||||||
uuid::log::Level level;
|
uuid::log::Level level;
|
||||||
@@ -494,7 +495,7 @@ void Console::load_standard_commands(unsigned int context) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
shell.print(F("levels: "));
|
shell.print("levels: ");
|
||||||
std::vector<std::string> v = uuid::log::levels_lowercase();
|
std::vector<std::string> v = uuid::log::levels_lowercase();
|
||||||
size_t i = v.size();
|
size_t i = v.size();
|
||||||
while (i--) {
|
while (i--) {
|
||||||
@@ -511,22 +512,22 @@ void Console::load_standard_commands(unsigned int context) {
|
|||||||
|
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(help)},
|
string_vector{F_(help)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
shell.print_all_available_commands();
|
shell.print_all_available_commands();
|
||||||
});
|
});
|
||||||
|
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(exit)},
|
string_vector{F_(exit)},
|
||||||
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { shell.stop(); });
|
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { shell.stop(); });
|
||||||
|
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(su)},
|
string_vector{F_(su)},
|
||||||
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
auto become_admin = [](Shell & shell) {
|
auto become_admin = [](Shell & shell) {
|
||||||
shell.logger().log(LogLevel::NOTICE, LogFacility::AUTH, F("su session opened on console"));
|
shell.logger().log(LogLevel::NOTICE, LogFacility::AUTH, ("su session opened on console"));
|
||||||
shell.add_flags(CommandFlags::ADMIN);
|
shell.add_flags(CommandFlags::ADMIN);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -542,8 +543,8 @@ void Console::load_standard_commands(unsigned int context) {
|
|||||||
become_admin(shell);
|
become_admin(shell);
|
||||||
} else {
|
} else {
|
||||||
shell.delay_until(now + INVALID_PASSWORD_DELAY_MS, [](Shell & shell) {
|
shell.delay_until(now + INVALID_PASSWORD_DELAY_MS, [](Shell & shell) {
|
||||||
shell.logger().log(LogLevel::NOTICE, LogFacility::AUTH, F("Invalid su password on console"));
|
shell.logger().log(LogLevel::NOTICE, LogFacility::AUTH, ("Invalid su password on console"));
|
||||||
shell.println(F("su: incorrect password"));
|
shell.println("su: incorrect password");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -557,21 +558,21 @@ void Console::load_standard_commands(unsigned int context) {
|
|||||||
void Console::load_system_commands(unsigned int context) {
|
void Console::load_system_commands(unsigned int context) {
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(restart)},
|
string_vector{F_(restart)},
|
||||||
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) {
|
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
EMSESP::system_.system_restart();
|
EMSESP::system_.system_restart();
|
||||||
});
|
});
|
||||||
|
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(wifi), F_(reconnect)},
|
string_vector{F_(wifi), F_(reconnect)},
|
||||||
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) {
|
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
EMSESP::system_.wifi_reconnect();
|
EMSESP::system_.wifi_reconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
EMSESPShell::commands->add_command(ShellContext::MAIN,
|
EMSESPShell::commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(format)},
|
string_vector{F_(format)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
shell.enter_password(F_(password_prompt), [=](Shell & shell, bool completed, const std::string & password) {
|
shell.enter_password(F_(password_prompt), [=](Shell & shell, bool completed, const std::string & password) {
|
||||||
if (completed) {
|
if (completed) {
|
||||||
@@ -579,7 +580,7 @@ void Console::load_system_commands(unsigned int context) {
|
|||||||
if (securitySettings.jwtSecret.equals(password.c_str())) {
|
if (securitySettings.jwtSecret.equals(password.c_str())) {
|
||||||
EMSESP::system_.format(shell);
|
EMSESP::system_.format(shell);
|
||||||
} else {
|
} else {
|
||||||
shell.println(F("incorrect password"));
|
shell.println("incorrect password");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -588,7 +589,7 @@ void Console::load_system_commands(unsigned int context) {
|
|||||||
|
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(passwd)},
|
string_vector{F_(passwd)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
shell.enter_password(F_(new_password_prompt1), [](Shell & shell, bool completed, const std::string & password1) {
|
shell.enter_password(F_(new_password_prompt1), [](Shell & shell, bool completed, const std::string & password1) {
|
||||||
if (completed) {
|
if (completed) {
|
||||||
@@ -602,9 +603,9 @@ void Console::load_system_commands(unsigned int context) {
|
|||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
},
|
},
|
||||||
"local");
|
"local");
|
||||||
shell.println(F("su password updated"));
|
shell.println("su password updated");
|
||||||
} else {
|
} else {
|
||||||
shell.println(F("Passwords do not match"));
|
shell.println("Passwords do not match");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -614,7 +615,7 @@ void Console::load_system_commands(unsigned int context) {
|
|||||||
|
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(show), F_(system)},
|
string_vector{F_(show), F_(system)},
|
||||||
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
EMSESP::system_.show_system(shell);
|
EMSESP::system_.show_system(shell);
|
||||||
shell.println();
|
shell.println();
|
||||||
@@ -622,8 +623,8 @@ void Console::load_system_commands(unsigned int context) {
|
|||||||
|
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(set), F_(hostname)},
|
string_vector{F_(set), F_(hostname)},
|
||||||
flash_string_vector{F_(name_mandatory)},
|
string_vector{F_(name_mandatory)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
shell.println("The network connection will be reset...");
|
shell.println("The network connection will be reset...");
|
||||||
Shell::loop_all();
|
Shell::loop_all();
|
||||||
@@ -638,8 +639,8 @@ void Console::load_system_commands(unsigned int context) {
|
|||||||
|
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(set), F_(wifi), F_(ssid)},
|
string_vector{F_(set), F_(wifi), F_(ssid)},
|
||||||
flash_string_vector{F_(name_mandatory)},
|
string_vector{F_(name_mandatory)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
EMSESP::esp8266React.getNetworkSettingsService()->updateWithoutPropagation([&](NetworkSettings & networkSettings) {
|
EMSESP::esp8266React.getNetworkSettingsService()->updateWithoutPropagation([&](NetworkSettings & networkSettings) {
|
||||||
networkSettings.ssid = arguments.front().c_str();
|
networkSettings.ssid = arguments.front().c_str();
|
||||||
@@ -651,8 +652,8 @@ void Console::load_system_commands(unsigned int context) {
|
|||||||
// added by mvdp
|
// added by mvdp
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F("mqtt"), F("subscribe")},
|
string_vector{("mqtt"), ("subscribe")},
|
||||||
flash_string_vector{F("<topic>")},
|
string_vector{("<topic>")},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
Mqtt::subscribe(arguments.front());
|
Mqtt::subscribe(arguments.front());
|
||||||
shell.println("subscribing");
|
shell.println("subscribing");
|
||||||
@@ -660,7 +661,7 @@ void Console::load_system_commands(unsigned int context) {
|
|||||||
|
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(set), F_(wifi), F_(password)},
|
string_vector{F_(set), F_(wifi), F_(password)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
shell.enter_password(F_(new_password_prompt1), [](Shell & shell, bool completed, const std::string & password1) {
|
shell.enter_password(F_(new_password_prompt1), [](Shell & shell, bool completed, const std::string & password1) {
|
||||||
if (completed) {
|
if (completed) {
|
||||||
@@ -675,7 +676,7 @@ void Console::load_system_commands(unsigned int context) {
|
|||||||
});
|
});
|
||||||
shell.println("Use `wifi reconnect` to save and apply the new settings");
|
shell.println("Use `wifi reconnect` to save and apply the new settings");
|
||||||
} else {
|
} else {
|
||||||
shell.println(F("Passwords do not match"));
|
shell.println("Passwords do not match");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -685,13 +686,13 @@ void Console::load_system_commands(unsigned int context) {
|
|||||||
|
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(set), F_(board_profile)},
|
string_vector{F_(set), F_(board_profile)},
|
||||||
flash_string_vector{F_(name_mandatory)},
|
string_vector{F_(name_mandatory)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
std::vector<int8_t> data; // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode
|
std::vector<int8_t> data; // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode
|
||||||
std::string board_profile = Helpers::toUpper(arguments.front());
|
std::string board_profile = Helpers::toUpper(arguments.front());
|
||||||
if (!EMSESP::system_.load_board_profile(data, board_profile)) {
|
if (!EMSESP::system_.load_board_profile(data, board_profile)) {
|
||||||
shell.println(F("Invalid board profile (S32, E32, MH-ET, NODEMCU, OLIMEX, OLIMEXPOE, C3MINI, CUSTOM)"));
|
shell.println(("Invalid board profile (S32, E32, MH-ET, NODEMCU, OLIMEX, OLIMEXPOE, C3MINI, CUSTOM)"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EMSESP::webSettingsService.update(
|
EMSESP::webSettingsService.update(
|
||||||
@@ -714,7 +715,7 @@ void Console::load_system_commands(unsigned int context) {
|
|||||||
});
|
});
|
||||||
EMSESPShell::commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(show), F_(users)},
|
string_vector{F_(show), F_(users)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
EMSESP::system_.show_users(shell);
|
EMSESP::system_.show_users(shell);
|
||||||
});
|
});
|
||||||
@@ -730,14 +731,14 @@ std::string EMSESPShell::prompt_suffix() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EMSESPShell::end_of_transmission() {
|
void EMSESPShell::end_of_transmission() {
|
||||||
invoke_command(read_flash_string(F_(exit)));
|
invoke_command((F_(exit)));
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSESPStreamConsole::EMSESPStreamConsole(Stream & stream, bool local)
|
EMSESPStreamConsole::EMSESPStreamConsole(Stream & stream, bool local)
|
||||||
: uuid::console::Shell(commands, ShellContext::MAIN, local ? (CommandFlags::USER | CommandFlags::LOCAL) : CommandFlags::USER)
|
: uuid::console::Shell(commands, ShellContext::MAIN, local ? (CommandFlags::USER | CommandFlags::LOCAL) : CommandFlags::USER)
|
||||||
, uuid::console::StreamConsole(stream)
|
, uuid::console::StreamConsole(stream)
|
||||||
, EMSESPShell()
|
, EMSESPShell()
|
||||||
, name_(read_flash_string(F("Serial")))
|
, name_("Serial")
|
||||||
, pty_(SIZE_MAX)
|
, pty_(SIZE_MAX)
|
||||||
, addr_()
|
, addr_()
|
||||||
, port_(0) {
|
, port_(0) {
|
||||||
@@ -763,14 +764,14 @@ EMSESPStreamConsole::EMSESPStreamConsole(Stream & stream, const IPAddress & addr
|
|||||||
snprintf(text.data(), text.size(), "pty%u", (uint16_t)pty_);
|
snprintf(text.data(), text.size(), "pty%u", (uint16_t)pty_);
|
||||||
name_ = text.data();
|
name_ = text.data();
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
logger().info(F("Allocated console %s for connection from [%s]:%u"), name_.c_str(), uuid::printable_to_string(addr_).c_str(), port_);
|
logger().info("Allocated console %s for connection from [%s]:%u", name_.c_str(), uuid::printable_to_string(addr_).c_str(), port_);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSESPStreamConsole::~EMSESPStreamConsole() {
|
EMSESPStreamConsole::~EMSESPStreamConsole() {
|
||||||
if (pty_ != SIZE_MAX) {
|
if (pty_ != SIZE_MAX) {
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
logger().info(F("Shutdown console %s for connection from [%s]:%u"), name_.c_str(), uuid::printable_to_string(addr_).c_str(), port_);
|
logger().info("Shutdown console %s for connection from [%s]:%u", name_.c_str(), uuid::printable_to_string(addr_).c_str(), port_);
|
||||||
#endif
|
#endif
|
||||||
ptys_[pty_] = false;
|
ptys_[pty_] = false;
|
||||||
ptys_.shrink_to_fit();
|
ptys_.shrink_to_fit();
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ void DallasSensor::start() {
|
|||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
bus_.begin(dallas_gpio_);
|
bus_.begin(dallas_gpio_);
|
||||||
LOG_INFO(F("Starting Dallas sensor service"));
|
LOG_INFO("Starting Dallas sensor service");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Add API calls
|
// Add API calls
|
||||||
@@ -50,12 +50,12 @@ void DallasSensor::start() {
|
|||||||
EMSdevice::DeviceType::DALLASSENSOR,
|
EMSdevice::DeviceType::DALLASSENSOR,
|
||||||
F_(info),
|
F_(info),
|
||||||
[&](const char * value, const int8_t id, JsonObject & output) { return command_info(value, id, output); },
|
[&](const char * value, const int8_t id, JsonObject & output) { return command_info(value, id, output); },
|
||||||
F_(info_cmd));
|
FL_(info_cmd));
|
||||||
Command::add(
|
Command::add(
|
||||||
EMSdevice::DeviceType::DALLASSENSOR,
|
EMSdevice::DeviceType::DALLASSENSOR,
|
||||||
F_(commands),
|
F_(commands),
|
||||||
[&](const char * value, const int8_t id, JsonObject & output) { return command_commands(value, id, output); },
|
[&](const char * value, const int8_t id, JsonObject & output) { return command_commands(value, id, output); },
|
||||||
F_(commands_cmd));
|
FL_(commands_cmd));
|
||||||
|
|
||||||
Mqtt::subscribe(EMSdevice::DeviceType::DALLASSENSOR, "dallasssensor/#", nullptr); // use empty function callback
|
Mqtt::subscribe(EMSdevice::DeviceType::DALLASSENSOR, "dallasssensor/#", nullptr); // use empty function callback
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ void DallasSensor::loop() {
|
|||||||
if (state_ == State::IDLE) {
|
if (state_ == State::IDLE) {
|
||||||
if (time_now - last_activity_ >= READ_INTERVAL_MS) {
|
if (time_now - last_activity_ >= READ_INTERVAL_MS) {
|
||||||
#ifdef EMSESP_DEBUG_SENSOR
|
#ifdef EMSESP_DEBUG_SENSOR
|
||||||
LOG_DEBUG(F("[DEBUG] Read sensor temperature"));
|
LOG_DEBUG("[DEBUG] Read sensor temperature");
|
||||||
#endif
|
#endif
|
||||||
if (bus_.reset() || parasite_) {
|
if (bus_.reset() || parasite_) {
|
||||||
YIELD;
|
YIELD;
|
||||||
@@ -99,7 +99,7 @@ void DallasSensor::loop() {
|
|||||||
if (++scanretry_ > SCAN_MAX) { // every 30 sec
|
if (++scanretry_ > SCAN_MAX) { // every 30 sec
|
||||||
scanretry_ = 0;
|
scanretry_ = 0;
|
||||||
#ifdef EMSESP_DEBUG_SENSOR
|
#ifdef EMSESP_DEBUG_SENSOR
|
||||||
LOG_ERROR(F("Bus reset failed"));
|
LOG_ERROR("Bus reset failed");
|
||||||
#endif
|
#endif
|
||||||
for (auto & sensor : sensors_) {
|
for (auto & sensor : sensors_) {
|
||||||
sensor.temperature_c = EMS_VALUE_SHORT_NOTSET;
|
sensor.temperature_c = EMS_VALUE_SHORT_NOTSET;
|
||||||
@@ -112,13 +112,13 @@ void DallasSensor::loop() {
|
|||||||
} else if (state_ == State::READING) {
|
} else if (state_ == State::READING) {
|
||||||
if (temperature_convert_complete() && (time_now - last_activity_ > CONVERSION_MS)) {
|
if (temperature_convert_complete() && (time_now - last_activity_ > CONVERSION_MS)) {
|
||||||
#ifdef EMSESP_DEBUG_SENSOR
|
#ifdef EMSESP_DEBUG_SENSOR
|
||||||
LOG_DEBUG(F("Scanning for sensors"));
|
LOG_DEBUG("Scanning for sensors");
|
||||||
#endif
|
#endif
|
||||||
bus_.reset_search();
|
bus_.reset_search();
|
||||||
state_ = State::SCANNING;
|
state_ = State::SCANNING;
|
||||||
} else if (time_now - last_activity_ > READ_TIMEOUT_MS) {
|
} else if (time_now - last_activity_ > READ_TIMEOUT_MS) {
|
||||||
#ifdef EMSESP_DEBUG_SENSOR
|
#ifdef EMSESP_DEBUG_SENSOR
|
||||||
LOG_WARNING(F("Dallas sensor read timeout"));
|
LOG_WARNING("Dallas sensor read timeout");
|
||||||
#endif
|
#endif
|
||||||
state_ = State::IDLE;
|
state_ = State::IDLE;
|
||||||
sensorfails_++;
|
sensorfails_++;
|
||||||
@@ -126,7 +126,7 @@ void DallasSensor::loop() {
|
|||||||
} else if (state_ == State::SCANNING) {
|
} else if (state_ == State::SCANNING) {
|
||||||
if (time_now - last_activity_ > SCAN_TIMEOUT_MS) {
|
if (time_now - last_activity_ > SCAN_TIMEOUT_MS) {
|
||||||
#ifdef EMSESP_DEBUG_SENSOR
|
#ifdef EMSESP_DEBUG_SENSOR
|
||||||
LOG_ERROR(F("Dallas sensor scan timeout"));
|
LOG_ERROR("Dallas sensor scan timeout");
|
||||||
#endif
|
#endif
|
||||||
state_ = State::IDLE;
|
state_ = State::IDLE;
|
||||||
sensorfails_++;
|
sensorfails_++;
|
||||||
@@ -181,12 +181,12 @@ void DallasSensor::loop() {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
sensorfails_++;
|
sensorfails_++;
|
||||||
LOG_ERROR(F("Unknown dallas sensor %s"), Sensor(addr).id().c_str());
|
LOG_ERROR("Unknown dallas sensor %s", Sensor(addr).id().c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sensorfails_++;
|
sensorfails_++;
|
||||||
LOG_ERROR(F("Invalid dallas sensor %s"), Sensor(addr).id().c_str());
|
LOG_ERROR("Invalid dallas sensor %s", Sensor(addr).id().c_str());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!parasite_) {
|
if (!parasite_) {
|
||||||
@@ -204,7 +204,7 @@ void DallasSensor::loop() {
|
|||||||
scancnt_ = 0;
|
scancnt_ = 0;
|
||||||
} else if (scancnt_ == SCAN_START + 1) { // startup
|
} else if (scancnt_ == SCAN_START + 1) { // startup
|
||||||
firstscan_ = sensors_.size();
|
firstscan_ = sensors_.size();
|
||||||
// LOG_DEBUG(F("Adding %d dallas sensor(s) from first scan"), firstscan_);
|
// LOG_DEBUG(("Adding %d dallas sensor(s) from first scan"), firstscan_);
|
||||||
} else if ((scancnt_ <= 0) && (firstscan_ != sensors_.size())) { // check 2 times for no change of sensor #
|
} else if ((scancnt_ <= 0) && (firstscan_ != sensors_.size())) { // check 2 times for no change of sensor #
|
||||||
scancnt_ = SCAN_START;
|
scancnt_ = SCAN_START;
|
||||||
sensors_.clear(); // restart scaning and clear to get correct numbering
|
sensors_.clear(); // restart scaning and clear to get correct numbering
|
||||||
@@ -230,7 +230,7 @@ bool DallasSensor::temperature_convert_complete() {
|
|||||||
int16_t DallasSensor::get_temperature_c(const uint8_t addr[]) {
|
int16_t DallasSensor::get_temperature_c(const uint8_t addr[]) {
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
if (!bus_.reset()) {
|
if (!bus_.reset()) {
|
||||||
LOG_ERROR(F("Bus reset failed before reading scratchpad from %s"), Sensor(addr).id().c_str());
|
LOG_ERROR("Bus reset failed before reading scratchpad from %s", Sensor(addr).id().c_str());
|
||||||
return EMS_VALUE_SHORT_NOTSET;
|
return EMS_VALUE_SHORT_NOTSET;
|
||||||
}
|
}
|
||||||
YIELD;
|
YIELD;
|
||||||
@@ -242,13 +242,13 @@ int16_t DallasSensor::get_temperature_c(const uint8_t addr[]) {
|
|||||||
YIELD;
|
YIELD;
|
||||||
|
|
||||||
if (!bus_.reset()) {
|
if (!bus_.reset()) {
|
||||||
LOG_ERROR(F("Bus reset failed after reading scratchpad from %s"), Sensor(addr).id().c_str());
|
LOG_ERROR("Bus reset failed after reading scratchpad from %s", Sensor(addr).id().c_str());
|
||||||
return EMS_VALUE_SHORT_NOTSET;
|
return EMS_VALUE_SHORT_NOTSET;
|
||||||
}
|
}
|
||||||
YIELD;
|
YIELD;
|
||||||
|
|
||||||
if (bus_.crc8(scratchpad, SCRATCHPAD_LEN - 1) != scratchpad[SCRATCHPAD_LEN - 1]) {
|
if (bus_.crc8(scratchpad, SCRATCHPAD_LEN - 1) != scratchpad[SCRATCHPAD_LEN - 1]) {
|
||||||
LOG_WARNING(F("Invalid scratchpad CRC: %02X%02X%02X%02X%02X%02X%02X%02X%02X from sensor %s"),
|
LOG_WARNING("Invalid scratchpad CRC: %02X%02X%02X%02X%02X%02X%02X%02X%02X from sensor %s",
|
||||||
scratchpad[0],
|
scratchpad[0],
|
||||||
scratchpad[1],
|
scratchpad[1],
|
||||||
scratchpad[2],
|
scratchpad[2],
|
||||||
@@ -315,7 +315,7 @@ bool DallasSensor::update(const std::string & id, const std::string & name, int1
|
|||||||
SensorCustomization.name = name;
|
SensorCustomization.name = name;
|
||||||
SensorCustomization.offset = offset;
|
SensorCustomization.offset = offset;
|
||||||
found = true;
|
found = true;
|
||||||
LOG_DEBUG(F("Customizing existing sensor ID %s"), id.c_str());
|
LOG_DEBUG("Customizing existing sensor ID %s", id.c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -325,7 +325,7 @@ bool DallasSensor::update(const std::string & id, const std::string & name, int1
|
|||||||
newSensor.name = name;
|
newSensor.name = name;
|
||||||
newSensor.offset = offset;
|
newSensor.offset = offset;
|
||||||
settings.sensorCustomizations.push_back(newSensor);
|
settings.sensorCustomizations.push_back(newSensor);
|
||||||
LOG_DEBUG(F("Adding new customization for sensor ID %s"), id.c_str());
|
LOG_DEBUG("Adding new customization for sensor ID %s", id.c_str());
|
||||||
}
|
}
|
||||||
sensor.ha_registered = false; // it's changed so we may need to recreate the HA config
|
sensor.ha_registered = false; // it's changed so we may need to recreate the HA config
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
@@ -360,14 +360,15 @@ bool DallasSensor::command_info(const char * value, const int8_t id, JsonObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const auto & sensor : sensors_) {
|
for (const auto & sensor : sensors_) {
|
||||||
|
char val[10];
|
||||||
if (id == -1) { // show number and id
|
if (id == -1) { // show number and id
|
||||||
JsonObject dataSensor = output.createNestedObject(sensor.name());
|
JsonObject dataSensor = output.createNestedObject(sensor.name());
|
||||||
dataSensor["id"] = sensor.id();
|
dataSensor["id"] = sensor.id();
|
||||||
if (Helpers::hasValue(sensor.temperature_c)) {
|
if (Helpers::hasValue(sensor.temperature_c)) {
|
||||||
dataSensor["temp"] = Helpers::transformNumFloat((float)(sensor.temperature_c), 10, EMSESP::system_.fahrenheit() ? 2 : 0);
|
dataSensor["temp"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
|
||||||
}
|
}
|
||||||
} else if (Helpers::hasValue(sensor.temperature_c)) {
|
} else if (Helpers::hasValue(sensor.temperature_c)) {
|
||||||
output[sensor.name()] = Helpers::transformNumFloat((float)(sensor.temperature_c), 10, EMSESP::system_.fahrenheit() ? 2 : 0);
|
output[sensor.name()] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,14 +393,17 @@ bool DallasSensor::get_value_info(JsonObject & output, const char * cmd, const i
|
|||||||
if (strcmp(command_s, sensor.name().c_str()) == 0) {
|
if (strcmp(command_s, sensor.name().c_str()) == 0) {
|
||||||
output["id"] = sensor.id();
|
output["id"] = sensor.id();
|
||||||
output["name"] = sensor.name();
|
output["name"] = sensor.name();
|
||||||
|
char val[10];
|
||||||
if (Helpers::hasValue(sensor.temperature_c)) {
|
if (Helpers::hasValue(sensor.temperature_c)) {
|
||||||
output["value"] = Helpers::transformNumFloat((float)(sensor.temperature_c), 10, EMSESP::system_.fahrenheit() ? 2 : 0);
|
output["value"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
output["type"] = F_(number);
|
output["type"] = F_(number);
|
||||||
output["min"] = Helpers::transformNumFloat(-55, 0, EMSESP::system_.fahrenheit() ? 2 : 0);
|
output["min"] = serialized(Helpers::render_value(val, -55, 0, EMSESP::system_.fahrenheit() ? 2 : 0));
|
||||||
output["max"] = Helpers::transformNumFloat(125, 0, EMSESP::system_.fahrenheit() ? 2 : 0);
|
output["max"] = serialized(Helpers::render_value(val, 125, 0, EMSESP::system_.fahrenheit() ? 2 : 0));
|
||||||
output["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES);
|
output["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES);
|
||||||
output["writeable"] = false;
|
output["writeable"] = false;
|
||||||
|
|
||||||
// if we're filtering on an attribute, go find it
|
// if we're filtering on an attribute, go find it
|
||||||
if (attribute_s) {
|
if (attribute_s) {
|
||||||
if (output.containsKey(attribute_s)) {
|
if (output.containsKey(attribute_s)) {
|
||||||
@@ -426,9 +430,9 @@ void DallasSensor::publish_sensor(const Sensor & sensor) {
|
|||||||
if (Mqtt::publish_single()) {
|
if (Mqtt::publish_single()) {
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
if (Mqtt::publish_single2cmd()) {
|
if (Mqtt::publish_single2cmd()) {
|
||||||
snprintf(topic, sizeof(topic), "%s/%s", read_flash_string(F_(dallassensor)).c_str(), sensor.name().c_str());
|
snprintf(topic, sizeof(topic), "%s/%s", (F_(dallassensor)), sensor.name().c_str());
|
||||||
} else {
|
} else {
|
||||||
snprintf(topic, sizeof(topic), "%s%s/%s", read_flash_string(F_(dallassensor)).c_str(), "_data", sensor.name().c_str());
|
snprintf(topic, sizeof(topic), "%s%s/%s", (F_(dallassensor)), "_data", sensor.name().c_str());
|
||||||
}
|
}
|
||||||
char payload[10];
|
char payload[10];
|
||||||
Mqtt::publish(topic, Helpers::render_value(payload, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
|
Mqtt::publish(topic, Helpers::render_value(payload, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
|
||||||
@@ -441,7 +445,7 @@ void DallasSensor::remove_ha_topic(const std::string & id) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef EMSESP_DEBUG
|
#ifdef EMSESP_DEBUG
|
||||||
LOG_DEBUG(F("Removing HA config for temperature sensor ID %s"), id.c_str());
|
LOG_DEBUG("Removing HA config for temperature sensor ID %s", id.c_str());
|
||||||
#endif
|
#endif
|
||||||
// use '_' as HA doesn't like '-' in the topic name
|
// use '_' as HA doesn't like '-' in the topic name
|
||||||
std::string sensorid = id;
|
std::string sensorid = id;
|
||||||
@@ -469,24 +473,25 @@ void DallasSensor::publish_values(const bool force) {
|
|||||||
|
|
||||||
for (auto & sensor : sensors_) {
|
for (auto & sensor : sensors_) {
|
||||||
bool has_value = Helpers::hasValue(sensor.temperature_c);
|
bool has_value = Helpers::hasValue(sensor.temperature_c);
|
||||||
|
char val[10];
|
||||||
if (Mqtt::is_nested()) {
|
if (Mqtt::is_nested()) {
|
||||||
JsonObject dataSensor = doc.createNestedObject(sensor.id());
|
JsonObject dataSensor = doc.createNestedObject(sensor.id());
|
||||||
dataSensor["name"] = sensor.name();
|
dataSensor["name"] = sensor.name();
|
||||||
if (has_value) {
|
if (has_value) {
|
||||||
dataSensor["temp"] = Helpers::transformNumFloat((float)(sensor.temperature_c), 10, EMSESP::system_.fahrenheit() ? 2 : 0);
|
dataSensor["temp"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
|
||||||
}
|
}
|
||||||
} else if (has_value) {
|
} else if (has_value) {
|
||||||
doc[sensor.name()] = Helpers::transformNumFloat((float)(sensor.temperature_c), 10, EMSESP::system_.fahrenheit() ? 2 : 0);
|
doc[sensor.name()] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the HA MQTT config
|
// create the HA MQTT config
|
||||||
// to e.g. homeassistant/sensor/ems-esp/dallassensor_28-233D-9497-0C03/config
|
// to e.g. homeassistant/sensor/ems-esp/dallassensor_28-233D-9497-0C03/config
|
||||||
if (Mqtt::ha_enabled()) {
|
if (Mqtt::ha_enabled()) {
|
||||||
if (!sensor.ha_registered || force) {
|
if (!sensor.ha_registered || force) {
|
||||||
LOG_DEBUG(F("Recreating HA config for sensor ID %s"), sensor.id().c_str());
|
LOG_DEBUG("Recreating HA config for sensor ID %s", sensor.id().c_str());
|
||||||
|
|
||||||
StaticJsonDocument<EMSESP_JSON_SIZE_MEDIUM> config;
|
StaticJsonDocument<EMSESP_JSON_SIZE_MEDIUM> config;
|
||||||
config["dev_cla"] = FJSON("temperature");
|
config["dev_cla"] = "temperature";
|
||||||
|
|
||||||
char stat_t[50];
|
char stat_t[50];
|
||||||
snprintf(stat_t, sizeof(stat_t), "%s/dallassensor_data", Mqtt::base().c_str());
|
snprintf(stat_t, sizeof(stat_t), "%s/dallassensor_data", Mqtt::base().c_str());
|
||||||
@@ -530,7 +535,7 @@ void DallasSensor::publish_values(const bool force) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Mqtt::publish(F("dallassensor_data"), doc.as<JsonObject>());
|
Mqtt::publish("dallassensor_data", doc.as<JsonObject>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -574,7 +579,7 @@ bool DallasSensor::Sensor::apply_customization() {
|
|||||||
if (!sensors.empty()) {
|
if (!sensors.empty()) {
|
||||||
for (const auto & sensor : sensors) {
|
for (const auto & sensor : sensors) {
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
LOG_DEBUG(F("Loading customization for dallas sensor %s"), sensor.id.c_str());
|
LOG_DEBUG("Loading customization for dallas sensor %s", sensor.id.c_str());
|
||||||
#endif
|
#endif
|
||||||
if (id_ == sensor.id) {
|
if (id_ == sensor.id) {
|
||||||
set_name(sensor.name);
|
set_name(sensor.name);
|
||||||
|
|||||||
@@ -24,140 +24,142 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Boilers - 0x08
|
// Boilers - 0x08
|
||||||
{ 64, DeviceType::BOILER, F("BK13/BK15/Smartline/GB1x2"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{ 64, DeviceType::BOILER, "BK13/BK15/Smartline/GB1x2", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{ 72, DeviceType::BOILER, F("GB125/MC10"), DeviceFlags::EMS_DEVICE_FLAG_EMS},
|
{ 72, DeviceType::BOILER, "GB125/MC10", DeviceFlags::EMS_DEVICE_FLAG_EMS},
|
||||||
{ 81, DeviceType::BOILER, F("Cascade CM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{ 81, DeviceType::BOILER, "Cascade CM10", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{ 84, DeviceType::BOILER, F("Logamax Plus GB022"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{ 84, DeviceType::BOILER, "Logamax Plus GB022", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{ 95, DeviceType::BOILER, F("Condens 2500/Logamax/Logomatic/Cerapur Top/Greenstar/Generic HT3"), DeviceFlags::EMS_DEVICE_FLAG_HT3},
|
{ 95, DeviceType::BOILER, "Condens 2500/Logamax/Logomatic/Cerapur Top/Greenstar/Generic HT3", DeviceFlags::EMS_DEVICE_FLAG_HT3},
|
||||||
{115, DeviceType::BOILER, F("Topline/GB162"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{115, DeviceType::BOILER, "Topline/GB162", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{122, DeviceType::BOILER, F("Proline"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{122, DeviceType::BOILER, "Proline", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{123, DeviceType::BOILER, F("GBx72/Trendline/Cerapur/Greenstar Si/27i"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{123, DeviceType::BOILER, "GBx72/Trendline/Cerapur/Greenstar Si/27i", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{131, DeviceType::BOILER, F("GB212"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{131, DeviceType::BOILER, "GB212", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{132, DeviceType::BOILER, F("GC7000F"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{132, DeviceType::BOILER, "GC7000F", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{133, DeviceType::BOILER, F("Logano GB125/KB195i/Logamatic MC110"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{133, DeviceType::BOILER, "Logano GB125/KB195i/Logamatic MC110", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{154, DeviceType::BOILER, F("Greenstar 30Ri Compact"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{154, DeviceType::BOILER, "Greenstar 30Ri Compact", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{167, DeviceType::BOILER, F("Cerapur Aero"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{167, DeviceType::BOILER, "Cerapur Aero", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{168, DeviceType::BOILER, F("Hybrid Heatpump"), DeviceFlags::EMS_DEVICE_FLAG_HYBRID},
|
{168, DeviceType::BOILER, "Hybrid Heatpump", DeviceFlags::EMS_DEVICE_FLAG_HYBRID},
|
||||||
{170, DeviceType::BOILER, F("Logano GB212"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{170, DeviceType::BOILER, "Logano GB212", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{172, DeviceType::BOILER, F("Enviline/Compress 6000AW/Hybrid 7000iAW/SupraEco/Geo 5xx"), DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP},
|
{172, DeviceType::BOILER, "Enviline/Compress 6000AW/Hybrid 7000iAW/SupraEco/Geo 5xx", DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP},
|
||||||
{173, DeviceType::BOILER, F("Geo 5xx"), DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP},
|
{173, DeviceType::BOILER, "Geo 5xx", DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP},
|
||||||
{195, DeviceType::BOILER, F("Condens 5000i/Greenstar 8000"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{195, DeviceType::BOILER, "Condens 5000i/Greenstar 8000", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{203, DeviceType::BOILER, F("Logamax U122/Cerapur"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{203, DeviceType::BOILER, "Logamax U122/Cerapur", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{206, DeviceType::BOILER, F("Ecomline Excellent"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{206, DeviceType::BOILER, "Ecomline Excellent", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{208, DeviceType::BOILER, F("Logamax Plus/GB192/Condens GC9000"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{208, DeviceType::BOILER, "Logamax Plus/GB192/Condens GC9000", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{210, DeviceType::BOILER, F("Cascade MC400"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{210, DeviceType::BOILER, "Cascade MC400", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{211, DeviceType::BOILER, F("EasyControl Adapter"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{211, DeviceType::BOILER, "EasyControl Adapter", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{228, DeviceType::BOILER, F("Alternative Heatsource"), DeviceFlags::EMS_DEVICE_FLAG_AM200},
|
{228, DeviceType::BOILER, "Alternative Heatsource", DeviceFlags::EMS_DEVICE_FLAG_AM200},
|
||||||
{234, DeviceType::BOILER, F("Logamax Plus GB122/Condense 2300"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{234, DeviceType::BOILER, "Logamax Plus GB122/Condense 2300", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
// Controllers - 0x09 / 0x10 / 0x50
|
// Controllers - 0x09 / 0x10 / 0x50
|
||||||
{ 68, DeviceType::CONTROLLER, F("BC10/RFM20"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{ 68, DeviceType::CONTROLLER, "BC10/RFM20", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{ 81, DeviceType::CONTROLLER, F("CM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{ 81, DeviceType::CONTROLLER, "CM10", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{ 84, DeviceType::CONTROLLER, F("GB022"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{ 84, DeviceType::CONTROLLER, "GB022", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{ 89, DeviceType::CONTROLLER, F("BC10 GB142"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{ 89, DeviceType::CONTROLLER, "BC10 GB142", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{ 95, DeviceType::CONTROLLER, F("HT3"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{ 95, DeviceType::CONTROLLER, "HT3", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{114, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{114, DeviceType::CONTROLLER, "BC10", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{125, DeviceType::CONTROLLER, F("BC25"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{125, DeviceType::CONTROLLER, "BC25", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{152, DeviceType::CONTROLLER, F("Controller"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{152, DeviceType::CONTROLLER, "Controller", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{168, DeviceType::CONTROLLER, F("Hybrid Heatpump"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{168, DeviceType::CONTROLLER, "Hybrid Heatpump", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{169, DeviceType::CONTROLLER, F("BC40"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{169, DeviceType::CONTROLLER, "BC40", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{190, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{190, DeviceType::CONTROLLER, "BC10", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{194, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{194, DeviceType::CONTROLLER, "BC10", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{206, DeviceType::CONTROLLER, F("Ecomline"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{206, DeviceType::CONTROLLER, "Ecomline", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{207, DeviceType::CONTROLLER, F("Sense II/CS200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x10
|
{207, DeviceType::CONTROLLER, "Sense II/CS200", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x10
|
||||||
{209, DeviceType::CONTROLLER, F("ErP"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{209, DeviceType::CONTROLLER, "ErP", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{218, DeviceType::CONTROLLER, F("M200/RFM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x50
|
{218, DeviceType::CONTROLLER, "M200/RFM200", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x50
|
||||||
{224, DeviceType::CONTROLLER, F("9000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{220, DeviceType::CONTROLLER, "BC30", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x16
|
||||||
{229, DeviceType::CONTROLLER, F("8700i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{224, DeviceType::CONTROLLER, "9000i", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{230, DeviceType::CONTROLLER, F("BC Base"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{229, DeviceType::CONTROLLER, "8700i", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{240, DeviceType::CONTROLLER, F("Rego 3000"), DeviceFlags::EMS_DEVICE_FLAG_IVT}, // 0x09
|
{230, DeviceType::CONTROLLER, "BC Base", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{241, DeviceType::CONTROLLER, F("Condens 5000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{240, DeviceType::CONTROLLER, "Rego 3000", DeviceFlags::EMS_DEVICE_FLAG_IVT}, // 0x09
|
||||||
|
{241, DeviceType::CONTROLLER, "Condens 5000i", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
|
|
||||||
// Thermostat - not currently supporting write operations, like the Easy/100 types - 0x18
|
// Thermostat - not currently supporting write operations, like the Easy/100 types - 0x18
|
||||||
{202, DeviceType::THERMOSTAT, F("Logamatic TC100/Moduline Easy"), DeviceFlags::EMS_DEVICE_FLAG_EASY | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18, cannot write
|
{202, DeviceType::THERMOSTAT, "Logamatic TC100/Moduline Easy", DeviceFlags::EMS_DEVICE_FLAG_EASY | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18, cannot write
|
||||||
{203, DeviceType::THERMOSTAT, F("EasyControl CT200"), DeviceFlags::EMS_DEVICE_FLAG_EASY | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18, cannot write
|
{203, DeviceType::THERMOSTAT, "EasyControl CT200", DeviceFlags::EMS_DEVICE_FLAG_EASY | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18, cannot write
|
||||||
|
|
||||||
// Thermostat - Buderus/Nefit/Bosch specific - 0x17 / 0x10 / 0x18 / 0x19-0x1B for hc2-4 / 0x38
|
// Thermostat - Buderus/Nefit/Bosch specific - 0x17 / 0x10 / 0x18 / 0x19-0x1B for hc2-4 / 0x38
|
||||||
{ 65, DeviceType::THERMOSTAT, F("RC10"), DeviceFlags::EMS_DEVICE_FLAG_RC20_N},// 0x17
|
{ 65, DeviceType::THERMOSTAT, "RC10", DeviceFlags::EMS_DEVICE_FLAG_RC20_N},// 0x17
|
||||||
{ 67, DeviceType::THERMOSTAT, F("RC30"), DeviceFlags::EMS_DEVICE_FLAG_RC30_N},// 0x10 - based on RC35
|
{ 67, DeviceType::THERMOSTAT, "RC30", DeviceFlags::EMS_DEVICE_FLAG_RC30_N},// 0x10 - based on RC35
|
||||||
{ 77, DeviceType::THERMOSTAT, F("RC20/Moduline 300"), DeviceFlags::EMS_DEVICE_FLAG_RC20},// 0x17
|
{ 77, DeviceType::THERMOSTAT, "RC20/Moduline 300", DeviceFlags::EMS_DEVICE_FLAG_RC20},// 0x17
|
||||||
{ 78, DeviceType::THERMOSTAT, F("Moduline 400"), DeviceFlags::EMS_DEVICE_FLAG_RC30}, // 0x10
|
{ 78, DeviceType::THERMOSTAT, "Moduline 400", DeviceFlags::EMS_DEVICE_FLAG_RC30}, // 0x10
|
||||||
{ 79, DeviceType::THERMOSTAT, F("RC10/Moduline 100"), DeviceFlags::EMS_DEVICE_FLAG_RC10},// 0x17
|
{ 79, DeviceType::THERMOSTAT, "RC10/Moduline 100", DeviceFlags::EMS_DEVICE_FLAG_RC10},// 0x17
|
||||||
{ 80, DeviceType::THERMOSTAT, F("Moduline 200"), DeviceFlags::EMS_DEVICE_FLAG_RC10}, // 0x17
|
{ 80, DeviceType::THERMOSTAT, "Moduline 200", DeviceFlags::EMS_DEVICE_FLAG_RC10}, // 0x17
|
||||||
{ 86, DeviceType::THERMOSTAT, F("RC35"), DeviceFlags::EMS_DEVICE_FLAG_RC35}, // 0x10
|
{ 86, DeviceType::THERMOSTAT, "RC35", DeviceFlags::EMS_DEVICE_FLAG_RC35}, // 0x10
|
||||||
{ 90, DeviceType::THERMOSTAT, F("RC10/Moduline 100"), DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17
|
{ 90, DeviceType::THERMOSTAT, "RC10/Moduline 100", DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17
|
||||||
{ 93, DeviceType::THERMOSTAT, F("RC20RF"), DeviceFlags::EMS_DEVICE_FLAG_RC20}, // 0x19
|
{ 93, DeviceType::THERMOSTAT, "RC20RF", DeviceFlags::EMS_DEVICE_FLAG_RC20}, // 0x19
|
||||||
{ 94, DeviceType::THERMOSTAT, F("RFM20 Remote"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x18
|
{ 94, DeviceType::THERMOSTAT, "RFM20 Remote", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x18
|
||||||
{151, DeviceType::THERMOSTAT, F("RC25"), DeviceFlags::EMS_DEVICE_FLAG_RC25}, // 0x17
|
{151, DeviceType::THERMOSTAT, "RC25", DeviceFlags::EMS_DEVICE_FLAG_RC25}, // 0x17
|
||||||
{157, DeviceType::THERMOSTAT, F("RC200/CW100"), DeviceFlags::EMS_DEVICE_FLAG_RC100}, // 0x18
|
{157, DeviceType::THERMOSTAT, "RC200/CW100", DeviceFlags::EMS_DEVICE_FLAG_RC100}, // 0x18
|
||||||
{158, DeviceType::THERMOSTAT, F("RC300/RC310/Moduline 3000/1010H/CW400/Sense II"), DeviceFlags::EMS_DEVICE_FLAG_RC300}, // 0x10
|
{158, DeviceType::THERMOSTAT, "RC300/RC310/Moduline 3000/1010H/CW400/Sense II", DeviceFlags::EMS_DEVICE_FLAG_RC300}, // 0x10
|
||||||
{165, DeviceType::THERMOSTAT, F("RC100/Moduline 1000/1010"), DeviceFlags::EMS_DEVICE_FLAG_RC100}, // 0x18, 0x38
|
{165, DeviceType::THERMOSTAT, "RC100/Moduline 1000/1010", DeviceFlags::EMS_DEVICE_FLAG_RC100}, // 0x18, 0x38
|
||||||
{172, DeviceType::THERMOSTAT, F("Rego 2000/3000"), DeviceFlags::EMS_DEVICE_FLAG_RC300}, // 0x10
|
{172, DeviceType::THERMOSTAT, "Rego 2000/3000", DeviceFlags::EMS_DEVICE_FLAG_RC300}, // 0x10
|
||||||
{216, DeviceType::THERMOSTAT, F("CRF200S"), DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
|
{216, DeviceType::THERMOSTAT, "CRF200S", DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
|
||||||
{246, DeviceType::THERMOSTAT, F("Comfort+2RF"), DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
|
{246, DeviceType::THERMOSTAT, "Comfort+2RF", DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
|
||||||
|
|
||||||
// Thermostat - Sieger - 0x10 / 0x17
|
// Thermostat - Sieger - 0x10 / 0x17
|
||||||
{ 66, DeviceType::THERMOSTAT, F("ES72/RC20"), DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17 or remote
|
{ 66, DeviceType::THERMOSTAT, "ES72/RC20", DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17 or remote
|
||||||
{ 76, DeviceType::THERMOSTAT, F("ES73"), DeviceFlags::EMS_DEVICE_FLAG_RC30_N}, // 0x10
|
{ 76, DeviceType::THERMOSTAT, "ES73", DeviceFlags::EMS_DEVICE_FLAG_RC30_N}, // 0x10
|
||||||
{113, DeviceType::THERMOSTAT, F("ES72/RC20"), DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17
|
{113, DeviceType::THERMOSTAT, "ES72/RC20", DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17
|
||||||
|
|
||||||
// Thermostat - Junkers - 0x10
|
// Thermostat - Junkers - 0x10
|
||||||
{105, DeviceType::THERMOSTAT, F("FW100"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
{105, DeviceType::THERMOSTAT, "FW100", DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
||||||
{106, DeviceType::THERMOSTAT, F("FW200"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
{106, DeviceType::THERMOSTAT, "FW200", DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
||||||
{107, DeviceType::THERMOSTAT, F("FR100"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_OLD}, // older model
|
{107, DeviceType::THERMOSTAT, "FR100", DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_OLD}, // older model
|
||||||
{108, DeviceType::THERMOSTAT, F("FR110"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_OLD}, // older model
|
{108, DeviceType::THERMOSTAT, "FR110", DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_OLD}, // older model
|
||||||
{109, DeviceType::THERMOSTAT, F("FB10"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
{109, DeviceType::THERMOSTAT, "FB10", DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
||||||
{110, DeviceType::THERMOSTAT, F("FB100"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
{110, DeviceType::THERMOSTAT, "FB100", DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
||||||
{111, DeviceType::THERMOSTAT, F("FR10"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_OLD}, // older model
|
{111, DeviceType::THERMOSTAT, "FR10", DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_OLD}, // older model
|
||||||
{147, DeviceType::THERMOSTAT, F("FR50"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_OLD},
|
{116, DeviceType::THERMOSTAT, "FW500", DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
||||||
{191, DeviceType::THERMOSTAT, F("FR120"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_OLD}, // older model
|
{147, DeviceType::THERMOSTAT, "FR50", DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_OLD},
|
||||||
{192, DeviceType::THERMOSTAT, F("FW120"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
{191, DeviceType::THERMOSTAT, "FR120", DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_OLD}, // older model
|
||||||
|
{192, DeviceType::THERMOSTAT, "FW120", DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
||||||
|
|
||||||
// Thermostat remote - 0x38
|
// Thermostat remote - 0x38
|
||||||
{200, DeviceType::THERMOSTAT, F("RC100H"), DeviceFlags::EMS_DEVICE_FLAG_RC100H},
|
{200, DeviceType::THERMOSTAT, "RC100H", DeviceFlags::EMS_DEVICE_FLAG_RC100H},
|
||||||
|
|
||||||
// Solar Modules - 0x30 (for solar), 0x2A, 0x41 (for ww)
|
// Solar Modules - 0x30 (for solar), 0x2A, 0x41 (for ww)
|
||||||
{ 73, DeviceType::SOLAR, F("SM10"), DeviceFlags::EMS_DEVICE_FLAG_SM10},
|
{ 73, DeviceType::SOLAR, "SM10", DeviceFlags::EMS_DEVICE_FLAG_SM10},
|
||||||
{101, DeviceType::SOLAR, F("ISM1"), DeviceFlags::EMS_DEVICE_FLAG_ISM},
|
{101, DeviceType::SOLAR, "ISM1", DeviceFlags::EMS_DEVICE_FLAG_ISM},
|
||||||
{103, DeviceType::SOLAR, F("ISM2"), DeviceFlags::EMS_DEVICE_FLAG_ISM},
|
{103, DeviceType::SOLAR, "ISM2", DeviceFlags::EMS_DEVICE_FLAG_ISM},
|
||||||
{162, DeviceType::SOLAR, F("SM50"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
|
{162, DeviceType::SOLAR, "SM50", DeviceFlags::EMS_DEVICE_FLAG_SM100},
|
||||||
{163, DeviceType::SOLAR, F("SM100/MS100"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
|
{163, DeviceType::SOLAR, "SM100/MS100", DeviceFlags::EMS_DEVICE_FLAG_SM100},
|
||||||
{164, DeviceType::SOLAR, F("SM200/MS200"), DeviceFlags::EMS_DEVICE_FLAG_SM100},
|
{164, DeviceType::SOLAR, "SM200/MS200", DeviceFlags::EMS_DEVICE_FLAG_SM100},
|
||||||
|
|
||||||
// Mixer Modules - 0x20-0x27 for HC, 0x28-0x29 for WWC and 0x11 for the MP100
|
// Mixer Modules - 0x20-0x27 for HC, 0x28-0x29 for WWC and 0x11 for the MP100
|
||||||
{ 69, DeviceType::MIXER, F("MM10"), DeviceFlags::EMS_DEVICE_FLAG_MM10},
|
{ 69, DeviceType::MIXER, "MM10", DeviceFlags::EMS_DEVICE_FLAG_MM10},
|
||||||
{100, DeviceType::MIXER, F("IPM"), DeviceFlags::EMS_DEVICE_FLAG_IPM},
|
{100, DeviceType::MIXER, "IPM", DeviceFlags::EMS_DEVICE_FLAG_IPM},
|
||||||
{102, DeviceType::MIXER, F("IPM"), DeviceFlags::EMS_DEVICE_FLAG_IPM},
|
{102, DeviceType::MIXER, "IPM", DeviceFlags::EMS_DEVICE_FLAG_IPM},
|
||||||
{159, DeviceType::MIXER, F("MM50"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
{159, DeviceType::MIXER, "MM50", DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
||||||
{160, DeviceType::MIXER, F("MM100"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
{160, DeviceType::MIXER, "MM100", DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
||||||
{161, DeviceType::MIXER, F("MM200"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
{161, DeviceType::MIXER, "MM200", DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
||||||
{204, DeviceType::MIXER, F("MP100"), DeviceFlags::EMS_DEVICE_FLAG_MP}, // pool
|
{204, DeviceType::MIXER, "MP100", DeviceFlags::EMS_DEVICE_FLAG_MP}, // pool
|
||||||
|
|
||||||
// Heat Pumps - 0x38?
|
// Heat Pumps - 0x38?
|
||||||
{252, DeviceType::HEATPUMP, F("HP Module"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{252, DeviceType::HEATPUMP, "HP Module", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
// Heat Pumps - 0x53
|
// Heat Pumps - 0x53
|
||||||
{248, DeviceType::HEATPUMP, F("Hybrid Manager HM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{248, DeviceType::HEATPUMP, "Hybrid Manager HM200", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
// Connect devices - 0x02
|
// Connect devices - 0x02
|
||||||
{171, DeviceType::CONNECT, F("OpenTherm Converter"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{171, DeviceType::CONNECT, "OpenTherm Converter", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{205, DeviceType::CONNECT, F("Moduline Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{205, DeviceType::CONNECT, "Moduline Easy Connect", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{206, DeviceType::CONNECT, F("Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{206, DeviceType::CONNECT, "Easy Connect", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
// Wireless sensor base - 0x50
|
// Wireless sensor base - 0x50
|
||||||
{236, DeviceType::CONNECT, F("Wireless sensor base"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{236, DeviceType::CONNECT, "Wireless sensor base", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{238, DeviceType::CONNECT, F("Wireless sensor base"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{238, DeviceType::CONNECT, "Wireless sensor base", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
// Switches - 0x11
|
// Switches - 0x11
|
||||||
{ 71, DeviceType::SWITCH, F("WM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{ 71, DeviceType::SWITCH, "WM10", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
// EM10 error contact and analog flowtemp control- 0x12
|
// EM10 error contact and analog flowtemp control- 0x12
|
||||||
{ 74, DeviceType::GATEWAY, F("Error Module EM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{ 74, DeviceType::GATEWAY, "Error Module EM10", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
// Gateways - 0x48
|
// Gateways - 0x48
|
||||||
{189, DeviceType::GATEWAY, F("KM200/MB LAN 2"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{189, DeviceType::GATEWAY, "KM200/MB LAN 2", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
// Generic - 0x40 or other with no product-id and no version
|
// Generic - 0x40 or other with no product-id and no version
|
||||||
{0, DeviceType::GENERIC, F("unknown"), DeviceFlags::EMS_DEVICE_FLAG_NONE}
|
{0, DeviceType::GENERIC, "unknown", DeviceFlags::EMS_DEVICE_FLAG_NONE}
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|||||||
@@ -24,16 +24,16 @@ REGISTER_FACTORY(Boiler, EMSdevice::DeviceType::BOILER)
|
|||||||
|
|
||||||
uuid::log::Logger Boiler::logger_{F_(boiler), uuid::log::Facility::CONSOLE};
|
uuid::log::Logger Boiler::logger_{F_(boiler), uuid::log::Facility::CONSOLE};
|
||||||
|
|
||||||
Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||||
// alternative heatsource special messages
|
// alternative heatsource special messages
|
||||||
|
|
||||||
if (device_id == EMSdevice::EMS_DEVICE_ID_AM200) {
|
if (device_id == EMSdevice::EMS_DEVICE_ID_AM200) {
|
||||||
register_telegram_type(0x54D, F("AmTemperatures"), false, MAKE_PF_CB(process_amTempMessage));
|
register_telegram_type(0x54D, "AmTemperatures", false, MAKE_PF_CB(process_amTempMessage));
|
||||||
register_telegram_type(0x54E, F("AmStatus"), false, MAKE_PF_CB(process_amStatusMessage));
|
register_telegram_type(0x54E, "AmStatus", false, MAKE_PF_CB(process_amStatusMessage));
|
||||||
register_telegram_type(0x54F, F("AmCommand"), false, MAKE_PF_CB(process_amCommandMessage)); // not broadcasted, but actually not used
|
register_telegram_type(0x54F, "AmCommand", false, MAKE_PF_CB(process_amCommandMessage)); // not broadcasted, but actually not used
|
||||||
register_telegram_type(0x550, F("AmExtra"), false, MAKE_PF_CB(process_amExtraMessage));
|
register_telegram_type(0x550, "AmExtra", false, MAKE_PF_CB(process_amExtraMessage));
|
||||||
register_telegram_type(0x54C, F("AmSettings"), true, MAKE_PF_CB(process_amSettingMessage)); // not broadcasted
|
register_telegram_type(0x54C, "AmSettings", true, MAKE_PF_CB(process_amSettingMessage)); // not broadcasted
|
||||||
|
|
||||||
register_device_value(DeviceValueTAG::TAG_AHS,
|
register_device_value(DeviceValueTAG::TAG_AHS,
|
||||||
&curFlowTemp_,
|
&curFlowTemp_,
|
||||||
@@ -113,12 +113,12 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
if (device_id >= EMSdevice::EMS_DEVICE_ID_BOILER_1) {
|
if (device_id >= EMSdevice::EMS_DEVICE_ID_BOILER_1) {
|
||||||
uint8_t hs = device_id - EMSdevice::EMS_DEVICE_ID_BOILER_1; // heating source id, count from 0
|
uint8_t hs = device_id - EMSdevice::EMS_DEVICE_ID_BOILER_1; // heating source id, count from 0
|
||||||
// Runtime of each heatingsource in 0x06DC, ff
|
// Runtime of each heatingsource in 0x06DC, ff
|
||||||
register_telegram_type(0x6DC + hs, F("CascadeMessage"), false, MAKE_PF_CB(process_CascadeMessage));
|
register_telegram_type(0x6DC + hs, "CascadeMessage", false, MAKE_PF_CB(process_CascadeMessage));
|
||||||
register_device_value(DeviceValueTAG::TAG_HS1 + hs, &burnWorkMin_, DeviceValueType::TIME, FL_(burnWorkMin), DeviceValueUOM::MINUTES);
|
register_device_value(DeviceValueTAG::TAG_HS1 + hs, &burnWorkMin_, DeviceValueType::TIME, FL_(burnWorkMin), DeviceValueUOM::MINUTES);
|
||||||
// selBurnpower in D2 and E4
|
// selBurnpower in D2 and E4
|
||||||
// register_telegram_type(0xD2, F("CascadePowerMessage"), false, MAKE_PF_CB(process_CascadePowerMessage));
|
// register_telegram_type(0xD2, "CascadePowerMessage", false, MAKE_PF_CB(process_CascadePowerMessage));
|
||||||
// individual Flowtemps and powervalues for each heatingsource in E4
|
// individual Flowtemps and powervalues for each heatingsource in E4
|
||||||
register_telegram_type(0xE4, F("UBAMonitorFastPlus"), false, MAKE_PF_CB(process_UBAMonitorFastPlus));
|
register_telegram_type(0xE4, "UBAMonitorFastPlus", false, MAKE_PF_CB(process_UBAMonitorFastPlus));
|
||||||
register_device_value(DeviceValueTAG::TAG_HS1 + hs, &selFlowTemp_, DeviceValueType::UINT, FL_(selFlowTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_HS1 + hs, &selFlowTemp_, DeviceValueType::UINT, FL_(selFlowTemp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_HS1 + hs, &selBurnPow_, DeviceValueType::UINT, FL_(selBurnPow), DeviceValueUOM::PERCENT);
|
register_device_value(DeviceValueTAG::TAG_HS1 + hs, &selBurnPow_, DeviceValueType::UINT, FL_(selBurnPow), DeviceValueUOM::PERCENT);
|
||||||
register_device_value(DeviceValueTAG::TAG_HS1 + hs,
|
register_device_value(DeviceValueTAG::TAG_HS1 + hs,
|
||||||
@@ -136,51 +136,51 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
|
|
||||||
// the telegram handlers...
|
// the telegram handlers...
|
||||||
// common for all boilers
|
// common for all boilers
|
||||||
register_telegram_type(0xBF, F("ErrorMessage"), false, MAKE_PF_CB(process_ErrorMessage));
|
register_telegram_type(0xBF, "ErrorMessage", false, MAKE_PF_CB(process_ErrorMessage));
|
||||||
register_telegram_type(0x10, F("UBAErrorMessage1"), false, MAKE_PF_CB(process_UBAErrorMessage));
|
register_telegram_type(0x10, "UBAErrorMessage1", false, MAKE_PF_CB(process_UBAErrorMessage));
|
||||||
register_telegram_type(0x11, F("UBAErrorMessage2"), false, MAKE_PF_CB(process_UBAErrorMessage));
|
register_telegram_type(0x11, "UBAErrorMessage2", false, MAKE_PF_CB(process_UBAErrorMessage));
|
||||||
register_telegram_type(0xC2, F("UBAErrorMessage3"), false, MAKE_PF_CB(process_UBAErrorMessage2));
|
register_telegram_type(0xC2, "UBAErrorMessage3", false, MAKE_PF_CB(process_UBAErrorMessage2));
|
||||||
register_telegram_type(0x14, F("UBATotalUptime"), true, MAKE_PF_CB(process_UBATotalUptime));
|
register_telegram_type(0x14, "UBATotalUptime", true, MAKE_PF_CB(process_UBATotalUptime));
|
||||||
register_telegram_type(0x15, F("UBAMaintenanceData"), false, MAKE_PF_CB(process_UBAMaintenanceData));
|
register_telegram_type(0x15, "UBAMaintenanceData", false, MAKE_PF_CB(process_UBAMaintenanceData));
|
||||||
register_telegram_type(0x1C, F("UBAMaintenanceStatus"), false, MAKE_PF_CB(process_UBAMaintenanceStatus));
|
register_telegram_type(0x1C, "UBAMaintenanceStatus", false, MAKE_PF_CB(process_UBAMaintenanceStatus));
|
||||||
|
|
||||||
// EMS1.0 and maybe EMS+?
|
// EMS1.0 and maybe EMS+?
|
||||||
register_telegram_type(0x18, F("UBAMonitorFast"), false, MAKE_PF_CB(process_UBAMonitorFast));
|
register_telegram_type(0x18, "UBAMonitorFast", false, MAKE_PF_CB(process_UBAMonitorFast));
|
||||||
register_telegram_type(0x19, F("UBAMonitorSlow"), false, MAKE_PF_CB(process_UBAMonitorSlow));
|
register_telegram_type(0x19, "UBAMonitorSlow", false, MAKE_PF_CB(process_UBAMonitorSlow));
|
||||||
register_telegram_type(0x1A, F("UBASetPoints"), false, MAKE_PF_CB(process_UBASetPoints));
|
register_telegram_type(0x1A, "UBASetPoints", false, MAKE_PF_CB(process_UBASetPoints));
|
||||||
register_telegram_type(0x35, F("UBAFlags"), false, MAKE_PF_CB(process_UBAFlags));
|
register_telegram_type(0x35, "UBAFlags", false, MAKE_PF_CB(process_UBAFlags));
|
||||||
|
|
||||||
// only EMS 1.0
|
// only EMS 1.0
|
||||||
register_telegram_type(0x16, F("UBAParameters"), true, MAKE_PF_CB(process_UBAParameters));
|
register_telegram_type(0x16, "UBAParameters", true, MAKE_PF_CB(process_UBAParameters));
|
||||||
register_telegram_type(0x33, F("UBAParameterWW"), true, MAKE_PF_CB(process_UBAParameterWW));
|
register_telegram_type(0x33, "UBAParameterWW", true, MAKE_PF_CB(process_UBAParameterWW));
|
||||||
register_telegram_type(0x34, F("UBAMonitorWW"), false, MAKE_PF_CB(process_UBAMonitorWW));
|
register_telegram_type(0x34, "UBAMonitorWW", false, MAKE_PF_CB(process_UBAMonitorWW));
|
||||||
|
|
||||||
// not ems1.0, but HT3
|
// not ems1.0, but HT3
|
||||||
if (model() != EMSdevice::EMS_DEVICE_FLAG_EMS) {
|
if (model() != EMSdevice::EMS_DEVICE_FLAG_EMS) {
|
||||||
register_telegram_type(0x26, F("UBASettingsWW"), true, MAKE_PF_CB(process_UBASettingsWW));
|
register_telegram_type(0x26, "UBASettingsWW", true, MAKE_PF_CB(process_UBASettingsWW));
|
||||||
register_telegram_type(0x2A, F("MC110Status"), false, MAKE_PF_CB(process_MC110Status));
|
register_telegram_type(0x2A, "MC110Status", false, MAKE_PF_CB(process_MC110Status));
|
||||||
}
|
}
|
||||||
|
|
||||||
// only EMS+
|
// only EMS+
|
||||||
if (model() != EMSdevice::EMS_DEVICE_FLAG_EMS && model() != EMSdevice::EMS_DEVICE_FLAG_HT3 && model() != EMSdevice::EMS_DEVICE_FLAG_HYBRID) {
|
if (model() != EMSdevice::EMS_DEVICE_FLAG_EMS && model() != EMSdevice::EMS_DEVICE_FLAG_HT3 && model() != EMSdevice::EMS_DEVICE_FLAG_HYBRID) {
|
||||||
register_telegram_type(0xD1, F("UBAOutdoorTemp"), false, MAKE_PF_CB(process_UBAOutdoorTemp));
|
register_telegram_type(0xD1, "UBAOutdoorTemp", false, MAKE_PF_CB(process_UBAOutdoorTemp));
|
||||||
register_telegram_type(0xE3, F("UBAMonitorSlowPlus2"), false, MAKE_PF_CB(process_UBAMonitorSlowPlus2));
|
register_telegram_type(0xE3, "UBAMonitorSlowPlus2", false, MAKE_PF_CB(process_UBAMonitorSlowPlus2));
|
||||||
register_telegram_type(0xE4, F("UBAMonitorFastPlus"), false, MAKE_PF_CB(process_UBAMonitorFastPlus));
|
register_telegram_type(0xE4, "UBAMonitorFastPlus", false, MAKE_PF_CB(process_UBAMonitorFastPlus));
|
||||||
register_telegram_type(0xE5, F("UBAMonitorSlowPlus"), false, MAKE_PF_CB(process_UBAMonitorSlowPlus));
|
register_telegram_type(0xE5, "UBAMonitorSlowPlus", false, MAKE_PF_CB(process_UBAMonitorSlowPlus));
|
||||||
register_telegram_type(0xE6, F("UBAParametersPlus"), true, MAKE_PF_CB(process_UBAParametersPlus));
|
register_telegram_type(0xE6, "UBAParametersPlus", true, MAKE_PF_CB(process_UBAParametersPlus));
|
||||||
register_telegram_type(0xE9, F("UBAMonitorWWPlus"), false, MAKE_PF_CB(process_UBAMonitorWWPlus));
|
register_telegram_type(0xE9, "UBAMonitorWWPlus", false, MAKE_PF_CB(process_UBAMonitorWWPlus));
|
||||||
register_telegram_type(0xEA, F("UBAParameterWWPlus"), true, MAKE_PF_CB(process_UBAParameterWWPlus));
|
register_telegram_type(0xEA, "UBAParameterWWPlus", true, MAKE_PF_CB(process_UBAParameterWWPlus));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model() == EMSdevice::EMS_DEVICE_FLAG_HEATPUMP) {
|
if (model() == EMSdevice::EMS_DEVICE_FLAG_HEATPUMP) {
|
||||||
register_telegram_type(0x494, F("UBAEnergySupplied"), false, MAKE_PF_CB(process_UBAEnergySupplied));
|
register_telegram_type(0x494, "UBAEnergySupplied", false, MAKE_PF_CB(process_UBAEnergySupplied));
|
||||||
register_telegram_type(0x495, F("UBAInformation"), false, MAKE_PF_CB(process_UBAInformation));
|
register_telegram_type(0x495, "UBAInformation", false, MAKE_PF_CB(process_UBAInformation));
|
||||||
register_telegram_type(0x48D, F("HpPower"), true, MAKE_PF_CB(process_HpPower));
|
register_telegram_type(0x48D, "HpPower", true, MAKE_PF_CB(process_HpPower));
|
||||||
register_telegram_type(0x48F, F("HpOutdoor"), false, MAKE_PF_CB(process_HpOutdoor));
|
register_telegram_type(0x48F, "HpOutdoor", false, MAKE_PF_CB(process_HpOutdoor));
|
||||||
register_telegram_type(0x48A, F("HpPool"), true, MAKE_PF_CB(process_HpPool));
|
register_telegram_type(0x48A, "HpPool", true, MAKE_PF_CB(process_HpPool));
|
||||||
register_telegram_type(0x4A2, F("HpInput"), false, MAKE_PF_CB(process_HpInput));
|
register_telegram_type(0x4A2, "HpInput", false, MAKE_PF_CB(process_HpInput));
|
||||||
register_telegram_type(0x486, F("HpInConfig"), false, MAKE_PF_CB(process_HpInConfig));
|
register_telegram_type(0x486, "HpInConfig", false, MAKE_PF_CB(process_HpInConfig));
|
||||||
register_telegram_type(0x492, F("HpHeaterConfig"), false, MAKE_PF_CB(process_HpHeaterConfig));
|
register_telegram_type(0x492, "HpHeaterConfig", false, MAKE_PF_CB(process_HpHeaterConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -189,7 +189,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
* enable settings here if no thermostat is used in system
|
* enable settings here if no thermostat is used in system
|
||||||
*
|
*
|
||||||
if (model() == EMSdevice::EMS_DEVICE_FLAG_HYBRID) {
|
if (model() == EMSdevice::EMS_DEVICE_FLAG_HYBRID) {
|
||||||
register_telegram_type(0xBB, F("HybridHp"), true, MAKE_PF_CB(process_HybridHp));
|
register_telegram_type(0xBB, "HybridHp", true, MAKE_PF_CB(process_HybridHp));
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -2178,11 +2178,11 @@ bool Boiler::set_ww_circulation_mode(const char * value, const int8_t id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (v < 7) {
|
if (v < 7) {
|
||||||
// LOG_INFO(F("Setting dhw circulation mode %dx3min"), v);
|
// LOG_INFO("Setting dhw circulation mode %dx3min", v);
|
||||||
} else if (v == 7) {
|
} else if (v == 7) {
|
||||||
// LOG_INFO(F("Setting dhw circulation mode continuous"));
|
// LOG_INFO("Setting dhw circulation mode continuous");
|
||||||
} else {
|
} else {
|
||||||
// LOG_WARNING(F("Set dhw circulation mode: Invalid value"));
|
// LOG_WARNING("Set dhw circulation mode: Invalid value");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2206,12 +2206,12 @@ bool Boiler::set_reset(const char * value, const int8_t id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (num == 1) {
|
if (num == 1) {
|
||||||
// LOG_INFO(F("Reset boiler maintenance message"));
|
// LOG_INFO("Reset boiler maintenance message");
|
||||||
write_command(0x05, 0x08, 0xFF, 0x1C);
|
write_command(0x05, 0x08, 0xFF, 0x1C);
|
||||||
has_update(&reset_);
|
has_update(&reset_);
|
||||||
return true;
|
return true;
|
||||||
} else if (num == 2) {
|
} else if (num == 2) {
|
||||||
// LOG_INFO(F("Reset boiler error message"));
|
// LOG_INFO("Reset boiler error message");
|
||||||
write_command(0x05, 0x00, 0x5A); // error reset
|
write_command(0x05, 0x00, 0x5A); // error reset
|
||||||
has_update(&reset_);
|
has_update(&reset_);
|
||||||
return true;
|
return true;
|
||||||
@@ -2227,8 +2227,8 @@ bool Boiler::set_maintenance(const char * value, const int8_t id) {
|
|||||||
|
|
||||||
std::string s;
|
std::string s;
|
||||||
if (Helpers::value2string(value, s)) {
|
if (Helpers::value2string(value, s)) {
|
||||||
if (s == Helpers::translated_word(FL_(reset))) {
|
if (s == std::string(Helpers::translated_word(FL_(reset)))) {
|
||||||
// LOG_INFO(F("Reset boiler maintenance message"));
|
// LOG_INFO("Reset boiler maintenance message");
|
||||||
write_command(0x05, 0x08, 0xFF, 0x1C);
|
write_command(0x05, 0x08, 0xFF, 0x1C);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2239,11 +2239,11 @@ bool Boiler::set_maintenance(const char * value, const int8_t id) {
|
|||||||
uint8_t month = (value[3] - '0') * 10 + (value[4] - '0');
|
uint8_t month = (value[3] - '0') * 10 + (value[4] - '0');
|
||||||
uint8_t year = (uint8_t)(Helpers::atoint(&value[6]) - 2000);
|
uint8_t year = (uint8_t)(Helpers::atoint(&value[6]) - 2000);
|
||||||
if (day > 0 && day < 32 && month > 0 && month < 13) {
|
if (day > 0 && day < 32 && month > 0 && month < 13) {
|
||||||
LOG_INFO(F("Setting maintenance date to %02d.%02d.%04d"), day, month, year + 2000);
|
LOG_INFO("Setting maintenance date to %02d.%02d.%04d", day, month, year + 2000);
|
||||||
uint8_t data[5] = {2, (uint8_t)(maintenanceTime_ / 100), day, month, year};
|
uint8_t data[5] = {2, (uint8_t)(maintenanceTime_ / 100), day, month, year};
|
||||||
write_command(0x15, 0, data, 5, 0x15);
|
write_command(0x15, 0, data, 5, 0x15);
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING(F("Setting maintenance: wrong format %d.%d.%d"), day, month, year + 2000);
|
LOG_WARNING("Setting maintenance: wrong format %d.%d.%d", day, month, year + 2000);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -2252,7 +2252,7 @@ bool Boiler::set_maintenance(const char * value, const int8_t id) {
|
|||||||
int hrs;
|
int hrs;
|
||||||
if (Helpers::value2number(value, hrs)) {
|
if (Helpers::value2number(value, hrs)) {
|
||||||
if (hrs > 99 && hrs < 25600) {
|
if (hrs > 99 && hrs < 25600) {
|
||||||
LOG_INFO(F("Setting maintenance time %d hours"), hrs);
|
LOG_INFO("Setting maintenance time %d hours", hrs);
|
||||||
uint8_t data[2] = {1, (uint8_t)(hrs / 100)};
|
uint8_t data[2] = {1, (uint8_t)(hrs / 100)};
|
||||||
write_command(0x15, 0, data, 2, 0x15);
|
write_command(0x15, 0, data, 2, 0x15);
|
||||||
return true;
|
return true;
|
||||||
@@ -2261,12 +2261,12 @@ bool Boiler::set_maintenance(const char * value, const int8_t id) {
|
|||||||
|
|
||||||
uint8_t num;
|
uint8_t num;
|
||||||
if (Helpers::value2enum(value, num, FL_(enum_off_time_date_manual))) {
|
if (Helpers::value2enum(value, num, FL_(enum_off_time_date_manual))) {
|
||||||
LOG_INFO(F("Setting maintenance type to %s"), value);
|
LOG_INFO("Setting maintenance type to %s", value);
|
||||||
write_command(0x15, 0, num, 0x15);
|
write_command(0x15, 0, num, 0x15);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_WARNING(F("Setting maintenance: wrong format"));
|
LOG_WARNING("Setting maintenance: wrong format");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//maintenance
|
//maintenance
|
||||||
@@ -2274,13 +2274,13 @@ bool Boiler::set_maintenancetime(const char * value, const int8_t id) {
|
|||||||
int hrs;
|
int hrs;
|
||||||
if (Helpers::value2number(value, hrs)) {
|
if (Helpers::value2number(value, hrs)) {
|
||||||
if (hrs > 99 && hrs < 25600) {
|
if (hrs > 99 && hrs < 25600) {
|
||||||
LOG_INFO(F("Setting maintenance time %d hours"), hrs);
|
LOG_INFO("Setting maintenance time %d hours", hrs);
|
||||||
uint8_t data[2] = {1, (uint8_t)(hrs / 100)};
|
uint8_t data[2] = {1, (uint8_t)(hrs / 100)};
|
||||||
write_command(0x15, 0, data, 2, 0x15);
|
write_command(0x15, 0, data, 2, 0x15);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG_WARNING(F("Setting maintenance: wrong format"));
|
LOG_WARNING("Setting maintenance: wrong format");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2291,17 +2291,17 @@ bool Boiler::set_maintenancedate(const char * value, const int8_t id) {
|
|||||||
uint8_t month = (value[3] - '0') * 10 + (value[4] - '0');
|
uint8_t month = (value[3] - '0') * 10 + (value[4] - '0');
|
||||||
uint8_t year = (uint8_t)(Helpers::atoint(&value[6]) - 2000);
|
uint8_t year = (uint8_t)(Helpers::atoint(&value[6]) - 2000);
|
||||||
if (day > 0 && day < 32 && month > 0 && month < 13) {
|
if (day > 0 && day < 32 && month > 0 && month < 13) {
|
||||||
LOG_INFO(F("Setting maintenance date to %02d.%02d.%04d"), day, month, year + 2000);
|
LOG_INFO("Setting maintenance date to %02d.%02d.%04d", day, month, year + 2000);
|
||||||
uint8_t data[5] = {2, (uint8_t)(maintenanceTime_ / 100), day, month, year};
|
uint8_t data[5] = {2, (uint8_t)(maintenanceTime_ / 100), day, month, year};
|
||||||
write_command(0x15, 0, data, 5, 0x15);
|
write_command(0x15, 0, data, 5, 0x15);
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING(F("Setting maintenance: wrong format %d.%d.%d"), day, month, year + 2000);
|
LOG_WARNING("Setting maintenance: wrong format %d.%d.%d", day, month, year + 2000);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_WARNING(F("Setting maintenance: wrong format"));
|
LOG_WARNING("Setting maintenance: wrong format");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2312,7 +2312,7 @@ bool Boiler::set_pool_temp(const char * value, const int8_t id) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint8_t v2 = ((v * 2) + 0.5);
|
uint8_t v2 = ((v * 2) + 0.5);
|
||||||
// LOG_INFO(F("Setting pool temperature to %d.%d C"), v2 >> 1, (v2 & 0x01) * 5);
|
// LOG_INFO("Setting pool temperature to %d.%d C", v2 >> 1, (v2 & 0x01) * 5);
|
||||||
write_command(0x48A, 1, v2, 0x48A);
|
write_command(0x48A, 1, v2, 0x48A);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace emsesp {
|
|||||||
|
|
||||||
class Boiler : public EMSdevice {
|
class Boiler : public EMSdevice {
|
||||||
public:
|
public:
|
||||||
Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand);
|
Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static uuid::log::Logger logger_;
|
static uuid::log::Logger logger_;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace emsesp {
|
|||||||
|
|
||||||
REGISTER_FACTORY(Connect, EMSdevice::DeviceType::CONNECT);
|
REGISTER_FACTORY(Connect, EMSdevice::DeviceType::CONNECT);
|
||||||
|
|
||||||
Connect::Connect(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
Connect::Connect(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace emsesp {
|
|||||||
|
|
||||||
class Connect : public EMSdevice {
|
class Connect : public EMSdevice {
|
||||||
public:
|
public:
|
||||||
Connect(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand);
|
Connect(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ namespace emsesp {
|
|||||||
|
|
||||||
REGISTER_FACTORY(Controller, EMSdevice::DeviceType::CONTROLLER);
|
REGISTER_FACTORY(Controller, EMSdevice::DeviceType::CONTROLLER);
|
||||||
|
|
||||||
Controller::Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
Controller::Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||||
// IVT broadcasts Thermostat time from controller (0x09) if display is off.
|
// IVT broadcasts Thermostat time from controller (0x09) if display is off.
|
||||||
if ((flags & 0x0F) == EMS_DEVICE_FLAG_IVT) {
|
if ((flags & 0x0F) == EMS_DEVICE_FLAG_IVT) {
|
||||||
register_telegram_type(0x06, F("RCTime"), false, MAKE_PF_CB(process_dateTime));
|
register_telegram_type(0x06, "RCTime", false, MAKE_PF_CB(process_dateTime));
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dateTime_, DeviceValueType::STRING, FL_(dateTime), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dateTime_, DeviceValueType::STRING, FL_(dateTime), DeviceValueUOM::NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace emsesp {
|
|||||||
|
|
||||||
class Controller : public EMSdevice {
|
class Controller : public EMSdevice {
|
||||||
public:
|
public:
|
||||||
Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand);
|
Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
|
||||||
|
|
||||||
void process_dateTime(std::shared_ptr<const Telegram> telegram);
|
void process_dateTime(std::shared_ptr<const Telegram> telegram);
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace emsesp {
|
|||||||
|
|
||||||
REGISTER_FACTORY(Gateway, EMSdevice::DeviceType::GATEWAY);
|
REGISTER_FACTORY(Gateway, EMSdevice::DeviceType::GATEWAY);
|
||||||
|
|
||||||
Gateway::Gateway(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
Gateway::Gateway(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace emsesp {
|
|||||||
|
|
||||||
class Gateway : public EMSdevice {
|
class Gateway : public EMSdevice {
|
||||||
public:
|
public:
|
||||||
Gateway(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand);
|
Gateway(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ REGISTER_FACTORY(Generic, EMSdevice::DeviceType::GENERIC);
|
|||||||
|
|
||||||
uuid::log::Logger Generic::logger_{F_(generic), uuid::log::Facility::CONSOLE};
|
uuid::log::Logger Generic::logger_{F_(generic), uuid::log::Facility::CONSOLE};
|
||||||
|
|
||||||
Generic::Generic(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
Generic::Generic(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace emsesp {
|
|||||||
|
|
||||||
class Generic : public EMSdevice {
|
class Generic : public EMSdevice {
|
||||||
public:
|
public:
|
||||||
Generic(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand);
|
Generic(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static uuid::log::Logger logger_;
|
static uuid::log::Logger logger_;
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ namespace emsesp {
|
|||||||
|
|
||||||
REGISTER_FACTORY(Heatpump, EMSdevice::DeviceType::HEATPUMP);
|
REGISTER_FACTORY(Heatpump, EMSdevice::DeviceType::HEATPUMP);
|
||||||
|
|
||||||
Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||||
// telegram handlers
|
// telegram handlers
|
||||||
register_telegram_type(0x042B, F("HP1"), false, MAKE_PF_CB(process_HPMonitor1));
|
register_telegram_type(0x042B, "HP1", false, MAKE_PF_CB(process_HPMonitor1));
|
||||||
register_telegram_type(0x047B, F("HP2"), false, MAKE_PF_CB(process_HPMonitor2));
|
register_telegram_type(0x047B, "HP2", false, MAKE_PF_CB(process_HPMonitor2));
|
||||||
|
|
||||||
// device values
|
// device values
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &airHumidity_, DeviceValueType::UINT, FL_(airHumidity), DeviceValueUOM::PERCENT);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &airHumidity_, DeviceValueType::UINT, FL_(airHumidity), DeviceValueUOM::PERCENT);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace emsesp {
|
|||||||
|
|
||||||
class Heatpump : public EMSdevice {
|
class Heatpump : public EMSdevice {
|
||||||
public:
|
public:
|
||||||
Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand);
|
Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t airHumidity_;
|
uint8_t airHumidity_;
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ REGISTER_FACTORY(Mixer, EMSdevice::DeviceType::MIXER);
|
|||||||
|
|
||||||
uuid::log::Logger Mixer::logger_{F_(mixer), uuid::log::Facility::CONSOLE};
|
uuid::log::Logger Mixer::logger_{F_(mixer), uuid::log::Facility::CONSOLE};
|
||||||
|
|
||||||
Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||||
// Pool module
|
// Pool module
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_MP) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_MP) {
|
||||||
register_telegram_type(0x5BA, F("HpPoolStatus"), true, MAKE_PF_CB(process_HpPoolStatus));
|
register_telegram_type(0x5BA, "HpPoolStatus", true, MAKE_PF_CB(process_HpPoolStatus));
|
||||||
type_ = Type::MP;
|
type_ = Type::MP;
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&poolTemp_,
|
&poolTemp_,
|
||||||
@@ -43,8 +43,8 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
// EMS+
|
// EMS+
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) {
|
||||||
if (device_id >= 0x20 && device_id <= 0x27) {
|
if (device_id >= 0x20 && device_id <= 0x27) {
|
||||||
register_telegram_type(device_id - 0x20 + 0x02D7, F("MMPLUSStatusMessage_HC"), false, MAKE_PF_CB(process_MMPLUSStatusMessage_HC));
|
register_telegram_type(device_id - 0x20 + 0x02D7, "MMPLUSStatusMessage_HC", false, MAKE_PF_CB(process_MMPLUSStatusMessage_HC));
|
||||||
// register_telegram_type(device_id - 0x20 + 0x02E1, F("MMPLUSStetMessage_HC"), true, MAKE_PF_CB(process_MMPLUSSetMessage_HC));
|
// register_telegram_type(device_id - 0x20 + 0x02E1, "MMPLUSStetMessage_HC", true, MAKE_PF_CB(process_MMPLUSSetMessage_HC));
|
||||||
type_ = Type::HC;
|
type_ = Type::HC;
|
||||||
hc_ = device_id - 0x20 + 1;
|
hc_ = device_id - 0x20 + 1;
|
||||||
uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1;
|
uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1;
|
||||||
@@ -53,9 +53,9 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
register_device_value(tag, &flowSetTemp_, DeviceValueType::UINT, FL_(flowSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flowSetTemp));
|
register_device_value(tag, &flowSetTemp_, DeviceValueType::UINT, FL_(flowSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flowSetTemp));
|
||||||
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, FL_(pumpStatus), DeviceValueUOM::NONE, MAKE_CF_CB(set_pump));
|
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, FL_(pumpStatus), DeviceValueUOM::NONE, MAKE_CF_CB(set_pump));
|
||||||
} else if (device_id >= 0x28 && device_id <= 0x29) {
|
} else if (device_id >= 0x28 && device_id <= 0x29) {
|
||||||
register_telegram_type(device_id - 0x28 + 0x0331, F("MMPLUSStatusMessage_WWC"), false, MAKE_PF_CB(process_MMPLUSStatusMessage_WWC));
|
register_telegram_type(device_id - 0x28 + 0x0331, "MMPLUSStatusMessage_WWC", false, MAKE_PF_CB(process_MMPLUSStatusMessage_WWC));
|
||||||
register_telegram_type(device_id - 0x28 + 0x0313, F("MMPLUSConfigMessage_WWC"), true, MAKE_PF_CB(process_MMPLUSConfigMessage_WWC));
|
register_telegram_type(device_id - 0x28 + 0x0313, "MMPLUSConfigMessage_WWC", true, MAKE_PF_CB(process_MMPLUSConfigMessage_WWC));
|
||||||
// register_telegram_type(device_id - 0x28 + 0x033B, F("MMPLUSSetMessage_WWC"), true, MAKE_PF_CB(process_MMPLUSSetMessage_WWC));
|
// register_telegram_type(device_id - 0x28 + 0x033B, "MMPLUSSetMessage_WWC", true, MAKE_PF_CB(process_MMPLUSSetMessage_WWC));
|
||||||
type_ = Type::WWC;
|
type_ = Type::WWC;
|
||||||
hc_ = device_id - 0x28 + 1;
|
hc_ = device_id - 0x28 + 1;
|
||||||
uint8_t tag = DeviceValueTAG::TAG_WWC1 + hc_ - 1;
|
uint8_t tag = DeviceValueTAG::TAG_WWC1 + hc_ - 1;
|
||||||
@@ -85,9 +85,9 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
|
|
||||||
// EMS 1.0
|
// EMS 1.0
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_MM10) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_MM10) {
|
||||||
register_telegram_type(0x00AA, F("MMConfigMessage"), true, MAKE_PF_CB(process_MMConfigMessage));
|
register_telegram_type(0x00AA, "MMConfigMessage", true, MAKE_PF_CB(process_MMConfigMessage));
|
||||||
register_telegram_type(0x00AB, F("MMStatusMessage"), false, MAKE_PF_CB(process_MMStatusMessage));
|
register_telegram_type(0x00AB, "MMStatusMessage", false, MAKE_PF_CB(process_MMStatusMessage));
|
||||||
register_telegram_type(0x00AC, F("MMSetMessage"), false, MAKE_PF_CB(process_MMSetMessage));
|
register_telegram_type(0x00AC, "MMSetMessage", false, MAKE_PF_CB(process_MMSetMessage));
|
||||||
type_ = Type::HC;
|
type_ = Type::HC;
|
||||||
hc_ = device_id - 0x20 + 1;
|
hc_ = device_id - 0x20 + 1;
|
||||||
uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1;
|
uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1;
|
||||||
@@ -110,10 +110,10 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
// HT3
|
// HT3
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_IPM) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_IPM) {
|
||||||
if (device_id >= 0x40) { // special DHW pos 10
|
if (device_id >= 0x40) { // special DHW pos 10
|
||||||
register_telegram_type(0x34, F("UBAMonitorWW"), false, MAKE_PF_CB(process_IPMMonitorWW));
|
register_telegram_type(0x34, "UBAMonitorWW", false, MAKE_PF_CB(process_IPMMonitorWW));
|
||||||
register_telegram_type(0x1E, F("HydrTemp"), false, MAKE_PF_CB(process_IPMHydrTemp));
|
register_telegram_type(0x1E, "HydrTemp", false, MAKE_PF_CB(process_IPMHydrTemp));
|
||||||
register_telegram_type(0x33, F("UBAParameterWW"), true, MAKE_PF_CB(process_IPMParameterWW));
|
register_telegram_type(0x33, "UBAParameterWW", true, MAKE_PF_CB(process_IPMParameterWW));
|
||||||
// register_telegram_type(0x10D, F("wwNTCStatus"), false, MAKE_PF_CB(process_wwNTCStatus));
|
// register_telegram_type(0x10D, "wwNTCStatus", false, MAKE_PF_CB(process_wwNTCStatus));
|
||||||
type_ = Type::WWC;
|
type_ = Type::WWC;
|
||||||
hc_ = device_id - 0x40 + 1;
|
hc_ = device_id - 0x40 + 1;
|
||||||
uint8_t tag = DeviceValueTAG::TAG_WWC9 + hc_ - 1;
|
uint8_t tag = DeviceValueTAG::TAG_WWC9 + hc_ - 1;
|
||||||
@@ -139,9 +139,9 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
MAKE_CF_CB(set_wwCircPump));
|
MAKE_CF_CB(set_wwCircPump));
|
||||||
register_device_value(tag, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCircMode));
|
register_device_value(tag, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCircMode));
|
||||||
} else {
|
} else {
|
||||||
register_telegram_type(0x010C, F("IPMStatusMessage"), false, MAKE_PF_CB(process_IPMStatusMessage));
|
register_telegram_type(0x010C, "IPMStatusMessage", false, MAKE_PF_CB(process_IPMStatusMessage));
|
||||||
register_telegram_type(0x011E, F("IPMTempMessage"), false, MAKE_PF_CB(process_IPMTempMessage));
|
register_telegram_type(0x011E, "IPMTempMessage", false, MAKE_PF_CB(process_IPMTempMessage));
|
||||||
// register_telegram_type(0x0123, F("IPMSetMessage"), false, MAKE_PF_CB(process_IPMSetMessage));
|
// register_telegram_type(0x0123, "IPMSetMessage", false, MAKE_PF_CB(process_IPMSetMessage));
|
||||||
type_ = Type::HC;
|
type_ = Type::HC;
|
||||||
hc_ = device_id - 0x20 + 1;
|
hc_ = device_id - 0x20 + 1;
|
||||||
uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1;
|
uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace emsesp {
|
|||||||
|
|
||||||
class Mixer : public EMSdevice {
|
class Mixer : public EMSdevice {
|
||||||
public:
|
public:
|
||||||
Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand);
|
Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static uuid::log::Logger logger_;
|
static uuid::log::Logger logger_;
|
||||||
|
|||||||
@@ -24,48 +24,48 @@ REGISTER_FACTORY(Solar, EMSdevice::DeviceType::SOLAR);
|
|||||||
|
|
||||||
uuid::log::Logger Solar::logger_{F_(solar), uuid::log::Facility::CONSOLE};
|
uuid::log::Logger Solar::logger_{F_(solar), uuid::log::Facility::CONSOLE};
|
||||||
|
|
||||||
Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||||
// telegram handlers
|
// telegram handlers
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM10) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM10) {
|
||||||
register_telegram_type(0x97, F("SM10Monitor"), false, MAKE_PF_CB(process_SM10Monitor));
|
register_telegram_type(0x97, "SM10Monitor", false, MAKE_PF_CB(process_SM10Monitor));
|
||||||
register_telegram_type(0x96, F("SM10Config"), true, MAKE_PF_CB(process_SM10Config));
|
register_telegram_type(0x96, "SM10Config", true, MAKE_PF_CB(process_SM10Config));
|
||||||
EMSESP::send_read_request(0x97, device_id);
|
EMSESP::send_read_request(0x97, device_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM100) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM100) {
|
||||||
if (device_id == 0x2A) { // SM100 DHW
|
if (device_id == 0x2A) { // SM100 DHW
|
||||||
register_telegram_type(0x07D6, F("SM100wwTemperature"), false, MAKE_PF_CB(process_SM100wwTemperature));
|
register_telegram_type(0x07D6, "SM100wwTemperature", false, MAKE_PF_CB(process_SM100wwTemperature));
|
||||||
register_telegram_type(0x07AA, F("SM100wwStatus"), false, MAKE_PF_CB(process_SM100wwStatus));
|
register_telegram_type(0x07AA, "SM100wwStatus", false, MAKE_PF_CB(process_SM100wwStatus));
|
||||||
register_telegram_type(0x07AB, F("SM100wwCommand"), false, MAKE_PF_CB(process_SM100wwCommand));
|
register_telegram_type(0x07AB, "SM100wwCommand", false, MAKE_PF_CB(process_SM100wwCommand));
|
||||||
register_telegram_type(0x07A5, F("SM100wwCirc"), true, MAKE_PF_CB(process_SM100wwCirc));
|
register_telegram_type(0x07A5, "SM100wwCirc", true, MAKE_PF_CB(process_SM100wwCirc));
|
||||||
register_telegram_type(0x07A6, F("SM100wwParam"), true, MAKE_PF_CB(process_SM100wwParam));
|
register_telegram_type(0x07A6, "SM100wwParam", true, MAKE_PF_CB(process_SM100wwParam));
|
||||||
register_telegram_type(0x07AE, F("SM100wwKeepWarm"), true, MAKE_PF_CB(process_SM100wwKeepWarm));
|
register_telegram_type(0x07AE, "SM100wwKeepWarm", true, MAKE_PF_CB(process_SM100wwKeepWarm));
|
||||||
register_telegram_type(0x07E0, F("SM100wwStatus2"), true, MAKE_PF_CB(process_SM100wwStatus2));
|
register_telegram_type(0x07E0, "SM100wwStatus2", true, MAKE_PF_CB(process_SM100wwStatus2));
|
||||||
} else {
|
} else {
|
||||||
// F9 is not a telegram type, it's a flag for configure
|
// F9 is not a telegram type, it's a flag for configure
|
||||||
// register_telegram_type(0xF9, F("ParamCfg"), false, MAKE_PF_CB(process_SM100ParamCfg));
|
// register_telegram_type(0xF9, "ParamCfg", false, MAKE_PF_CB(process_SM100ParamCfg));
|
||||||
register_telegram_type(0x0358, F("SM100SystemConfig"), true, MAKE_PF_CB(process_SM100SystemConfig));
|
register_telegram_type(0x0358, "SM100SystemConfig", true, MAKE_PF_CB(process_SM100SystemConfig));
|
||||||
register_telegram_type(0x035A, F("SM100CircuitConfig"), true, MAKE_PF_CB(process_SM100CircuitConfig));
|
register_telegram_type(0x035A, "SM100CircuitConfig", true, MAKE_PF_CB(process_SM100CircuitConfig));
|
||||||
register_telegram_type(0x035D, F("SM100Circuit2Config"), true, MAKE_PF_CB(process_SM100Circuit2Config));
|
register_telegram_type(0x035D, "SM100Circuit2Config", true, MAKE_PF_CB(process_SM100Circuit2Config));
|
||||||
register_telegram_type(0x0362, F("SM100Monitor"), false, MAKE_PF_CB(process_SM100Monitor));
|
register_telegram_type(0x0362, "SM100Monitor", false, MAKE_PF_CB(process_SM100Monitor));
|
||||||
register_telegram_type(0x0363, F("SM100Monitor2"), false, MAKE_PF_CB(process_SM100Monitor2));
|
register_telegram_type(0x0363, "SM100Monitor2", false, MAKE_PF_CB(process_SM100Monitor2));
|
||||||
register_telegram_type(0x0366, F("SM100Config"), false, MAKE_PF_CB(process_SM100Config));
|
register_telegram_type(0x0366, "SM100Config", false, MAKE_PF_CB(process_SM100Config));
|
||||||
register_telegram_type(0x0364, F("SM100Status"), false, MAKE_PF_CB(process_SM100Status));
|
register_telegram_type(0x0364, "SM100Status", false, MAKE_PF_CB(process_SM100Status));
|
||||||
register_telegram_type(0x036A, F("SM100Status2"), false, MAKE_PF_CB(process_SM100Status2));
|
register_telegram_type(0x036A, "SM100Status2", false, MAKE_PF_CB(process_SM100Status2));
|
||||||
register_telegram_type(0x0380, F("SM100CollectorConfig"), true, MAKE_PF_CB(process_SM100CollectorConfig));
|
register_telegram_type(0x0380, "SM100CollectorConfig", true, MAKE_PF_CB(process_SM100CollectorConfig));
|
||||||
register_telegram_type(0x038E, F("SM100Energy"), true, MAKE_PF_CB(process_SM100Energy));
|
register_telegram_type(0x038E, "SM100Energy", true, MAKE_PF_CB(process_SM100Energy));
|
||||||
register_telegram_type(0x0391, F("SM100Time"), true, MAKE_PF_CB(process_SM100Time));
|
register_telegram_type(0x0391, "SM100Time", true, MAKE_PF_CB(process_SM100Time));
|
||||||
register_telegram_type(0x035F, F("SM100Config1"), true, MAKE_PF_CB(process_SM100Config1));
|
register_telegram_type(0x035F, "SM100Config1", true, MAKE_PF_CB(process_SM100Config1));
|
||||||
register_telegram_type(0x035C, F("SM100HeatAssist"), true, MAKE_PF_CB(process_SM100HeatAssist));
|
register_telegram_type(0x035C, "SM100HeatAssist", true, MAKE_PF_CB(process_SM100HeatAssist));
|
||||||
register_telegram_type(0x0361, F("SM100Differential"), true, MAKE_PF_CB(process_SM100Differential));
|
register_telegram_type(0x0361, "SM100Differential", true, MAKE_PF_CB(process_SM100Differential));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_ISM) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_ISM) {
|
||||||
register_telegram_type(0x0103, F("ISM1StatusMessage"), true, MAKE_PF_CB(process_ISM1StatusMessage));
|
register_telegram_type(0x0103, "ISM1StatusMessage", true, MAKE_PF_CB(process_ISM1StatusMessage));
|
||||||
register_telegram_type(0x0101, F("ISM1Set"), true, MAKE_PF_CB(process_ISM1Set));
|
register_telegram_type(0x0101, "ISM1Set", true, MAKE_PF_CB(process_ISM1Set));
|
||||||
register_telegram_type(0x0104, F("ISM2StatusMessage"), false, MAKE_PF_CB(process_ISM2StatusMessage));
|
register_telegram_type(0x0104, "ISM2StatusMessage", false, MAKE_PF_CB(process_ISM2StatusMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
// device values...
|
// device values...
|
||||||
@@ -664,7 +664,7 @@ void Solar::process_SM100ParamCfg(std::shared_ptr<const Telegram> telegram) {
|
|||||||
telegram->read_value(max, 13);
|
telegram->read_value(max, 13);
|
||||||
telegram->read_value(cur, 17);
|
telegram->read_value(cur, 17);
|
||||||
|
|
||||||
// LOG_DEBUG(F("SM100ParamCfg param=0x%04X, offset=%d, min=%d, default=%d, max=%d, current=%d"), t_id, of, min, def, max, cur));
|
// LOG_DEBUG("SM100ParamCfg param=0x%04X, offset=%d, min=%d, default=%d, max=%d, current=%d", t_id, of, min, def, max, cur));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace emsesp {
|
|||||||
|
|
||||||
class Solar : public EMSdevice {
|
class Solar : public EMSdevice {
|
||||||
public:
|
public:
|
||||||
Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand);
|
Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static uuid::log::Logger logger_;
|
static uuid::log::Logger logger_;
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ namespace emsesp {
|
|||||||
|
|
||||||
REGISTER_FACTORY(Switch, EMSdevice::DeviceType::SWITCH);
|
REGISTER_FACTORY(Switch, EMSdevice::DeviceType::SWITCH);
|
||||||
|
|
||||||
Switch::Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
Switch::Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||||
// WM10 module, device_id 0x11
|
// WM10 module, device_id 0x11
|
||||||
register_telegram_type(0x9C, F("WM10MonitorMessage"), false, MAKE_PF_CB(process_WM10MonitorMessage));
|
register_telegram_type(0x9C, "WM10MonitorMessage", false, MAKE_PF_CB(process_WM10MonitorMessage));
|
||||||
register_telegram_type(0x9D, F("WM10SetMessage"), false, MAKE_PF_CB(process_WM10SetMessage));
|
register_telegram_type(0x9D, "WM10SetMessage", false, MAKE_PF_CB(process_WM10SetMessage));
|
||||||
register_telegram_type(0x1E, F("WM10TempMessage"), false, MAKE_PF_CB(process_WM10TempMessage));
|
register_telegram_type(0x1E, "WM10TempMessage", false, MAKE_PF_CB(process_WM10TempMessage));
|
||||||
|
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &activated_, DeviceValueType::BOOL, FL_(activated), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &activated_, DeviceValueType::BOOL, FL_(activated), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace emsesp {
|
|||||||
|
|
||||||
class Switch : public EMSdevice {
|
class Switch : public EMSdevice {
|
||||||
public:
|
public:
|
||||||
Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand);
|
Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void process_WM10SetMessage(std::shared_ptr<const Telegram> telegram);
|
void process_WM10SetMessage(std::shared_ptr<const Telegram> telegram);
|
||||||
|
|||||||
@@ -24,37 +24,37 @@ REGISTER_FACTORY(Thermostat, EMSdevice::DeviceType::THERMOSTAT);
|
|||||||
|
|
||||||
uuid::log::Logger Thermostat::logger_{F_(thermostat), uuid::log::Facility::CONSOLE};
|
uuid::log::Logger Thermostat::logger_{F_(thermostat), uuid::log::Facility::CONSOLE};
|
||||||
|
|
||||||
Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||||
uint8_t model = this->model();
|
uint8_t model = this->model();
|
||||||
|
|
||||||
// RF remote sensor seen at 0x40, maybe this is also for different hc with id 0x40 - 0x47? emsesp.cpp maps only 0x40
|
// RF remote sensor seen at 0x40, maybe this is also for different hc with id 0x40 - 0x47? emsesp.cpp maps only 0x40
|
||||||
if (device_id >= 0x40 && device_id <= 0x47) {
|
if (device_id >= 0x40 && device_id <= 0x47) {
|
||||||
register_telegram_type(0x0435, F("RFTemp"), false, MAKE_PF_CB(process_RemoteTemp));
|
register_telegram_type(0x0435, "RFTemp", false, MAKE_PF_CB(process_RemoteTemp));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// remote thermostats with humidity: RC100H remote
|
// remote thermostats with humidity: RC100H remote
|
||||||
if (device_id >= 0x38 && device_id <= 0x3F) {
|
if (device_id >= 0x38 && device_id <= 0x3F) {
|
||||||
register_telegram_type(0x042B, F("RemoteTemp"), false, MAKE_PF_CB(process_RemoteTemp));
|
register_telegram_type(0x042B, "RemoteTemp", false, MAKE_PF_CB(process_RemoteTemp));
|
||||||
register_telegram_type(0x047B, F("RemoteHumidity"), false, MAKE_PF_CB(process_RemoteHumidity));
|
register_telegram_type(0x047B, "RemoteHumidity", false, MAKE_PF_CB(process_RemoteHumidity));
|
||||||
register_telegram_type(0x0273, F("RemoteCorrection"), true, MAKE_PF_CB(process_RemoteCorrection));
|
register_telegram_type(0x0273, "RemoteCorrection", true, MAKE_PF_CB(process_RemoteCorrection));
|
||||||
register_device_values(); // register device values for common values (not heating circuit)
|
register_device_values(); // register device values for common values (not heating circuit)
|
||||||
return; // no values to add
|
return; // no values to add
|
||||||
}
|
}
|
||||||
|
|
||||||
// common telegram handlers
|
// common telegram handlers
|
||||||
register_telegram_type(EMS_TYPE_RCOutdoorTemp, F("RCOutdoorTemp"), false, MAKE_PF_CB(process_RCOutdoorTemp));
|
register_telegram_type(EMS_TYPE_RCOutdoorTemp, "RCOutdoorTemp", false, MAKE_PF_CB(process_RCOutdoorTemp));
|
||||||
register_telegram_type(EMS_TYPE_RCTime, F("RCTime"), false, MAKE_PF_CB(process_RCTime));
|
register_telegram_type(EMS_TYPE_RCTime, "RCTime", false, MAKE_PF_CB(process_RCTime));
|
||||||
register_telegram_type(0xA2, F("RCError"), false, MAKE_PF_CB(process_RCError));
|
register_telegram_type(0xA2, "RCError", false, MAKE_PF_CB(process_RCError));
|
||||||
register_telegram_type(0x12, F("RCErrorMessage"), false, MAKE_PF_CB(process_RCErrorMessage));
|
register_telegram_type(0x12, "RCErrorMessage", false, MAKE_PF_CB(process_RCErrorMessage));
|
||||||
register_telegram_type(0x13, F("RCErrorMessage2"), false, MAKE_PF_CB(process_RCErrorMessage));
|
register_telegram_type(0x13, "RCErrorMessage2", false, MAKE_PF_CB(process_RCErrorMessage));
|
||||||
// RC10
|
// RC10
|
||||||
if (model == EMSdevice::EMS_DEVICE_FLAG_RC10) {
|
if (model == EMSdevice::EMS_DEVICE_FLAG_RC10) {
|
||||||
monitor_typeids = {0xB1};
|
monitor_typeids = {0xB1};
|
||||||
set_typeids = {0xB0};
|
set_typeids = {0xB0};
|
||||||
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
||||||
register_telegram_type(monitor_typeids[i], F("RC10Monitor"), false, MAKE_PF_CB(process_RC10Monitor));
|
register_telegram_type(monitor_typeids[i], "RC10Monitor", false, MAKE_PF_CB(process_RC10Monitor));
|
||||||
register_telegram_type(set_typeids[i], F("RC10Set"), false, MAKE_PF_CB(process_RC10Set));
|
register_telegram_type(set_typeids[i], "RC10Set", false, MAKE_PF_CB(process_RC10Set));
|
||||||
}
|
}
|
||||||
|
|
||||||
// RC35
|
// RC35
|
||||||
@@ -64,15 +64,15 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
|||||||
timer_typeids = {0x3F, 0x49, 0x53, 0x5D};
|
timer_typeids = {0x3F, 0x49, 0x53, 0x5D};
|
||||||
timer2_typeids = {0x42, 0x4C, 0x56, 0x60};
|
timer2_typeids = {0x42, 0x4C, 0x56, 0x60};
|
||||||
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
||||||
register_telegram_type(monitor_typeids[i], F("RC35Monitor"), false, MAKE_PF_CB(process_RC35Monitor));
|
register_telegram_type(monitor_typeids[i], "RC35Monitor", false, MAKE_PF_CB(process_RC35Monitor));
|
||||||
register_telegram_type(set_typeids[i], F("RC35Set"), false, MAKE_PF_CB(process_RC35Set));
|
register_telegram_type(set_typeids[i], "RC35Set", false, MAKE_PF_CB(process_RC35Set));
|
||||||
register_telegram_type(timer_typeids[i], F("RC35Timer"), false, MAKE_PF_CB(process_RC35Timer));
|
register_telegram_type(timer_typeids[i], "RC35Timer", false, MAKE_PF_CB(process_RC35Timer));
|
||||||
register_telegram_type(timer2_typeids[i], F("RC35Timer2"), false, MAKE_PF_CB(process_RC35Timer));
|
register_telegram_type(timer2_typeids[i], "RC35Timer2", false, MAKE_PF_CB(process_RC35Timer));
|
||||||
}
|
}
|
||||||
register_telegram_type(EMS_TYPE_IBASettings, F("IBASettings"), true, MAKE_PF_CB(process_IBASettings));
|
register_telegram_type(EMS_TYPE_IBASettings, "IBASettings", true, MAKE_PF_CB(process_IBASettings));
|
||||||
register_telegram_type(EMS_TYPE_wwSettings, F("WWSettings"), true, MAKE_PF_CB(process_RC35wwSettings));
|
register_telegram_type(EMS_TYPE_wwSettings, "WWSettings", true, MAKE_PF_CB(process_RC35wwSettings));
|
||||||
register_telegram_type(0x38, F("WWTimer"), true, MAKE_PF_CB(process_RC35wwTimer));
|
register_telegram_type(0x38, "WWTimer", true, MAKE_PF_CB(process_RC35wwTimer));
|
||||||
register_telegram_type(0x39, F("WWCircTimer"), true, MAKE_PF_CB(process_RC35wwTimer));
|
register_telegram_type(0x39, "WWCircTimer", true, MAKE_PF_CB(process_RC35wwTimer));
|
||||||
|
|
||||||
// RC20
|
// RC20
|
||||||
} else if (model == EMSdevice::EMS_DEVICE_FLAG_RC20) {
|
} else if (model == EMSdevice::EMS_DEVICE_FLAG_RC20) {
|
||||||
@@ -81,22 +81,22 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
|||||||
curve_typeids = {0x90};
|
curve_typeids = {0x90};
|
||||||
timer_typeids = {0x8F};
|
timer_typeids = {0x8F};
|
||||||
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
||||||
register_telegram_type(monitor_typeids[i], F("RC20Monitor"), false, MAKE_PF_CB(process_RC20Monitor));
|
register_telegram_type(monitor_typeids[i], "RC20Monitor", false, MAKE_PF_CB(process_RC20Monitor));
|
||||||
register_telegram_type(set_typeids[i], F("RC20Set"), false, MAKE_PF_CB(process_RC20Set));
|
register_telegram_type(set_typeids[i], "RC20Set", false, MAKE_PF_CB(process_RC20Set));
|
||||||
register_telegram_type(curve_typeids[i], F("RC20Temp"), false, MAKE_PF_CB(process_RC20Temp));
|
register_telegram_type(curve_typeids[i], "RC20Temp", false, MAKE_PF_CB(process_RC20Temp));
|
||||||
register_telegram_type(timer_typeids[i], F("RC20Timer"), false, MAKE_PF_CB(process_RC20Timer));
|
register_telegram_type(timer_typeids[i], "RC20Timer", false, MAKE_PF_CB(process_RC20Timer));
|
||||||
}
|
}
|
||||||
// remote thermostat uses only 0xAF
|
// remote thermostat uses only 0xAF
|
||||||
register_telegram_type(0xAF, F("RC20Remote"), false, MAKE_PF_CB(process_RC20Remote));
|
register_telegram_type(0xAF, "RC20Remote", false, MAKE_PF_CB(process_RC20Remote));
|
||||||
// RC20 newer
|
// RC20 newer
|
||||||
} else if ((model == EMSdevice::EMS_DEVICE_FLAG_RC20_N) || (model == EMSdevice::EMS_DEVICE_FLAG_RC25)) {
|
} else if ((model == EMSdevice::EMS_DEVICE_FLAG_RC20_N) || (model == EMSdevice::EMS_DEVICE_FLAG_RC25)) {
|
||||||
monitor_typeids = {0xAE};
|
monitor_typeids = {0xAE};
|
||||||
set_typeids = {0xAD};
|
set_typeids = {0xAD};
|
||||||
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
||||||
register_telegram_type(monitor_typeids[i], F("RC20Monitor"), false, MAKE_PF_CB(process_RC20Monitor_2));
|
register_telegram_type(monitor_typeids[i], "RC20Monitor", false, MAKE_PF_CB(process_RC20Monitor_2));
|
||||||
register_telegram_type(set_typeids[i], F("RC20Set"), false, MAKE_PF_CB(process_RC20Set_2));
|
register_telegram_type(set_typeids[i], "RC20Set", false, MAKE_PF_CB(process_RC20Set_2));
|
||||||
}
|
}
|
||||||
register_telegram_type(0xAF, F("RC20Remote"), false, MAKE_PF_CB(process_RC20Remote));
|
register_telegram_type(0xAF, "RC20Remote", false, MAKE_PF_CB(process_RC20Remote));
|
||||||
// RC30
|
// RC30
|
||||||
} else if (model == EMSdevice::EMS_DEVICE_FLAG_RC30) {
|
} else if (model == EMSdevice::EMS_DEVICE_FLAG_RC30) {
|
||||||
monitor_typeids = {0x41};
|
monitor_typeids = {0x41};
|
||||||
@@ -104,27 +104,27 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
|||||||
curve_typeids = {0x40};
|
curve_typeids = {0x40};
|
||||||
timer_typeids = {0x3F};
|
timer_typeids = {0x3F};
|
||||||
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
||||||
register_telegram_type(monitor_typeids[i], F("RC30Monitor"), false, MAKE_PF_CB(process_RC30Monitor));
|
register_telegram_type(monitor_typeids[i], "RC30Monitor", false, MAKE_PF_CB(process_RC30Monitor));
|
||||||
register_telegram_type(set_typeids[i], F("RC30Set"), false, MAKE_PF_CB(process_RC30Set));
|
register_telegram_type(set_typeids[i], "RC30Set", false, MAKE_PF_CB(process_RC30Set));
|
||||||
register_telegram_type(curve_typeids[i], F("RC30Temp"), false, MAKE_PF_CB(process_RC30Temp));
|
register_telegram_type(curve_typeids[i], "RC30Temp", false, MAKE_PF_CB(process_RC30Temp));
|
||||||
register_telegram_type(timer_typeids[i], F("RC30Timer"), false, MAKE_PF_CB(process_RC35Timer));
|
register_telegram_type(timer_typeids[i], "RC30Timer", false, MAKE_PF_CB(process_RC35Timer));
|
||||||
}
|
}
|
||||||
register_telegram_type(EMS_TYPE_RC30wwSettings, F("RC30WWSettings"), true, MAKE_PF_CB(process_RC30wwSettings));
|
register_telegram_type(EMS_TYPE_RC30wwSettings, "RC30WWSettings", true, MAKE_PF_CB(process_RC30wwSettings));
|
||||||
register_telegram_type(0x38, F("WWTimer"), true, MAKE_PF_CB(process_RC35wwTimer));
|
register_telegram_type(0x38, "WWTimer", true, MAKE_PF_CB(process_RC35wwTimer));
|
||||||
register_telegram_type(0x39, F("WWCircTimer"), true, MAKE_PF_CB(process_RC35wwTimer));
|
register_telegram_type(0x39, "WWCircTimer", true, MAKE_PF_CB(process_RC35wwTimer));
|
||||||
|
|
||||||
// EASY
|
// EASY
|
||||||
} else if (model == EMSdevice::EMS_DEVICE_FLAG_EASY) {
|
} else if (model == EMSdevice::EMS_DEVICE_FLAG_EASY) {
|
||||||
monitor_typeids = {0x0A};
|
monitor_typeids = {0x0A};
|
||||||
set_typeids = {};
|
set_typeids = {};
|
||||||
register_telegram_type(monitor_typeids[0], F("EasyMonitor"), true, MAKE_PF_CB(process_EasyMonitor));
|
register_telegram_type(monitor_typeids[0], "EasyMonitor", true, MAKE_PF_CB(process_EasyMonitor));
|
||||||
|
|
||||||
// CRF
|
// CRF
|
||||||
} else if (model == EMSdevice::EMS_DEVICE_FLAG_CRF) {
|
} else if (model == EMSdevice::EMS_DEVICE_FLAG_CRF) {
|
||||||
monitor_typeids = {0x02A5, 0x02A6, 0x02A7, 0x02A8};
|
monitor_typeids = {0x02A5, 0x02A6, 0x02A7, 0x02A8};
|
||||||
set_typeids = {};
|
set_typeids = {};
|
||||||
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
||||||
register_telegram_type(monitor_typeids[i], F("CRFMonitor"), false, MAKE_PF_CB(process_CRFMonitor));
|
register_telegram_type(monitor_typeids[i], "CRFMonitor", false, MAKE_PF_CB(process_CRFMonitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
// RC300/RC100
|
// RC300/RC100
|
||||||
@@ -136,46 +136,46 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
|||||||
curve_typeids = {0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1, 0x02A2};
|
curve_typeids = {0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1, 0x02A2};
|
||||||
summer2_typeids = {0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0476, 0x0477, 0x0478};
|
summer2_typeids = {0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0476, 0x0477, 0x0478};
|
||||||
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
||||||
register_telegram_type(monitor_typeids[i], F("RC300Monitor"), false, MAKE_PF_CB(process_RC300Monitor));
|
register_telegram_type(monitor_typeids[i], "RC300Monitor", false, MAKE_PF_CB(process_RC300Monitor));
|
||||||
register_telegram_type(set_typeids[i], F("RC300Set"), false, MAKE_PF_CB(process_RC300Set));
|
register_telegram_type(set_typeids[i], "RC300Set", false, MAKE_PF_CB(process_RC300Set));
|
||||||
register_telegram_type(summer_typeids[i], F("RC300Summer"), false, MAKE_PF_CB(process_RC300Summer));
|
register_telegram_type(summer_typeids[i], "RC300Summer", false, MAKE_PF_CB(process_RC300Summer));
|
||||||
register_telegram_type(curve_typeids[i], F("RC300Curves"), false, MAKE_PF_CB(process_RC300Curve));
|
register_telegram_type(curve_typeids[i], "RC300Curves", false, MAKE_PF_CB(process_RC300Curve));
|
||||||
register_telegram_type(summer2_typeids[i], F("RC300Summer2"), false, MAKE_PF_CB(process_RC300Summer2));
|
register_telegram_type(summer2_typeids[i], "RC300Summer2", false, MAKE_PF_CB(process_RC300Summer2));
|
||||||
}
|
}
|
||||||
for (uint8_t i = 0; i < set2_typeids.size(); i++) {
|
for (uint8_t i = 0; i < set2_typeids.size(); i++) {
|
||||||
register_telegram_type(set2_typeids[i], F("RC300Set2"), false, MAKE_PF_CB(process_RC300Set2));
|
register_telegram_type(set2_typeids[i], "RC300Set2", false, MAKE_PF_CB(process_RC300Set2));
|
||||||
}
|
}
|
||||||
register_telegram_type(0x2F5, F("RC300WWmode"), true, MAKE_PF_CB(process_RC300WWmode));
|
register_telegram_type(0x2F5, "RC300WWmode", true, MAKE_PF_CB(process_RC300WWmode));
|
||||||
register_telegram_type(0x31B, F("RC300WWtemp"), true, MAKE_PF_CB(process_RC300WWtemp));
|
register_telegram_type(0x31B, "RC300WWtemp", true, MAKE_PF_CB(process_RC300WWtemp));
|
||||||
register_telegram_type(0x31D, F("RC300WWmode2"), false, MAKE_PF_CB(process_RC300WWmode2));
|
register_telegram_type(0x31D, "RC300WWmode2", false, MAKE_PF_CB(process_RC300WWmode2));
|
||||||
register_telegram_type(0x31E, F("RC300WWmode2"), false, MAKE_PF_CB(process_RC300WWmode2));
|
register_telegram_type(0x31E, "RC300WWmode2", false, MAKE_PF_CB(process_RC300WWmode2));
|
||||||
register_telegram_type(0x23A, F("RC300OutdoorTemp"), true, MAKE_PF_CB(process_RC300OutdoorTemp));
|
register_telegram_type(0x23A, "RC300OutdoorTemp", true, MAKE_PF_CB(process_RC300OutdoorTemp));
|
||||||
register_telegram_type(0x267, F("RC300Floordry"), false, MAKE_PF_CB(process_RC300Floordry));
|
register_telegram_type(0x267, "RC300Floordry", false, MAKE_PF_CB(process_RC300Floordry));
|
||||||
register_telegram_type(0x240, F("RC300Settings"), true, MAKE_PF_CB(process_RC300Settings));
|
register_telegram_type(0x240, "RC300Settings", true, MAKE_PF_CB(process_RC300Settings));
|
||||||
|
|
||||||
// JUNKERS/HT3
|
// JUNKERS/HT3
|
||||||
} else if (model == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
|
} else if (model == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
|
||||||
monitor_typeids = {0x016F, 0x0170, 0x0171, 0x0172};
|
monitor_typeids = {0x016F, 0x0170, 0x0171, 0x0172};
|
||||||
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
||||||
register_telegram_type(monitor_typeids[i], F("JunkersMonitor"), false, MAKE_PF_CB(process_JunkersMonitor));
|
register_telegram_type(monitor_typeids[i], "JunkersMonitor", false, MAKE_PF_CB(process_JunkersMonitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_flags(EMS_DEVICE_FLAG_JUNKERS_OLD)) {
|
if (has_flags(EMS_DEVICE_FLAG_JUNKERS_OLD)) {
|
||||||
// FR120, FR100
|
// FR120, FR100
|
||||||
set_typeids = {0x0179, 0x017A, 0x017B, 0x017C};
|
set_typeids = {0x0179, 0x017A, 0x017B, 0x017C};
|
||||||
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
||||||
register_telegram_type(set_typeids[i], F("JunkersSet"), false, MAKE_PF_CB(process_JunkersSet2));
|
register_telegram_type(set_typeids[i], "JunkersSet", false, MAKE_PF_CB(process_JunkersSet2));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
set_typeids = {0x0165, 0x0166, 0x0167, 0x0168};
|
set_typeids = {0x0165, 0x0166, 0x0167, 0x0168};
|
||||||
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
||||||
register_telegram_type(set_typeids[i], F("JunkersSet"), false, MAKE_PF_CB(process_JunkersSet));
|
register_telegram_type(set_typeids[i], "JunkersSet", false, MAKE_PF_CB(process_JunkersSet));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
register_telegram_type(0xBB, F("HybridSettings"), true, MAKE_PF_CB(process_JunkersHybridSettings));
|
register_telegram_type(0xBB, "HybridSettings", true, MAKE_PF_CB(process_JunkersHybridSettings));
|
||||||
register_telegram_type(0x23, F("JunkersSetMixer"), true, MAKE_PF_CB(process_JunkersSetMixer));
|
register_telegram_type(0x23, "JunkersSetMixer", true, MAKE_PF_CB(process_JunkersSetMixer));
|
||||||
register_telegram_type(0x123, F("JunkersRemote"), false, MAKE_PF_CB(process_JunkersRemoteMonitor));
|
register_telegram_type(0x123, "JunkersRemote", false, MAKE_PF_CB(process_JunkersRemoteMonitor));
|
||||||
register_telegram_type(0x1D3, F("JunkersDhw"), true, MAKE_PF_CB(process_JunkersWW));
|
register_telegram_type(0x1D3, "JunkersDhw", true, MAKE_PF_CB(process_JunkersWW));
|
||||||
}
|
}
|
||||||
|
|
||||||
// register device values for common values (not heating circuit)
|
// register device values for common values (not heating circuit)
|
||||||
@@ -522,7 +522,7 @@ void Thermostat::process_RC10Set(std::shared_ptr<const Telegram> telegram) {
|
|||||||
if (hc == nullptr) {
|
if (hc == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
has_update(telegram, ibaClockOffset_, 0);
|
has_update(telegram, ibaCalIntTemperature_, 0);
|
||||||
has_update(telegram, backlight_, 1);
|
has_update(telegram, backlight_, 1);
|
||||||
has_update(telegram, wwMode_, 2);
|
has_update(telegram, wwMode_, 2);
|
||||||
has_update(telegram, hc->nighttemp, 3);
|
has_update(telegram, hc->nighttemp, 3);
|
||||||
@@ -593,8 +593,7 @@ void Thermostat::process_RC20Timer(std::shared_ptr<const Telegram> telegram) {
|
|||||||
uint8_t time = telegram->message_data[1];
|
uint8_t time = telegram->message_data[1];
|
||||||
|
|
||||||
// we use EN settings for the day abbreviation
|
// we use EN settings for the day abbreviation
|
||||||
std::string sday = read_flash_string(FL_(enum_dayOfWeek)[day][0]);
|
std::string sday = (FL_(enum_dayOfWeek)[day][0]);
|
||||||
// std::string sday = Helpers::translated_word(FL_(enum_dayOfWeek)[day]);
|
|
||||||
|
|
||||||
if (day == 7) {
|
if (day == 7) {
|
||||||
snprintf(data, sizeof(data), "%02d not_set", no);
|
snprintf(data, sizeof(data), "%02d not_set", no);
|
||||||
@@ -680,13 +679,19 @@ void Thermostat::process_JunkersSet(std::shared_ptr<const Telegram> telegram) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
has_update(telegram, hc->daytemp, 17); // is * 2
|
has_update(telegram, hc->daytemp, 17); // is * 2
|
||||||
has_update(telegram, hc->nighttemp, 16); // is * 2
|
has_update(telegram, hc->nighttemp, 16); // is * 2
|
||||||
has_update(telegram, hc->nofrosttemp, 15); // is * 2
|
has_update(telegram, hc->nofrosttemp, 15); // is * 2
|
||||||
has_update(telegram, hc->control, 1); // remote: 0-off, 1-FB10, 2-FB100
|
has_update(telegram, hc->control, 1); // remote: 0-off, 1-FB10, 2-FB100
|
||||||
has_enumupdate(telegram, hc->program, 13, 1); // 1-6: 1 = A, 2 = B,...
|
has_enumupdate(telegram, hc->program, 13, 1); // 1-6: 1 = A, 2 = B,...
|
||||||
has_enumupdate(telegram, hc->mode, 14, 1); // 0 = nofrost, 1 = eco, 2 = heat, 3 = auto
|
has_enumupdate(telegram, hc->mode, 14, 1); // 0 = nofrost, 1 = eco, 2 = heat, 3 = auto
|
||||||
has_update(telegram, hc->roomsensor, 9); // 1-intern, 2-extern, 3-autoselect the lower value
|
has_update(telegram, hc->daytemp, 17); // is * 2
|
||||||
|
has_update(telegram, hc->nighttemp, 16); // is * 2
|
||||||
|
has_update(telegram, hc->nofrosttemp, 15); // is * 2
|
||||||
|
has_update(telegram, hc->control, 1); // remote: 0-off, 1-FB10, 2-FB100
|
||||||
|
has_enumupdate(telegram, hc->program, 13, 1); // 1-6: 1 = A, 2 = B,...
|
||||||
|
has_enumupdate(telegram, hc->mode, 14, 1); // 0 = nofrost, 1 = eco, 2 = heat, 3 = auto
|
||||||
|
has_enumupdate(telegram, hc->roomsensor, 9, 1); // 1-intern, 2-extern, 3-autoselect the lower value
|
||||||
}
|
}
|
||||||
|
|
||||||
// type 0x0179, ff
|
// type 0x0179, ff
|
||||||
@@ -795,20 +800,11 @@ void Thermostat::process_RC35wwTimer(std::shared_ptr<const Telegram> telegram) {
|
|||||||
|
|
||||||
char data[sizeof(wwSwitchTime_)];
|
char data[sizeof(wwSwitchTime_)];
|
||||||
// we use EN settings for the day abbreviation
|
// we use EN settings for the day abbreviation
|
||||||
std::string sday = read_flash_string(FL_(enum_dayOfWeek)[day][0]);
|
std::string sday = (FL_(enum_dayOfWeek)[day][0]);
|
||||||
// std::string sday = Helpers::translated_word(FL_(enum_dayOfWeek)[day]);
|
|
||||||
if (day == 7) {
|
if (day == 7) {
|
||||||
snprintf(data, sizeof(data), "%02d not_set", no);
|
snprintf(data, sizeof(data), "%02d not_set", no);
|
||||||
} else {
|
} else {
|
||||||
snprintf(data,
|
snprintf(data, sizeof(data), "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), on ? "on" : "off");
|
||||||
sizeof(data),
|
|
||||||
"%02d %s %02d:%02d %s",
|
|
||||||
no,
|
|
||||||
sday.c_str(),
|
|
||||||
time / 6,
|
|
||||||
10 * (time % 6),
|
|
||||||
// on ? (Helpers::translated_word(FL_(on))).c_str() : (Helpers::translated_word(FL_(off))).c_str());
|
|
||||||
on ? "on" : "off");
|
|
||||||
}
|
}
|
||||||
if (telegram->type_id == 0x38) {
|
if (telegram->type_id == 0x38) {
|
||||||
has_update(wwSwitchTime_, data, sizeof(wwSwitchTime_));
|
has_update(wwSwitchTime_, data, sizeof(wwSwitchTime_));
|
||||||
@@ -1102,6 +1098,7 @@ void Thermostat::process_RC300OutdoorTemp(std::shared_ptr<const Telegram> telegr
|
|||||||
|
|
||||||
// 0x240 RC300 parameter
|
// 0x240 RC300 parameter
|
||||||
void Thermostat::process_RC300Settings(std::shared_ptr<const Telegram> telegram) {
|
void Thermostat::process_RC300Settings(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
has_update(telegram, ibaCalIntTemperature_, 7);
|
||||||
has_update(telegram, ibaDamping_, 8);
|
has_update(telegram, ibaDamping_, 8);
|
||||||
has_enumupdate(telegram, ibaBuildingType_, 9, 1); // 1=light, 2=medium, 3=heavy
|
has_enumupdate(telegram, ibaBuildingType_, 9, 1); // 1=light, 2=medium, 3=heavy
|
||||||
has_update(telegram, ibaMinExtTemperature_, 10);
|
has_update(telegram, ibaMinExtTemperature_, 10);
|
||||||
@@ -1273,8 +1270,7 @@ void Thermostat::process_RC35Timer(std::shared_ptr<const Telegram> telegram) {
|
|||||||
uint8_t time = telegram->message_data[1];
|
uint8_t time = telegram->message_data[1];
|
||||||
|
|
||||||
// we use EN settings for the day abbreviation
|
// we use EN settings for the day abbreviation
|
||||||
std::string sday = read_flash_string(FL_(enum_dayOfWeek)[day][0]);
|
std::string sday = (FL_(enum_dayOfWeek)[day][0]);
|
||||||
// std::string sday = Helpers::translated_word(FL_(enum_dayOfWeek)[day]);
|
|
||||||
if (day == 7) {
|
if (day == 7) {
|
||||||
snprintf(data, sizeof(data), "%02d not_set", no);
|
snprintf(data, sizeof(data), "%02d not_set", no);
|
||||||
} else if (model() == EMS_DEVICE_FLAG_RC30) {
|
} else if (model() == EMS_DEVICE_FLAG_RC30) {
|
||||||
@@ -1363,14 +1359,15 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
|
|||||||
strftime(newdatetime, sizeof(dateTime_), "%d.%m.%G %H:%M", tm_);
|
strftime(newdatetime, sizeof(dateTime_), "%d.%m.%G %H:%M", tm_);
|
||||||
has_update(dateTime_, newdatetime, sizeof(dateTime_));
|
has_update(dateTime_, newdatetime, sizeof(dateTime_));
|
||||||
|
|
||||||
bool ivtclock = (telegram->message_data[0] & 0x80) == 0x80; // dont sync ivt-clock, #439
|
bool ivtclock = (telegram->message_data[0] & 0x80) == 0x80; // dont sync ivt-clock, #439
|
||||||
time_t ttime = mktime(tm_); // thermostat time
|
bool junkersclock = model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS;
|
||||||
|
time_t ttime = mktime(tm_); // thermostat time
|
||||||
// correct thermostat clock if we have valid ntp time, and could write the command
|
// correct thermostat clock if we have valid ntp time, and could write the command
|
||||||
if (!ivtclock && tset_ && EMSESP::system_.ntp_connected() && !EMSESP::system_.readonly_mode() && has_command(&dateTime_)) {
|
if (!ivtclock && !junkersclock && tset_ && EMSESP::system_.ntp_connected() && !EMSESP::system_.readonly_mode() && has_command(&dateTime_)) {
|
||||||
double difference = difftime(now, ttime);
|
double difference = difftime(now, ttime);
|
||||||
if (difference > 15 || difference < -15) {
|
if (difference > 15 || difference < -15) {
|
||||||
set_datetime("ntp", -1); // set from NTP
|
set_datetime("ntp", -1); // set from NTP
|
||||||
LOG_INFO(F("thermostat time correction from ntp"));
|
LOG_INFO("thermostat time correction from ntp");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
@@ -1381,7 +1378,7 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
|
|||||||
}
|
}
|
||||||
struct timeval newnow = {.tv_sec = ttime};
|
struct timeval newnow = {.tv_sec = ttime};
|
||||||
settimeofday(&newnow, nullptr);
|
settimeofday(&newnow, nullptr);
|
||||||
LOG_INFO(F("ems-esp time set from thermostat"));
|
LOG_INFO("ems-esp time set from thermostat");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -1549,7 +1546,7 @@ bool Thermostat::set_calinttemp(const char * value, const int8_t id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto t = (int8_t)(ct * 10);
|
auto t = (int8_t)(ct * 10);
|
||||||
LOG_DEBUG(F("Calibrating internal temperature to %d.%d C"), t / 10, t < 0 ? -t % 10 : t % 10);
|
LOG_DEBUG("Calibrating internal temperature to %d.%d C", t / 10, t < 0 ? -t % 10 : t % 10);
|
||||||
|
|
||||||
if (model() == EMS_DEVICE_FLAG_RC10) {
|
if (model() == EMS_DEVICE_FLAG_RC10) {
|
||||||
write_command(0xB0, 0, t, 0xB0);
|
write_command(0xB0, 0, t, 0xB0);
|
||||||
@@ -1557,6 +1554,8 @@ bool Thermostat::set_calinttemp(const char * value, const int8_t id) {
|
|||||||
write_command(EMS_TYPE_RC30Settings, 1, t, EMS_TYPE_RC30Settings);
|
write_command(EMS_TYPE_RC30Settings, 1, t, EMS_TYPE_RC30Settings);
|
||||||
} else if (model() == EMS_DEVICE_FLAG_RC100H) {
|
} else if (model() == EMS_DEVICE_FLAG_RC100H) {
|
||||||
write_command(0x273, 0, t, 0x273);
|
write_command(0x273, 0, t, 0x273);
|
||||||
|
} else if (model() == EMS_DEVICE_FLAG_RC100 || model() == EMS_DEVICE_FLAG_RC300) {
|
||||||
|
write_command(0x240, 7, t, 0x240);
|
||||||
} else {
|
} else {
|
||||||
write_command(EMS_TYPE_IBASettings, 2, t, EMS_TYPE_IBASettings);
|
write_command(EMS_TYPE_IBASettings, 2, t, EMS_TYPE_IBASettings);
|
||||||
}
|
}
|
||||||
@@ -1564,10 +1563,10 @@ bool Thermostat::set_calinttemp(const char * value, const int8_t id) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0xA5 - Set the display settings
|
// 0xA5 - Set the display settings, RC30_N
|
||||||
bool Thermostat::set_display(const char * value, const int8_t id) {
|
bool Thermostat::set_display(const char * value, const int8_t id) {
|
||||||
int ds = 0;
|
uint8_t ds;
|
||||||
if (!Helpers::value2number(value, ds)) {
|
if (!Helpers::value2enum(value, ds, FL_(enum_ibaMainDisplay))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1714,7 +1713,7 @@ bool Thermostat::set_roomsensor(const char * value, const int8_t id) {
|
|||||||
uint8_t ctrl = 0;
|
uint8_t ctrl = 0;
|
||||||
if (model() == EMS_DEVICE_FLAG_JUNKERS && !has_flags(EMS_DEVICE_FLAG_JUNKERS_OLD)) {
|
if (model() == EMS_DEVICE_FLAG_JUNKERS && !has_flags(EMS_DEVICE_FLAG_JUNKERS_OLD)) {
|
||||||
if (Helpers::value2enum(value, ctrl, FL_(enum_roomsensor))) {
|
if (Helpers::value2enum(value, ctrl, FL_(enum_roomsensor))) {
|
||||||
write_command(set_typeids[hc->hc()], 9, ctrl);
|
write_command(set_typeids[hc->hc()], 9, ctrl + 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2151,7 +2150,7 @@ bool Thermostat::set_datetime(const char * value, const int8_t id) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!EMSESP::system_.ntp_connected()) {
|
if (!EMSESP::system_.ntp_connected()) {
|
||||||
LOG_WARNING(F("Set date: no valid NTP data, setting from ESP Clock"));
|
LOG_WARNING("Set date: no valid NTP data, setting from ESP Clock");
|
||||||
}
|
}
|
||||||
|
|
||||||
data[0] = tm_->tm_year - 100; // Bosch counts from 2000
|
data[0] = tm_->tm_year - 100; // Bosch counts from 2000
|
||||||
@@ -2162,6 +2161,10 @@ bool Thermostat::set_datetime(const char * value, const int8_t id) {
|
|||||||
data[5] = tm_->tm_sec;
|
data[5] = tm_->tm_sec;
|
||||||
data[6] = (tm_->tm_wday + 6) % 7; // Bosch counts from Mo, time from Su
|
data[6] = (tm_->tm_wday + 6) % 7; // Bosch counts from Mo, time from Su
|
||||||
data[7] = tm_->tm_isdst + 2; // set DST and flag for ext. clock
|
data[7] = tm_->tm_isdst + 2; // set DST and flag for ext. clock
|
||||||
|
if (model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
|
||||||
|
data[6]++; // Junkers use 1-7;
|
||||||
|
data[7] = 0;
|
||||||
|
}
|
||||||
} else if (dt.length() == 23) {
|
} else if (dt.length() == 23) {
|
||||||
data[0] = (dt[7] - '0') * 100 + (dt[8] - '0') * 10 + (dt[9] - '0'); // year
|
data[0] = (dt[7] - '0') * 100 + (dt[8] - '0') * 10 + (dt[9] - '0'); // year
|
||||||
data[1] = (dt[3] - '0') * 10 + (dt[4] - '0'); // month
|
data[1] = (dt[3] - '0') * 10 + (dt[4] - '0'); // month
|
||||||
@@ -2171,16 +2174,19 @@ bool Thermostat::set_datetime(const char * value, const int8_t id) {
|
|||||||
data[5] = (dt[17] - '0') * 10 + (dt[18] - '0'); // sec
|
data[5] = (dt[17] - '0') * 10 + (dt[18] - '0'); // sec
|
||||||
data[6] = (dt[20] - '0'); // day of week, Mo:0
|
data[6] = (dt[20] - '0'); // day of week, Mo:0
|
||||||
data[7] = (dt[22] - '0') + 2; // DST and flag
|
data[7] = (dt[22] - '0') + 2; // DST and flag
|
||||||
|
if (model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
|
||||||
|
data[7] = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING(F("Set date: invalid data, wrong length"));
|
LOG_WARNING("Set date: invalid data, wrong length");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (data[1] == 0 || data[1] > 12 || data[2] > 23 || data[3] == 0 || data[3] > 31 || data[4] > 59 || data[5] > 59 || data[6] > 6 || data[7] > 3) {
|
if (data[1] == 0 || data[1] > 12 || data[2] > 23 || data[3] == 0 || data[3] > 31 || data[4] > 59 || data[5] > 59 || data[6] > 6 || data[7] > 3) {
|
||||||
LOG_WARNING(F("Invalid date/time: %02d.%02d.2%03d-%02d:%02d:%02d-%d-%d"), data[3], data[1], data[0], data[2], data[4], data[5], data[6], data[7]);
|
LOG_WARNING("Invalid date/time: %02d.%02d.2%03d-%02d:%02d:%02d-%d-%d", data[3], data[1], data[0], data[2], data[4], data[5], data[6], data[7]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LOG_INFO(F("Setting date and time: %02d.%02d.2%03d-%02d:%02d:%02d-%d-%d"), data[3], data[1], data[0], data[2], data[4], data[5], data[6], data[7]);
|
// LOG_INFO("Setting date and time: %02d.%02d.2%03d-%02d:%02d:%02d-%d-%d", data[3], data[1], data[0], data[2], data[4], data[5], data[6], data[7]);
|
||||||
write_command(EMS_TYPE_time, 0, data, 8, EMS_TYPE_time);
|
write_command(EMS_TYPE_time, 0, data, 8, EMS_TYPE_time);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -2203,82 +2209,93 @@ bool Thermostat::set_roominfl_factor(const char * value, const int8_t id) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets the thermostat working mode, where mode is a string
|
// sets the thermostat working mode
|
||||||
// converts string mode to HeatingCircuit::Mode
|
|
||||||
bool Thermostat::set_mode(const char * value, const int8_t id) {
|
bool Thermostat::set_mode(const char * value, const int8_t id) {
|
||||||
if ((value == nullptr) || (strlen(value) >= 20)) {
|
if ((value == nullptr) || (strlen(value) >= 20)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string mode;
|
// first determine which enum we are using
|
||||||
|
const char * const ** mode_list = nullptr; // points to a translated list of modes
|
||||||
if (value[0] >= '0' && value[0] <= '9') {
|
switch (model()) {
|
||||||
uint8_t num = value[0] - '0';
|
case EMSdevice::EMS_DEVICE_FLAG_RC10:
|
||||||
switch (model()) {
|
mode_list = FL_(enum_mode6);
|
||||||
case EMSdevice::EMS_DEVICE_FLAG_RC10:
|
break;
|
||||||
mode = Helpers::translated_word(FL_(enum_mode6)[num], true);
|
case EMSdevice::EMS_DEVICE_FLAG_RC20:
|
||||||
break;
|
case EMSdevice::EMS_DEVICE_FLAG_RC20_N:
|
||||||
case EMSdevice::EMS_DEVICE_FLAG_RC20:
|
mode_list = FL_(enum_mode2);
|
||||||
case EMSdevice::EMS_DEVICE_FLAG_RC20_N:
|
break;
|
||||||
mode = Helpers::translated_word(FL_(enum_mode2)[num], true);
|
case EMSdevice::EMS_DEVICE_FLAG_RC25:
|
||||||
break;
|
case EMSdevice::EMS_DEVICE_FLAG_RC30:
|
||||||
case EMSdevice::EMS_DEVICE_FLAG_RC25:
|
case EMSdevice::EMS_DEVICE_FLAG_RC35:
|
||||||
case EMSdevice::EMS_DEVICE_FLAG_RC30:
|
case EMSdevice::EMS_DEVICE_FLAG_RC30_N:
|
||||||
case EMSdevice::EMS_DEVICE_FLAG_RC35:
|
mode_list = FL_(enum_mode3);
|
||||||
case EMSdevice::EMS_DEVICE_FLAG_RC30_N:
|
break;
|
||||||
mode = Helpers::translated_word(FL_(enum_mode3)[num], true);
|
case EMSdevice::EMS_DEVICE_FLAG_RC300:
|
||||||
break;
|
case EMSdevice::EMS_DEVICE_FLAG_RC100:
|
||||||
case EMSdevice::EMS_DEVICE_FLAG_RC300:
|
mode_list = FL_(enum_mode);
|
||||||
case EMSdevice::EMS_DEVICE_FLAG_RC100:
|
break;
|
||||||
mode = Helpers::translated_word(FL_(enum_mode)[num], true);
|
case EMSdevice::EMS_DEVICE_FLAG_JUNKERS:
|
||||||
break;
|
mode_list = FL_(enum_mode4);
|
||||||
case EMSdevice::EMS_DEVICE_FLAG_JUNKERS:
|
break;
|
||||||
mode = Helpers::translated_word(FL_(enum_mode4)[num], true);
|
case EMSdevice::EMS_DEVICE_FLAG_CRF:
|
||||||
break;
|
mode_list = FL_(enum_mode5);
|
||||||
case EMSdevice::EMS_DEVICE_FLAG_CRF:
|
break;
|
||||||
mode = Helpers::translated_word(FL_(enum_mode5)[num], true);
|
default:
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (!Helpers::value2string(value, mode)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id;
|
uint8_t enum_index = 0;
|
||||||
|
|
||||||
if (Helpers::translated_word(FL_(off), true) == mode) {
|
// check for a mode number as a string with a single digit (0..9)
|
||||||
return set_mode_n(HeatingCircuit::Mode::OFF, hc_num);
|
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
|
||||||
|
if (!Helpers::value2enum(value, enum_index, mode_list)) {
|
||||||
|
return false; // not found
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (Helpers::translated_word(FL_(manual), true) == mode) {
|
|
||||||
return set_mode_n(HeatingCircuit::Mode::MANUAL, hc_num);
|
uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id; // heating circuit
|
||||||
}
|
|
||||||
if (Helpers::translated_word(FL_(auto), true) == mode) {
|
// compare the english string
|
||||||
|
auto mode = mode_list[enum_index][0];
|
||||||
|
if (!strcmp(mode, FL_(auto)[0])) {
|
||||||
return set_mode_n(HeatingCircuit::Mode::AUTO, hc_num);
|
return set_mode_n(HeatingCircuit::Mode::AUTO, hc_num);
|
||||||
}
|
}
|
||||||
if (Helpers::translated_word(FL_(day), true) == mode) {
|
if (!strcmp(mode, FL_(off)[0])) {
|
||||||
|
return set_mode_n(HeatingCircuit::Mode::OFF, hc_num);
|
||||||
|
}
|
||||||
|
if (!strcmp(mode, FL_(manual)[0])) {
|
||||||
|
return set_mode_n(HeatingCircuit::Mode::MANUAL, hc_num);
|
||||||
|
}
|
||||||
|
if (!strcmp(mode, FL_(day)[0])) {
|
||||||
return set_mode_n(HeatingCircuit::Mode::DAY, hc_num);
|
return set_mode_n(HeatingCircuit::Mode::DAY, hc_num);
|
||||||
}
|
}
|
||||||
if (Helpers::translated_word(FL_(night), true) == mode) {
|
if (!strcmp(mode, FL_(night)[0])) {
|
||||||
return set_mode_n(HeatingCircuit::Mode::NIGHT, hc_num);
|
return set_mode_n(HeatingCircuit::Mode::NIGHT, hc_num);
|
||||||
}
|
}
|
||||||
if (Helpers::translated_word(FL_(heat), true) == mode) {
|
if (!strcmp(mode, FL_(heat)[0])) {
|
||||||
return set_mode_n(HeatingCircuit::Mode::HEAT, hc_num);
|
return set_mode_n(HeatingCircuit::Mode::HEAT, hc_num);
|
||||||
}
|
}
|
||||||
if (Helpers::translated_word(FL_(nofrost), true) == mode) {
|
if (!strcmp(mode, FL_(nofrost)[0])) {
|
||||||
return set_mode_n(HeatingCircuit::Mode::NOFROST, hc_num);
|
return set_mode_n(HeatingCircuit::Mode::NOFROST, hc_num);
|
||||||
}
|
}
|
||||||
if (Helpers::translated_word(FL_(eco), true) == mode) {
|
if (!strcmp(mode, FL_(eco)[0])) {
|
||||||
return set_mode_n(HeatingCircuit::Mode::ECO, hc_num);
|
return set_mode_n(HeatingCircuit::Mode::ECO, hc_num);
|
||||||
}
|
}
|
||||||
if (Helpers::translated_word(FL_(holiday), true) == mode) {
|
if (!strcmp(mode, FL_(holiday)[0])) {
|
||||||
return set_mode_n(HeatingCircuit::Mode::HOLIDAY, hc_num);
|
return set_mode_n(HeatingCircuit::Mode::HOLIDAY, hc_num);
|
||||||
}
|
}
|
||||||
if (Helpers::translated_word(FL_(comfort), true) == mode) {
|
if (!strcmp(mode, FL_(comfort)[0])) {
|
||||||
return set_mode_n(HeatingCircuit::Mode::COMFORT, hc_num);
|
return set_mode_n(HeatingCircuit::Mode::COMFORT, hc_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false; // not found
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the thermostat working mode
|
// Set the thermostat working mode
|
||||||
@@ -2301,14 +2318,12 @@ bool Thermostat::set_mode_n(const uint8_t mode, const uint8_t hc_num) {
|
|||||||
case HeatingCircuit::Mode::OFF:
|
case HeatingCircuit::Mode::OFF:
|
||||||
set_mode_value = 0;
|
set_mode_value = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeatingCircuit::Mode::DAY:
|
case HeatingCircuit::Mode::DAY:
|
||||||
case HeatingCircuit::Mode::HEAT:
|
case HeatingCircuit::Mode::HEAT:
|
||||||
case HeatingCircuit::Mode::MANUAL:
|
case HeatingCircuit::Mode::MANUAL:
|
||||||
case HeatingCircuit::Mode::NOFROST:
|
case HeatingCircuit::Mode::NOFROST:
|
||||||
set_mode_value = 1;
|
set_mode_value = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // AUTO & ECO
|
default: // AUTO & ECO
|
||||||
set_mode_value = 2;
|
set_mode_value = 2;
|
||||||
break;
|
break;
|
||||||
@@ -2653,7 +2668,7 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char
|
|||||||
day = 7;
|
day = 7;
|
||||||
on = 7;
|
on = 7;
|
||||||
time = 0x90;
|
time = 0x90;
|
||||||
// LOG_INFO(F("switchtime %02d cleared"), no);
|
// LOG_INFO("switchtime %02d cleared", no);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (strlen(value) > 1) {
|
if (strlen(value) > 1) {
|
||||||
@@ -2670,14 +2685,9 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char
|
|||||||
if (strlen(value) > 4) {
|
if (strlen(value) > 4) {
|
||||||
for (uint8_t i = 0; i < 7; i++) {
|
for (uint8_t i = 0; i < 7; i++) {
|
||||||
// we use EN settings for the day abbreviation
|
// we use EN settings for the day abbreviation
|
||||||
if (!strncmp(&value[3], read_flash_string(FL_(enum_dayOfWeek)[i][0]).c_str(), 2)) {
|
if (!strncmp(&value[3], (FL_(enum_dayOfWeek)[i][0]), 2)) {
|
||||||
day = i;
|
day = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto translated_dow = Helpers::translated_word(FL_(enum_dayOfWeek)[i]);
|
|
||||||
// if (!strncmp(&value[3], translated_dow.c_str(), translated_dow.length())) {
|
|
||||||
// day = i;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (strlen(value) > 10) {
|
if (strlen(value) > 10) {
|
||||||
@@ -2694,7 +2704,7 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char
|
|||||||
day = 7;
|
day = 7;
|
||||||
on = 7;
|
on = 7;
|
||||||
time = 0x90;
|
time = 0x90;
|
||||||
// LOG_INFO(F("switchtime %02d cleared"), no);
|
// LOG_INFO("switchtime %02d cleared", no);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint8_t data[2] = {0xE7, 0x90}; // unset switchtime
|
uint8_t data[2] = {0xE7, 0x90}; // unset switchtime
|
||||||
@@ -2710,21 +2720,19 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char
|
|||||||
max_on = 1;
|
max_on = 1;
|
||||||
}
|
}
|
||||||
if (no > 41 || time > 0x90 || ((on < min_on || on > max_on) && on != 7)) {
|
if (no > 41 || time > 0x90 || ((on < min_on || on > max_on) && on != 7)) {
|
||||||
// LOG_WARNING(F("Setting switchtime: Invalid data: %s"), value);
|
// LOG_WARNING("Setting switchtime: Invalid data: %s", value);
|
||||||
// LOG_WARNING(F("Setting switchtime: Invalid data: %02d.%1d.0x%02X.%1d"), no, day, time, on);
|
// LOG_WARNING("Setting switchtime: Invalid data: %02d.%1d.0x%02X.%1d", no, day, time, on);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (data[0] != 0xE7) {
|
if (data[0] != 0xE7) {
|
||||||
// we use EN settings for the day abbreviation
|
// we use EN settings for the day abbreviation
|
||||||
std::string sday = read_flash_string(FL_(enum_dayOfWeek)[day][0]);
|
std::string sday = (FL_(enum_dayOfWeek)[day][0]);
|
||||||
// std::string sday = Helpers::translated_word(FL_(enum_dayOfWeek)[day]);
|
|
||||||
if (model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_N) {
|
if (model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_N) {
|
||||||
snprintf(out, len, "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), on ? "on" : "off");
|
snprintf(out, len, "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), on ? "on" : "off");
|
||||||
} else if ((model() == EMS_DEVICE_FLAG_RC20) || (model() == EMS_DEVICE_FLAG_RC30)) {
|
} else if ((model() == EMS_DEVICE_FLAG_RC20) || (model() == EMS_DEVICE_FLAG_RC30)) {
|
||||||
snprintf(out, len, "%02d %s %02d:%02d T%d", no, sday.c_str(), time / 6, 10 * (time % 6), on);
|
snprintf(out, len, "%02d %s %02d:%02d T%d", no, sday.c_str(), time / 6, 10 * (time % 6), on);
|
||||||
} else {
|
} else {
|
||||||
std::string son = read_flash_string(FL_(enum_switchmode)[on][0]);
|
std::string son = (FL_(enum_switchmode)[on][0]);
|
||||||
// std::string son = Helpers::translated_word(FL_(enum_switchmode)[on]);
|
|
||||||
snprintf(out, len, "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), son.c_str());
|
snprintf(out, len, "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), son.c_str());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -3382,6 +3390,13 @@ void Thermostat::register_device_values() {
|
|||||||
FL_(dateTime),
|
FL_(dateTime),
|
||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_datetime));
|
MAKE_CF_CB(set_datetime));
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&ibaCalIntTemperature_,
|
||||||
|
DeviceValueType::INT,
|
||||||
|
DeviceValueNumOp::DV_NUMOP_DIV10,
|
||||||
|
FL_(ibaCalIntTemperature),
|
||||||
|
DeviceValueUOM::DEGREES_R,
|
||||||
|
MAKE_CF_CB(set_calinttemp));
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&floordrystatus_,
|
&floordrystatus_,
|
||||||
DeviceValueType::ENUM,
|
DeviceValueType::ENUM,
|
||||||
@@ -3506,12 +3521,6 @@ void Thermostat::register_device_values() {
|
|||||||
FL_(ibaLanguage),
|
FL_(ibaLanguage),
|
||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_language));
|
MAKE_CF_CB(set_language));
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
|
||||||
&ibaMainDisplay_,
|
|
||||||
DeviceValueType::ENUM,
|
|
||||||
FL_(enum_ibaMainDisplay),
|
|
||||||
FL_(ibaMainDisplay),
|
|
||||||
DeviceValueUOM::NONE);
|
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &backlight_, DeviceValueType::BOOL, FL_(backlight), DeviceValueUOM::NONE, MAKE_CF_CB(set_backlight));
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &backlight_, DeviceValueType::BOOL, FL_(backlight), DeviceValueUOM::NONE, MAKE_CF_CB(set_backlight));
|
||||||
register_device_value(
|
register_device_value(
|
||||||
DeviceValueTAG::TAG_DEVICE_DATA, &brightness_, DeviceValueType::INT, FL_(brightness), DeviceValueUOM::NONE, MAKE_CF_CB(set_brightness), -15, 15);
|
DeviceValueTAG::TAG_DEVICE_DATA, &brightness_, DeviceValueType::INT, FL_(brightness), DeviceValueUOM::NONE, MAKE_CF_CB(set_brightness), -15, 15);
|
||||||
@@ -3599,13 +3608,15 @@ void Thermostat::register_device_values() {
|
|||||||
DeviceValueType::ENUM,
|
DeviceValueType::ENUM,
|
||||||
FL_(enum_ibaMainDisplay),
|
FL_(enum_ibaMainDisplay),
|
||||||
FL_(ibaMainDisplay),
|
FL_(ibaMainDisplay),
|
||||||
DeviceValueUOM::NONE);
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_display));
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &ibaLanguage_, DeviceValueType::ENUM, FL_(enum_ibaLanguage), FL_(ibaLanguage), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &ibaLanguage_, DeviceValueType::ENUM, FL_(enum_ibaLanguage), FL_(ibaLanguage), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&ibaClockOffset_,
|
&ibaClockOffset_,
|
||||||
DeviceValueType::INT,
|
DeviceValueType::INT,
|
||||||
FL_(ibaClockOffset),
|
FL_(ibaClockOffset),
|
||||||
DeviceValueUOM::SECONDS); // offset (in sec) to clock, 0xff=-1s, 0x02=2s
|
DeviceValueUOM::SECONDS,
|
||||||
|
MAKE_CF_CB(set_clockoffset)); // offset (in sec) to clock, 0xff=-1s, 0x02=2s
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&ibaCalIntTemperature_,
|
&ibaCalIntTemperature_,
|
||||||
DeviceValueType::INT,
|
DeviceValueType::INT,
|
||||||
@@ -3840,8 +3851,9 @@ void Thermostat::register_device_values() {
|
|||||||
MAKE_CF_CB(set_wwVacation));
|
MAKE_CF_CB(set_wwVacation));
|
||||||
break;
|
break;
|
||||||
case EMS_DEVICE_FLAG_JUNKERS:
|
case EMS_DEVICE_FLAG_JUNKERS:
|
||||||
|
// FR100 is not writable, see. https://github.com/emsesp/EMS-ESP32/issues/536
|
||||||
|
// FW500 is not writable, see. https://github.com/emsesp/EMS-ESP32/issues/666
|
||||||
if (has_flags(EMS_DEVICE_FLAG_JUNKERS_OLD)) {
|
if (has_flags(EMS_DEVICE_FLAG_JUNKERS_OLD)) {
|
||||||
// FR100 is not writable, see. https://github.com/emsesp/EMS-ESP32/issues/536
|
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dateTime_, DeviceValueType::STRING, FL_(tpl_datetime), FL_(dateTime), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dateTime_, DeviceValueType::STRING, FL_(tpl_datetime), FL_(dateTime), DeviceValueUOM::NONE);
|
||||||
} else {
|
} else {
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
@@ -3950,7 +3962,7 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
|
|||||||
register_device_value(tag, &hc->selTemp, DeviceValueType::SHORT, seltemp_divider, FL_(selRoomTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_temp), 0, 30);
|
register_device_value(tag, &hc->selTemp, DeviceValueType::SHORT, seltemp_divider, FL_(selRoomTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_temp), 0, 30);
|
||||||
}
|
}
|
||||||
register_device_value(tag, &hc->roomTemp, DeviceValueType::SHORT, roomtemp_divider, FL_(roomTemp), DeviceValueUOM::DEGREES);
|
register_device_value(tag, &hc->roomTemp, DeviceValueType::SHORT, roomtemp_divider, FL_(roomTemp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(tag, &hc->climate, DeviceValueType::ENUM, FL_(enum_climate), FL_(climate), DeviceValueUOM::NONE);
|
register_device_value(tag, &hc->climate, DeviceValueType::ENUM, FL_(enum_climate), FL_(climate), DeviceValueUOM::NONE, nullptr, 5, 30);
|
||||||
|
|
||||||
switch (model) {
|
switch (model) {
|
||||||
case EMS_DEVICE_FLAG_RC10:
|
case EMS_DEVICE_FLAG_RC10:
|
||||||
@@ -4135,9 +4147,16 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
|
|||||||
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_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->modetype, DeviceValueType::ENUM, FL_(enum_modetype3), FL_(modetype), DeviceValueUOM::NONE);
|
||||||
register_device_value(
|
register_device_value(
|
||||||
tag, &hc->daytemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(daytemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_daytemp));
|
tag, &hc->daytemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(daytemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_daytemp), 5, 30);
|
||||||
register_device_value(
|
register_device_value(tag,
|
||||||
tag, &hc->nighttemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(nighttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nighttemp));
|
&hc->nighttemp,
|
||||||
|
DeviceValueType::UINT,
|
||||||
|
DeviceValueNumOp::DV_NUMOP_DIV2,
|
||||||
|
FL_(nighttemp),
|
||||||
|
DeviceValueUOM::DEGREES,
|
||||||
|
MAKE_CF_CB(set_nighttemp),
|
||||||
|
5,
|
||||||
|
30);
|
||||||
register_device_value(tag, &hc->designtemp, DeviceValueType::UINT, FL_(designtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_designtemp), 30, 90);
|
register_device_value(tag, &hc->designtemp, DeviceValueType::UINT, FL_(designtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_designtemp), 30, 90);
|
||||||
register_device_value(tag,
|
register_device_value(tag,
|
||||||
&hc->offsettemp,
|
&hc->offsettemp,
|
||||||
@@ -4154,7 +4173,9 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
|
|||||||
DeviceValueNumOp::DV_NUMOP_DIV2,
|
DeviceValueNumOp::DV_NUMOP_DIV2,
|
||||||
FL_(holidaytemp),
|
FL_(holidaytemp),
|
||||||
DeviceValueUOM::DEGREES,
|
DeviceValueUOM::DEGREES,
|
||||||
MAKE_CF_CB(set_holidaytemp));
|
MAKE_CF_CB(set_holidaytemp),
|
||||||
|
5,
|
||||||
|
30);
|
||||||
register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, FL_(targetflowtemp), DeviceValueUOM::DEGREES);
|
register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, FL_(targetflowtemp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(tag, &hc->summertemp, DeviceValueType::UINT, FL_(summertemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_summertemp), 9, 25);
|
register_device_value(tag, &hc->summertemp, DeviceValueType::UINT, FL_(summertemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_summertemp), 9, 25);
|
||||||
register_device_value(tag, &hc->summermode, DeviceValueType::ENUM, FL_(enum_summer), FL_(summermode), DeviceValueUOM::NONE);
|
register_device_value(tag, &hc->summermode, DeviceValueType::ENUM, FL_(enum_summer), FL_(summermode), DeviceValueUOM::NONE);
|
||||||
@@ -4183,7 +4204,9 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
|
|||||||
DeviceValueNumOp::DV_NUMOP_DIV2,
|
DeviceValueNumOp::DV_NUMOP_DIV2,
|
||||||
FL_(tempautotemp),
|
FL_(tempautotemp),
|
||||||
DeviceValueUOM::DEGREES,
|
DeviceValueUOM::DEGREES,
|
||||||
MAKE_CF_CB(set_tempautotemp));
|
MAKE_CF_CB(set_tempautotemp),
|
||||||
|
0,
|
||||||
|
30);
|
||||||
register_device_value(tag, &hc->noreducetemp, DeviceValueType::INT, FL_(noreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_noreducetemp), -30, 10);
|
register_device_value(tag, &hc->noreducetemp, DeviceValueType::INT, FL_(noreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_noreducetemp), -30, 10);
|
||||||
register_device_value(tag, &hc->reducetemp, DeviceValueType::INT, FL_(reducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_reducetemp), -20, 10);
|
register_device_value(tag, &hc->reducetemp, DeviceValueType::INT, FL_(reducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_reducetemp), -20, 10);
|
||||||
register_device_value(tag, &hc->vacreducetemp, DeviceValueType::INT, FL_(vacreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_vacreducetemp), -20, 10);
|
register_device_value(tag, &hc->vacreducetemp, DeviceValueType::INT, FL_(vacreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_vacreducetemp), -20, 10);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace emsesp {
|
|||||||
|
|
||||||
class Thermostat : public EMSdevice {
|
class Thermostat : public EMSdevice {
|
||||||
public:
|
public:
|
||||||
Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand);
|
Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
|
||||||
class HeatingCircuit {
|
class HeatingCircuit {
|
||||||
public:
|
public:
|
||||||
HeatingCircuit(const uint8_t hc_num, const uint8_t model)
|
HeatingCircuit(const uint8_t hc_num, const uint8_t model)
|
||||||
|
|||||||
@@ -44,69 +44,69 @@ bool EMSdevice::has_entities() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string EMSdevice::tag_to_string(uint8_t tag) {
|
std::string EMSdevice::tag_to_string(uint8_t tag) {
|
||||||
return read_flash_string(DeviceValue::DeviceValueTAG_s[tag]);
|
return (DeviceValue::DeviceValueTAG_s[tag]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EMSdevice::tag_to_mqtt(uint8_t tag) {
|
std::string EMSdevice::tag_to_mqtt(uint8_t tag) {
|
||||||
return read_flash_string(DeviceValue::DeviceValueTAG_mqtt[tag]);
|
return (DeviceValue::DeviceValueTAG_mqtt[tag]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert UOM to a string - these don't need translating
|
// convert UOM to a string - these don't need translating
|
||||||
std::string EMSdevice::uom_to_string(uint8_t uom) {
|
std::string EMSdevice::uom_to_string(uint8_t uom) {
|
||||||
if (EMSESP::system_.fahrenheit() && (uom == DeviceValueUOM::DEGREES || uom == DeviceValueUOM::DEGREES_R)) {
|
if (EMSESP::system_.fahrenheit() && (uom == DeviceValueUOM::DEGREES || uom == DeviceValueUOM::DEGREES_R)) {
|
||||||
return read_flash_string(DeviceValue::DeviceValueUOM_s[DeviceValueUOM::FAHRENHEIT]);
|
return (DeviceValue::DeviceValueUOM_s[DeviceValueUOM::FAHRENHEIT]);
|
||||||
}
|
}
|
||||||
return read_flash_string(DeviceValue::DeviceValueUOM_s[uom]);
|
return (DeviceValue::DeviceValueUOM_s[uom]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EMSdevice::brand_to_string() const {
|
std::string EMSdevice::brand_to_string() const {
|
||||||
switch (brand_) {
|
switch (brand_) {
|
||||||
case EMSdevice::Brand::BOSCH:
|
case EMSdevice::Brand::BOSCH:
|
||||||
return read_flash_string(F("Bosch"));
|
return ("Bosch");
|
||||||
case EMSdevice::Brand::JUNKERS:
|
case EMSdevice::Brand::JUNKERS:
|
||||||
return read_flash_string(F("Junkers"));
|
return ("Junkers");
|
||||||
case EMSdevice::Brand::BUDERUS:
|
case EMSdevice::Brand::BUDERUS:
|
||||||
return read_flash_string(F("Buderus"));
|
return ("Buderus");
|
||||||
case EMSdevice::Brand::NEFIT:
|
case EMSdevice::Brand::NEFIT:
|
||||||
return read_flash_string(F("Nefit"));
|
return ("Nefit");
|
||||||
case EMSdevice::Brand::SIEGER:
|
case EMSdevice::Brand::SIEGER:
|
||||||
return read_flash_string(F("Sieger"));
|
return ("Sieger");
|
||||||
case EMSdevice::Brand::WORCESTER:
|
case EMSdevice::Brand::WORCESTER:
|
||||||
return read_flash_string(F("Worcester"));
|
return ("Worcester");
|
||||||
case EMSdevice::Brand::IVT:
|
case EMSdevice::Brand::IVT:
|
||||||
return read_flash_string(F("IVT"));
|
return ("IVT");
|
||||||
default:
|
default:
|
||||||
return read_flash_string(F(""));
|
return ("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the name of the MQTT topic to use for a specific device, without the base
|
// returns the name of the MQTT topic to use for a specific device, without the base
|
||||||
std::string EMSdevice::device_type_2_device_name(const uint8_t device_type) {
|
const char * EMSdevice::device_type_2_device_name(const uint8_t device_type) {
|
||||||
switch (device_type) {
|
switch (device_type) {
|
||||||
case DeviceType::SYSTEM:
|
case DeviceType::SYSTEM:
|
||||||
return read_flash_string(F_(system));
|
return (F_(system));
|
||||||
case DeviceType::BOILER:
|
case DeviceType::BOILER:
|
||||||
return read_flash_string(F_(boiler));
|
return (F_(boiler));
|
||||||
case DeviceType::THERMOSTAT:
|
case DeviceType::THERMOSTAT:
|
||||||
return read_flash_string(F_(thermostat));
|
return (F_(thermostat));
|
||||||
case DeviceType::HEATPUMP:
|
case DeviceType::HEATPUMP:
|
||||||
return read_flash_string(F_(heatpump));
|
return (F_(heatpump));
|
||||||
case DeviceType::SOLAR:
|
case DeviceType::SOLAR:
|
||||||
return read_flash_string(F_(solar));
|
return (F_(solar));
|
||||||
case DeviceType::CONNECT:
|
case DeviceType::CONNECT:
|
||||||
return read_flash_string(F_(connect));
|
return (F_(connect));
|
||||||
case DeviceType::MIXER:
|
case DeviceType::MIXER:
|
||||||
return read_flash_string(F_(mixer));
|
return (F_(mixer));
|
||||||
case DeviceType::DALLASSENSOR:
|
case DeviceType::DALLASSENSOR:
|
||||||
return read_flash_string(F_(dallassensor));
|
return (F_(dallassensor));
|
||||||
case DeviceType::ANALOGSENSOR:
|
case DeviceType::ANALOGSENSOR:
|
||||||
return read_flash_string(F_(analogsensor));
|
return (F_(analogsensor));
|
||||||
case DeviceType::CONTROLLER:
|
case DeviceType::CONTROLLER:
|
||||||
return read_flash_string(F_(controller));
|
return (F_(controller));
|
||||||
case DeviceType::SWITCH:
|
case DeviceType::SWITCH:
|
||||||
return read_flash_string(F_(switch));
|
return (F_(switch));
|
||||||
case DeviceType::GATEWAY:
|
case DeviceType::GATEWAY:
|
||||||
return read_flash_string(F_(gateway));
|
return (F_(gateway));
|
||||||
default:
|
default:
|
||||||
return Helpers::translated_word(FL_(unknown));
|
return Helpers::translated_word(FL_(unknown));
|
||||||
}
|
}
|
||||||
@@ -193,11 +193,11 @@ uint8_t EMSdevice::decode_brand(uint8_t value) {
|
|||||||
std::string EMSdevice::to_string() const {
|
std::string EMSdevice::to_string() const {
|
||||||
// for devices that haven't been lookup yet, don't show all details
|
// for devices that haven't been lookup yet, don't show all details
|
||||||
if (product_id_ == 0) {
|
if (product_id_ == 0) {
|
||||||
return name_ + " (DeviceID:" + Helpers::hextoa(device_id_) + ")";
|
return std::string(name_) + " (DeviceID:" + Helpers::hextoa(device_id_) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (brand_ == Brand::NO_BRAND) {
|
if (brand_ == Brand::NO_BRAND) {
|
||||||
return name_ + " (DeviceID:" + Helpers::hextoa(device_id_) + ", ProductID:" + Helpers::itoa(product_id_) + ", Version:" + version_ + ")";
|
return std::string(name_) + " (DeviceID:" + Helpers::hextoa(device_id_) + ", ProductID:" + Helpers::itoa(product_id_) + ", Version:" + version_ + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
return brand_to_string() + " " + name_ + " (DeviceID:" + Helpers::hextoa(device_id_) + ", ProductID:" + Helpers::itoa(product_id_) + ", Version:" + version_
|
return brand_to_string() + " " + name_ + " (DeviceID:" + Helpers::hextoa(device_id_) + ", ProductID:" + Helpers::itoa(product_id_) + ", Version:" + version_
|
||||||
@@ -215,7 +215,7 @@ std::string EMSdevice::to_string_short() const {
|
|||||||
|
|
||||||
// for each telegram that has the fetch value set (true) do a read request
|
// for each telegram that has the fetch value set (true) do a read request
|
||||||
void EMSdevice::fetch_values() {
|
void EMSdevice::fetch_values() {
|
||||||
EMSESP::logger().debug(F("Fetching values for deviceID 0x%02X"), device_id());
|
EMSESP::logger().debug("Fetching values for deviceID 0x%02X", device_id());
|
||||||
|
|
||||||
for (const auto & tf : telegram_functions_) {
|
for (const auto & tf : telegram_functions_) {
|
||||||
if (tf.fetch_) {
|
if (tf.fetch_) {
|
||||||
@@ -226,7 +226,7 @@ void EMSdevice::fetch_values() {
|
|||||||
|
|
||||||
// toggle on/off automatic fetch for a telegramID
|
// toggle on/off automatic fetch for a telegramID
|
||||||
void EMSdevice::toggle_fetch(uint16_t telegram_id, bool toggle) {
|
void EMSdevice::toggle_fetch(uint16_t telegram_id, bool toggle) {
|
||||||
EMSESP::logger().debug(F("Toggling fetch for deviceID 0x%02X, telegramID 0x%02X to %d"), device_id(), telegram_id, toggle);
|
EMSESP::logger().debug("Toggling fetch for deviceID 0x%02X, telegramID 0x%02X to %d", device_id(), telegram_id, toggle);
|
||||||
|
|
||||||
for (auto & tf : telegram_functions_) {
|
for (auto & tf : telegram_functions_) {
|
||||||
if (tf.telegram_type_id_ == telegram_id) {
|
if (tf.telegram_type_id_ == telegram_id) {
|
||||||
@@ -259,14 +259,14 @@ bool EMSdevice::has_tag(const uint8_t tag) const {
|
|||||||
// called from the command 'entities'
|
// called from the command 'entities'
|
||||||
void EMSdevice::list_device_entries(JsonObject & output) const {
|
void EMSdevice::list_device_entries(JsonObject & output) const {
|
||||||
for (const auto & dv : devicevalues_) {
|
for (const auto & dv : devicevalues_) {
|
||||||
std::string fullname = dv.get_fullname();
|
auto fullname = dv.get_fullname();
|
||||||
if (!dv.has_state(DeviceValueState::DV_WEB_EXCLUDE) && dv.type != DeviceValueType::CMD && !fullname.empty()) {
|
if (!dv.has_state(DeviceValueState::DV_WEB_EXCLUDE) && dv.type != DeviceValueType::CMD && !fullname.empty()) {
|
||||||
// if we have a tag prefix it
|
// if we have a tag prefix it
|
||||||
char key[50];
|
char key[50];
|
||||||
if (!EMSdevice::tag_to_mqtt(dv.tag).empty()) {
|
if (!EMSdevice::tag_to_mqtt(dv.tag).empty()) {
|
||||||
snprintf(key, sizeof(key), "%s.%s", EMSdevice::tag_to_mqtt(dv.tag).c_str(), read_flash_string(dv.short_name).c_str());
|
snprintf(key, sizeof(key), "%s.%s", EMSdevice::tag_to_mqtt(dv.tag).c_str(), (dv.short_name));
|
||||||
} else {
|
} else {
|
||||||
snprintf(key, sizeof(key), "%s", read_flash_string(dv.short_name).c_str());
|
snprintf(key, sizeof(key), "%s", (dv.short_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArray details = output.createNestedArray(key);
|
JsonArray details = output.createNestedArray(key);
|
||||||
@@ -289,7 +289,7 @@ void EMSdevice::show_telegram_handlers(uuid::console::Shell & shell) const {
|
|||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
// colored list of type-ids
|
// colored list of type-ids
|
||||||
shell.printf(F(" This %s will listen to telegram type IDs: "), device_type_name().c_str());
|
shell.printf(" This %s will listen to telegram type IDs: ", device_type_name().c_str());
|
||||||
for (const auto & tf : telegram_functions_) {
|
for (const auto & tf : telegram_functions_) {
|
||||||
if (tf.received_ && !tf.fetch_) {
|
if (tf.received_ && !tf.fetch_) {
|
||||||
shell.printf(COLOR_BRIGHT_GREEN);
|
shell.printf(COLOR_BRIGHT_GREEN);
|
||||||
@@ -298,34 +298,34 @@ void EMSdevice::show_telegram_handlers(uuid::console::Shell & shell) const {
|
|||||||
} else {
|
} else {
|
||||||
shell.printf(COLOR_BRIGHT_RED);
|
shell.printf(COLOR_BRIGHT_RED);
|
||||||
}
|
}
|
||||||
shell.printf(F("0x%02X "), tf.telegram_type_id_);
|
shell.printf("0x%02X ", tf.telegram_type_id_);
|
||||||
}
|
}
|
||||||
shell.printf(COLOR_RESET);
|
shell.printf(COLOR_RESET);
|
||||||
*/
|
*/
|
||||||
shell.printf(F(" Received telegram type IDs: "));
|
shell.printf(" Received telegram type IDs: ");
|
||||||
for (const auto & tf : telegram_functions_) {
|
for (const auto & tf : telegram_functions_) {
|
||||||
if (tf.received_ && !tf.fetch_) {
|
if (tf.received_ && !tf.fetch_) {
|
||||||
shell.printf(F("0x%02X "), tf.telegram_type_id_);
|
shell.printf("0x%02X ", tf.telegram_type_id_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shell.println();
|
shell.println();
|
||||||
shell.printf(F(" Fetched telegram type IDs: "));
|
shell.printf(" Fetched telegram type IDs: ");
|
||||||
for (const auto & tf : telegram_functions_) {
|
for (const auto & tf : telegram_functions_) {
|
||||||
if (tf.fetch_) {
|
if (tf.fetch_) {
|
||||||
shell.printf(F("0x%02X "), tf.telegram_type_id_);
|
shell.printf("0x%02X ", tf.telegram_type_id_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shell.println();
|
shell.println();
|
||||||
shell.printf(F(" Pending telegram type IDs: "));
|
shell.printf(" Pending telegram type IDs: ");
|
||||||
for (const auto & tf : telegram_functions_) {
|
for (const auto & tf : telegram_functions_) {
|
||||||
if (!tf.received_ && !tf.fetch_) {
|
if (!tf.received_ && !tf.fetch_) {
|
||||||
shell.printf(F("0x%02X "), tf.telegram_type_id_);
|
shell.printf("0x%02X ", tf.telegram_type_id_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shell.println();
|
shell.println();
|
||||||
shell.printf(F(" Ignored telegram type IDs: "));
|
shell.printf(" Ignored telegram type IDs: ");
|
||||||
for (auto handlers : handlers_ignored_) {
|
for (auto handlers : handlers_ignored_) {
|
||||||
shell.printf(F("0x%02X "), handlers);
|
shell.printf("0x%02X ", handlers);
|
||||||
}
|
}
|
||||||
shell.println();
|
shell.println();
|
||||||
}
|
}
|
||||||
@@ -379,7 +379,7 @@ void EMSdevice::show_mqtt_handlers(uuid::console::Shell & shell) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// register a callback function for a specific telegram type
|
// register a callback function for a specific telegram type
|
||||||
void EMSdevice::register_telegram_type(const uint16_t telegram_type_id, const __FlashStringHelper * telegram_type_name, bool fetch, const process_function_p f) {
|
void EMSdevice::register_telegram_type(const uint16_t telegram_type_id, const char * telegram_type_name, bool fetch, const process_function_p f) {
|
||||||
telegram_functions_.emplace_back(telegram_type_id, telegram_type_name, fetch, false, f);
|
telegram_functions_.emplace_back(telegram_type_id, telegram_type_name, fetch, false, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,28 +390,34 @@ void EMSdevice::register_telegram_type(const uint16_t telegram_type_id, const __
|
|||||||
// type: one of DeviceValueType
|
// type: one of DeviceValueType
|
||||||
// options: options for enum, which are translated as a list of lists
|
// options: options for enum, which are translated as a list of lists
|
||||||
// options_single: list of names
|
// options_single: list of names
|
||||||
// numeric_operatpr: to divide or multiply, see DeviceValueNumOps::
|
// numeric_operator: to divide or multiply, see DeviceValueNumOps::
|
||||||
// short_name: used in Mqtt as keys
|
// short_name: used in MQTT as keys
|
||||||
// fullname: used in Web and Console unless empty (nullptr) - can be translated
|
// fullname: used in Web and Console unless empty (nullptr) - can be translated
|
||||||
// uom: unit of measure from DeviceValueUOM
|
// uom: unit of measure from DeviceValueUOM
|
||||||
// has_cmd: true if this is an associated command
|
// has_cmd: true if this is an associated command
|
||||||
// min: min allowed value
|
// min: min allowed value
|
||||||
// max: max allowed value
|
// max: max allowed value
|
||||||
void EMSdevice::add_device_value(uint8_t tag,
|
void EMSdevice::add_device_value(uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
const __FlashStringHelper * const ** options,
|
const char * const ** options,
|
||||||
const __FlashStringHelper * const * options_single,
|
const char * const * options_single,
|
||||||
int8_t numeric_operator,
|
int8_t numeric_operator,
|
||||||
const __FlashStringHelper * const * name,
|
const char * const * name,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
const cmd_function_p f,
|
const cmd_function_p f,
|
||||||
int16_t min,
|
int16_t min,
|
||||||
uint16_t max) {
|
uint16_t max) {
|
||||||
bool has_cmd = (f != nullptr);
|
bool has_cmd = (f != nullptr);
|
||||||
|
|
||||||
auto short_name = name[0];
|
auto short_name = name[0];
|
||||||
const class __FlashStringHelper * const * fullname = &name[1]; // translations start at index 1
|
|
||||||
|
const char * const * fullname;
|
||||||
|
if (Helpers::count_items(name) == 1) {
|
||||||
|
fullname = nullptr; // no translations available, use empty to prevent crash
|
||||||
|
} else {
|
||||||
|
fullname = &name[1]; // translations start at index 1
|
||||||
|
}
|
||||||
|
|
||||||
// initialize the device value depending on it's type
|
// initialize the device value depending on it's type
|
||||||
if (type == DeviceValueType::STRING) {
|
if (type == DeviceValueType::STRING) {
|
||||||
@@ -440,7 +446,7 @@ void EMSdevice::add_device_value(uint8_t tag,
|
|||||||
EMSESP::webCustomizationService.read([&](WebCustomization & settings) {
|
EMSESP::webCustomizationService.read([&](WebCustomization & settings) {
|
||||||
for (EntityCustomization entityCustomization : settings.entityCustomizations) {
|
for (EntityCustomization entityCustomization : settings.entityCustomizations) {
|
||||||
if ((entityCustomization.product_id == product_id()) && (entityCustomization.device_id == device_id())) {
|
if ((entityCustomization.product_id == product_id()) && (entityCustomization.device_id == device_id())) {
|
||||||
std::string entity = tag < DeviceValueTAG::TAG_HC1 ? read_flash_string(short_name) : tag_to_string(tag) + "/" + read_flash_string(short_name);
|
std::string entity = tag < DeviceValueTAG::TAG_HC1 ? (short_name) : tag_to_string(tag) + "/" + (short_name);
|
||||||
for (std::string entity_id : entityCustomization.entity_ids) {
|
for (std::string entity_id : entityCustomization.entity_ids) {
|
||||||
// if there is an appended custom name, strip it to get the true entity name
|
// if there is an appended custom name, strip it to get the true entity name
|
||||||
// and extract the new custom name
|
// and extract the new custom name
|
||||||
@@ -472,7 +478,6 @@ void EMSdevice::add_device_value(uint8_t tag,
|
|||||||
// add the device entity
|
// add the device entity
|
||||||
devicevalues_.emplace_back(
|
devicevalues_.emplace_back(
|
||||||
device_type_, tag, value_p, type, options, options_single, numeric_operator, short_name, fullname, custom_fullname, uom, has_cmd, min, max, state);
|
device_type_, tag, value_p, type, options, options_single, numeric_operator, short_name, fullname, custom_fullname, uom, has_cmd, min, max, state);
|
||||||
devicevalues_.back().set_custom_minmax();
|
|
||||||
|
|
||||||
// add a new command if it has a function attached
|
// add a new command if it has a function attached
|
||||||
if (!has_cmd) {
|
if (!has_cmd) {
|
||||||
@@ -490,108 +495,102 @@ void EMSdevice::add_device_value(uint8_t tag,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add the command to our library
|
// add the command to our library
|
||||||
// cmd is the short_name and the description is the fullname (not the custom fullname)
|
Command::add(device_type_, short_name, f, fullname, flags);
|
||||||
Command::add(device_type_, short_name, f, Helpers::translated_fword(fullname), flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// single list of options
|
// single list of options
|
||||||
void EMSdevice::register_device_value(uint8_t tag,
|
void EMSdevice::register_device_value(uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
const __FlashStringHelper * const * options_single,
|
const char * const * options_single,
|
||||||
const __FlashStringHelper * const * name,
|
const char * const * name,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
const cmd_function_p f) {
|
const cmd_function_p f) {
|
||||||
// create a multi-list from the options
|
// create a multi-list from the options
|
||||||
add_device_value(tag, value_p, type, nullptr, options_single, 0, name, uom, f, 0, 0);
|
add_device_value(tag, value_p, type, nullptr, options_single, 0, name, uom, f, 0, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
// single list of options, with no translations, with min and max
|
// single list of options, with no translations, with min and max
|
||||||
void EMSdevice::register_device_value(uint8_t tag,
|
void EMSdevice::register_device_value(uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
const __FlashStringHelper * const * options_single,
|
const char * const * options_single,
|
||||||
const __FlashStringHelper * const * name,
|
const char * const * name,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
const cmd_function_p f,
|
const cmd_function_p f,
|
||||||
int16_t min,
|
int16_t min,
|
||||||
uint16_t max) {
|
uint16_t max) {
|
||||||
// create a multi-list from the options
|
// create a multi-list from the options
|
||||||
add_device_value(tag, value_p, type, nullptr, options_single, 0, name, uom, f, min, max);
|
add_device_value(tag, value_p, type, nullptr, options_single, 0, name, uom, f, min, max);
|
||||||
};
|
};
|
||||||
|
|
||||||
void EMSdevice::register_device_value(uint8_t tag,
|
void EMSdevice::register_device_value(uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
int8_t numeric_operator,
|
int8_t numeric_operator,
|
||||||
const __FlashStringHelper * const * name,
|
const char * const * name,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
const cmd_function_p f) {
|
const cmd_function_p f) {
|
||||||
add_device_value(tag, value_p, type, nullptr, nullptr, numeric_operator, name, uom, f, 0, 0);
|
add_device_value(tag, value_p, type, nullptr, nullptr, numeric_operator, name, uom, f, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EMSdevice::register_device_value(uint8_t tag,
|
void EMSdevice::register_device_value(uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
int8_t numeric_operator,
|
int8_t numeric_operator,
|
||||||
const __FlashStringHelper * const * name,
|
const char * const * name,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
const cmd_function_p f,
|
const cmd_function_p f,
|
||||||
int16_t min,
|
int16_t min,
|
||||||
uint16_t max) {
|
uint16_t max) {
|
||||||
add_device_value(tag, value_p, type, nullptr, nullptr, numeric_operator, name, uom, f, min, max);
|
add_device_value(tag, value_p, type, nullptr, nullptr, numeric_operator, name, uom, f, min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no options, no function
|
// no options, no function
|
||||||
void EMSdevice::register_device_value(uint8_t tag, void * value_p, uint8_t type, const __FlashStringHelper * const * name, uint8_t uom, const cmd_function_p f) {
|
void EMSdevice::register_device_value(uint8_t tag, void * value_p, uint8_t type, const char * const * name, uint8_t uom, const cmd_function_p f) {
|
||||||
add_device_value(tag, value_p, type, nullptr, nullptr, 0, name, uom, f, 0, 0);
|
add_device_value(tag, value_p, type, nullptr, nullptr, 0, name, uom, f, 0, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
// no options, with min/max
|
// no options, with min/max
|
||||||
void EMSdevice::register_device_value(uint8_t tag,
|
void EMSdevice::register_device_value(uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
const __FlashStringHelper * const * name,
|
const char * const * name,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
const cmd_function_p f,
|
const cmd_function_p f,
|
||||||
int16_t min,
|
int16_t min,
|
||||||
uint16_t max) {
|
uint16_t max) {
|
||||||
add_device_value(tag, value_p, type, nullptr, nullptr, 0, name, uom, f, min, max);
|
add_device_value(tag, value_p, type, nullptr, nullptr, 0, name, uom, f, min, max);
|
||||||
};
|
};
|
||||||
|
|
||||||
// function with min and max values
|
// function with min and max values
|
||||||
// adds a new command to the command list
|
// adds a new command to the command list
|
||||||
// in this function we separate out the short and long names and take any translations
|
// in this function we separate out the short and long names and take any translations
|
||||||
void EMSdevice::register_device_value(uint8_t tag,
|
void EMSdevice::register_device_value(uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
const __FlashStringHelper * const ** options,
|
const char * const ** options,
|
||||||
const __FlashStringHelper * const * name,
|
const char * const * name,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
const cmd_function_p f,
|
const cmd_function_p f,
|
||||||
int16_t min,
|
int16_t min,
|
||||||
uint16_t max) {
|
uint16_t max) {
|
||||||
add_device_value(tag, value_p, type, options, nullptr, 0, name, uom, f, min, max);
|
add_device_value(tag, value_p, type, options, nullptr, 0, name, uom, f, min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
// function with no min and max values (set to 0)
|
// function with no min and max values (set to 0)
|
||||||
void EMSdevice::register_device_value(uint8_t tag,
|
void EMSdevice::register_device_value(uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
const __FlashStringHelper * const ** options,
|
const char * const ** options,
|
||||||
const __FlashStringHelper * const * name,
|
const char * const * name,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
const cmd_function_p f) {
|
const cmd_function_p f) {
|
||||||
add_device_value(tag, value_p, type, options, nullptr, 0, name, uom, f, 0, 0);
|
add_device_value(tag, value_p, type, options, nullptr, 0, name, uom, f, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no associated command function, or min/max values
|
// no associated command function, or min/max values
|
||||||
void EMSdevice::register_device_value(uint8_t tag,
|
void EMSdevice::register_device_value(uint8_t tag, void * value_p, uint8_t type, const char * const ** options, const char * const * name, uint8_t uom) {
|
||||||
void * value_p,
|
|
||||||
uint8_t type,
|
|
||||||
const __FlashStringHelper * const ** options,
|
|
||||||
const __FlashStringHelper * const * name,
|
|
||||||
uint8_t uom) {
|
|
||||||
add_device_value(tag, value_p, type, options, nullptr, 0, name, uom, nullptr, 0, 0);
|
add_device_value(tag, value_p, type, options, nullptr, 0, name, uom, nullptr, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,7 +609,7 @@ 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_) {
|
||||||
// check command name and tag, id -1 is default hc and only checks name
|
// check command name and tag, id -1 is default hc and only checks name
|
||||||
if (dv.has_cmd && read_flash_string(dv.short_name) == cmd && (dv.tag < DeviceValueTAG::TAG_HC1 || dv.tag == tag || id == -1)) {
|
if (dv.has_cmd && std::string(dv.short_name) == cmd && (dv.tag < DeviceValueTAG::TAG_HC1 || dv.tag == tag || id == -1)) {
|
||||||
return dv.has_state(DeviceValueState::DV_READONLY);
|
return dv.has_state(DeviceValueState::DV_READONLY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -638,24 +637,14 @@ void EMSdevice::publish_value(void * value_p) const {
|
|||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
if (Mqtt::publish_single2cmd()) {
|
if (Mqtt::publish_single2cmd()) {
|
||||||
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
snprintf(topic,
|
snprintf(topic, sizeof(topic), "%s/%s/%s", device_type_2_device_name(device_type_), tag_to_mqtt(dv.tag).c_str(), (dv.short_name));
|
||||||
sizeof(topic),
|
|
||||||
"%s/%s/%s",
|
|
||||||
device_type_2_device_name(device_type_).c_str(),
|
|
||||||
tag_to_mqtt(dv.tag).c_str(),
|
|
||||||
read_flash_string(dv.short_name).c_str());
|
|
||||||
} else {
|
} else {
|
||||||
snprintf(topic, sizeof(topic), "%s/%s", device_type_2_device_name(device_type_).c_str(), read_flash_string(dv.short_name).c_str());
|
snprintf(topic, sizeof(topic), "%s/%s", device_type_2_device_name(device_type_), (dv.short_name));
|
||||||
}
|
}
|
||||||
} else if (Mqtt::is_nested() && dv.tag >= DeviceValueTAG::TAG_HC1) {
|
} else if (Mqtt::is_nested() && dv.tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
snprintf(topic,
|
snprintf(topic, sizeof(topic), "%s/%s/%s", Mqtt::tag_to_topic(device_type_, dv.tag).c_str(), tag_to_mqtt(dv.tag).c_str(), (dv.short_name));
|
||||||
sizeof(topic),
|
|
||||||
"%s/%s/%s",
|
|
||||||
Mqtt::tag_to_topic(device_type_, dv.tag).c_str(),
|
|
||||||
tag_to_mqtt(dv.tag).c_str(),
|
|
||||||
read_flash_string(dv.short_name).c_str());
|
|
||||||
} else {
|
} else {
|
||||||
snprintf(topic, sizeof(topic), "%s/%s", Mqtt::tag_to_topic(device_type_, dv.tag).c_str(), read_flash_string(dv.short_name).c_str());
|
snprintf(topic, sizeof(topic), "%s/%s", Mqtt::tag_to_topic(device_type_, dv.tag).c_str(), (dv.short_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t num_op = dv.numeric_operator;
|
int8_t num_op = dv.numeric_operator;
|
||||||
@@ -673,7 +662,7 @@ void EMSdevice::publish_value(void * value_p) const {
|
|||||||
Helpers::render_value(payload, *(uint8_t *)(value_p), 0);
|
Helpers::render_value(payload, *(uint8_t *)(value_p), 0);
|
||||||
} else {
|
} else {
|
||||||
auto enum_str = Helpers::translated_word(dv.options[*(uint8_t *)(value_p)]);
|
auto enum_str = Helpers::translated_word(dv.options[*(uint8_t *)(value_p)]);
|
||||||
strlcpy(payload, enum_str.c_str(), sizeof(payload));
|
strlcpy(payload, enum_str, sizeof(payload));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -717,7 +706,6 @@ void EMSdevice::publish_value(void * value_p) const {
|
|||||||
|
|
||||||
// looks up the UOM for a given key from the device value table
|
// looks up the UOM for a given key from the device value table
|
||||||
// key is the fullname
|
// key is the fullname
|
||||||
// TODO really should be using the shortname as the identifier
|
|
||||||
std::string EMSdevice::get_value_uom(const char * key) const {
|
std::string EMSdevice::get_value_uom(const char * key) const {
|
||||||
// the key may have a TAG string prefixed at the beginning. If so, remove it
|
// the key may have a TAG string prefixed at the beginning. If so, remove it
|
||||||
char new_key[80];
|
char new_key[80];
|
||||||
@@ -725,11 +713,12 @@ std::string EMSdevice::get_value_uom(const char * key) const {
|
|||||||
char * key_p = new_key;
|
char * key_p = new_key;
|
||||||
|
|
||||||
for (uint8_t i = 0; i < DeviceValue::tag_count; i++) {
|
for (uint8_t i = 0; i < DeviceValue::tag_count; i++) {
|
||||||
auto tag = read_flash_string(DeviceValue::DeviceValueTAG_s[i]);
|
auto tag = (DeviceValue::DeviceValueTAG_s[i]);
|
||||||
if (!tag.empty()) {
|
if (tag) {
|
||||||
std::string key2 = key; // copy char to a std::string
|
std::string key2 = key; // copy string to a std::string so we can use the find function
|
||||||
if ((key2.find(tag) != std::string::npos) && (key[tag.length()] == ' ')) {
|
uint8_t length = strlen(tag);
|
||||||
key_p += tag.length() + 1; // remove the tag
|
if ((key2.find(tag) != std::string::npos) && (key[length] == ' ')) {
|
||||||
|
key_p += length + 1; // remove the tag
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -800,9 +789,9 @@ void EMSdevice::generate_values_web(JsonObject & output) {
|
|||||||
} else if ((dv.type == DeviceValueType::USHORT) && Helpers::hasValue(*(uint16_t *)(dv.value_p))) {
|
} else if ((dv.type == DeviceValueType::USHORT) && Helpers::hasValue(*(uint16_t *)(dv.value_p))) {
|
||||||
obj["v"] = Helpers::transformNumFloat(*(uint16_t *)(dv.value_p), dv.numeric_operator, fahrenheit);
|
obj["v"] = Helpers::transformNumFloat(*(uint16_t *)(dv.value_p), dv.numeric_operator, fahrenheit);
|
||||||
} else if ((dv.type == DeviceValueType::ULONG) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
} else if ((dv.type == DeviceValueType::ULONG) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
||||||
obj["v"] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), dv.numeric_operator, fahrenheit);
|
obj["v"] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), dv.numeric_operator);
|
||||||
} else if ((dv.type == DeviceValueType::TIME) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
} else if ((dv.type == DeviceValueType::TIME) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
||||||
obj["v"] = dv.numeric_operator ? (*(uint32_t *)(dv.value_p) / dv.numeric_operator) : *(uint32_t *)(dv.value_p);
|
obj["v"] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), dv.numeric_operator);
|
||||||
} else {
|
} else {
|
||||||
obj["v"] = ""; // must have a value for sorting to work
|
obj["v"] = ""; // must have a value for sorting to work
|
||||||
}
|
}
|
||||||
@@ -824,7 +813,7 @@ void EMSdevice::generate_values_web(JsonObject & output) {
|
|||||||
if (dv.has_cmd && !dv.has_state(DeviceValueState::DV_READONLY)) {
|
if (dv.has_cmd && !dv.has_state(DeviceValueState::DV_READONLY)) {
|
||||||
// add the name of the Command function
|
// add the name of the Command function
|
||||||
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
obj["c"] = tag_to_mqtt(dv.tag) + "/" + read_flash_string(dv.short_name);
|
obj["c"] = tag_to_mqtt(dv.tag) + "/" + (dv.short_name);
|
||||||
} else {
|
} else {
|
||||||
obj["c"] = dv.short_name;
|
obj["c"] = dv.short_name;
|
||||||
}
|
}
|
||||||
@@ -834,7 +823,7 @@ void EMSdevice::generate_values_web(JsonObject & output) {
|
|||||||
JsonArray l = obj.createNestedArray("l");
|
JsonArray l = obj.createNestedArray("l");
|
||||||
for (uint8_t i = 0; i < dv.options_size; i++) {
|
for (uint8_t i = 0; i < dv.options_size; i++) {
|
||||||
auto enum_str = Helpers::translated_word(dv.options[i]);
|
auto enum_str = Helpers::translated_word(dv.options[i]);
|
||||||
if (!enum_str.empty()) {
|
if (enum_str) {
|
||||||
l.add(enum_str);
|
l.add(enum_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -860,7 +849,8 @@ void EMSdevice::generate_values_web(JsonObject & output) {
|
|||||||
obj["s"] = Helpers::render_value(s, (float)(-1) * dv.numeric_operator, 0);
|
obj["s"] = Helpers::render_value(s, (float)(-1) * dv.numeric_operator, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t dv_set_min, dv_set_max;
|
int16_t dv_set_min;
|
||||||
|
uint16_t dv_set_max;
|
||||||
if (dv.get_min_max(dv_set_min, dv_set_max)) {
|
if (dv.get_min_max(dv_set_min, dv_set_max)) {
|
||||||
obj["m"] = Helpers::render_value(s, dv_set_min, 0);
|
obj["m"] = Helpers::render_value(s, dv_set_min, 0);
|
||||||
obj["x"] = Helpers::render_value(s, dv_set_max, 0);
|
obj["x"] = Helpers::render_value(s, dv_set_max, 0);
|
||||||
@@ -900,61 +890,39 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) {
|
|||||||
|
|
||||||
// handle Integers and Floats
|
// handle Integers and Floats
|
||||||
else {
|
else {
|
||||||
int8_t num_op = dv.numeric_operator;
|
|
||||||
bool make_float;
|
|
||||||
if (num_op == 0) {
|
|
||||||
// no changes to number
|
|
||||||
make_float = false;
|
|
||||||
num_op = 1; // so it gets *1
|
|
||||||
} else if (num_op < 0) {
|
|
||||||
// negative numbers, convert to a positive multiplier
|
|
||||||
make_float = false;
|
|
||||||
num_op *= -1;
|
|
||||||
} else {
|
|
||||||
// has a divider, make it a float
|
|
||||||
make_float = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// always convert temperatures to floats with 1 decimal place
|
|
||||||
if ((dv.uom == DeviceValueUOM::DEGREES) || (dv.uom == DeviceValueUOM::DEGREES_R)) {
|
|
||||||
make_float = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dv.type == DeviceValueType::INT) {
|
if (dv.type == DeviceValueType::INT) {
|
||||||
obj["v"] = make_float ? Helpers::transformNumFloat(*(int8_t *)(dv.value_p), num_op, fahrenheit) : *(int8_t *)(dv.value_p) * num_op;
|
obj["v"] = Helpers::transformNumFloat(*(int8_t *)(dv.value_p), dv.numeric_operator, fahrenheit);
|
||||||
} else if (dv.type == DeviceValueType::UINT) {
|
} else if (dv.type == DeviceValueType::UINT) {
|
||||||
obj["v"] = make_float ? Helpers::transformNumFloat(*(uint8_t *)(dv.value_p), num_op, fahrenheit) : *(uint8_t *)(dv.value_p) * num_op;
|
obj["v"] = Helpers::transformNumFloat(*(uint8_t *)(dv.value_p), dv.numeric_operator, fahrenheit);
|
||||||
} else if (dv.type == DeviceValueType::SHORT) {
|
} else if (dv.type == DeviceValueType::SHORT) {
|
||||||
obj["v"] = make_float ? Helpers::transformNumFloat(*(int16_t *)(dv.value_p), num_op, fahrenheit) : *(int16_t *)(dv.value_p) * num_op;
|
obj["v"] = Helpers::transformNumFloat(*(int16_t *)(dv.value_p), dv.numeric_operator, fahrenheit);
|
||||||
} else if (dv.type == DeviceValueType::USHORT) {
|
} else if (dv.type == DeviceValueType::USHORT) {
|
||||||
obj["v"] = make_float ? Helpers::transformNumFloat(*(uint16_t *)(dv.value_p), num_op, fahrenheit) : *(uint16_t *)(dv.value_p) * num_op;
|
obj["v"] = Helpers::transformNumFloat(*(uint16_t *)(dv.value_p), dv.numeric_operator, fahrenheit);
|
||||||
} else if (dv.type == DeviceValueType::ULONG) {
|
} else if (dv.type == DeviceValueType::ULONG) {
|
||||||
obj["v"] = make_float ? Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), num_op) : *(uint32_t *)(dv.value_p) * num_op;
|
obj["v"] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), dv.numeric_operator);
|
||||||
} else if (dv.type == DeviceValueType::TIME) {
|
} else if (dv.type == DeviceValueType::TIME) {
|
||||||
// sometimes we need to divide by 60
|
obj["v"] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), dv.numeric_operator);
|
||||||
obj["v"] = (num_op == DeviceValueNumOp::DV_NUMOP_DIV60) ? (uint32_t)Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), num_op)
|
|
||||||
: *(uint32_t *)(dv.value_p);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// id holds the shortname and must always have a value for the WebUI table to work
|
// id holds the shortname and must always have a value for the WebUI table to work
|
||||||
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
obj["id"] = tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name);
|
obj["id"] = tag_to_string(dv.tag) + "/" + (dv.short_name);
|
||||||
} else {
|
} else {
|
||||||
obj["id"] = read_flash_string(dv.short_name);
|
obj["id"] = (dv.short_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// n is the fullname, and can be optional
|
// n is the fullname, and can be optional
|
||||||
// don't add the fullname if its a command
|
// don't add the fullname if its a command
|
||||||
auto fullname = Helpers::translated_word(dv.fullname);
|
auto fullname = Helpers::translated_word(dv.fullname);
|
||||||
if (dv.type != DeviceValueType::CMD) {
|
if (dv.type != DeviceValueType::CMD) {
|
||||||
if (!fullname.empty()) {
|
if (fullname) {
|
||||||
if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) {
|
if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) {
|
||||||
obj["n"] = fullname;
|
obj["n"] = fullname;
|
||||||
} else {
|
} else {
|
||||||
char name[50];
|
char name[50];
|
||||||
snprintf(name, sizeof(name), "%s %s", tag_to_string(dv.tag).c_str(), fullname.c_str());
|
snprintf(name, sizeof(name), "%s %s", tag_to_string(dv.tag).c_str(), fullname);
|
||||||
obj["n"] = name;
|
obj["n"] = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -965,8 +933,12 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) {
|
|||||||
obj["cn"] = custom_fullname;
|
obj["cn"] = custom_fullname;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// it's a command
|
obj["n"] = "!" + std::string(fullname); // prefix commands with a !
|
||||||
obj["n"] = "!" + fullname; // prefix ! to fullname for commands
|
}
|
||||||
|
|
||||||
|
// add the custom name, is optional
|
||||||
|
if (!dv.custom_fullname.empty()) {
|
||||||
|
obj["cn"] = dv.custom_fullname;
|
||||||
}
|
}
|
||||||
|
|
||||||
obj["m"] = dv.state >> 4; // send back the mask state. We're only interested in the high nibble
|
obj["m"] = dv.state >> 4; // send back the mask state. We're only interested in the high nibble
|
||||||
@@ -986,12 +958,25 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EMSdevice::set_climate_minmax(uint8_t tag, int16_t min, uint16_t max) {
|
||||||
|
for (auto & dv : devicevalues_) {
|
||||||
|
if (dv.tag == tag && dv.short_name == FL_(climate[0])) {
|
||||||
|
if (dv.min != min || dv.max != max) {
|
||||||
|
dv.min = min;
|
||||||
|
dv.max = max;
|
||||||
|
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
||||||
|
Mqtt::publish_ha_climate_config(dv.tag, false, true); // delete topic (remove = true)
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// set mask per device entity based on the id which is prefixed with the 2 char hex mask value
|
// set mask per device entity based on the id which is prefixed with the 2 char hex mask value
|
||||||
// returns true if the entity has a mask set (not 0 the default)
|
// returns true if the entity has a mask set (not 0 the default)
|
||||||
void EMSdevice::setCustomEntity(const std::string & entity_id) {
|
void EMSdevice::setCustomEntity(const std::string & entity_id) {
|
||||||
for (auto & dv : devicevalues_) {
|
for (auto & dv : devicevalues_) {
|
||||||
std::string entity_name =
|
std::string entity_name = dv.tag < DeviceValueTAG::TAG_HC1 ? (dv.short_name) : tag_to_string(dv.tag) + "/" + (dv.short_name);
|
||||||
dv.tag < DeviceValueTAG::TAG_HC1 ? read_flash_string(dv.short_name) : tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name);
|
|
||||||
|
|
||||||
// extra shortname
|
// extra shortname
|
||||||
std::string shortname;
|
std::string shortname;
|
||||||
@@ -1009,7 +994,7 @@ void EMSdevice::setCustomEntity(const std::string & entity_id) {
|
|||||||
uint8_t new_mask = Helpers::hextoint(entity_id.substr(0, 2).c_str()); // first character contains mask flags
|
uint8_t new_mask = Helpers::hextoint(entity_id.substr(0, 2).c_str()); // first character contains mask flags
|
||||||
|
|
||||||
// if it's a new mask, reconfigure HA
|
// if it's a new mask, reconfigure HA
|
||||||
if (Mqtt::ha_enabled() && ((current_mask ^ new_mask) & (DeviceValueState::DV_READONLY >> 4))) {
|
if (Mqtt::ha_enabled() && (has_custom_name || ((current_mask ^ new_mask) & (DeviceValueState::DV_READONLY >> 4)))) {
|
||||||
// remove ha config on change of dv_readonly flag
|
// remove ha config on change of dv_readonly flag
|
||||||
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
||||||
Mqtt::publish_ha_sensor_config(dv, "", "", true); // delete topic (remove = true)
|
Mqtt::publish_ha_sensor_config(dv, "", "", true); // delete topic (remove = true)
|
||||||
@@ -1024,7 +1009,17 @@ void EMSdevice::setCustomEntity(const std::string & entity_id) {
|
|||||||
} else {
|
} else {
|
||||||
dv.custom_fullname = "";
|
dv.custom_fullname = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto min = dv.min;
|
||||||
|
auto max = dv.max;
|
||||||
|
|
||||||
|
// set the min / max
|
||||||
dv.set_custom_minmax();
|
dv.set_custom_minmax();
|
||||||
|
|
||||||
|
if (Mqtt::ha_enabled() && dv.short_name == FL_(seltemp)[0] && (min != dv.min || max != dv.max)) {
|
||||||
|
set_climate_minmax(dv.tag, dv.min, dv.max);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1033,9 +1028,8 @@ void EMSdevice::setCustomEntity(const std::string & entity_id) {
|
|||||||
// populate a string vector with entities that have masks set or have a custom name
|
// populate a string vector with entities that have masks set or have a custom name
|
||||||
void EMSdevice::getCustomEntities(std::vector<std::string> & entity_ids) {
|
void EMSdevice::getCustomEntities(std::vector<std::string> & entity_ids) {
|
||||||
for (const auto & dv : devicevalues_) {
|
for (const auto & dv : devicevalues_) {
|
||||||
std::string entity_name =
|
std::string entity_name = dv.tag < DeviceValueTAG::TAG_HC1 ? (dv.short_name) : tag_to_string(dv.tag) + "/" + (dv.short_name);
|
||||||
dv.tag < DeviceValueTAG::TAG_HC1 ? read_flash_string(dv.short_name) : tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name);
|
uint8_t mask = dv.state >> 4;
|
||||||
uint8_t mask = dv.state >> 4;
|
|
||||||
|
|
||||||
if (mask || !dv.custom_fullname.empty()) {
|
if (mask || !dv.custom_fullname.empty()) {
|
||||||
if (dv.custom_fullname.empty()) {
|
if (dv.custom_fullname.empty()) {
|
||||||
@@ -1073,9 +1067,7 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
|
|||||||
|
|
||||||
// search device value with this tag
|
// search device value with this tag
|
||||||
for (auto & dv : devicevalues_) {
|
for (auto & dv : devicevalues_) {
|
||||||
if (strcmp(command_s, Helpers::toLower(read_flash_string(dv.short_name)).c_str()) == 0 && (tag <= 0 || tag == dv.tag)) {
|
if (!strcmp(command_s, dv.short_name) && (tag <= 0 || tag == dv.tag)) {
|
||||||
int8_t num_op = dv.numeric_operator;
|
|
||||||
|
|
||||||
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
|
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
|
||||||
|
|
||||||
const char * type = "type";
|
const char * type = "type";
|
||||||
@@ -1096,6 +1088,7 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
|
|||||||
json["circuit"] = tag_to_mqtt(dv.tag);
|
json["circuit"] = tag_to_mqtt(dv.tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char val[10];
|
||||||
switch (dv.type) {
|
switch (dv.type) {
|
||||||
case DeviceValueType::ENUM: {
|
case DeviceValueType::ENUM: {
|
||||||
if (*(uint8_t *)(dv.value_p) < dv.options_size) {
|
if (*(uint8_t *)(dv.value_p) < dv.options_size) {
|
||||||
@@ -1115,35 +1108,35 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
|
|||||||
|
|
||||||
case DeviceValueType::USHORT:
|
case DeviceValueType::USHORT:
|
||||||
if (Helpers::hasValue(*(uint16_t *)(dv.value_p))) {
|
if (Helpers::hasValue(*(uint16_t *)(dv.value_p))) {
|
||||||
json[value] = Helpers::transformNumFloat(*(uint16_t *)(dv.value_p), num_op, fahrenheit);
|
json[value] = serialized(Helpers::render_value(val, *(uint16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
||||||
}
|
}
|
||||||
json[type] = F_(number);
|
json[type] = F_(number);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DeviceValueType::UINT:
|
case DeviceValueType::UINT:
|
||||||
if (Helpers::hasValue(*(uint8_t *)(dv.value_p))) {
|
if (Helpers::hasValue(*(uint8_t *)(dv.value_p))) {
|
||||||
json[value] = Helpers::transformNumFloat(*(uint8_t *)(dv.value_p), num_op, fahrenheit);
|
json[value] = serialized(Helpers::render_value(val, *(uint8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
||||||
}
|
}
|
||||||
json[type] = F_(number);
|
json[type] = F_(number);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DeviceValueType::SHORT:
|
case DeviceValueType::SHORT:
|
||||||
if (Helpers::hasValue(*(int16_t *)(dv.value_p))) {
|
if (Helpers::hasValue(*(int16_t *)(dv.value_p))) {
|
||||||
json[value] = Helpers::transformNumFloat(*(int16_t *)(dv.value_p), num_op, fahrenheit);
|
json[value] = serialized(Helpers::render_value(val, *(int16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
||||||
}
|
}
|
||||||
json[type] = F_(number);
|
json[type] = F_(number);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DeviceValueType::INT:
|
case DeviceValueType::INT:
|
||||||
if (Helpers::hasValue(*(int8_t *)(dv.value_p))) {
|
if (Helpers::hasValue(*(int8_t *)(dv.value_p))) {
|
||||||
json[value] = Helpers::transformNumFloat(*(int8_t *)(dv.value_p), num_op, fahrenheit);
|
json[value] = serialized(Helpers::render_value(val, *(int8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
||||||
}
|
}
|
||||||
json[type] = F_(number);
|
json[type] = F_(number);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DeviceValueType::ULONG:
|
case DeviceValueType::ULONG:
|
||||||
if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
||||||
json[value] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), num_op);
|
json[value] = serialized(Helpers::render_value(val, *(uint32_t *)(dv.value_p), dv.numeric_operator));
|
||||||
}
|
}
|
||||||
json[type] = F_(number);
|
json[type] = F_(number);
|
||||||
break;
|
break;
|
||||||
@@ -1160,12 +1153,12 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
|
|||||||
json[value] = Helpers::render_boolean(s, value_b);
|
json[value] = Helpers::render_boolean(s, value_b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
json[type] = F("boolean");
|
json[type] = ("boolean");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DeviceValueType::TIME:
|
case DeviceValueType::TIME:
|
||||||
if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
||||||
json[value] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), num_op);
|
json[value] = serialized(Helpers::render_value(val, *(uint32_t *)(dv.value_p), dv.numeric_operator));
|
||||||
}
|
}
|
||||||
json[type] = F_(number);
|
json[type] = F_(number);
|
||||||
break;
|
break;
|
||||||
@@ -1174,7 +1167,7 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
|
|||||||
if (Helpers::hasValue((char *)(dv.value_p))) {
|
if (Helpers::hasValue((char *)(dv.value_p))) {
|
||||||
json[value] = (char *)(dv.value_p);
|
json[value] = (char *)(dv.value_p);
|
||||||
}
|
}
|
||||||
json[type] = F("string");
|
json[type] = ("string");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DeviceValueType::CMD:
|
case DeviceValueType::CMD:
|
||||||
@@ -1192,11 +1185,14 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the min and max
|
// set the min and max only for commands
|
||||||
int16_t dv_set_min, dv_set_max;
|
if (dv.has_cmd) {
|
||||||
if (dv.get_min_max(dv_set_min, dv_set_max)) {
|
int16_t dv_set_min;
|
||||||
json["min"] = dv_set_min;
|
uint16_t dv_set_max;
|
||||||
json["max"] = dv_set_max;
|
if (dv.get_min_max(dv_set_min, dv_set_max)) {
|
||||||
|
json["min"] = dv_set_min;
|
||||||
|
json["max"] = dv_set_max;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add uom if it's not a " " (single space)
|
// add uom if it's not a " " (single space)
|
||||||
@@ -1216,7 +1212,7 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
|
|||||||
// if we're filtering on an attribute, go find it
|
// if we're filtering on an attribute, go find it
|
||||||
if (attribute_s) {
|
if (attribute_s) {
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
EMSESP::logger().debug(F("[DEBUG] Attribute '%s'"), attribute_s);
|
EMSESP::logger().debug("[DEBUG] Attribute '%s'", attribute_s);
|
||||||
#endif
|
#endif
|
||||||
if (json.containsKey(attribute_s)) {
|
if (json.containsKey(attribute_s)) {
|
||||||
JsonVariant data = json[attribute_s];
|
JsonVariant data = json[attribute_s];
|
||||||
@@ -1291,7 +1287,7 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c
|
|||||||
strlcpy(name, fullname.c_str(), sizeof(name)); // use full name
|
strlcpy(name, fullname.c_str(), sizeof(name)); // use full name
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
strlcpy(name, read_flash_string(dv.short_name).c_str(), sizeof(name)); // use short name
|
strlcpy(name, (dv.short_name), sizeof(name)); // use short name
|
||||||
|
|
||||||
// if we have a tag, and its different to the last one create a nested object. only for hc, wwc and hs
|
// if we have a tag, and its different to the last one create a nested object. only for hc, wwc and hs
|
||||||
if (dv.tag != old_tag) {
|
if (dv.tag != old_tag) {
|
||||||
@@ -1316,6 +1312,9 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c
|
|||||||
json[name] = value_b;
|
json[name] = value_b;
|
||||||
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
||||||
json[name] = value_b ? 1 : 0;
|
json[name] = value_b ? 1 : 0;
|
||||||
|
} else {
|
||||||
|
char s[7];
|
||||||
|
json[name] = Helpers::render_boolean(s, value_b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1341,64 +1340,21 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c
|
|||||||
: (dv.uom == DeviceValueUOM::DEGREES) ? 2
|
: (dv.uom == DeviceValueUOM::DEGREES) ? 2
|
||||||
: (dv.uom == DeviceValueUOM::DEGREES_R) ? 1
|
: (dv.uom == DeviceValueUOM::DEGREES_R) ? 1
|
||||||
: 0;
|
: 0;
|
||||||
|
char val[10];
|
||||||
int8_t num_op = dv.numeric_operator;
|
|
||||||
bool make_float;
|
|
||||||
if (num_op == 0) {
|
|
||||||
// no changes to number
|
|
||||||
make_float = false;
|
|
||||||
num_op = 1; // so it gets *1
|
|
||||||
} else if (num_op < 0) {
|
|
||||||
// negative numbers, convert to a positive multiplier
|
|
||||||
make_float = false;
|
|
||||||
num_op *= -1;
|
|
||||||
} else {
|
|
||||||
// has a divider, make it a float
|
|
||||||
make_float = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// always convert temperatures to floats with 1 decimal place
|
|
||||||
if ((dv.uom == DeviceValueUOM::DEGREES) || (dv.uom == DeviceValueUOM::DEGREES_R)) {
|
|
||||||
make_float = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dv.type == DeviceValueType::INT) {
|
if (dv.type == DeviceValueType::INT) {
|
||||||
if (make_float) {
|
json[name] = serialized(Helpers::render_value(val, *(int8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
||||||
json[name] = Helpers::transformNumFloat(*(int8_t *)(dv.value_p), num_op, fahrenheit);
|
|
||||||
} else {
|
|
||||||
json[name] = *(int8_t *)(dv.value_p) * num_op;
|
|
||||||
}
|
|
||||||
} else if (dv.type == DeviceValueType::UINT) {
|
} else if (dv.type == DeviceValueType::UINT) {
|
||||||
if (make_float) {
|
json[name] = serialized(Helpers::render_value(val, *(uint8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
||||||
json[name] = Helpers::transformNumFloat(*(uint8_t *)(dv.value_p), num_op, fahrenheit);
|
|
||||||
} else {
|
|
||||||
json[name] = *(uint8_t *)(dv.value_p) * num_op;
|
|
||||||
}
|
|
||||||
} else if (dv.type == DeviceValueType::SHORT) {
|
} else if (dv.type == DeviceValueType::SHORT) {
|
||||||
if (make_float) {
|
json[name] = serialized(Helpers::render_value(val, *(int16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
||||||
json[name] = Helpers::transformNumFloat(*(int16_t *)(dv.value_p), num_op, fahrenheit);
|
|
||||||
} else {
|
|
||||||
json[name] = *(int16_t *)(dv.value_p) * num_op;
|
|
||||||
}
|
|
||||||
} else if (dv.type == DeviceValueType::USHORT) {
|
} else if (dv.type == DeviceValueType::USHORT) {
|
||||||
if (make_float) {
|
json[name] = serialized(Helpers::render_value(val, *(uint16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
||||||
json[name] = Helpers::transformNumFloat(*(uint16_t *)(dv.value_p), num_op, fahrenheit);
|
|
||||||
} else {
|
|
||||||
json[name] = *(uint16_t *)(dv.value_p) * num_op;
|
|
||||||
}
|
|
||||||
} else if (dv.type == DeviceValueType::ULONG) {
|
} else if (dv.type == DeviceValueType::ULONG) {
|
||||||
if (make_float) {
|
json[name] = serialized(Helpers::render_value(val, *(uint32_t *)(dv.value_p), dv.numeric_operator));
|
||||||
json[name] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), num_op, fahrenheit);
|
|
||||||
} else {
|
|
||||||
json[name] = *(uint32_t *)(dv.value_p) * num_op;
|
|
||||||
}
|
|
||||||
} else if ((dv.type == DeviceValueType::TIME) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
} else if ((dv.type == DeviceValueType::TIME) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
||||||
uint32_t time_value;
|
uint32_t time_value = *(uint32_t *)(dv.value_p);
|
||||||
if (num_op == DeviceValueNumOp::DV_NUMOP_DIV60) {
|
if (dv.numeric_operator == DeviceValueNumOp::DV_NUMOP_DIV60) {
|
||||||
// sometimes we need to divide by 60
|
time_value /= 60; // sometimes we need to divide by 60
|
||||||
time_value = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), num_op);
|
|
||||||
} else {
|
|
||||||
time_value = *(uint32_t *)(dv.value_p);
|
|
||||||
}
|
}
|
||||||
if (output_target == OUTPUT_TARGET::API_VERBOSE || output_target == OUTPUT_TARGET::CONSOLE) {
|
if (output_target == OUTPUT_TARGET::API_VERBOSE || output_target == OUTPUT_TARGET::CONSOLE) {
|
||||||
char time_s[60];
|
char time_s[60];
|
||||||
@@ -1406,11 +1362,11 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c
|
|||||||
sizeof(time_s),
|
sizeof(time_s),
|
||||||
"%d %s %d %s %d %s",
|
"%d %s %d %s %d %s",
|
||||||
(time_value / 1440),
|
(time_value / 1440),
|
||||||
Helpers::translated_word(FL_(days)).c_str(),
|
Helpers::translated_word(FL_(days)),
|
||||||
((time_value % 1440) / 60),
|
((time_value % 1440) / 60),
|
||||||
Helpers::translated_word(FL_(hours)).c_str(),
|
Helpers::translated_word(FL_(hours)),
|
||||||
(time_value % 60),
|
(time_value % 60),
|
||||||
Helpers::translated_word(FL_(minutes)).c_str());
|
Helpers::translated_word(FL_(minutes)));
|
||||||
json[name] = time_s;
|
json[name] = time_s;
|
||||||
} else {
|
} else {
|
||||||
json[name] = time_value;
|
json[name] = time_value;
|
||||||
@@ -1474,12 +1430,12 @@ void EMSdevice::mqtt_ha_entity_config_create() {
|
|||||||
if (*(int8_t *)(dv.value_p) == 1 && (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) || dv.has_state(DeviceValueState::DV_HA_CLIMATE_NO_RT))) {
|
if (*(int8_t *)(dv.value_p) == 1 && (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) || dv.has_state(DeviceValueState::DV_HA_CLIMATE_NO_RT))) {
|
||||||
dv.remove_state(DeviceValueState::DV_HA_CLIMATE_NO_RT);
|
dv.remove_state(DeviceValueState::DV_HA_CLIMATE_NO_RT);
|
||||||
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
||||||
Mqtt::publish_ha_climate_config(dv.tag, true);
|
Mqtt::publish_ha_climate_config(dv.tag, true, false, dv.min, dv.max);
|
||||||
} else if (*(int8_t *)(dv.value_p) == 0
|
} else if (*(int8_t *)(dv.value_p) == 0
|
||||||
&& (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) || !dv.has_state(DeviceValueState::DV_HA_CLIMATE_NO_RT))) {
|
&& (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) || !dv.has_state(DeviceValueState::DV_HA_CLIMATE_NO_RT))) {
|
||||||
dv.add_state(DeviceValueState::DV_HA_CLIMATE_NO_RT);
|
dv.add_state(DeviceValueState::DV_HA_CLIMATE_NO_RT);
|
||||||
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
||||||
Mqtt::publish_ha_climate_config(dv.tag, false);
|
Mqtt::publish_ha_climate_config(dv.tag, false, false, dv.min, dv.max);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && (dv.type != DeviceValueType::CMD) && dv.has_state(DeviceValueState::DV_ACTIVE)
|
if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && (dv.type != DeviceValueType::CMD) && dv.has_state(DeviceValueState::DV_ACTIVE)
|
||||||
@@ -1517,14 +1473,14 @@ bool EMSdevice::has_telegram_id(uint16_t id) const {
|
|||||||
std::string EMSdevice::telegram_type_name(std::shared_ptr<const Telegram> telegram) const {
|
std::string EMSdevice::telegram_type_name(std::shared_ptr<const Telegram> telegram) const {
|
||||||
// see if it's one of the common ones, like Version
|
// see if it's one of the common ones, like Version
|
||||||
if (telegram->type_id == EMS_TYPE_VERSION) {
|
if (telegram->type_id == EMS_TYPE_VERSION) {
|
||||||
return read_flash_string(F("Version"));
|
return ("Version");
|
||||||
} else if (telegram->type_id == EMS_TYPE_UBADevices) {
|
} else if (telegram->type_id == EMS_TYPE_UBADevices) {
|
||||||
return read_flash_string(F("UBADevices"));
|
return ("UBADevices");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto & tf : telegram_functions_) {
|
for (const auto & tf : telegram_functions_) {
|
||||||
if ((tf.telegram_type_id_ == telegram->type_id) && (telegram->type_id != 0xFF)) {
|
if ((tf.telegram_type_id_ == telegram->type_id) && (telegram->type_id != 0xFF)) {
|
||||||
return read_flash_string(tf.telegram_type_name_);
|
return (tf.telegram_type_name_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1539,7 +1495,7 @@ bool EMSdevice::handle_telegram(std::shared_ptr<const Telegram> telegram) {
|
|||||||
// if the data block is empty and we have not received data before, assume that this telegram
|
// if the data block is empty and we have not received data before, assume that this telegram
|
||||||
// is not recognized by the bus master. So remove it from the automatic fetch list
|
// is not recognized by the bus master. So remove it from the automatic fetch list
|
||||||
if (telegram->message_length == 0 && telegram->offset == 0 && !tf.received_) {
|
if (telegram->message_length == 0 && telegram->offset == 0 && !tf.received_) {
|
||||||
EMSESP::logger().debug(F("This telegram (%s) is not recognized by the EMS bus"), read_flash_string(tf.telegram_type_name_).c_str());
|
EMSESP::logger().debug(("This telegram (%s) is not recognized by the EMS bus"), (tf.telegram_type_name_));
|
||||||
tf.fetch_ = false;
|
tf.fetch_ = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
179
src/emsdevice.h
179
src/emsdevice.h
@@ -34,7 +34,7 @@ class EMSdevice {
|
|||||||
static constexpr uint8_t EMS_DEVICES_MAX_TELEGRAMS = 20;
|
static constexpr uint8_t EMS_DEVICES_MAX_TELEGRAMS = 20;
|
||||||
|
|
||||||
// device_type defines which derived class to use, e.g. BOILER, THERMOSTAT etc..
|
// device_type defines which derived class to use, e.g. BOILER, THERMOSTAT etc..
|
||||||
EMSdevice(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
EMSdevice(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||||
: device_type_(device_type)
|
: device_type_(device_type)
|
||||||
, device_id_(device_id)
|
, device_id_(device_id)
|
||||||
, product_id_(product_id)
|
, product_id_(product_id)
|
||||||
@@ -46,11 +46,11 @@ class EMSdevice {
|
|||||||
|
|
||||||
std::string device_type_name() const;
|
std::string device_type_name() const;
|
||||||
|
|
||||||
static std::string device_type_2_device_name(const uint8_t device_type);
|
static const char * device_type_2_device_name(const uint8_t device_type);
|
||||||
static uint8_t device_name_2_device_type(const char * topic);
|
static uint8_t device_name_2_device_type(const char * topic);
|
||||||
static std::string uom_to_string(uint8_t uom);
|
static std::string uom_to_string(uint8_t uom);
|
||||||
static std::string tag_to_string(uint8_t tag);
|
static std::string tag_to_string(uint8_t tag);
|
||||||
static std::string tag_to_mqtt(uint8_t tag);
|
static std::string tag_to_mqtt(uint8_t tag);
|
||||||
|
|
||||||
bool has_tag(const uint8_t tag) const;
|
bool has_tag(const uint8_t tag) const;
|
||||||
|
|
||||||
@@ -104,11 +104,11 @@ class EMSdevice {
|
|||||||
return brand_;
|
return brand_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void name(const std::string & name) {
|
inline void name(const char * name) {
|
||||||
name_ = name;
|
name_ = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string name() const {
|
inline const char * name() const {
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,12 +187,13 @@ class EMSdevice {
|
|||||||
void list_device_entries(JsonObject & output) const;
|
void list_device_entries(JsonObject & output) const;
|
||||||
void add_handlers_ignored(const uint16_t handler);
|
void add_handlers_ignored(const uint16_t handler);
|
||||||
|
|
||||||
|
void set_climate_minmax(uint8_t tag, int16_t min, uint16_t max);
|
||||||
void setCustomEntity(const std::string & entity_id);
|
void setCustomEntity(const std::string & entity_id);
|
||||||
void getCustomEntities(std::vector<std::string> & entity_ids);
|
void getCustomEntities(std::vector<std::string> & entity_ids);
|
||||||
|
|
||||||
using process_function_p = std::function<void(std::shared_ptr<const Telegram>)>;
|
using process_function_p = std::function<void(std::shared_ptr<const Telegram>)>;
|
||||||
|
|
||||||
void register_telegram_type(const uint16_t telegram_type_id, const __FlashStringHelper * telegram_type_name, bool fetch, const process_function_p cb);
|
void register_telegram_type(const uint16_t telegram_type_id, const char * telegram_type_name, bool fetch, const process_function_p cb);
|
||||||
bool handle_telegram(std::shared_ptr<const Telegram> telegram);
|
bool handle_telegram(std::shared_ptr<const Telegram> telegram);
|
||||||
|
|
||||||
std::string get_value_uom(const char * key) const;
|
std::string get_value_uom(const char * key) const;
|
||||||
@@ -204,93 +205,77 @@ class EMSdevice {
|
|||||||
void generate_values_web(JsonObject & output);
|
void generate_values_web(JsonObject & output);
|
||||||
void generate_values_web_customization(JsonArray & output);
|
void generate_values_web_customization(JsonArray & output);
|
||||||
|
|
||||||
void add_device_value(uint8_t tag,
|
void add_device_value(uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
const __FlashStringHelper * const ** options,
|
const char * const ** options,
|
||||||
const __FlashStringHelper * const * options_single,
|
const char * const * options_single,
|
||||||
int8_t numeric_operator,
|
int8_t numeric_operator,
|
||||||
const __FlashStringHelper * const * name,
|
const char * const * name,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
const cmd_function_p f,
|
const cmd_function_p f,
|
||||||
int16_t min,
|
int16_t min,
|
||||||
uint16_t max);
|
uint16_t max);
|
||||||
|
|
||||||
void register_device_value(uint8_t tag,
|
void register_device_value(uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
const __FlashStringHelper * const ** options,
|
const char * const ** options,
|
||||||
const __FlashStringHelper * const * name,
|
const char * const * name,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
const cmd_function_p f,
|
const cmd_function_p f,
|
||||||
int16_t min,
|
int16_t min,
|
||||||
uint16_t max);
|
uint16_t max);
|
||||||
|
|
||||||
void register_device_value(uint8_t tag,
|
void
|
||||||
void * value_p,
|
register_device_value(uint8_t tag, void * value_p, uint8_t type, const char * const ** options, const char * const * name, uint8_t uom, const cmd_function_p f);
|
||||||
uint8_t type,
|
|
||||||
const __FlashStringHelper * const ** options,
|
|
||||||
const __FlashStringHelper * const * name,
|
|
||||||
uint8_t uom,
|
|
||||||
const cmd_function_p f);
|
|
||||||
|
|
||||||
void register_device_value(uint8_t tag,
|
void register_device_value(uint8_t tag, void * value_p, uint8_t type, const char * const ** options, const char * const * name, uint8_t uom);
|
||||||
void * value_p,
|
|
||||||
uint8_t type,
|
|
||||||
const __FlashStringHelper * const ** options,
|
|
||||||
const __FlashStringHelper * const * name,
|
|
||||||
uint8_t uom);
|
|
||||||
|
|
||||||
void register_device_value(uint8_t tag,
|
void register_device_value(uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
int8_t numeric_operator,
|
int8_t numeric_operator,
|
||||||
const __FlashStringHelper * const * name,
|
const char * const * name,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
const cmd_function_p f = nullptr);
|
const cmd_function_p f = nullptr);
|
||||||
|
|
||||||
void register_device_value(uint8_t tag,
|
void register_device_value(uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
int8_t numeric_operator,
|
int8_t numeric_operator,
|
||||||
const __FlashStringHelper * const * name,
|
const char * const * name,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
const cmd_function_p f,
|
const cmd_function_p f,
|
||||||
int16_t min,
|
int16_t min,
|
||||||
uint16_t max);
|
uint16_t max);
|
||||||
|
|
||||||
// single list of options
|
// single list of options
|
||||||
void register_device_value(uint8_t tag,
|
void register_device_value(uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
const __FlashStringHelper * const * options_single,
|
const char * const * options_single,
|
||||||
const __FlashStringHelper * const * name,
|
const char * const * name,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
const cmd_function_p f = nullptr);
|
const cmd_function_p f = nullptr);
|
||||||
|
|
||||||
// single list of options, with no translations, with min and max
|
// single list of options, with no translations, with min and max
|
||||||
void register_device_value(uint8_t tag,
|
void register_device_value(uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
const __FlashStringHelper * const * options_single,
|
const char * const * options_single,
|
||||||
const __FlashStringHelper * const * name,
|
const char * const * name,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
const cmd_function_p f,
|
const cmd_function_p f,
|
||||||
int16_t min,
|
int16_t min,
|
||||||
uint16_t max);
|
uint16_t max);
|
||||||
|
|
||||||
// no options, optional function f
|
// no options, optional function f
|
||||||
void register_device_value(uint8_t tag, void * value_p, uint8_t type, const __FlashStringHelper * const * name, uint8_t uom, const cmd_function_p f = nullptr);
|
void register_device_value(uint8_t tag, void * value_p, uint8_t type, const char * const * name, uint8_t uom, const cmd_function_p f = nullptr);
|
||||||
|
|
||||||
// no options, with min/max
|
// no options, with min/max
|
||||||
void register_device_value(uint8_t tag,
|
void
|
||||||
void * value_p,
|
register_device_value(uint8_t tag, void * value_p, uint8_t type, const char * const * name, uint8_t uom, const cmd_function_p f, int16_t min, uint16_t max);
|
||||||
uint8_t type,
|
|
||||||
const __FlashStringHelper * const * name,
|
|
||||||
uint8_t uom,
|
|
||||||
const cmd_function_p f,
|
|
||||||
int16_t min,
|
|
||||||
uint16_t max);
|
|
||||||
|
|
||||||
void write_command(const uint16_t type_id, const uint8_t offset, uint8_t * message_data, const uint8_t message_length, const uint16_t validate_typeid) const;
|
void write_command(const uint16_t type_id, const uint8_t offset, uint8_t * message_data, const uint8_t message_length, const uint16_t validate_typeid) const;
|
||||||
void write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid) const;
|
void write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid) const;
|
||||||
@@ -424,27 +409,27 @@ class EMSdevice {
|
|||||||
bool has_entities() const;
|
bool has_entities() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t unique_id_;
|
uint8_t unique_id_;
|
||||||
uint8_t device_type_ = DeviceType::SYSTEM;
|
uint8_t device_type_ = DeviceType::SYSTEM;
|
||||||
uint8_t device_id_ = 0;
|
uint8_t device_id_ = 0;
|
||||||
uint8_t product_id_ = 0;
|
uint8_t product_id_ = 0;
|
||||||
char version_[6];
|
char version_[6];
|
||||||
std::string name_; // the long name for the EMS model
|
const char * name_; // the long name for the EMS model
|
||||||
uint8_t flags_ = 0;
|
uint8_t flags_ = 0;
|
||||||
uint8_t brand_ = Brand::NO_BRAND;
|
uint8_t brand_ = Brand::NO_BRAND;
|
||||||
|
|
||||||
bool ha_config_done_ = false;
|
bool ha_config_done_ = false;
|
||||||
bool has_update_ = false;
|
bool has_update_ = false;
|
||||||
bool ha_config_firstrun_ = true; // this means a first setup of HA is needed after a restart
|
bool ha_config_firstrun_ = true; // this means a first setup of HA is needed after a restart
|
||||||
|
|
||||||
struct TelegramFunction {
|
struct TelegramFunction {
|
||||||
uint16_t telegram_type_id_; // it's type_id
|
uint16_t telegram_type_id_; // it's type_id
|
||||||
const __FlashStringHelper * telegram_type_name_; // e.g. RC20Message
|
const char * telegram_type_name_; // e.g. RC20Message
|
||||||
bool fetch_; // if this type_id be queried automatically
|
bool fetch_; // if this type_id be queried automatically
|
||||||
bool received_;
|
bool received_;
|
||||||
process_function_p process_function_;
|
process_function_p process_function_;
|
||||||
|
|
||||||
TelegramFunction(uint16_t telegram_type_id, const __FlashStringHelper * telegram_type_name, bool fetch, bool received, const process_function_p process_function)
|
TelegramFunction(uint16_t telegram_type_id, const char * telegram_type_name, bool fetch, bool received, const process_function_p process_function)
|
||||||
: telegram_type_id_(telegram_type_id)
|
: telegram_type_id_(telegram_type_id)
|
||||||
, telegram_type_name_(telegram_type_name)
|
, telegram_type_name_(telegram_type_name)
|
||||||
, fetch_(fetch)
|
, fetch_(fetch)
|
||||||
|
|||||||
@@ -23,21 +23,21 @@
|
|||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
DeviceValue::DeviceValue(uint8_t device_type,
|
DeviceValue::DeviceValue(uint8_t device_type,
|
||||||
uint8_t tag,
|
uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
const __FlashStringHelper * const ** options,
|
const char * const ** options,
|
||||||
const __FlashStringHelper * const * options_single,
|
const char * const * options_single,
|
||||||
int8_t numeric_operator,
|
int8_t numeric_operator,
|
||||||
const __FlashStringHelper * const short_name,
|
const char * const short_name,
|
||||||
const __FlashStringHelper * const * fullname,
|
const char * const * fullname,
|
||||||
std::string & custom_fullname,
|
std::string & custom_fullname,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
bool has_cmd,
|
bool has_cmd,
|
||||||
int16_t min,
|
int16_t min,
|
||||||
uint16_t max,
|
uint16_t max,
|
||||||
uint8_t state)
|
uint8_t state)
|
||||||
: device_type(device_type)
|
: device_type(device_type)
|
||||||
, tag(tag)
|
, tag(tag)
|
||||||
, value_p(value_p)
|
, value_p(value_p)
|
||||||
@@ -60,17 +60,21 @@ DeviceValue::DeviceValue(uint8_t device_type,
|
|||||||
options_size = Helpers::count_items(options);
|
options_size = Helpers::count_items(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the min/max
|
||||||
|
set_custom_minmax();
|
||||||
|
|
||||||
#ifdef EMSESP_STANDALONE
|
#ifdef EMSESP_STANDALONE
|
||||||
// only added for debugging
|
// only added for debugging
|
||||||
Serial.print("registering entity: ");
|
Serial.print(COLOR_BRIGHT_RED_BACKGROUND);
|
||||||
Serial.print(read_flash_string(short_name).c_str());
|
Serial.print(" registering entity: ");
|
||||||
|
Serial.print((short_name));
|
||||||
Serial.print("/");
|
Serial.print("/");
|
||||||
if (!custom_fullname.empty()) {
|
if (!custom_fullname.empty()) {
|
||||||
Serial.print(COLOR_BRIGHT_CYAN);
|
Serial.print(COLOR_BRIGHT_CYAN);
|
||||||
Serial.print(custom_fullname.c_str());
|
Serial.print(custom_fullname.c_str());
|
||||||
Serial.print(COLOR_RESET);
|
Serial.print(COLOR_RESET);
|
||||||
} else {
|
} else {
|
||||||
Serial.print(Helpers::translated_word(fullname).c_str());
|
Serial.print(Helpers::translated_word(fullname));
|
||||||
}
|
}
|
||||||
Serial.print(" (#options=");
|
Serial.print(" (#options=");
|
||||||
Serial.print(options_size);
|
Serial.print(options_size);
|
||||||
@@ -83,23 +87,23 @@ DeviceValue::DeviceValue(uint8_t device_type,
|
|||||||
Serial.print(" option");
|
Serial.print(" option");
|
||||||
Serial.print(i + 1);
|
Serial.print(i + 1);
|
||||||
Serial.print(":");
|
Serial.print(":");
|
||||||
auto str = Helpers::translated_fword(options[i]);
|
auto str = Helpers::translated_word(options[i]);
|
||||||
Serial.print(read_flash_string(str).c_str());
|
Serial.print(str);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
} else if (options_single != nullptr) {
|
} else if (options_single != nullptr) {
|
||||||
Serial.print("option1:!");
|
Serial.print("option1:!");
|
||||||
Serial.print(read_flash_string(options_single[0]).c_str());
|
Serial.print((options_single[0]));
|
||||||
Serial.print("!");
|
Serial.print("!");
|
||||||
}
|
}
|
||||||
Serial.println("");
|
Serial.println(COLOR_RESET);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// mapping of UOM, to match order in DeviceValueUOM enum emsdevice.h
|
// mapping of UOM, to match order in DeviceValueUOM enum emsdevice.h
|
||||||
// also maps to DeviceValueUOM in interface/src/project/types.ts for the Web UI
|
// also maps to DeviceValueUOM in interface/src/project/types.ts for the Web UI
|
||||||
// must be an int of 4 bytes, 32bit aligned
|
// must be an int of 4 bytes, 32bit aligned
|
||||||
const __FlashStringHelper * DeviceValue::DeviceValueUOM_s[] __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = {
|
const char * DeviceValue::DeviceValueUOM_s[] = {
|
||||||
|
|
||||||
F_(uom_blank),
|
F_(uom_blank),
|
||||||
F_(uom_degrees),
|
F_(uom_degrees),
|
||||||
@@ -125,7 +129,7 @@ const __FlashStringHelper * DeviceValue::DeviceValueUOM_s[] __attribute__((__ali
|
|||||||
|
|
||||||
// mapping of TAGs, to match order in DeviceValueTAG enum in emsdevice.h
|
// mapping of TAGs, to match order in DeviceValueTAG enum in emsdevice.h
|
||||||
// must be an int of 4 bytes, 32bit aligned
|
// must be an int of 4 bytes, 32bit aligned
|
||||||
const __FlashStringHelper * const DeviceValue::DeviceValueTAG_s[] PROGMEM = {
|
const char * const DeviceValue::DeviceValueTAG_s[] = {
|
||||||
|
|
||||||
F_(tag_none), // ""
|
F_(tag_none), // ""
|
||||||
F_(tag_heartbeat), // ""
|
F_(tag_heartbeat), // ""
|
||||||
@@ -171,7 +175,7 @@ const __FlashStringHelper * const DeviceValue::DeviceValueTAG_s[] PROGMEM = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// MQTT topics derived from tags
|
// MQTT topics derived from tags
|
||||||
const __FlashStringHelper * const DeviceValue::DeviceValueTAG_mqtt[] PROGMEM = {
|
const char * const DeviceValue::DeviceValueTAG_mqtt[] = {
|
||||||
|
|
||||||
F_(tag_none), // ""
|
F_(tag_none), // ""
|
||||||
F_(heartbeat), // "heartbeat"
|
F_(heartbeat), // "heartbeat"
|
||||||
@@ -217,7 +221,7 @@ const __FlashStringHelper * const DeviceValue::DeviceValueTAG_mqtt[] PROGMEM = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// count #tags once at compile time
|
// count #tags once at compile time
|
||||||
size_t DeviceValue::tag_count = sizeof(DeviceValue::DeviceValueTAG_s) / sizeof(__FlashStringHelper *);
|
size_t DeviceValue::tag_count = sizeof(DeviceValue::DeviceValueTAG_s) / sizeof(char *);
|
||||||
|
|
||||||
// checks whether the device value has an actual value
|
// checks whether the device value has an actual value
|
||||||
// returns true if its valid
|
// returns true if its valid
|
||||||
@@ -266,7 +270,7 @@ bool DeviceValue::hasValue() const {
|
|||||||
// converts to signed int, which means rounding to an whole integer
|
// converts to signed int, which means rounding to an whole integer
|
||||||
// returns false if there is no min/max needed
|
// returns false if there is no min/max needed
|
||||||
// Types BOOL, ENUM, STRING and CMD are not used
|
// Types BOOL, ENUM, STRING and CMD are not used
|
||||||
bool DeviceValue::get_min_max(int16_t & dv_set_min, int16_t & dv_set_max) {
|
bool DeviceValue::get_min_max(int16_t & dv_set_min, uint16_t & dv_set_max) {
|
||||||
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (uom == DeviceValueUOM::DEGREES) ? 2 : (uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
|
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (uom == DeviceValueUOM::DEGREES) ? 2 : (uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
|
||||||
|
|
||||||
// if we have individual limits set already, just do the conversion
|
// if we have individual limits set already, just do the conversion
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
#include "helpers.h" // for conversions
|
#include "helpers.h" // for conversions
|
||||||
#include "default_settings.h" // for enum types
|
#include "default_settings.h" // for enum types
|
||||||
#include <uuid/common.h> // for read_flash_string
|
|
||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
@@ -143,41 +142,41 @@ class DeviceValue {
|
|||||||
DV_NUMOP_MUL15 = -15
|
DV_NUMOP_MUL15 = -15
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t device_type; // EMSdevice::DeviceType
|
uint8_t device_type; // EMSdevice::DeviceType
|
||||||
uint8_t tag; // DeviceValueTAG::*
|
uint8_t tag; // DeviceValueTAG::*
|
||||||
void * value_p; // pointer to variable of any type
|
void * value_p; // pointer to variable of any type
|
||||||
uint8_t type; // DeviceValueType::*
|
uint8_t type; // DeviceValueType::*
|
||||||
const __FlashStringHelper * const ** options; // options as a flash char array
|
const char * const ** options; // options as a flash char array
|
||||||
const __FlashStringHelper * const * options_single; // options are not translated
|
const char * const * options_single; // options are not translated
|
||||||
int8_t numeric_operator;
|
int8_t numeric_operator;
|
||||||
uint8_t options_size; // number of options in the char array, calculated
|
uint8_t options_size; // number of options in the char array, calculated
|
||||||
const __FlashStringHelper * const short_name; // used in MQTT and API
|
const char * const short_name; // used in MQTT and API
|
||||||
const __FlashStringHelper * const * fullname; // used in Web and Console, is translated
|
const char * const * fullname; // used in Web and Console, is translated
|
||||||
std::string custom_fullname; // optional, from customization
|
std::string custom_fullname; // optional, from customization
|
||||||
uint8_t uom; // DeviceValueUOM::*
|
uint8_t uom; // DeviceValueUOM::*
|
||||||
bool has_cmd; // true if there is a Console/MQTT command which matches the short_name
|
bool has_cmd; // true if there is a Console/MQTT command which matches the short_name
|
||||||
int16_t min; // min range
|
int16_t min; // min range
|
||||||
uint16_t max; // max range
|
uint16_t max; // max range
|
||||||
uint8_t state; // DeviceValueState::*
|
uint8_t state; // DeviceValueState::*
|
||||||
|
|
||||||
DeviceValue(uint8_t device_type,
|
DeviceValue(uint8_t device_type,
|
||||||
uint8_t tag,
|
uint8_t tag,
|
||||||
void * value_p,
|
void * value_p,
|
||||||
uint8_t type,
|
uint8_t type,
|
||||||
const __FlashStringHelper * const ** options,
|
const char * const ** options,
|
||||||
const __FlashStringHelper * const * options_single,
|
const char * const * options_single,
|
||||||
int8_t numeric_operator,
|
int8_t numeric_operator,
|
||||||
const __FlashStringHelper * const short_name,
|
const char * const short_name,
|
||||||
const __FlashStringHelper * const * fullname,
|
const char * const * fullname,
|
||||||
std::string & custom_fullname,
|
std::string & custom_fullname,
|
||||||
uint8_t uom,
|
uint8_t uom,
|
||||||
bool has_cmd,
|
bool has_cmd,
|
||||||
int16_t min,
|
int16_t min,
|
||||||
uint16_t max,
|
uint16_t max,
|
||||||
uint8_t state);
|
uint8_t state);
|
||||||
|
|
||||||
bool hasValue() const;
|
bool hasValue() const;
|
||||||
bool get_min_max(int16_t & dv_set_min, int16_t & dv_set_max);
|
bool get_min_max(int16_t & dv_set_min, uint16_t & dv_set_max);
|
||||||
|
|
||||||
void set_custom_minmax();
|
void set_custom_minmax();
|
||||||
bool get_custom_min(int16_t & val);
|
bool get_custom_min(int16_t & val);
|
||||||
@@ -199,10 +198,10 @@ class DeviceValue {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const __FlashStringHelper * DeviceValueUOM_s[];
|
static const char * DeviceValueUOM_s[];
|
||||||
static const __FlashStringHelper * const DeviceValueTAG_s[];
|
static const char * const DeviceValueTAG_s[];
|
||||||
static const __FlashStringHelper * const DeviceValueTAG_mqtt[];
|
static const char * const DeviceValueTAG_mqtt[];
|
||||||
static size_t tag_count; // # tags
|
static size_t tag_count; // # tags
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace emsesp
|
}; // namespace emsesp
|
||||||
|
|||||||
158
src/emsesp.cpp
158
src/emsesp.cpp
@@ -190,7 +190,7 @@ void EMSESP::uart_init() {
|
|||||||
if (System::is_valid_gpio(rx_gpio) && System::is_valid_gpio(tx_gpio)) {
|
if (System::is_valid_gpio(rx_gpio) && System::is_valid_gpio(tx_gpio)) {
|
||||||
EMSuart::start(tx_mode, rx_gpio, tx_gpio); // start UART
|
EMSuart::start(tx_mode, rx_gpio, tx_gpio); // start UART
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING(F("Invalid UART Rx/Tx GPIOs. Check config."));
|
LOG_WARNING("Invalid UART Rx/Tx GPIOs. Check config.");
|
||||||
}
|
}
|
||||||
|
|
||||||
txservice_.start(); // sends out request to EMS bus for all devices
|
txservice_.start(); // sends out request to EMS bus for all devices
|
||||||
@@ -234,42 +234,42 @@ void EMSESP::show_ems(uuid::console::Shell & shell) {
|
|||||||
// EMS bus information
|
// EMS bus information
|
||||||
switch (bus_status()) {
|
switch (bus_status()) {
|
||||||
case BUS_STATUS_OFFLINE:
|
case BUS_STATUS_OFFLINE:
|
||||||
shell.printfln(F("EMS Bus is disconnected."));
|
shell.printfln("EMS Bus is disconnected.");
|
||||||
break;
|
break;
|
||||||
case BUS_STATUS_TX_ERRORS:
|
case BUS_STATUS_TX_ERRORS:
|
||||||
shell.printfln(F("EMS Bus is connected, but Tx is not stable."));
|
shell.printfln("EMS Bus is connected, but Tx is not stable.");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
shell.printfln(F("EMS Bus is connected."));
|
shell.printfln("EMS Bus is connected.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
shell.println();
|
shell.println();
|
||||||
|
|
||||||
if (bus_status() != BUS_STATUS_OFFLINE) {
|
if (bus_status() != BUS_STATUS_OFFLINE) {
|
||||||
shell.printfln(F("EMS Bus info:"));
|
shell.printfln("EMS Bus info:");
|
||||||
EMSESP::webSettingsService.read([&](WebSettings & settings) { shell.printfln(F(" Tx mode: %d"), settings.tx_mode); });
|
EMSESP::webSettingsService.read([&](WebSettings & settings) { shell.printfln(" Tx mode: %d", settings.tx_mode); });
|
||||||
shell.printfln(F(" Bus protocol: %s"), EMSbus::is_ht3() ? F("HT3") : F("Buderus"));
|
shell.printfln(" Bus protocol: %s", EMSbus::is_ht3() ? ("HT3") : ("Buderus"));
|
||||||
shell.printfln(F(" #recognized EMS devices: %d"), EMSESP::emsdevices.size());
|
shell.printfln(" #recognized EMS devices: %d", EMSESP::emsdevices.size());
|
||||||
shell.printfln(F(" #telegrams received: %d"), rxservice_.telegram_count());
|
shell.printfln(" #telegrams received: %d", rxservice_.telegram_count());
|
||||||
shell.printfln(F(" #read requests sent: %d"), txservice_.telegram_read_count());
|
shell.printfln(" #read requests sent: %d", txservice_.telegram_read_count());
|
||||||
shell.printfln(F(" #write requests sent: %d"), txservice_.telegram_write_count());
|
shell.printfln(" #write requests sent: %d", txservice_.telegram_write_count());
|
||||||
shell.printfln(F(" #incomplete telegrams: %d"), rxservice_.telegram_error_count());
|
shell.printfln(" #incomplete telegrams: %d", rxservice_.telegram_error_count());
|
||||||
shell.printfln(F(" #read fails (after %d retries): %d"), TxService::MAXIMUM_TX_RETRIES, txservice_.telegram_read_fail_count());
|
shell.printfln((" #read fails (after %d retries): %d"), TxService::MAXIMUM_TX_RETRIES, txservice_.telegram_read_fail_count());
|
||||||
shell.printfln(F(" #write fails (after %d retries): %d"), TxService::MAXIMUM_TX_RETRIES, txservice_.telegram_write_fail_count());
|
shell.printfln((" #write fails (after %d retries): %d"), TxService::MAXIMUM_TX_RETRIES, txservice_.telegram_write_fail_count());
|
||||||
shell.printfln(F(" Rx line quality: %d%%"), rxservice_.quality());
|
shell.printfln(" Rx line quality: %d%%", rxservice_.quality());
|
||||||
shell.printfln(F(" Tx line quality: %d%%"), (txservice_.read_quality() + txservice_.read_quality()) / 2);
|
shell.printfln(" Tx line quality: %d%%", (txservice_.read_quality() + txservice_.read_quality()) / 2);
|
||||||
shell.println();
|
shell.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rx queue
|
// Rx queue
|
||||||
auto rx_telegrams = rxservice_.queue();
|
auto rx_telegrams = rxservice_.queue();
|
||||||
if (rx_telegrams.empty()) {
|
if (rx_telegrams.empty()) {
|
||||||
shell.printfln(F("Rx Queue is empty"));
|
shell.printfln("Rx Queue is empty");
|
||||||
} else {
|
} else {
|
||||||
shell.printfln(F("Rx Queue (%ld telegram%s):"), rx_telegrams.size(), rx_telegrams.size() == 1 ? "" : "s");
|
shell.printfln(("Rx Queue (%ld telegram%s):"), rx_telegrams.size(), rx_telegrams.size() == 1 ? "" : "s");
|
||||||
for (const auto & it : rx_telegrams) {
|
for (const auto & it : rx_telegrams) {
|
||||||
shell.printfln(F(" [%02d] %s"), it.id_, pretty_telegram(it.telegram_).c_str());
|
shell.printfln(" [%02d] %s", it.id_, pretty_telegram(it.telegram_).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,20 +278,20 @@ void EMSESP::show_ems(uuid::console::Shell & shell) {
|
|||||||
// Tx queue
|
// Tx queue
|
||||||
auto tx_telegrams = txservice_.queue();
|
auto tx_telegrams = txservice_.queue();
|
||||||
if (tx_telegrams.empty()) {
|
if (tx_telegrams.empty()) {
|
||||||
shell.printfln(F("Tx Queue is empty"));
|
shell.printfln("Tx Queue is empty");
|
||||||
} else {
|
} else {
|
||||||
shell.printfln(F("Tx Queue (%ld telegram%s):"), tx_telegrams.size(), tx_telegrams.size() == 1 ? "" : "s");
|
shell.printfln(("Tx Queue (%ld telegram%s):"), tx_telegrams.size(), tx_telegrams.size() == 1 ? "" : "s");
|
||||||
|
|
||||||
std::string op;
|
std::string op;
|
||||||
for (const auto & it : tx_telegrams) {
|
for (const auto & it : tx_telegrams) {
|
||||||
if ((it.telegram_->operation) == Telegram::Operation::TX_RAW) {
|
if ((it.telegram_->operation) == Telegram::Operation::TX_RAW) {
|
||||||
op = read_flash_string(F("RAW "));
|
op = "RAW ";
|
||||||
} else if ((it.telegram_->operation) == Telegram::Operation::TX_READ) {
|
} else if ((it.telegram_->operation) == Telegram::Operation::TX_READ) {
|
||||||
op = read_flash_string(F("READ "));
|
op = "READ ";
|
||||||
} else if ((it.telegram_->operation) == Telegram::Operation::TX_WRITE) {
|
} else if ((it.telegram_->operation) == Telegram::Operation::TX_WRITE) {
|
||||||
op = read_flash_string(F("WRITE"));
|
op = "WRITE";
|
||||||
}
|
}
|
||||||
shell.printfln(F(" [%02d%c] %s %s"), it.id_, ((it.retry_) ? '*' : ' '), op.c_str(), pretty_telegram(it.telegram_).c_str());
|
shell.printfln(" [%02d%c] %s %s", it.id_, ((it.retry_) ? '*' : ' '), op.c_str(), pretty_telegram(it.telegram_).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +301,7 @@ void EMSESP::show_ems(uuid::console::Shell & shell) {
|
|||||||
// show EMS device values to the shell console
|
// show EMS device values to the shell console
|
||||||
void EMSESP::show_device_values(uuid::console::Shell & shell) {
|
void EMSESP::show_device_values(uuid::console::Shell & shell) {
|
||||||
if (emsdevices.empty()) {
|
if (emsdevices.empty()) {
|
||||||
shell.printfln(F("No EMS devices detected."));
|
shell.printfln("No EMS devices detected.");
|
||||||
shell.println();
|
shell.println();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -311,7 +311,7 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) {
|
|||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice && (emsdevice->device_type() == device_class.first)) {
|
if (emsdevice && (emsdevice->device_type() == device_class.first)) {
|
||||||
// print header
|
// print header
|
||||||
shell.printfln(F("%s: %s (%d)"), emsdevice->device_type_name().c_str(), emsdevice->to_string().c_str(), emsdevice->count_entities());
|
shell.printfln(("%s: %s (%d)"), emsdevice->device_type_name().c_str(), emsdevice->to_string().c_str(), emsdevice->count_entities());
|
||||||
|
|
||||||
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XXLARGE_DYN); // use max size
|
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XXLARGE_DYN); // use max size
|
||||||
JsonObject json = doc.to<JsonObject>();
|
JsonObject json = doc.to<JsonObject>();
|
||||||
@@ -359,14 +359,14 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) {
|
|||||||
// show Dallas temperature sensors and Analog sensors
|
// show Dallas temperature sensors and Analog sensors
|
||||||
void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
|
void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
|
||||||
if (dallassensor_.have_sensors()) {
|
if (dallassensor_.have_sensors()) {
|
||||||
shell.printfln(F("Temperature sensors:"));
|
shell.printfln("Temperature sensors:");
|
||||||
char s[10];
|
char s[10];
|
||||||
char s2[10];
|
char s2[10];
|
||||||
uint8_t fahrenheit = EMSESP::system_.fahrenheit() ? 2 : 0;
|
uint8_t fahrenheit = EMSESP::system_.fahrenheit() ? 2 : 0;
|
||||||
|
|
||||||
for (const auto & sensor : dallassensor_.sensors()) {
|
for (const auto & sensor : dallassensor_.sensors()) {
|
||||||
if (Helpers::hasValue(sensor.temperature_c)) {
|
if (Helpers::hasValue(sensor.temperature_c)) {
|
||||||
shell.printfln(F(" %s: %s%s °%c%s (offset %s, ID: %s)"),
|
shell.printfln((" %s: %s%s °%c%s (offset %s, ID: %s)"),
|
||||||
sensor.name().c_str(),
|
sensor.name().c_str(),
|
||||||
COLOR_BRIGHT_GREEN,
|
COLOR_BRIGHT_GREEN,
|
||||||
Helpers::render_value(s, sensor.temperature_c, 10, fahrenheit),
|
Helpers::render_value(s, sensor.temperature_c, 10, fahrenheit),
|
||||||
@@ -375,10 +375,7 @@ void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
|
|||||||
Helpers::render_value(s2, sensor.offset(), 10, fahrenheit),
|
Helpers::render_value(s2, sensor.offset(), 10, fahrenheit),
|
||||||
sensor.id().c_str());
|
sensor.id().c_str());
|
||||||
} else {
|
} else {
|
||||||
shell.printfln(F(" %s (offset %s, ID: %s)"),
|
shell.printfln((" %s (offset %s, ID: %s)"), sensor.name().c_str(), Helpers::render_value(s, sensor.offset(), 10, fahrenheit), sensor.id().c_str());
|
||||||
sensor.name().c_str(),
|
|
||||||
Helpers::render_value(s, sensor.offset(), 10, fahrenheit),
|
|
||||||
sensor.id().c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shell.println();
|
shell.println();
|
||||||
@@ -387,11 +384,11 @@ void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
|
|||||||
if (analogsensor_.have_sensors()) {
|
if (analogsensor_.have_sensors()) {
|
||||||
char s[10];
|
char s[10];
|
||||||
char s2[10];
|
char s2[10];
|
||||||
shell.printfln(F("Analog sensors:"));
|
shell.printfln("Analog sensors:");
|
||||||
for (const auto & sensor : analogsensor_.sensors()) {
|
for (const auto & sensor : analogsensor_.sensors()) {
|
||||||
switch (sensor.type()) {
|
switch (sensor.type()) {
|
||||||
case AnalogSensor::AnalogType::ADC:
|
case AnalogSensor::AnalogType::ADC:
|
||||||
shell.printfln(F(" %s: %s%s %s%s (Type: ADC, Factor: %s, Offset: %d)"),
|
shell.printfln((" %s: %s%s %s%s (Type: ADC, Factor: %s, Offset: %d)"),
|
||||||
sensor.name().c_str(),
|
sensor.name().c_str(),
|
||||||
COLOR_BRIGHT_GREEN,
|
COLOR_BRIGHT_GREEN,
|
||||||
Helpers::render_value(s, sensor.value(), 2),
|
Helpers::render_value(s, sensor.value(), 2),
|
||||||
@@ -403,7 +400,7 @@ void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
|
|||||||
default:
|
default:
|
||||||
// case AnalogSensor::AnalogType::DIGITAL_IN:
|
// case AnalogSensor::AnalogType::DIGITAL_IN:
|
||||||
// case AnalogSensor::AnalogType::COUNTER:
|
// case AnalogSensor::AnalogType::COUNTER:
|
||||||
shell.printfln(F(" %s: %s%d%s (Type: %s)"),
|
shell.printfln((" %s: %s%d%s (Type: %s)"),
|
||||||
sensor.name().c_str(),
|
sensor.name().c_str(),
|
||||||
COLOR_BRIGHT_GREEN,
|
COLOR_BRIGHT_GREEN,
|
||||||
(uint16_t)sensor.value(), // as int
|
(uint16_t)sensor.value(), // as int
|
||||||
@@ -540,7 +537,7 @@ void EMSESP::publish_device_values(uint8_t device_type) {
|
|||||||
}
|
}
|
||||||
if (need_publish) {
|
if (need_publish) {
|
||||||
if (doc.overflowed()) {
|
if (doc.overflowed()) {
|
||||||
LOG_WARNING(F("MQTT buffer overflow, please use individual topics"));
|
LOG_WARNING("MQTT buffer overflow, please use individual topics");
|
||||||
}
|
}
|
||||||
Mqtt::publish(Mqtt::tag_to_topic(device_type, DeviceValueTAG::TAG_NONE), json);
|
Mqtt::publish(Mqtt::tag_to_topic(device_type, DeviceValueTAG::TAG_NONE), json);
|
||||||
}
|
}
|
||||||
@@ -625,9 +622,9 @@ bool EMSESP::get_device_value_info(JsonObject & root, const char * cmd, const in
|
|||||||
// search for recognized device_ids : Me, All, otherwise print hex value
|
// search for recognized device_ids : Me, All, otherwise print hex value
|
||||||
std::string EMSESP::device_tostring(const uint8_t device_id) {
|
std::string EMSESP::device_tostring(const uint8_t device_id) {
|
||||||
if ((device_id & 0x7F) == rxservice_.ems_bus_id()) {
|
if ((device_id & 0x7F) == rxservice_.ems_bus_id()) {
|
||||||
return read_flash_string(F("Me"));
|
return "Me";
|
||||||
} else if (device_id == 0x00) {
|
} else if (device_id == 0x00) {
|
||||||
return read_flash_string(F("All"));
|
return "All";
|
||||||
} else {
|
} else {
|
||||||
char buffer[5];
|
char buffer[5];
|
||||||
return Helpers::hextoa(buffer, device_id);
|
return Helpers::hextoa(buffer, device_id);
|
||||||
@@ -672,14 +669,14 @@ std::string EMSESP::pretty_telegram(std::shared_ptr<const Telegram> telegram) {
|
|||||||
|
|
||||||
// check for global/common types like Version & UBADevices
|
// check for global/common types like Version & UBADevices
|
||||||
if (telegram->type_id == EMSdevice::EMS_TYPE_VERSION) {
|
if (telegram->type_id == EMSdevice::EMS_TYPE_VERSION) {
|
||||||
type_name = read_flash_string(F("Version"));
|
type_name = "Version";
|
||||||
} else if (telegram->type_id == EMSdevice::EMS_TYPE_UBADevices) {
|
} else if (telegram->type_id == EMSdevice::EMS_TYPE_UBADevices) {
|
||||||
type_name = read_flash_string(F("UBADevices"));
|
type_name = "UBADevices";
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we don't know the type show
|
// if we don't know the type show
|
||||||
if (type_name.empty()) {
|
if (type_name.empty()) {
|
||||||
type_name = read_flash_string(F("?"));
|
type_name = "?";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string str;
|
std::string str;
|
||||||
@@ -728,7 +725,7 @@ void EMSESP::process_UBADevices(std::shared_ptr<const Telegram> telegram) {
|
|||||||
// if we haven't already detected this device, request it's version details, unless its us (EMS-ESP)
|
// if we haven't already detected this device, request it's version details, unless its us (EMS-ESP)
|
||||||
// when the version info is received, it will automagically add the device
|
// when the version info is received, it will automagically add the device
|
||||||
if ((device_id != EMSbus::ems_bus_id()) && !(EMSESP::device_exists(device_id))) {
|
if ((device_id != EMSbus::ems_bus_id()) && !(EMSESP::device_exists(device_id))) {
|
||||||
LOG_DEBUG(F("New EMS device detected with ID 0x%02X. Requesting version information."), device_id);
|
LOG_DEBUG("New EMS device detected with ID 0x%02X. Requesting version information.", device_id);
|
||||||
send_read_request(EMSdevice::EMS_TYPE_VERSION, device_id);
|
send_read_request(EMSdevice::EMS_TYPE_VERSION, device_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -788,7 +785,7 @@ void EMSESP::process_version(std::shared_ptr<const Telegram> telegram) {
|
|||||||
bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
|
bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
|
||||||
// if watching or reading...
|
// if watching or reading...
|
||||||
if ((telegram->type_id == read_id_) && (telegram->dest == txservice_.ems_bus_id())) {
|
if ((telegram->type_id == read_id_) && (telegram->dest == txservice_.ems_bus_id())) {
|
||||||
LOG_INFO(F("%s"), pretty_telegram(telegram).c_str());
|
LOG_INFO("%s", pretty_telegram(telegram).c_str());
|
||||||
if (Mqtt::send_response()) {
|
if (Mqtt::send_response()) {
|
||||||
publish_response(telegram);
|
publish_response(telegram);
|
||||||
}
|
}
|
||||||
@@ -800,18 +797,18 @@ bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
|
|||||||
} else if (watch() == WATCH_ON) {
|
} else if (watch() == WATCH_ON) {
|
||||||
if ((watch_id_ == WATCH_ID_NONE) || (telegram->type_id == watch_id_)
|
if ((watch_id_ == WATCH_ID_NONE) || (telegram->type_id == watch_id_)
|
||||||
|| ((watch_id_ < 0x80) && ((telegram->src == watch_id_) || (telegram->dest == watch_id_)))) {
|
|| ((watch_id_ < 0x80) && ((telegram->src == watch_id_) || (telegram->dest == watch_id_)))) {
|
||||||
LOG_NOTICE(F("%s"), pretty_telegram(telegram).c_str());
|
LOG_NOTICE("%s", pretty_telegram(telegram).c_str());
|
||||||
} else if (!trace_raw_) {
|
} else if (!trace_raw_) {
|
||||||
LOG_TRACE(F("%s"), pretty_telegram(telegram).c_str());
|
LOG_TRACE("%s", pretty_telegram(telegram).c_str());
|
||||||
}
|
}
|
||||||
} else if (!trace_raw_) {
|
} else if (!trace_raw_) {
|
||||||
LOG_TRACE(F("%s"), pretty_telegram(telegram).c_str());
|
LOG_TRACE("%s", pretty_telegram(telegram).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// only process broadcast telegrams or ones sent to us on request
|
// only process broadcast telegrams or ones sent to us on request
|
||||||
// if ((telegram->dest != 0x00) && (telegram->dest != rxservice_.ems_bus_id())) {
|
// if ((telegram->dest != 0x00) && (telegram->dest != rxservice_.ems_bus_id())) {
|
||||||
if (telegram->operation == Telegram::Operation::RX_READ) {
|
if (telegram->operation == Telegram::Operation::RX_READ) {
|
||||||
// LOG_DEBUG(F("read telegram received, not processing"));
|
// LOG_DEBUG("read telegram received, not processing");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -861,9 +858,9 @@ bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
LOG_DEBUG(F("No telegram type handler found for ID 0x%02X (src 0x%02X)"), telegram->type_id, telegram->src);
|
LOG_DEBUG(("No telegram type handler found for ID 0x%02X (src 0x%02X)"), telegram->type_id, telegram->src);
|
||||||
if (watch() == WATCH_UNKNOWN) {
|
if (watch() == WATCH_UNKNOWN) {
|
||||||
LOG_NOTICE(F("%s"), pretty_telegram(telegram).c_str());
|
LOG_NOTICE("%s", pretty_telegram(telegram).c_str());
|
||||||
}
|
}
|
||||||
if (!wait_km_ && !knowndevice && (telegram->src != EMSbus::ems_bus_id()) && (telegram->message_length > 0)) {
|
if (!wait_km_ && !knowndevice && (telegram->src != EMSbus::ems_bus_id()) && (telegram->message_length > 0)) {
|
||||||
send_read_request(EMSdevice::EMS_TYPE_VERSION, telegram->src);
|
send_read_request(EMSdevice::EMS_TYPE_VERSION, telegram->src);
|
||||||
@@ -887,12 +884,12 @@ bool EMSESP::device_exists(const uint8_t device_id) {
|
|||||||
// for each associated EMS device go and get its system information
|
// for each associated EMS device go and get its system information
|
||||||
void EMSESP::show_devices(uuid::console::Shell & shell) {
|
void EMSESP::show_devices(uuid::console::Shell & shell) {
|
||||||
if (emsdevices.empty()) {
|
if (emsdevices.empty()) {
|
||||||
shell.printfln(F("No EMS devices detected. Try using 'scan devices' from the ems menu."));
|
shell.printfln("No EMS devices detected. Try using 'scan devices' from the ems menu.");
|
||||||
shell.println();
|
shell.println();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
shell.printfln(F("These EMS devices are currently active:"));
|
shell.printfln("These EMS devices are currently active:");
|
||||||
shell.println();
|
shell.println();
|
||||||
|
|
||||||
// count the number of thermostats
|
// count the number of thermostats
|
||||||
@@ -908,7 +905,7 @@ void EMSESP::show_devices(uuid::console::Shell & shell) {
|
|||||||
for (const auto & device_class : EMSFactory::device_handlers()) {
|
for (const auto & device_class : EMSFactory::device_handlers()) {
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice && (emsdevice->device_type() == device_class.first)) {
|
if (emsdevice && (emsdevice->device_type() == device_class.first)) {
|
||||||
shell.printf(F("%s: %s"), emsdevice->device_type_name().c_str(), emsdevice->to_string().c_str());
|
shell.printf("%s: %s", emsdevice->device_type_name().c_str(), emsdevice->to_string().c_str());
|
||||||
shell.println();
|
shell.println();
|
||||||
emsdevice->show_telegram_handlers(shell);
|
emsdevice->show_telegram_handlers(shell);
|
||||||
|
|
||||||
@@ -935,7 +932,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
if (product_id == 0) { // update only with valid product_id
|
if (product_id == 0) { // update only with valid product_id
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
LOG_DEBUG(F("Updating details for already active deviceID 0x%02X"), device_id);
|
LOG_DEBUG("Updating details for already active deviceID 0x%02X", device_id);
|
||||||
emsdevice->product_id(product_id);
|
emsdevice->product_id(product_id);
|
||||||
emsdevice->version(version);
|
emsdevice->version(version);
|
||||||
// only set brand if it doesn't already exist
|
// only set brand if it doesn't already exist
|
||||||
@@ -945,7 +942,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
// find the name and flags in our database
|
// find the name and flags in our database
|
||||||
for (const auto & device : device_library_) {
|
for (const auto & device : device_library_) {
|
||||||
if (device.product_id == product_id && device.device_type == emsdevice->device_type()) {
|
if (device.product_id == product_id && device.device_type == emsdevice->device_type()) {
|
||||||
emsdevice->name(std::move(read_flash_string(device.name)));
|
emsdevice->name(device.name);
|
||||||
emsdevice->add_flags(device.flags);
|
emsdevice->add_flags(device.flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -976,14 +973,13 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
|
|
||||||
// if we don't recognize the productID report it and add as a generic device
|
// if we don't recognize the productID report it and add as a generic device
|
||||||
if (device_p == nullptr) {
|
if (device_p == nullptr) {
|
||||||
LOG_NOTICE(F("Unrecognized EMS device (deviceID 0x%02X, productID %d). Please report on GitHub."), device_id, product_id);
|
LOG_NOTICE(("Unrecognized EMS device (deviceID 0x%02X, productID %d). Please report on GitHub."), device_id, product_id);
|
||||||
std::string name("unknown");
|
|
||||||
emsdevices.push_back(
|
emsdevices.push_back(
|
||||||
EMSFactory::add(DeviceType::GENERIC, device_id, product_id, version, name, DeviceFlags::EMS_DEVICE_FLAG_NONE, EMSdevice::Brand::NO_BRAND));
|
EMSFactory::add(DeviceType::GENERIC, device_id, product_id, version, "unknown", DeviceFlags::EMS_DEVICE_FLAG_NONE, EMSdevice::Brand::NO_BRAND));
|
||||||
return false; // not found
|
return false; // not found
|
||||||
}
|
}
|
||||||
|
|
||||||
auto name = read_flash_string(device_p->name);
|
auto name = device_p->name;
|
||||||
auto device_type = device_p->device_type;
|
auto device_type = device_p->device_type;
|
||||||
auto flags = device_p->flags;
|
auto flags = device_p->flags;
|
||||||
|
|
||||||
@@ -1022,14 +1018,14 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
name = "generic boiler";
|
name = "generic boiler";
|
||||||
device_type = DeviceType::BOILER;
|
device_type = DeviceType::BOILER;
|
||||||
flags = DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP;
|
flags = DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP;
|
||||||
LOG_WARNING(F("Unknown EMS boiler. Using generic profile. Please report on GitHub."));
|
LOG_WARNING("Unknown EMS boiler. Using generic profile. Please report on GitHub.");
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING(F("Unrecognized EMS device (device ID 0x%02X, no product ID). Please report on GitHub."), device_id);
|
LOG_WARNING(("Unrecognized EMS device (device ID 0x%02X, no product ID). Please report on GitHub."), device_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG(F("Adding new device %s (deviceID 0x%02X, productID %d, version %s)"), name.c_str(), device_id, product_id, version);
|
LOG_DEBUG(("Adding new device %s (deviceID 0x%02X, productID %d, version %s)"), name, device_id, product_id, version);
|
||||||
emsdevices.push_back(EMSFactory::add(device_type, device_id, product_id, version, name, flags, brand));
|
emsdevices.push_back(EMSFactory::add(device_type, device_id, product_id, version, name, flags, brand));
|
||||||
|
|
||||||
// assign a unique ID. Note that this is not actual unique after a restart as it's dependent on the order that devices are found
|
// assign a unique ID. Note that this is not actual unique after a restart as it's dependent on the order that devices are found
|
||||||
@@ -1043,7 +1039,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
fetch_device_values(device_id); // go and fetch its data
|
fetch_device_values(device_id); // go and fetch its data
|
||||||
|
|
||||||
// Print to LOG showing we've added a new device
|
// Print to LOG showing we've added a new device
|
||||||
LOG_INFO(F("Recognized new %s with deviceID 0x%02X"), EMSdevice::device_type_2_device_name(device_type).c_str(), device_id);
|
LOG_INFO("Recognized new %s with deviceID 0x%02X", EMSdevice::device_type_2_device_name(device_type), device_id);
|
||||||
|
|
||||||
// add command commands for all devices, except for connect, controller and gateway
|
// add command commands for all devices, except for connect, controller and gateway
|
||||||
if ((device_type == DeviceType::CONNECT) || (device_type == DeviceType::CONTROLLER) || (device_type == DeviceType::GATEWAY)) {
|
if ((device_type == DeviceType::CONNECT) || (device_type == DeviceType::CONTROLLER) || (device_type == DeviceType::GATEWAY)) {
|
||||||
@@ -1056,10 +1052,10 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
[device_type](const char * value, const int8_t id, JsonObject & output) {
|
[device_type](const char * value, const int8_t id, JsonObject & output) {
|
||||||
return command_info(device_type, output, id, EMSdevice::OUTPUT_TARGET::API_VERBOSE);
|
return command_info(device_type, output, id, EMSdevice::OUTPUT_TARGET::API_VERBOSE);
|
||||||
},
|
},
|
||||||
F_(info_cmd));
|
FL_(info_cmd));
|
||||||
Command::add(
|
Command::add(
|
||||||
device_type,
|
device_type,
|
||||||
F("values"),
|
("values"),
|
||||||
[device_type](const char * value, const int8_t id, JsonObject & output) {
|
[device_type](const char * value, const int8_t id, JsonObject & output) {
|
||||||
return command_info(device_type, output, id, EMSdevice::OUTPUT_TARGET::API_SHORTNAMES); // HIDDEN command showing short names, used in e.g. /api/boiler
|
return command_info(device_type, output, id, EMSdevice::OUTPUT_TARGET::API_SHORTNAMES); // HIDDEN command showing short names, used in e.g. /api/boiler
|
||||||
},
|
},
|
||||||
@@ -1069,15 +1065,16 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
device_type,
|
device_type,
|
||||||
F_(commands),
|
F_(commands),
|
||||||
[device_type](const char * value, const int8_t id, JsonObject & output) { return command_commands(device_type, output, id); },
|
[device_type](const char * value, const int8_t id, JsonObject & output) { return command_commands(device_type, output, id); },
|
||||||
F_(commands_cmd));
|
FL_(commands_cmd));
|
||||||
Command::add(
|
Command::add(
|
||||||
device_type,
|
device_type,
|
||||||
F_(entities),
|
F_(entities),
|
||||||
[device_type](const char * value, const int8_t id, JsonObject & output) { return command_entities(device_type, output, id); },
|
[device_type](const char * value, const int8_t id, JsonObject & output) { return command_entities(device_type, output, id); },
|
||||||
F_(entities_cmd));
|
FL_(entities_cmd));
|
||||||
|
|
||||||
// MQTT subscribe to the device e.g. "ems-esp/boiler/#"
|
// MQTT subscribe to the device e.g. "ems-esp/boiler/#"
|
||||||
Mqtt::subscribe(device_type, EMSdevice::device_type_2_device_name(device_type) + "/#", nullptr);
|
auto topic = std::string(EMSdevice::device_type_2_device_name(device_type)) + "/#";
|
||||||
|
Mqtt::subscribe(device_type, topic, nullptr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1178,7 +1175,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
|
|||||||
Roomctrl::check((data[1] ^ 0x80 ^ rxservice_.ems_mask()), data);
|
Roomctrl::check((data[1] ^ 0x80 ^ rxservice_.ems_mask()), data);
|
||||||
#ifdef EMSESP_UART_DEBUG
|
#ifdef EMSESP_UART_DEBUG
|
||||||
// get_uptime is only updated once per loop, does not give the right time
|
// get_uptime is only updated once per loop, does not give the right time
|
||||||
LOG_TRACE(F("[UART_DEBUG] Echo after %d ms: %s"), ::millis() - rx_time_, Helpers::data_to_hex(data, length).c_str());
|
LOG_TRACE("[UART_DEBUG] Echo after %d ms: %s", ::millis() - rx_time_, Helpers::data_to_hex(data, length).c_str());
|
||||||
#endif
|
#endif
|
||||||
// add to RxQueue for log/watch
|
// add to RxQueue for log/watch
|
||||||
rxservice_.add(data, length);
|
rxservice_.add(data, length);
|
||||||
@@ -1194,14 +1191,14 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
|
|||||||
// if we're waiting on a Write operation, we want a single byte 1 or 4
|
// if we're waiting on a Write operation, we want a single byte 1 or 4
|
||||||
if ((tx_state == Telegram::Operation::TX_WRITE) && (length == 1)) {
|
if ((tx_state == Telegram::Operation::TX_WRITE) && (length == 1)) {
|
||||||
if (first_value == TxService::TX_WRITE_SUCCESS) {
|
if (first_value == TxService::TX_WRITE_SUCCESS) {
|
||||||
LOG_DEBUG(F("Last Tx write successful"));
|
LOG_DEBUG("Last Tx write successful");
|
||||||
txservice_.increment_telegram_write_count(); // last tx/write was confirmed ok
|
txservice_.increment_telegram_write_count(); // last tx/write was confirmed ok
|
||||||
txservice_.send_poll(); // close the bus
|
txservice_.send_poll(); // close the bus
|
||||||
publish_id_ = txservice_.post_send_query(); // follow up with any post-read if set
|
publish_id_ = txservice_.post_send_query(); // follow up with any post-read if set
|
||||||
txservice_.reset_retry_count();
|
txservice_.reset_retry_count();
|
||||||
tx_successful = true;
|
tx_successful = true;
|
||||||
} else if (first_value == TxService::TX_WRITE_FAIL) {
|
} else if (first_value == TxService::TX_WRITE_FAIL) {
|
||||||
LOG_ERROR(F("Last Tx write rejected by host"));
|
LOG_ERROR("Last Tx write rejected by host");
|
||||||
txservice_.send_poll(); // close the bus
|
txservice_.send_poll(); // close the bus
|
||||||
txservice_.reset_retry_count();
|
txservice_.reset_retry_count();
|
||||||
}
|
}
|
||||||
@@ -1210,7 +1207,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
|
|||||||
uint8_t src = data[0];
|
uint8_t src = data[0];
|
||||||
uint8_t dest = data[1];
|
uint8_t dest = data[1];
|
||||||
if (txservice_.is_last_tx(src, dest)) {
|
if (txservice_.is_last_tx(src, dest)) {
|
||||||
LOG_DEBUG(F("Last Tx read successful"));
|
LOG_DEBUG("Last Tx read successful");
|
||||||
txservice_.increment_telegram_read_count();
|
txservice_.increment_telegram_read_count();
|
||||||
txservice_.send_poll(); // close the bus
|
txservice_.send_poll(); // close the bus
|
||||||
txservice_.reset_retry_count();
|
txservice_.reset_retry_count();
|
||||||
@@ -1252,11 +1249,11 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
|
|||||||
#ifdef EMSESP_UART_DEBUG
|
#ifdef EMSESP_UART_DEBUG
|
||||||
char s[4];
|
char s[4];
|
||||||
if (first_value & 0x80) {
|
if (first_value & 0x80) {
|
||||||
LOG_TRACE(F("[UART_DEBUG] next Poll %s after %d ms"), Helpers::hextoa(s, first_value), ::millis() - rx_time_);
|
LOG_TRACE("[UART_DEBUG] next Poll %s after %d ms", Helpers::hextoa(s, first_value), ::millis() - rx_time_);
|
||||||
// time measurement starts here, use millis because get_uptime is only updated once per loop
|
// time measurement starts here, use millis because get_uptime is only updated once per loop
|
||||||
rx_time_ = ::millis();
|
rx_time_ = ::millis();
|
||||||
} else {
|
} else {
|
||||||
LOG_TRACE(F("[UART_DEBUG] Poll ack %s after %d ms"), Helpers::hextoa(s, first_value), ::millis() - rx_time_);
|
LOG_TRACE("[UART_DEBUG] Poll ack %s after %d ms", Helpers::hextoa(s, first_value), ::millis() - rx_time_);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// check for poll to us, if so send top message from Tx queue immediately and quit
|
// check for poll to us, if so send top message from Tx queue immediately and quit
|
||||||
@@ -1268,7 +1265,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
#ifdef EMSESP_UART_DEBUG
|
#ifdef EMSESP_UART_DEBUG
|
||||||
LOG_TRACE(F("[UART_DEBUG] Reply after %d ms: %s"), ::millis() - rx_time_, Helpers::data_to_hex(data, length).c_str());
|
LOG_TRACE("[UART_DEBUG] Reply after %d ms: %s", ::millis() - rx_time_, Helpers::data_to_hex(data, length).c_str());
|
||||||
#endif
|
#endif
|
||||||
Roomctrl::check((data[1] ^ 0x80 ^ rxservice_.ems_mask()), data); // check if there is a message for the roomcontroller
|
Roomctrl::check((data[1] ^ 0x80 ^ rxservice_.ems_mask()), data); // check if there is a message for the roomcontroller
|
||||||
|
|
||||||
@@ -1293,14 +1290,14 @@ void EMSESP::start() {
|
|||||||
webLogService.begin(); // start web log service. now we can start capturing logs to the web log
|
webLogService.begin(); // start web log service. now we can start capturing logs to the web log
|
||||||
|
|
||||||
#ifdef EMSESP_DEBUG
|
#ifdef EMSESP_DEBUG
|
||||||
LOG_NOTICE(F("System is running in Debug mode"));
|
LOG_NOTICE("System is running in Debug mode");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LOG_INFO(F("Last system reset reason Core0: %s, Core1: %s"), system_.reset_reason(0).c_str(), system_.reset_reason(1).c_str());
|
LOG_INFO("Last system reset reason Core0: %s, Core1: %s", system_.reset_reason(0).c_str(), system_.reset_reason(1).c_str());
|
||||||
|
|
||||||
// do any system upgrades
|
// do any system upgrades
|
||||||
if (system_.check_upgrade()) {
|
if (system_.check_upgrade()) {
|
||||||
LOG_INFO(F("System needs a restart to apply new settings. Please wait."));
|
LOG_INFO("System needs a restart to apply new settings. Please wait.");
|
||||||
system_.system_restart();
|
system_.system_restart();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1316,7 +1313,7 @@ void EMSESP::start() {
|
|||||||
// start all the EMS-ESP services
|
// start all the EMS-ESP services
|
||||||
mqtt_.start(); // mqtt init
|
mqtt_.start(); // mqtt init
|
||||||
system_.start(); // starts commands, led, adc, button, network, syslog & uart
|
system_.start(); // starts commands, led, adc, button, network, syslog & uart
|
||||||
LOG_INFO(F("Starting EMS-ESP version %s (hostname: %s)"), EMSESP_APP_VERSION, system_.hostname().c_str()); // welcome message
|
LOG_INFO(("Starting EMS-ESP version %s (hostname: %s)"), EMSESP_APP_VERSION, system_.hostname().c_str()); // welcome message
|
||||||
|
|
||||||
shower_.start(); // initialize shower timer and shower alert
|
shower_.start(); // initialize shower timer and shower alert
|
||||||
dallassensor_.start(); // Dallas external sensors
|
dallassensor_.start(); // Dallas external sensors
|
||||||
@@ -1327,7 +1324,7 @@ void EMSESP::start() {
|
|||||||
device_library_ = {
|
device_library_ = {
|
||||||
#include "device_library.h"
|
#include "device_library.h"
|
||||||
};
|
};
|
||||||
LOG_INFO(F("Loaded EMS device library (%d records)"), device_library_.size());
|
LOG_INFO(("Loaded EMS device library (%d records)"), device_library_.size());
|
||||||
|
|
||||||
#if defined(EMSESP_STANDALONE)
|
#if defined(EMSESP_STANDALONE)
|
||||||
Mqtt::on_connect(); // simulate an MQTT connection
|
Mqtt::on_connect(); // simulate an MQTT connection
|
||||||
@@ -1344,6 +1341,7 @@ void EMSESP::scheduled_fetch_values() {
|
|||||||
last_fetch_ = uuid::get_uptime();
|
last_fetch_ = uuid::get_uptime();
|
||||||
no = 1;
|
no = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (txservice_.tx_queue_empty()) {
|
if (txservice_.tx_queue_empty()) {
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
|
|||||||
@@ -251,10 +251,10 @@ class EMSESP {
|
|||||||
static constexpr uint8_t EMS_WAIT_KM_TIMEOUT = 60; // wait one minute
|
static constexpr uint8_t EMS_WAIT_KM_TIMEOUT = 60; // wait one minute
|
||||||
|
|
||||||
struct Device_record {
|
struct Device_record {
|
||||||
uint8_t product_id;
|
uint8_t product_id;
|
||||||
EMSdevice::DeviceType device_type;
|
EMSdevice::DeviceType device_type;
|
||||||
const __FlashStringHelper * name;
|
const char * name;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
};
|
};
|
||||||
static std::vector<Device_record> device_library_;
|
static std::vector<Device_record> device_library_;
|
||||||
|
|
||||||
|
|||||||
@@ -55,12 +55,12 @@ class EMSFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Construct derived class returning an unique ptr
|
// Construct derived class returning an unique ptr
|
||||||
static auto add(const uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, std::string & name, uint8_t flags, uint8_t brand)
|
static auto add(const uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||||
-> std::unique_ptr<EMSdevice> {
|
-> std::unique_ptr<EMSdevice> {
|
||||||
return std::unique_ptr<EMSdevice>(EMSFactory::makeRaw(device_type, device_id, product_id, version, name, flags, brand));
|
return std::unique_ptr<EMSdevice>(EMSFactory::makeRaw(device_type, device_id, product_id, version, name, flags, brand));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual auto construct(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, std::string & name, uint8_t flags, uint8_t brand) const
|
virtual auto construct(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand) const
|
||||||
-> EMSdevice * = 0;
|
-> EMSdevice * = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -72,7 +72,7 @@ class EMSFactory {
|
|||||||
|
|
||||||
// Construct derived class returning a raw pointer
|
// Construct derived class returning a raw pointer
|
||||||
// find which EMS device it is and use that class
|
// find which EMS device it is and use that class
|
||||||
static auto makeRaw(const uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, std::string & name, uint8_t flags, uint8_t brand)
|
static auto makeRaw(const uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
||||||
-> EMSdevice * {
|
-> EMSdevice * {
|
||||||
auto it = EMSFactory::getRegister().find(device_type);
|
auto it = EMSFactory::getRegister().find(device_type);
|
||||||
if (it != EMSFactory::getRegister().end()) {
|
if (it != EMSFactory::getRegister().end()) {
|
||||||
@@ -90,7 +90,7 @@ class ConcreteEMSFactory : EMSFactory {
|
|||||||
EMSFactory::registerFactory(device_type, this);
|
EMSFactory::registerFactory(device_type, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto construct(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, std::string & name, uint8_t flags, uint8_t brand) const
|
auto construct(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand) const
|
||||||
-> EMSdevice * {
|
-> EMSdevice * {
|
||||||
return new DerivedClass(device_type, device_id, product_id, version, name, flags, brand);
|
return new DerivedClass(device_type, device_id, product_id, version, name, flags, brand);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,9 +179,9 @@ char * Helpers::render_boolean(char * result, const bool value, const bool dashb
|
|||||||
uint8_t bool_format_ = dashboard ? EMSESP::system_.bool_dashboard() : EMSESP::system_.bool_format();
|
uint8_t bool_format_ = dashboard ? EMSESP::system_.bool_dashboard() : EMSESP::system_.bool_format();
|
||||||
|
|
||||||
if (bool_format_ == BOOL_FORMAT_ONOFF_STR) {
|
if (bool_format_ == BOOL_FORMAT_ONOFF_STR) {
|
||||||
strlcpy(result, value ? translated_word(FL_(on)).c_str() : translated_word(FL_(off)).c_str(), 5);
|
strlcpy(result, value ? translated_word(FL_(on)) : translated_word(FL_(off)), 5);
|
||||||
} else if (bool_format_ == BOOL_FORMAT_ONOFF_STR_CAP) {
|
} else if (bool_format_ == BOOL_FORMAT_ONOFF_STR_CAP) {
|
||||||
strlcpy(result, value ? translated_word(FL_(ON)).c_str() : translated_word(FL_(OFF)).c_str(), 5);
|
strlcpy(result, value ? translated_word(FL_(ON)) : translated_word(FL_(OFF)), 5);
|
||||||
} else if ((bool_format_ == BOOL_FORMAT_10) || (bool_format_ == BOOL_FORMAT_10_STR)) {
|
} else if ((bool_format_ == BOOL_FORMAT_10) || (bool_format_ == BOOL_FORMAT_10_STR)) {
|
||||||
strlcpy(result, value ? "1" : "0", 2);
|
strlcpy(result, value ? "1" : "0", 2);
|
||||||
} else {
|
} else {
|
||||||
@@ -593,12 +593,12 @@ bool Helpers::value2bool(const char * value, bool & value_b) {
|
|||||||
|
|
||||||
std::string bool_str = toLower(value); // convert to lower case
|
std::string bool_str = toLower(value); // convert to lower case
|
||||||
|
|
||||||
if ((bool_str == Helpers::translated_word(FL_(on))) || (bool_str == "on") || (bool_str == "1") || (bool_str == "true")) {
|
if ((bool_str == std::string(Helpers::translated_word(FL_(on)))) || (bool_str == "on") || (bool_str == "1") || (bool_str == "true")) {
|
||||||
value_b = true;
|
value_b = true;
|
||||||
return true; // is a bool
|
return true; // is a bool
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((bool_str == Helpers::translated_word(FL_(off))) || (bool_str == "off") || (bool_str == "0") || (bool_str == "false")) {
|
if ((bool_str == std::string(Helpers::translated_word(FL_(off)))) || (bool_str == "off") || (bool_str == "0") || (bool_str == "false")) {
|
||||||
value_b = false;
|
value_b = false;
|
||||||
return true; // is a bool
|
return true; // is a bool
|
||||||
}
|
}
|
||||||
@@ -608,15 +608,15 @@ bool Helpers::value2bool(const char * value, bool & value_b) {
|
|||||||
|
|
||||||
// checks to see if a string is member of a vector and return the index, also allow true/false for on/off
|
// checks to see if a string is member of a vector and return the index, also allow true/false for on/off
|
||||||
// this for a list of lists, when using translated strings
|
// this for a list of lists, when using translated strings
|
||||||
bool Helpers::value2enum(const char * value, uint8_t & value_ui, const __FlashStringHelper * const ** strs) {
|
bool Helpers::value2enum(const char * value, uint8_t & value_ui, const char * const ** strs) {
|
||||||
if ((value == nullptr) || (strlen(value) == 0)) {
|
if ((value == nullptr) || (strlen(value) == 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::string str = toLower(value);
|
std::string str = toLower(value);
|
||||||
|
|
||||||
for (value_ui = 0; strs[value_ui]; value_ui++) {
|
for (value_ui = 0; strs[value_ui]; value_ui++) {
|
||||||
std::string str1 = toLower(Helpers::translated_word(strs[value_ui]));
|
std::string str1 = toLower(std::string(Helpers::translated_word(strs[value_ui])));
|
||||||
std::string str2 = toLower(read_flash_string(strs[value_ui][0])); // also check for default language
|
std::string str2 = toLower((strs[value_ui][0])); // also check for default language
|
||||||
if ((str1 != "")
|
if ((str1 != "")
|
||||||
&& ((str2 == "off" && str == "false") || (str2 == "on" && str == "true") || (str == str1) || (str == str2)
|
&& ((str2 == "off" && str == "false") || (str2 == "on" && str == "true") || (str == str1) || (str == str2)
|
||||||
|| (value[0] == ('0' + value_ui) && value[1] == '\0'))) {
|
|| (value[0] == ('0' + value_ui) && value[1] == '\0'))) {
|
||||||
@@ -627,19 +627,25 @@ bool Helpers::value2enum(const char * value, uint8_t & value_ui, const __FlashSt
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks to see if a string is member of a vector and return the index, also allow true/false for on/off
|
// finds the string (value) of a list vector (strs)
|
||||||
bool Helpers::value2enum(const char * value, uint8_t & value_ui, const __FlashStringHelper * const * strs) {
|
// returns true if found, and sets the value_ui to the index, else false
|
||||||
|
// also allow true/false for on/off
|
||||||
|
bool Helpers::value2enum(const char * value, uint8_t & value_ui, const char * const * strs) {
|
||||||
if ((value == nullptr) || (strlen(value) == 0)) {
|
if ((value == nullptr) || (strlen(value) == 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::string str = toLower(value);
|
std::string str = toLower(value);
|
||||||
|
|
||||||
|
std::string s_on = Helpers::translated_word(FL_(on));
|
||||||
|
std::string s_off = Helpers::translated_word(FL_(off));
|
||||||
|
|
||||||
|
// stops when a nullptr is found, which is the end delimeter of a MAKE_PSTR_LIST()
|
||||||
|
// could use count_items() to avoid buffer over-run but this works
|
||||||
for (value_ui = 0; strs[value_ui]; value_ui++) {
|
for (value_ui = 0; strs[value_ui]; value_ui++) {
|
||||||
std::string enum_str = toLower(read_flash_string(strs[value_ui]));
|
std::string enum_str = toLower((strs[value_ui]));
|
||||||
|
|
||||||
if ((enum_str != "")
|
if ((enum_str != "")
|
||||||
&& ((enum_str == "off" && (str == Helpers::translated_word(FL_(off)) || str == "false"))
|
&& ((enum_str == "off" && (str == s_off || str == "false")) || (enum_str == "on" && (str == s_on || str == "true")) || (str == enum_str)
|
||||||
|| (enum_str == "on" && (str == Helpers::translated_word(FL_(on)) || str == "true")) || (str == enum_str)
|
|
||||||
|| (value[0] == ('0' + value_ui) && value[1] == '\0'))) {
|
|| (value[0] == ('0' + value_ui) && value[1] == '\0'))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -655,6 +661,10 @@ std::string Helpers::toLower(std::string const & s) {
|
|||||||
return lc;
|
return lc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Helpers::toLower(const char * s) {
|
||||||
|
return toLower(std::string(s));
|
||||||
|
}
|
||||||
|
|
||||||
std::string Helpers::toUpper(std::string const & s) {
|
std::string Helpers::toUpper(std::string const & s) {
|
||||||
std::string lc = s;
|
std::string lc = s;
|
||||||
std::transform(lc.begin(), lc.end(), lc.begin(), [](unsigned char c) { return std::toupper(c); });
|
std::transform(lc.begin(), lc.end(), lc.begin(), [](unsigned char c) { return std::toupper(c); });
|
||||||
@@ -676,7 +686,7 @@ void Helpers::replace_char(char * str, char find, char replace) {
|
|||||||
|
|
||||||
// count number of items in a list
|
// count number of items in a list
|
||||||
// the end of a list has a nullptr
|
// the end of a list has a nullptr
|
||||||
uint8_t Helpers::count_items(const __FlashStringHelper * const * list) {
|
uint8_t Helpers::count_items(const char * const * list) {
|
||||||
uint8_t list_size = 0;
|
uint8_t list_size = 0;
|
||||||
if (list != nullptr) {
|
if (list != nullptr) {
|
||||||
while (list[list_size]) {
|
while (list[list_size]) {
|
||||||
@@ -688,7 +698,7 @@ uint8_t Helpers::count_items(const __FlashStringHelper * const * list) {
|
|||||||
|
|
||||||
// count number of items in a list of lists
|
// count number of items in a list of lists
|
||||||
// the end of a list has a nullptr
|
// the end of a list has a nullptr
|
||||||
uint8_t Helpers::count_items(const __FlashStringHelper * const ** list) {
|
uint8_t Helpers::count_items(const char * const ** list) {
|
||||||
uint8_t list_size = 0;
|
uint8_t list_size = 0;
|
||||||
if (list != nullptr) {
|
if (list != nullptr) {
|
||||||
while (list[list_size]) {
|
while (list[list_size]) {
|
||||||
@@ -698,27 +708,17 @@ uint8_t Helpers::count_items(const __FlashStringHelper * const ** list) {
|
|||||||
return list_size;
|
return list_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return translated string as a std::string, optionally converting to lowercase (for console commands)
|
// returns char pointer to translated description or fullname
|
||||||
// takes a FL(...)
|
const char * Helpers::translated_word(const char * const * strings) {
|
||||||
std::string Helpers::translated_word(const __FlashStringHelper * const * strings, bool to_lower) {
|
|
||||||
uint8_t language_index = EMSESP::system_.language_index();
|
uint8_t language_index = EMSESP::system_.language_index();
|
||||||
uint8_t index = 0;
|
uint8_t index = 0;
|
||||||
|
|
||||||
// see how many translations we have for this entity. if there is no translation for this, revert to EN
|
if (!strings) {
|
||||||
if (Helpers::count_items(strings) >= language_index + 1 && !read_flash_string(strings[language_index]).empty()) {
|
return ""; // no translations
|
||||||
index = language_index;
|
|
||||||
}
|
}
|
||||||
return to_lower ? toLower(read_flash_string(strings[index])) : read_flash_string(strings[index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// return translated string
|
|
||||||
// takes a F(...)
|
|
||||||
const __FlashStringHelper * Helpers::translated_fword(const __FlashStringHelper * const * strings) {
|
|
||||||
uint8_t language_index = EMSESP::system_.language_index();
|
|
||||||
uint8_t index = 0;
|
|
||||||
|
|
||||||
// see how many translations we have for this entity. if there is no translation for this, revert to EN
|
// see how many translations we have for this entity. if there is no translation for this, revert to EN
|
||||||
if (Helpers::count_items(strings) >= language_index + 1 && !read_flash_string(strings[language_index]).empty()) {
|
if (Helpers::count_items(strings) >= language_index + 1 && strlen(strings[language_index])) {
|
||||||
index = language_index;
|
index = language_index;
|
||||||
}
|
}
|
||||||
return strings[index];
|
return strings[index];
|
||||||
|
|||||||
@@ -54,7 +54,9 @@ class Helpers {
|
|||||||
|
|
||||||
static std::string toLower(std::string const & s);
|
static std::string toLower(std::string const & s);
|
||||||
static std::string toUpper(std::string const & s);
|
static std::string toUpper(std::string const & s);
|
||||||
static void replace_char(char * str, char find, char replace);
|
static std::string toLower(const char * s);
|
||||||
|
|
||||||
|
static void replace_char(char * str, char find, char replace);
|
||||||
|
|
||||||
static bool hasValue(const uint8_t & value, const uint8_t isBool = 0);
|
static bool hasValue(const uint8_t & value, const uint8_t isBool = 0);
|
||||||
static bool hasValue(const int8_t & value);
|
static bool hasValue(const int8_t & value);
|
||||||
@@ -67,16 +69,15 @@ class Helpers {
|
|||||||
static bool value2float(const char * value, float & value_f);
|
static bool value2float(const char * value, float & value_f);
|
||||||
static bool value2bool(const char * value, bool & value_b);
|
static bool value2bool(const char * value, bool & value_b);
|
||||||
static bool value2string(const char * value, std::string & value_s);
|
static bool value2string(const char * value, std::string & value_s);
|
||||||
static bool value2enum(const char * value, uint8_t & value_ui, const __FlashStringHelper * const ** strs);
|
static bool value2enum(const char * value, uint8_t & value_ui, const char * const ** strs);
|
||||||
static bool value2enum(const char * value, uint8_t & value_ui, const __FlashStringHelper * const * strs);
|
static bool value2enum(const char * value, uint8_t & value_ui, const char * const * strs);
|
||||||
static bool value2temperature(const char * value, float & value_f, bool relative = false);
|
static bool value2temperature(const char * value, float & value_f, bool relative = false);
|
||||||
static bool value2temperature(const char * value, int & value_i, const bool relative = false, const int min = -2147483648, const int max = 2147483647);
|
static bool value2temperature(const char * value, int & value_i, const bool relative = false, const int min = -2147483648, const int max = 2147483647);
|
||||||
|
|
||||||
static uint8_t count_items(const __FlashStringHelper * const ** list);
|
static uint8_t count_items(const char * const ** list);
|
||||||
static uint8_t count_items(const __FlashStringHelper * const * list);
|
static uint8_t count_items(const char * const * list);
|
||||||
|
|
||||||
static std::string translated_word(const __FlashStringHelper * const * strings, bool to_lower = false);
|
static const char * translated_word(const char * const * strings);
|
||||||
static const __FlashStringHelper * translated_fword(const __FlashStringHelper * const * strings);
|
|
||||||
|
|
||||||
#ifdef EMSESP_STANDALONE
|
#ifdef EMSESP_STANDALONE
|
||||||
static char * ultostr(char * ptr, uint32_t value, const uint8_t base);
|
static char * ultostr(char * ptr, uint32_t value, const uint8_t base);
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* THIS FILE CONTAINS STANDARD STRING LITERALS THAT DON'T NEED LANGUAGE TRANSLATIONS
|
* THIS FILE CONTAINS STANDARD STRING LITERALS THAT DON'T NEED LANGUAGE TRANSLATIONS
|
||||||
*/
|
*/
|
||||||
@@ -144,55 +146,55 @@ MAKE_PSTR(password_prompt, "Password: ")
|
|||||||
MAKE_PSTR(unset, "<unset>")
|
MAKE_PSTR(unset, "<unset>")
|
||||||
|
|
||||||
// more common names that don't need translations
|
// more common names that don't need translations
|
||||||
MAKE_PSTR_LIST(1x3min, F("1x3min"))
|
MAKE_PSTR_LIST(1x3min, "1x3min")
|
||||||
MAKE_PSTR_LIST(2x3min, F("2x3min"))
|
MAKE_PSTR_LIST(2x3min, "2x3min")
|
||||||
MAKE_PSTR_LIST(3x3min, F("3x3min"))
|
MAKE_PSTR_LIST(3x3min, "3x3min")
|
||||||
MAKE_PSTR_LIST(4x3min, F("4x3min"))
|
MAKE_PSTR_LIST(4x3min, "4x3min")
|
||||||
MAKE_PSTR_LIST(5x3min, F("5x3min"))
|
MAKE_PSTR_LIST(5x3min, "5x3min")
|
||||||
MAKE_PSTR_LIST(6x3min, F("6x3min"))
|
MAKE_PSTR_LIST(6x3min, "6x3min")
|
||||||
MAKE_PSTR_LIST(auto, F("auto"))
|
MAKE_PSTR_LIST(auto, "auto")
|
||||||
MAKE_PSTR_LIST(na, F("n/a"))
|
MAKE_PSTR_LIST(na, "n/a")
|
||||||
MAKE_PSTR_LIST(rc3x, F("rc3x"))
|
MAKE_PSTR_LIST(rc3x, "rc3x")
|
||||||
MAKE_PSTR_LIST(rc20, F("rc20"))
|
MAKE_PSTR_LIST(rc20, "rc20")
|
||||||
MAKE_PSTR_LIST(fb10, F("fb10"))
|
MAKE_PSTR_LIST(fb10, "fb10")
|
||||||
MAKE_PSTR_LIST(fb100, F("fb100"))
|
MAKE_PSTR_LIST(fb100, "fb100")
|
||||||
MAKE_PSTR_LIST(dash, F("-"))
|
MAKE_PSTR_LIST(dash, "-")
|
||||||
MAKE_PSTR_LIST(error, F("error"))
|
MAKE_PSTR_LIST(error, "error")
|
||||||
MAKE_PSTR_LIST(BLANK, F(""))
|
MAKE_PSTR_LIST(BLANK, "")
|
||||||
MAKE_PSTR_LIST(pwm, F("pwm"))
|
MAKE_PSTR_LIST(pwm, "pwm")
|
||||||
MAKE_PSTR_LIST(pwm_invers, F("pwm inverse"))
|
MAKE_PSTR_LIST(pwm_invers, "pwm inverse")
|
||||||
MAKE_PSTR_LIST(mpc, F("mpc"))
|
MAKE_PSTR_LIST(mpc, "mpc")
|
||||||
MAKE_PSTR_LIST(tempauto, F("temp auto"))
|
MAKE_PSTR_LIST(tempauto, "temp auto")
|
||||||
MAKE_PSTR_LIST(bypass, F("bypass"))
|
MAKE_PSTR_LIST(bypass, "bypass")
|
||||||
MAKE_PSTR_LIST(mixer, F("mixer"))
|
MAKE_PSTR_LIST(mixer, "mixer")
|
||||||
MAKE_PSTR_LIST(monovalent, F("monovalent"))
|
MAKE_PSTR_LIST(monovalent, "monovalent")
|
||||||
MAKE_PSTR_LIST(bivalent, F("bivalent"))
|
MAKE_PSTR_LIST(bivalent, "bivalent")
|
||||||
MAKE_PSTR_LIST(n_o, F("n_o"))
|
MAKE_PSTR_LIST(n_o, "n_o")
|
||||||
MAKE_PSTR_LIST(n_c, F("n_c"))
|
MAKE_PSTR_LIST(n_c, "n_c")
|
||||||
MAKE_PSTR_LIST(prog1, F("prog 1"))
|
MAKE_PSTR_LIST(prog1, "prog 1")
|
||||||
MAKE_PSTR_LIST(prog2, F("prog 2"))
|
MAKE_PSTR_LIST(prog2, "prog 2")
|
||||||
MAKE_PSTR_LIST(proga, F("prog a"))
|
MAKE_PSTR_LIST(proga, "prog a")
|
||||||
MAKE_PSTR_LIST(progb, F("prog b"))
|
MAKE_PSTR_LIST(progb, "prog b")
|
||||||
MAKE_PSTR_LIST(progc, F("prog c"))
|
MAKE_PSTR_LIST(progc, "prog c")
|
||||||
MAKE_PSTR_LIST(progd, F("prog d"))
|
MAKE_PSTR_LIST(progd, "prog d")
|
||||||
MAKE_PSTR_LIST(proge, F("prog e"))
|
MAKE_PSTR_LIST(proge, "prog e")
|
||||||
MAKE_PSTR_LIST(progf, F("prog f"))
|
MAKE_PSTR_LIST(progf, "prog f")
|
||||||
MAKE_PSTR_LIST(rc35, F("RC35"))
|
MAKE_PSTR_LIST(rc35, "RC35")
|
||||||
MAKE_PSTR_LIST(0kW, F("0 kW"))
|
MAKE_PSTR_LIST(0kW, "0 kW")
|
||||||
MAKE_PSTR_LIST(2kW, F("2 kW"))
|
MAKE_PSTR_LIST(2kW, "2 kW")
|
||||||
MAKE_PSTR_LIST(3kW, F("3 kW"))
|
MAKE_PSTR_LIST(3kW, "3 kW")
|
||||||
MAKE_PSTR_LIST(4kW, F("4 kW"))
|
MAKE_PSTR_LIST(4kW, "4 kW")
|
||||||
MAKE_PSTR_LIST(6kW, F("6 kW"))
|
MAKE_PSTR_LIST(6kW, "6 kW")
|
||||||
MAKE_PSTR_LIST(9kW, F("9 kW"))
|
MAKE_PSTR_LIST(9kW, "9 kW")
|
||||||
|
|
||||||
// templates - this are not translated and will be saved under optons_single
|
// templates - this are not translated and will be saved under options_single
|
||||||
MAKE_PSTR_LIST(tpl_datetime, F("Format: < NTP | dd.mm.yyyy-hh:mm:ss-day(0-6)-dst(0/1) >"))
|
MAKE_PSTR_LIST(tpl_datetime, "Format: < NTP | dd.mm.yyyy-hh:mm:ss-day(0-6)-dst(0/1) >")
|
||||||
MAKE_PSTR_LIST(tpl_switchtime, F("Format: <nn> [ not_set | day hh:mm on|off ]"))
|
MAKE_PSTR_LIST(tpl_switchtime, "Format: <nn> [ not_set | day hh:mm on|off ]")
|
||||||
MAKE_PSTR_LIST(tpl_switchtime1, F("Format: <nn> [ not_set | day hh:mm Tn ]"))
|
MAKE_PSTR_LIST(tpl_switchtime1, "Format: <nn> [ not_set | day hh:mm Tn ]")
|
||||||
MAKE_PSTR_LIST(tpl_holidays, F("Format: < dd.mm.yyyy-dd.mm.yyyy >"))
|
MAKE_PSTR_LIST(tpl_holidays, "Format: < dd.mm.yyyy-dd.mm.yyyy >")
|
||||||
MAKE_PSTR_LIST(tpl_date, F("Format: < dd.mm.yyyy >"))
|
MAKE_PSTR_LIST(tpl_date, "Format: < dd.mm.yyyy >")
|
||||||
MAKE_PSTR_LIST(tpl_input, F("Format: <inv>[<evu1><evu2><evu3><comp><aux><cool><heat><dhw><pv>]"))
|
MAKE_PSTR_LIST(tpl_input, "Format: <inv>[<evu1><evu2><evu3><comp><aux><cool><heat><dhw><pv>]")
|
||||||
MAKE_PSTR_LIST(tpl_input4, F("Format: <inv>[<comp><aux><cool><heat><dhw><pv>]"))
|
MAKE_PSTR_LIST(tpl_input4, "Format: <inv>[<comp><aux><cool><heat><dhw><pv>]")
|
||||||
|
|
||||||
// Unit Of Measurement mapping - maps to DeviceValueUOM_s in emsdevice.cpp
|
// Unit Of Measurement mapping - maps to DeviceValueUOM_s in emsdevice.cpp
|
||||||
// These don't need translating, it will mess up HA and the API
|
// These don't need translating, it will mess up HA and the API
|
||||||
@@ -217,11 +219,6 @@ MAKE_PSTR(uom_sqm, "sqm")
|
|||||||
MAKE_PSTR(uom_m3, "m3")
|
MAKE_PSTR(uom_m3, "m3")
|
||||||
MAKE_PSTR(uom_l, "l")
|
MAKE_PSTR(uom_l, "l")
|
||||||
|
|
||||||
// commands
|
|
||||||
MAKE_PSTR(info_cmd, "lists all values")
|
|
||||||
MAKE_PSTR(commands_cmd, "lists all commands")
|
|
||||||
MAKE_PSTR(entities_cmd, "lists all entities")
|
|
||||||
|
|
||||||
// TAG mapping - maps to DeviceValueTAG_s in emsdevice.cpp
|
// TAG mapping - maps to DeviceValueTAG_s in emsdevice.cpp
|
||||||
// use empty string if want to suppress showing tags
|
// use empty string if want to suppress showing tags
|
||||||
// mqtt tags must not have spaces
|
// mqtt tags must not have spaces
|
||||||
@@ -273,16 +270,17 @@ MAKE_PSTR(response, "response")
|
|||||||
MAKE_PSTR(tag_boiler_data_ww_mqtt, "ww")
|
MAKE_PSTR(tag_boiler_data_ww_mqtt, "ww")
|
||||||
MAKE_PSTR(tag_device_data_ww_mqtt, "")
|
MAKE_PSTR(tag_device_data_ww_mqtt, "")
|
||||||
|
|
||||||
MAKE_PSTR_LIST(climate, F("HA climate config creation"))
|
// Home Assistant - this is special and has no translations
|
||||||
|
MAKE_PSTR_LIST(climate, "HA climate config creation")
|
||||||
|
|
||||||
// syslog
|
// syslog
|
||||||
MAKE_PSTR_LIST(list_syslog_level, F("off"), F("emerg"), F("alert"), F("crit"), F("error"), F("warn"), F("notice"), F("info"), F("debug"), F("trace"), F("all"))
|
MAKE_PSTR_LIST(list_syslog_level, "off", "emerg", "alert", "crit", "error", "warn", "notice", "info", "debug", "trace", "all")
|
||||||
|
|
||||||
// sensors
|
// sensors
|
||||||
MAKE_PSTR_LIST(list_sensortype, F("none"), F("digital in"), F("counter"), F("adc"), F("timer"), F("rate"), F("digital out"), F("pwm 0"), F("pwm 1"), F("pwm 2"))
|
MAKE_PSTR_LIST(list_sensortype, "none", "digital in", "counter", "adc", "timer", "rate", "digital out", "pwm 0", "pwm 1", "pwm 2")
|
||||||
|
|
||||||
// watch
|
// watch
|
||||||
MAKE_PSTR_LIST(list_watch, F("off"), F("on"), F("raw"), F("unknown"))
|
MAKE_PSTR_LIST(list_watch, "off", "on", "raw", "unknown")
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The rest below are Enums and generated from translations lists
|
* The rest below are Enums and generated from translations lists
|
||||||
@@ -302,16 +300,7 @@ MAKE_PSTR_ENUM(enum_reset, FL_(dash), FL_(maintenance), FL_(error))
|
|||||||
MAKE_PSTR_ENUM(enum_maxHeat, FL_(0kW), FL_(2kW), FL_(3kW), FL_(4kW), FL_(6kW), FL_(9kW))
|
MAKE_PSTR_ENUM(enum_maxHeat, FL_(0kW), FL_(2kW), FL_(3kW), FL_(4kW), FL_(6kW), FL_(9kW))
|
||||||
|
|
||||||
// thermostat lists
|
// thermostat lists
|
||||||
MAKE_PSTR_ENUM(enum_ibaMainDisplay,
|
MAKE_PSTR_ENUM(enum_ibaMainDisplay, FL_(internal_temperature), FL_(internal_setpoint), FL_(external_temperature), FL_(burner_temperature), FL_(ww_temperature), FL_(functioning_mode), FL_(time), FL_(date), FL_(smoke_temperature))
|
||||||
FL_(internal_temperature),
|
|
||||||
FL_(internal_setpoint),
|
|
||||||
FL_(external_temperature),
|
|
||||||
FL_(burner_temperature),
|
|
||||||
FL_(ww_temperature),
|
|
||||||
FL_(functioning_mode),
|
|
||||||
FL_(time),
|
|
||||||
FL_(date),
|
|
||||||
FL_(smoke_temperature))
|
|
||||||
MAKE_PSTR_ENUM(enum_ibaLanguage, FL_(german), FL_(dutch), FL_(french), FL_(italian))
|
MAKE_PSTR_ENUM(enum_ibaLanguage, FL_(german), FL_(dutch), FL_(french), FL_(italian))
|
||||||
MAKE_PSTR_ENUM(enum_ibaLanguage_RC30, FL_(german), FL_(dutch))
|
MAKE_PSTR_ENUM(enum_ibaLanguage_RC30, FL_(german), FL_(dutch))
|
||||||
MAKE_PSTR_ENUM(enum_floordrystatus, FL_(off), FL_(start), FL_(heat), FL_(hold), FL_(cool), FL_(end))
|
MAKE_PSTR_ENUM(enum_floordrystatus, FL_(off), FL_(start), FL_(heat), FL_(hold), FL_(cool), FL_(end))
|
||||||
@@ -379,3 +368,5 @@ MAKE_PSTR_ENUM(enum_bufConfig, FL_(monovalent), FL_(bivalent))
|
|||||||
MAKE_PSTR_ENUM(enum_blockTerm, FL_(n_o), FL_(n_c))
|
MAKE_PSTR_ENUM(enum_blockTerm, FL_(n_o), FL_(n_c))
|
||||||
|
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
// clang-format on
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
279
src/mqtt.cpp
279
src/mqtt.cpp
@@ -186,26 +186,26 @@ void Mqtt::loop() {
|
|||||||
|
|
||||||
// print MQTT log and other stuff to console
|
// print MQTT log and other stuff to console
|
||||||
void Mqtt::show_mqtt(uuid::console::Shell & shell) {
|
void Mqtt::show_mqtt(uuid::console::Shell & shell) {
|
||||||
shell.printfln(F("MQTT is %s"), connected() ? read_flash_string(F_(connected)).c_str() : read_flash_string(F_(disconnected)).c_str());
|
shell.printfln("MQTT is %s", connected() ? F_(connected) : F_(disconnected));
|
||||||
|
|
||||||
shell.printfln(F("MQTT publish errors: %lu"), mqtt_publish_fails_);
|
shell.printfln("MQTT publish errors: %lu", mqtt_publish_fails_);
|
||||||
shell.println();
|
shell.println();
|
||||||
|
|
||||||
// show subscriptions
|
// show subscriptions
|
||||||
shell.printfln(F("MQTT topic subscriptions:"));
|
shell.printfln("MQTT topic subscriptions:");
|
||||||
for (const auto & mqtt_subfunction : mqtt_subfunctions_) {
|
for (const auto & mqtt_subfunction : mqtt_subfunctions_) {
|
||||||
shell.printfln(F(" %s/%s"), mqtt_base_.c_str(), mqtt_subfunction.topic_.c_str());
|
shell.printfln(" %s/%s", mqtt_base_.c_str(), mqtt_subfunction.topic_.c_str());
|
||||||
}
|
}
|
||||||
shell.println();
|
shell.println();
|
||||||
|
|
||||||
// show queues
|
// show queues
|
||||||
if (mqtt_messages_.empty()) {
|
if (mqtt_messages_.empty()) {
|
||||||
shell.printfln(F("MQTT queue is empty"));
|
shell.printfln("MQTT queue is empty");
|
||||||
shell.println();
|
shell.println();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
shell.printfln(F("MQTT queue (%d/%d messages):"), mqtt_messages_.size(), MAX_MQTT_MESSAGES);
|
shell.printfln(("MQTT queue (%d/%d messages):"), mqtt_messages_.size(), MAX_MQTT_MESSAGES);
|
||||||
|
|
||||||
for (const auto & message : mqtt_messages_) {
|
for (const auto & message : mqtt_messages_) {
|
||||||
auto content = message.content_;
|
auto content = message.content_;
|
||||||
@@ -222,12 +222,12 @@ void Mqtt::show_mqtt(uuid::console::Shell & shell) {
|
|||||||
// Publish messages
|
// Publish messages
|
||||||
if (message.retry_count_ == 0) {
|
if (message.retry_count_ == 0) {
|
||||||
if (message.packet_id_ == 0) {
|
if (message.packet_id_ == 0) {
|
||||||
shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s"), message.id_, topic, content->payload.c_str());
|
shell.printfln((" [%02d] (Pub) topic=%s payload=%s"), message.id_, topic, content->payload.c_str());
|
||||||
} else {
|
} else {
|
||||||
shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s (pid %d)"), message.id_, topic, content->payload.c_str(), message.packet_id_);
|
shell.printfln((" [%02d] (Pub) topic=%s payload=%s (pid %d)"), message.id_, topic, content->payload.c_str(), message.packet_id_);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s (pid %d, retry #%d)"),
|
shell.printfln((" [%02d] (Pub) topic=%s payload=%s (pid %d, retry #%d)"),
|
||||||
message.id_,
|
message.id_,
|
||||||
topic,
|
topic,
|
||||||
content->payload.c_str(),
|
content->payload.c_str(),
|
||||||
@@ -236,7 +236,7 @@ void Mqtt::show_mqtt(uuid::console::Shell & shell) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Subscribe messages
|
// Subscribe messages
|
||||||
shell.printfln(F(" [%02d] (Sub) topic=%s"), message.id_, topic);
|
shell.printfln((" [%02d] (Sub) topic=%s"), message.id_, topic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shell.println();
|
shell.println();
|
||||||
@@ -264,16 +264,16 @@ void Mqtt::on_message(const char * topic, const char * payload, size_t len) cons
|
|||||||
|
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
if (len) {
|
if (len) {
|
||||||
LOG_DEBUG(F("Received topic `%s` => payload `%s` (length %d)"), topic, message, len);
|
LOG_DEBUG(("Received topic `%s` => payload `%s` (length %d)"), topic, message, len);
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG(F("Received topic `%s`"), topic);
|
LOG_DEBUG("Received topic `%s`", topic);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// remove HA topics if we don't use discovery
|
// remove HA topics if we don't use discovery
|
||||||
if (strncmp(topic, discovery_prefix().c_str(), discovery_prefix().size()) == 0) {
|
if (strncmp(topic, discovery_prefix().c_str(), discovery_prefix().size()) == 0) {
|
||||||
if (!ha_enabled_ && len) { // don't ping pong the empty message
|
if (!ha_enabled_ && len) { // don't ping pong the empty message
|
||||||
queue_publish_message(topic, "", true);
|
queue_publish_message(topic, "", true);
|
||||||
LOG_DEBUG(F("Remove topic %s"), topic);
|
LOG_DEBUG("Remove topic %s", topic);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -285,7 +285,7 @@ void Mqtt::on_message(const char * topic, const char * payload, size_t len) cons
|
|||||||
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(F("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(F_(response), "error: invalid data");
|
||||||
}
|
}
|
||||||
@@ -341,10 +341,10 @@ void Mqtt::show_topic_handlers(uuid::console::Shell & shell, const uint8_t devic
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// shell.print(F(" Subscribed MQTT topics: "));
|
// shell.print(" Subscribed MQTT topics: ");
|
||||||
// for (const auto & mqtt_subfunction : mqtt_subfunctions_) {
|
// for (const auto & mqtt_subfunction : mqtt_subfunctions_) {
|
||||||
// if (mqtt_subfunction.device_type_ == device_type) {
|
// if (mqtt_subfunction.device_type_ == device_type) {
|
||||||
// shell.printf(F("%s "), mqtt_subfunction.topic_.c_str());
|
// shell.printf("%s ", mqtt_subfunction.topic_.c_str());
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
shell.println();
|
shell.println();
|
||||||
@@ -358,7 +358,7 @@ void Mqtt::on_publish(uint16_t packetId) const {
|
|||||||
// find the MQTT message in the queue and remove it
|
// find the MQTT message in the queue and remove it
|
||||||
if (mqtt_messages_.empty()) {
|
if (mqtt_messages_.empty()) {
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
LOG_DEBUG(F("[DEBUG] No message stored for ACK pid %d"), packetId);
|
LOG_DEBUG("[DEBUG] No message stored for ACK pid %d", packetId);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -368,18 +368,18 @@ void Mqtt::on_publish(uint16_t packetId) const {
|
|||||||
// if the last published failed, don't bother checking it. wait for the next retry
|
// if the last published failed, don't bother checking it. wait for the next retry
|
||||||
if (mqtt_message.packet_id_ == 0) {
|
if (mqtt_message.packet_id_ == 0) {
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
LOG_DEBUG(F("[DEBUG] ACK for failed message pid 0"));
|
LOG_DEBUG("[DEBUG] ACK for failed message pid 0");
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mqtt_message.packet_id_ != packetId) {
|
if (mqtt_message.packet_id_ != packetId) {
|
||||||
LOG_ERROR(F("Mismatch, expecting PID %d, got %d"), mqtt_message.packet_id_, packetId);
|
LOG_ERROR("Mismatch, expecting PID %d, got %d", mqtt_message.packet_id_, packetId);
|
||||||
mqtt_publish_fails_++; // increment error count
|
mqtt_publish_fails_++; // increment error count
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
LOG_DEBUG(F("[DEBUG] ACK pid %d"), packetId);
|
LOG_DEBUG("[DEBUG] ACK pid %d", packetId);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mqtt_messages_.pop_front(); // always remove from queue, regardless if there was a successful ACK
|
mqtt_messages_.pop_front(); // always remove from queue, regardless if there was a successful ACK
|
||||||
@@ -450,17 +450,17 @@ void Mqtt::start() {
|
|||||||
}
|
}
|
||||||
connecting_ = false;
|
connecting_ = false;
|
||||||
if (reason == AsyncMqttClientDisconnectReason::TCP_DISCONNECTED) {
|
if (reason == AsyncMqttClientDisconnectReason::TCP_DISCONNECTED) {
|
||||||
LOG_WARNING(F("MQTT disconnected: TCP"));
|
LOG_WARNING("MQTT disconnected: TCP");
|
||||||
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_IDENTIFIER_REJECTED) {
|
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_IDENTIFIER_REJECTED) {
|
||||||
LOG_WARNING(F("MQTT disconnected: Identifier Rejected"));
|
LOG_WARNING("MQTT disconnected: Identifier Rejected");
|
||||||
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_SERVER_UNAVAILABLE) {
|
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_SERVER_UNAVAILABLE) {
|
||||||
LOG_WARNING(F("MQTT disconnected: Server unavailable"));
|
LOG_WARNING("MQTT disconnected: Server unavailable");
|
||||||
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_MALFORMED_CREDENTIALS) {
|
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_MALFORMED_CREDENTIALS) {
|
||||||
LOG_WARNING(F("MQTT disconnected: Malformed credentials"));
|
LOG_WARNING("MQTT disconnected: Malformed credentials");
|
||||||
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_NOT_AUTHORIZED) {
|
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_NOT_AUTHORIZED) {
|
||||||
LOG_WARNING(F("MQTT disconnected: Not authorized"));
|
LOG_WARNING("MQTT disconnected: Not authorized");
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING(F("MQTT disconnected: code %d"), reason);
|
LOG_WARNING("MQTT disconnected: code %d", reason);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -535,7 +535,7 @@ void Mqtt::on_connect() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO(F("MQTT connected"));
|
LOG_INFO("MQTT connected");
|
||||||
|
|
||||||
connecting_ = true;
|
connecting_ = true;
|
||||||
connectcount_++;
|
connectcount_++;
|
||||||
@@ -546,15 +546,15 @@ void Mqtt::on_connect() {
|
|||||||
StaticJsonDocument<EMSESP_JSON_SIZE_MEDIUM> doc;
|
StaticJsonDocument<EMSESP_JSON_SIZE_MEDIUM> doc;
|
||||||
// first time to connect
|
// first time to connect
|
||||||
if (connectcount_ == 1) {
|
if (connectcount_ == 1) {
|
||||||
doc["event"] = FJSON("start");
|
doc["event"] = "start";
|
||||||
} else {
|
} else {
|
||||||
doc["event"] = FJSON("reconnect");
|
doc["event"] = "reconnect";
|
||||||
}
|
}
|
||||||
|
|
||||||
doc["version"] = EMSESP_APP_VERSION;
|
doc["version"] = EMSESP_APP_VERSION;
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
if (WiFi.status() == WL_CONNECTED) {
|
if (WiFi.status() == WL_CONNECTED) {
|
||||||
doc["connection"] = F("WiFi");
|
doc["connection"] = ("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();
|
||||||
@@ -567,7 +567,7 @@ void Mqtt::on_connect() {
|
|||||||
doc["IPv6 address"] = uuid::printable_to_string(WiFi.localIPv6());
|
doc["IPv6 address"] = uuid::printable_to_string(WiFi.localIPv6());
|
||||||
}
|
}
|
||||||
} else if (EMSESP::system_.ethernet_connected()) {
|
} else if (EMSESP::system_.ethernet_connected()) {
|
||||||
doc["connection"] = F("Ethernet");
|
doc["connection"] = ("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());
|
||||||
@@ -600,7 +600,7 @@ void Mqtt::on_connect() {
|
|||||||
// re-subscribe to all custom registered MQTT topics
|
// re-subscribe to all custom registered MQTT topics
|
||||||
resubscribe();
|
resubscribe();
|
||||||
|
|
||||||
publish_retain(F("status"), "online", true); // say we're alive to the Last Will topic, with retain on
|
publish_retain("status", "online", true); // say we're alive to the Last Will topic, with retain on
|
||||||
|
|
||||||
mqtt_publish_fails_ = 0; // reset fail count to 0
|
mqtt_publish_fails_ = 0; // reset fail count to 0
|
||||||
|
|
||||||
@@ -609,7 +609,7 @@ void Mqtt::on_connect() {
|
|||||||
LOG_INFO("Queue size: %d", mqtt_messages_.size());
|
LOG_INFO("Queue size: %d", mqtt_messages_.size());
|
||||||
for (const auto & message : mqtt_messages_) {
|
for (const auto & message : mqtt_messages_) {
|
||||||
auto content = message.content_;
|
auto content = message.content_;
|
||||||
LOG_INFO(F(" [%02d] (%d) topic=%s payload=%s"), message.id_, content->operation, content->topic.c_str(), content->payload.c_str());
|
LOG_INFO((" [%02d] (%d) topic=%s payload=%s"), message.id_, content->operation, content->topic.c_str(), content->payload.c_str());
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
@@ -620,21 +620,21 @@ 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"] = FJSON("ems-esp-system");
|
doc["uniq_id"] = "ems-esp-system";
|
||||||
doc["~"] = mqtt_base_; // default ems-esp
|
doc["~"] = mqtt_base_; // default ems-esp
|
||||||
// doc["avty_t"] = FJSON("~/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"] = FJSON("~/heartbeat"); // store also as HA attributes
|
// doc["json_attr_t"] = "~/heartbeat"; // store also as HA attributes
|
||||||
doc["stat_t"] = FJSON("~/heartbeat");
|
doc["stat_t"] = "~/heartbeat";
|
||||||
doc["object_id"] = FJSON("ems_esp_status");
|
doc["object_id"] = "ems_esp_status";
|
||||||
doc["name"] = FJSON("EMS-ESP status");
|
doc["name"] = "EMS-ESP status";
|
||||||
doc["ic"] = F_(icondevice);
|
doc["ic"] = F_(icondevice);
|
||||||
doc["val_tpl"] = FJSON("{{value_json['bus_status']}}");
|
doc["val_tpl"] = "{{value_json['bus_status']}}";
|
||||||
|
|
||||||
JsonObject dev = doc.createNestedObject("dev");
|
JsonObject dev = doc.createNestedObject("dev");
|
||||||
dev["name"] = F_(EMSESP); // "EMS-ESP"
|
dev["name"] = "EMS-ESP";
|
||||||
dev["sw"] = "v" + std::string(EMSESP_APP_VERSION);
|
dev["sw"] = "v" + std::string(EMSESP_APP_VERSION);
|
||||||
dev["mf"] = FJSON("proddy");
|
dev["mf"] = "proddy";
|
||||||
dev["mdl"] = F_(EMSESP); // "EMS-ESP"
|
dev["mdl"] = "EMS-ESP";
|
||||||
JsonArray ids = dev.createNestedArray("ids");
|
JsonArray ids = dev.createNestedArray("ids");
|
||||||
ids.add("ems-esp");
|
ids.add("ems-esp");
|
||||||
|
|
||||||
@@ -644,19 +644,20 @@ void Mqtt::ha_status() {
|
|||||||
|
|
||||||
// create the sensors - must match the MQTT payload keys
|
// create the sensors - must match the MQTT payload keys
|
||||||
if (!EMSESP::system_.ethernet_connected()) {
|
if (!EMSESP::system_.ethernet_connected()) {
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("WiFi RSSI"), F("rssi"), DeviceValueUOM::DBM);
|
publish_system_ha_sensor_config(DeviceValueType::INT, ("WiFi RSSI"), ("rssi"), DeviceValueUOM::DBM);
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("WiFi strength"), F("wifistrength"), DeviceValueUOM::PERCENT);
|
publish_system_ha_sensor_config(DeviceValueType::INT, ("WiFi strength"), ("wifistrength"), DeviceValueUOM::PERCENT);
|
||||||
}
|
}
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("Uptime"), F("uptime"), DeviceValueUOM::NONE);
|
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("Uptime (sec)"), F("uptime_sec"), DeviceValueUOM::SECONDS);
|
publish_system_ha_sensor_config(DeviceValueType::INT, ("Uptime"), ("uptime"), DeviceValueUOM::NONE);
|
||||||
publish_system_ha_sensor_config(DeviceValueType::BOOL, F("NTP status"), F("ntp_status"), DeviceValueUOM::NONE);
|
publish_system_ha_sensor_config(DeviceValueType::INT, ("Uptime (sec)"), ("uptime_sec"), DeviceValueUOM::SECONDS);
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("Free memory"), F("freemem"), DeviceValueUOM::KB);
|
publish_system_ha_sensor_config(DeviceValueType::BOOL, ("NTP status"), ("ntp_status"), DeviceValueUOM::NONE);
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("MQTT fails"), F("mqttfails"), DeviceValueUOM::NONE);
|
publish_system_ha_sensor_config(DeviceValueType::INT, ("Free memory"), ("freemem"), DeviceValueUOM::KB);
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("Rx received"), F("rxreceived"), DeviceValueUOM::NONE);
|
publish_system_ha_sensor_config(DeviceValueType::INT, ("MQTT fails"), ("mqttfails"), DeviceValueUOM::NONE);
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("Rx fails"), F("rxfails"), DeviceValueUOM::NONE);
|
publish_system_ha_sensor_config(DeviceValueType::INT, ("Rx received"), ("rxreceived"), DeviceValueUOM::NONE);
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("Tx reads"), F("txreads"), DeviceValueUOM::NONE);
|
publish_system_ha_sensor_config(DeviceValueType::INT, ("Rx fails"), ("rxfails"), DeviceValueUOM::NONE);
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("Tx writes"), F("txwrites"), DeviceValueUOM::NONE);
|
publish_system_ha_sensor_config(DeviceValueType::INT, ("Tx reads"), ("txreads"), DeviceValueUOM::NONE);
|
||||||
publish_system_ha_sensor_config(DeviceValueType::INT, F("Tx fails"), F("txfails"), DeviceValueUOM::NONE);
|
publish_system_ha_sensor_config(DeviceValueType::INT, ("Tx writes"), ("txwrites"), DeviceValueUOM::NONE);
|
||||||
|
publish_system_ha_sensor_config(DeviceValueType::INT, ("Tx fails"), ("txfails"), DeviceValueUOM::NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add sub or pub task to the queue.
|
// add sub or pub task to the queue.
|
||||||
@@ -686,7 +687,7 @@ std::shared_ptr<const MqttMessage> Mqtt::queue_message(const uint8_t operation,
|
|||||||
// if the queue is full, make room but removing the last one
|
// if the queue is full, make room but removing the last one
|
||||||
if (mqtt_messages_.size() >= MAX_MQTT_MESSAGES) {
|
if (mqtt_messages_.size() >= MAX_MQTT_MESSAGES) {
|
||||||
mqtt_messages_.pop_front();
|
mqtt_messages_.pop_front();
|
||||||
LOG_WARNING(F("Queue overflow, removing one message"));
|
LOG_WARNING("Queue overflow, removing one message");
|
||||||
mqtt_publish_fails_++;
|
mqtt_publish_fails_++;
|
||||||
}
|
}
|
||||||
mqtt_messages_.emplace_back(mqtt_message_id_++, std::move(message));
|
mqtt_messages_.emplace_back(mqtt_message_id_++, std::move(message));
|
||||||
@@ -718,17 +719,17 @@ void Mqtt::publish(const std::string & topic, const std::string & payload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MQTT Publish, using a user's retain flag - except for char * strings
|
// MQTT Publish, using a user's retain flag - except for char * strings
|
||||||
void Mqtt::publish(const __FlashStringHelper * topic, const char * payload) {
|
void Mqtt::publish(const char * topic, const char * payload) {
|
||||||
queue_publish_message(read_flash_string(topic), payload, mqtt_retain_);
|
queue_publish_message((topic), payload, mqtt_retain_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MQTT Publish, using a specific retain flag, topic is a flash string
|
// MQTT Publish, using a specific retain flag, topic is a flash string
|
||||||
void Mqtt::publish(const __FlashStringHelper * topic, const std::string & payload) {
|
void Mqtt::publish(const char * topic, const std::string & payload) {
|
||||||
queue_publish_message(read_flash_string(topic), payload, mqtt_retain_);
|
queue_publish_message((topic), payload, mqtt_retain_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mqtt::publish(const __FlashStringHelper * topic, const JsonObject & payload) {
|
void Mqtt::publish(const char * topic, const JsonObject & payload) {
|
||||||
publish(read_flash_string(topic), payload);
|
publish_retain(topic, payload, mqtt_retain_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// publish json doc, only if its not empty
|
// publish json doc, only if its not empty
|
||||||
@@ -737,12 +738,16 @@ void Mqtt::publish(const std::string & topic, const JsonObject & payload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MQTT Publish, using a specific retain flag, topic is a flash string, forcing retain flag
|
// MQTT Publish, using a specific retain flag, topic is a flash string, forcing retain flag
|
||||||
void Mqtt::publish_retain(const __FlashStringHelper * topic, const std::string & payload, bool retain) {
|
void Mqtt::publish_retain(const char * topic, const std::string & payload, bool retain) {
|
||||||
queue_publish_message(read_flash_string(topic), payload, retain);
|
queue_publish_message((topic), payload, retain);
|
||||||
}
|
}
|
||||||
|
|
||||||
// publish json doc, only if its not empty, using the retain flag
|
// publish json doc, only if its not empty, using the retain flag
|
||||||
void Mqtt::publish_retain(const std::string & topic, const JsonObject & payload, bool retain) {
|
void Mqtt::publish_retain(const std::string & topic, const JsonObject & payload, bool retain) {
|
||||||
|
publish_retain(topic.c_str(), payload, retain);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mqtt::publish_retain(const char * topic, const JsonObject & payload, bool retain) {
|
||||||
if (enabled() && payload.size()) {
|
if (enabled() && payload.size()) {
|
||||||
std::string payload_text;
|
std::string payload_text;
|
||||||
serializeJson(payload, payload_text); // convert json to string
|
serializeJson(payload, payload_text); // convert json to string
|
||||||
@@ -750,30 +755,22 @@ void Mqtt::publish_retain(const std::string & topic, const JsonObject & payload,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mqtt::publish_retain(const __FlashStringHelper * topic, const JsonObject & payload, bool retain) {
|
|
||||||
publish_retain(read_flash_string(topic), payload, retain);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mqtt::publish_ha(const __FlashStringHelper * topic, const JsonObject & payload) {
|
|
||||||
publish_ha(read_flash_string(topic), payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
// publish empty payload to remove the topic
|
// publish empty payload to remove the topic
|
||||||
void Mqtt::publish_ha(const std::string & topic) {
|
void Mqtt::publish_ha(const char * topic) {
|
||||||
if (!enabled()) {
|
if (!enabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string fulltopic = Mqtt::discovery_prefix() + topic;
|
std::string fulltopic = Mqtt::discovery_prefix() + topic;
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
LOG_DEBUG(F("[DEBUG] Publishing empty HA topic=%s"), fulltopic.c_str());
|
LOG_DEBUG("[DEBUG] Publishing empty HA topic=%s", fulltopic.c_str());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
queue_publish_message(fulltopic, "", true); // publish with retain to remove from broker
|
queue_publish_message(fulltopic, "", true); // publish with retain to remove from broker
|
||||||
}
|
}
|
||||||
|
|
||||||
// publish a Home Assistant config topic and payload, with retain flag off.
|
// publish a Home Assistant config topic and payload, with retain flag off.
|
||||||
void Mqtt::publish_ha(const std::string & topic, const JsonObject & payload) {
|
void Mqtt::publish_ha(const char * topic, const JsonObject & payload) {
|
||||||
if (!enabled()) {
|
if (!enabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -784,9 +781,9 @@ void Mqtt::publish_ha(const std::string & topic, const JsonObject & payload) {
|
|||||||
|
|
||||||
std::string fulltopic = Mqtt::discovery_prefix() + topic;
|
std::string fulltopic = Mqtt::discovery_prefix() + topic;
|
||||||
#if defined(EMSESP_STANDALONE)
|
#if defined(EMSESP_STANDALONE)
|
||||||
LOG_DEBUG(F("Publishing HA topic=%s, payload=%s"), fulltopic.c_str(), payload_text.c_str());
|
LOG_DEBUG("Publishing HA topic=%s, payload=%s", fulltopic.c_str(), payload_text.c_str());
|
||||||
#elif defined(EMSESP_DEBUG)
|
#elif defined(EMSESP_DEBUG)
|
||||||
LOG_DEBUG(F("[debug] Publishing HA topic=%s, payload=%s"), fulltopic.c_str(), payload_text.c_str());
|
LOG_DEBUG("[debug] Publishing HA topic=%s, payload=%s", fulltopic.c_str(), payload_text.c_str());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// queue messages if the MQTT connection is not yet established. to ensure we don't miss messages
|
// queue messages if the MQTT connection is not yet established. to ensure we don't miss messages
|
||||||
@@ -815,7 +812,7 @@ void Mqtt::process_queue() {
|
|||||||
// it will have a real packet ID
|
// it will have a real packet ID
|
||||||
if (mqtt_message.packet_id_ > 0) {
|
if (mqtt_message.packet_id_ > 0) {
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
LOG_DEBUG(F("[DEBUG] Waiting for QOS-ACK"));
|
LOG_DEBUG("[DEBUG] Waiting for QOS-ACK");
|
||||||
#endif
|
#endif
|
||||||
// if we don't get the ack within 10 minutes, republish with new packet_id
|
// if we don't get the ack within 10 minutes, republish with new packet_id
|
||||||
if (uuid::get_uptime_sec() - last_publish_queue_ < 600) {
|
if (uuid::get_uptime_sec() - last_publish_queue_ < 600) {
|
||||||
@@ -826,13 +823,13 @@ void Mqtt::process_queue() {
|
|||||||
|
|
||||||
// if we're subscribing...
|
// if we're subscribing...
|
||||||
if (message->operation == Operation::SUBSCRIBE) {
|
if (message->operation == Operation::SUBSCRIBE) {
|
||||||
LOG_DEBUG(F("Subscribing to topic '%s'"), topic);
|
LOG_DEBUG("Subscribing to topic '%s'", topic);
|
||||||
uint16_t packet_id = mqttClient_->subscribe(topic, mqtt_qos_);
|
uint16_t packet_id = mqttClient_->subscribe(topic, mqtt_qos_);
|
||||||
if (!packet_id) {
|
if (!packet_id) {
|
||||||
if (++mqtt_messages_.front().retry_count_ < MQTT_PUBLISH_MAX_RETRY) {
|
if (++mqtt_messages_.front().retry_count_ < MQTT_PUBLISH_MAX_RETRY) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG_ERROR(F("Error subscribing to topic '%s'"), topic);
|
LOG_ERROR("Error subscribing to topic '%s'", topic);
|
||||||
mqtt_publish_fails_++; // increment failure counter
|
mqtt_publish_fails_++; // increment failure counter
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -843,13 +840,13 @@ void Mqtt::process_queue() {
|
|||||||
|
|
||||||
// if we're unsubscribing...
|
// if we're unsubscribing...
|
||||||
if (message->operation == Operation::UNSUBSCRIBE) {
|
if (message->operation == Operation::UNSUBSCRIBE) {
|
||||||
LOG_DEBUG(F("Subscribing to topic '%s'"), topic);
|
LOG_DEBUG("Subscribing to topic '%s'", topic);
|
||||||
uint16_t packet_id = mqttClient_->unsubscribe(topic);
|
uint16_t packet_id = mqttClient_->unsubscribe(topic);
|
||||||
if (!packet_id) {
|
if (!packet_id) {
|
||||||
if (++mqtt_messages_.front().retry_count_ < MQTT_PUBLISH_MAX_RETRY) {
|
if (++mqtt_messages_.front().retry_count_ < MQTT_PUBLISH_MAX_RETRY) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG_ERROR(F("Error unsubscribing to topic '%s'"), topic);
|
LOG_ERROR("Error unsubscribing to topic '%s'", topic);
|
||||||
mqtt_publish_fails_++; // increment failure counter
|
mqtt_publish_fails_++; // increment failure counter
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -860,7 +857,7 @@ void Mqtt::process_queue() {
|
|||||||
|
|
||||||
// else try and publish it
|
// else try and publish it
|
||||||
uint16_t packet_id = mqttClient_->publish(topic, mqtt_qos_, message->retain, message->payload.c_str(), message->payload.size(), false, mqtt_message.id_);
|
uint16_t packet_id = mqttClient_->publish(topic, mqtt_qos_, message->retain, message->payload.c_str(), message->payload.size(), false, mqtt_message.id_);
|
||||||
LOG_DEBUG(F("Publishing topic %s (#%02d, retain=%d, retry=%d, size=%d, pid=%d)"),
|
LOG_DEBUG(("Publishing topic %s (#%02d, retain=%d, retry=%d, size=%d, pid=%d)"),
|
||||||
topic,
|
topic,
|
||||||
mqtt_message.id_,
|
mqtt_message.id_,
|
||||||
message->retain,
|
message->retain,
|
||||||
@@ -871,14 +868,14 @@ void Mqtt::process_queue() {
|
|||||||
if (packet_id == 0) {
|
if (packet_id == 0) {
|
||||||
// it failed. if we retried n times, give up. remove from queue
|
// it failed. if we retried n times, give up. remove from queue
|
||||||
if (mqtt_message.retry_count_ == (MQTT_PUBLISH_MAX_RETRY - 1)) {
|
if (mqtt_message.retry_count_ == (MQTT_PUBLISH_MAX_RETRY - 1)) {
|
||||||
LOG_ERROR(F("Failed to publish to %s after %d attempts"), topic, mqtt_message.retry_count_ + 1);
|
LOG_ERROR("Failed to publish to %s after %d attempts", topic, mqtt_message.retry_count_ + 1);
|
||||||
mqtt_publish_fails_++; // increment failure counter
|
mqtt_publish_fails_++; // increment failure counter
|
||||||
mqtt_messages_.pop_front(); // delete
|
mqtt_messages_.pop_front(); // delete
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// update the record
|
// update the record
|
||||||
mqtt_messages_.front().retry_count_++;
|
mqtt_messages_.front().retry_count_++;
|
||||||
LOG_DEBUG(F("Failed to publish to %s. Trying again, #%d"), topic, mqtt_message.retry_count_ + 1);
|
LOG_DEBUG("Failed to publish to %s. Trying again, #%d", topic, mqtt_message.retry_count_ + 1);
|
||||||
return; // leave on queue for next time so it gets republished
|
return; // leave on queue for next time so it gets republished
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -888,7 +885,7 @@ void Mqtt::process_queue() {
|
|||||||
if (mqtt_qos_ != 0) {
|
if (mqtt_qos_ != 0) {
|
||||||
mqtt_messages_.front().packet_id_ = packet_id;
|
mqtt_messages_.front().packet_id_ = packet_id;
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
LOG_DEBUG(F("[DEBUG] Setting packetID for ACK to %d"), packet_id);
|
LOG_DEBUG("[DEBUG] Setting packetID for ACK to %d", packet_id);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -902,23 +899,24 @@ void Mqtt::publish_ha_sensor_config(DeviceValue & dv, const std::string & model,
|
|||||||
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> dev_json;
|
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> dev_json;
|
||||||
|
|
||||||
// always create the ids
|
// always create the ids
|
||||||
JsonArray ids = dev_json.createNestedArray("ids");
|
JsonArray ids = dev_json.createNestedArray("ids");
|
||||||
char ha_device[40];
|
char ha_device[40];
|
||||||
std::string device_type_name = EMSdevice::device_type_2_device_name(dv.device_type);
|
auto device_type_name = EMSdevice::device_type_2_device_name(dv.device_type);
|
||||||
snprintf(ha_device, sizeof(ha_device), "ems-esp-%s", device_type_name.c_str());
|
snprintf(ha_device, sizeof(ha_device), "ems-esp-%s", device_type_name);
|
||||||
ids.add(ha_device);
|
ids.add(ha_device);
|
||||||
|
|
||||||
if (create_device_config) {
|
if (create_device_config) {
|
||||||
device_type_name[0] = toupper(device_type_name[0]); // capitalize
|
auto cap_name = strdup(device_type_name);
|
||||||
dev_json["name"] = "EMS-ESP " + device_type_name;
|
cap_name[0] = toupper(cap_name[0]); // capitalize
|
||||||
|
dev_json["name"] = std::string("EMS-ESP ") + cap_name;
|
||||||
dev_json["mf"] = brand;
|
dev_json["mf"] = brand;
|
||||||
dev_json["mdl"] = model;
|
dev_json["mdl"] = model;
|
||||||
dev_json["via_device"] = "ems-esp";
|
dev_json["via_device"] = "ems-esp";
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate the min and max
|
// calculate the min and max
|
||||||
int16_t dv_set_min;
|
int16_t dv_set_min;
|
||||||
int16_t dv_set_max;
|
uint16_t dv_set_max;
|
||||||
(void)dv.get_min_max(dv_set_min, dv_set_max);
|
(void)dv.get_min_max(dv_set_min, dv_set_max);
|
||||||
|
|
||||||
// determine if we're creating the command topics which we use special HA configs
|
// determine if we're creating the command topics which we use special HA configs
|
||||||
@@ -927,8 +925,8 @@ 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(),
|
dv.get_fullname().c_str(),
|
||||||
dv.fullname[0],
|
(dv.fullname ? dv.fullname[0] : nullptr), // EN name
|
||||||
dv.device_type,
|
dv.device_type,
|
||||||
dv.short_name,
|
dv.short_name,
|
||||||
dv.uom,
|
dv.uom,
|
||||||
@@ -942,50 +940,47 @@ void Mqtt::publish_ha_sensor_config(DeviceValue & dv, const std::string & model,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// publish HA sensor for System using the heartbeat tag
|
// publish HA sensor for System using the heartbeat tag
|
||||||
void Mqtt::publish_system_ha_sensor_config(uint8_t type, const __FlashStringHelper * name, const __FlashStringHelper * entity, const uint8_t uom) {
|
void Mqtt::publish_system_ha_sensor_config(uint8_t type, const char * name, const char * entity, const uint8_t uom) {
|
||||||
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
||||||
JsonObject dev_json = doc.createNestedObject("dev");
|
JsonObject dev_json = doc.createNestedObject("dev");
|
||||||
|
|
||||||
JsonArray ids = dev_json.createNestedArray("ids");
|
JsonArray ids = dev_json.createNestedArray("ids");
|
||||||
ids.add("ems-esp");
|
ids.add("ems-esp");
|
||||||
|
|
||||||
auto fullname = read_flash_string(name);
|
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, fullname, name, EMSdevice::DeviceType::SYSTEM, entity, uom, false, false, nullptr, 0, 0, 0, dev_json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MQTT discovery configs
|
// MQTT discovery configs
|
||||||
// entity must match the key/value pair in the *_data topic
|
// entity must match the key/value pair in the *_data topic
|
||||||
// note: some extra string copying done here, it looks messy but does help with heap fragmentation issues
|
// note: some extra string copying done here, it looks messy but does help with heap fragmentation issues
|
||||||
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 std::string & fullname, // fullname, already translated
|
const char * const fullname, // fullname, already translated
|
||||||
const __FlashStringHelper * const en_name,
|
const char * const en_name,
|
||||||
const uint8_t device_type, // EMSdevice::DeviceType
|
const uint8_t device_type, // EMSdevice::DeviceType
|
||||||
const __FlashStringHelper * 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)
|
||||||
const bool remove, // true if we want to remove this topic
|
const bool remove, // true if we want to remove this topic
|
||||||
const bool has_cmd,
|
const bool has_cmd,
|
||||||
const __FlashStringHelper * const ** options,
|
const char * const ** options,
|
||||||
uint8_t options_size,
|
uint8_t options_size,
|
||||||
const int16_t dv_set_min,
|
const int16_t dv_set_min,
|
||||||
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.empty() || en_name == nullptr) {
|
if (fullname == nullptr || en_name == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the device name
|
// create the device name
|
||||||
char device_name[50];
|
auto device_name = EMSdevice::device_type_2_device_name(device_type);
|
||||||
strlcpy(device_name, EMSdevice::device_type_2_device_name(device_type).c_str(), sizeof(device_name));
|
|
||||||
|
|
||||||
// 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 new_entity[50];
|
||||||
if (tag >= DeviceValueTAG::TAG_HC1) {
|
if (tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
snprintf(new_entity, sizeof(new_entity), "%s.%s", EMSdevice::tag_to_string(tag).c_str(), read_flash_string(entity).c_str());
|
snprintf(new_entity, sizeof(new_entity), "%s.%s", EMSdevice::tag_to_string(tag).c_str(), (entity));
|
||||||
} else {
|
} else {
|
||||||
snprintf(new_entity, sizeof(new_entity), "%s", read_flash_string(entity).c_str());
|
snprintf(new_entity, sizeof(new_entity), "%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, replacing all . with _ as not to break HA
|
||||||
@@ -1037,7 +1032,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type,
|
|||||||
// 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(F("Removing HA config for %s"), uniq);
|
LOG_DEBUG("Removing HA config for %s", uniq);
|
||||||
publish_ha(topic);
|
publish_ha(topic);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1107,7 +1102,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type,
|
|||||||
|
|
||||||
// friendly name = <tag> <name>
|
// friendly name = <tag> <name>
|
||||||
char ha_name[70];
|
char ha_name[70];
|
||||||
char * F_name = strdup(fullname.c_str());
|
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 (have_tag) {
|
||||||
snprintf(ha_name, sizeof(ha_name), "%s %s", EMSdevice::tag_to_string(tag).c_str(), F_name);
|
snprintf(ha_name, sizeof(ha_name), "%s %s", EMSdevice::tag_to_string(tag).c_str(), F_name);
|
||||||
@@ -1120,14 +1115,12 @@ void Mqtt::publish_ha_sensor_config(uint8_t type,
|
|||||||
// entity id is generated from the name, see https://www.home-assistant.io/docs/mqtt/discovery/#use-object_id-to-influence-the-entity-id
|
// 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
|
// so we override it to make it unique using entity_id
|
||||||
// See https://github.com/emsesp/EMS-ESP32/issues/596
|
// See https://github.com/emsesp/EMS-ESP32/issues/596
|
||||||
// keep it compatible to v3.4, use english fullname, no prefix (basename prefix commmented out)
|
// keep it compatible to v3.4, use english fullname, no prefix (basename prefix commented out)
|
||||||
char object_id[130];
|
char object_id[130];
|
||||||
if (have_tag) {
|
if (have_tag) {
|
||||||
// snprintf(object_id, sizeof(object_id), "%s_%s_%s_%s", mqtt_basename_, device_name, EMSdevice::tag_to_string(tag).c_str(), read_flash_string(en_name).c_str());
|
snprintf(object_id, sizeof(object_id), "%s_%s_%s", device_name, EMSdevice::tag_to_string(tag).c_str(), en_name);
|
||||||
snprintf(object_id, sizeof(object_id), "%s_%s_%s", device_name, EMSdevice::tag_to_string(tag).c_str(), read_flash_string(en_name).c_str());
|
|
||||||
} else {
|
} else {
|
||||||
// snprintf(object_id, sizeof(object_id), "%s_%s_%s", mqtt_basename_, device_name, read_flash_string(en_name).c_str());
|
snprintf(object_id, sizeof(object_id), "%s_%s", device_name, en_name);
|
||||||
snprintf(object_id, sizeof(object_id), "%s_%s", device_name, read_flash_string(en_name).c_str());
|
|
||||||
}
|
}
|
||||||
doc["object_id"] = object_id;
|
doc["object_id"] = object_id;
|
||||||
|
|
||||||
@@ -1137,7 +1130,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type,
|
|||||||
if (is_nested()) {
|
if (is_nested()) {
|
||||||
snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", new_entity);
|
snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", new_entity);
|
||||||
} else {
|
} else {
|
||||||
snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", read_flash_string(entity).c_str());
|
snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", entity);
|
||||||
}
|
}
|
||||||
doc["val_tpl"] = val_tpl;
|
doc["val_tpl"] = val_tpl;
|
||||||
|
|
||||||
@@ -1147,9 +1140,9 @@ void Mqtt::publish_ha_sensor_config(uint8_t type,
|
|||||||
// and has no unit of measure or icon
|
// and has no unit of measure or icon
|
||||||
if (type == DeviceValueType::BOOL) {
|
if (type == DeviceValueType::BOOL) {
|
||||||
char result[10];
|
char result[10];
|
||||||
doc[F("payload_on")] = Helpers::render_boolean(result, true);
|
doc[("payload_on")] = Helpers::render_boolean(result, true);
|
||||||
doc[F("payload_off")] = Helpers::render_boolean(result, false);
|
doc[("payload_off")] = Helpers::render_boolean(result, false);
|
||||||
doc[sc_ha] = F_(measurement);
|
doc[sc_ha] = F_(measurement);
|
||||||
} else {
|
} else {
|
||||||
// always set the uom
|
// always set the uom
|
||||||
if (uom != DeviceValueUOM::NONE) {
|
if (uom != DeviceValueUOM::NONE) {
|
||||||
@@ -1169,11 +1162,11 @@ void Mqtt::publish_ha_sensor_config(uint8_t type,
|
|||||||
case DeviceValueUOM::DEGREES:
|
case DeviceValueUOM::DEGREES:
|
||||||
case DeviceValueUOM::DEGREES_R:
|
case DeviceValueUOM::DEGREES_R:
|
||||||
doc[sc_ha] = F_(measurement);
|
doc[sc_ha] = F_(measurement);
|
||||||
doc[dc_ha] = F("temperature"); // no icon needed
|
doc[dc_ha] = "temperature"; // no icon needed
|
||||||
break;
|
break;
|
||||||
case DeviceValueUOM::PERCENT:
|
case DeviceValueUOM::PERCENT:
|
||||||
doc[sc_ha] = F_(measurement);
|
doc[sc_ha] = F_(measurement);
|
||||||
doc[dc_ha] = F("power_factor"); // no icon needed
|
doc[dc_ha] = "power_factor"; // no icon needed
|
||||||
break;
|
break;
|
||||||
case DeviceValueUOM::SECONDS:
|
case DeviceValueUOM::SECONDS:
|
||||||
case DeviceValueUOM::MINUTES:
|
case DeviceValueUOM::MINUTES:
|
||||||
@@ -1198,11 +1191,11 @@ void Mqtt::publish_ha_sensor_config(uint8_t type,
|
|||||||
} else {
|
} else {
|
||||||
doc[sc_ha] = F_(measurement);
|
doc[sc_ha] = F_(measurement);
|
||||||
}
|
}
|
||||||
doc[dc_ha] = F("energy"); // no icon needed
|
doc[dc_ha] = "energy"; // no icon needed
|
||||||
break;
|
break;
|
||||||
case DeviceValueUOM::KWH:
|
case DeviceValueUOM::KWH:
|
||||||
doc[sc_ha] = F_(total_increasing);
|
doc[sc_ha] = F_(total_increasing);
|
||||||
doc[dc_ha] = F("energy"); // no icon needed
|
doc[dc_ha] = "energy"; // no icon needed
|
||||||
break;
|
break;
|
||||||
case DeviceValueUOM::UA:
|
case DeviceValueUOM::UA:
|
||||||
doc[ic_ha] = F_(iconua);
|
doc[ic_ha] = F_(iconua);
|
||||||
@@ -1210,16 +1203,16 @@ void Mqtt::publish_ha_sensor_config(uint8_t type,
|
|||||||
break;
|
break;
|
||||||
case DeviceValueUOM::BAR:
|
case DeviceValueUOM::BAR:
|
||||||
doc[sc_ha] = F_(measurement);
|
doc[sc_ha] = F_(measurement);
|
||||||
doc[dc_ha] = F("pressure");
|
doc[dc_ha] = "pressure";
|
||||||
break;
|
break;
|
||||||
case DeviceValueUOM::W:
|
case DeviceValueUOM::W:
|
||||||
case DeviceValueUOM::KW:
|
case DeviceValueUOM::KW:
|
||||||
doc[sc_ha] = F_(measurement);
|
doc[sc_ha] = F_(measurement);
|
||||||
doc[dc_ha] = F("power");
|
doc[dc_ha] = "power";
|
||||||
break;
|
break;
|
||||||
case DeviceValueUOM::DBM:
|
case DeviceValueUOM::DBM:
|
||||||
doc[sc_ha] = F_(measurement);
|
doc[sc_ha] = F_(measurement);
|
||||||
doc[dc_ha] = F("signal_strength");
|
doc[dc_ha] = "signal_strength";
|
||||||
break;
|
break;
|
||||||
case DeviceValueUOM::NONE:
|
case DeviceValueUOM::NONE:
|
||||||
// for device entities which have numerical values, with no UOM
|
// for device entities which have numerical values, with no UOM
|
||||||
@@ -1248,7 +1241,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type,
|
|||||||
publish_ha(topic, doc.as<JsonObject>());
|
publish_ha(topic, doc.as<JsonObject>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mqtt::publish_ha_climate_config(uint8_t tag, bool has_roomtemp, bool remove) {
|
void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp, const bool remove, const int16_t min, const uint16_t max) {
|
||||||
uint8_t hc_num = tag - DeviceValueTAG::TAG_HC1 + 1;
|
uint8_t hc_num = tag - DeviceValueTAG::TAG_HC1 + 1;
|
||||||
|
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
@@ -1321,8 +1314,8 @@ void Mqtt::publish_ha_climate_config(uint8_t tag, bool has_roomtemp, bool remove
|
|||||||
doc["curr_temp_tpl"] = currtemp_s;
|
doc["curr_temp_tpl"] = currtemp_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
doc["min_temp"] = Helpers::render_value(min_s, (uint32_t)5, 0, EMSESP::system_.fahrenheit() ? 2 : 0);
|
doc["min_temp"] = Helpers::render_value(min_s, min, 0, EMSESP::system_.fahrenheit() ? 2 : 0);
|
||||||
doc["max_temp"] = Helpers::render_value(max_s, (uint32_t)30, 0, EMSESP::system_.fahrenheit() ? 2 : 0);
|
doc["max_temp"] = Helpers::render_value(max_s, max, 0, EMSESP::system_.fahrenheit() ? 2 : 0);
|
||||||
doc["temp_step"] = "0.5";
|
doc["temp_step"] = "0.5";
|
||||||
|
|
||||||
// the HA climate component only responds to auto, heat and off
|
// the HA climate component only responds to auto, heat and off
|
||||||
@@ -1348,11 +1341,13 @@ std::string Mqtt::tag_to_topic(uint8_t device_type, uint8_t tag) {
|
|||||||
return EMSdevice::tag_to_mqtt(tag);
|
return EMSdevice::tag_to_mqtt(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string topic = EMSdevice::device_type_2_device_name(device_type);
|
||||||
|
|
||||||
// if there is a tag add it
|
// if there is a tag add it
|
||||||
if (!EMSdevice::tag_to_mqtt(tag).empty() && ((tag == DeviceValueTAG::TAG_BOILER_DATA_WW) || (!is_nested() && tag >= DeviceValueTAG::TAG_HC1))) {
|
if (!EMSdevice::tag_to_mqtt(tag).empty() && ((tag == DeviceValueTAG::TAG_BOILER_DATA_WW) || (!is_nested() && tag >= DeviceValueTAG::TAG_HC1))) {
|
||||||
return EMSdevice::device_type_2_device_name(device_type) + "_data_" + EMSdevice::tag_to_mqtt(tag);
|
return topic + "_data_" + EMSdevice::tag_to_mqtt(tag);
|
||||||
} else {
|
} else {
|
||||||
return EMSdevice::device_type_2_device_name(device_type) + "_data";
|
return topic + "_data";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
59
src/mqtt.h
59
src/mqtt.h
@@ -79,36 +79,35 @@ class Mqtt {
|
|||||||
static void resubscribe();
|
static void resubscribe();
|
||||||
|
|
||||||
static void publish(const std::string & topic, const std::string & payload);
|
static void publish(const std::string & topic, const std::string & payload);
|
||||||
static void publish(const __FlashStringHelper * topic, const char * payload);
|
static void publish(const char * topic, const char * payload);
|
||||||
static void publish(const std::string & topic, const JsonObject & payload);
|
static void publish(const std::string & topic, const JsonObject & payload);
|
||||||
static void publish(const __FlashStringHelper * topic, const JsonObject & payload);
|
static void publish(const char * topic, const JsonObject & payload);
|
||||||
static void publish(const __FlashStringHelper * topic, const std::string & payload);
|
static void publish(const char * topic, const std::string & payload);
|
||||||
static void publish_retain(const std::string & topic, const JsonObject & payload, bool retain);
|
static void publish_retain(const std::string & topic, const JsonObject & payload, bool retain);
|
||||||
static void publish_retain(const __FlashStringHelper * topic, const std::string & payload, bool retain);
|
static void publish_retain(const char * topic, const std::string & payload, bool retain);
|
||||||
static void publish_retain(const __FlashStringHelper * topic, const JsonObject & payload, bool retain);
|
static void publish_retain(const char * topic, const JsonObject & payload, bool retain);
|
||||||
static void publish_ha(const std::string & topic, const JsonObject & payload);
|
static void publish_ha(const char * topic, const JsonObject & payload);
|
||||||
static void publish_ha(const __FlashStringHelper * topic, const JsonObject & payload);
|
static void publish_ha(const char * topic);
|
||||||
static void publish_ha(const std::string & topic);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
publish_ha_sensor_config(DeviceValue & dv, const std::string & model, const std::string & brand, const bool remove, const bool create_device_config = false);
|
publish_ha_sensor_config(DeviceValue & dv, const std::string & model, const std::string & brand, const bool remove, const bool create_device_config = false);
|
||||||
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 std::string & fullname,
|
const char * const fullname,
|
||||||
const __FlashStringHelper * const en_name,
|
const char * const en_name,
|
||||||
const uint8_t device_type,
|
const uint8_t device_type,
|
||||||
const __FlashStringHelper * const entity,
|
const char * const entity,
|
||||||
const uint8_t uom,
|
const uint8_t uom,
|
||||||
const bool remove,
|
const bool remove,
|
||||||
const bool has_cmd,
|
const bool has_cmd,
|
||||||
const __FlashStringHelper * const ** options,
|
const char * const ** options,
|
||||||
uint8_t options_size,
|
uint8_t options_size,
|
||||||
const int16_t dv_set_min,
|
const int16_t dv_set_min,
|
||||||
const int16_t dv_set_max,
|
const int16_t dv_set_max,
|
||||||
const JsonObject & dev_json);
|
const JsonObject & dev_json);
|
||||||
|
|
||||||
static void publish_system_ha_sensor_config(uint8_t type, const __FlashStringHelper * name, const __FlashStringHelper * entity, const uint8_t uom);
|
static void publish_system_ha_sensor_config(uint8_t type, const char * name, const char * entity, const uint8_t uom);
|
||||||
static void publish_ha_climate_config(uint8_t tag, bool has_roomtemp, bool remove = false);
|
static void publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp, const bool remove = false, const int16_t min = 5, const uint16_t max = 30);
|
||||||
|
|
||||||
static void show_topic_handlers(uuid::console::Shell & shell, const uint8_t device_type);
|
static void show_topic_handlers(uuid::console::Shell & shell, const uint8_t device_type);
|
||||||
static void show_mqtt(uuid::console::Shell & shell);
|
static void show_mqtt(uuid::console::Shell & shell);
|
||||||
@@ -167,6 +166,14 @@ class Mqtt {
|
|||||||
return mqtt_publish_fails_;
|
return mqtt_publish_fails_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t publish_queued() {
|
||||||
|
return mqtt_messages_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t connect_count() {
|
||||||
|
return connectcount_;
|
||||||
|
}
|
||||||
|
|
||||||
static void reset_mqtt();
|
static void reset_mqtt();
|
||||||
|
|
||||||
static bool is_nested() {
|
static bool is_nested() {
|
||||||
@@ -178,7 +185,7 @@ class Mqtt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool publish_single() {
|
static bool publish_single() {
|
||||||
return publish_single_;
|
return mqtt_enabled_ && publish_single_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool publish_single2cmd() {
|
static bool publish_single2cmd() {
|
||||||
@@ -190,7 +197,7 @@ class Mqtt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool ha_enabled() {
|
static bool ha_enabled() {
|
||||||
return ha_enabled_;
|
return mqtt_enabled_ && ha_enabled_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ha_enabled(bool ha_enabled) {
|
static void ha_enabled(bool ha_enabled) {
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ void Shower::loop() {
|
|||||||
// first check to see if hot water has been on long enough to be recognized as a Shower/Bath
|
// first check to see if hot water has been on long enough to be recognized as a Shower/Bath
|
||||||
if (!shower_state_ && (time_now - timer_start_) > SHOWER_MIN_DURATION) {
|
if (!shower_state_ && (time_now - timer_start_) > SHOWER_MIN_DURATION) {
|
||||||
set_shower_state(true);
|
set_shower_state(true);
|
||||||
LOG_DEBUG(F("[Shower] hot water still running, starting shower timer"));
|
LOG_DEBUG("[Shower] hot water still running, starting shower timer");
|
||||||
}
|
}
|
||||||
// check if the shower has been on too long
|
// check if the shower has been on too long
|
||||||
else if ((time_now - timer_start_) > shower_alert_trigger_) {
|
else if ((time_now - timer_start_) > shower_alert_trigger_) {
|
||||||
@@ -82,8 +82,8 @@ void Shower::loop() {
|
|||||||
char s[50];
|
char s[50];
|
||||||
snprintf(s, 50, "%d minutes and %d seconds", (uint8_t)(duration_ / 60000), (uint8_t)((duration_ / 1000) % 60));
|
snprintf(s, 50, "%d minutes and %d seconds", (uint8_t)(duration_ / 60000), (uint8_t)((duration_ / 1000) % 60));
|
||||||
doc["duration"] = s;
|
doc["duration"] = s;
|
||||||
Mqtt::publish(F("shower_data"), doc.as<JsonObject>());
|
Mqtt::publish("shower_data", doc.as<JsonObject>());
|
||||||
LOG_DEBUG(F("[Shower] finished with duration %d"), duration_);
|
LOG_DEBUG("[Shower] finished with duration %d", duration_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ void Shower::loop() {
|
|||||||
// turn back on the hot water for the shower
|
// turn back on the hot water for the shower
|
||||||
void Shower::shower_alert_stop() {
|
void Shower::shower_alert_stop() {
|
||||||
if (doing_cold_shot_) {
|
if (doing_cold_shot_) {
|
||||||
LOG_DEBUG(F("Shower Alert stopped"));
|
LOG_DEBUG("Shower Alert stopped");
|
||||||
(void)Command::call(EMSdevice::DeviceType::BOILER, "wwtapactivated", "true");
|
(void)Command::call(EMSdevice::DeviceType::BOILER, "wwtapactivated", "true");
|
||||||
doing_cold_shot_ = false;
|
doing_cold_shot_ = false;
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,7 @@ void Shower::shower_alert_stop() {
|
|||||||
// turn off hot water to send a shot of cold
|
// turn off hot water to send a shot of cold
|
||||||
void Shower::shower_alert_start() {
|
void Shower::shower_alert_start() {
|
||||||
if (shower_alert_) {
|
if (shower_alert_) {
|
||||||
LOG_DEBUG(F("Shower Alert started"));
|
LOG_DEBUG("Shower Alert started");
|
||||||
(void)Command::call(EMSdevice::DeviceType::BOILER, "wwtapactivated", "false");
|
(void)Command::call(EMSdevice::DeviceType::BOILER, "wwtapactivated", "false");
|
||||||
doing_cold_shot_ = true;
|
doing_cold_shot_ = true;
|
||||||
alert_timer_start_ = uuid::get_uptime(); // timer starts now
|
alert_timer_start_ = uuid::get_uptime(); // timer starts now
|
||||||
@@ -144,22 +144,22 @@ void Shower::set_shower_state(bool state, bool force) {
|
|||||||
|
|
||||||
// always publish as a string
|
// always publish as a string
|
||||||
char s[7];
|
char s[7];
|
||||||
Mqtt::publish(F("shower_active"), Helpers::render_boolean(s, shower_state_)); // https://github.com/emsesp/EMS-ESP/issues/369
|
Mqtt::publish("shower_active", Helpers::render_boolean(s, shower_state_)); // https://github.com/emsesp/EMS-ESP/issues/369
|
||||||
|
|
||||||
// send out HA MQTT Discovery config topic
|
// send out HA MQTT Discovery config topic
|
||||||
if ((Mqtt::ha_enabled()) && (!ha_configdone_ || force)) {
|
if ((Mqtt::ha_enabled()) && (!ha_configdone_ || force)) {
|
||||||
ha_configdone_ = true;
|
ha_configdone_ = true;
|
||||||
|
|
||||||
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
||||||
doc["name"] = FJSON("Shower Active");
|
doc["name"] = "Shower Active";
|
||||||
doc["uniq_id"] = FJSON("shower_active");
|
doc["uniq_id"] = "shower_active";
|
||||||
doc["~"] = Mqtt::base();
|
doc["~"] = Mqtt::base();
|
||||||
doc["stat_t"] = FJSON("~/shower_active");
|
doc["stat_t"] = "~/shower_active";
|
||||||
|
|
||||||
// always render boolean as strings for HA
|
// always render boolean as strings for HA
|
||||||
char result[10];
|
char result[10];
|
||||||
doc[F("payload_on")] = Helpers::render_boolean(result, true);
|
doc[("payload_on")] = Helpers::render_boolean(result, true);
|
||||||
doc[F("payload_off")] = Helpers::render_boolean(result, false);
|
doc[("payload_off")] = Helpers::render_boolean(result, false);
|
||||||
|
|
||||||
JsonObject dev = doc.createNestedObject("dev");
|
JsonObject dev = doc.createNestedObject("dev");
|
||||||
JsonArray ids = dev.createNestedArray("ids");
|
JsonArray ids = dev.createNestedArray("ids");
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user