mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
Render values in Web natively #70
This commit is contained in:
@@ -9,12 +9,13 @@
|
||||
## Fixed
|
||||
|
||||
- HA thermostat mode was not in sync with actual mode [#66](https://github.com/emsesp/EMS-ESP32/issues/66)
|
||||
- Don't publish rssi if Wifi is disabled and ethernet is being used
|
||||
|
||||
## Changed
|
||||
|
||||
|
||||
- `info` command always shows full names in API. For short names query the device or name directly, e.g. `http://ems-esp/api/boiler`
|
||||
- free memory is shown in kilobytes
|
||||
- boiler's warm water entities have ww added to the Home Assistant entity name [#67](https://github.com/emsesp/EMS-ESP32/issues/67)
|
||||
- improved layout and rendering of device values in the WebUI, also the edit value screen
|
||||
|
||||
## Removed
|
||||
|
||||
211
interface/package-lock.json
generated
211
interface/package-lock.json
generated
@@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.11.4",
|
||||
"@material-ui/icons": "^4.11.2",
|
||||
"@msgpack/msgpack": "^2.7.0",
|
||||
"@types/lodash": "^4.14.168",
|
||||
"@types/node": "^15.0.1",
|
||||
"@types/react": "^17.0.4",
|
||||
@@ -2175,6 +2176,14 @@
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@msgpack/msgpack": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.7.0.tgz",
|
||||
"integrity": "sha512-mlRYq9FSsOd4m+3wZWatemn3hGFZPWNJ4JQOdrir4rrMK2PyIk26idKBoUWrqF3HJJHl+5GpRU+M0wEruJwecg==",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
|
||||
@@ -4578,21 +4587,25 @@
|
||||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.16.3",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz",
|
||||
"integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==",
|
||||
"version": "4.16.6",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz",
|
||||
"integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==",
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001181",
|
||||
"colorette": "^1.2.1",
|
||||
"electron-to-chromium": "^1.3.649",
|
||||
"caniuse-lite": "^1.0.30001219",
|
||||
"colorette": "^1.2.2",
|
||||
"electron-to-chromium": "^1.3.723",
|
||||
"escalade": "^3.1.1",
|
||||
"node-releases": "^1.1.70"
|
||||
"node-releases": "^1.1.71"
|
||||
},
|
||||
"bin": {
|
||||
"browserslist": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/browserslist"
|
||||
}
|
||||
},
|
||||
"node_modules/bser": {
|
||||
@@ -4835,9 +4848,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001208",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001208.tgz",
|
||||
"integrity": "sha512-OE5UE4+nBOro8Dyvv0lfx+SRtfVIOM9uhKqFmJeUbGriqhhStgp1A0OyBpgy3OUF8AhYCT+PVwPC1gMl2ZcQMA=="
|
||||
"version": "1.0.30001235",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001235.tgz",
|
||||
"integrity": "sha512-zWEwIVqnzPkSAXOUlQnPW2oKoYb2aLQ4Q5ejdjBcnH63rfypaW34CxaeBn1VMya2XaEU3P/R2qHpWyj+l0BT1A==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/browserslist"
|
||||
}
|
||||
},
|
||||
"node_modules/capture-exit": {
|
||||
"version": "2.0.0",
|
||||
@@ -6613,9 +6630,9 @@
|
||||
"integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0="
|
||||
},
|
||||
"node_modules/dns-packet": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
|
||||
"integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz",
|
||||
"integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==",
|
||||
"dependencies": {
|
||||
"ip": "^1.1.0",
|
||||
"safe-buffer": "^5.0.1"
|
||||
@@ -6837,9 +6854,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.3.712",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.712.tgz",
|
||||
"integrity": "sha512-3kRVibBeCM4vsgoHHGKHmPocLqtFAGTrebXxxtgKs87hNUzXrX2NuS3jnBys7IozCnw7viQlozxKkmty2KNfrw=="
|
||||
"version": "1.3.749",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.749.tgz",
|
||||
"integrity": "sha512-F+v2zxZgw/fMwPz/VUGIggG4ZndDsYy0vlpthi3tjmDZlcfbhN5mYW0evXUsBr2sUtuDANFtle410A9u/sd/4A=="
|
||||
},
|
||||
"node_modules/elliptic": {
|
||||
"version": "6.5.4",
|
||||
@@ -13248,9 +13265,9 @@
|
||||
"integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE="
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.1.22",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz",
|
||||
"integrity": "sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ==",
|
||||
"version": "3.1.23",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
|
||||
"integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==",
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
@@ -14860,11 +14877,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss-initial": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.2.tgz",
|
||||
"integrity": "sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==",
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.4.tgz",
|
||||
"integrity": "sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg==",
|
||||
"dependencies": {
|
||||
"lodash.template": "^4.5.0",
|
||||
"postcss": "^7.0.2"
|
||||
}
|
||||
},
|
||||
@@ -15566,24 +15582,20 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss-safe-parser/node_modules/postcss": {
|
||||
"version": "8.2.9",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.9.tgz",
|
||||
"integrity": "sha512-b+TmuIL4jGtCHtoLi+G/PisuIl9avxs8IZMSmlABRwNz5RLUUACrC+ws81dcomz1nRezm5YPdXiMEzBEKgYn+Q==",
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.0.tgz",
|
||||
"integrity": "sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ==",
|
||||
"dependencies": {
|
||||
"colorette": "^1.2.2",
|
||||
"nanoid": "^3.1.22",
|
||||
"source-map": "^0.6.1"
|
||||
"nanoid": "^3.1.23",
|
||||
"source-map-js": "^0.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss-safe-parser/node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss-selector-matches": {
|
||||
@@ -16948,9 +16960,9 @@
|
||||
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
|
||||
},
|
||||
"node_modules/resolve-url-loader": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.2.tgz",
|
||||
"integrity": "sha512-QEb4A76c8Mi7I3xNKXlRKQSlLBwjUV/ULFMP+G7n3/7tJZ8MG5wsZ3ucxP1Jz8Vevn6fnJsxDx9cIls+utGzPQ==",
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.3.tgz",
|
||||
"integrity": "sha512-WbDSNFiKPPLem1ln+EVTE+bFUBdTTytfQZWbmghroaFNFaAVmGq0Saqw6F/306CwgPXsGwXVxbODE+3xAo/YbA==",
|
||||
"dependencies": {
|
||||
"adjust-sourcemap-loader": "3.0.0",
|
||||
"camelcase": "5.3.1",
|
||||
@@ -17966,6 +17978,14 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz",
|
||||
"integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-resolve": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
|
||||
@@ -20710,9 +20730,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-dev-server/node_modules/ws": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
|
||||
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
|
||||
"integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
|
||||
"dependencies": {
|
||||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
@@ -21489,11 +21509,23 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "7.4.4",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz",
|
||||
"integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==",
|
||||
"version": "7.4.6",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
|
||||
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xdg-basedir": {
|
||||
@@ -23497,6 +23529,11 @@
|
||||
"react-is": "^16.8.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"@msgpack/msgpack": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.7.0.tgz",
|
||||
"integrity": "sha512-mlRYq9FSsOd4m+3wZWatemn3hGFZPWNJ4JQOdrir4rrMK2PyIk26idKBoUWrqF3HJJHl+5GpRU+M0wEruJwecg=="
|
||||
},
|
||||
"@nodelib/fs.scandir": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
|
||||
@@ -25598,15 +25635,15 @@
|
||||
}
|
||||
},
|
||||
"browserslist": {
|
||||
"version": "4.16.3",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz",
|
||||
"integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==",
|
||||
"version": "4.16.6",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz",
|
||||
"integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==",
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30001181",
|
||||
"colorette": "^1.2.1",
|
||||
"electron-to-chromium": "^1.3.649",
|
||||
"caniuse-lite": "^1.0.30001219",
|
||||
"colorette": "^1.2.2",
|
||||
"electron-to-chromium": "^1.3.723",
|
||||
"escalade": "^3.1.1",
|
||||
"node-releases": "^1.1.70"
|
||||
"node-releases": "^1.1.71"
|
||||
}
|
||||
},
|
||||
"bser": {
|
||||
@@ -25812,9 +25849,9 @@
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001208",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001208.tgz",
|
||||
"integrity": "sha512-OE5UE4+nBOro8Dyvv0lfx+SRtfVIOM9uhKqFmJeUbGriqhhStgp1A0OyBpgy3OUF8AhYCT+PVwPC1gMl2ZcQMA=="
|
||||
"version": "1.0.30001235",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001235.tgz",
|
||||
"integrity": "sha512-zWEwIVqnzPkSAXOUlQnPW2oKoYb2aLQ4Q5ejdjBcnH63rfypaW34CxaeBn1VMya2XaEU3P/R2qHpWyj+l0BT1A=="
|
||||
},
|
||||
"capture-exit": {
|
||||
"version": "2.0.0",
|
||||
@@ -27268,9 +27305,9 @@
|
||||
"integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0="
|
||||
},
|
||||
"dns-packet": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
|
||||
"integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz",
|
||||
"integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==",
|
||||
"requires": {
|
||||
"ip": "^1.1.0",
|
||||
"safe-buffer": "^5.0.1"
|
||||
@@ -27477,9 +27514,9 @@
|
||||
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA=="
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.712",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.712.tgz",
|
||||
"integrity": "sha512-3kRVibBeCM4vsgoHHGKHmPocLqtFAGTrebXxxtgKs87hNUzXrX2NuS3jnBys7IozCnw7viQlozxKkmty2KNfrw=="
|
||||
"version": "1.3.749",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.749.tgz",
|
||||
"integrity": "sha512-F+v2zxZgw/fMwPz/VUGIggG4ZndDsYy0vlpthi3tjmDZlcfbhN5mYW0evXUsBr2sUtuDANFtle410A9u/sd/4A=="
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "6.5.4",
|
||||
@@ -32656,9 +32693,9 @@
|
||||
"integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE="
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.1.22",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz",
|
||||
"integrity": "sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ=="
|
||||
"version": "3.1.23",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
|
||||
"integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw=="
|
||||
},
|
||||
"nanomatch": {
|
||||
"version": "1.2.13",
|
||||
@@ -33963,11 +34000,10 @@
|
||||
}
|
||||
},
|
||||
"postcss-initial": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.2.tgz",
|
||||
"integrity": "sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==",
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.4.tgz",
|
||||
"integrity": "sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg==",
|
||||
"requires": {
|
||||
"lodash.template": "^4.5.0",
|
||||
"postcss": "^7.0.2"
|
||||
}
|
||||
},
|
||||
@@ -34569,19 +34605,14 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"postcss": {
|
||||
"version": "8.2.9",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.9.tgz",
|
||||
"integrity": "sha512-b+TmuIL4jGtCHtoLi+G/PisuIl9avxs8IZMSmlABRwNz5RLUUACrC+ws81dcomz1nRezm5YPdXiMEzBEKgYn+Q==",
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.0.tgz",
|
||||
"integrity": "sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ==",
|
||||
"requires": {
|
||||
"colorette": "^1.2.2",
|
||||
"nanoid": "^3.1.22",
|
||||
"source-map": "^0.6.1"
|
||||
"nanoid": "^3.1.23",
|
||||
"source-map-js": "^0.6.2"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -35699,9 +35730,9 @@
|
||||
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
|
||||
},
|
||||
"resolve-url-loader": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.2.tgz",
|
||||
"integrity": "sha512-QEb4A76c8Mi7I3xNKXlRKQSlLBwjUV/ULFMP+G7n3/7tJZ8MG5wsZ3ucxP1Jz8Vevn6fnJsxDx9cIls+utGzPQ==",
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.3.tgz",
|
||||
"integrity": "sha512-WbDSNFiKPPLem1ln+EVTE+bFUBdTTytfQZWbmghroaFNFaAVmGq0Saqw6F/306CwgPXsGwXVxbODE+3xAo/YbA==",
|
||||
"requires": {
|
||||
"adjust-sourcemap-loader": "3.0.0",
|
||||
"camelcase": "5.3.1",
|
||||
@@ -36573,6 +36604,11 @@
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
|
||||
},
|
||||
"source-map-js": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz",
|
||||
"integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug=="
|
||||
},
|
||||
"source-map-resolve": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
|
||||
@@ -39090,9 +39126,9 @@
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
|
||||
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
|
||||
"integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
@@ -39543,9 +39579,10 @@
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "7.4.4",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz",
|
||||
"integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw=="
|
||||
"version": "7.4.6",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
|
||||
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
|
||||
"requires": {}
|
||||
},
|
||||
"xdg-basedir": {
|
||||
"version": "4.0.0",
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.11.4",
|
||||
"@material-ui/icons": "^4.11.2",
|
||||
"@msgpack/msgpack": "^2.7.0",
|
||||
"@types/lodash": "^4.14.168",
|
||||
"@types/node": "^15.0.1",
|
||||
"@types/react": "^17.0.4",
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { withStyles, Theme, createStyles } from '@material-ui/core/styles';
|
||||
|
||||
import parseMilliseconds from 'parse-ms';
|
||||
|
||||
import { Decoder } from '@msgpack/msgpack';
|
||||
const decoder = new Decoder();
|
||||
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -37,7 +42,9 @@ import {
|
||||
EMSESPDevices,
|
||||
EMSESPDeviceData,
|
||||
Device,
|
||||
DeviceValue
|
||||
DeviceValue,
|
||||
DeviceValueUOM,
|
||||
DeviceValueUOM_s
|
||||
} from './EMSESPtypes';
|
||||
|
||||
import ValueForm from './ValueForm';
|
||||
@@ -85,25 +92,48 @@ interface EMSESPDevicesFormState {
|
||||
processing: boolean;
|
||||
deviceData?: EMSESPDeviceData;
|
||||
selectedDevice?: number;
|
||||
devicevalue?: DeviceValue;
|
||||
edit_devicevalue?: DeviceValue;
|
||||
}
|
||||
|
||||
type EMSESPDevicesFormProps = RestFormProps<EMSESPDevices> &
|
||||
AuthenticatedContextProps &
|
||||
WithWidthProps;
|
||||
|
||||
function formatTemp(t: string) {
|
||||
if (t == null) {
|
||||
return 'n/a';
|
||||
export const formatDuration = (duration_min: number) => {
|
||||
const { days, hours, minutes } = parseMilliseconds(duration_min * 60000);
|
||||
let formatted = '';
|
||||
if (days) {
|
||||
formatted += pluralize(days, 'day');
|
||||
}
|
||||
return t + ' °C';
|
||||
}
|
||||
if (hours) {
|
||||
formatted += pluralize(hours, 'hour');
|
||||
}
|
||||
if (minutes) {
|
||||
formatted += pluralize(minutes, 'minute');
|
||||
}
|
||||
return formatted;
|
||||
};
|
||||
|
||||
function formatUnit(u: string) {
|
||||
if (u == null) {
|
||||
return u;
|
||||
const pluralize = (count: number, noun: string, suffix = 's') =>
|
||||
` ${count} ${noun}${count !== 1 ? suffix : ''} `;
|
||||
|
||||
function formatValue(value: any, uom: number) {
|
||||
switch (uom) {
|
||||
case DeviceValueUOM.HOURS:
|
||||
return formatDuration(value * 60);
|
||||
case DeviceValueUOM.MINUTES:
|
||||
return formatDuration(value);
|
||||
case DeviceValueUOM.NONE:
|
||||
return value;
|
||||
case DeviceValueUOM.NUM:
|
||||
return new Intl.NumberFormat().format(value);
|
||||
case DeviceValueUOM.BOOLEAN:
|
||||
return value ? 'on' : 'off';
|
||||
default:
|
||||
return (
|
||||
new Intl.NumberFormat().format(value) + ' ' + DeviceValueUOM_s[uom]
|
||||
);
|
||||
}
|
||||
return ' ' + u;
|
||||
}
|
||||
|
||||
class EMSESPDevicesForm extends Component<
|
||||
@@ -119,25 +149,26 @@ class EMSESPDevicesForm extends Component<
|
||||
event: React.ChangeEvent<HTMLInputElement>
|
||||
) => {
|
||||
this.setState({
|
||||
devicevalue: {
|
||||
...this.state.devicevalue!,
|
||||
edit_devicevalue: {
|
||||
...this.state.edit_devicevalue!,
|
||||
[name]: extractEventValue(event)
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
cancelEditingValue = () => {
|
||||
this.setState({
|
||||
devicevalue: undefined
|
||||
});
|
||||
this.setState({ edit_devicevalue: undefined });
|
||||
};
|
||||
|
||||
doneEditingValue = () => {
|
||||
const { devicevalue } = this.state;
|
||||
const { edit_devicevalue, selectedDevice } = this.state;
|
||||
|
||||
redirectingAuthorizedFetch(WRITE_VALUE_ENDPOINT, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ devicevalue: devicevalue }),
|
||||
body: JSON.stringify({
|
||||
id: selectedDevice,
|
||||
devicevalue: edit_devicevalue
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
@@ -165,23 +196,13 @@ class EMSESPDevicesForm extends Component<
|
||||
});
|
||||
});
|
||||
|
||||
if (devicevalue) {
|
||||
this.setState({
|
||||
devicevalue: undefined
|
||||
});
|
||||
if (edit_devicevalue) {
|
||||
this.setState({ edit_devicevalue: undefined });
|
||||
}
|
||||
};
|
||||
|
||||
sendCommand = (i: number) => {
|
||||
this.setState({
|
||||
devicevalue: {
|
||||
id: this.state.selectedDevice!,
|
||||
data: this.state.deviceData?.data[i]!,
|
||||
uom: this.state.deviceData?.data[i + 1]!,
|
||||
name: this.state.deviceData?.data[i + 2]!,
|
||||
cmd: this.state.deviceData?.data[i + 3]!
|
||||
}
|
||||
});
|
||||
sendCommand = (dv: DeviceValue) => {
|
||||
this.setState({ edit_devicevalue: dv });
|
||||
};
|
||||
|
||||
noDevices = () => {
|
||||
@@ -290,7 +311,7 @@ class EMSESPDevicesForm extends Component<
|
||||
</TableCell>
|
||||
<TableCell align="center">{sensorData.id}</TableCell>
|
||||
<TableCell align="right">
|
||||
{formatTemp(sensorData.temp)}
|
||||
{formatValue(sensorData.temp, DeviceValueUOM.DEGREES)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
@@ -318,7 +339,7 @@ class EMSESPDevicesForm extends Component<
|
||||
>
|
||||
<DialogTitle>Confirm Scan Devices</DialogTitle>
|
||||
<DialogContent dividers>
|
||||
Are you sure you want to initiate a scan on the EMS bus for all new
|
||||
Are you sure you want to start a scan on the EMS bus for all new
|
||||
devices?
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
@@ -384,11 +405,12 @@ class EMSESPDevicesForm extends Component<
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status === 200) {
|
||||
return response.json();
|
||||
return response.arrayBuffer();
|
||||
}
|
||||
throw Error('Unexpected response code: ' + response.status);
|
||||
})
|
||||
.then((json) => {
|
||||
.then((arrayBuffer) => {
|
||||
const json: any = decoder.decode(arrayBuffer);
|
||||
this.setState({ deviceData: json });
|
||||
})
|
||||
.catch((error) => {
|
||||
@@ -429,40 +451,33 @@ class EMSESPDevicesForm extends Component<
|
||||
>
|
||||
<TableHead></TableHead>
|
||||
<TableBody>
|
||||
{deviceData.data.map((item, i) => {
|
||||
if (i % 4) {
|
||||
return null;
|
||||
} else {
|
||||
return (
|
||||
<TableRow hover key={i}>
|
||||
<TableCell padding="checkbox" style={{ width: 18 }}>
|
||||
{deviceData.data[i + 3] && me.admin && (
|
||||
<CustomTooltip
|
||||
title="change value"
|
||||
placement="left-end"
|
||||
>
|
||||
<IconButton
|
||||
edge="start"
|
||||
size="small"
|
||||
aria-label="Edit"
|
||||
onClick={() => this.sendCommand(i)}
|
||||
>
|
||||
<EditIcon color="primary" fontSize="small" />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell padding="none" component="th" scope="row">
|
||||
{deviceData.data[i + 2]}
|
||||
</TableCell>
|
||||
<TableCell padding="none" align="right">
|
||||
{deviceData.data[i]}
|
||||
{formatUnit(deviceData.data[i + 1])}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
}
|
||||
})}
|
||||
{deviceData.data.map((item, i) => (
|
||||
<TableRow hover key={i}>
|
||||
<TableCell padding="checkbox" style={{ width: 18 }}>
|
||||
{item.c && me.admin && (
|
||||
<CustomTooltip
|
||||
title="change value"
|
||||
placement="left-end"
|
||||
>
|
||||
<IconButton
|
||||
edge="start"
|
||||
size="small"
|
||||
aria-label="Edit"
|
||||
onClick={() => this.sendCommand(item)}
|
||||
>
|
||||
<EditIcon color="primary" fontSize="small" />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell padding="none" component="th" scope="row">
|
||||
{item.n}
|
||||
</TableCell>
|
||||
<TableCell padding="none" align="right">
|
||||
{formatValue(item.v, item.u)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
@@ -479,7 +494,7 @@ class EMSESPDevicesForm extends Component<
|
||||
}
|
||||
|
||||
render() {
|
||||
const { devicevalue } = this.state;
|
||||
const { edit_devicevalue } = this.state;
|
||||
return (
|
||||
<Fragment>
|
||||
<br></br>
|
||||
@@ -509,9 +524,9 @@ class EMSESPDevicesForm extends Component<
|
||||
</Box>
|
||||
</Box>
|
||||
{this.renderScanDevicesDialog()}
|
||||
{devicevalue && (
|
||||
{edit_devicevalue && (
|
||||
<ValueForm
|
||||
devicevalue={devicevalue}
|
||||
devicevalue={edit_devicevalue}
|
||||
onDoneEditing={this.doneEditingValue}
|
||||
onCancelEditing={this.cancelEditingValue}
|
||||
handleValueChange={this.handleValueChange}
|
||||
|
||||
@@ -58,15 +58,54 @@ export interface EMSESPDevices {
|
||||
sensors: Sensor[];
|
||||
}
|
||||
|
||||
export interface EMSESPDeviceData {
|
||||
name: string;
|
||||
data: string[];
|
||||
export interface DeviceValue {
|
||||
v: any;
|
||||
u: number;
|
||||
n: string;
|
||||
c: string;
|
||||
}
|
||||
|
||||
export interface DeviceValue {
|
||||
id: number;
|
||||
data: string;
|
||||
uom: string;
|
||||
export interface EMSESPDeviceData {
|
||||
name: string;
|
||||
cmd: string;
|
||||
data: DeviceValue[];
|
||||
}
|
||||
|
||||
export enum DeviceValueUOM {
|
||||
NONE = 0,
|
||||
DEGREES,
|
||||
PERCENT,
|
||||
LMIN,
|
||||
KWH,
|
||||
WH,
|
||||
HOURS,
|
||||
MINUTES,
|
||||
UA,
|
||||
BAR,
|
||||
KW,
|
||||
W,
|
||||
KB,
|
||||
SECONDS,
|
||||
DBM,
|
||||
NUM,
|
||||
BOOLEAN
|
||||
}
|
||||
|
||||
export const DeviceValueUOM_s = [
|
||||
'',
|
||||
'°C',
|
||||
'%',
|
||||
'l/min',
|
||||
'kWh',
|
||||
'Wh',
|
||||
'hours',
|
||||
'minutes',
|
||||
'uA',
|
||||
'bar',
|
||||
'kW',
|
||||
'W',
|
||||
'KB',
|
||||
'seconds',
|
||||
'dBm',
|
||||
'number',
|
||||
'on/off'
|
||||
];
|
||||
|
||||
@@ -2,53 +2,21 @@
|
||||
/*
|
||||
Async Response to use with ArduinoJson and AsyncWebServer
|
||||
Written by Andrew Melvin (SticilFace) with help from me-no-dev and BBlanchon.
|
||||
|
||||
Example of callback in use
|
||||
|
||||
server.on("/json", HTTP_ANY, [](AsyncWebServerRequest * request) {
|
||||
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse();
|
||||
JsonObject& root = response->getRoot();
|
||||
root["key1"] = "key number one";
|
||||
JsonObject& nested = root.createNestedObject("nested");
|
||||
nested["key1"] = "key number one";
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
});
|
||||
|
||||
--------------------
|
||||
|
||||
Async Request to use with ArduinoJson and AsyncWebServer
|
||||
Written by Arsène von Wyss (avonwyss)
|
||||
|
||||
Example
|
||||
|
||||
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/rest/endpoint");
|
||||
handler->onRequest([](AsyncWebServerRequest *request, JsonVariant &json) {
|
||||
JsonObject& jsonObj = json.as<JsonObject>();
|
||||
// ...
|
||||
});
|
||||
server.addHandler(handler);
|
||||
|
||||
*/
|
||||
|
||||
#ifndef ASYNC_JSON_H_
|
||||
#define ASYNC_JSON_H_
|
||||
#include <ArduinoJson.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <Print.h>
|
||||
|
||||
#if ARDUINOJSON_VERSION_MAJOR == 5
|
||||
#define ARDUINOJSON_5_COMPATIBILITY
|
||||
#else
|
||||
#define DYNAMIC_JSON_DOCUMENT_SIZE 1024
|
||||
#endif
|
||||
|
||||
constexpr const char * JSON_MIMETYPE = "application/json";
|
||||
|
||||
/*
|
||||
* Json Response
|
||||
* */
|
||||
*/
|
||||
|
||||
class ChunkPrint : public Print {
|
||||
private:
|
||||
@@ -82,30 +50,14 @@ class ChunkPrint : public Print {
|
||||
}
|
||||
};
|
||||
|
||||
class AsyncJsonResponse : public AsyncAbstractResponse {
|
||||
class MsgpackAsyncJsonResponse : public AsyncAbstractResponse {
|
||||
protected:
|
||||
#ifdef ARDUINOJSON_5_COMPATIBILITY
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
#else
|
||||
DynamicJsonDocument _jsonBuffer;
|
||||
#endif
|
||||
|
||||
JsonVariant _root;
|
||||
bool _isValid;
|
||||
JsonVariant _root;
|
||||
bool _isValid;
|
||||
|
||||
public:
|
||||
#ifdef ARDUINOJSON_5_COMPATIBILITY
|
||||
AsyncJsonResponse(bool isArray = false)
|
||||
: _isValid{false} {
|
||||
_code = 200;
|
||||
_contentType = JSON_MIMETYPE;
|
||||
if (isArray)
|
||||
_root = _jsonBuffer.createArray();
|
||||
else
|
||||
_root = _jsonBuffer.createObject();
|
||||
}
|
||||
#else
|
||||
AsyncJsonResponse(bool isArray = false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE)
|
||||
MsgpackAsyncJsonResponse(bool isArray = false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE)
|
||||
: _jsonBuffer(maxJsonBufferSize)
|
||||
, _isValid{false} {
|
||||
_code = 200;
|
||||
@@ -115,9 +67,8 @@ class AsyncJsonResponse : public AsyncAbstractResponse {
|
||||
else
|
||||
_root = _jsonBuffer.createNestedObject();
|
||||
}
|
||||
#endif
|
||||
|
||||
~AsyncJsonResponse() {
|
||||
~MsgpackAsyncJsonResponse() {
|
||||
}
|
||||
JsonVariant & getRoot() {
|
||||
return _root;
|
||||
@@ -126,12 +77,7 @@ class AsyncJsonResponse : public AsyncAbstractResponse {
|
||||
return _isValid;
|
||||
}
|
||||
size_t setLength() {
|
||||
#ifdef ARDUINOJSON_5_COMPATIBILITY
|
||||
_contentLength = _root.measureLength();
|
||||
#else
|
||||
_contentLength = measureJson(_root);
|
||||
#endif
|
||||
|
||||
_contentLength = measureMsgPack(_root);
|
||||
if (_contentLength) {
|
||||
_isValid = true;
|
||||
}
|
||||
@@ -144,33 +90,66 @@ class AsyncJsonResponse : public AsyncAbstractResponse {
|
||||
|
||||
size_t _fillBuffer(uint8_t * data, size_t len) {
|
||||
ChunkPrint dest(data, _sentLength, len);
|
||||
serializeMsgPack(_root, dest);
|
||||
// serializeJson(_root, Serial); // for testing proddy
|
||||
// Serial.println();
|
||||
return len;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef ARDUINOJSON_5_COMPATIBILITY
|
||||
_root.printTo(dest);
|
||||
#else
|
||||
class AsyncJsonResponse : public AsyncAbstractResponse {
|
||||
protected:
|
||||
DynamicJsonDocument _jsonBuffer;
|
||||
|
||||
JsonVariant _root;
|
||||
bool _isValid;
|
||||
|
||||
public:
|
||||
AsyncJsonResponse(bool isArray = false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE)
|
||||
: _jsonBuffer(maxJsonBufferSize)
|
||||
, _isValid{false} {
|
||||
_code = 200;
|
||||
_contentType = JSON_MIMETYPE;
|
||||
if (isArray)
|
||||
_root = _jsonBuffer.createNestedArray();
|
||||
else
|
||||
_root = _jsonBuffer.createNestedObject();
|
||||
}
|
||||
|
||||
~AsyncJsonResponse() {
|
||||
}
|
||||
JsonVariant & getRoot() {
|
||||
return _root;
|
||||
}
|
||||
bool _sourceValid() const {
|
||||
return _isValid;
|
||||
}
|
||||
size_t setLength() {
|
||||
_contentLength = measureJson(_root);
|
||||
if (_contentLength) {
|
||||
_isValid = true;
|
||||
}
|
||||
return _contentLength;
|
||||
}
|
||||
|
||||
size_t getSize() {
|
||||
return _jsonBuffer.size();
|
||||
}
|
||||
|
||||
size_t _fillBuffer(uint8_t * data, size_t len) {
|
||||
ChunkPrint dest(data, _sentLength, len);
|
||||
serializeJson(_root, dest);
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
};
|
||||
|
||||
class PrettyAsyncJsonResponse : public AsyncJsonResponse {
|
||||
public:
|
||||
#ifdef ARDUINOJSON_5_COMPATIBILITY
|
||||
PrettyAsyncJsonResponse(bool isArray = false)
|
||||
: AsyncJsonResponse{isArray} {
|
||||
}
|
||||
#else
|
||||
PrettyAsyncJsonResponse(bool isArray = false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE)
|
||||
: AsyncJsonResponse{isArray, maxJsonBufferSize} {
|
||||
}
|
||||
#endif
|
||||
size_t setLength() {
|
||||
#ifdef ARDUINOJSON_5_COMPATIBILITY
|
||||
_contentLength = _root.measurePrettyLength();
|
||||
#else
|
||||
_contentLength = measureJsonPretty(_root);
|
||||
#endif
|
||||
if (_contentLength) {
|
||||
_isValid = true;
|
||||
}
|
||||
@@ -178,13 +157,9 @@ class PrettyAsyncJsonResponse : public AsyncJsonResponse {
|
||||
}
|
||||
size_t _fillBuffer(uint8_t * data, size_t len) {
|
||||
ChunkPrint dest(data, _sentLength, len);
|
||||
#ifdef ARDUINOJSON_5_COMPATIBILITY
|
||||
_root.prettyPrintTo(dest);
|
||||
#else
|
||||
serializeJsonPretty(_root, dest);
|
||||
// serializeJson(_root, Serial); // for testing
|
||||
// serializeJson(_root, Serial); // for testing proddy
|
||||
// Serial.println();
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
};
|
||||
@@ -204,14 +179,6 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
|
||||
size_t _maxContentLength;
|
||||
|
||||
public:
|
||||
#ifdef ARDUINOJSON_5_COMPATIBILITY
|
||||
AsyncCallbackJsonWebHandler(const String & uri, ArJsonRequestHandlerFunction onRequest)
|
||||
: _uri(uri)
|
||||
, _method(HTTP_POST | HTTP_PUT | HTTP_PATCH)
|
||||
, _onRequest(onRequest)
|
||||
, _maxContentLength(16384) {
|
||||
}
|
||||
#else
|
||||
AsyncCallbackJsonWebHandler(const String & uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE)
|
||||
: _uri(uri)
|
||||
, _method(HTTP_POST | HTTP_PUT | HTTP_PATCH)
|
||||
@@ -219,7 +186,6 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
|
||||
, maxJsonBufferSize(maxJsonBufferSize)
|
||||
, _maxContentLength(16384) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void setMethod(WebRequestMethodComposite method) {
|
||||
_method = method;
|
||||
@@ -251,17 +217,10 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
|
||||
virtual void handleRequest(AsyncWebServerRequest * request) override final {
|
||||
if (_onRequest) {
|
||||
if (request->_tempObject != NULL) {
|
||||
#ifdef ARDUINOJSON_5_COMPATIBILITY
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonVariant json = jsonBuffer.parse((uint8_t *)(request->_tempObject));
|
||||
if (json.success()) {
|
||||
#else
|
||||
DynamicJsonDocument jsonBuffer(this->maxJsonBufferSize);
|
||||
DeserializationError error = deserializeJson(jsonBuffer, (uint8_t *)(request->_tempObject));
|
||||
if (!error) {
|
||||
JsonVariant json = jsonBuffer.as<JsonVariant>();
|
||||
#endif
|
||||
|
||||
_onRequest(request, json);
|
||||
return;
|
||||
}
|
||||
@@ -288,4 +247,5 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
|
||||
return _onRequest ? false : true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -87,6 +87,52 @@ class PrettyAsyncJsonResponse {
|
||||
}
|
||||
};
|
||||
|
||||
class MsgpackAsyncJsonResponse {
|
||||
protected:
|
||||
DynamicJsonDocument _jsonBuffer;
|
||||
JsonVariant _root;
|
||||
bool _isValid;
|
||||
|
||||
public:
|
||||
MsgpackAsyncJsonResponse(bool isArray = false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE)
|
||||
: _jsonBuffer(maxJsonBufferSize)
|
||||
, _isValid{false} {
|
||||
if (isArray)
|
||||
_root = _jsonBuffer.createNestedArray();
|
||||
else
|
||||
_root = _jsonBuffer.createNestedObject();
|
||||
}
|
||||
|
||||
~MsgpackAsyncJsonResponse() {
|
||||
}
|
||||
|
||||
JsonVariant & getRoot() {
|
||||
return _root;
|
||||
}
|
||||
|
||||
bool _sourceValid() const {
|
||||
return _isValid;
|
||||
}
|
||||
|
||||
size_t setLength() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setContentType(const char * s) {
|
||||
}
|
||||
|
||||
size_t getSize() {
|
||||
return _jsonBuffer.size();
|
||||
}
|
||||
|
||||
size_t _fillBuffer(uint8_t * data, size_t len) {
|
||||
return len;
|
||||
}
|
||||
|
||||
void setCode(uint16_t) {
|
||||
}
|
||||
};
|
||||
|
||||
class AsyncJsonResponse {
|
||||
protected:
|
||||
DynamicJsonDocument _jsonBuffer;
|
||||
|
||||
@@ -12,6 +12,7 @@ class AsyncWebServerRequest;
|
||||
class AsyncWebServerResponse;
|
||||
class AsyncJsonResponse;
|
||||
class PrettyAsyncJsonResponse;
|
||||
class MsgpackAsyncJsonResponse;
|
||||
|
||||
class AsyncWebParameter {
|
||||
private:
|
||||
@@ -98,6 +99,7 @@ class AsyncWebServerRequest {
|
||||
void send(AsyncWebServerResponse * response){};
|
||||
void send(AsyncJsonResponse * response){};
|
||||
void send(PrettyAsyncJsonResponse * response){};
|
||||
void send(MsgpackAsyncJsonResponse * response){};
|
||||
void send(int code, const String & contentType = String(), const String & content = String()){};
|
||||
void send(int code, const String & contentType, const __FlashStringHelper *){};
|
||||
|
||||
@@ -194,9 +196,9 @@ class AsyncWebServerResponse {
|
||||
virtual ~AsyncWebServerResponse();
|
||||
};
|
||||
|
||||
typedef std::function<void(AsyncWebServerRequest * request)> ArRequestHandlerFunction;
|
||||
typedef std::function<void(AsyncWebServerRequest * request)> ArRequestHandlerFunction;
|
||||
typedef std::function<void(AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final)> ArUploadHandlerFunction;
|
||||
typedef std::function<void(AsyncWebServerRequest * request, uint8_t * data, size_t len, size_t index, size_t total)> ArBodyHandlerFunction;
|
||||
typedef std::function<void(AsyncWebServerRequest * request, uint8_t * data, size_t len, size_t index, size_t total)> ArBodyHandlerFunction;
|
||||
|
||||
class AsyncWebServer {
|
||||
protected:
|
||||
|
||||
14
mock-api/package-lock.json
generated
14
mock-api/package-lock.json
generated
@@ -9,10 +9,19 @@
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@msgpack/msgpack": "^2.7.0",
|
||||
"express": "^4.17.1",
|
||||
"nodemon": "^2.0.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@msgpack/msgpack": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.7.0.tgz",
|
||||
"integrity": "sha512-mlRYq9FSsOd4m+3wZWatemn3hGFZPWNJ4JQOdrir4rrMK2PyIk26idKBoUWrqF3HJJHl+5GpRU+M0wEruJwecg==",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/is": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
|
||||
@@ -1593,6 +1602,11 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@msgpack/msgpack": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.7.0.tgz",
|
||||
"integrity": "sha512-mlRYq9FSsOd4m+3wZWatemn3hGFZPWNJ4JQOdrir4rrMK2PyIk26idKBoUWrqF3HJJHl+5GpRU+M0wEruJwecg=="
|
||||
},
|
||||
"@sindresorhus/is": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"author": "proddy",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@msgpack/msgpack": "^2.7.0",
|
||||
"express": "^4.17.1",
|
||||
"nodemon": "^2.0.7"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
const express = require('express')
|
||||
const path = require('path')
|
||||
|
||||
const msgpack = require('@msgpack/msgpack')
|
||||
// import { encode } from "@msgpack/msgpack";
|
||||
|
||||
const app = express()
|
||||
const port = process.env.PORT || 3080
|
||||
|
||||
@@ -284,7 +287,10 @@ const emsesp_alldevices = {
|
||||
version: '01.03',
|
||||
},
|
||||
],
|
||||
sensors: [],
|
||||
sensors: [
|
||||
{ no: 1, id: '28-233D-9497-0C03', temp: '25.7' },
|
||||
{ no: 2, id: '28-243D-7437-1E3A', temp: '26.1' },
|
||||
],
|
||||
}
|
||||
const emsesp_status = {
|
||||
status: 0,
|
||||
@@ -293,273 +299,408 @@ const emsesp_status = {
|
||||
rx_quality: 100,
|
||||
tx_quality: 100,
|
||||
}
|
||||
|
||||
const emsesp_devicedata_1 = {
|
||||
name: 'Thermostat: RC20/Moduline 300',
|
||||
data: [
|
||||
'16:28:21 01/04/2021',
|
||||
'',
|
||||
'date/time',
|
||||
'datetime',
|
||||
'(0)',
|
||||
'',
|
||||
'error code',
|
||||
'',
|
||||
15,
|
||||
'°C',
|
||||
'(hc1) setpoint room temperature',
|
||||
'temp',
|
||||
20.5,
|
||||
'°C',
|
||||
'(hc1) current room temperature',
|
||||
'',
|
||||
'auto',
|
||||
'',
|
||||
'(hc1) mode',
|
||||
'mode',
|
||||
{
|
||||
v: '(0)',
|
||||
u: 0,
|
||||
n: 'error code',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: '14:54:39 06/06/2021',
|
||||
u: 0,
|
||||
n: 'date/time',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 18,
|
||||
u: 1,
|
||||
n: '(hc1) selected room temperature',
|
||||
c: 'hc1/seltemp',
|
||||
},
|
||||
{
|
||||
v: 22.6,
|
||||
u: 1,
|
||||
n: '(hc1) current room temperature',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 'auto',
|
||||
u: 0,
|
||||
n: '(hc1) mode',
|
||||
c: 'hc1/mode',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const emsesp_devicedata_2 = {
|
||||
name: 'Boiler: Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i',
|
||||
data: [
|
||||
'off',
|
||||
'',
|
||||
'heating active',
|
||||
'',
|
||||
'off',
|
||||
'',
|
||||
'warm water active',
|
||||
'',
|
||||
5,
|
||||
'°C',
|
||||
'selected flow temperature',
|
||||
'selflowtemp',
|
||||
0,
|
||||
'%',
|
||||
'burner selected max power',
|
||||
'',
|
||||
0,
|
||||
'%',
|
||||
'heating pump modulation',
|
||||
'',
|
||||
42.7,
|
||||
'°C',
|
||||
'current flow temperature',
|
||||
'',
|
||||
39,
|
||||
'°C',
|
||||
'return temperature',
|
||||
'',
|
||||
1.2,
|
||||
'bar',
|
||||
'system pressure',
|
||||
'',
|
||||
45.3,
|
||||
'°C',
|
||||
'max boiler temperature',
|
||||
'',
|
||||
'off',
|
||||
'',
|
||||
'gas',
|
||||
'',
|
||||
0,
|
||||
'uA',
|
||||
'flame current',
|
||||
'',
|
||||
'off',
|
||||
'',
|
||||
'heating pump',
|
||||
'',
|
||||
'off',
|
||||
'',
|
||||
'fan',
|
||||
'',
|
||||
'off',
|
||||
'',
|
||||
'ignition',
|
||||
'',
|
||||
'on',
|
||||
'',
|
||||
'heating activated',
|
||||
'',
|
||||
75,
|
||||
'°C',
|
||||
'heating temperature',
|
||||
'',
|
||||
90,
|
||||
'%',
|
||||
'burner pump max power',
|
||||
'',
|
||||
55,
|
||||
'%',
|
||||
'burner pump min power',
|
||||
'',
|
||||
1,
|
||||
null,
|
||||
'pump delay',
|
||||
'',
|
||||
10,
|
||||
null,
|
||||
'burner min period',
|
||||
'',
|
||||
0,
|
||||
'%',
|
||||
'burner min power',
|
||||
'',
|
||||
75,
|
||||
'%',
|
||||
'burner max power',
|
||||
'',
|
||||
-6,
|
||||
'°C',
|
||||
'hysteresis on temperature',
|
||||
'',
|
||||
6,
|
||||
'°C',
|
||||
'hysteresis off temperature',
|
||||
'',
|
||||
0,
|
||||
'%',
|
||||
'burner current power',
|
||||
'',
|
||||
295740,
|
||||
'',
|
||||
'burner # starts',
|
||||
'',
|
||||
'344 days 2 hours 8 minutes',
|
||||
null,
|
||||
'total burner operating time',
|
||||
'',
|
||||
'279 days 11 hours 55 minutes',
|
||||
null,
|
||||
'total heat operating time',
|
||||
'',
|
||||
'2946 days 19 hours 8 minutes',
|
||||
null,
|
||||
'total UBA operating time',
|
||||
'',
|
||||
'1C(210) 06.06.2020 12:07',
|
||||
'',
|
||||
'last error code',
|
||||
'',
|
||||
'0H',
|
||||
'',
|
||||
'service code',
|
||||
'',
|
||||
203,
|
||||
'',
|
||||
'service code number',
|
||||
'',
|
||||
'01.01.2012',
|
||||
'',
|
||||
'maintenance set date',
|
||||
'',
|
||||
'off',
|
||||
'',
|
||||
'maintenance scheduled',
|
||||
'',
|
||||
6000,
|
||||
'hours',
|
||||
'maintenance set time',
|
||||
'',
|
||||
60,
|
||||
'°C',
|
||||
'(warm water) selected temperature',
|
||||
'',
|
||||
62,
|
||||
'°C',
|
||||
'(warm water) set temperature',
|
||||
'',
|
||||
'flow',
|
||||
'',
|
||||
'(warm water) type',
|
||||
'',
|
||||
'hot',
|
||||
'',
|
||||
'(warm water) comfort',
|
||||
'',
|
||||
40,
|
||||
'',
|
||||
'(warm water) flow temperature offset',
|
||||
'',
|
||||
100,
|
||||
'%',
|
||||
'(warm water) max power',
|
||||
'',
|
||||
'off',
|
||||
'',
|
||||
'(warm water) circulation pump available',
|
||||
'',
|
||||
'3-way valve',
|
||||
'',
|
||||
'(warm water) charging type',
|
||||
'',
|
||||
70,
|
||||
'°C',
|
||||
'(warm water) disinfection temperature',
|
||||
'',
|
||||
'off',
|
||||
'',
|
||||
'(warm water) circulation pump freq',
|
||||
'',
|
||||
'off',
|
||||
'',
|
||||
'(warm water) circulation active',
|
||||
'',
|
||||
34.7,
|
||||
'°C',
|
||||
'(warm water) current intern temperature',
|
||||
'',
|
||||
0,
|
||||
'l/min',
|
||||
'(warm water) current tap water flow',
|
||||
'',
|
||||
34.6,
|
||||
'°C',
|
||||
'(warm water) storage intern temperature',
|
||||
'',
|
||||
'on',
|
||||
'',
|
||||
'(warm water) activated',
|
||||
'',
|
||||
'off',
|
||||
'',
|
||||
'(warm water) one time charging',
|
||||
'',
|
||||
'off',
|
||||
'',
|
||||
'(warm water) disinfecting',
|
||||
'',
|
||||
'off',
|
||||
'',
|
||||
'(warm water) charging',
|
||||
'',
|
||||
'off',
|
||||
'',
|
||||
'(warm water) recharging',
|
||||
'',
|
||||
'on',
|
||||
'',
|
||||
'(warm water) temperature ok',
|
||||
'',
|
||||
'off',
|
||||
'',
|
||||
'(warm water) active',
|
||||
'',
|
||||
'on',
|
||||
'',
|
||||
'(warm water) heating',
|
||||
'',
|
||||
262387,
|
||||
'',
|
||||
'(warm water) # starts',
|
||||
'',
|
||||
'64 days 14 hours 13 minutes',
|
||||
null,
|
||||
'(warm water) active time',
|
||||
'',
|
||||
{
|
||||
v: false,
|
||||
u: 16,
|
||||
n: 'heating active',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: false,
|
||||
u: 16,
|
||||
n: 'warm water active',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 5,
|
||||
u: 1,
|
||||
n: 'selected flow temperature',
|
||||
c: 'selflowtemp',
|
||||
},
|
||||
{
|
||||
v: 0,
|
||||
u: 2,
|
||||
n: 'burner selected max power',
|
||||
c: 'selburnpow',
|
||||
},
|
||||
{
|
||||
v: 0,
|
||||
u: 2,
|
||||
n: 'heating pump modulation',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 51,
|
||||
u: 1,
|
||||
n: 'current flow temperature',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 49.8,
|
||||
u: 1,
|
||||
n: 'return temperature',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 1.1,
|
||||
u: 9,
|
||||
n: 'system pressure',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 52.7,
|
||||
u: 1,
|
||||
n: 'boiler temperature',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: false,
|
||||
u: 16,
|
||||
n: 'gas',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 0,
|
||||
u: 8,
|
||||
n: 'flame current',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: false,
|
||||
u: 16,
|
||||
n: 'heating pump',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: false,
|
||||
u: 16,
|
||||
n: 'fan',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: false,
|
||||
u: 16,
|
||||
n: 'ignition',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: true,
|
||||
u: 16,
|
||||
n: 'heating activated',
|
||||
c: 'heatingactivated',
|
||||
},
|
||||
{
|
||||
v: 75,
|
||||
u: 1,
|
||||
n: 'heating temperature',
|
||||
c: 'heatingtemp',
|
||||
},
|
||||
{
|
||||
v: 90,
|
||||
u: 2,
|
||||
n: 'burner pump max power',
|
||||
c: 'pumpmodmax',
|
||||
},
|
||||
{
|
||||
v: 55,
|
||||
u: 2,
|
||||
n: 'burner pump min power',
|
||||
c: 'pumpmodmin',
|
||||
},
|
||||
{
|
||||
v: 1,
|
||||
u: 7,
|
||||
n: 'pump delay',
|
||||
c: 'pumpdelay',
|
||||
},
|
||||
{
|
||||
v: 10,
|
||||
u: 7,
|
||||
n: 'burner min period',
|
||||
c: 'burnminperiod',
|
||||
},
|
||||
{
|
||||
v: 0,
|
||||
u: 2,
|
||||
n: 'burner min power',
|
||||
c: 'burnminpower',
|
||||
},
|
||||
{
|
||||
v: 75,
|
||||
u: 2,
|
||||
n: 'burner max power',
|
||||
c: 'burnmaxpower',
|
||||
},
|
||||
{
|
||||
v: -6,
|
||||
u: 1,
|
||||
n: 'hysteresis on temperature',
|
||||
c: 'boilhyston',
|
||||
},
|
||||
{
|
||||
v: 6,
|
||||
u: 1,
|
||||
n: 'hysteresis off temperature',
|
||||
c: 'boilhystoff',
|
||||
},
|
||||
{
|
||||
v: 0,
|
||||
u: 2,
|
||||
n: 'burner current power',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 303226,
|
||||
u: 15,
|
||||
n: '# burner starts',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 510634,
|
||||
u: 7,
|
||||
n: 'total burner operating time',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 415235,
|
||||
u: 7,
|
||||
n: 'total heat operating time',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 4338730,
|
||||
u: 7,
|
||||
n: 'total UBA operating time',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: '1C(210) 06.06.2020 12:07',
|
||||
u: 0,
|
||||
n: 'last error code',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: '0H',
|
||||
u: 0,
|
||||
n: 'service code',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 203,
|
||||
u: 0,
|
||||
n: 'service code number',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: '01.01.2012',
|
||||
u: 0,
|
||||
n: 'maintenance set date',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 'off',
|
||||
u: 0,
|
||||
n: 'maintenance scheduled',
|
||||
c: 'maintenance',
|
||||
},
|
||||
{
|
||||
v: 6000,
|
||||
u: 6,
|
||||
n: 'maintenance set time',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 60,
|
||||
u: 1,
|
||||
n: '(ww) selected temperature',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 62,
|
||||
u: 1,
|
||||
n: '(ww) set temperature',
|
||||
c: 'wwsettemp',
|
||||
},
|
||||
{
|
||||
v: 'flow',
|
||||
u: 0,
|
||||
n: '(ww) type',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 'hot',
|
||||
u: 0,
|
||||
n: '(ww) comfort',
|
||||
c: 'wwcomfort',
|
||||
},
|
||||
{
|
||||
v: 40,
|
||||
u: 0,
|
||||
n: '(ww) flow temperature offset',
|
||||
c: 'wwflowtempoffset',
|
||||
},
|
||||
{
|
||||
v: 100,
|
||||
u: 2,
|
||||
n: '(ww) max power',
|
||||
c: 'wwmaxpower',
|
||||
},
|
||||
{
|
||||
v: false,
|
||||
u: 16,
|
||||
n: '(ww) circulation pump available',
|
||||
c: 'wwcircpump',
|
||||
},
|
||||
{
|
||||
v: 'charge pump',
|
||||
u: 0,
|
||||
n: '(ww) charging type',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 70,
|
||||
u: 1,
|
||||
n: '(ww) disinfection temperature',
|
||||
c: 'wwdisinfectiontemp',
|
||||
},
|
||||
{
|
||||
v: 'off',
|
||||
u: 0,
|
||||
n: '(ww) circulation pump frequency',
|
||||
c: 'wwcircmode',
|
||||
},
|
||||
{
|
||||
v: false,
|
||||
u: 16,
|
||||
n: '(ww) circulation active',
|
||||
c: 'wwcirc',
|
||||
},
|
||||
{
|
||||
v: 44.4,
|
||||
u: 1,
|
||||
n: '(ww) current intern temperature',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 0,
|
||||
u: 3,
|
||||
n: '(ww) current tap water flow',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 44.4,
|
||||
u: 1,
|
||||
n: '(ww) storage intern temperature',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: true,
|
||||
u: 16,
|
||||
n: '(ww) activated',
|
||||
c: 'wwactivated',
|
||||
},
|
||||
{
|
||||
v: false,
|
||||
u: 16,
|
||||
n: '(ww) one time charging',
|
||||
c: 'wwonetime',
|
||||
},
|
||||
{
|
||||
v: false,
|
||||
u: 16,
|
||||
n: '(ww) disinfecting',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: false,
|
||||
u: 16,
|
||||
n: '(ww) charging',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: false,
|
||||
u: 16,
|
||||
n: '(ww) recharging',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: true,
|
||||
u: 16,
|
||||
n: '(ww) temperature ok',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: false,
|
||||
u: 16,
|
||||
n: '(ww) active',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: true,
|
||||
u: 16,
|
||||
n: '(ww) heating',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 268671,
|
||||
u: 15,
|
||||
n: '(ww) # starts',
|
||||
c: '',
|
||||
},
|
||||
{
|
||||
v: 95399,
|
||||
u: 7,
|
||||
n: '(ww) active time',
|
||||
c: '',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const emsesp_devicedata_3 = {
|
||||
name: 'Controller: BC1',
|
||||
data: [],
|
||||
}
|
||||
|
||||
// NETWORK
|
||||
app.get(NETWORK_STATUS_ENDPOINT, (req, res) => {
|
||||
res.json(network_status)
|
||||
@@ -672,16 +813,27 @@ app.get(EMSESP_STATUS_ENDPOINT, (req, res) => {
|
||||
app.post(EMSESP_DEVICEDATA_ENDPOINT, (req, res) => {
|
||||
const id = req.body.id
|
||||
if (id == 1) {
|
||||
res.json(emsesp_devicedata_1)
|
||||
const encoded = msgpack.encode(emsesp_devicedata_1)
|
||||
res.write(encoded, 'binary')
|
||||
res.end(null, 'binary')
|
||||
}
|
||||
if (id == 2) {
|
||||
res.json(emsesp_devicedata_2)
|
||||
const encoded = msgpack.encode(emsesp_devicedata_2)
|
||||
res.write(encoded, 'binary')
|
||||
res.end(null, 'binary')
|
||||
}
|
||||
if (id == 3) {
|
||||
const encoded = msgpack.encode(emsesp_devicedata_3)
|
||||
res.write(encoded, 'binary')
|
||||
res.end(null, 'binary')
|
||||
}
|
||||
})
|
||||
|
||||
app.post(WRITE_VALUE_ENDPOINT, (req, res) => {
|
||||
const devicevalue = req.body.devicevalue
|
||||
const id = req.body.id
|
||||
|
||||
console.log(id)
|
||||
console.log(devicevalue)
|
||||
|
||||
res.sendStatus(200)
|
||||
|
||||
@@ -26,7 +26,7 @@ WebDevicesService::WebDevicesService(AsyncWebServer * server, SecurityManager *
|
||||
: _device_dataHandler(DEVICE_DATA_SERVICE_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebDevicesService::device_data, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED))
|
||||
, _writevalue_dataHandler(WRITE_VALUE_SERVICE_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebDevicesService::write_value, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED)) {
|
||||
securityManager->wrapCallback(std::bind(&WebDevicesService::write_value, this, _1, _2), AuthenticationPredicates::IS_ADMIN)) {
|
||||
server->on(EMSESP_DEVICES_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebDevicesService::all_devices, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
@@ -83,9 +83,10 @@ void WebDevicesService::all_devices(AsyncWebServerRequest * request) {
|
||||
}
|
||||
|
||||
// The unique_id is the unique record ID from the Web table to identify which device to load
|
||||
// Compresses the JSON using MsgPack https://msgpack.org/index.html
|
||||
void WebDevicesService::device_data(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
if (json.is<JsonObject>()) {
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XXLARGE_DYN);
|
||||
MsgpackAsyncJsonResponse * response = new MsgpackAsyncJsonResponse(false, EMSESP_JSON_SIZE_XXLARGE_DYN);
|
||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||
if (emsdevice) {
|
||||
if (emsdevice->unique_id() == json["id"]) {
|
||||
@@ -108,27 +109,20 @@ void WebDevicesService::device_data(AsyncWebServerRequest * request, JsonVariant
|
||||
|
||||
// takes a command and its data value from a specific Device, from the Web
|
||||
void WebDevicesService::write_value(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
// only issue commands if the API is enabled
|
||||
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
||||
if (!settings.notoken_api) {
|
||||
request->send(403); // forbidden error
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
if (json.is<JsonObject>()) {
|
||||
JsonObject dv = json["devicevalue"];
|
||||
uint8_t id = json["id"];
|
||||
|
||||
// using the unique ID from the web find the real device type
|
||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||
if (emsdevice) {
|
||||
if (emsdevice->unique_id() == dv["id"].as<int>()) {
|
||||
const char * cmd = dv["cmd"];
|
||||
if (emsdevice->unique_id() == id) {
|
||||
const char * cmd = dv["c"];
|
||||
uint8_t device_type = emsdevice->device_type();
|
||||
bool ok = false;
|
||||
char s[10];
|
||||
// the data could be in any format, but we need string
|
||||
JsonVariant data = dv["data"];
|
||||
JsonVariant data = dv["v"];
|
||||
if (data.is<const char *>()) {
|
||||
ok = Command::call(device_type, cmd, data.as<const char *>());
|
||||
} else if (data.is<int>()) {
|
||||
@@ -139,16 +133,17 @@ void WebDevicesService::write_value(AsyncWebServerRequest * request, JsonVariant
|
||||
ok = Command::call(device_type, cmd, data.as<bool>() ? "true" : "false");
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
request->send(200);
|
||||
}
|
||||
return; // found device, quit
|
||||
// send "Write command sent to device" or "Write command failed"
|
||||
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 204);
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
request->send(204); // no content error
|
||||
}
|
||||
|
||||
AsyncWebServerResponse * response = request->beginResponse(204); // Write command failed
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -86,7 +86,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
||||
}
|
||||
// MQTT commands for boiler topic
|
||||
register_device_value(
|
||||
TAG_BOILER_DATA, &dummybool_, DeviceValueType::BOOL, nullptr, FL_(wwtapactivated), DeviceValueUOM::NONE, MAKE_CF_CB(set_tapwarmwater_activated));
|
||||
TAG_BOILER_DATA, &dummybool_, DeviceValueType::BOOL, nullptr, FL_(wwtapactivated), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_tapwarmwater_activated));
|
||||
register_device_value(TAG_BOILER_DATA, &dummy8u_, DeviceValueType::ENUM, FL_(enum_reset), FL_(reset), DeviceValueUOM::NONE, MAKE_CF_CB(set_reset));
|
||||
|
||||
// add values
|
||||
@@ -96,8 +96,8 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
||||
register_device_value(TAG_BOILER_DATA, &id_, DeviceValueType::UINT, nullptr, FL_(ID), DeviceValueUOM::NONE);
|
||||
id_ = product_id;
|
||||
|
||||
register_device_value(TAG_BOILER_DATA, &heatingActive_, DeviceValueType::BOOL, nullptr, FL_(heatingActive), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_BOILER_DATA, &tapwaterActive_, DeviceValueType::BOOL, nullptr, FL_(tapwaterActive), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_BOILER_DATA, &heatingActive_, DeviceValueType::BOOL, nullptr, FL_(heatingActive), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_BOILER_DATA, &tapwaterActive_, DeviceValueType::BOOL, nullptr, FL_(tapwaterActive), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_BOILER_DATA, &selFlowTemp_, DeviceValueType::UINT, nullptr, FL_(selFlowTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flow_temp));
|
||||
register_device_value(TAG_BOILER_DATA, &selBurnPow_, DeviceValueType::UINT, nullptr, FL_(selBurnPow), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_burn_power));
|
||||
register_device_value(TAG_BOILER_DATA, &heatingPumpMod_, DeviceValueType::UINT, nullptr, FL_(heatingPumpMod), DeviceValueUOM::PERCENT);
|
||||
@@ -109,13 +109,13 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
||||
register_device_value(TAG_BOILER_DATA, &sysPress_, DeviceValueType::UINT, FL_(div10), FL_(sysPress), DeviceValueUOM::BAR);
|
||||
register_device_value(TAG_BOILER_DATA, &boilTemp_, DeviceValueType::USHORT, FL_(div10), FL_(boilTemp), DeviceValueUOM::DEGREES);
|
||||
register_device_value(TAG_BOILER_DATA, &exhaustTemp_, DeviceValueType::USHORT, FL_(div10), FL_(exhaustTemp), DeviceValueUOM::DEGREES);
|
||||
register_device_value(TAG_BOILER_DATA, &burnGas_, DeviceValueType::BOOL, nullptr, FL_(burnGas), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_BOILER_DATA, &burnGas_, DeviceValueType::BOOL, nullptr, FL_(burnGas), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_BOILER_DATA, &flameCurr_, DeviceValueType::USHORT, FL_(div10), FL_(flameCurr), DeviceValueUOM::UA);
|
||||
register_device_value(TAG_BOILER_DATA, &heatingPump_, DeviceValueType::BOOL, nullptr, FL_(heatingPump), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_BOILER_DATA, &fanWork_, DeviceValueType::BOOL, nullptr, FL_(fanWork), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_BOILER_DATA, &ignWork_, DeviceValueType::BOOL, nullptr, FL_(ignWork), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_BOILER_DATA, &heatingPump_, DeviceValueType::BOOL, nullptr, FL_(heatingPump), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_BOILER_DATA, &fanWork_, DeviceValueType::BOOL, nullptr, FL_(fanWork), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_BOILER_DATA, &ignWork_, DeviceValueType::BOOL, nullptr, FL_(ignWork), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(
|
||||
TAG_BOILER_DATA, &heatingActivated_, DeviceValueType::BOOL, nullptr, FL_(heatingActivated), DeviceValueUOM::NONE, MAKE_CF_CB(set_heating_activated));
|
||||
TAG_BOILER_DATA, &heatingActivated_, DeviceValueType::BOOL, nullptr, FL_(heatingActivated), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_heating_activated));
|
||||
register_device_value(TAG_BOILER_DATA, &heatingTemp_, DeviceValueType::UINT, nullptr, FL_(heatingTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_heating_temp));
|
||||
register_device_value(TAG_BOILER_DATA, &pumpModMax_, DeviceValueType::UINT, nullptr, FL_(pumpModMax), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_max_pump));
|
||||
register_device_value(TAG_BOILER_DATA, &pumpModMin_, DeviceValueType::UINT, nullptr, FL_(pumpModMin), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_min_pump));
|
||||
@@ -190,8 +190,8 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
||||
register_device_value(
|
||||
TAG_DEVICE_DATA_WW, &wWMaxPower_, DeviceValueType::UINT, nullptr, FL_(wWMaxPower), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_warmwater_maxpower));
|
||||
register_device_value(
|
||||
TAG_DEVICE_DATA_WW, &wWCircPump_, DeviceValueType::BOOL, nullptr, FL_(wWCircPump), DeviceValueUOM::NONE, MAKE_CF_CB(set_warmwater_circulation_pump));
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWChargeType_, DeviceValueType::BOOL, FL_(enum_charge), FL_(wWChargeType), DeviceValueUOM::NONE);
|
||||
TAG_DEVICE_DATA_WW, &wWCircPump_, DeviceValueType::BOOL, nullptr, FL_(wWCircPump), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_warmwater_circulation_pump));
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWChargeType_, DeviceValueType::ENUM, FL_(enum_charge), FL_(wWChargeType), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_DEVICE_DATA_WW,
|
||||
&wWDisinfectionTemp_,
|
||||
DeviceValueType::UINT,
|
||||
@@ -206,21 +206,21 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
||||
FL_(wWCircMode),
|
||||
DeviceValueUOM::NONE,
|
||||
MAKE_CF_CB(set_warmwater_circulation_mode));
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWCirc_, DeviceValueType::BOOL, nullptr, FL_(wWCirc), DeviceValueUOM::NONE, MAKE_CF_CB(set_warmwater_circulation));
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWCirc_, DeviceValueType::BOOL, nullptr, FL_(wWCirc), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_warmwater_circulation));
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWCurTemp_, DeviceValueType::USHORT, FL_(div10), FL_(wWCurTemp), DeviceValueUOM::DEGREES);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWCurTemp2_, DeviceValueType::USHORT, FL_(div10), FL_(wWCurTemp2), DeviceValueUOM::DEGREES);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWCurFlow_, DeviceValueType::UINT, FL_(div10), FL_(wWCurFlow), DeviceValueUOM::LMIN);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWStorageTemp1_, DeviceValueType::USHORT, FL_(div10), FL_(wWStorageTemp1), DeviceValueUOM::DEGREES);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWStorageTemp2_, DeviceValueType::USHORT, FL_(div10), FL_(wWStorageTemp2), DeviceValueUOM::DEGREES);
|
||||
register_device_value(
|
||||
TAG_DEVICE_DATA_WW, &wWActivated_, DeviceValueType::BOOL, nullptr, FL_(wWActivated), DeviceValueUOM::NONE, MAKE_CF_CB(set_warmwater_activated));
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWOneTime_, DeviceValueType::BOOL, nullptr, FL_(wWOneTime), DeviceValueUOM::NONE, MAKE_CF_CB(set_warmwater_onetime));
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWDisinfecting_, DeviceValueType::BOOL, nullptr, FL_(wWDisinfecting), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWCharging_, DeviceValueType::BOOL, nullptr, FL_(wWCharging), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWRecharging_, DeviceValueType::BOOL, nullptr, FL_(wWRecharging), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWTempOK_, DeviceValueType::BOOL, nullptr, FL_(wWTempOK), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWActive_, DeviceValueType::BOOL, nullptr, FL_(wWActive), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWHeat_, DeviceValueType::BOOL, nullptr, FL_(wWHeat), DeviceValueUOM::NONE);
|
||||
TAG_DEVICE_DATA_WW, &wWActivated_, DeviceValueType::BOOL, nullptr, FL_(wWActivated), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_warmwater_activated));
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWOneTime_, DeviceValueType::BOOL, nullptr, FL_(wWOneTime), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_warmwater_onetime));
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWDisinfecting_, DeviceValueType::BOOL, nullptr, FL_(wWDisinfecting), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWCharging_, DeviceValueType::BOOL, nullptr, FL_(wWCharging), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWRecharging_, DeviceValueType::BOOL, nullptr, FL_(wWRecharging), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWTempOK_, DeviceValueType::BOOL, nullptr, FL_(wWTempOK), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWActive_, DeviceValueType::BOOL, nullptr, FL_(wWActive), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWHeat_, DeviceValueType::BOOL, nullptr, FL_(wWHeat), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wWSetPumpPower_, DeviceValueType::UINT, nullptr, FL_(wWSetPumpPower), DeviceValueUOM::PERCENT);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &mixerTemp_, DeviceValueType::USHORT, FL_(div10), FL_(mixerTemp), DeviceValueUOM::DEGREES);
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &tankMiddleTemp_, DeviceValueType::USHORT, FL_(div10), FL_(tankMiddleTemp), DeviceValueUOM::DEGREES);
|
||||
@@ -311,7 +311,6 @@ void Boiler::check_active(const bool force) {
|
||||
}
|
||||
|
||||
// 0x33
|
||||
// Boiler(0x08) -> Me(0x0B), UBAParameterWW(0x33), data: 08 FF 30 FB FF 28 FF 07 46 00 00
|
||||
void Boiler::process_UBAParameterWW(std::shared_ptr<const Telegram> telegram) {
|
||||
// has_update(telegram->read_bitvalue(wwEquipt_,0,3)); // 8=boiler has ww
|
||||
has_update(telegram->read_value(wWActivated_, 1)); // 0xFF means on
|
||||
@@ -322,8 +321,7 @@ void Boiler::process_UBAParameterWW(std::shared_ptr<const Telegram> telegram) {
|
||||
has_update(telegram->read_value(wWCircPump_, 6)); // 0xFF means on
|
||||
has_update(telegram->read_value(wWCircMode_, 7)); // 1=1x3min 6=6x3min 7=continuous
|
||||
has_update(telegram->read_value(wWDisinfectionTemp_, 8));
|
||||
has_update(telegram->read_value(wWChargeType_,
|
||||
10)); // 0 = charge pump, 0xff = 3-way valve
|
||||
has_update(telegram->read_bitvalue(wWChargeType_, 10, 0)); // 0 = charge pump, 0xff = 3-way valve
|
||||
|
||||
telegram->read_value(wWComfort_, 9);
|
||||
if (wWComfort_ == 0x00) {
|
||||
@@ -1175,7 +1173,7 @@ bool Boiler::set_warmwater_circulation_pump(const char * value, const int8_t id)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set the mode of circulation, 1x3min, ... 6x3min, continuos
|
||||
// Set the mode of circulation, 1x3min, ... 6x3min, continuous
|
||||
// true = on, false = off
|
||||
bool Boiler::set_warmwater_circulation_mode(const char * value, const int8_t id) {
|
||||
int v = 0;
|
||||
@@ -1187,7 +1185,7 @@ bool Boiler::set_warmwater_circulation_mode(const char * value, const int8_t id)
|
||||
if (v < 7) {
|
||||
LOG_INFO(F("Setting warm water circulation mode %dx3min"), v);
|
||||
} else if (v == 7) {
|
||||
LOG_INFO(F("Setting warm water circulation mode continuos"));
|
||||
LOG_INFO(F("Setting warm water circulation mode continuous"));
|
||||
} else {
|
||||
LOG_WARNING(F("Set warm water circulation mode: Invalid value"));
|
||||
return false;
|
||||
|
||||
@@ -60,7 +60,7 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
|
||||
register_device_value(tag, &id_, DeviceValueType::UINT, nullptr, FL_(ID), DeviceValueUOM::NONE);
|
||||
register_device_value(tag, &flowSetTemp_, DeviceValueType::UINT, nullptr, FL_(flowSetTemp), DeviceValueUOM::DEGREES);
|
||||
register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES);
|
||||
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::NONE);
|
||||
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(tag, &status_, DeviceValueType::INT, nullptr, FL_(mixerStatus), DeviceValueUOM::PERCENT);
|
||||
register_device_value(tag, &flowTempVf_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempVf), DeviceValueUOM::DEGREES);
|
||||
} else {
|
||||
@@ -69,7 +69,7 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
|
||||
uint8_t tag = TAG_WWC1 + hc_ - 1;
|
||||
register_device_value(tag, &id_, DeviceValueType::UINT, nullptr, FL_(ID), DeviceValueUOM::NONE);
|
||||
register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(wwTemp), DeviceValueUOM::DEGREES);
|
||||
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(wwPumpStatus), DeviceValueUOM::NONE);
|
||||
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(wwPumpStatus), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(tag, &status_, DeviceValueType::INT, nullptr, FL_(wwTempStatus), DeviceValueUOM::NONE);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,12 +80,11 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
|
||||
|
||||
register_device_value(TAG_NONE, &collectorTemp_, DeviceValueType::SHORT, FL_(div10), FL_(collectorTemp), DeviceValueUOM::DEGREES);
|
||||
register_device_value(TAG_NONE, &tankBottomTemp_, DeviceValueType::SHORT, FL_(div10), FL_(tankBottomTemp), DeviceValueUOM::DEGREES);
|
||||
register_device_value(TAG_NONE, &solarPump_, DeviceValueType::BOOL, nullptr, FL_(solarPump), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_NONE, &solarPump_, DeviceValueType::BOOL, nullptr, FL_(solarPump), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_NONE, &pumpWorkTime_, DeviceValueType::TIME, nullptr, FL_(pumpWorkTime), DeviceValueUOM::MINUTES);
|
||||
register_device_value(TAG_NONE, &tankMaxTemp_, DeviceValueType::UINT, nullptr, FL_(tankMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_TankMaxTemp));
|
||||
|
||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM10) {
|
||||
// register_device_value(TAG_NONE, &collectorMaxTemp_, DeviceValueType::UINT, nullptr, FL_(collectorMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_CollectorMaxTemp));
|
||||
register_device_value(TAG_NONE, &solarPumpModulation_, DeviceValueType::UINT, nullptr, FL_(solarPumpModulation), DeviceValueUOM::PERCENT);
|
||||
register_device_value(TAG_NONE, &solarPumpMinMod_, DeviceValueType::UINT, nullptr, FL_(pumpMinMod), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_PumpMinMod));
|
||||
register_device_value(
|
||||
@@ -96,17 +95,16 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
|
||||
TAG_NONE, &collectorMaxTemp_, DeviceValueType::UINT, nullptr, FL_(collectorMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_CollectorMaxTemp));
|
||||
register_device_value(
|
||||
TAG_NONE, &collectorMinTemp_, DeviceValueType::UINT, nullptr, FL_(collectorMinTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_CollectorMinTemp));
|
||||
register_device_value(TAG_NONE, &collectorShutdown_, DeviceValueType::BOOL, nullptr, FL_(collectorShutdown), DeviceValueUOM::NONE);
|
||||
// register_device_value(TAG_NONE, &tankHeated_, DeviceValueType::BOOL, nullptr, FL_(tankHeated), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_NONE, &collectorShutdown_, DeviceValueType::BOOL, nullptr, FL_(collectorShutdown), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_NONE, &solarPower_, DeviceValueType::ULONG, nullptr, FL_(solarPower), DeviceValueUOM::W);
|
||||
register_device_value(TAG_NONE, &energyLastHour_, DeviceValueType::ULONG, FL_(div10), FL_(energyLastHour), DeviceValueUOM::WH);
|
||||
register_device_value(TAG_NONE, &maxFlow_, DeviceValueType::UINT, FL_(div10), FL_(maxFlow), DeviceValueUOM::LMIN, MAKE_CF_CB(set_SM10MaxFlow));
|
||||
register_device_value(TAG_DEVICE_DATA_WW, &wwMinTemp_, DeviceValueType::UINT, nullptr, FL_(wwMinTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwMinTemp));
|
||||
register_device_value(TAG_NONE, &solarIsEnabled_, DeviceValueType::BOOL, nullptr, FL_(activated), DeviceValueUOM::NONE, MAKE_CF_CB(set_solarEnabled));
|
||||
register_device_value(TAG_NONE, &solarIsEnabled_, DeviceValueType::BOOL, nullptr, FL_(activated), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_solarEnabled));
|
||||
}
|
||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_ISM) {
|
||||
register_device_value(TAG_NONE, &collectorShutdown_, DeviceValueType::BOOL, nullptr, FL_(collectorShutdown), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_NONE, &tankHeated_, DeviceValueType::BOOL, nullptr, FL_(tankHeated), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_NONE, &collectorShutdown_, DeviceValueType::BOOL, nullptr, FL_(collectorShutdown), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_NONE, &tankHeated_, DeviceValueType::BOOL, nullptr, FL_(tankHeated), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_NONE, &energyLastHour_, DeviceValueType::ULONG, FL_(div10), FL_(energyLastHour), DeviceValueUOM::WH);
|
||||
}
|
||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM100) {
|
||||
@@ -119,9 +117,9 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
|
||||
register_device_value(TAG_NONE, &tankBottomTemp2_, DeviceValueType::SHORT, FL_(div10), FL_(tank2BottomTemp), DeviceValueUOM::DEGREES);
|
||||
register_device_value(TAG_NONE, &heatExchangerTemp_, DeviceValueType::SHORT, FL_(div10), FL_(heatExchangerTemp), DeviceValueUOM::DEGREES);
|
||||
register_device_value(TAG_NONE, &cylinderPumpModulation_, DeviceValueType::UINT, nullptr, FL_(cylinderPumpModulation), DeviceValueUOM::PERCENT);
|
||||
register_device_value(TAG_NONE, &valveStatus_, DeviceValueType::BOOL, nullptr, FL_(valveStatus), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_NONE, &tankHeated_, DeviceValueType::BOOL, nullptr, FL_(tankHeated), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_NONE, &collectorShutdown_, DeviceValueType::BOOL, nullptr, FL_(collectorShutdown), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_NONE, &valveStatus_, DeviceValueType::BOOL, nullptr, FL_(valveStatus), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_NONE, &tankHeated_, DeviceValueType::BOOL, nullptr, FL_(tankHeated), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_NONE, &collectorShutdown_, DeviceValueType::BOOL, nullptr, FL_(collectorShutdown), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(
|
||||
TAG_NONE, &collectorMaxTemp_, DeviceValueType::UINT, nullptr, FL_(collectorMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_CollectorMaxTemp));
|
||||
register_device_value(
|
||||
@@ -131,12 +129,12 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
|
||||
register_device_value(TAG_NONE, &energyTotal_, DeviceValueType::ULONG, FL_(div10), FL_(energyTotal), DeviceValueUOM::KWH);
|
||||
|
||||
register_device_value(
|
||||
TAG_NONE, &heatTransferSystem_, DeviceValueType::BOOL, nullptr, FL_(heatTransferSystem), DeviceValueUOM::NONE, MAKE_CF_CB(set_heatTransferSystem));
|
||||
register_device_value(TAG_NONE, &externalTank_, DeviceValueType::BOOL, nullptr, FL_(externalTank), DeviceValueUOM::NONE, MAKE_CF_CB(set_externalTank));
|
||||
TAG_NONE, &heatTransferSystem_, DeviceValueType::BOOL, nullptr, FL_(heatTransferSystem), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_heatTransferSystem));
|
||||
register_device_value(TAG_NONE, &externalTank_, DeviceValueType::BOOL, nullptr, FL_(externalTank), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_externalTank));
|
||||
register_device_value(
|
||||
TAG_NONE, &thermalDisinfect_, DeviceValueType::BOOL, nullptr, FL_(thermalDisinfect), DeviceValueUOM::NONE, MAKE_CF_CB(set_thermalDisinfect));
|
||||
register_device_value(TAG_NONE, &heatMetering_, DeviceValueType::BOOL, nullptr, FL_(heatMetering), DeviceValueUOM::NONE, MAKE_CF_CB(set_heatMetering));
|
||||
register_device_value(TAG_NONE, &solarIsEnabled_, DeviceValueType::BOOL, nullptr, FL_(activated), DeviceValueUOM::NONE, MAKE_CF_CB(set_solarEnabled));
|
||||
TAG_NONE, &thermalDisinfect_, DeviceValueType::BOOL, nullptr, FL_(thermalDisinfect), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_thermalDisinfect));
|
||||
register_device_value(TAG_NONE, &heatMetering_, DeviceValueType::BOOL, nullptr, FL_(heatMetering), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_heatMetering));
|
||||
register_device_value(TAG_NONE, &solarIsEnabled_, DeviceValueType::BOOL, nullptr, FL_(activated), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_solarEnabled));
|
||||
|
||||
// telegram 0x035A
|
||||
register_device_value(
|
||||
@@ -146,21 +144,21 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
|
||||
DeviceValueType::BOOL,
|
||||
nullptr,
|
||||
FL_(solarPumpKick),
|
||||
DeviceValueUOM::NONE,
|
||||
DeviceValueUOM::BOOLEAN,
|
||||
MAKE_CF_CB(set_solarPumpKick)); // pump kick for vacuum collector, 00=off
|
||||
register_device_value(TAG_NONE,
|
||||
&plainWaterMode_,
|
||||
DeviceValueType::BOOL,
|
||||
nullptr,
|
||||
FL_(plainWaterMode),
|
||||
DeviceValueUOM::NONE,
|
||||
DeviceValueUOM::BOOLEAN,
|
||||
MAKE_CF_CB(set_plainWaterMode)); // system does not use antifreeze, 00=off
|
||||
register_device_value(TAG_NONE,
|
||||
&doubleMatchFlow_,
|
||||
DeviceValueType::BOOL,
|
||||
nullptr,
|
||||
FL_(doubleMatchFlow),
|
||||
DeviceValueUOM::NONE,
|
||||
DeviceValueUOM::BOOLEAN,
|
||||
MAKE_CF_CB(set_doubleMatchFlow)); // double Match Flow, 00=off
|
||||
|
||||
// telegram 0x380
|
||||
|
||||
@@ -35,7 +35,7 @@ Switch::Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const
|
||||
register_telegram_type(0x1E, F("WM10TempMessage"), false, MAKE_PF_CB(process_WM10TempMessage));
|
||||
|
||||
register_device_value(TAG_NONE, &id_, DeviceValueType::UINT, nullptr, FL_(ID), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_NONE, &activated_, DeviceValueType::BOOL, nullptr, FL_(activated), DeviceValueUOM::NONE);
|
||||
register_device_value(TAG_NONE, &activated_, DeviceValueType::BOOL, nullptr, FL_(activated), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(TAG_NONE, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES);
|
||||
register_device_value(TAG_NONE, &status_, DeviceValueType::INT, nullptr, FL_(status), DeviceValueUOM::NONE);
|
||||
id_ = product_id;
|
||||
|
||||
@@ -2306,7 +2306,7 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
|
||||
register_device_value(tag, &hc->heatingtype, DeviceValueType::ENUM, FL_(enum_heatingtype), FL_(heatingtype), DeviceValueUOM::NONE);
|
||||
register_device_value(
|
||||
tag, &hc->summer_setmode, DeviceValueType::ENUM, FL_(enum_summermode), FL_(summermode), DeviceValueUOM::NONE, MAKE_CF_CB(set_summermode));
|
||||
register_device_value(tag, &hc->summermode, DeviceValueType::BOOL, nullptr, FL_(summermode), DeviceValueUOM::NONE);
|
||||
register_device_value(tag, &hc->summermode, DeviceValueType::BOOL, nullptr, FL_(summermode), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(
|
||||
tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode), FL_(controlmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_controlmode));
|
||||
register_device_value(tag, &hc->program, DeviceValueType::UINT, nullptr, FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program));
|
||||
@@ -2338,8 +2338,8 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
|
||||
register_device_value(tag, &hc->holidaytemp, DeviceValueType::UINT, FL_(div2), FL_(holidaytemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_holidaytemp));
|
||||
register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, nullptr, FL_(targetflowtemp), DeviceValueUOM::DEGREES);
|
||||
register_device_value(tag, &hc->summertemp, DeviceValueType::UINT, nullptr, FL_(summertemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_summertemp));
|
||||
register_device_value(tag, &hc->summermode, DeviceValueType::BOOL, nullptr, FL_(summermode), DeviceValueUOM::NONE);
|
||||
register_device_value(tag, &hc->holidaymode, DeviceValueType::BOOL, nullptr, FL_(holidaymode), DeviceValueUOM::NONE, MAKE_CF_CB(set_holiday));
|
||||
register_device_value(tag, &hc->summermode, DeviceValueType::BOOL, nullptr, FL_(summermode), DeviceValueUOM::BOOLEAN);
|
||||
register_device_value(tag, &hc->holidaymode, DeviceValueType::BOOL, nullptr, FL_(holidaymode), DeviceValueUOM::BOOLEAN, MAKE_CF_CB(set_holiday));
|
||||
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, nullptr, FL_(nofrosttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nofrosttemp));
|
||||
register_device_value(tag, &hc->roominfluence, DeviceValueType::UINT, nullptr, FL_(roominfluence), DeviceValueUOM::NONE, MAKE_CF_CB(set_roominfluence));
|
||||
register_device_value(tag, &hc->minflowtemp, DeviceValueType::UINT, nullptr, FL_(minflowtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_minflowtemp));
|
||||
|
||||
@@ -39,7 +39,8 @@ static const __FlashStringHelper * DeviceValueUOM_s[] __attribute__((__aligned__
|
||||
F_(kb),
|
||||
F_(seconds),
|
||||
F_(dbm),
|
||||
F_(num)
|
||||
F_(num),
|
||||
F_(bool)
|
||||
|
||||
};
|
||||
|
||||
@@ -543,7 +544,7 @@ std::string EMSdevice::get_value_uom(const char * key) {
|
||||
for (const auto & dv : devicevalues_) {
|
||||
if (dv.full_name != nullptr) {
|
||||
if (uuid::read_flash_string(dv.full_name) == p) {
|
||||
// ignore TIME since "minutes" is already included
|
||||
// ignore TIME since "minutes" is already added to the string value
|
||||
if ((dv.uom == DeviceValueUOM::NONE) || (dv.uom == DeviceValueUOM::MINUTES)) {
|
||||
break;
|
||||
}
|
||||
@@ -555,37 +556,34 @@ std::string EMSdevice::get_value_uom(const char * key) {
|
||||
return std::string{}; // not found
|
||||
}
|
||||
|
||||
// prepare array of device values, as 3 elements serialized (name, value, uom) in array to send to Web UI
|
||||
// returns number of elements
|
||||
bool EMSdevice::generate_values_json_web(JsonObject & json) {
|
||||
// prepare array of device values used for the Web UI
|
||||
// v = value, u=uom, n=name, c=cmd
|
||||
void EMSdevice::generate_values_json_web(JsonObject & json) {
|
||||
json["name"] = to_string_short();
|
||||
JsonArray data = json.createNestedArray("data");
|
||||
|
||||
uint8_t num_elements = 0;
|
||||
|
||||
for (const auto & dv : devicevalues_) {
|
||||
// ignore if full_name empty
|
||||
if (dv.full_name != nullptr) {
|
||||
JsonObject obj; // create the object, if needed
|
||||
|
||||
// handle Booleans (true, false)
|
||||
if ((dv.type == DeviceValueType::BOOL) && Helpers::hasValue(*(uint8_t *)(dv.value_p), EMS_VALUE_BOOL)) {
|
||||
// see if we have options for the bool's
|
||||
if (dv.options_size == 2) {
|
||||
data.add(*(uint8_t *)(dv.value_p) ? dv.options[0] : dv.options[1]);
|
||||
} else {
|
||||
// always render booleans as on or off
|
||||
data.add(*(uint8_t *)(dv.value_p) ? F_(on) : F_(off));
|
||||
}
|
||||
obj = data.createNestedObject();
|
||||
obj["v"] = *(bool *)(dv.value_p);
|
||||
}
|
||||
|
||||
// handle TEXT strings
|
||||
else if ((dv.type == DeviceValueType::TEXT) && (Helpers::hasValue((char *)(dv.value_p)))) {
|
||||
data.add((char *)(dv.value_p));
|
||||
obj = data.createNestedObject();
|
||||
obj["v"] = (char *)(dv.value_p);
|
||||
}
|
||||
|
||||
// handle ENUMs
|
||||
else if ((dv.type == DeviceValueType::ENUM) && Helpers::hasValue(*(uint8_t *)(dv.value_p))) {
|
||||
if (*(uint8_t *)(dv.value_p) < dv.options_size) {
|
||||
data.add(dv.options[*(uint8_t *)(dv.value_p)]);
|
||||
obj = data.createNestedObject();
|
||||
obj["v"] = dv.options[*(uint8_t *)(dv.value_p)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,83 +594,55 @@ bool EMSdevice::generate_values_json_web(JsonObject & json) {
|
||||
// the nested if's is necessary due to the way the ArduinoJson templates are pre-processed by the compiler
|
||||
uint8_t divider = (dv.options_size == 1) ? Helpers::atoint(uuid::read_flash_string(dv.options[0]).c_str()) : 0;
|
||||
|
||||
// INT
|
||||
if ((dv.type == DeviceValueType::INT) && Helpers::hasValue(*(int8_t *)(dv.value_p))) {
|
||||
if (divider) {
|
||||
data.add(Helpers::round2(*(int8_t *)(dv.value_p), divider));
|
||||
} else {
|
||||
data.add(*(int8_t *)(dv.value_p));
|
||||
}
|
||||
obj = data.createNestedObject();
|
||||
obj["v"] = (divider) ? Helpers::round2(*(int8_t *)(dv.value_p), divider) : *(int8_t *)(dv.value_p);
|
||||
} else if ((dv.type == DeviceValueType::UINT) && Helpers::hasValue(*(uint8_t *)(dv.value_p))) {
|
||||
if (divider) {
|
||||
data.add(Helpers::round2(*(uint8_t *)(dv.value_p), divider));
|
||||
} else {
|
||||
data.add(*(uint8_t *)(dv.value_p));
|
||||
}
|
||||
obj = data.createNestedObject();
|
||||
obj["v"] = (divider) ? Helpers::round2(*(uint8_t *)(dv.value_p), divider) : *(uint8_t *)(dv.value_p);
|
||||
} else if ((dv.type == DeviceValueType::SHORT) && Helpers::hasValue(*(int16_t *)(dv.value_p))) {
|
||||
if (divider) {
|
||||
data.add(Helpers::round2(*(int16_t *)(dv.value_p), divider));
|
||||
} else {
|
||||
data.add(*(int16_t *)(dv.value_p));
|
||||
}
|
||||
obj = data.createNestedObject();
|
||||
obj["v"] = (divider) ? Helpers::round2(*(int16_t *)(dv.value_p), divider) : *(int16_t *)(dv.value_p);
|
||||
} else if ((dv.type == DeviceValueType::USHORT) && Helpers::hasValue(*(uint16_t *)(dv.value_p))) {
|
||||
if (divider) {
|
||||
data.add(Helpers::round2(*(uint16_t *)(dv.value_p), divider));
|
||||
} else {
|
||||
data.add(*(uint16_t *)(dv.value_p));
|
||||
}
|
||||
obj = data.createNestedObject();
|
||||
obj["v"] = (divider) ? Helpers::round2(*(uint16_t *)(dv.value_p), divider) : *(uint16_t *)(dv.value_p);
|
||||
} else if ((dv.type == DeviceValueType::ULONG) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
||||
if (divider) {
|
||||
data.add(Helpers::round2(*(uint32_t *)(dv.value_p), divider));
|
||||
} else {
|
||||
data.add(*(uint32_t *)(dv.value_p));
|
||||
}
|
||||
obj = data.createNestedObject();
|
||||
obj["v"] = (divider) ? Helpers::round2(*(uint32_t *)(dv.value_p), divider) : *(uint32_t *)(dv.value_p);
|
||||
} else if ((dv.type == DeviceValueType::TIME) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
||||
uint32_t time_value = *(uint32_t *)(dv.value_p);
|
||||
time_value = (divider) ? time_value / divider : time_value; // sometimes we need to divide by 60
|
||||
char time_s[40];
|
||||
snprintf_P(time_s, 40, PSTR("%d days %d hours %d minutes"), (time_value / 1440), ((time_value % 1440) / 60), (time_value % 60));
|
||||
data.add(time_s);
|
||||
obj = data.createNestedObject();
|
||||
obj["v"] = (divider) ? time_value / divider : time_value; // sometimes we need to divide by 60
|
||||
}
|
||||
}
|
||||
|
||||
// check if we've added a data element by comparing the size
|
||||
// then add the remaining elements
|
||||
uint8_t sz = data.size();
|
||||
if (sz > num_elements) {
|
||||
// check if we've added a data element then add the remaining elements
|
||||
if (obj.containsKey("v")) {
|
||||
// add the unit of measure (uom)
|
||||
if (dv.uom == DeviceValueUOM::MINUTES) {
|
||||
data.add(nullptr); // use null for time/date
|
||||
} else {
|
||||
data.add(uom_to_string(dv.uom));
|
||||
}
|
||||
obj["u"] = dv.uom;
|
||||
|
||||
// add name, prefixing the tag if it exists
|
||||
if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) {
|
||||
data.add(dv.full_name);
|
||||
obj["n"] = dv.full_name;
|
||||
} else {
|
||||
char name[50];
|
||||
snprintf_P(name, sizeof(name), "(%s) %s", tag_to_string(dv.tag).c_str(), uuid::read_flash_string(dv.full_name).c_str());
|
||||
data.add(name);
|
||||
obj["n"] = name;
|
||||
}
|
||||
|
||||
// add the name of the Command function if it exists
|
||||
if (dv.has_cmd) {
|
||||
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
||||
data.add(tag_to_string(dv.tag) + "/" + uuid::read_flash_string(dv.short_name));
|
||||
obj["c"] = tag_to_string(dv.tag) + "/" + uuid::read_flash_string(dv.short_name);
|
||||
} else {
|
||||
data.add(dv.short_name);
|
||||
obj["c"] = dv.short_name;
|
||||
}
|
||||
} else {
|
||||
data.add("");
|
||||
obj["c"] = "";
|
||||
}
|
||||
|
||||
num_elements = sz + 3; // increase count by 3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (num_elements != 0);
|
||||
}
|
||||
|
||||
bool EMSdevice::get_value_info(JsonObject & root, const char * cmd, const int8_t id) {
|
||||
@@ -778,9 +748,7 @@ bool EMSdevice::get_value_info(JsonObject & root, const char * cmd, const int8_t
|
||||
break;
|
||||
case DeviceValueType::BOOL: {
|
||||
if (Helpers::hasValue(*(uint8_t *)(dv.value_p), EMS_VALUE_BOOL)) {
|
||||
if (dv.options_size == 2) {
|
||||
json[value] = (bool)(*(uint8_t *)(dv.value_p)) ? dv.options[0] : dv.options[1];
|
||||
} else if (Mqtt::bool_format() == BOOL_FORMAT_ONOFF) {
|
||||
if (Mqtt::bool_format() == BOOL_FORMAT_ONOFF) {
|
||||
json[value] = (bool)(*(uint8_t *)(dv.value_p)) ? F_(on) : F_(off);
|
||||
} else if (Mqtt::bool_format() == BOOL_FORMAT_ONOFF_CAP) {
|
||||
json[value] = (bool)(*(uint8_t *)(dv.value_p)) ? F_(ON) : F_(OFF);
|
||||
@@ -794,10 +762,8 @@ bool EMSdevice::get_value_info(JsonObject & root, const char * cmd, const int8_t
|
||||
json[min] = 0;
|
||||
json[max] = 1;
|
||||
JsonArray enum_ = json.createNestedArray(F_(enum));
|
||||
if (dv.options_size == 2) {
|
||||
enum_.add(dv.options[1]);
|
||||
enum_.add(dv.options[0]);
|
||||
} else if (Mqtt::bool_format() == BOOL_FORMAT_ONOFF) {
|
||||
|
||||
if (Mqtt::bool_format() == BOOL_FORMAT_ONOFF) {
|
||||
enum_.add(F_(off));
|
||||
enum_.add(F_(on));
|
||||
} else if (Mqtt::bool_format() == BOOL_FORMAT_ONOFF_CAP) {
|
||||
@@ -885,31 +851,26 @@ bool EMSdevice::generate_values_json(JsonObject & root, const uint8_t tag_filter
|
||||
|
||||
// handle Booleans (true, false)
|
||||
if ((dv.type == DeviceValueType::BOOL) && Helpers::hasValue(*(uint8_t *)(dv.value_p), EMS_VALUE_BOOL)) {
|
||||
// see if we have options for the bool's
|
||||
if (dv.options_size == 2 && Mqtt::bool_format() != BOOL_FORMAT_10) {
|
||||
json[name] = *(uint8_t *)(dv.value_p) ? dv.options[0] : dv.options[1];
|
||||
// see how to render the value depending on the setting
|
||||
// when in console mode we always use on and off
|
||||
if ((Mqtt::bool_format() == BOOL_FORMAT_ONOFF) || console) {
|
||||
// on or off as strings
|
||||
json[name] = *(uint8_t *)(dv.value_p) ? F_(on) : F_(off);
|
||||
has_value = true;
|
||||
} else if (Mqtt::bool_format() == BOOL_FORMAT_ONOFF_CAP) {
|
||||
// on or off as strings
|
||||
json[name] = *(uint8_t *)(dv.value_p) ? F_(ON) : F_(OFF);
|
||||
has_value = true;
|
||||
} else if (Mqtt::bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
||||
// true or false values (as real booleans, not strings)
|
||||
json[name] = (bool)(*(uint8_t *)(dv.value_p)) ? true : false;
|
||||
has_value = true;
|
||||
} else {
|
||||
// see how to render the value depending on the setting
|
||||
// when in console mode we always use on and off
|
||||
if ((Mqtt::bool_format() == BOOL_FORMAT_ONOFF) || console) {
|
||||
// on or off as strings
|
||||
json[name] = *(uint8_t *)(dv.value_p) ? F_(on) : F_(off);
|
||||
has_value = true;
|
||||
} else if (Mqtt::bool_format() == BOOL_FORMAT_ONOFF_CAP) {
|
||||
// on or off as strings
|
||||
json[name] = *(uint8_t *)(dv.value_p) ? F_(ON) : F_(OFF);
|
||||
has_value = true;
|
||||
} else if (Mqtt::bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
||||
// true or false values (as real booleans, not strings)
|
||||
json[name] = (bool)(*(uint8_t *)(dv.value_p)) ? true : false;
|
||||
has_value = true;
|
||||
} else {
|
||||
// numerical 1 or 0
|
||||
json[name] = (uint8_t)(*(uint8_t *)(dv.value_p)) ? 1 : 0;
|
||||
has_value = true;
|
||||
}
|
||||
// numerical 1 or 0
|
||||
json[name] = (uint8_t)(*(uint8_t *)(dv.value_p)) ? 1 : 0;
|
||||
has_value = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// handle TEXT strings
|
||||
|
||||
@@ -48,22 +48,23 @@ enum DeviceValueType : uint8_t {
|
||||
// sequence is important!
|
||||
enum DeviceValueUOM : uint8_t {
|
||||
|
||||
NONE = 0,
|
||||
DEGREES,
|
||||
PERCENT,
|
||||
LMIN,
|
||||
KWH,
|
||||
WH,
|
||||
HOURS,
|
||||
MINUTES,
|
||||
UA,
|
||||
BAR,
|
||||
KW,
|
||||
W,
|
||||
KB,
|
||||
SECONDS,
|
||||
DBM,
|
||||
NUM
|
||||
NONE = 0, // 0
|
||||
DEGREES, // 1
|
||||
PERCENT, // 2
|
||||
LMIN, // 3
|
||||
KWH, // 4
|
||||
WH, // 5
|
||||
HOURS, // 6
|
||||
MINUTES, // 7
|
||||
UA, // 8
|
||||
BAR, // 9
|
||||
KW, // 10
|
||||
W, // 11
|
||||
KB, // 12
|
||||
SECONDS, // 13
|
||||
DBM, // 14
|
||||
NUM, // 15
|
||||
BOOLEAN // 16
|
||||
|
||||
};
|
||||
|
||||
@@ -244,7 +245,7 @@ class EMSdevice {
|
||||
std::string get_value_uom(const char * key);
|
||||
bool get_value_info(JsonObject & root, const char * cmd, const int8_t id);
|
||||
bool generate_values_json(JsonObject & json, const uint8_t tag_filter, const bool nested, const bool console = false);
|
||||
bool generate_values_json_web(JsonObject & json);
|
||||
void generate_values_json_web(JsonObject & json);
|
||||
|
||||
void register_device_value(uint8_t tag,
|
||||
void * value_p,
|
||||
|
||||
@@ -172,6 +172,7 @@ MAKE_PSTR(kb, "KB")
|
||||
MAKE_PSTR(seconds, "seconds")
|
||||
MAKE_PSTR(dbm, "dBm")
|
||||
MAKE_PSTR(num, " ") // this is hack so HA renders numbers correctly
|
||||
MAKE_PSTR(bool, " ") // this is hack so HA renders numbers correctly
|
||||
|
||||
// TAG mapping - maps to DeviceValueTAG_s in emsdevice.cpp
|
||||
// use empty string if want to suppress showing tags
|
||||
@@ -220,7 +221,7 @@ MAKE_PSTR_WORD(3x3min)
|
||||
MAKE_PSTR_WORD(4x3min)
|
||||
MAKE_PSTR_WORD(5x3min)
|
||||
MAKE_PSTR_WORD(6x3min)
|
||||
MAKE_PSTR_WORD(continuos)
|
||||
MAKE_PSTR_WORD(continuous)
|
||||
MAKE_PSTR(3wayvalve, "3-way valve")
|
||||
MAKE_PSTR(chargepump, "charge pump")
|
||||
MAKE_PSTR_WORD(hot)
|
||||
@@ -235,7 +236,7 @@ MAKE_PSTR_WORD(error)
|
||||
|
||||
// boiler lists
|
||||
MAKE_PSTR_LIST(enum_off_time_date, F_(off), F_(time), F_(date))
|
||||
MAKE_PSTR_LIST(enum_freq, F_(off), F_(1x3min), F_(2x3min), F_(3x3min), F_(4x3min), F_(5x3min), F_(6x3min), F_(continuos))
|
||||
MAKE_PSTR_LIST(enum_freq, F_(off), F_(1x3min), F_(2x3min), F_(3x3min), F_(4x3min), F_(5x3min), F_(6x3min), F_(continuous))
|
||||
MAKE_PSTR_LIST(enum_charge, F_(3wayvalve), F_(chargepump))
|
||||
MAKE_PSTR_LIST(enum_comfort, F_(hot), F_(eco), F_(intelligent))
|
||||
MAKE_PSTR_LIST(enum_flow, F_(off), F_(flow), F_(bufferedflow), F_(buffer), F_(layeredbuffer))
|
||||
|
||||
@@ -333,29 +333,30 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd) {
|
||||
run_test("boiler");
|
||||
run_test("thermostat");
|
||||
|
||||
// test call
|
||||
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE_DYN);
|
||||
JsonObject json = doc.to<JsonObject>();
|
||||
Command::call(EMSdevice::DeviceType::BOILER, "info", nullptr, -1, json);
|
||||
#if defined(EMSESP_STANDALONE)
|
||||
Serial.print(COLOR_YELLOW);
|
||||
if (json.size() != 0) {
|
||||
serializeJson(doc, Serial);
|
||||
}
|
||||
shell.println();
|
||||
Serial.print(COLOR_RESET);
|
||||
#endif
|
||||
|
||||
DynamicJsonDocument doc(8000); // some absurb high number
|
||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||
if (emsdevice) {
|
||||
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE_DYN);
|
||||
doc.clear();
|
||||
JsonObject json = doc.to<JsonObject>();
|
||||
Command::call(emsdevice->device_type(), "info", nullptr, -1, json);
|
||||
|
||||
Serial.print(COLOR_YELLOW);
|
||||
if (json.size() != 0) {
|
||||
serializeJson(doc, Serial);
|
||||
}
|
||||
shell.println();
|
||||
Serial.print(COLOR_RESET);
|
||||
|
||||
|
||||
doc.clear();
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
emsdevice->generate_values_json_web(root);
|
||||
|
||||
#if defined(EMSESP_STANDALONE)
|
||||
Serial.print(COLOR_BRIGHT_MAGENTA);
|
||||
serializeJson(doc, Serial);
|
||||
Serial.print(COLOR_RESET);
|
||||
Serial.println();
|
||||
Serial.print("** memoryUsage=");
|
||||
Serial.print(doc.memoryUsage());
|
||||
@@ -364,10 +365,9 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd) {
|
||||
Serial.print(" measureJson=");
|
||||
Serial.print(measureJson(doc));
|
||||
Serial.println(" **");
|
||||
Serial.print(COLOR_RESET);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@ namespace emsesp {
|
||||
// #define EMSESP_DEBUG_DEFAULT "thermostat"
|
||||
// #define EMSESP_DEBUG_DEFAULT "solar"
|
||||
// #define EMSESP_DEBUG_DEFAULT "mixer"
|
||||
// #define EMSESP_DEBUG_DEFAULT "web"
|
||||
#define EMSESP_DEBUG_DEFAULT "general"
|
||||
#define EMSESP_DEBUG_DEFAULT "web"
|
||||
// #define EMSESP_DEBUG_DEFAULT "general"
|
||||
// #define EMSESP_DEBUG_DEFAULT "boiler"
|
||||
// #define EMSESP_DEBUG_DEFAULT "mqtt2"
|
||||
// #define EMSESP_DEBUG_DEFAULT "mqtt_nested"
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define EMSESP_APP_VERSION "3.1.1b4"
|
||||
#define EMSESP_APP_VERSION "3.1.1b5"
|
||||
|
||||
Reference in New Issue
Block a user