mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-03-21 17:16:34 +03:00
Compare commits
32 Commits
16b6bef393
...
32474d10ce
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32474d10ce | ||
|
|
7c3de25c20 | ||
|
|
f75b7b1a59 | ||
|
|
a3e01b8a3b | ||
|
|
6c9a9b8632 | ||
|
|
3fba75868f | ||
|
|
8dee390d75 | ||
|
|
dc838639b2 | ||
|
|
3fd05c8eb7 | ||
|
|
5f0df140b0 | ||
|
|
b98cbd3ec5 | ||
|
|
18d67d088e | ||
|
|
0bf60394fe | ||
|
|
cec5ffd547 | ||
|
|
026ea4450e | ||
|
|
9a1dd5bb98 | ||
|
|
fbc42fbb15 | ||
|
|
5613cde00f | ||
|
|
d65d6f49cd | ||
|
|
c9bc18cf4b | ||
|
|
9179127bce | ||
|
|
0dc3fd43e9 | ||
|
|
b0d490036f | ||
|
|
c28b098c65 | ||
|
|
4a6ccce09a | ||
|
|
5053ad08dd | ||
|
|
72b4809ed8 | ||
|
|
6799fe5189 | ||
|
|
12635ff4a5 | ||
|
|
5908fd9d9c | ||
|
|
5c07a2c0cc | ||
|
|
f5048abae7 |
@@ -49,6 +49,7 @@ For more details go to [docs.emsesp.org](https://docs.emsesp.org/).
|
|||||||
- ventilation bypass state from telegram 0x55C [#1197](https://github.com/emsesp/EMS-ESP32/issues/1197)
|
- ventilation bypass state from telegram 0x55C [#1197](https://github.com/emsesp/EMS-ESP32/issues/1197)
|
||||||
- set selflowtemp for ems+ boilers [#2641](https://github.com/emsesp/EMS-ESP32/discussions/2641)
|
- set selflowtemp for ems+ boilers [#2641](https://github.com/emsesp/EMS-ESP32/discussions/2641)
|
||||||
- syslog timestamp [#2704](https://github.com/emsesp/EMS-ESP32/issues/2704)
|
- syslog timestamp [#2704](https://github.com/emsesp/EMS-ESP32/issues/2704)
|
||||||
|
- fixed FS format command [#2720](https://github.com/emsesp/EMS-ESP32/discussions/2720)
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
@@ -57,4 +58,7 @@ For more details go to [docs.emsesp.org](https://docs.emsesp.org/).
|
|||||||
- updated core libraries like AsyncTCP, AsyncWebServer and Modbus
|
- updated core libraries like AsyncTCP, AsyncWebServer and Modbus
|
||||||
- remove command `scan deep`
|
- remove command `scan deep`
|
||||||
- ignore repeated `forceheatingoff` commands [#2641](https://github.com/emsesp/EMS-ESP32/discussions/2641)
|
- ignore repeated `forceheatingoff` commands [#2641](https://github.com/emsesp/EMS-ESP32/discussions/2641)
|
||||||
- optimized web for performance
|
- optimized web for better performance by adding lazy loading and caching
|
||||||
|
- internal system analog sensors (core_voltage, supply_voltage and gateway_temperature) cannot be accidentally removed
|
||||||
|
- double click button reconnects EMS-ESP to AP
|
||||||
|
- place system message command in side scheduler loop to reduce stack memory usage by 2KB
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
"rollup-plugin-visualizer": "^6.0.5",
|
"rollup-plugin-visualizer": "^6.0.5",
|
||||||
"terser": "^5.44.1",
|
"terser": "^5.44.1",
|
||||||
"typescript-eslint": "^8.46.3",
|
"typescript-eslint": "^8.46.3",
|
||||||
"vite": "^7.2.0",
|
"vite": "^7.2.2",
|
||||||
"vite-plugin-imagemin": "^0.6.1",
|
"vite-plugin-imagemin": "^0.6.1",
|
||||||
"vite-tsconfig-paths": "^5.1.4"
|
"vite-tsconfig-paths": "^5.1.4"
|
||||||
},
|
},
|
||||||
|
|||||||
254
interface/pnpm-lock.yaml
generated
254
interface/pnpm-lock.yaml
generated
@@ -83,7 +83,7 @@ importers:
|
|||||||
version: 9.39.1
|
version: 9.39.1
|
||||||
'@preact/preset-vite':
|
'@preact/preset-vite':
|
||||||
specifier: ^2.10.2
|
specifier: ^2.10.2
|
||||||
version: 2.10.2(@babel/core@7.28.5)(preact@10.27.2)(vite@7.2.0(@types/node@24.10.0)(terser@5.44.1))
|
version: 2.10.2(@babel/core@7.28.5)(preact@10.27.2)(vite@7.2.2(@types/node@24.10.0)(terser@5.44.1))
|
||||||
'@trivago/prettier-plugin-sort-imports':
|
'@trivago/prettier-plugin-sort-imports':
|
||||||
specifier: ^6.0.0
|
specifier: ^6.0.0
|
||||||
version: 6.0.0(prettier@3.6.2)
|
version: 6.0.0(prettier@3.6.2)
|
||||||
@@ -113,7 +113,7 @@ importers:
|
|||||||
version: 3.6.2
|
version: 3.6.2
|
||||||
rollup-plugin-visualizer:
|
rollup-plugin-visualizer:
|
||||||
specifier: ^6.0.5
|
specifier: ^6.0.5
|
||||||
version: 6.0.5(rollup@4.52.5)
|
version: 6.0.5(rollup@4.53.1)
|
||||||
terser:
|
terser:
|
||||||
specifier: ^5.44.1
|
specifier: ^5.44.1
|
||||||
version: 5.44.1
|
version: 5.44.1
|
||||||
@@ -121,14 +121,14 @@ importers:
|
|||||||
specifier: ^8.46.3
|
specifier: ^8.46.3
|
||||||
version: 8.46.3(eslint@9.39.1)(typescript@5.9.3)
|
version: 8.46.3(eslint@9.39.1)(typescript@5.9.3)
|
||||||
vite:
|
vite:
|
||||||
specifier: ^7.2.0
|
specifier: ^7.2.2
|
||||||
version: 7.2.0(@types/node@24.10.0)(terser@5.44.1)
|
version: 7.2.2(@types/node@24.10.0)(terser@5.44.1)
|
||||||
vite-plugin-imagemin:
|
vite-plugin-imagemin:
|
||||||
specifier: ^0.6.1
|
specifier: ^0.6.1
|
||||||
version: 0.6.1(vite@7.2.0(@types/node@24.10.0)(terser@5.44.1))
|
version: 0.6.1(vite@7.2.2(@types/node@24.10.0)(terser@5.44.1))
|
||||||
vite-tsconfig-paths:
|
vite-tsconfig-paths:
|
||||||
specifier: ^5.1.4
|
specifier: ^5.1.4
|
||||||
version: 5.1.4(typescript@5.9.3)(vite@7.2.0(@types/node@24.10.0)(terser@5.44.1))
|
version: 5.1.4(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(terser@5.44.1))
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
@@ -679,113 +679,113 @@ packages:
|
|||||||
resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==}
|
resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==}
|
||||||
engines: {node: '>= 8.0.0'}
|
engines: {node: '>= 8.0.0'}
|
||||||
|
|
||||||
'@rollup/rollup-android-arm-eabi@4.52.5':
|
'@rollup/rollup-android-arm-eabi@4.53.1':
|
||||||
resolution: {integrity: sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==}
|
resolution: {integrity: sha512-bxZtughE4VNVJlL1RdoSE545kc4JxL7op57KKoi59/gwuU5rV6jLWFXXc8jwgFoT6vtj+ZjO+Z2C5nrY0Cl6wA==}
|
||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
|
||||||
'@rollup/rollup-android-arm64@4.52.5':
|
'@rollup/rollup-android-arm64@4.53.1':
|
||||||
resolution: {integrity: sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==}
|
resolution: {integrity: sha512-44a1hreb02cAAfAKmZfXVercPFaDjqXCK+iKeVOlJ9ltvnO6QqsBHgKVPTu+MJHSLLeMEUbeG2qiDYgbFPU48g==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
|
||||||
'@rollup/rollup-darwin-arm64@4.52.5':
|
'@rollup/rollup-darwin-arm64@4.53.1':
|
||||||
resolution: {integrity: sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==}
|
resolution: {integrity: sha512-usmzIgD0rf1syoOZ2WZvy8YpXK5G1V3btm3QZddoGSa6mOgfXWkkv+642bfUUldomgrbiLQGrPryb7DXLovPWQ==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@rollup/rollup-darwin-x64@4.52.5':
|
'@rollup/rollup-darwin-x64@4.53.1':
|
||||||
resolution: {integrity: sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==}
|
resolution: {integrity: sha512-is3r/k4vig2Gt8mKtTlzzyaSQ+hd87kDxiN3uDSDwggJLUV56Umli6OoL+/YZa/KvtdrdyNfMKHzL/P4siOOmg==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@rollup/rollup-freebsd-arm64@4.52.5':
|
'@rollup/rollup-freebsd-arm64@4.53.1':
|
||||||
resolution: {integrity: sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==}
|
resolution: {integrity: sha512-QJ1ksgp/bDJkZB4daldVmHaEQkG4r8PUXitCOC2WRmRaSaHx5RwPoI3DHVfXKwDkB+Sk6auFI/+JHacTekPRSw==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [freebsd]
|
os: [freebsd]
|
||||||
|
|
||||||
'@rollup/rollup-freebsd-x64@4.52.5':
|
'@rollup/rollup-freebsd-x64@4.53.1':
|
||||||
resolution: {integrity: sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==}
|
resolution: {integrity: sha512-J6ma5xgAzvqsnU6a0+jgGX/gvoGokqpkx6zY4cWizRrm0ffhHDpJKQgC8dtDb3+MqfZDIqs64REbfHDMzxLMqQ==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [freebsd]
|
os: [freebsd]
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm-gnueabihf@4.52.5':
|
'@rollup/rollup-linux-arm-gnueabihf@4.53.1':
|
||||||
resolution: {integrity: sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==}
|
resolution: {integrity: sha512-JzWRR41o2U3/KMNKRuZNsDUAcAVUYhsPuMlx5RUldw0E4lvSIXFUwejtYz1HJXohUmqs/M6BBJAUBzKXZVddbg==}
|
||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm-musleabihf@4.52.5':
|
'@rollup/rollup-linux-arm-musleabihf@4.53.1':
|
||||||
resolution: {integrity: sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==}
|
resolution: {integrity: sha512-L8kRIrnfMrEoHLHtHn+4uYA52fiLDEDyezgxZtGUTiII/yb04Krq+vk3P2Try+Vya9LeCE9ZHU8CXD6J9EhzHQ==}
|
||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm64-gnu@4.52.5':
|
'@rollup/rollup-linux-arm64-gnu@4.53.1':
|
||||||
resolution: {integrity: sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==}
|
resolution: {integrity: sha512-ysAc0MFRV+WtQ8li8hi3EoFi7us6d1UzaS/+Dp7FYZfg3NdDljGMoVyiIp6Ucz7uhlYDBZ/zt6XI0YEZbUO11Q==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm64-musl@4.52.5':
|
'@rollup/rollup-linux-arm64-musl@4.53.1':
|
||||||
resolution: {integrity: sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==}
|
resolution: {integrity: sha512-UV6l9MJpDbDZZ/fJvqNcvO1PcivGEf1AvKuTcHoLjVZVFeAMygnamCTDikCVMRnA+qJe+B3pSbgX2+lBMqgBhA==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rollup/rollup-linux-loong64-gnu@4.52.5':
|
'@rollup/rollup-linux-loong64-gnu@4.53.1':
|
||||||
resolution: {integrity: sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==}
|
resolution: {integrity: sha512-UDUtelEprkA85g95Q+nj3Xf0M4hHa4DiJ+3P3h4BuGliY4NReYYqwlc0Y8ICLjN4+uIgCEvaygYlpf0hUj90Yg==}
|
||||||
cpu: [loong64]
|
cpu: [loong64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rollup/rollup-linux-ppc64-gnu@4.52.5':
|
'@rollup/rollup-linux-ppc64-gnu@4.53.1':
|
||||||
resolution: {integrity: sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==}
|
resolution: {integrity: sha512-vrRn+BYhEtNOte/zbc2wAUQReJXxEx2URfTol6OEfY2zFEUK92pkFBSXRylDM7aHi+YqEPJt9/ABYzmcrS4SgQ==}
|
||||||
cpu: [ppc64]
|
cpu: [ppc64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rollup/rollup-linux-riscv64-gnu@4.52.5':
|
'@rollup/rollup-linux-riscv64-gnu@4.53.1':
|
||||||
resolution: {integrity: sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==}
|
resolution: {integrity: sha512-gto/1CxHyi4A7YqZZNznQYrVlPSaodOBPKM+6xcDSCMVZN/Fzb4K+AIkNz/1yAYz9h3Ng+e2fY9H6bgawVq17w==}
|
||||||
cpu: [riscv64]
|
cpu: [riscv64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rollup/rollup-linux-riscv64-musl@4.52.5':
|
'@rollup/rollup-linux-riscv64-musl@4.53.1':
|
||||||
resolution: {integrity: sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==}
|
resolution: {integrity: sha512-KZ6Vx7jAw3aLNjFR8eYVcQVdFa/cvBzDNRFM3z7XhNNunWjA03eUrEwJYPk0G8V7Gs08IThFKcAPS4WY/ybIrQ==}
|
||||||
cpu: [riscv64]
|
cpu: [riscv64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rollup/rollup-linux-s390x-gnu@4.52.5':
|
'@rollup/rollup-linux-s390x-gnu@4.53.1':
|
||||||
resolution: {integrity: sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==}
|
resolution: {integrity: sha512-HvEixy2s/rWNgpwyKpXJcHmE7om1M89hxBTBi9Fs6zVuLU4gOrEMQNbNsN/tBVIMbLyysz/iwNiGtMOpLAOlvA==}
|
||||||
cpu: [s390x]
|
cpu: [s390x]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rollup/rollup-linux-x64-gnu@4.52.5':
|
'@rollup/rollup-linux-x64-gnu@4.53.1':
|
||||||
resolution: {integrity: sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==}
|
resolution: {integrity: sha512-E/n8x2MSjAQgjj9IixO4UeEUeqXLtiA7pyoXCFYLuXpBA/t2hnbIdxHfA7kK9BFsYAoNU4st1rHYdldl8dTqGA==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rollup/rollup-linux-x64-musl@4.52.5':
|
'@rollup/rollup-linux-x64-musl@4.53.1':
|
||||||
resolution: {integrity: sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==}
|
resolution: {integrity: sha512-IhJ087PbLOQXCN6Ui/3FUkI9pWNZe/Z7rEIVOzMsOs1/HSAECCvSZ7PkIbkNqL/AZn6WbZvnoVZw/qwqYMo4/w==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@rollup/rollup-openharmony-arm64@4.52.5':
|
'@rollup/rollup-openharmony-arm64@4.53.1':
|
||||||
resolution: {integrity: sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==}
|
resolution: {integrity: sha512-0++oPNgLJHBblreu0SFM7b3mAsBJBTY0Ksrmu9N6ZVrPiTkRgda52mWR7TKhHAsUb9noCjFvAw9l6ZO1yzaVbA==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [openharmony]
|
os: [openharmony]
|
||||||
|
|
||||||
'@rollup/rollup-win32-arm64-msvc@4.52.5':
|
'@rollup/rollup-win32-arm64-msvc@4.53.1':
|
||||||
resolution: {integrity: sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==}
|
resolution: {integrity: sha512-VJXivz61c5uVdbmitLkDlbcTk9Or43YC2QVLRkqp86QoeFSqI81bNgjhttqhKNMKnQMWnecOCm7lZz4s+WLGpQ==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@rollup/rollup-win32-ia32-msvc@4.52.5':
|
'@rollup/rollup-win32-ia32-msvc@4.53.1':
|
||||||
resolution: {integrity: sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==}
|
resolution: {integrity: sha512-NmZPVTUOitCXUH6erJDzTQ/jotYw4CnkMDjCYRxNHVD9bNyfrGoIse684F9okwzKCV4AIHRbUkeTBc9F2OOH5Q==}
|
||||||
cpu: [ia32]
|
cpu: [ia32]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@rollup/rollup-win32-x64-gnu@4.52.5':
|
'@rollup/rollup-win32-x64-gnu@4.53.1':
|
||||||
resolution: {integrity: sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==}
|
resolution: {integrity: sha512-2SNj7COIdAf6yliSpLdLG8BEsp5lgzRehgfkP0Av8zKfQFKku6JcvbobvHASPJu4f3BFxej5g+HuQPvqPhHvpQ==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@rollup/rollup-win32-x64-msvc@4.52.5':
|
'@rollup/rollup-win32-x64-msvc@4.53.1':
|
||||||
resolution: {integrity: sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==}
|
resolution: {integrity: sha512-rLarc1Ofcs3DHtgSzFO31pZsCh8g05R2azN1q3fF+H423Co87My0R+tazOEvYVKXSLh8C4LerMK41/K7wlklcg==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
@@ -1027,8 +1027,8 @@ packages:
|
|||||||
base64-js@1.5.1:
|
base64-js@1.5.1:
|
||||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||||
|
|
||||||
baseline-browser-mapping@2.8.24:
|
baseline-browser-mapping@2.8.25:
|
||||||
resolution: {integrity: sha512-uUhTRDPXamakPyghwrUcjaGvvBqGrWvBHReoiULMIpOJVM9IYzQh83Xk2Onx5HlGI2o10NNCzcs9TG/S3TkwrQ==}
|
resolution: {integrity: sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
bin-build@3.0.0:
|
bin-build@3.0.0:
|
||||||
@@ -1117,8 +1117,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==}
|
resolution: {integrity: sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
caniuse-lite@1.0.30001753:
|
caniuse-lite@1.0.30001754:
|
||||||
resolution: {integrity: sha512-Bj5H35MD/ebaOV4iDLqPEtiliTN29qkGtEHCwawWn4cYm+bPJM2NsaP30vtZcnERClMzp52J4+aw2UNbK4o+zw==}
|
resolution: {integrity: sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==}
|
||||||
|
|
||||||
caw@2.0.1:
|
caw@2.0.1:
|
||||||
resolution: {integrity: sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==}
|
resolution: {integrity: sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==}
|
||||||
@@ -1337,8 +1337,8 @@ packages:
|
|||||||
duplexer3@0.1.5:
|
duplexer3@0.1.5:
|
||||||
resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==}
|
resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==}
|
||||||
|
|
||||||
electron-to-chromium@1.5.245:
|
electron-to-chromium@1.5.249:
|
||||||
resolution: {integrity: sha512-rdmGfW47ZhL/oWEJAY4qxRtdly2B98ooTJ0pdEI4jhVLZ6tNf8fPtov2wS1IRKwFJT92le3x4Knxiwzl7cPPpQ==}
|
resolution: {integrity: sha512-5vcfL3BBe++qZ5kuFhD/p8WOM1N9m3nwvJPULJx+4xf2usSlZFJ0qoNYO2fOX4hi3ocuDcmDobtA+5SFr4OmBg==}
|
||||||
|
|
||||||
emoji-regex@8.0.0:
|
emoji-regex@8.0.0:
|
||||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||||
@@ -2628,8 +2628,8 @@ packages:
|
|||||||
rollup:
|
rollup:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
rollup@4.52.5:
|
rollup@4.53.1:
|
||||||
resolution: {integrity: sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==}
|
resolution: {integrity: sha512-n2I0V0lN3E9cxxMqBCT3opWOiQBzRN7UG60z/WDKqdX2zHUS/39lezBcsckZFsV6fUTSnfqI7kHf60jDAPGKug==}
|
||||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
@@ -2999,8 +2999,8 @@ packages:
|
|||||||
vite:
|
vite:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
vite@7.2.0:
|
vite@7.2.2:
|
||||||
resolution: {integrity: sha512-C/Naxf8H0pBx1PA4BdpT+c/5wdqI9ILMdwjSMILw7tVIh3JsxzZqdeTLmmdaoh5MYUEOyBnM9K3o0DzoZ/fe+w==}
|
resolution: {integrity: sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==}
|
||||||
engines: {node: ^20.19.0 || >=22.12.0}
|
engines: {node: ^20.19.0 || >=22.12.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3598,18 +3598,18 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
preact: 10.27.2
|
preact: 10.27.2
|
||||||
|
|
||||||
'@preact/preset-vite@2.10.2(@babel/core@7.28.5)(preact@10.27.2)(vite@7.2.0(@types/node@24.10.0)(terser@5.44.1))':
|
'@preact/preset-vite@2.10.2(@babel/core@7.28.5)(preact@10.27.2)(vite@7.2.2(@types/node@24.10.0)(terser@5.44.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.28.5
|
'@babel/core': 7.28.5
|
||||||
'@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.5)
|
'@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.5)
|
||||||
'@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.5)
|
'@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.5)
|
||||||
'@prefresh/vite': 2.4.11(preact@10.27.2)(vite@7.2.0(@types/node@24.10.0)(terser@5.44.1))
|
'@prefresh/vite': 2.4.11(preact@10.27.2)(vite@7.2.2(@types/node@24.10.0)(terser@5.44.1))
|
||||||
'@rollup/pluginutils': 4.2.1
|
'@rollup/pluginutils': 4.2.1
|
||||||
babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.28.5)
|
babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.28.5)
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
vite: 7.2.0(@types/node@24.10.0)(terser@5.44.1)
|
vite: 7.2.2(@types/node@24.10.0)(terser@5.44.1)
|
||||||
vite-prerender-plugin: 0.5.12(vite@7.2.0(@types/node@24.10.0)(terser@5.44.1))
|
vite-prerender-plugin: 0.5.12(vite@7.2.2(@types/node@24.10.0)(terser@5.44.1))
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- preact
|
- preact
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -3622,7 +3622,7 @@ snapshots:
|
|||||||
|
|
||||||
'@prefresh/utils@1.2.1': {}
|
'@prefresh/utils@1.2.1': {}
|
||||||
|
|
||||||
'@prefresh/vite@2.4.11(preact@10.27.2)(vite@7.2.0(@types/node@24.10.0)(terser@5.44.1))':
|
'@prefresh/vite@2.4.11(preact@10.27.2)(vite@7.2.2(@types/node@24.10.0)(terser@5.44.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.28.5
|
'@babel/core': 7.28.5
|
||||||
'@prefresh/babel-plugin': 0.5.2
|
'@prefresh/babel-plugin': 0.5.2
|
||||||
@@ -3630,7 +3630,7 @@ snapshots:
|
|||||||
'@prefresh/utils': 1.2.1
|
'@prefresh/utils': 1.2.1
|
||||||
'@rollup/pluginutils': 4.2.1
|
'@rollup/pluginutils': 4.2.1
|
||||||
preact: 10.27.2
|
preact: 10.27.2
|
||||||
vite: 7.2.0(@types/node@24.10.0)(terser@5.44.1)
|
vite: 7.2.2(@types/node@24.10.0)(terser@5.44.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -3639,70 +3639,70 @@ snapshots:
|
|||||||
estree-walker: 2.0.2
|
estree-walker: 2.0.2
|
||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
|
|
||||||
'@rollup/rollup-android-arm-eabi@4.52.5':
|
'@rollup/rollup-android-arm-eabi@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-android-arm64@4.52.5':
|
'@rollup/rollup-android-arm64@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-darwin-arm64@4.52.5':
|
'@rollup/rollup-darwin-arm64@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-darwin-x64@4.52.5':
|
'@rollup/rollup-darwin-x64@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-freebsd-arm64@4.52.5':
|
'@rollup/rollup-freebsd-arm64@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-freebsd-x64@4.52.5':
|
'@rollup/rollup-freebsd-x64@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm-gnueabihf@4.52.5':
|
'@rollup/rollup-linux-arm-gnueabihf@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm-musleabihf@4.52.5':
|
'@rollup/rollup-linux-arm-musleabihf@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm64-gnu@4.52.5':
|
'@rollup/rollup-linux-arm64-gnu@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm64-musl@4.52.5':
|
'@rollup/rollup-linux-arm64-musl@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-loong64-gnu@4.52.5':
|
'@rollup/rollup-linux-loong64-gnu@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-ppc64-gnu@4.52.5':
|
'@rollup/rollup-linux-ppc64-gnu@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-riscv64-gnu@4.52.5':
|
'@rollup/rollup-linux-riscv64-gnu@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-riscv64-musl@4.52.5':
|
'@rollup/rollup-linux-riscv64-musl@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-s390x-gnu@4.52.5':
|
'@rollup/rollup-linux-s390x-gnu@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-x64-gnu@4.52.5':
|
'@rollup/rollup-linux-x64-gnu@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-x64-musl@4.52.5':
|
'@rollup/rollup-linux-x64-musl@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-openharmony-arm64@4.52.5':
|
'@rollup/rollup-openharmony-arm64@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-win32-arm64-msvc@4.52.5':
|
'@rollup/rollup-win32-arm64-msvc@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-win32-ia32-msvc@4.52.5':
|
'@rollup/rollup-win32-ia32-msvc@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-win32-x64-gnu@4.52.5':
|
'@rollup/rollup-win32-x64-gnu@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-win32-x64-msvc@4.52.5':
|
'@rollup/rollup-win32-x64-msvc@4.53.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@sindresorhus/is@0.7.0': {}
|
'@sindresorhus/is@0.7.0': {}
|
||||||
@@ -3963,7 +3963,7 @@ snapshots:
|
|||||||
|
|
||||||
base64-js@1.5.1: {}
|
base64-js@1.5.1: {}
|
||||||
|
|
||||||
baseline-browser-mapping@2.8.24: {}
|
baseline-browser-mapping@2.8.25: {}
|
||||||
|
|
||||||
bin-build@3.0.0:
|
bin-build@3.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4020,9 +4020,9 @@ snapshots:
|
|||||||
|
|
||||||
browserslist@4.27.0:
|
browserslist@4.27.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
baseline-browser-mapping: 2.8.24
|
baseline-browser-mapping: 2.8.25
|
||||||
caniuse-lite: 1.0.30001753
|
caniuse-lite: 1.0.30001754
|
||||||
electron-to-chromium: 1.5.245
|
electron-to-chromium: 1.5.249
|
||||||
node-releases: 2.0.27
|
node-releases: 2.0.27
|
||||||
update-browserslist-db: 1.1.4(browserslist@4.27.0)
|
update-browserslist-db: 1.1.4(browserslist@4.27.0)
|
||||||
|
|
||||||
@@ -4080,7 +4080,7 @@ snapshots:
|
|||||||
|
|
||||||
camelcase@2.1.1: {}
|
camelcase@2.1.1: {}
|
||||||
|
|
||||||
caniuse-lite@1.0.30001753: {}
|
caniuse-lite@1.0.30001754: {}
|
||||||
|
|
||||||
caw@2.0.1:
|
caw@2.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4367,7 +4367,7 @@ snapshots:
|
|||||||
|
|
||||||
duplexer3@0.1.5: {}
|
duplexer3@0.1.5: {}
|
||||||
|
|
||||||
electron-to-chromium@1.5.245: {}
|
electron-to-chromium@1.5.249: {}
|
||||||
|
|
||||||
emoji-regex@8.0.0: {}
|
emoji-regex@8.0.0: {}
|
||||||
|
|
||||||
@@ -5621,41 +5621,41 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
glob: 7.2.3
|
glob: 7.2.3
|
||||||
|
|
||||||
rollup-plugin-visualizer@6.0.5(rollup@4.52.5):
|
rollup-plugin-visualizer@6.0.5(rollup@4.53.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
open: 8.4.2
|
open: 8.4.2
|
||||||
picomatch: 4.0.3
|
picomatch: 4.0.3
|
||||||
source-map: 0.7.6
|
source-map: 0.7.6
|
||||||
yargs: 17.7.2
|
yargs: 17.7.2
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
rollup: 4.52.5
|
rollup: 4.53.1
|
||||||
|
|
||||||
rollup@4.52.5:
|
rollup@4.53.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.8
|
'@types/estree': 1.0.8
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@rollup/rollup-android-arm-eabi': 4.52.5
|
'@rollup/rollup-android-arm-eabi': 4.53.1
|
||||||
'@rollup/rollup-android-arm64': 4.52.5
|
'@rollup/rollup-android-arm64': 4.53.1
|
||||||
'@rollup/rollup-darwin-arm64': 4.52.5
|
'@rollup/rollup-darwin-arm64': 4.53.1
|
||||||
'@rollup/rollup-darwin-x64': 4.52.5
|
'@rollup/rollup-darwin-x64': 4.53.1
|
||||||
'@rollup/rollup-freebsd-arm64': 4.52.5
|
'@rollup/rollup-freebsd-arm64': 4.53.1
|
||||||
'@rollup/rollup-freebsd-x64': 4.52.5
|
'@rollup/rollup-freebsd-x64': 4.53.1
|
||||||
'@rollup/rollup-linux-arm-gnueabihf': 4.52.5
|
'@rollup/rollup-linux-arm-gnueabihf': 4.53.1
|
||||||
'@rollup/rollup-linux-arm-musleabihf': 4.52.5
|
'@rollup/rollup-linux-arm-musleabihf': 4.53.1
|
||||||
'@rollup/rollup-linux-arm64-gnu': 4.52.5
|
'@rollup/rollup-linux-arm64-gnu': 4.53.1
|
||||||
'@rollup/rollup-linux-arm64-musl': 4.52.5
|
'@rollup/rollup-linux-arm64-musl': 4.53.1
|
||||||
'@rollup/rollup-linux-loong64-gnu': 4.52.5
|
'@rollup/rollup-linux-loong64-gnu': 4.53.1
|
||||||
'@rollup/rollup-linux-ppc64-gnu': 4.52.5
|
'@rollup/rollup-linux-ppc64-gnu': 4.53.1
|
||||||
'@rollup/rollup-linux-riscv64-gnu': 4.52.5
|
'@rollup/rollup-linux-riscv64-gnu': 4.53.1
|
||||||
'@rollup/rollup-linux-riscv64-musl': 4.52.5
|
'@rollup/rollup-linux-riscv64-musl': 4.53.1
|
||||||
'@rollup/rollup-linux-s390x-gnu': 4.52.5
|
'@rollup/rollup-linux-s390x-gnu': 4.53.1
|
||||||
'@rollup/rollup-linux-x64-gnu': 4.52.5
|
'@rollup/rollup-linux-x64-gnu': 4.53.1
|
||||||
'@rollup/rollup-linux-x64-musl': 4.52.5
|
'@rollup/rollup-linux-x64-musl': 4.53.1
|
||||||
'@rollup/rollup-openharmony-arm64': 4.52.5
|
'@rollup/rollup-openharmony-arm64': 4.53.1
|
||||||
'@rollup/rollup-win32-arm64-msvc': 4.52.5
|
'@rollup/rollup-win32-arm64-msvc': 4.53.1
|
||||||
'@rollup/rollup-win32-ia32-msvc': 4.52.5
|
'@rollup/rollup-win32-ia32-msvc': 4.53.1
|
||||||
'@rollup/rollup-win32-x64-gnu': 4.52.5
|
'@rollup/rollup-win32-x64-gnu': 4.53.1
|
||||||
'@rollup/rollup-win32-x64-msvc': 4.52.5
|
'@rollup/rollup-win32-x64-msvc': 4.53.1
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
|
||||||
run-parallel@1.2.0:
|
run-parallel@1.2.0:
|
||||||
@@ -5970,7 +5970,7 @@ snapshots:
|
|||||||
spdx-correct: 3.2.0
|
spdx-correct: 3.2.0
|
||||||
spdx-expression-parse: 3.0.1
|
spdx-expression-parse: 3.0.1
|
||||||
|
|
||||||
vite-plugin-imagemin@0.6.1(vite@7.2.0(@types/node@24.10.0)(terser@5.44.1)):
|
vite-plugin-imagemin@0.6.1(vite@7.2.2(@types/node@24.10.0)(terser@5.44.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/imagemin': 7.0.1
|
'@types/imagemin': 7.0.1
|
||||||
'@types/imagemin-gifsicle': 7.0.4
|
'@types/imagemin-gifsicle': 7.0.4
|
||||||
@@ -5995,11 +5995,11 @@ snapshots:
|
|||||||
imagemin-webp: 6.1.0
|
imagemin-webp: 6.1.0
|
||||||
jpegtran-bin: 6.0.1
|
jpegtran-bin: 6.0.1
|
||||||
pathe: 0.2.0
|
pathe: 0.2.0
|
||||||
vite: 7.2.0(@types/node@24.10.0)(terser@5.44.1)
|
vite: 7.2.2(@types/node@24.10.0)(terser@5.44.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
vite-prerender-plugin@0.5.12(vite@7.2.0(@types/node@24.10.0)(terser@5.44.1)):
|
vite-prerender-plugin@0.5.12(vite@7.2.2(@types/node@24.10.0)(terser@5.44.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
kolorist: 1.8.0
|
kolorist: 1.8.0
|
||||||
magic-string: 0.30.21
|
magic-string: 0.30.21
|
||||||
@@ -6007,26 +6007,26 @@ snapshots:
|
|||||||
simple-code-frame: 1.3.0
|
simple-code-frame: 1.3.0
|
||||||
source-map: 0.7.6
|
source-map: 0.7.6
|
||||||
stack-trace: 1.0.0-pre2
|
stack-trace: 1.0.0-pre2
|
||||||
vite: 7.2.0(@types/node@24.10.0)(terser@5.44.1)
|
vite: 7.2.2(@types/node@24.10.0)(terser@5.44.1)
|
||||||
|
|
||||||
vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.2.0(@types/node@24.10.0)(terser@5.44.1)):
|
vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(terser@5.44.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
globrex: 0.1.2
|
globrex: 0.1.2
|
||||||
tsconfck: 3.1.6(typescript@5.9.3)
|
tsconfck: 3.1.6(typescript@5.9.3)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
vite: 7.2.0(@types/node@24.10.0)(terser@5.44.1)
|
vite: 7.2.2(@types/node@24.10.0)(terser@5.44.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
|
|
||||||
vite@7.2.0(@types/node@24.10.0)(terser@5.44.1):
|
vite@7.2.2(@types/node@24.10.0)(terser@5.44.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.25.12
|
esbuild: 0.25.12
|
||||||
fdir: 6.5.0(picomatch@4.0.3)
|
fdir: 6.5.0(picomatch@4.0.3)
|
||||||
picomatch: 4.0.3
|
picomatch: 4.0.3
|
||||||
postcss: 8.5.6
|
postcss: 8.5.6
|
||||||
rollup: 4.52.5
|
rollup: 4.53.1
|
||||||
tinyglobby: 0.2.15
|
tinyglobby: 0.2.15
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 24.10.0
|
'@types/node': 24.10.0
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ const common_theme = {
|
|||||||
}
|
}
|
||||||
&:hover .td {
|
&:hover .td {
|
||||||
background-color: #177ac9;
|
background-color: #177ac9;
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
Cell: `
|
Cell: `
|
||||||
@@ -297,7 +298,12 @@ const Sensors = () => {
|
|||||||
|
|
||||||
const onTemperatureDialogSave = useCallback(
|
const onTemperatureDialogSave = useCallback(
|
||||||
async (ts: TemperatureSensor) => {
|
async (ts: TemperatureSensor) => {
|
||||||
await sendTemperatureSensor({ id: ts.id, name: ts.n, offset: ts.o })
|
await sendTemperatureSensor({
|
||||||
|
id: ts.id,
|
||||||
|
name: ts.n,
|
||||||
|
offset: ts.o,
|
||||||
|
is_system: ts.s
|
||||||
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success(LL.UPDATED_OF(LL.SENSOR(1)));
|
toast.success(LL.UPDATED_OF(LL.SENSOR(1)));
|
||||||
})
|
})
|
||||||
@@ -342,7 +348,8 @@ const Sensors = () => {
|
|||||||
t: 0,
|
t: 0,
|
||||||
f: 1,
|
f: 1,
|
||||||
d: false,
|
d: false,
|
||||||
o_n: ''
|
o_n: '',
|
||||||
|
s: false
|
||||||
});
|
});
|
||||||
setAnalogDialogOpen(true);
|
setAnalogDialogOpen(true);
|
||||||
}, []);
|
}, []);
|
||||||
@@ -357,7 +364,8 @@ const Sensors = () => {
|
|||||||
factor: as.f,
|
factor: as.f,
|
||||||
uom: as.u,
|
uom: as.u,
|
||||||
type: as.t,
|
type: as.t,
|
||||||
deleted: as.d
|
deleted: as.d,
|
||||||
|
is_system: as.s
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success(LL.UPDATED_OF(LL.ANALOG_SENSOR(2)));
|
toast.success(LL.UPDATED_OF(LL.ANALOG_SENSOR(2)));
|
||||||
@@ -431,20 +439,25 @@ const Sensors = () => {
|
|||||||
</HeaderRow>
|
</HeaderRow>
|
||||||
</Header>
|
</Header>
|
||||||
<Body>
|
<Body>
|
||||||
{tableList.map((a: AnalogSensor) => (
|
{tableList.map((as: AnalogSensor) => (
|
||||||
<Row key={a.id} item={a} onClick={() => updateAnalogSensor(a)}>
|
<Row
|
||||||
<Cell stiff>{a.g}</Cell>
|
style={{ color: as.s ? 'grey' : 'inherit' }}
|
||||||
<Cell>{a.n}</Cell>
|
key={as.id}
|
||||||
<Cell stiff>{AnalogTypeNames[a.t]} </Cell>
|
item={as}
|
||||||
{(a.t === AnalogType.DIGITAL_OUT &&
|
onClick={() => updateAnalogSensor(as)}
|
||||||
a.g !== GPIO_25 &&
|
>
|
||||||
a.g !== GPIO_26) ||
|
<Cell stiff>{as.g}</Cell>
|
||||||
a.t === AnalogType.DIGITAL_IN ||
|
<Cell>{as.n}</Cell>
|
||||||
a.t === AnalogType.PULSE ? (
|
<Cell stiff>{AnalogTypeNames[as.t]} </Cell>
|
||||||
<Cell stiff>{a.v ? LL.ON() : LL.OFF()}</Cell>
|
{(as.t === AnalogType.DIGITAL_OUT &&
|
||||||
|
as.g !== GPIO_25 &&
|
||||||
|
as.g !== GPIO_26) ||
|
||||||
|
as.t === AnalogType.DIGITAL_IN ||
|
||||||
|
as.t === AnalogType.PULSE ? (
|
||||||
|
<Cell stiff>{as.v ? LL.ON() : LL.OFF()}</Cell>
|
||||||
) : (
|
) : (
|
||||||
<Cell stiff>
|
<Cell stiff>
|
||||||
{a.t !== AnalogType.NOTUSED ? formatValue(a.v, a.u) : ''}
|
{as.t !== AnalogType.NOTUSED ? formatValue(as.v, as.u) : ''}
|
||||||
</Cell>
|
</Cell>
|
||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
@@ -506,6 +519,7 @@ const Sensors = () => {
|
|||||||
<Body>
|
<Body>
|
||||||
{tableList.map((ts: TemperatureSensor) => (
|
{tableList.map((ts: TemperatureSensor) => (
|
||||||
<Row
|
<Row
|
||||||
|
style={{ color: ts.s ? 'grey' : 'inherit' }}
|
||||||
key={ts.id}
|
key={ts.id}
|
||||||
item={ts}
|
item={ts}
|
||||||
onClick={() => updateTemperatureSensor(ts)}
|
onClick={() => updateTemperatureSensor(ts)}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
|
import DoneIcon from '@mui/icons-material/Done';
|
||||||
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
import {
|
import {
|
||||||
@@ -288,7 +289,7 @@ const SensorsAnalogDialog = ({
|
|||||||
name="f"
|
name="f"
|
||||||
label={LL.FACTOR()}
|
label={LL.FACTOR()}
|
||||||
value={numberValue(editItem.f)}
|
value={numberValue(editItem.f)}
|
||||||
sx={{ width: '11ch' }}
|
sx={{ width: '14ch' }}
|
||||||
type="number"
|
type="number"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
@@ -441,12 +442,25 @@ const SensorsAnalogDialog = ({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
{editItem.s && (
|
||||||
|
<Grid>
|
||||||
|
<Typography mt={1} color="warning.main" variant="body2">
|
||||||
|
<WarningIcon
|
||||||
|
fontSize="small"
|
||||||
|
sx={{ mr: 1, verticalAlign: 'middle' }}
|
||||||
|
color="warning"
|
||||||
|
/>
|
||||||
|
{LL.SYSTEM(0)} {LL.SENSOR(0)}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
{!creating && (
|
{!creating && (
|
||||||
<Box flexGrow={1} sx={{ '& button': { mt: 0 } }}>
|
<Box flexGrow={1} sx={{ '& button': { mt: 0 } }}>
|
||||||
<Button
|
<Button
|
||||||
startIcon={<RemoveIcon />}
|
startIcon={<RemoveIcon />}
|
||||||
|
disabled={editItem.s}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="warning"
|
color="warning"
|
||||||
onClick={remove}
|
onClick={remove}
|
||||||
@@ -464,7 +478,7 @@ const SensorsAnalogDialog = ({
|
|||||||
{LL.CANCEL()}
|
{LL.CANCEL()}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
startIcon={<WarningIcon color="warning" />}
|
startIcon={<DoneIcon />}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onClick={save}
|
onClick={save}
|
||||||
color="primary"
|
color="primary"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
|
import DoneIcon from '@mui/icons-material/Done';
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
@@ -139,6 +140,18 @@ const SensorsTemperatureDialog = ({
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
{editItem.s && (
|
||||||
|
<Grid>
|
||||||
|
<Typography mt={1} color="warning.main" variant="body2">
|
||||||
|
<WarningIcon
|
||||||
|
fontSize="small"
|
||||||
|
sx={{ mr: 1, verticalAlign: 'middle' }}
|
||||||
|
color="warning"
|
||||||
|
/>
|
||||||
|
{LL.SYSTEM(0)} {LL.SENSOR(0)}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button
|
<Button
|
||||||
@@ -150,7 +163,7 @@ const SensorsTemperatureDialog = ({
|
|||||||
{LL.CANCEL()}
|
{LL.CANCEL()}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
startIcon={<WarningIcon color="warning" />}
|
startIcon={<DoneIcon />}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onClick={save}
|
onClick={save}
|
||||||
color="primary"
|
color="primary"
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ export interface TemperatureSensor {
|
|||||||
t?: number; // temp, optional
|
t?: number; // temp, optional
|
||||||
o: number; // offset
|
o: number; // offset
|
||||||
u: number; // uom
|
u: number; // uom
|
||||||
|
s: boolean; // system sensor flag
|
||||||
o_n?: string;
|
o_n?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,6 +96,7 @@ export interface AnalogSensor {
|
|||||||
f: number;
|
f: number;
|
||||||
t: number;
|
t: number;
|
||||||
d: boolean; // deleted flag
|
d: boolean; // deleted flag
|
||||||
|
s: boolean; // system sensor flag
|
||||||
o_n?: string;
|
o_n?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +104,7 @@ export interface WriteTemperatureSensor {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
offset: number;
|
offset: number;
|
||||||
|
is_system: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SensorData {
|
export interface SensorData {
|
||||||
@@ -317,6 +320,7 @@ export interface WriteAnalogSensor {
|
|||||||
uom: number;
|
uom: number;
|
||||||
type: number;
|
type: number;
|
||||||
deleted: boolean;
|
deleted: boolean;
|
||||||
|
is_system: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DeviceEntityMask {
|
export enum DeviceEntityMask {
|
||||||
|
|||||||
@@ -37,13 +37,13 @@ import { validate } from 'validators';
|
|||||||
|
|
||||||
import { API, getBoardProfile, readSettings, writeSettings } from '../../api/app';
|
import { API, getBoardProfile, readSettings, writeSettings } from '../../api/app';
|
||||||
import { BOARD_PROFILES } from '../main/types';
|
import { BOARD_PROFILES } from '../main/types';
|
||||||
import type { APIcall, Settings } from '../main/types';
|
import type { APIcall, BoardProfileKey, Settings } from '../main/types';
|
||||||
import { createSettingsValidator } from '../main/validators';
|
import { createSettingsValidator } from '../main/validators';
|
||||||
|
|
||||||
export function boardProfileSelectItems() {
|
export function boardProfileSelectItems() {
|
||||||
return Object.keys(BOARD_PROFILES).map((code) => (
|
return Object.keys(BOARD_PROFILES).map((code) => (
|
||||||
<MenuItem key={code} value={code}>
|
<MenuItem key={code} value={code}>
|
||||||
{BOARD_PROFILES[code]}
|
{BOARD_PROFILES[code as BoardProfileKey]}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
@@ -30,11 +30,14 @@ import { SectionContent, useLayoutTitle } from 'components';
|
|||||||
import ListMenuItem from 'components/layout/ListMenuItem';
|
import ListMenuItem from 'components/layout/ListMenuItem';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
|
||||||
|
import SystemMonitor from '../status/SystemMonitor';
|
||||||
|
|
||||||
const Settings = () => {
|
const Settings = () => {
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
useLayoutTitle(LL.SETTINGS(0));
|
useLayoutTitle(LL.SETTINGS(0));
|
||||||
|
|
||||||
const [confirmFactoryReset, setConfirmFactoryReset] = useState(false);
|
const [confirmFactoryReset, setConfirmFactoryReset] = useState(false);
|
||||||
|
const [restarting, setRestarting] = useState<boolean>();
|
||||||
|
|
||||||
const { send: sendAPI } = useRequest((data: APIcall) => API(data), {
|
const { send: sendAPI } = useRequest((data: APIcall) => API(data), {
|
||||||
immediate: false
|
immediate: false
|
||||||
@@ -42,6 +45,7 @@ const Settings = () => {
|
|||||||
|
|
||||||
const doFormat = useCallback(async () => {
|
const doFormat = useCallback(async () => {
|
||||||
await sendAPI({ device: 'system', cmd: 'format', id: 0 }).then(() => {
|
await sendAPI({ device: 'system', cmd: 'format', id: 0 }).then(() => {
|
||||||
|
setRestarting(true);
|
||||||
setConfirmFactoryReset(false);
|
setConfirmFactoryReset(false);
|
||||||
});
|
});
|
||||||
}, [sendAPI]);
|
}, [sendAPI]);
|
||||||
@@ -54,120 +58,131 @@ const Settings = () => {
|
|||||||
setConfirmFactoryReset(true);
|
setConfirmFactoryReset(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
const content = useMemo(() => {
|
||||||
<SectionContent>
|
return (
|
||||||
<List>
|
<>
|
||||||
<ListMenuItem
|
<List>
|
||||||
icon={TuneIcon}
|
<ListMenuItem
|
||||||
bgcolor="#134ba2"
|
icon={TuneIcon}
|
||||||
label={LL.APPLICATION()}
|
bgcolor="#134ba2"
|
||||||
text={LL.APPLICATION_SETTINGS_1()}
|
label={LL.APPLICATION()}
|
||||||
to="application"
|
text={LL.APPLICATION_SETTINGS_1()}
|
||||||
/>
|
to="application"
|
||||||
|
/>
|
||||||
|
|
||||||
<ListMenuItem
|
<ListMenuItem
|
||||||
icon={SettingsEthernetIcon}
|
icon={SettingsEthernetIcon}
|
||||||
bgcolor="#40828f"
|
bgcolor="#40828f"
|
||||||
label={LL.NETWORK(0)}
|
label={LL.NETWORK(0)}
|
||||||
text={LL.CONFIGURE(LL.SETTINGS_OF(LL.NETWORK(1)))}
|
text={LL.CONFIGURE(LL.SETTINGS_OF(LL.NETWORK(1)))}
|
||||||
to="network"
|
to="network"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ListMenuItem
|
<ListMenuItem
|
||||||
icon={SettingsInputAntennaIcon}
|
icon={SettingsInputAntennaIcon}
|
||||||
bgcolor="#5f9a5f"
|
bgcolor="#5f9a5f"
|
||||||
label={LL.ACCESS_POINT(0)}
|
label={LL.ACCESS_POINT(0)}
|
||||||
text={LL.CONFIGURE(LL.ACCESS_POINT(1))}
|
text={LL.CONFIGURE(LL.ACCESS_POINT(1))}
|
||||||
to="ap"
|
to="ap"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ListMenuItem
|
<ListMenuItem
|
||||||
icon={AccessTimeIcon}
|
icon={AccessTimeIcon}
|
||||||
bgcolor="#c5572c"
|
bgcolor="#c5572c"
|
||||||
label="NTP"
|
label="NTP"
|
||||||
text={LL.CONFIGURE(LL.LOCAL_TIME(1))}
|
text={LL.CONFIGURE(LL.LOCAL_TIME(1))}
|
||||||
to="ntp"
|
to="ntp"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ListMenuItem
|
<ListMenuItem
|
||||||
icon={DeviceHubIcon}
|
icon={DeviceHubIcon}
|
||||||
bgcolor="#68374d"
|
bgcolor="#68374d"
|
||||||
label="MQTT"
|
label="MQTT"
|
||||||
text={LL.CONFIGURE('MQTT')}
|
text={LL.CONFIGURE('MQTT')}
|
||||||
to="mqtt"
|
to="mqtt"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ListMenuItem
|
<ListMenuItem
|
||||||
icon={LockIcon}
|
icon={LockIcon}
|
||||||
label={LL.SECURITY(0)}
|
label={LL.SECURITY(0)}
|
||||||
text={LL.SECURITY_1()}
|
text={LL.SECURITY_1()}
|
||||||
to="security"
|
to="security"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ListMenuItem
|
<ListMenuItem
|
||||||
icon={ViewModuleIcon}
|
icon={ViewModuleIcon}
|
||||||
bgcolor="#efc34b"
|
bgcolor="#efc34b"
|
||||||
label={LL.MODULES()}
|
label={LL.MODULES()}
|
||||||
text={LL.MODULES_1()}
|
text={LL.MODULES_1()}
|
||||||
to="modules"
|
to="modules"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ListMenuItem
|
<ListMenuItem
|
||||||
icon={ImportExportIcon}
|
icon={ImportExportIcon}
|
||||||
bgcolor="#5d89f7"
|
bgcolor="#5d89f7"
|
||||||
label={LL.DOWNLOAD_UPLOAD()}
|
label={LL.DOWNLOAD_UPLOAD()}
|
||||||
text={LL.DOWNLOAD_UPLOAD_1()}
|
text={LL.DOWNLOAD_UPLOAD_1()}
|
||||||
to="downloadUpload"
|
to="downloadUpload"
|
||||||
/>
|
/>
|
||||||
</List>
|
</List>
|
||||||
|
|
||||||
<Dialog
|
<Dialog
|
||||||
sx={dialogStyle}
|
sx={dialogStyle}
|
||||||
open={confirmFactoryReset}
|
open={confirmFactoryReset}
|
||||||
onClose={handleFactoryResetClose}
|
onClose={handleFactoryResetClose}
|
||||||
>
|
>
|
||||||
<DialogTitle>{LL.FACTORY_RESET()}</DialogTitle>
|
<DialogTitle>{LL.FACTORY_RESET()}</DialogTitle>
|
||||||
<DialogContent dividers>{LL.SYSTEM_FACTORY_TEXT_DIALOG()}</DialogContent>
|
<DialogContent dividers>{LL.SYSTEM_FACTORY_TEXT_DIALOG()}</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button
|
<Button
|
||||||
startIcon={<CancelIcon />}
|
startIcon={<CancelIcon />}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onClick={handleFactoryResetClose}
|
onClick={handleFactoryResetClose}
|
||||||
color="secondary"
|
color="secondary"
|
||||||
>
|
>
|
||||||
{LL.CANCEL()}
|
{LL.CANCEL()}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
startIcon={<SettingsBackupRestoreIcon />}
|
||||||
|
variant="outlined"
|
||||||
|
onClick={doFormat}
|
||||||
|
color="error"
|
||||||
|
>
|
||||||
|
{LL.FACTORY_RESET()}
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<Box
|
||||||
|
mt={2}
|
||||||
|
display="flex"
|
||||||
|
justifyContent="flex-end"
|
||||||
|
flexWrap="nowrap"
|
||||||
|
whiteSpace="nowrap"
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
startIcon={<SettingsBackupRestoreIcon />}
|
startIcon={<SettingsBackupRestoreIcon />}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onClick={doFormat}
|
onClick={handleFactoryResetClick}
|
||||||
color="error"
|
color="error"
|
||||||
>
|
>
|
||||||
{LL.FACTORY_RESET()}
|
{LL.FACTORY_RESET()}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</Box>
|
||||||
</Dialog>
|
</>
|
||||||
|
);
|
||||||
|
}, [
|
||||||
|
LL,
|
||||||
|
handleFactoryResetClick,
|
||||||
|
handleFactoryResetClose,
|
||||||
|
doFormat,
|
||||||
|
confirmFactoryReset,
|
||||||
|
restarting
|
||||||
|
]);
|
||||||
|
|
||||||
<Divider />
|
return <SectionContent>{restarting ? <SystemMonitor /> : content}</SectionContent>;
|
||||||
|
|
||||||
<Box
|
|
||||||
mt={2}
|
|
||||||
display="flex"
|
|
||||||
justifyContent="flex-end"
|
|
||||||
flexWrap="nowrap"
|
|
||||||
whiteSpace="nowrap"
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
startIcon={<SettingsBackupRestoreIcon />}
|
|
||||||
variant="outlined"
|
|
||||||
onClick={handleFactoryResetClick}
|
|
||||||
color="error"
|
|
||||||
>
|
|
||||||
{LL.FACTORY_RESET()}
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
</SectionContent>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Settings;
|
export default Settings;
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ const ValidatedTextField: FC<ValidatedTextFieldProps> = ({
|
|||||||
<>
|
<>
|
||||||
<TextField error={!!errors} {...rest} aria-label="Error" />
|
<TextField error={!!errors} {...rest} aria-label="Error" />
|
||||||
{errors?.map((e) => (
|
{errors?.map((e) => (
|
||||||
<FormHelperText key={e.message}>{e.message}</FormHelperText>
|
<FormHelperText key={e.message} sx={{ color: 'rgb(250, 95, 84)' }}>
|
||||||
|
{e.message}
|
||||||
|
</FormHelperText>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ const cz: Translation = {
|
|||||||
UPDATE_AVAILABLE: 'aktualizace dostupná',
|
UPDATE_AVAILABLE: 'aktualizace dostupná',
|
||||||
LATEST_VERSION: 'Používáte nejnovější verzi {0}firmwaru',
|
LATEST_VERSION: 'Používáte nejnovější verzi {0}firmwaru',
|
||||||
PLEASE_WAIT: 'Prosím čekejte',
|
PLEASE_WAIT: 'Prosím čekejte',
|
||||||
RESTARTING_PRE: 'Inicializace',
|
RESTARTING_PRE: 'Bootování',
|
||||||
RESTARTING_POST: 'Příprava',
|
RESTARTING_POST: 'Příprava',
|
||||||
AUTO_SCROLL: 'Automatické rolování',
|
AUTO_SCROLL: 'Automatické rolování',
|
||||||
DASHBOARD: 'Dashboard',
|
DASHBOARD: 'Dashboard',
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ const de: Translation = {
|
|||||||
UPDATE_AVAILABLE: 'Firmware-Update verfügbar',
|
UPDATE_AVAILABLE: 'Firmware-Update verfügbar',
|
||||||
LATEST_VERSION: 'Sie verwenden die neueste {0} Firmware-Version',
|
LATEST_VERSION: 'Sie verwenden die neueste {0} Firmware-Version',
|
||||||
PLEASE_WAIT: 'Bitte warten',
|
PLEASE_WAIT: 'Bitte warten',
|
||||||
RESTARTING_PRE: 'Initialisierung',
|
RESTARTING_PRE: 'Booten',
|
||||||
RESTARTING_POST: 'Vorbereitung',
|
RESTARTING_POST: 'Vorbereitung',
|
||||||
AUTO_SCROLL: 'Automatisches Scrollen',
|
AUTO_SCROLL: 'Automatisches Scrollen',
|
||||||
DASHBOARD: 'Dashboard',
|
DASHBOARD: 'Dashboard',
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ const en: Translation = {
|
|||||||
UPDATE_AVAILABLE: 'update available',
|
UPDATE_AVAILABLE: 'update available',
|
||||||
LATEST_VERSION: 'You are using the latest {0} firmware version',
|
LATEST_VERSION: 'You are using the latest {0} firmware version',
|
||||||
PLEASE_WAIT: 'Please wait',
|
PLEASE_WAIT: 'Please wait',
|
||||||
RESTARTING_PRE: 'Initializing',
|
RESTARTING_PRE: 'Booting',
|
||||||
RESTARTING_POST: 'Preparing',
|
RESTARTING_POST: 'Preparing',
|
||||||
AUTO_SCROLL: 'Auto Scroll',
|
AUTO_SCROLL: 'Auto Scroll',
|
||||||
DASHBOARD: 'Dashboard',
|
DASHBOARD: 'Dashboard',
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ const fr: Translation = {
|
|||||||
UPDATE_AVAILABLE: 'mise à jour disponible',
|
UPDATE_AVAILABLE: 'mise à jour disponible',
|
||||||
LATEST_VERSION: 'Vous utilisez la dernière version {0} du firmware',
|
LATEST_VERSION: 'Vous utilisez la dernière version {0} du firmware',
|
||||||
PLEASE_WAIT: 'Veuillez patienter',
|
PLEASE_WAIT: 'Veuillez patienter',
|
||||||
RESTARTING_PRE: 'Initialisation',
|
RESTARTING_PRE: 'Démarrage',
|
||||||
RESTARTING_POST: 'Préparation',
|
RESTARTING_POST: 'Préparation',
|
||||||
AUTO_SCROLL: 'Défilement automatique',
|
AUTO_SCROLL: 'Défilement automatique',
|
||||||
DASHBOARD: 'Tableau de bord',
|
DASHBOARD: 'Tableau de bord',
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ const it: Translation = {
|
|||||||
UPDATE_AVAILABLE: 'aggiornamento disponibile',
|
UPDATE_AVAILABLE: 'aggiornamento disponibile',
|
||||||
LATEST_VERSION: 'Stai usando la versione più recente del firmware {0}',
|
LATEST_VERSION: 'Stai usando la versione più recente del firmware {0}',
|
||||||
PLEASE_WAIT: 'Attendere',
|
PLEASE_WAIT: 'Attendere',
|
||||||
RESTARTING_PRE: 'Inizializzazione',
|
RESTARTING_PRE: 'Avviamento',
|
||||||
RESTARTING_POST: 'Preparazione',
|
RESTARTING_POST: 'Preparazione',
|
||||||
AUTO_SCROLL: 'Scorrimento automatico',
|
AUTO_SCROLL: 'Scorrimento automatico',
|
||||||
DASHBOARD: 'Pannello di controllo',
|
DASHBOARD: 'Pannello di controllo',
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ const nl: Translation = {
|
|||||||
UPDATE_AVAILABLE: 'update beschikbaar',
|
UPDATE_AVAILABLE: 'update beschikbaar',
|
||||||
LATEST_VERSION: 'U gebruikt de nieuwste {0} firmwareversie',
|
LATEST_VERSION: 'U gebruikt de nieuwste {0} firmwareversie',
|
||||||
PLEASE_WAIT: 'Een ogenblik geduld',
|
PLEASE_WAIT: 'Een ogenblik geduld',
|
||||||
RESTARTING_PRE: 'Initialiseren',
|
RESTARTING_PRE: 'Booten',
|
||||||
RESTARTING_POST: 'Voorbereiding',
|
RESTARTING_POST: 'Voorbereiding',
|
||||||
AUTO_SCROLL: 'Automatisch Scrollen',
|
AUTO_SCROLL: 'Automatisch Scrollen',
|
||||||
DASHBOARD: 'Dashboard',
|
DASHBOARD: 'Dashboard',
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ const no: Translation = {
|
|||||||
UPDATE_AVAILABLE: 'oppdatering tilgjengelig',
|
UPDATE_AVAILABLE: 'oppdatering tilgjengelig',
|
||||||
LATEST_VERSION: 'Du bruker den nyeste {0} firmware versjonen',
|
LATEST_VERSION: 'Du bruker den nyeste {0} firmware versjonen',
|
||||||
PLEASE_WAIT: 'Vennligst vent',
|
PLEASE_WAIT: 'Vennligst vent',
|
||||||
RESTARTING_PRE: 'Initialiserer',
|
RESTARTING_PRE: 'Starte',
|
||||||
RESTARTING_POST: 'Forbereder',
|
RESTARTING_POST: 'Forbereder',
|
||||||
AUTO_SCROLL: 'Automatisk rulling',
|
AUTO_SCROLL: 'Automatisk rulling',
|
||||||
DASHBOARD: 'Dashboard',
|
DASHBOARD: 'Dashboard',
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ const pl: BaseTranslation = {
|
|||||||
UPDATE_AVAILABLE: 'aktualizacja dostępna',
|
UPDATE_AVAILABLE: 'aktualizacja dostępna',
|
||||||
LATEST_VERSION: 'Jesteś używając najnowszej wersji firmware {0}',
|
LATEST_VERSION: 'Jesteś używając najnowszej wersji firmware {0}',
|
||||||
PLEASE_WAIT: 'Proszę czekać',
|
PLEASE_WAIT: 'Proszę czekać',
|
||||||
RESTARTING_PRE: 'Inicjalizacja',
|
RESTARTING_PRE: 'Uruchamianie',
|
||||||
RESTARTING_POST: 'Przygotowanie',
|
RESTARTING_POST: 'Przygotowanie',
|
||||||
AUTO_SCROLL: 'Auto Scroll',
|
AUTO_SCROLL: 'Auto Scroll',
|
||||||
DASHBOARD: 'Pulpit',
|
DASHBOARD: 'Pulpit',
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ const sk: Translation = {
|
|||||||
UPDATE_AVAILABLE: 'dostupná aktualizácia',
|
UPDATE_AVAILABLE: 'dostupná aktualizácia',
|
||||||
LATEST_VERSION: 'Používate poslednú {0} verziu firmvéru',
|
LATEST_VERSION: 'Používate poslednú {0} verziu firmvéru',
|
||||||
PLEASE_WAIT: 'Čakajte prosím',
|
PLEASE_WAIT: 'Čakajte prosím',
|
||||||
RESTARTING_PRE: 'Prebieha inicializácia',
|
RESTARTING_PRE: 'Bootovanie',
|
||||||
RESTARTING_POST: 'Príprava',
|
RESTARTING_POST: 'Príprava',
|
||||||
AUTO_SCROLL: 'Automatické rolovanie',
|
AUTO_SCROLL: 'Automatické rolovanie',
|
||||||
DASHBOARD: 'Panel',
|
DASHBOARD: 'Panel',
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ const sv: Translation = {
|
|||||||
UPDATE_AVAILABLE: 'uppdatering tillgänglig',
|
UPDATE_AVAILABLE: 'uppdatering tillgänglig',
|
||||||
LATEST_VERSION: 'Du använder den senaste {0} firmwareversionen.',
|
LATEST_VERSION: 'Du använder den senaste {0} firmwareversionen.',
|
||||||
PLEASE_WAIT: 'Var god vänta',
|
PLEASE_WAIT: 'Var god vänta',
|
||||||
RESTARTING_PRE: 'Initialiserar',
|
RESTARTING_PRE: 'Bootar',
|
||||||
RESTARTING_POST: 'Förbereder',
|
RESTARTING_POST: 'Förbereder',
|
||||||
AUTO_SCROLL: 'Autoskrolla',
|
AUTO_SCROLL: 'Autoskrolla',
|
||||||
DASHBOARD: 'Kontrollpanel',
|
DASHBOARD: 'Kontrollpanel',
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ const tr: Translation = {
|
|||||||
UPDATE_AVAILABLE: 'güncellendi!',
|
UPDATE_AVAILABLE: 'güncellendi!',
|
||||||
LATEST_VERSION: 'En son {0} firmware sürümünü kullanıyorsunuz.',
|
LATEST_VERSION: 'En son {0} firmware sürümünü kullanıyorsunuz.',
|
||||||
PLEASE_WAIT: 'Lütfen bekleyin',
|
PLEASE_WAIT: 'Lütfen bekleyin',
|
||||||
RESTARTING_PRE: 'Başlatılıyor',
|
RESTARTING_PRE: 'Yükleniyor',
|
||||||
RESTARTING_POST: 'Hazırlanıyor',
|
RESTARTING_POST: 'Hazırlanıyor',
|
||||||
AUTO_SCROLL: 'Otomatik kaydırma',
|
AUTO_SCROLL: 'Otomatik kaydırma',
|
||||||
DASHBOARD: 'Kontrol Paneli',
|
DASHBOARD: 'Kontrol Paneli',
|
||||||
|
|||||||
@@ -23,10 +23,10 @@
|
|||||||
// Constructor
|
// Constructor
|
||||||
PButton::PButton() {
|
PButton::PButton() {
|
||||||
// Initialization of default properties
|
// Initialization of default properties
|
||||||
Debounce_ = 40; // Debounce period to prevent flickering when pressing or releasing the button (in ms)
|
Debounce_ = 40; // Debounce period to prevent flickering when pressing or releasing the button (in ms)
|
||||||
DblClickDelay_ = 250; // Max period between clicks for a double click event (in ms)
|
DblClickDelay_ = 250; // Max period between clicks for a double click event (in ms)
|
||||||
LongPressDelay_ = 750; // Hold period for a long press event (in ms)
|
LongPressDelay_ = 9500; // Hold period for a long press event (in ms)
|
||||||
VLongPressDelay_ = 3000; // Hold period for a very long press event (in ms)
|
VLongPressDelay_ = 20000; // Hold period for a very long press event (in ms)
|
||||||
|
|
||||||
cb_onClick = nullptr;
|
cb_onClick = nullptr;
|
||||||
cb_onDblClick = nullptr;
|
cb_onDblClick = nullptr;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#define NTP_SETTINGS_FILE "/config/ntpSettings.json"
|
#define NTP_SETTINGS_FILE "/config/ntpSettings.json"
|
||||||
#define EMSESP_SETTINGS_FILE "/config/emsespSettings.json"
|
#define EMSESP_SETTINGS_FILE "/config/emsespSettings.json"
|
||||||
|
|
||||||
|
#define AP_MODE_ALWAYS 0
|
||||||
class DummySettings {
|
class DummySettings {
|
||||||
public:
|
public:
|
||||||
// SYSTEM
|
// SYSTEM
|
||||||
@@ -55,6 +56,7 @@ class DummySettings {
|
|||||||
uint16_t publish_time_other = 10;
|
uint16_t publish_time_other = 10;
|
||||||
uint16_t publish_time_sensor = 10;
|
uint16_t publish_time_sensor = 10;
|
||||||
uint16_t publish_time_heartbeat = 60;
|
uint16_t publish_time_heartbeat = 60;
|
||||||
|
uint32_t publish_time_water = 0;
|
||||||
|
|
||||||
String hostname = "ems-esp";
|
String hostname = "ems-esp";
|
||||||
String jwtSecret = "ems-esp";
|
String jwtSecret = "ems-esp";
|
||||||
@@ -72,11 +74,15 @@ class DummySettings {
|
|||||||
String CORSOrigin = "*";
|
String CORSOrigin = "*";
|
||||||
uint8_t tx_power = 0;
|
uint8_t tx_power = 0;
|
||||||
|
|
||||||
uint8_t provisionMode = 0;
|
// AP
|
||||||
uint32_t publish_time_water = 0;
|
uint8_t provisionMode = 0;
|
||||||
|
|
||||||
static void read(DummySettings & settings, JsonObject root){};
|
// NTP
|
||||||
static void read(DummySettings & settings){};
|
String server = "pool.ntp.org";
|
||||||
|
String tzLabel = "Europe/London";
|
||||||
|
|
||||||
|
static void read(DummySettings & settings, JsonObject root) {};
|
||||||
|
static void read(DummySettings & settings) {};
|
||||||
|
|
||||||
static StateUpdateResult update(JsonObject root, DummySettings & settings) {
|
static StateUpdateResult update(JsonObject root, DummySettings & settings) {
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
@@ -85,7 +91,7 @@ class DummySettings {
|
|||||||
|
|
||||||
class DummySettingsService : public StatefulService<DummySettings> {
|
class DummySettingsService : public StatefulService<DummySettings> {
|
||||||
public:
|
public:
|
||||||
DummySettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager){};
|
DummySettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager) {};
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
void loop();
|
void loop();
|
||||||
@@ -101,12 +107,12 @@ class ESP32React {
|
|||||||
public:
|
public:
|
||||||
ESP32React(AsyncWebServer * server, FS * fs)
|
ESP32React(AsyncWebServer * server, FS * fs)
|
||||||
: _settings(server, fs, nullptr)
|
: _settings(server, fs, nullptr)
|
||||||
, _securitySettingsService(server, fs){};
|
, _securitySettingsService(server, fs) {};
|
||||||
|
|
||||||
void begin() {
|
void begin() {
|
||||||
_mqttClient = new espMqttClient();
|
_mqttClient = new espMqttClient();
|
||||||
};
|
};
|
||||||
void loop(){};
|
void loop() {};
|
||||||
|
|
||||||
SecurityManager * getSecurityManager() {
|
SecurityManager * getSecurityManager() {
|
||||||
return &_securitySettingsService;
|
return &_securitySettingsService;
|
||||||
|
|||||||
@@ -276,10 +276,10 @@ function updateMask(entity: any, de: any, dd: any) {
|
|||||||
const old_custom_name = dd.nodes[dd_objIndex].cn;
|
const old_custom_name = dd.nodes[dd_objIndex].cn;
|
||||||
console.log(
|
console.log(
|
||||||
'comparing names, old (' +
|
'comparing names, old (' +
|
||||||
old_custom_name +
|
old_custom_name +
|
||||||
') with new (' +
|
') with new (' +
|
||||||
new_custom_name +
|
new_custom_name +
|
||||||
')'
|
')'
|
||||||
);
|
);
|
||||||
if (old_custom_name !== new_custom_name) {
|
if (old_custom_name !== new_custom_name) {
|
||||||
changed = true;
|
changed = true;
|
||||||
@@ -375,15 +375,15 @@ function check_upgrade(version: string) {
|
|||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
'Upgrade this version (' +
|
'Upgrade this version (' +
|
||||||
THIS_VERSION +
|
THIS_VERSION +
|
||||||
') to dev (' +
|
') to dev (' +
|
||||||
dev_version +
|
dev_version +
|
||||||
') is ' +
|
') is ' +
|
||||||
(DEV_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') +
|
(DEV_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') +
|
||||||
' and to stable (' +
|
' and to stable (' +
|
||||||
stable_version +
|
stable_version +
|
||||||
') is ' +
|
') is ' +
|
||||||
(STABLE_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO')
|
(STABLE_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO')
|
||||||
);
|
);
|
||||||
data = {
|
data = {
|
||||||
emsesp_version: THIS_VERSION,
|
emsesp_version: THIS_VERSION,
|
||||||
@@ -962,17 +962,89 @@ const emsesp_coredata_custom = {
|
|||||||
const emsesp_sensordata = {
|
const emsesp_sensordata = {
|
||||||
// ts: [],
|
// ts: [],
|
||||||
ts: [
|
ts: [
|
||||||
{ id: '28-233D-9497-0C03', n: 'Dallas 1', t: 25.7, o: 1.2, u: 1 },
|
{ id: '28-233D-9497-0C03', n: 'Dallas 1', t: 25.7, o: 1.2, u: 1, s: false },
|
||||||
{ id: '28-243D-7437-1E3A', n: 'Dallas 2 outside', t: 26.1, o: 0, u: 1 },
|
{
|
||||||
{ id: '28-243E-7437-1E3B', n: 'Zolder', t: 27.1, o: 0, u: 1 },
|
id: '28-243D-7437-1E3A',
|
||||||
{ id: '28-183D-1892-0C33', n: 'Roof', o: 2, u: 1 } // no temperature
|
n: 'Dallas 2 outside',
|
||||||
|
t: 26.1,
|
||||||
|
o: 0,
|
||||||
|
u: 1,
|
||||||
|
s: false
|
||||||
|
},
|
||||||
|
{ id: '28-243E-7437-1E3B', n: 'Zolder', t: 27.1, o: 0, u: 1, s: false },
|
||||||
|
{ id: '28-183D-1892-0C33', n: 'Roof', o: 2, u: 1, s: false }, // no temperature
|
||||||
|
{
|
||||||
|
id: '28_1767_7B13_2502',
|
||||||
|
n: 'gateway_temperature',
|
||||||
|
t: 28.1,
|
||||||
|
o: 0,
|
||||||
|
u: 1,
|
||||||
|
s: true
|
||||||
|
} // internal system temp
|
||||||
],
|
],
|
||||||
// as: [],
|
// as: [],
|
||||||
as: [
|
as: [
|
||||||
{ id: 1, g: 36, n: 'motor', v: 0, u: 0, o: 17, f: 0, t: 0, d: false },
|
{ id: 1, g: 35, n: 'motor', v: 0, u: 0, o: 17, f: 0, t: 0, d: false, s: false },
|
||||||
{ id: 2, g: 37, n: 'External switch', v: 13, u: 0, o: 17, f: 0, t: 1, d: false },
|
{
|
||||||
{ id: 3, g: 39, n: 'Pulse count', v: 144, u: 0, o: 0, f: 0, t: 2, d: false },
|
id: 2,
|
||||||
{ id: 4, g: 40, n: 'Pressure', v: 16, u: 17, o: 0, f: 0, t: 3, d: false }
|
g: 37,
|
||||||
|
n: 'External switch',
|
||||||
|
v: 13,
|
||||||
|
u: 0,
|
||||||
|
o: 17,
|
||||||
|
f: 0,
|
||||||
|
t: 1,
|
||||||
|
d: false,
|
||||||
|
s: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
g: 39,
|
||||||
|
n: 'Pulse count',
|
||||||
|
v: 144,
|
||||||
|
u: 0,
|
||||||
|
o: 0,
|
||||||
|
f: 0,
|
||||||
|
t: 2,
|
||||||
|
d: false,
|
||||||
|
s: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
g: 40,
|
||||||
|
n: 'Pressure',
|
||||||
|
v: 16,
|
||||||
|
u: 17,
|
||||||
|
o: 0,
|
||||||
|
f: 0,
|
||||||
|
t: 3,
|
||||||
|
d: false,
|
||||||
|
s: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
g: 39,
|
||||||
|
n: 'core_voltage',
|
||||||
|
v: 3.34,
|
||||||
|
u: 23,
|
||||||
|
o: 0,
|
||||||
|
f: 0.003771,
|
||||||
|
t: 3,
|
||||||
|
d: false,
|
||||||
|
s: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
g: 36,
|
||||||
|
n: 'supply_voltage',
|
||||||
|
v: 12.21,
|
||||||
|
u: 23,
|
||||||
|
o: 0,
|
||||||
|
f: 0.017,
|
||||||
|
t: 3,
|
||||||
|
d: false,
|
||||||
|
s: true
|
||||||
|
}
|
||||||
],
|
],
|
||||||
analog_enabled: true
|
analog_enabled: true
|
||||||
};
|
};
|
||||||
@@ -4520,8 +4592,12 @@ router
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add temperature sensor data. no command c
|
// add temperature sensor data. no command c
|
||||||
if (emsesp_sensordata.ts.length > 0) {
|
// remove system sensors first
|
||||||
const sensor_data = emsesp_sensordata.ts.map((item, index) => ({
|
const enabledTemperatureSensors = emsesp_sensordata.ts.filter(
|
||||||
|
(item) => !item.s
|
||||||
|
);
|
||||||
|
if (enabledTemperatureSensors.length > 0) {
|
||||||
|
const sensor_data = enabledTemperatureSensors.map((item, index) => ({
|
||||||
id: DeviceTypeUniqueID.TEMPERATURESENSOR_UID * 100 + index,
|
id: DeviceTypeUniqueID.TEMPERATURESENSOR_UID * 100 + index,
|
||||||
dv: {
|
dv: {
|
||||||
id: '00' + item.n,
|
id: '00' + item.n,
|
||||||
@@ -4539,8 +4615,9 @@ router
|
|||||||
|
|
||||||
// add analog sensor data. no command c
|
// add analog sensor data. no command c
|
||||||
// remove disabled sensors first (t = 0) and create data in one pass
|
// remove disabled sensors first (t = 0) and create data in one pass
|
||||||
|
// remove system sensors first
|
||||||
const enabledAnalogSensors = emsesp_sensordata.as.filter(
|
const enabledAnalogSensors = emsesp_sensordata.as.filter(
|
||||||
(item) => item.t !== 0
|
(item) => item.t !== 0 && !item.s
|
||||||
);
|
);
|
||||||
if (enabledAnalogSensors.length > 0) {
|
if (enabledAnalogSensors.length > 0) {
|
||||||
const sensor_data = enabledAnalogSensors.map((item, index) => ({
|
const sensor_data = enabledAnalogSensors.map((item, index) => ({
|
||||||
@@ -4794,6 +4871,7 @@ router
|
|||||||
if (objIndex !== -1) {
|
if (objIndex !== -1) {
|
||||||
emsesp_sensordata.ts[objIndex].n = ts.name;
|
emsesp_sensordata.ts[objIndex].n = ts.name;
|
||||||
emsesp_sensordata.ts[objIndex].o = ts.offset;
|
emsesp_sensordata.ts[objIndex].o = ts.offset;
|
||||||
|
emsesp_sensordata.ts[objIndex].s = ts.is_system;
|
||||||
}
|
}
|
||||||
console.log('temp sensor saved', ts);
|
console.log('temp sensor saved', ts);
|
||||||
return status(200);
|
return status(200);
|
||||||
@@ -4811,6 +4889,7 @@ router
|
|||||||
u: as.uom,
|
u: as.uom,
|
||||||
t: as.type,
|
t: as.type,
|
||||||
d: as.deleted,
|
d: as.deleted,
|
||||||
|
s: as.is_system,
|
||||||
v: 0 // must be added for demo only
|
v: 0 // must be added for demo only
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -4828,6 +4907,7 @@ router
|
|||||||
emsesp_sensordata.as[objIndex].o = as.offset;
|
emsesp_sensordata.as[objIndex].o = as.offset;
|
||||||
emsesp_sensordata.as[objIndex].u = as.uom;
|
emsesp_sensordata.as[objIndex].u = as.uom;
|
||||||
emsesp_sensordata.as[objIndex].t = as.type;
|
emsesp_sensordata.as[objIndex].t = as.type;
|
||||||
|
emsesp_sensordata.as[objIndex].s = as.is_system;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log('analog sensor saved', as);
|
console.log('analog sensor saved', as);
|
||||||
|
|||||||
@@ -1435,4 +1435,5 @@ teddybear
|
|||||||
washingmachine
|
washingmachine
|
||||||
switchprogram
|
switchprogram
|
||||||
brotlin
|
brotlin
|
||||||
fanspd
|
fanspd
|
||||||
|
currhum
|
||||||
@@ -58,7 +58,7 @@ enum APNetworkStatus { ACTIVE = 0, INACTIVE, LINGERING };
|
|||||||
|
|
||||||
class APSettings {
|
class APSettings {
|
||||||
public:
|
public:
|
||||||
uint8_t provisionMode;
|
uint8_t provisionMode; // 0 = on, 2 = off
|
||||||
String ssid;
|
String ssid;
|
||||||
String password;
|
String password;
|
||||||
uint8_t channel;
|
uint8_t channel;
|
||||||
|
|||||||
@@ -52,18 +52,23 @@ void AnalogSensor::start(const bool factory_settings) {
|
|||||||
// if (factory_settings && EMSESP::nvs_.getString("boot").equals("E32V2_2") && EMSESP::nvs_.getString("hwrevision").equals("3.0")) {
|
// if (factory_settings && EMSESP::nvs_.getString("boot").equals("E32V2_2") && EMSESP::nvs_.getString("hwrevision").equals("3.0")) {
|
||||||
if (factory_settings && analogReadMilliVolts(39) > 700) { // core voltage > 2.6V
|
if (factory_settings && analogReadMilliVolts(39) > 700) { // core voltage > 2.6V
|
||||||
EMSESP::webCustomizationService.update([&](WebCustomization & settings) {
|
EMSESP::webCustomizationService.update([&](WebCustomization & settings) {
|
||||||
auto newSensor = AnalogCustomization();
|
auto newSensor = AnalogCustomization();
|
||||||
newSensor.gpio = 39;
|
|
||||||
newSensor.name = "core_voltage";
|
newSensor.gpio = 39;
|
||||||
newSensor.offset = 0;
|
newSensor.name = "core_voltage";
|
||||||
newSensor.factor = 0.00377136; // Divider 24k - 8,66k
|
newSensor.offset = 0;
|
||||||
newSensor.uom = DeviceValueUOM::VOLTS;
|
newSensor.factor = 0.00377136; // Divider 24k - 8,66k
|
||||||
newSensor.type = AnalogType::ADC;
|
newSensor.uom = DeviceValueUOM::VOLTS;
|
||||||
|
newSensor.type = AnalogType::ADC;
|
||||||
|
newSensor.is_system = true;
|
||||||
settings.analogCustomizations.push_back(newSensor);
|
settings.analogCustomizations.push_back(newSensor);
|
||||||
newSensor.gpio = 36;
|
|
||||||
newSensor.name = "supply_voltage";
|
newSensor.gpio = 36;
|
||||||
newSensor.factor = 0.017; // Divider 24k - 1,5k
|
newSensor.name = "supply_voltage";
|
||||||
|
newSensor.factor = 0.017; // Divider 24k - 1,5k
|
||||||
|
newSensor.is_system = true;
|
||||||
settings.analogCustomizations.push_back(newSensor);
|
settings.analogCustomizations.push_back(newSensor);
|
||||||
|
|
||||||
return StateUpdateResult::CHANGED; // persist the change
|
return StateUpdateResult::CHANGED; // persist the change
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -150,7 +155,7 @@ void AnalogSensor::reload(bool get_nvs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
sensors_.emplace_back(sensor.gpio, sensor.name, sensor.offset, sensor.factor, sensor.uom, sensor.type);
|
sensors_.emplace_back(sensor.gpio, sensor.name, sensor.offset, sensor.factor, sensor.uom, sensor.type, sensor.is_system);
|
||||||
sensors_.back().ha_registered = false; // this will trigger recreate of the HA config
|
sensors_.back().ha_registered = false; // this will trigger recreate of the HA config
|
||||||
if (sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT) {
|
if (sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT) {
|
||||||
sensors_.back().set_value(sensor.offset);
|
sensors_.back().set_value(sensor.offset);
|
||||||
@@ -469,7 +474,7 @@ void AnalogSensor::loop() {
|
|||||||
|
|
||||||
// update analog information name and offset
|
// update analog information name and offset
|
||||||
// a type value of -1 is used to delete the sensor
|
// a type value of -1 is used to delete the sensor
|
||||||
bool AnalogSensor::update(uint8_t gpio, std::string & name, double offset, double factor, uint8_t uom, int8_t type, bool deleted) {
|
bool AnalogSensor::update(uint8_t gpio, std::string & name, double offset, double factor, uint8_t uom, int8_t type, bool deleted, bool is_system) {
|
||||||
// first see if we can find the sensor in our customization list
|
// first see if we can find the sensor in our customization list
|
||||||
bool found_sensor = false;
|
bool found_sensor = false;
|
||||||
EMSESP::webCustomizationService.update([&](WebCustomization & settings) {
|
EMSESP::webCustomizationService.update([&](WebCustomization & settings) {
|
||||||
@@ -496,11 +501,12 @@ bool AnalogSensor::update(uint8_t gpio, std::string & name, double offset, doubl
|
|||||||
if (name != AnalogCustomization.name) {
|
if (name != AnalogCustomization.name) {
|
||||||
EMSESP::nvs_.remove(AnalogCustomization.name.c_str());
|
EMSESP::nvs_.remove(AnalogCustomization.name.c_str());
|
||||||
}
|
}
|
||||||
AnalogCustomization.name = name;
|
AnalogCustomization.name = name;
|
||||||
AnalogCustomization.offset = offset;
|
AnalogCustomization.offset = offset;
|
||||||
AnalogCustomization.factor = factor;
|
AnalogCustomization.factor = factor;
|
||||||
AnalogCustomization.uom = uom;
|
AnalogCustomization.uom = uom;
|
||||||
AnalogCustomization.type = type;
|
AnalogCustomization.type = type;
|
||||||
|
AnalogCustomization.is_system = is_system;
|
||||||
LOG_DEBUG("Customizing existing analog GPIO %02d", gpio);
|
LOG_DEBUG("Customizing existing analog GPIO %02d", gpio);
|
||||||
}
|
}
|
||||||
return StateUpdateResult::CHANGED; // persist the change
|
return StateUpdateResult::CHANGED; // persist the change
|
||||||
@@ -517,13 +523,14 @@ bool AnalogSensor::update(uint8_t gpio, std::string & name, double offset, doubl
|
|||||||
// we didn't find it, it's new, so create and store it in the customization list
|
// we didn't find it, it's new, so create and store it in the customization list
|
||||||
if (!found_sensor) {
|
if (!found_sensor) {
|
||||||
EMSESP::webCustomizationService.update([&](WebCustomization & settings) {
|
EMSESP::webCustomizationService.update([&](WebCustomization & settings) {
|
||||||
auto newSensor = AnalogCustomization();
|
auto newSensor = AnalogCustomization();
|
||||||
newSensor.gpio = gpio;
|
newSensor.gpio = gpio;
|
||||||
newSensor.name = name;
|
newSensor.name = name;
|
||||||
newSensor.offset = offset;
|
newSensor.offset = offset;
|
||||||
newSensor.factor = factor;
|
newSensor.factor = factor;
|
||||||
newSensor.uom = uom;
|
newSensor.uom = uom;
|
||||||
newSensor.type = type;
|
newSensor.type = type;
|
||||||
|
newSensor.is_system = is_system;
|
||||||
settings.analogCustomizations.push_back(newSensor);
|
settings.analogCustomizations.push_back(newSensor);
|
||||||
LOG_DEBUG("Adding new customization for analog sensor GPIO %02d", gpio);
|
LOG_DEBUG("Adding new customization for analog sensor GPIO %02d", gpio);
|
||||||
return StateUpdateResult::CHANGED; // persist the change
|
return StateUpdateResult::CHANGED; // persist the change
|
||||||
@@ -836,7 +843,8 @@ void AnalogSensor::get_value_json(JsonObject output, const Sensor & sensor) {
|
|||||||
output["readable"] = true;
|
output["readable"] = true;
|
||||||
output["writeable"] = sensor.type() == AnalogType::COUNTER || sensor.type() == AnalogType::RGB || sensor.type() == AnalogType::PULSE
|
output["writeable"] = sensor.type() == AnalogType::COUNTER || sensor.type() == AnalogType::RGB || sensor.type() == AnalogType::PULSE
|
||||||
|| (sensor.type() >= AnalogType::DIGITAL_OUT && sensor.type() <= AnalogType::PWM_2);
|
|| (sensor.type() >= AnalogType::DIGITAL_OUT && sensor.type() <= AnalogType::PWM_2);
|
||||||
output["visible"] = true;
|
output["visible"] = true;
|
||||||
|
output["is_system"] = sensor.is_system();
|
||||||
if (sensor.type() == AnalogType::COUNTER) {
|
if (sensor.type() == AnalogType::COUNTER) {
|
||||||
output["min"] = 0;
|
output["min"] = 0;
|
||||||
output["max"] = 4000000;
|
output["max"] = 4000000;
|
||||||
@@ -863,13 +871,20 @@ void AnalogSensor::get_value_json(JsonObject output, const Sensor & sensor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this creates the sensor, initializing everything
|
// this creates the sensor, initializing everything
|
||||||
AnalogSensor::Sensor::Sensor(const uint8_t gpio, const std::string & name, const double offset, const double factor, const uint8_t uom, const int8_t type)
|
AnalogSensor::Sensor::Sensor(const uint8_t gpio,
|
||||||
|
const std::string & name,
|
||||||
|
const double offset,
|
||||||
|
const double factor,
|
||||||
|
const uint8_t uom,
|
||||||
|
const int8_t type,
|
||||||
|
const bool is_system)
|
||||||
: gpio_(gpio)
|
: gpio_(gpio)
|
||||||
, name_(name)
|
, name_(name)
|
||||||
, offset_(offset)
|
, offset_(offset)
|
||||||
, factor_(factor)
|
, factor_(factor)
|
||||||
, uom_(uom)
|
, uom_(uom)
|
||||||
, type_(type) {
|
, type_(type)
|
||||||
|
, is_system_(is_system) {
|
||||||
value_ = 0; // init value to 0 always
|
value_ = 0; // init value to 0 always
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class AnalogSensor {
|
|||||||
public:
|
public:
|
||||||
class Sensor {
|
class Sensor {
|
||||||
public:
|
public:
|
||||||
Sensor(const uint8_t gpio, const std::string & name, const double offset, const double factor, const uint8_t uom, const int8_t type);
|
Sensor(const uint8_t gpio, const std::string & name, const double offset, const double factor, const uint8_t uom, const int8_t type, const bool is_system);
|
||||||
~Sensor() = default;
|
~Sensor() = default;
|
||||||
|
|
||||||
void set_offset(const double offset) {
|
void set_offset(const double offset) {
|
||||||
@@ -44,7 +44,6 @@ class AnalogSensor {
|
|||||||
std::string name() const {
|
std::string name() const {
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_name(const std::string & name) {
|
void set_name(const std::string & name) {
|
||||||
name_ = name;
|
name_ = name;
|
||||||
}
|
}
|
||||||
@@ -61,10 +60,16 @@ class AnalogSensor {
|
|||||||
value_ = value;
|
value_ = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_system() const {
|
||||||
|
return is_system_;
|
||||||
|
}
|
||||||
|
void set_is_system(const bool is_system) {
|
||||||
|
is_system_ = is_system;
|
||||||
|
}
|
||||||
|
|
||||||
double factor() const {
|
double factor() const {
|
||||||
return factor_;
|
return factor_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_factor(const double factor) {
|
void set_factor(const double factor) {
|
||||||
factor_ = factor;
|
factor_ = factor;
|
||||||
}
|
}
|
||||||
@@ -76,7 +81,6 @@ class AnalogSensor {
|
|||||||
void set_uom(const uint8_t uom) {
|
void set_uom(const uint8_t uom) {
|
||||||
uom_ = uom;
|
uom_ = uom;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t uom() const {
|
uint8_t uom() const {
|
||||||
return uom_;
|
return uom_;
|
||||||
}
|
}
|
||||||
@@ -105,8 +109,9 @@ class AnalogSensor {
|
|||||||
double offset_;
|
double offset_;
|
||||||
double factor_;
|
double factor_;
|
||||||
uint8_t uom_;
|
uint8_t uom_;
|
||||||
double value_; // double because of the factor is a double
|
double value_; // double because of the factor is a double
|
||||||
int8_t type_; // one of the AnalogType enum
|
int8_t type_; // one of the AnalogType enum
|
||||||
|
bool is_system_; // if true, the sensor is a system sensor
|
||||||
};
|
};
|
||||||
|
|
||||||
AnalogSensor() = default;
|
AnalogSensor() = default;
|
||||||
@@ -161,13 +166,15 @@ class AnalogSensor {
|
|||||||
|
|
||||||
size_t count_entities(bool include_disabled = true) const {
|
size_t count_entities(bool include_disabled = true) const {
|
||||||
if (!include_disabled) {
|
if (!include_disabled) {
|
||||||
// count number of items in sensors_ where type is not set to disabled
|
// count number of items in sensors_ where type is not set to disabled and not a system sensor
|
||||||
return std::count_if(sensors_.begin(), sensors_.end(), [](const Sensor & sensor) { return sensor.type() != AnalogSensor::AnalogType::NOTUSED; });
|
return std::count_if(sensors_.begin(), sensors_.end(), [](const Sensor & sensor) {
|
||||||
|
return sensor.type() != AnalogSensor::AnalogType::NOTUSED && !sensor.is_system();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return sensors_.size();
|
return sensors_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool update(uint8_t gpio, std::string & name, double offset, double factor, uint8_t uom, int8_t type, bool deleted = false);
|
bool update(uint8_t gpio, std::string & name, double offset, double factor, uint8_t uom, int8_t type, bool deleted, bool is_system);
|
||||||
bool get_value_info(JsonObject output, const char * cmd, const int8_t id = -1);
|
bool get_value_info(JsonObject output, const char * cmd, const int8_t id = -1);
|
||||||
void store_counters();
|
void store_counters();
|
||||||
|
|
||||||
|
|||||||
@@ -592,6 +592,7 @@ bool Command::list(const uint8_t device_type, JsonObject output) {
|
|||||||
output["ap/enabled"] = Helpers::translated_word(FL_(system_cmd));
|
output["ap/enabled"] = Helpers::translated_word(FL_(system_cmd));
|
||||||
output["syslog/enabled"] = Helpers::translated_word(FL_(system_cmd));
|
output["syslog/enabled"] = Helpers::translated_word(FL_(system_cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a list of commands we have registered, and sort them
|
// create a list of commands we have registered, and sort them
|
||||||
std::list<std::string> sorted_cmds;
|
std::list<std::string> sorted_cmds;
|
||||||
for (const auto & cf : cmdfunctions_) {
|
for (const auto & cf : cmdfunctions_) {
|
||||||
|
|||||||
@@ -44,39 +44,39 @@ using string_vector = std::vector<const char *>;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
|
#define FPSTR(pstr_pointer) pstr_pointer
|
||||||
|
#define MAKE_WORD_CUSTOM(string_name, string_literal) static const char __pstr__##string_name[] = string_literal;
|
||||||
|
#define MAKE_WORD(string_name) MAKE_WORD_CUSTOM(string_name, #string_name)
|
||||||
|
|
||||||
|
#define F_(string_name) (__pstr__##string_name)
|
||||||
|
#define FL_(list_name) (__pstr__L_##list_name)
|
||||||
|
|
||||||
|
// Translation counter - capture baseline before any MAKE_TRANSLATION calls
|
||||||
|
enum { EMSESP_TRANSLATION_COUNT_START = __COUNTER__ };
|
||||||
|
|
||||||
#define FPSTR(pstr_pointer) pstr_pointer
|
// The language settings below must match system.cpp
|
||||||
#define MAKE_WORD_CUSTOM(string_name, string_literal) static const char __pstr__##string_name[] = string_literal;
|
#if defined(EMSESP_EN_ONLY)
|
||||||
#define MAKE_WORD(string_name) MAKE_WORD_CUSTOM(string_name, #string_name)
|
// EN only
|
||||||
|
#define MAKE_WORD_TRANSLATION(list_name, en, ...) static const char * const __pstr__L_##list_name[] = {en, nullptr};
|
||||||
#define F_(string_name) (__pstr__##string_name)
|
#define MAKE_TRANSLATION(list_name, shortname, en, ...) static constexpr int __translation_counter_##list_name = __COUNTER__; static const char * const __pstr__L_##list_name[] = {shortname, en, nullptr};
|
||||||
#define FL_(list_name) (__pstr__L_##list_name)
|
#elif defined(EMSESP_TEST) || defined(EMSESP_DE_ONLY)
|
||||||
|
// EN + DE (Test mode uses two languages to save flash memory)
|
||||||
// The language settings below must match system.cpp
|
#define MAKE_WORD_TRANSLATION(list_name, en, de, ...) static const char * const __pstr__L_##list_name[] = {en, de, nullptr};
|
||||||
#if defined(EMSESP_TEST)
|
#define MAKE_TRANSLATION(list_name, shortname, en, de, ...) static constexpr int __translation_counter_##list_name = __COUNTER__; static const char * const __pstr__L_##list_name[] = {shortname, en, de, nullptr};
|
||||||
// in Test mode use two languages (en & de) to save flash memory needed for the tests
|
#else
|
||||||
#define MAKE_WORD_TRANSLATION(list_name, en, de, ...) static const char * const __pstr__L_##list_name[] = {en, de, nullptr};
|
// All languages
|
||||||
#define MAKE_TRANSLATION(list_name, shortname, en, de, ...) static const char * const __pstr__L_##list_name[] = {shortname, en, de, nullptr};
|
#define MAKE_WORD_TRANSLATION(list_name, ...) static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr};
|
||||||
#elif defined(EMSESP_EN_ONLY)
|
#define MAKE_TRANSLATION(list_name, ...) static constexpr int __translation_counter_##list_name = __COUNTER__; static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr};
|
||||||
// EN only
|
#endif
|
||||||
#define MAKE_WORD_TRANSLATION(list_name, en, ...) static const char * const __pstr__L_##list_name[] = {en, nullptr};
|
|
||||||
#define MAKE_TRANSLATION(list_name, shortname, en, ...) static const char * const __pstr__L_##list_name[] = {shortname, en, nullptr};
|
#define MAKE_NOTRANSLATION(list_name, ...) static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr};
|
||||||
#elif defined(EMSESP_DE_ONLY)
|
|
||||||
// EN + DE
|
// fixed strings, no translations
|
||||||
#define MAKE_WORD_TRANSLATION(list_name, en, de, ...) static const char * const __pstr__L_##list_name[] = {en, de, nullptr};
|
#define MAKE_ENUM_FIXED(enum_name, ...) static const char * const __pstr__L_##enum_name[] = {__VA_ARGS__, nullptr};
|
||||||
#define MAKE_TRANSLATION(list_name, shortname, en, de, ...) static const char * const __pstr__L_##list_name[] = {shortname, en, de, nullptr};
|
|
||||||
#else
|
// with translations
|
||||||
#define MAKE_WORD_TRANSLATION(list_name, ...) static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr};
|
#define MAKE_ENUM(enum_name, ...) static const char * const * __pstr__L_##enum_name[] = {__VA_ARGS__, nullptr};
|
||||||
#define MAKE_TRANSLATION(list_name, ...) static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAKE_NOTRANSLATION(list_name, ...) static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr};
|
|
||||||
|
|
||||||
// fixed strings, no translations
|
|
||||||
#define MAKE_ENUM_FIXED(enum_name, ...) static const char * const __pstr__L_##enum_name[] = {__VA_ARGS__, nullptr};
|
|
||||||
|
|
||||||
// with translations
|
|
||||||
#define MAKE_ENUM(enum_name, ...) static const char * const * __pstr__L_##enum_name[] = {__VA_ARGS__, nullptr};
|
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@@ -84,4 +84,8 @@ using string_vector = std::vector<const char *>;
|
|||||||
#include "locale_translations.h"
|
#include "locale_translations.h"
|
||||||
#include "locale_common.h"
|
#include "locale_common.h"
|
||||||
|
|
||||||
|
// Translation count - dynamically calculated at compile-time
|
||||||
|
enum { EMSESP_TRANSLATION_COUNT_END = __COUNTER__ };
|
||||||
|
static constexpr uint16_t EMSESP_TRANSLATION_COUNT = EMSESP_TRANSLATION_COUNT_END - EMSESP_TRANSLATION_COUNT_START - 1;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -96,18 +96,35 @@ Preferences EMSESP::nvs_; // NV Storage
|
|||||||
// for a specific EMS device go and request data values
|
// for a specific EMS device go and request data values
|
||||||
// or if device_id is 0 it will fetch from all our known and active devices
|
// or if device_id is 0 it will fetch from all our known and active devices
|
||||||
void EMSESP::fetch_device_values(const uint8_t device_id) {
|
void EMSESP::fetch_device_values(const uint8_t device_id) {
|
||||||
for (const auto & emsdevice : emsdevices) {
|
// Early return if no devices
|
||||||
if ((device_id == 0) || emsdevice->is_device_id(device_id)) {
|
if (emsdevices.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If device_id is 0, fetch all
|
||||||
|
if (device_id == 0) {
|
||||||
|
for (const auto & emsdevice : emsdevices) {
|
||||||
emsdevice->fetch_values();
|
emsdevice->fetch_values();
|
||||||
if (device_id != 0) {
|
}
|
||||||
return; // quit, we only want to return the selected device
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch specific device
|
||||||
|
for (const auto & emsdevice : emsdevices) {
|
||||||
|
if (emsdevice->is_device_id(device_id)) {
|
||||||
|
emsdevice->fetch_values();
|
||||||
|
return; // quit, we only want to return the selected device
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// see if the deviceID exists
|
// see if the deviceID exists
|
||||||
bool EMSESP::valid_device(const uint8_t device_id) {
|
bool EMSESP::valid_device(const uint8_t device_id) {
|
||||||
|
// Early return if devices list is empty
|
||||||
|
if (emsdevices.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice && emsdevice->is_device_id(device_id)) {
|
if (emsdevice && emsdevice->is_device_id(device_id)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -118,6 +135,10 @@ bool EMSESP::valid_device(const uint8_t device_id) {
|
|||||||
|
|
||||||
// for a specific EMS device type go and request data values
|
// for a specific EMS device type go and request data values
|
||||||
void EMSESP::fetch_device_values_type(const uint8_t device_type) {
|
void EMSESP::fetch_device_values_type(const uint8_t device_type) {
|
||||||
|
if (emsdevices.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice && (emsdevice->device_type() == device_type)) {
|
if (emsdevice && (emsdevice->device_type() == device_type)) {
|
||||||
emsdevice->fetch_values();
|
emsdevice->fetch_values();
|
||||||
@@ -126,6 +147,10 @@ void EMSESP::fetch_device_values_type(const uint8_t device_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool EMSESP::cmd_is_readonly(const uint8_t device_type, const uint8_t device_id, const char * cmd, const int8_t id) {
|
bool EMSESP::cmd_is_readonly(const uint8_t device_type, const uint8_t device_id, const char * cmd, const int8_t id) {
|
||||||
|
if (emsdevices.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice && (emsdevice->device_type() == device_type) && (!device_id || emsdevice->device_id() == device_id)) {
|
if (emsdevice && (emsdevice->device_type() == device_type) && (!device_id || emsdevice->device_id() == device_id)) {
|
||||||
return emsdevice->is_readonly(cmd, id);
|
return emsdevice->is_readonly(cmd, id);
|
||||||
@@ -135,6 +160,10 @@ bool EMSESP::cmd_is_readonly(const uint8_t device_type, const uint8_t device_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t EMSESP::device_id_from_cmd(const uint8_t device_type, const char * cmd, const int8_t id) {
|
uint8_t EMSESP::device_id_from_cmd(const uint8_t device_type, const char * cmd, const int8_t id) {
|
||||||
|
if (emsdevices.empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice && emsdevice->device_type() == device_type && emsdevice->has_cmd(cmd, id)) {
|
if (emsdevice && emsdevice->device_type() == device_type && emsdevice->has_cmd(cmd, id)) {
|
||||||
return emsdevice->device_id();
|
return emsdevice->device_id();
|
||||||
@@ -151,10 +180,14 @@ void EMSESP::clear_all_devices() {
|
|||||||
|
|
||||||
// return number of devices of a known type
|
// return number of devices of a known type
|
||||||
uint8_t EMSESP::count_devices(const uint8_t device_type) {
|
uint8_t EMSESP::count_devices(const uint8_t device_type) {
|
||||||
|
if (emsdevices.empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice) {
|
if (emsdevice && emsdevice->device_type() == device_type) {
|
||||||
count += (emsdevice->device_type() == device_type);
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
@@ -162,10 +195,14 @@ uint8_t EMSESP::count_devices(const uint8_t device_type) {
|
|||||||
|
|
||||||
// return total number of devices excluding the Controller
|
// return total number of devices excluding the Controller
|
||||||
uint8_t EMSESP::count_devices() {
|
uint8_t EMSESP::count_devices() {
|
||||||
|
if (emsdevices.empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice) {
|
if (emsdevice && emsdevice->device_type() != EMSdevice::DeviceType::CONTROLLER) {
|
||||||
count += (emsdevice->device_type() != EMSdevice::DeviceType::CONTROLLER);
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
@@ -174,20 +211,22 @@ uint8_t EMSESP::count_devices() {
|
|||||||
// returns the index of a device if there are more of the same type
|
// returns the index of a device if there are more of the same type
|
||||||
// or 0 if there is only one or none
|
// or 0 if there is only one or none
|
||||||
uint8_t EMSESP::device_index(const uint8_t device_type, const uint8_t unique_id) {
|
uint8_t EMSESP::device_index(const uint8_t device_type, const uint8_t unique_id) {
|
||||||
if (count_devices(device_type) <= 1) {
|
uint8_t count = 0;
|
||||||
return 0; // none or only 1 device exists
|
uint8_t index = 0;
|
||||||
}
|
uint8_t current_index = 1;
|
||||||
uint8_t index = 1;
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice->device_type() == device_type) {
|
if (emsdevice->device_type() == device_type) {
|
||||||
// did we find it?
|
count++;
|
||||||
if (emsdevice->unique_id() == unique_id) {
|
if (emsdevice->unique_id() == unique_id) {
|
||||||
return index;
|
index = current_index;
|
||||||
}
|
}
|
||||||
index++;
|
current_index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0; // didn't find it
|
|
||||||
|
// Return 0 if only one device exists or not found
|
||||||
|
return (count <= 1) ? 0 : index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// scans for new devices
|
// scans for new devices
|
||||||
@@ -242,13 +281,8 @@ uint8_t EMSESP::bus_status() {
|
|||||||
uint32_t total_fail = txservice_.telegram_read_fail_count() + txservice_.telegram_write_fail_count();
|
uint32_t total_fail = txservice_.telegram_read_fail_count() + txservice_.telegram_write_fail_count();
|
||||||
|
|
||||||
// nothing sent and also no errors - must be ok
|
// nothing sent and also no errors - must be ok
|
||||||
if ((total_sent == 0) && (total_fail == 0)) {
|
if (total_sent == 0) {
|
||||||
return BUS_STATUS_CONNECTED;
|
return (total_fail == 0) ? BUS_STATUS_CONNECTED : BUS_STATUS_TX_ERRORS;
|
||||||
}
|
|
||||||
|
|
||||||
// nothing sent, but have Tx errors
|
|
||||||
if ((total_sent == 0) && (total_fail != 0)) {
|
|
||||||
return BUS_STATUS_TX_ERRORS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tx Failure rate > 10%
|
// Tx Failure rate > 10%
|
||||||
@@ -288,7 +322,7 @@ void EMSESP::show_ems(uuid::console::Shell & shell) {
|
|||||||
shell.printfln(" #read fails (after %d retries): %d", TxService::MAXIMUM_TX_RETRIES, txservice_.telegram_read_fail_count());
|
shell.printfln(" #read fails (after %d retries): %d", TxService::MAXIMUM_TX_RETRIES, txservice_.telegram_read_fail_count());
|
||||||
shell.printfln(" #write fails (after %d retries): %d", TxService::MAXIMUM_TX_RETRIES, txservice_.telegram_write_fail_count());
|
shell.printfln(" #write fails (after %d retries): %d", TxService::MAXIMUM_TX_RETRIES, txservice_.telegram_write_fail_count());
|
||||||
shell.printfln(" Rx line quality: %d%%", rxservice_.quality());
|
shell.printfln(" Rx line quality: %d%%", rxservice_.quality());
|
||||||
shell.printfln(" Tx line quality: %d%%", (txservice_.read_quality() + txservice_.read_quality()) / 2);
|
shell.printfln(" Tx line quality: %d%%", (txservice_.read_quality() + txservice_.write_quality()) / 2);
|
||||||
shell.println();
|
shell.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,16 +545,21 @@ void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
|
|||||||
|
|
||||||
for (const auto & sensor : temperaturesensor_.sensors()) {
|
for (const auto & sensor : temperaturesensor_.sensors()) {
|
||||||
if (Helpers::hasValue(sensor.temperature_c)) {
|
if (Helpers::hasValue(sensor.temperature_c)) {
|
||||||
shell.printfln(" %s: %s%s °%c%s (offset %s, ID: %s)",
|
shell.printfln(" %s: %s%s °%c%s (Offset: %s, ID: %s, System: %s)",
|
||||||
sensor.name().c_str(),
|
sensor.name().c_str(),
|
||||||
COLOR_BRIGHT_GREEN,
|
COLOR_BRIGHT_GREEN,
|
||||||
Helpers::render_value(s, sensor.temperature_c, 10, fahrenheit),
|
Helpers::render_value(s, sensor.temperature_c, 10, fahrenheit),
|
||||||
(fahrenheit == 0) ? 'C' : 'F',
|
(fahrenheit == 0) ? 'C' : 'F',
|
||||||
COLOR_RESET,
|
COLOR_RESET,
|
||||||
Helpers::render_value(s2, sensor.offset(), 10, fahrenheit),
|
Helpers::render_value(s2, sensor.offset(), 10, fahrenheit),
|
||||||
sensor.id().c_str());
|
sensor.id().c_str(),
|
||||||
|
sensor.is_system() ? "Yes" : "No");
|
||||||
} else {
|
} else {
|
||||||
shell.printfln(" %s (offset %s, ID: %s)", sensor.name().c_str(), Helpers::render_value(s, sensor.offset(), 10, fahrenheit), sensor.id().c_str());
|
shell.printfln(" %s (Offset: %s, ID: %s, System: %s)",
|
||||||
|
sensor.name().c_str(),
|
||||||
|
Helpers::render_value(s, sensor.offset(), 10, fahrenheit),
|
||||||
|
sensor.id().c_str(),
|
||||||
|
sensor.is_system() ? "Yes" : "No");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shell.println();
|
shell.println();
|
||||||
@@ -529,18 +568,20 @@ void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
|
|||||||
if (analogsensor_.have_sensors()) {
|
if (analogsensor_.have_sensors()) {
|
||||||
char s[10];
|
char s[10];
|
||||||
char s2[10];
|
char s2[10];
|
||||||
|
char s3[10];
|
||||||
shell.printfln("Analog sensors:");
|
shell.printfln("Analog sensors:");
|
||||||
for (const auto & sensor : analogsensor_.sensors()) {
|
for (const auto & sensor : analogsensor_.sensors()) {
|
||||||
switch (sensor.type()) {
|
switch (sensor.type()) {
|
||||||
case AnalogSensor::AnalogType::ADC:
|
case AnalogSensor::AnalogType::ADC:
|
||||||
shell.printfln(" %s: %s%s %s%s (Type: ADC, Factor: %s, Offset: %d)",
|
shell.printfln(" %s: %s%s %s%s (Type: ADC, Factor: %s, Offset: %s, System: %s)",
|
||||||
sensor.name().c_str(),
|
sensor.name().c_str(),
|
||||||
COLOR_BRIGHT_GREEN,
|
COLOR_BRIGHT_GREEN,
|
||||||
Helpers::render_value(s, sensor.value(), 2),
|
Helpers::render_value(s, sensor.value(), 2),
|
||||||
EMSdevice::uom_to_string(sensor.uom()),
|
EMSdevice::uom_to_string(sensor.uom()),
|
||||||
COLOR_RESET,
|
COLOR_RESET,
|
||||||
Helpers::render_value(s2, sensor.factor(), 4),
|
Helpers::render_value(s2, sensor.factor(), 4),
|
||||||
sensor.offset());
|
Helpers::render_value(s3, sensor.offset(), 2),
|
||||||
|
sensor.is_system() ? "Yes" : "No");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// case AnalogSensor::AnalogType::DIGITAL_IN:
|
// case AnalogSensor::AnalogType::DIGITAL_IN:
|
||||||
@@ -846,41 +887,58 @@ std::string EMSESP::pretty_telegram(std::shared_ptr<const Telegram> telegram) {
|
|||||||
std::string src_name("");
|
std::string src_name("");
|
||||||
std::string dest_name("");
|
std::string dest_name("");
|
||||||
std::string type_name("");
|
std::string type_name("");
|
||||||
|
|
||||||
|
// Single loop to find all device information
|
||||||
|
bool src_found = false;
|
||||||
|
bool dest_found = false;
|
||||||
|
bool type_found = false;
|
||||||
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
// get src & dest
|
// get src name
|
||||||
if (emsdevice->is_device_id(src)) {
|
if (!src_found && emsdevice->is_device_id(src)) {
|
||||||
src_name = emsdevice->device_type_name();
|
src_name = emsdevice->device_type_name();
|
||||||
} else if (emsdevice->is_device_id(dest)) {
|
src_found = true;
|
||||||
dest_name = emsdevice->device_type_name();
|
|
||||||
}
|
}
|
||||||
// get the type name
|
|
||||||
if (type_name.empty()) {
|
// get dest name
|
||||||
|
if (!dest_found && emsdevice->is_device_id(dest)) {
|
||||||
|
dest_name = emsdevice->device_type_name();
|
||||||
|
dest_found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the type name (try primary conditions first)
|
||||||
|
if (!type_found) {
|
||||||
if ((telegram->operation == Telegram::Operation::RX_READ && emsdevice->is_device_id(dest))
|
if ((telegram->operation == Telegram::Operation::RX_READ && emsdevice->is_device_id(dest))
|
||||||
|| (telegram->operation != Telegram::Operation::RX_READ && dest == 0 && emsdevice->is_device_id(src))
|
|| (telegram->operation != Telegram::Operation::RX_READ && dest == 0 && emsdevice->is_device_id(src))
|
||||||
|| (telegram->operation != Telegram::Operation::RX_READ && src == EMSbus::ems_bus_id() && emsdevice->is_device_id(dest))) {
|
|| (telegram->operation != Telegram::Operation::RX_READ && src == EMSbus::ems_bus_id() && emsdevice->is_device_id(dest))) {
|
||||||
type_name = emsdevice->telegram_type_name(telegram);
|
type_name = emsdevice->telegram_type_name(telegram);
|
||||||
|
if (!type_name.empty()) {
|
||||||
|
type_found = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Early exit if we found everything
|
||||||
|
if (src_found && dest_found && type_found) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (type_name.empty()) {
|
|
||||||
// fallback, get the type name from src
|
// Fallback for type name if not found - try src first, then dest
|
||||||
for (const auto & emsdevice : emsdevices) {
|
if (!type_found && telegram->operation != Telegram::Operation::RX_READ) {
|
||||||
if (telegram->operation != Telegram::Operation::RX_READ && emsdevice->is_device_id(src)) {
|
for (int i = 0; i < 2 && type_name.empty(); ++i) {
|
||||||
type_name = emsdevice->telegram_type_name(telegram);
|
uint8_t check_id = (i == 0) ? src : dest;
|
||||||
break;
|
for (const auto & emsdevice : emsdevices) {
|
||||||
|
if (emsdevice->is_device_id(check_id)) {
|
||||||
|
type_name = emsdevice->telegram_type_name(telegram);
|
||||||
|
if (!type_name.empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type_name.empty()) {
|
|
||||||
// 2nd fallback, get the type name from dest
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
|
||||||
if (telegram->operation != Telegram::Operation::RX_READ && emsdevice->is_device_id(dest)) {
|
|
||||||
type_name = emsdevice->telegram_type_name(telegram);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if we can't find names for the devices, use their hex values
|
// if we can't find names for the devices, use their hex values
|
||||||
if (src_name.empty()) {
|
if (src_name.empty()) {
|
||||||
src_name = device_tostring(src);
|
src_name = device_tostring(src);
|
||||||
@@ -1009,11 +1067,16 @@ void EMSESP::process_version(std::shared_ptr<const Telegram> telegram) {
|
|||||||
if (telegram->offset != 0) {
|
if (telegram->offset != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint8_t msg_len = telegram->message_length;
|
||||||
|
|
||||||
// for empty telegram add device with empty product, version and brand
|
// for empty telegram add device with empty product, version and brand
|
||||||
if (telegram->message_length == 0) {
|
if (msg_len == 0) {
|
||||||
(void)add_device(telegram->src, 0, "00.00", 0);
|
(void)add_device(telegram->src, 0, "00.00", 0);
|
||||||
return;
|
return;
|
||||||
} else if (telegram->message_length < 3) {
|
}
|
||||||
|
|
||||||
|
if (msg_len < 3) {
|
||||||
(void)add_device(telegram->src, telegram->message_data[0], "00.00", 0);
|
(void)add_device(telegram->src, telegram->message_data[0], "00.00", 0);
|
||||||
send_read_request(EMSdevice::EMS_TYPE_NAME, telegram->src, 27);
|
send_read_request(EMSdevice::EMS_TYPE_NAME, telegram->src, 27);
|
||||||
return;
|
return;
|
||||||
@@ -1023,7 +1086,7 @@ void EMSESP::process_version(std::shared_ptr<const Telegram> telegram) {
|
|||||||
uint8_t offset = 0;
|
uint8_t offset = 0;
|
||||||
if (telegram->message_data[0] == 0x00) {
|
if (telegram->message_data[0] == 0x00) {
|
||||||
// see if we have a 2nd subscriber
|
// see if we have a 2nd subscriber
|
||||||
if (telegram->message_length > 5 && telegram->message_data[3] != 0x00) {
|
if (msg_len > 5 && telegram->message_data[3] != 0x00) {
|
||||||
offset = 3;
|
offset = 3;
|
||||||
} else {
|
} else {
|
||||||
return; // ignore whole telegram
|
return; // ignore whole telegram
|
||||||
@@ -1040,7 +1103,7 @@ void EMSESP::process_version(std::shared_ptr<const Telegram> telegram) {
|
|||||||
|
|
||||||
// some devices store the protocol type (HT3, Buderus) in the last byte
|
// some devices store the protocol type (HT3, Buderus) in the last byte
|
||||||
uint8_t brand;
|
uint8_t brand;
|
||||||
if (telegram->message_length >= 10) {
|
if (msg_len >= 10) {
|
||||||
brand = EMSdevice::decode_brand(telegram->message_data[9]);
|
brand = EMSdevice::decode_brand(telegram->message_data[9]);
|
||||||
} else {
|
} else {
|
||||||
brand = EMSdevice::Brand::NO_BRAND; // unknown
|
brand = EMSdevice::Brand::NO_BRAND; // unknown
|
||||||
@@ -1116,57 +1179,53 @@ bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
|
|||||||
// calls the associated process function for that EMS device
|
// calls the associated process function for that EMS device
|
||||||
// returns false if the device_id doesn't recognize it
|
// returns false if the device_id doesn't recognize it
|
||||||
// after the telegram has been processed, see if there have been values changed and we need to do a MQTT publish
|
// after the telegram has been processed, see if there have been values changed and we need to do a MQTT publish
|
||||||
bool telegram_found = false;
|
bool telegram_found = false;
|
||||||
uint8_t device_found = 0;
|
uint8_t device_found = 0;
|
||||||
// broadcast or send to us
|
EMSdevice * found_device = nullptr;
|
||||||
|
|
||||||
|
// Combined loop: check all conditions in a single pass
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
|
// broadcast or send to us
|
||||||
if (emsdevice->is_device_id(telegram->src) && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id())) {
|
if (emsdevice->is_device_id(telegram->src) && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id())) {
|
||||||
telegram_found = emsdevice->handle_telegram(telegram);
|
telegram_found = emsdevice->handle_telegram(telegram);
|
||||||
device_found = emsdevice->unique_id();
|
found_device = emsdevice.get();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!telegram_found) {
|
|
||||||
// check for command to the device
|
// check for command to the device
|
||||||
for (const auto & emsdevice : emsdevices) {
|
if (!telegram_found && emsdevice->is_device_id(telegram->dest) && telegram->src != EMSbus::ems_bus_id()) {
|
||||||
if (emsdevice->is_device_id(telegram->dest) && telegram->src != EMSbus::ems_bus_id()) {
|
telegram_found = emsdevice->handle_telegram(telegram);
|
||||||
telegram_found = emsdevice->handle_telegram(telegram);
|
found_device = emsdevice.get();
|
||||||
device_found = emsdevice->unique_id();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!telegram_found) {
|
|
||||||
// check for sends to master thermostat
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
|
||||||
if (emsdevice->is_device_id(telegram->src) && telegram->dest == 0x10) {
|
|
||||||
telegram_found = emsdevice->handle_telegram(telegram);
|
|
||||||
device_found = emsdevice->unique_id();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
|
||||||
if (emsdevice->unique_id() == device_found) {
|
|
||||||
if (!telegram_found && telegram->message_length > 0) {
|
|
||||||
emsdevice->add_handlers_ignored(telegram->type_id);
|
|
||||||
}
|
|
||||||
if (wait_validate_ == telegram->type_id) {
|
|
||||||
wait_validate_ = 0;
|
|
||||||
}
|
|
||||||
if (Mqtt::connected() && telegram_found
|
|
||||||
&& ((mqtt_.get_publish_onchange(emsdevice->device_type()) && emsdevice->has_update())
|
|
||||||
|| (telegram->type_id == publish_id_ && telegram->dest == EMSbus::ems_bus_id()))) {
|
|
||||||
if (telegram->type_id == publish_id_) {
|
|
||||||
publish_id_ = 0;
|
|
||||||
}
|
|
||||||
emsdevice->has_update(false); // reset flag
|
|
||||||
if (!Mqtt::publish_single()) {
|
|
||||||
publish_device_values(emsdevice->device_type()); // publish to MQTT if we explicitly have too
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// check for sends to master thermostat
|
||||||
|
if (!telegram_found && emsdevice->is_device_id(telegram->src) && telegram->dest == 0x10) {
|
||||||
|
telegram_found = emsdevice->handle_telegram(telegram);
|
||||||
|
found_device = emsdevice.get();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_device) {
|
||||||
|
device_found = found_device->unique_id();
|
||||||
|
|
||||||
|
// Process the found device directly without another loop
|
||||||
|
if (!telegram_found && telegram->message_length > 0) {
|
||||||
|
found_device->add_handlers_ignored(telegram->type_id);
|
||||||
|
}
|
||||||
|
if (wait_validate_ == telegram->type_id) {
|
||||||
|
wait_validate_ = 0;
|
||||||
|
}
|
||||||
|
if (Mqtt::connected() && telegram_found
|
||||||
|
&& ((mqtt_.get_publish_onchange(found_device->device_type()) && found_device->has_update())
|
||||||
|
|| (telegram->type_id == publish_id_ && telegram->dest == EMSbus::ems_bus_id()))) {
|
||||||
|
if (telegram->type_id == publish_id_) {
|
||||||
|
publish_id_ = 0;
|
||||||
|
}
|
||||||
|
found_device->has_update(false); // reset flag
|
||||||
|
if (!Mqtt::publish_single()) {
|
||||||
|
publish_device_values(found_device->device_type()); // publish to MQTT if we explicitly have too
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// handle unknown broadcasted telegrams (or send to us)
|
// handle unknown broadcasted telegrams (or send to us)
|
||||||
if (!telegram_found && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id())) {
|
if (!telegram_found && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id())) {
|
||||||
@@ -1184,6 +1243,10 @@ bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
|
|||||||
|
|
||||||
// return true if we have this device already registered
|
// return true if we have this device already registered
|
||||||
bool EMSESP::device_exists(const uint8_t device_id) {
|
bool EMSESP::device_exists(const uint8_t device_id) {
|
||||||
|
if (emsdevices.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice && emsdevice->is_device_id(device_id)) {
|
if (emsdevice && emsdevice->is_device_id(device_id)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -1251,16 +1314,14 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// first check to see if we already have it, if so update the record
|
// first check to see if we already have it, if so update the record
|
||||||
auto it = emsdevices.begin();
|
for (auto it = emsdevices.begin(); it != emsdevices.end(); ++it) {
|
||||||
for (const auto & emsdevice : emsdevices) {
|
if ((*it) && (*it)->is_device_id(device_id)) {
|
||||||
if (emsdevice && emsdevice->is_device_id(device_id)) {
|
if (product_id == 0 || (*it)->product_id() != 0) { // update only with valid product_id
|
||||||
if (product_id == 0 || emsdevice->product_id() != 0) { // update only with valid product_id
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
emsdevices.erase(it); // erase the old device without product_id and re detect
|
emsdevices.erase(it); // erase the old device without product_id and re detect
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
it++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// look up the rest of the details using the product_id and create the new device object
|
// look up the rest of the details using the product_id and create the new device object
|
||||||
@@ -1691,7 +1752,7 @@ void EMSESP::start() {
|
|||||||
device_library_ = {
|
device_library_ = {
|
||||||
#include "device_library.h"
|
#include "device_library.h"
|
||||||
};
|
};
|
||||||
LOG_INFO("Loaded EMS device library (%d entries)", device_library_.size());
|
LOG_INFO("Library loaded: %d EMS devices, %d device entities, %s", device_library_.size(), EMSESP_TRANSLATION_COUNT, system_.languages_string().c_str());
|
||||||
|
|
||||||
system_.reload_settings(); // ... and store some of the settings locally
|
system_.reload_settings(); // ... and store some of the settings locally
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,19 @@ bool System::command_send(const char * value, const int8_t id) {
|
|||||||
return EMSESP::txservice_.send_raw(value); // ignore id
|
return EMSESP::txservice_.send_raw(value); // ignore id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return string of languages and count
|
||||||
|
std::string System::languages_string() {
|
||||||
|
std::string languages_string = std::to_string(NUM_LANGUAGES) + " languages (";
|
||||||
|
for (uint8_t i = 0; i < NUM_LANGUAGES; i++) {
|
||||||
|
languages_string += languages[i];
|
||||||
|
if (i != NUM_LANGUAGES - 1) {
|
||||||
|
languages_string += ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
languages_string += ")";
|
||||||
|
return languages_string;
|
||||||
|
}
|
||||||
|
|
||||||
// returns last response from MQTT
|
// returns last response from MQTT
|
||||||
bool System::command_response(const char * value, const int8_t id, JsonObject output) {
|
bool System::command_response(const char * value, const int8_t id, JsonObject output) {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
@@ -523,8 +536,18 @@ void System::button_OnClick(PButton & b) {
|
|||||||
|
|
||||||
// button double click
|
// button double click
|
||||||
void System::button_OnDblClick(PButton & b) {
|
void System::button_OnDblClick(PButton & b) {
|
||||||
LOG_NOTICE("Button pressed - double click - wifi reconnect");
|
LOG_NOTICE("Button pressed - double click - wifi reconnect to AP");
|
||||||
EMSESP::system_.wifi_reconnect();
|
// set AP mode to always so will join AP if wifi ssid fails to connect
|
||||||
|
EMSESP::esp32React.getAPSettingsService()->update([&](APSettings & apSettings) {
|
||||||
|
apSettings.provisionMode = AP_MODE_ALWAYS;
|
||||||
|
return StateUpdateResult::CHANGED;
|
||||||
|
});
|
||||||
|
// remove SSID from network settings
|
||||||
|
EMSESP::esp32React.getNetworkSettingsService()->update([&](NetworkSettings & networkSettings) {
|
||||||
|
networkSettings.ssid = "";
|
||||||
|
return StateUpdateResult::CHANGED;
|
||||||
|
});
|
||||||
|
EMSESP::esp32React.getNetworkSettingsService()->callUpdateHandlers(); // in case we've changed ssid or password
|
||||||
}
|
}
|
||||||
|
|
||||||
// button long press
|
// button long press
|
||||||
@@ -1439,6 +1462,7 @@ bool System::command_service(const char * cmd, const char * value) {
|
|||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
if (!ok && Helpers::value2number(value, n)) {
|
if (!ok && Helpers::value2number(value, n)) {
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
@@ -1647,26 +1671,38 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
|
||||||
EMSESP::esp32React.getAPSettingsService()->read([&](const APSettings & settings) {
|
|
||||||
const char * pM[] = {"always", "disconnected", "never"};
|
|
||||||
node["APProvisionMode"] = pM[settings.provisionMode];
|
|
||||||
node["APSecurity"] = settings.password.length() ? "wpa2" : "open";
|
|
||||||
node["APSSID"] = settings.ssid;
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// NTP status
|
// NTP status
|
||||||
node = output["ntp"].to<JsonObject>();
|
node = output["ntp"].to<JsonObject>();
|
||||||
#ifndef EMSESP_STANDALONE
|
|
||||||
node["NTPStatus"] = EMSESP::system_.ntp_connected() ? "connected" : "disconnected";
|
|
||||||
EMSESP::esp32React.getNTPSettingsService()->read([&](const NTPSettings & settings) {
|
EMSESP::esp32React.getNTPSettingsService()->read([&](const NTPSettings & settings) {
|
||||||
|
#ifndef EMSESP_STANDALONE
|
||||||
node["enabled"] = settings.enabled;
|
node["enabled"] = settings.enabled;
|
||||||
|
#else
|
||||||
|
node["enabled"] = true;
|
||||||
|
#endif
|
||||||
node["server"] = settings.server;
|
node["server"] = settings.server;
|
||||||
node["tzLabel"] = settings.tzLabel;
|
node["tzLabel"] = settings.tzLabel;
|
||||||
});
|
});
|
||||||
|
#ifndef EMSESP_STANDALONE
|
||||||
node["timestamp"] = time(nullptr);
|
node["timestamp"] = time(nullptr);
|
||||||
#endif
|
#endif
|
||||||
|
node["NTPStatus"] = EMSESP::system_.ntp_connected() ? "connected" : "disconnected";
|
||||||
|
|
||||||
|
// AP Status
|
||||||
|
node = output["ap"].to<JsonObject>();
|
||||||
|
EMSESP::esp32React.getAPSettingsService()->read([&](const APSettings & settings) {
|
||||||
|
const char * pM[] = {"always", "disconnected", "never"};
|
||||||
|
node["provisionMode"] = pM[settings.provisionMode];
|
||||||
|
node["ssid"] = settings.ssid;
|
||||||
|
#ifndef EMSESP_STANDALONE
|
||||||
|
node["security"] = settings.password.length() ? "wpa2" : "open";
|
||||||
|
node["channel"] = settings.channel;
|
||||||
|
node["ssidHidden"] = settings.ssidHidden;
|
||||||
|
node["maxClients"] = settings.maxClients;
|
||||||
|
node["localIP"] = settings.localIP.toString();
|
||||||
|
node["gatewayIP"] = settings.gatewayIP.toString();
|
||||||
|
node["subnetMask"] = settings.subnetMask.toString();
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
// MQTT Status
|
// MQTT Status
|
||||||
node = output["mqtt"].to<JsonObject>();
|
node = output["mqtt"].to<JsonObject>();
|
||||||
@@ -1764,7 +1800,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output
|
|||||||
node["busReadsFailed"] = EMSESP::txservice_.telegram_read_fail_count();
|
node["busReadsFailed"] = EMSESP::txservice_.telegram_read_fail_count();
|
||||||
node["busWritesFailed"] = EMSESP::txservice_.telegram_write_fail_count();
|
node["busWritesFailed"] = EMSESP::txservice_.telegram_write_fail_count();
|
||||||
node["busRxLineQuality"] = EMSESP::rxservice_.quality();
|
node["busRxLineQuality"] = EMSESP::rxservice_.quality();
|
||||||
node["busTxLineQuality"] = (EMSESP::txservice_.read_quality() + EMSESP::txservice_.read_quality()) / 2;
|
node["busTxLineQuality"] = (EMSESP::txservice_.read_quality() + EMSESP::txservice_.write_quality()) / 2;
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
node = output["settings"].to<JsonObject>();
|
node = output["settings"].to<JsonObject>();
|
||||||
@@ -1958,15 +1994,12 @@ bool System::load_board_profile(std::vector<int8_t> & data, const std::string &
|
|||||||
|
|
||||||
// format command - factory reset, removing all config files
|
// format command - factory reset, removing all config files
|
||||||
bool System::command_format(const char * value, const int8_t id) {
|
bool System::command_format(const char * value, const int8_t id) {
|
||||||
LOG_INFO("Removing all config files");
|
LOG_INFO("Formatting FS, removing all config files");
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
// TODO To replaced with LittleFS.rmdir(FS_CONFIG_DIRECTORY) now we're using IDF 4.2+
|
if (LittleFS.format()) {
|
||||||
File root = LittleFS.open(EMSESP_FS_CONFIG_DIRECTORY);
|
LOG_INFO("FS formatted successfully");
|
||||||
File file;
|
} else {
|
||||||
while ((file = root.openNextFile())) {
|
LOG_ERROR("Format failed");
|
||||||
String path = file.path();
|
|
||||||
file.close();
|
|
||||||
LittleFS.remove(path);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -291,6 +291,8 @@ class System {
|
|||||||
void wifi_reconnect();
|
void wifi_reconnect();
|
||||||
void show_users(uuid::console::Shell & shell);
|
void show_users(uuid::console::Shell & shell);
|
||||||
|
|
||||||
|
static std::string languages_string();
|
||||||
|
|
||||||
uint32_t FStotal() {
|
uint32_t FStotal() {
|
||||||
return fstotal_;
|
return fstotal_;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,11 +217,13 @@ void TemperatureSensor::loop() {
|
|||||||
if (!EMSESP::nvs_.isKey("intTemp")) {
|
if (!EMSESP::nvs_.isKey("intTemp")) {
|
||||||
EMSESP::nvs_.putString("intTemp", s->id().c_str());
|
EMSESP::nvs_.putString("intTemp", s->id().c_str());
|
||||||
}
|
}
|
||||||
|
s->set_is_system(true); // mark as internal system temperature sensor
|
||||||
EMSESP::webCustomizationService.update([&](WebCustomization & settings) {
|
EMSESP::webCustomizationService.update([&](WebCustomization & settings) {
|
||||||
auto newSensor = SensorCustomization();
|
auto newSensor = SensorCustomization();
|
||||||
newSensor.id = s->id();
|
newSensor.id = s->id();
|
||||||
newSensor.name = s->name();
|
newSensor.name = s->name();
|
||||||
newSensor.offset = 0;
|
newSensor.offset = 0;
|
||||||
|
newSensor.is_system = s->is_system(); // always true
|
||||||
settings.sensorCustomizations.push_back(newSensor);
|
settings.sensorCustomizations.push_back(newSensor);
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
});
|
});
|
||||||
@@ -313,7 +315,7 @@ int16_t TemperatureSensor::get_temperature_c(const uint8_t addr[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update temperature sensor information name and offset
|
// update temperature sensor information name and offset
|
||||||
bool TemperatureSensor::update(const std::string & id, const std::string & name, int16_t offset) {
|
bool TemperatureSensor::update(const std::string & id, const std::string & name, int16_t offset, bool is_system) {
|
||||||
// find the sensor
|
// find the sensor
|
||||||
for (auto & sensor : sensors_) {
|
for (auto & sensor : sensors_) {
|
||||||
if (sensor.id() == id) {
|
if (sensor.id() == id) {
|
||||||
@@ -329,23 +331,25 @@ bool TemperatureSensor::update(const std::string & id, const std::string & name,
|
|||||||
sensor.set_offset(offset);
|
sensor.set_offset(offset);
|
||||||
|
|
||||||
// store the new name and offset in our configuration
|
// store the new name and offset in our configuration
|
||||||
EMSESP::webCustomizationService.update([&id, &name, &offset, &sensor](WebCustomization & settings) {
|
EMSESP::webCustomizationService.update([&id, &name, &offset, &is_system, &sensor](WebCustomization & settings) {
|
||||||
// look it up to see if it exists
|
// look it up to see if it exists
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto & SensorCustomization : settings.sensorCustomizations) {
|
for (auto & SensorCustomization : settings.sensorCustomizations) {
|
||||||
if (SensorCustomization.id == id) {
|
if (SensorCustomization.id == id) {
|
||||||
SensorCustomization.name = name;
|
SensorCustomization.name = name;
|
||||||
SensorCustomization.offset = offset;
|
SensorCustomization.offset = offset;
|
||||||
found = true;
|
SensorCustomization.is_system = is_system;
|
||||||
|
found = true;
|
||||||
LOG_DEBUG("Customizing existing sensor ID %s", id.c_str());
|
LOG_DEBUG("Customizing existing sensor ID %s", id.c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
auto newSensor = SensorCustomization();
|
auto newSensor = SensorCustomization();
|
||||||
newSensor.id = id;
|
newSensor.id = id;
|
||||||
newSensor.name = name;
|
newSensor.name = name;
|
||||||
newSensor.offset = offset;
|
newSensor.offset = offset;
|
||||||
|
newSensor.is_system = false; // is user defined, not system
|
||||||
settings.sensorCustomizations.push_back(newSensor);
|
settings.sensorCustomizations.push_back(newSensor);
|
||||||
LOG_DEBUG("Adding new customization for sensor ID %s", id.c_str());
|
LOG_DEBUG("Adding new customization for sensor ID %s", id.c_str());
|
||||||
}
|
}
|
||||||
@@ -628,6 +632,7 @@ void TemperatureSensor::load_test_data() {
|
|||||||
sensors_.back().apply_customization();
|
sensors_.back().apply_customization();
|
||||||
sensors_.back().temperature_c = 123; // 12.3
|
sensors_.back().temperature_c = 123; // 12.3
|
||||||
sensors_.back().read = true;
|
sensors_.back().read = true;
|
||||||
|
sensors_.back().set_is_system(false);
|
||||||
publish_sensor(sensors_.back()); // call publish single
|
publish_sensor(sensors_.back()); // call publish single
|
||||||
|
|
||||||
// Sensor ID: 0B_0C0D_0E0F_1011
|
// Sensor ID: 0B_0C0D_0E0F_1011
|
||||||
@@ -636,6 +641,16 @@ void TemperatureSensor::load_test_data() {
|
|||||||
sensors_.back().apply_customization();
|
sensors_.back().apply_customization();
|
||||||
sensors_.back().temperature_c = 456; // 45.6
|
sensors_.back().temperature_c = 456; // 45.6
|
||||||
sensors_.back().read = true;
|
sensors_.back().read = true;
|
||||||
|
sensors_.back().set_is_system(false);
|
||||||
|
publish_sensor(sensors_.back()); // call publish single
|
||||||
|
|
||||||
|
// Sensor ID: 28_1767_7B13_2502
|
||||||
|
uint8_t addr3[ADDR_LEN] = {0x28, 0x17, 0x67, 0x7B, 0x13, 0x25, 0x02};
|
||||||
|
sensors_.emplace_back(addr3);
|
||||||
|
sensors_.back().apply_customization();
|
||||||
|
sensors_.back().temperature_c = 281; // 28.1
|
||||||
|
sensors_.back().read = true;
|
||||||
|
sensors_.back().set_is_system(true);
|
||||||
publish_sensor(sensors_.back()); // call publish single
|
publish_sensor(sensors_.back()); // call publish single
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -44,6 +44,13 @@ class TemperatureSensor {
|
|||||||
return internal_id_;
|
return internal_id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_system() const {
|
||||||
|
return is_system_;
|
||||||
|
}
|
||||||
|
void set_is_system(const bool is_system) {
|
||||||
|
is_system_ = is_system;
|
||||||
|
}
|
||||||
|
|
||||||
std::string id() const {
|
std::string id() const {
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
@@ -72,6 +79,7 @@ class TemperatureSensor {
|
|||||||
std::string id_;
|
std::string id_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
int16_t offset_;
|
int16_t offset_;
|
||||||
|
bool is_system_;
|
||||||
};
|
};
|
||||||
|
|
||||||
TemperatureSensor() = default;
|
TemperatureSensor() = default;
|
||||||
@@ -106,11 +114,13 @@ class TemperatureSensor {
|
|||||||
return (!sensors_.empty());
|
return (!sensors_.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t count_entities() const {
|
size_t count_entities(bool include_system = true) const {
|
||||||
return sensors_.size();
|
return std::count_if(sensors_.begin(), sensors_.end(), [include_system](const Sensor & sensor) {
|
||||||
|
return include_system ? sensor.is_system() : !sensor.is_system();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool update(const std::string & id, const std::string & name, int16_t offset);
|
bool update(const std::string & id, const std::string & name, int16_t offset, bool is_system);
|
||||||
|
|
||||||
#if defined(EMSESP_TEST)
|
#if defined(EMSESP_TEST)
|
||||||
void load_test_data();
|
void load_test_data();
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "3.7.3-dev.25"
|
#define EMSESP_APP_VERSION "3.7.3-dev.26"
|
||||||
|
|||||||
@@ -880,7 +880,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
shell.invoke_command("call system publish");
|
shell.invoke_command("call system publish");
|
||||||
|
|
||||||
// rename
|
// rename
|
||||||
EMSESP::temperaturesensor_.update("01_0203_0405_0607", "testtemperature", 2);
|
EMSESP::temperaturesensor_.update("01_0203_0405_0607", "testtemperature", 2, false);
|
||||||
shell.invoke_command("show values");
|
shell.invoke_command("show values");
|
||||||
shell.invoke_command("call system publish");
|
shell.invoke_command("call system publish");
|
||||||
ok = true;
|
ok = true;
|
||||||
|
|||||||
@@ -52,24 +52,25 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
|
|||||||
void WebCustomization::read(WebCustomization & customizations, JsonObject root) {
|
void WebCustomization::read(WebCustomization & customizations, JsonObject root) {
|
||||||
// Temperature Sensor customization
|
// Temperature Sensor customization
|
||||||
JsonArray sensorsJson = root["ts"].to<JsonArray>();
|
JsonArray sensorsJson = root["ts"].to<JsonArray>();
|
||||||
|
|
||||||
for (const SensorCustomization & sensor : customizations.sensorCustomizations) {
|
for (const SensorCustomization & sensor : customizations.sensorCustomizations) {
|
||||||
JsonObject sensorJson = sensorsJson.add<JsonObject>();
|
JsonObject sensorJson = sensorsJson.add<JsonObject>();
|
||||||
sensorJson["id"] = sensor.id; // ID of chip
|
sensorJson["id"] = sensor.id; // ID of chip
|
||||||
sensorJson["name"] = sensor.name; // n
|
sensorJson["name"] = sensor.name; // n
|
||||||
sensorJson["offset"] = sensor.offset; // o
|
sensorJson["offset"] = sensor.offset; // o
|
||||||
|
sensorJson["is_system"] = sensor.is_system; // s for core_voltage, supply_voltage
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analog Sensor customization
|
// Analog Sensor customization
|
||||||
JsonArray analogJson = root["as"].to<JsonArray>();
|
JsonArray analogJson = root["as"].to<JsonArray>();
|
||||||
for (const AnalogCustomization & sensor : customizations.analogCustomizations) {
|
for (const AnalogCustomization & sensor : customizations.analogCustomizations) {
|
||||||
JsonObject sensorJson = analogJson.add<JsonObject>();
|
JsonObject sensorJson = analogJson.add<JsonObject>();
|
||||||
sensorJson["gpio"] = sensor.gpio; // g
|
sensorJson["gpio"] = sensor.gpio; // g
|
||||||
sensorJson["name"] = sensor.name; // n
|
sensorJson["name"] = sensor.name; // n
|
||||||
sensorJson["offset"] = sensor.offset; // o
|
sensorJson["offset"] = sensor.offset; // o
|
||||||
sensorJson["factor"] = sensor.factor; // f
|
sensorJson["factor"] = sensor.factor; // f
|
||||||
sensorJson["uom"] = sensor.uom; // u
|
sensorJson["uom"] = sensor.uom; // u
|
||||||
sensorJson["type"] = sensor.type; // t
|
sensorJson["type"] = sensor.type; // t
|
||||||
|
sensorJson["is_system"] = sensor.is_system; // s for core_voltage, supply_voltage
|
||||||
}
|
}
|
||||||
|
|
||||||
// Masked entities customization and custom device name (optional)
|
// Masked entities customization and custom device name (optional)
|
||||||
@@ -104,6 +105,7 @@ StateUpdateResult WebCustomization::update(JsonObject root, WebCustomization & c
|
|||||||
if (sensor.id == sensor.name) {
|
if (sensor.id == sensor.name) {
|
||||||
sensor.name = ""; // no need to store id as name
|
sensor.name = ""; // no need to store id as name
|
||||||
}
|
}
|
||||||
|
sensor.is_system = sensorJson["is_system"];
|
||||||
std::replace(sensor.id.begin(), sensor.id.end(), '-', '_'); // change old ids to v3.7 style
|
std::replace(sensor.id.begin(), sensor.id.end(), '-', '_'); // change old ids to v3.7 style
|
||||||
customizations.sensorCustomizations.push_back(sensor); // add to list
|
customizations.sensorCustomizations.push_back(sensor); // add to list
|
||||||
}
|
}
|
||||||
@@ -115,13 +117,14 @@ StateUpdateResult WebCustomization::update(JsonObject root, WebCustomization & c
|
|||||||
auto analogJsons = root["as"].as<JsonArray>();
|
auto analogJsons = root["as"].as<JsonArray>();
|
||||||
for (const JsonObject analogJson : analogJsons) {
|
for (const JsonObject analogJson : analogJsons) {
|
||||||
// create each of the sensor, overwriting any previous settings
|
// create each of the sensor, overwriting any previous settings
|
||||||
auto analog = AnalogCustomization();
|
auto analog = AnalogCustomization();
|
||||||
analog.gpio = analogJson["gpio"];
|
analog.gpio = analogJson["gpio"];
|
||||||
analog.name = analogJson["name"].as<std::string>();
|
analog.name = analogJson["name"].as<std::string>();
|
||||||
analog.offset = analogJson["offset"];
|
analog.offset = analogJson["offset"];
|
||||||
analog.factor = analogJson["factor"];
|
analog.factor = analogJson["factor"];
|
||||||
analog.uom = analogJson["uom"];
|
analog.uom = analogJson["uom"];
|
||||||
analog.type = analogJson["type"];
|
analog.type = analogJson["type"];
|
||||||
|
analog.is_system = analogJson["is_system"];
|
||||||
if (_start && analog.type == EMSESP::analogsensor_.AnalogType::DIGITAL_OUT && analog.uom > DeviceValue::DeviceValueUOM::NONE) {
|
if (_start && analog.type == EMSESP::analogsensor_.AnalogType::DIGITAL_OUT && analog.uom > DeviceValue::DeviceValueUOM::NONE) {
|
||||||
analog.offset = analog.uom - 1;
|
analog.offset = analog.uom - 1;
|
||||||
}
|
}
|
||||||
@@ -371,55 +374,78 @@ void WebCustomizationService::load_test_data() {
|
|||||||
// Temperature sensors
|
// Temperature sensors
|
||||||
webCustomization.sensorCustomizations.clear(); // delete all existing sensors
|
webCustomization.sensorCustomizations.clear(); // delete all existing sensors
|
||||||
|
|
||||||
auto sensor = SensorCustomization();
|
auto sensor1 = SensorCustomization();
|
||||||
sensor.id = "01_0203_0405_0607";
|
sensor1.id = "01_0203_0405_0607";
|
||||||
sensor.name = "test_tempsensor1";
|
sensor1.name = "test_tempsensor1";
|
||||||
sensor.offset = 0;
|
sensor1.offset = 0;
|
||||||
webCustomization.sensorCustomizations.push_back(sensor);
|
sensor1.is_system = false;
|
||||||
|
webCustomization.sensorCustomizations.push_back(sensor1);
|
||||||
|
|
||||||
auto sensor2 = SensorCustomization();
|
auto sensor2 = SensorCustomization();
|
||||||
sensor2.id = "0B_0C0D_0E0F_1011";
|
sensor2.id = "0B_0C0D_0E0F_1011";
|
||||||
sensor2.name = "test_tempsensor2";
|
sensor2.name = "test_tempsensor2";
|
||||||
sensor2.offset = 4;
|
sensor2.offset = 4;
|
||||||
|
sensor2.is_system = false;
|
||||||
webCustomization.sensorCustomizations.push_back(sensor2);
|
webCustomization.sensorCustomizations.push_back(sensor2);
|
||||||
|
|
||||||
|
auto sensor3 = SensorCustomization();
|
||||||
|
sensor3.id = "28_1767_7B13_2502";
|
||||||
|
sensor3.name = "gateway_temperature";
|
||||||
|
sensor3.offset = 0;
|
||||||
|
sensor3.is_system = true;
|
||||||
|
webCustomization.sensorCustomizations.push_back(sensor3);
|
||||||
|
|
||||||
// Analog sensors
|
// Analog sensors
|
||||||
// This actually adds the sensors as we use customizations to store them
|
// This actually adds the sensors as we use customizations to store them
|
||||||
webCustomization.analogCustomizations.clear();
|
webCustomization.analogCustomizations.clear();
|
||||||
auto analog = AnalogCustomization();
|
auto analog = AnalogCustomization();
|
||||||
analog.gpio = 36;
|
analog.gpio = 36;
|
||||||
analog.name = "test_analogsensor1";
|
analog.name = "test_analogsensor1";
|
||||||
analog.offset = 0;
|
analog.offset = 0;
|
||||||
analog.factor = 0.1;
|
analog.factor = 0.2;
|
||||||
analog.uom = 17;
|
analog.uom = 17;
|
||||||
analog.type = 3; // ADC
|
analog.type = 3; // ADC
|
||||||
|
analog.is_system = false;
|
||||||
webCustomization.analogCustomizations.push_back(analog);
|
webCustomization.analogCustomizations.push_back(analog);
|
||||||
|
|
||||||
analog = AnalogCustomization();
|
analog = AnalogCustomization();
|
||||||
analog.gpio = 37;
|
analog.gpio = 37;
|
||||||
analog.name = "test_analogsensor2";
|
analog.name = "test_analogsensor2";
|
||||||
analog.offset = 0;
|
analog.offset = 0;
|
||||||
analog.factor = 1;
|
analog.factor = 1;
|
||||||
analog.uom = 0;
|
analog.uom = 0;
|
||||||
analog.type = 1; // DIGITAL_IN
|
analog.type = 1; // DIGITAL_IN
|
||||||
|
analog.is_system = false;
|
||||||
webCustomization.analogCustomizations.push_back(analog);
|
webCustomization.analogCustomizations.push_back(analog);
|
||||||
|
|
||||||
analog = AnalogCustomization();
|
analog = AnalogCustomization();
|
||||||
analog.gpio = 38;
|
analog.gpio = 38;
|
||||||
analog.name = "test_analogsensor3";
|
analog.name = "test_analogsensor3";
|
||||||
analog.offset = 0;
|
analog.offset = 0;
|
||||||
analog.factor = 1;
|
analog.factor = 1;
|
||||||
analog.uom = 0;
|
analog.uom = 0;
|
||||||
analog.type = 0; // disabled, not-used
|
analog.type = 0; // disabled, not-used
|
||||||
|
analog.is_system = false;
|
||||||
webCustomization.analogCustomizations.push_back(analog);
|
webCustomization.analogCustomizations.push_back(analog);
|
||||||
|
|
||||||
analog = AnalogCustomization();
|
analog = AnalogCustomization();
|
||||||
analog.gpio = 33;
|
analog.gpio = 33;
|
||||||
analog.name = "test_analogsensor4";
|
analog.name = "test_analogsensor4";
|
||||||
analog.offset = 0;
|
analog.offset = 0;
|
||||||
analog.factor = 1;
|
analog.factor = 1;
|
||||||
analog.uom = 0;
|
analog.uom = 0;
|
||||||
analog.type = 2; // COUNTER
|
analog.type = 2; // COUNTER
|
||||||
|
analog.is_system = false;
|
||||||
|
webCustomization.analogCustomizations.push_back(analog);
|
||||||
|
|
||||||
|
analog = AnalogCustomization();
|
||||||
|
analog.gpio = 39;
|
||||||
|
analog.name = "test_analogsensor5"; // core_voltage
|
||||||
|
analog.offset = 0;
|
||||||
|
analog.factor = 0.003771;
|
||||||
|
analog.uom = 23;
|
||||||
|
analog.type = 3; // ADC
|
||||||
|
analog.is_system = true;
|
||||||
webCustomization.analogCustomizations.push_back(analog);
|
webCustomization.analogCustomizations.push_back(analog);
|
||||||
|
|
||||||
// EMS entities, mark some as favorites
|
// EMS entities, mark some as favorites
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class SensorCustomization {
|
|||||||
std::string id;
|
std::string id;
|
||||||
std::string name;
|
std::string name;
|
||||||
uint16_t offset;
|
uint16_t offset;
|
||||||
|
bool is_system; // if true, the customization is a system customization
|
||||||
};
|
};
|
||||||
|
|
||||||
class AnalogCustomization {
|
class AnalogCustomization {
|
||||||
@@ -45,8 +46,9 @@ class AnalogCustomization {
|
|||||||
std::string name;
|
std::string name;
|
||||||
double offset;
|
double offset;
|
||||||
double factor;
|
double factor;
|
||||||
uint8_t uom; // 0 is none
|
uint8_t uom; // 0 is none
|
||||||
int8_t type; // -1 is for deletion
|
int8_t type; // -1 is for deletion
|
||||||
|
bool is_system; // if true, the customization is a system customization
|
||||||
|
|
||||||
// used for removing from a list
|
// used for removing from a list
|
||||||
bool operator==(const AnalogCustomization & a) const {
|
bool operator==(const AnalogCustomization & a) const {
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ void WebDataService::sensor_data(AsyncWebServerRequest * request) {
|
|||||||
obj["u"] = DeviceValueUOM::DEGREES;
|
obj["u"] = DeviceValueUOM::DEGREES;
|
||||||
obj["o"] = (float)(sensor.offset()) / 10;
|
obj["o"] = (float)(sensor.offset()) / 10;
|
||||||
}
|
}
|
||||||
|
obj["s"] = sensor.is_system();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +144,7 @@ void WebDataService::sensor_data(AsyncWebServerRequest * request) {
|
|||||||
obj["o"] = sensor.offset();
|
obj["o"] = sensor.offset();
|
||||||
obj["f"] = sensor.factor();
|
obj["f"] = sensor.factor();
|
||||||
obj["t"] = sensor.type();
|
obj["t"] = sensor.type();
|
||||||
|
obj["s"] = sensor.is_system();
|
||||||
|
|
||||||
if (sensor.type() != AnalogSensor::AnalogType::NOTUSED) {
|
if (sensor.type() != AnalogSensor::AnalogType::NOTUSED) {
|
||||||
obj["v"] = Helpers::transformNumFloat(sensor.value()); // is optional and is a float
|
obj["v"] = Helpers::transformNumFloat(sensor.value()); // is optional and is a float
|
||||||
@@ -322,7 +324,9 @@ void WebDataService::write_temperature_sensor(AsyncWebServerRequest * request, J
|
|||||||
offset10 = offset / 0.18;
|
offset10 = offset / 0.18;
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = EMSESP::temperaturesensor_.update(id, name, offset10);
|
bool is_system = sensor["is_system"];
|
||||||
|
|
||||||
|
ok = EMSESP::temperaturesensor_.update(id, name, offset10, is_system);
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 400); // bad request
|
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 400); // bad request
|
||||||
@@ -335,14 +339,15 @@ void WebDataService::write_analog_sensor(AsyncWebServerRequest * request, JsonVa
|
|||||||
if (json.is<JsonObject>()) {
|
if (json.is<JsonObject>()) {
|
||||||
JsonObject analog = json;
|
JsonObject analog = json;
|
||||||
|
|
||||||
uint8_t gpio = analog["gpio"];
|
uint8_t gpio = analog["gpio"];
|
||||||
std::string name = analog["name"];
|
std::string name = analog["name"];
|
||||||
double factor = analog["factor"];
|
double factor = analog["factor"];
|
||||||
double offset = analog["offset"];
|
double offset = analog["offset"];
|
||||||
uint8_t uom = analog["uom"];
|
uint8_t uom = analog["uom"];
|
||||||
int8_t type = analog["type"];
|
int8_t type = analog["type"];
|
||||||
bool deleted = analog["deleted"];
|
bool deleted = analog["deleted"];
|
||||||
ok = EMSESP::analogsensor_.update(gpio, name, offset, factor, uom, type, deleted);
|
bool is_system = analog["is_system"];
|
||||||
|
ok = EMSESP::analogsensor_.update(gpio, name, offset, factor, uom, type, deleted, is_system);
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 400); // ok or bad request
|
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 400); // ok or bad request
|
||||||
@@ -387,13 +392,17 @@ void WebDataService::dashboard_data(AsyncWebServerRequest * request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add temperature sensors, if we have any
|
// add temperature sensors, if we have any
|
||||||
if (EMSESP::temperaturesensor_.have_sensors()) {
|
if (EMSESP::temperaturesensor_.count_entities(true)) { // no system sensors
|
||||||
JsonObject obj = nodes.add<JsonObject>();
|
JsonObject obj = nodes.add<JsonObject>();
|
||||||
obj["id"] = EMSdevice::DeviceTypeUniqueID::TEMPERATURESENSOR_UID; // it's unique id
|
obj["id"] = EMSdevice::DeviceTypeUniqueID::TEMPERATURESENSOR_UID; // it's unique id
|
||||||
obj["t"] = EMSdevice::DeviceType::TEMPERATURESENSOR; // device type number
|
obj["t"] = EMSdevice::DeviceType::TEMPERATURESENSOR; // device type number
|
||||||
JsonArray nodes = obj["nodes"].to<JsonArray>();
|
JsonArray nodes = obj["nodes"].to<JsonArray>();
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
for (const auto & sensor : EMSESP::temperaturesensor_.sensors()) {
|
for (const auto & sensor : EMSESP::temperaturesensor_.sensors()) {
|
||||||
|
// ignore system sensors
|
||||||
|
if (sensor.is_system()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
JsonObject node = nodes.add<JsonObject>();
|
JsonObject node = nodes.add<JsonObject>();
|
||||||
node["id"] = (EMSdevice::DeviceTypeUniqueID::TEMPERATURESENSOR_UID * 100) + count++;
|
node["id"] = (EMSdevice::DeviceTypeUniqueID::TEMPERATURESENSOR_UID * 100) + count++;
|
||||||
|
|
||||||
@@ -421,6 +430,10 @@ void WebDataService::dashboard_data(AsyncWebServerRequest * request) {
|
|||||||
JsonArray nodes = obj["nodes"].to<JsonArray>();
|
JsonArray nodes = obj["nodes"].to<JsonArray>();
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
for (const auto & sensor : EMSESP::analogsensor_.sensors()) {
|
for (const auto & sensor : EMSESP::analogsensor_.sensors()) {
|
||||||
|
// ignore system sensors
|
||||||
|
if (sensor.is_system()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (sensor.type() != AnalogSensor::AnalogType::NOTUSED) { // ignore disabled
|
if (sensor.type() != AnalogSensor::AnalogType::NOTUSED) { // ignore disabled
|
||||||
JsonObject node = nodes.add<JsonObject>();
|
JsonObject node = nodes.add<JsonObject>();
|
||||||
node["id"] = (EMSdevice::DeviceTypeUniqueID::ANALOGSENSOR_UID * 100) + count++;
|
node["id"] = (EMSdevice::DeviceTypeUniqueID::ANALOGSENSOR_UID * 100) + count++;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
// ---------- START - CUT HERE ----------
|
// ---------- START - CUT HERE ----------
|
||||||
|
|
||||||
void test_1() {
|
void test_1() {
|
||||||
@@ -162,25 +161,27 @@ void test_21() {
|
|||||||
auto expected_response =
|
auto expected_response =
|
||||||
"[{\"system\":{\"version\":\"dev\",\"uptime\":\"000+00:00:00.000\",\"uptimeSec\":0,\"resetReason\":\"Unknown / "
|
"[{\"system\":{\"version\":\"dev\",\"uptime\":\"000+00:00:00.000\",\"uptimeSec\":0,\"resetReason\":\"Unknown / "
|
||||||
"Unknown\"},\"network\":{\"network\":\"WiFi\",\"hostname\":\"ems-esp\",\"RSSI\":-23,\"TxPowerSetting\":0,\"staticIP\":false,\"lowBandwidth\":false,"
|
"Unknown\"},\"network\":{\"network\":\"WiFi\",\"hostname\":\"ems-esp\",\"RSSI\":-23,\"TxPowerSetting\":0,\"staticIP\":false,\"lowBandwidth\":false,"
|
||||||
"\"disableSleep\":true,\"enableMDNS\":true,\"enableCORS\":false},\"ntp\":{},\"mqtt\":{\"MQTTStatus\":\"disconnected\",\"MQTTPublishes\":0,"
|
"\"disableSleep\":true,\"enableMDNS\":true,\"enableCORS\":false},\"ntp\":{\"enabled\":true,\"server\":\"pool.ntp.org\",\"tzLabel\":\"Europe/"
|
||||||
"\"MQTTQueued\":0,\"MQTTPublishFails\":0,\"MQTTReconnects\":0,\"enabled\":true,\"clientID\":\"ems-esp\",\"keepAlive\":60,\"cleanSession\":false,"
|
"London\",\"NTPStatus\":\"disconnected\"},\"ap\":{\"provisionMode\":\"always\",\"ssid\":\"ems-esp\"},\"mqtt\":{\"MQTTStatus\":\"disconnected\","
|
||||||
"\"entityFormat\":1,\"base\":\"ems-esp\",\"discoveryPrefix\":\"homeassistant\",\"discoveryType\":0,\"nestedFormat\":1,\"haEnabled\":true,\"mqttQos\":0,"
|
"\"MQTTPublishes\":0,\"MQTTQueued\":0,\"MQTTPublishFails\":0,\"MQTTReconnects\":0,\"enabled\":true,\"clientID\":\"ems-esp\",\"keepAlive\":60,"
|
||||||
"\"mqttRetain\":false,\"publishTimeHeartbeat\":60,\"publishTimeBoiler\":10,\"publishTimeThermostat\":10,\"publishTimeSolar\":10,\"publishTimeMixer\":"
|
"\"cleanSession\":false,\"entityFormat\":1,\"base\":\"ems-esp\",\"discoveryPrefix\":\"homeassistant\",\"discoveryType\":0,\"nestedFormat\":1,"
|
||||||
"10,\"publishTimeWater\":0,\"publishTimeOther\":10,\"publishTimeSensor\":10,\"publishSingle\":false,\"publish2command\":false,\"sendResponse\":false},"
|
"\"haEnabled\":true,\"mqttQos\":0,\"mqttRetain\":false,\"publishTimeHeartbeat\":60,\"publishTimeBoiler\":10,\"publishTimeThermostat\":10,"
|
||||||
"\"syslog\":{\"enabled\":false},\"sensor\":{\"temperatureSensors\":2,\"temperatureSensorReads\":0,\"temperatureSensorFails\":0,\"analogSensors\":4,"
|
"\"publishTimeSolar\":10,\"publishTimeMixer\":10,\"publishTimeWater\":0,\"publishTimeOther\":10,\"publishTimeSensor\":10,\"publishSingle\":false,"
|
||||||
"\"analogSensorReads\":0,\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{\"busStatus\":\"connected\",\"busProtocol\":"
|
"\"publish2command\":false,\"sendResponse\":false},\"syslog\":{\"enabled\":false},\"sensor\":{\"temperatureSensors\":1,\"temperatureSensorReads\":0,"
|
||||||
"\"Buderus\",\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,\"busReadsFailed\":0,\"busWritesFailed\":0,"
|
"\"temperatureSensorFails\":0,\"analogSensors\":5,\"analogSensorReads\":0,\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{"
|
||||||
"\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":\"en\",\"txMode\":8,\"emsBusID\":11,"
|
"\"busStatus\":\"connected\",\"busProtocol\":\"Buderus\",\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,"
|
||||||
"\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,\"readonlyMode\":false,\"fahrenheit\":"
|
"\"busReadsFailed\":0,\"busWritesFailed\":0,\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":"
|
||||||
"false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,\"telnetEnabled\":true,"
|
"\"en\",\"txMode\":8,\"emsBusID\":11,\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,"
|
||||||
"\"maxWebLogBuffer\":25,\"modbusEnabled\":false,\"forceHeatingOff\":false,\"developerMode\":false},\"devices\":[{\"type\":\"boiler\",\"name\":\"My "
|
"\"readonlyMode\":false,\"fahrenheit\":false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,"
|
||||||
"Custom "
|
"\"telnetEnabled\":true,\"maxWebLogBuffer\":25,\"modbusEnabled\":false,\"forceHeatingOff\":false,\"developerMode\":false},\"devices\":[{\"type\":"
|
||||||
|
"\"boiler\",\"name\":\"My Custom "
|
||||||
"Boiler\",\"deviceID\":\"0x08\",\"productID\":123,\"brand\":\"\",\"version\":\"01.00\",\"entities\":38,\"handlersReceived\":\"0x18\","
|
"Boiler\",\"deviceID\":\"0x08\",\"productID\":123,\"brand\":\"\",\"version\":\"01.00\",\"entities\":38,\"handlersReceived\":\"0x18\","
|
||||||
"\"handlersFetched\":\"0x14 0x33\",\"handlersPending\":\"0xBF 0x10 0x11 0xC2 0xC6 0x15 0x1C 0x19 0x1A 0x35 0x34 0x2A 0xD1 0xE3 0xE4 0xE5 0xE9 0x02E0 "
|
"\"handlersFetched\":\"0x14 0x33\",\"handlersPending\":\"0xBF 0x10 0x11 0xC2 0xC6 0x15 0x1C 0x19 0x1A 0x35 0x34 0x2A 0xD1 0xE3 0xE4 0xE5 0xE9 0x02E0 "
|
||||||
"0x2E 0x3B\"},{\"type\":\"thermostat\",\"name\":\"FW120\",\"deviceID\":\"0x10\",\"productID\":192,\"brand\":\"\",\"version\":\"01.00\",\"entities\":15,"
|
"0x2E "
|
||||||
|
"0x3B\"},{\"type\":\"thermostat\",\"name\":\"FW120\",\"deviceID\":\"0x10\",\"productID\":192,\"brand\":\"\",\"version\":\"01.00\",\"entities\":15,"
|
||||||
"\"handlersReceived\":\"0x016F\",\"handlersFetched\":\"0x0170 0x0171\",\"handlersPending\":\"0xA3 0x06 0xA2 0x12 0x13 0x0172 0x0165 "
|
"\"handlersReceived\":\"0x016F\",\"handlersFetched\":\"0x0170 0x0171\",\"handlersPending\":\"0xA3 0x06 0xA2 0x12 0x13 0x0172 0x0165 "
|
||||||
"0x0168\"},{\"type\":\"temperaturesensor\",\"name\":\"temperaturesensor\",\"entities\":2},{\"type\":\"analogsensor\",\"name\":\"analogsensor\","
|
"0x0168\"},{\"type\":\"temperaturesensor\",\"name\":\"temperaturesensor\",\"entities\":1},{\"type\":\"analogsensor\",\"name\":\"analogsensor\","
|
||||||
"\"entities\":4},{\"type\":\"scheduler\",\"name\":\"scheduler\",\"entities\":2},{\"type\":\"custom\",\"name\":\"custom\",\"entities\":4}]}]";
|
"\"entities\":5},{\"type\":\"scheduler\",\"name\":\"scheduler\",\"entities\":2},{\"type\":\"custom\",\"name\":\"custom\",\"entities\":4}]}]";
|
||||||
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/system"));
|
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/system"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,25 +189,27 @@ void test_22() {
|
|||||||
auto expected_response =
|
auto expected_response =
|
||||||
"[{\"system\":{\"version\":\"dev\",\"uptime\":\"000+00:00:00.000\",\"uptimeSec\":0,\"resetReason\":\"Unknown / "
|
"[{\"system\":{\"version\":\"dev\",\"uptime\":\"000+00:00:00.000\",\"uptimeSec\":0,\"resetReason\":\"Unknown / "
|
||||||
"Unknown\"},\"network\":{\"network\":\"WiFi\",\"hostname\":\"ems-esp\",\"RSSI\":-23,\"TxPowerSetting\":0,\"staticIP\":false,\"lowBandwidth\":false,"
|
"Unknown\"},\"network\":{\"network\":\"WiFi\",\"hostname\":\"ems-esp\",\"RSSI\":-23,\"TxPowerSetting\":0,\"staticIP\":false,\"lowBandwidth\":false,"
|
||||||
"\"disableSleep\":true,\"enableMDNS\":true,\"enableCORS\":false},\"ntp\":{},\"mqtt\":{\"MQTTStatus\":\"disconnected\",\"MQTTPublishes\":0,"
|
"\"disableSleep\":true,\"enableMDNS\":true,\"enableCORS\":false},\"ntp\":{\"enabled\":true,\"server\":\"pool.ntp.org\",\"tzLabel\":\"Europe/"
|
||||||
"\"MQTTQueued\":0,\"MQTTPublishFails\":0,\"MQTTReconnects\":0,\"enabled\":true,\"clientID\":\"ems-esp\",\"keepAlive\":60,\"cleanSession\":false,"
|
"London\",\"NTPStatus\":\"disconnected\"},\"ap\":{\"provisionMode\":\"always\",\"ssid\":\"ems-esp\"},\"mqtt\":{\"MQTTStatus\":\"disconnected\","
|
||||||
"\"entityFormat\":1,\"base\":\"ems-esp\",\"discoveryPrefix\":\"homeassistant\",\"discoveryType\":0,\"nestedFormat\":1,\"haEnabled\":true,\"mqttQos\":0,"
|
"\"MQTTPublishes\":0,\"MQTTQueued\":0,\"MQTTPublishFails\":0,\"MQTTReconnects\":0,\"enabled\":true,\"clientID\":\"ems-esp\",\"keepAlive\":60,"
|
||||||
"\"mqttRetain\":false,\"publishTimeHeartbeat\":60,\"publishTimeBoiler\":10,\"publishTimeThermostat\":10,\"publishTimeSolar\":10,\"publishTimeMixer\":"
|
"\"cleanSession\":false,\"entityFormat\":1,\"base\":\"ems-esp\",\"discoveryPrefix\":\"homeassistant\",\"discoveryType\":0,\"nestedFormat\":1,"
|
||||||
"10,\"publishTimeWater\":0,\"publishTimeOther\":10,\"publishTimeSensor\":10,\"publishSingle\":false,\"publish2command\":false,\"sendResponse\":false},"
|
"\"haEnabled\":true,\"mqttQos\":0,\"mqttRetain\":false,\"publishTimeHeartbeat\":60,\"publishTimeBoiler\":10,\"publishTimeThermostat\":10,"
|
||||||
"\"syslog\":{\"enabled\":false},\"sensor\":{\"temperatureSensors\":2,\"temperatureSensorReads\":0,\"temperatureSensorFails\":0,\"analogSensors\":4,"
|
"\"publishTimeSolar\":10,\"publishTimeMixer\":10,\"publishTimeWater\":0,\"publishTimeOther\":10,\"publishTimeSensor\":10,\"publishSingle\":false,"
|
||||||
"\"analogSensorReads\":0,\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{\"busStatus\":\"connected\",\"busProtocol\":"
|
"\"publish2command\":false,\"sendResponse\":false},\"syslog\":{\"enabled\":false},\"sensor\":{\"temperatureSensors\":1,\"temperatureSensorReads\":0,"
|
||||||
"\"Buderus\",\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,\"busReadsFailed\":0,\"busWritesFailed\":0,"
|
"\"temperatureSensorFails\":0,\"analogSensors\":5,\"analogSensorReads\":0,\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{"
|
||||||
"\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":\"en\",\"txMode\":8,\"emsBusID\":11,"
|
"\"busStatus\":\"connected\",\"busProtocol\":\"Buderus\",\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,"
|
||||||
"\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,\"readonlyMode\":false,\"fahrenheit\":"
|
"\"busReadsFailed\":0,\"busWritesFailed\":0,\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":"
|
||||||
"false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,\"telnetEnabled\":true,"
|
"\"en\",\"txMode\":8,\"emsBusID\":11,\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,"
|
||||||
"\"maxWebLogBuffer\":25,\"modbusEnabled\":false,\"forceHeatingOff\":false,\"developerMode\":false},\"devices\":[{\"type\":\"boiler\",\"name\":\"My "
|
"\"readonlyMode\":false,\"fahrenheit\":false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,"
|
||||||
"Custom "
|
"\"telnetEnabled\":true,\"maxWebLogBuffer\":25,\"modbusEnabled\":false,\"forceHeatingOff\":false,\"developerMode\":false},\"devices\":[{\"type\":"
|
||||||
|
"\"boiler\",\"name\":\"My Custom "
|
||||||
"Boiler\",\"deviceID\":\"0x08\",\"productID\":123,\"brand\":\"\",\"version\":\"01.00\",\"entities\":38,\"handlersReceived\":\"0x18\","
|
"Boiler\",\"deviceID\":\"0x08\",\"productID\":123,\"brand\":\"\",\"version\":\"01.00\",\"entities\":38,\"handlersReceived\":\"0x18\","
|
||||||
"\"handlersFetched\":\"0x14 0x33\",\"handlersPending\":\"0xBF 0x10 0x11 0xC2 0xC6 0x15 0x1C 0x19 0x1A 0x35 0x34 0x2A 0xD1 0xE3 0xE4 0xE5 0xE9 0x02E0 "
|
"\"handlersFetched\":\"0x14 0x33\",\"handlersPending\":\"0xBF 0x10 0x11 0xC2 0xC6 0x15 0x1C 0x19 0x1A 0x35 0x34 0x2A 0xD1 0xE3 0xE4 0xE5 0xE9 0x02E0 "
|
||||||
"0x2E 0x3B\"},{\"type\":\"thermostat\",\"name\":\"FW120\",\"deviceID\":\"0x10\",\"productID\":192,\"brand\":\"\",\"version\":\"01.00\",\"entities\":15,"
|
"0x2E "
|
||||||
|
"0x3B\"},{\"type\":\"thermostat\",\"name\":\"FW120\",\"deviceID\":\"0x10\",\"productID\":192,\"brand\":\"\",\"version\":\"01.00\",\"entities\":15,"
|
||||||
"\"handlersReceived\":\"0x016F\",\"handlersFetched\":\"0x0170 0x0171\",\"handlersPending\":\"0xA3 0x06 0xA2 0x12 0x13 0x0172 0x0165 "
|
"\"handlersReceived\":\"0x016F\",\"handlersFetched\":\"0x0170 0x0171\",\"handlersPending\":\"0xA3 0x06 0xA2 0x12 0x13 0x0172 0x0165 "
|
||||||
"0x0168\"},{\"type\":\"temperaturesensor\",\"name\":\"temperaturesensor\",\"entities\":2},{\"type\":\"analogsensor\",\"name\":\"analogsensor\","
|
"0x0168\"},{\"type\":\"temperaturesensor\",\"name\":\"temperaturesensor\",\"entities\":1},{\"type\":\"analogsensor\",\"name\":\"analogsensor\","
|
||||||
"\"entities\":4},{\"type\":\"scheduler\",\"name\":\"scheduler\",\"entities\":2},{\"type\":\"custom\",\"name\":\"custom\",\"entities\":4}]}]";
|
"\"entities\":5},{\"type\":\"scheduler\",\"name\":\"scheduler\",\"entities\":2},{\"type\":\"custom\",\"name\":\"custom\",\"entities\":4}]}]";
|
||||||
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/system/info"));
|
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/system/info"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,12 +247,12 @@ void test_28() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void test_29() {
|
void test_29() {
|
||||||
auto expected_response = "[{\"test_tempsensor1\":12.3,\"test_tempsensor2\":45.6}]";
|
auto expected_response = "[{\"test_tempsensor1\":12.3,\"test_tempsensor2\":45.6,\"gateway_temperature\":28.1}]";
|
||||||
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/temperaturesensor"));
|
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/temperaturesensor"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_30() {
|
void test_30() {
|
||||||
auto expected_response = "[{\"test_tempsensor1\":12.3,\"test_tempsensor2\":45.6}]";
|
auto expected_response = "[{\"test_tempsensor1\":12.3,\"test_tempsensor2\":45.6,\"gateway_temperature\":28.1}]";
|
||||||
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/temperaturesensor/info"));
|
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/temperaturesensor/info"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,18 +274,19 @@ void test_33() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void test_34() {
|
void test_34() {
|
||||||
auto expected_response = "[{\"test_analogsensor1\":0,\"test_analogsensor2\":1,\"test_analogsensor3\":0,\"test_analogsensor4\":0}]";
|
auto expected_response = "[{\"test_analogsensor1\":0,\"test_analogsensor2\":1,\"test_analogsensor3\":0,\"test_analogsensor4\":0,\"test_analogsensor5\":0}]";
|
||||||
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/analogsensor"));
|
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/analogsensor"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_35() {
|
void test_35() {
|
||||||
auto expected_response = "[{\"test_analogsensor1\":0,\"test_analogsensor2\":1,\"test_analogsensor3\":0,\"test_analogsensor4\":0}]";
|
auto expected_response = "[{\"test_analogsensor1\":0,\"test_analogsensor2\":1,\"test_analogsensor3\":0,\"test_analogsensor4\":0,\"test_analogsensor5\":0}]";
|
||||||
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/analogsensor/info"));
|
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/analogsensor/info"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_36() {
|
void test_36() {
|
||||||
auto expected_response = "[{\"name\":\"test_analogsensor1\",\"fullname\":\"test_analogsensor1\",\"gpio\":36,\"type\":\"number\",\"analog\":\"adc\","
|
auto expected_response =
|
||||||
"\"value\":0,\"readable\":true,\"writeable\":false,\"visible\":true,\"offset\":0,\"factor\":0.1,\"uom\":\"mV\"}]";
|
"[{\"name\":\"test_analogsensor1\",\"fullname\":\"test_analogsensor1\",\"gpio\":36,\"type\":\"number\",\"analog\":\"adc\",\"value\":0,\"readable\":"
|
||||||
|
"true,\"writeable\":false,\"visible\":true,\"is_system\":false,\"offset\":0,\"factor\":0.2,\"uom\":\"mV\"}]";
|
||||||
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/analogsensor/test_analogsensor1"));
|
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/analogsensor/test_analogsensor1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,4 +437,4 @@ void run_tests() {
|
|||||||
RUN_TEST(test_54);
|
RUN_TEST(test_54);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- END - CUT HERE ----------
|
// ---------- END - CUT HERE ----------
|
||||||
|
|||||||
Reference in New Issue
Block a user