mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-06-19 06:16:35 +03:00
Compare commits
25 Commits
224bf63ded
...
44168216fe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44168216fe | ||
|
|
dee4f3531d | ||
|
|
bf07f904fc | ||
|
|
26c2b1b14e | ||
|
|
7153bfefba | ||
|
|
807b77d418 | ||
|
|
c69a7b03ef | ||
|
|
a39626bb0e | ||
|
|
68e14875b3 | ||
|
|
2d6d664109 | ||
|
|
dd58973118 | ||
|
|
17d3f182a0 | ||
|
|
1961090c4c | ||
|
|
33fda705c0 | ||
|
|
208717a896 | ||
|
|
6afc6b1baa | ||
|
|
a4ddd73fc8 | ||
|
|
4459b1e333 | ||
|
|
b2a66a0789 | ||
|
|
33d1315395 | ||
|
|
a0cae13f53 | ||
|
|
d1e2634594 | ||
|
|
b2247f5f58 | ||
|
|
ae46ca2b8a | ||
|
|
82ab22518e |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -78,3 +78,4 @@ interface/.tsbuildinfo
|
||||
test/test_api/package-lock.json
|
||||
.clangd
|
||||
mklittlefs
|
||||
.cursor
|
||||
|
||||
@@ -18,6 +18,7 @@ For more details go to [emsesp.org](https://emsesp.org/).
|
||||
- updated version check [#3047](https://github.com/emsesp/EMS-ESP32/issues/3047)
|
||||
- auto-logic to set ht3/ems+ tx-mode
|
||||
- polarity for digital_in sensors [#3070](https://github.com/emsesp/EMS-ESP32/discussions/3070)
|
||||
- user-requested LED blink [#3063](https://github.com/emsesp/EMS-ESP32/issues/3063)
|
||||
|
||||
## Fixed
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"ssid": "",
|
||||
"bssid": "",
|
||||
"password": "",
|
||||
"hostname": "ems-esp2",
|
||||
"hostname": "ems-esp",
|
||||
"static_ip_config": false,
|
||||
"bandwidth20": false,
|
||||
"nosleep": true,
|
||||
|
||||
@@ -3,7 +3,7 @@ build_flags =
|
||||
; WiFi settings
|
||||
-D FACTORY_WIFI_SSID=\"\"
|
||||
-D FACTORY_WIFI_PASSWORD=\"\"
|
||||
-D FACTORY_WIFI_HOSTNAME=\"ems-esp\"
|
||||
-D FACTORY_NETWORK_HOSTNAME=\"ems-esp\"
|
||||
|
||||
; Access point settings
|
||||
-D FACTORY_AP_PROVISION_MODE=AP_MODE_DISCONNECTED
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"react": "^19.2.6",
|
||||
"react-dom": "^19.2.6",
|
||||
"react-icons": "^5.6.0",
|
||||
"react-router": "^7.15.0",
|
||||
"react-router": "^7.15.1",
|
||||
"react-toastify": "^11.1.0",
|
||||
"typesafe-i18n": "^5.27.1",
|
||||
"typescript": "^6.0.3"
|
||||
@@ -47,17 +47,17 @@
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@preact/preset-vite": "^2.10.5",
|
||||
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
|
||||
"@types/node": "^25.7.0",
|
||||
"@types/node": "^25.8.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"concurrently": "^9.2.1",
|
||||
"eslint": "^10.3.0",
|
||||
"eslint": "^10.4.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"prettier": "^3.8.3",
|
||||
"rollup-plugin-visualizer": "^7.0.1",
|
||||
"terser": "^5.47.1",
|
||||
"typescript-eslint": "^8.59.3",
|
||||
"vite": "^8.0.12",
|
||||
"vite": "^8.0.13",
|
||||
"vite-plugin-imagemin": "^0.6.1"
|
||||
},
|
||||
"packageManager": "pnpm@10.33.4+sha512.1c67b3b359b2d408119ba1ed289f34b8fc3c6873412bec6fd264fbdc82489e510fcbecb9ce9d22dae7f3b76269d8441046014bdca53b9979cd7a561ad631b800"
|
||||
|
||||
306
interface/pnpm-lock.yaml
generated
306
interface/pnpm-lock.yaml
generated
@@ -54,8 +54,8 @@ importers:
|
||||
specifier: ^5.6.0
|
||||
version: 5.6.0(react@19.2.6)
|
||||
react-router:
|
||||
specifier: ^7.15.0
|
||||
version: 7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
|
||||
specifier: ^7.15.1
|
||||
version: 7.15.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
|
||||
react-toastify:
|
||||
specifier: ^11.1.0
|
||||
version: 11.1.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
|
||||
@@ -68,16 +68,16 @@ importers:
|
||||
devDependencies:
|
||||
'@eslint/js':
|
||||
specifier: ^10.0.1
|
||||
version: 10.0.1(eslint@10.3.0)
|
||||
version: 10.0.1(eslint@10.4.0)
|
||||
'@preact/preset-vite':
|
||||
specifier: ^2.10.5
|
||||
version: 2.10.5(@babel/core@7.29.0)(preact@10.29.1)(rollup@4.59.0)(vite@8.0.12(@types/node@25.7.0)(terser@5.47.1))
|
||||
version: 2.10.5(@babel/core@7.29.0)(preact@10.29.1)(rollup@4.59.0)(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1))
|
||||
'@trivago/prettier-plugin-sort-imports':
|
||||
specifier: ^6.0.2
|
||||
version: 6.0.2(prettier@3.8.3)
|
||||
'@types/node':
|
||||
specifier: ^25.7.0
|
||||
version: 25.7.0
|
||||
specifier: ^25.8.0
|
||||
version: 25.8.0
|
||||
'@types/react':
|
||||
specifier: ^19.2.14
|
||||
version: 19.2.14
|
||||
@@ -88,29 +88,29 @@ importers:
|
||||
specifier: ^9.2.1
|
||||
version: 9.2.1
|
||||
eslint:
|
||||
specifier: ^10.3.0
|
||||
version: 10.3.0
|
||||
specifier: ^10.4.0
|
||||
version: 10.4.0
|
||||
eslint-config-prettier:
|
||||
specifier: ^10.1.8
|
||||
version: 10.1.8(eslint@10.3.0)
|
||||
version: 10.1.8(eslint@10.4.0)
|
||||
prettier:
|
||||
specifier: ^3.8.3
|
||||
version: 3.8.3
|
||||
rollup-plugin-visualizer:
|
||||
specifier: ^7.0.1
|
||||
version: 7.0.1(rolldown@1.0.0)(rollup@4.59.0)
|
||||
version: 7.0.1(rolldown@1.0.1)(rollup@4.59.0)
|
||||
terser:
|
||||
specifier: ^5.47.1
|
||||
version: 5.47.1
|
||||
typescript-eslint:
|
||||
specifier: ^8.59.3
|
||||
version: 8.59.3(eslint@10.3.0)(typescript@6.0.3)
|
||||
version: 8.59.3(eslint@10.4.0)(typescript@6.0.3)
|
||||
vite:
|
||||
specifier: ^8.0.12
|
||||
version: 8.0.12(@types/node@25.7.0)(terser@5.47.1)
|
||||
specifier: ^8.0.13
|
||||
version: 8.0.13(@types/node@25.8.0)(terser@5.47.1)
|
||||
vite-plugin-imagemin:
|
||||
specifier: ^0.6.1
|
||||
version: 0.6.1(vite@8.0.12(@types/node@25.7.0)(terser@5.47.1))
|
||||
version: 0.6.1(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1))
|
||||
|
||||
packages:
|
||||
|
||||
@@ -302,8 +302,8 @@ packages:
|
||||
resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==}
|
||||
engines: {node: ^20.19.0 || ^22.13.0 || >=24}
|
||||
|
||||
'@eslint/config-helpers@0.5.5':
|
||||
resolution: {integrity: sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==}
|
||||
'@eslint/config-helpers@0.6.0':
|
||||
resolution: {integrity: sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==}
|
||||
engines: {node: ^20.19.0 || ^22.13.0 || >=24}
|
||||
|
||||
'@eslint/core@1.2.1':
|
||||
@@ -475,8 +475,8 @@ packages:
|
||||
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
'@oxc-project/types@0.129.0':
|
||||
resolution: {integrity: sha512-3oz8m3FGdr2nDXVqmFUw7jolKliC4MoyXYIG2c7gpjBnzUWQpUGIYcXYKxTdTi+N2jusvt610ckTMkxdwHkYEg==}
|
||||
'@oxc-project/types@0.130.0':
|
||||
resolution: {integrity: sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==}
|
||||
|
||||
'@popperjs/core@2.11.8':
|
||||
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
|
||||
@@ -504,103 +504,103 @@ packages:
|
||||
preact: ^10.4.0 || ^11.0.0-0
|
||||
vite: '>=2.0.0'
|
||||
|
||||
'@rolldown/binding-android-arm64@1.0.0':
|
||||
resolution: {integrity: sha512-TWMZnRLMe63C2Lhyicviu7ZHaU4kxa6PS3rofvc9GmcvptzNN11BcfQ4Sl7MwTOsisQoa2keB/EBdNCAnUo8vA==}
|
||||
'@rolldown/binding-android-arm64@1.0.1':
|
||||
resolution: {integrity: sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@rolldown/binding-darwin-arm64@1.0.0':
|
||||
resolution: {integrity: sha512-6XcD+8k0gPVItNagEw78/qqcBDwKcwDYS8V2hRmVsfUSIrd8cWe/CBvRDI5toqFyPfj+FJr6t8U6Xj2P2prEew==}
|
||||
'@rolldown/binding-darwin-arm64@1.0.1':
|
||||
resolution: {integrity: sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@rolldown/binding-darwin-x64@1.0.0':
|
||||
resolution: {integrity: sha512-iN/tWVXRQDWvmZlKdceP1Dwug9GDpEymhb9p4xnEe6zvCg5lFmzVljl+1qR1NVx3yfGpr2Na+CuLmv5IU8uzfQ==}
|
||||
'@rolldown/binding-darwin-x64@1.0.1':
|
||||
resolution: {integrity: sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@rolldown/binding-freebsd-x64@1.0.0':
|
||||
resolution: {integrity: sha512-jjQMDvvwSOuhOwMszD/klSOjyWMM3zI64hWTj9KT5x4MxRbZAf+7vLQ6qouRhtsLVFHr3f0ILaJAfgENPiQdAQ==}
|
||||
'@rolldown/binding-freebsd-x64@1.0.1':
|
||||
resolution: {integrity: sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@rolldown/binding-linux-arm-gnueabihf@1.0.0':
|
||||
resolution: {integrity: sha512-d//Dtg2x6/m3mbV64yUGNnDGNZaDGRpDLLNGerHQUVObuNaIQaaDp25yUiqGXtHEXX+NP2d0wAlmKgpYgIAJ2A==}
|
||||
'@rolldown/binding-linux-arm-gnueabihf@1.0.1':
|
||||
resolution: {integrity: sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@rolldown/binding-linux-arm64-gnu@1.0.0':
|
||||
resolution: {integrity: sha512-n7Ofp0mx+aB2cC+Sdy5YtMnXtY9lchnHbY+3Yt0uq9JsWQExf4f5Whu0tK0R8Jdc9S6RchTHjIFY7uc92puOVQ==}
|
||||
'@rolldown/binding-linux-arm64-gnu@1.0.1':
|
||||
resolution: {integrity: sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rolldown/binding-linux-arm64-musl@1.0.0':
|
||||
resolution: {integrity: sha512-EIVjy2cgd7uuMMo94FVkBp7F6DhcZAUwNURkSG3RwUmvAXR6s0ISxM81U+IydcZByPG0pZIHsf1b6kTxoFDgJA==}
|
||||
'@rolldown/binding-linux-arm64-musl@1.0.1':
|
||||
resolution: {integrity: sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rolldown/binding-linux-ppc64-gnu@1.0.0':
|
||||
resolution: {integrity: sha512-JEwwOPcwTLAcpDQlqSmjEmfs63xJnSiUNIGvLcDLUHCWK4XowpS/7c7tUsUH6uT/ct6bMUTdXKfI8967FYj6mg==}
|
||||
'@rolldown/binding-linux-ppc64-gnu@1.0.1':
|
||||
resolution: {integrity: sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rolldown/binding-linux-s390x-gnu@1.0.0':
|
||||
resolution: {integrity: sha512-0wjCFhLrihtAubnT9iA0N++0pSV0z5Hg7tNGdNJ4RFaINceHadoF+kiFGyY1qSSNVIAZtLotG8Ju1bgDPkjnFA==}
|
||||
'@rolldown/binding-linux-s390x-gnu@1.0.1':
|
||||
resolution: {integrity: sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rolldown/binding-linux-x64-gnu@1.0.0':
|
||||
resolution: {integrity: sha512-Dfn7iak9BcMMePxcoJfpSbWqnEyrp/dRF63/8qW/eHBdOZov6x5aShLLEYGYdIeSJ6vMLK/XCVB+lGIxm41bQA==}
|
||||
'@rolldown/binding-linux-x64-gnu@1.0.1':
|
||||
resolution: {integrity: sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rolldown/binding-linux-x64-musl@1.0.0':
|
||||
resolution: {integrity: sha512-5/utzzDmD/pD/bmuaUcbTf/sZYy0aztwIVlfpoW1fTjCZ0BaPOMVWGZL1zvgxyi7ZIVYWlxKONHmSbHuiOh8Jw==}
|
||||
'@rolldown/binding-linux-x64-musl@1.0.1':
|
||||
resolution: {integrity: sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rolldown/binding-openharmony-arm64@1.0.0':
|
||||
resolution: {integrity: sha512-ouJs8VcUomfLfpbUECqFMRqdV4x6aeAK3MA4m6vTrJJjKyWTV5KnxZx7Jd9G+GlDaQQxubcba00x16OyJ1meig==}
|
||||
'@rolldown/binding-openharmony-arm64@1.0.1':
|
||||
resolution: {integrity: sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@rolldown/binding-wasm32-wasi@1.0.0':
|
||||
resolution: {integrity: sha512-E+oHKGiDA+lsKMmFtffDDw91EryDT7uJocrIuCHqhm6bCTM6xFK+3gaCkYOHfPwQr0cCNarSM2xaELoQDz9jJg==}
|
||||
'@rolldown/binding-wasm32-wasi@1.0.1':
|
||||
resolution: {integrity: sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [wasm32]
|
||||
|
||||
'@rolldown/binding-win32-arm64-msvc@1.0.0':
|
||||
resolution: {integrity: sha512-yYK02n8Rngo+gbm1y6G0+7jk1sJ/2Wt7K0me0Y7k/ErBpyf+LJ2gFpqWVTcRV1rUepBlQRmpgWkTQCiiwrK0Ow==}
|
||||
'@rolldown/binding-win32-arm64-msvc@1.0.1':
|
||||
resolution: {integrity: sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@rolldown/binding-win32-x64-msvc@1.0.0':
|
||||
resolution: {integrity: sha512-14bpChMahXRRXiTwahSl+zzHPW6qQTXtkMuJBFlbo+pqSAews2d4BdCSHfrJ/MBsCZtpmTafsY+1QhBzitcmdg==}
|
||||
'@rolldown/binding-win32-x64-msvc@1.0.1':
|
||||
resolution: {integrity: sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@rolldown/pluginutils@1.0.0':
|
||||
resolution: {integrity: sha512-aKs/3GSWyV0mrhNmt/96/Z3yczC3yvrzYATCiCXQebBsGyYzjNdUphRVLeJQ67ySKVXRfMxt2lm12pmXvbPFQQ==}
|
||||
'@rolldown/pluginutils@1.0.1':
|
||||
resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}
|
||||
|
||||
'@rollup/pluginutils@4.2.1':
|
||||
resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==}
|
||||
@@ -829,8 +829,8 @@ packages:
|
||||
resolution: {integrity: sha512-zmPitbQ8+6zNutpwgcQuLcsEpn/Cj54Kbn7L5pX0Os5kdWplB7xPgEh/g+SWOB/qmows2gpuCaPyduq8ZZRnxA==}
|
||||
deprecated: This is a stub types definition. minimatch provides its own type definitions, so you do not need this installed.
|
||||
|
||||
'@types/node@25.7.0':
|
||||
resolution: {integrity: sha512-z+pdZyxE+RTQE9AcboAZCb4otwcrvgHD+GlBpPgn0emDVt0ohrTMhAwlr2Wd9nZ+nihhYFxO2pThz3C5qSu2Eg==}
|
||||
'@types/node@25.8.0':
|
||||
resolution: {integrity: sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ==}
|
||||
|
||||
'@types/parse-json@4.0.2':
|
||||
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
|
||||
@@ -1330,8 +1330,8 @@ packages:
|
||||
duplexer3@0.1.5:
|
||||
resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==}
|
||||
|
||||
electron-to-chromium@1.5.353:
|
||||
resolution: {integrity: sha512-kOrWphBi8TOZyiJZqsgqIle0lw+tzmnQK83pV9dZUd01Nm2POECSyFQMAuarzZdYqQW7FH9RaYOuaRo3h+bQ3w==}
|
||||
electron-to-chromium@1.5.357:
|
||||
resolution: {integrity: sha512-NHlTIQDK8fmVwHwuIzmXYEJ1Ewq3D9wDNc0cWXxDGysP6Pb21giwGNkxiTifyKy/4SoPuN5l6GLP1W9Sv7zB2g==}
|
||||
|
||||
emoji-regex@10.6.0:
|
||||
resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
|
||||
@@ -1519,8 +1519,8 @@ packages:
|
||||
resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==}
|
||||
engines: {node: ^20.19.0 || ^22.13.0 || >=24}
|
||||
|
||||
eslint@10.3.0:
|
||||
resolution: {integrity: sha512-XbEXaRva5cF0ZQB8w6MluHA0kZZfV2DuCMJ3ozyEOHLwDpZX2Lmm/7Pp0xdJmI0GL1W05VH5VwIFHEm1Vcw2gw==}
|
||||
eslint@10.4.0:
|
||||
resolution: {integrity: sha512-loXy6bWOoP3EP6JA7jo6p5jMpBJmHmsNZM5SFRHLdh1MGOPurMnNBj4ZlAbaqUAaQWbCr7jHV4P7gzAyryZWkQ==}
|
||||
engines: {node: ^20.19.0 || ^22.13.0 || >=24}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@@ -2589,8 +2589,8 @@ packages:
|
||||
react-is@19.2.6:
|
||||
resolution: {integrity: sha512-XjBR15BhXuylgWGuslhDKqlSayuqvqBX91BP8pauG8kd1zY8kotkNWbXksTCNRarse4kuGbe2kIY05ARtwNIvw==}
|
||||
|
||||
react-router@7.15.0:
|
||||
resolution: {integrity: sha512-HW9vYwuM8f4yx66Izy8xfrzCM+SBJluoZcCbww9A1TySax11S5Vgw6fi3ZjMONw9J4gQwngL7PzkyIpJJpJ7RQ==}
|
||||
react-router@7.15.1:
|
||||
resolution: {integrity: sha512-R8rl9HhgikFYoPJymnUtPXWbnDb3oget6lQnfIoupbt61aT9aOhRkDsY2XRhZRyX1Z/8a5sL74fXmFNm3NRK5A==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
peerDependencies:
|
||||
react: '>=18'
|
||||
@@ -2676,8 +2676,8 @@ packages:
|
||||
deprecated: Rimraf versions prior to v4 are no longer supported
|
||||
hasBin: true
|
||||
|
||||
rolldown@1.0.0:
|
||||
resolution: {integrity: sha512-yD986aXDESFGS95spT1LAv0jssywP4npMEjmMHyN2/5+eE8qQJUype2AaKkRiLgBgyD0LFlubwAht7VmY8rGoA==}
|
||||
rolldown@1.0.1:
|
||||
resolution: {integrity: sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
hasBin: true
|
||||
|
||||
@@ -3010,8 +3010,8 @@ packages:
|
||||
unbzip2-stream@1.4.3:
|
||||
resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==}
|
||||
|
||||
undici-types@7.21.0:
|
||||
resolution: {integrity: sha512-w9IMgQrz4O0YN1LtB7K5P63vhlIOvC7opSmouCJ+ZywlPAlO9gIkJ+otk6LvGpAs2wg4econaCz3TvQ9xPoyuQ==}
|
||||
undici-types@7.24.6:
|
||||
resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==}
|
||||
|
||||
universalify@2.0.1:
|
||||
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
|
||||
@@ -3059,8 +3059,8 @@ packages:
|
||||
peerDependencies:
|
||||
vite: 5.x || 6.x || 7.x || 8.x
|
||||
|
||||
vite@8.0.12:
|
||||
resolution: {integrity: sha512-w2dDofOWv2QB09ZITZBsvKTVAlYvPR4IAmrY/v0ir9KvLs0xybR7i48wxhM1/oyBWO34wPns+bPGw5ZrZqDpZg==}
|
||||
vite@8.0.13:
|
||||
resolution: {integrity: sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@@ -3420,9 +3420,9 @@ snapshots:
|
||||
'@esbuild/linux-loong64@0.14.54':
|
||||
optional: true
|
||||
|
||||
'@eslint-community/eslint-utils@4.9.1(eslint@10.3.0)':
|
||||
'@eslint-community/eslint-utils@4.9.1(eslint@10.4.0)':
|
||||
dependencies:
|
||||
eslint: 10.3.0
|
||||
eslint: 10.4.0
|
||||
eslint-visitor-keys: 3.4.3
|
||||
|
||||
'@eslint-community/regexpp@4.12.2': {}
|
||||
@@ -3435,7 +3435,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@eslint/config-helpers@0.5.5':
|
||||
'@eslint/config-helpers@0.6.0':
|
||||
dependencies:
|
||||
'@eslint/core': 1.2.1
|
||||
|
||||
@@ -3443,9 +3443,9 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.15
|
||||
|
||||
'@eslint/js@10.0.1(eslint@10.3.0)':
|
||||
'@eslint/js@10.0.1(eslint@10.4.0)':
|
||||
optionalDependencies:
|
||||
eslint: 10.3.0
|
||||
eslint: 10.4.0
|
||||
|
||||
'@eslint/object-schema@3.0.5': {}
|
||||
|
||||
@@ -3600,23 +3600,23 @@ snapshots:
|
||||
'@nodelib/fs.scandir': 2.1.5
|
||||
fastq: 1.20.1
|
||||
|
||||
'@oxc-project/types@0.129.0': {}
|
||||
'@oxc-project/types@0.130.0': {}
|
||||
|
||||
'@popperjs/core@2.11.8': {}
|
||||
|
||||
'@preact/preset-vite@2.10.5(@babel/core@7.29.0)(preact@10.29.1)(rollup@4.59.0)(vite@8.0.12(@types/node@25.7.0)(terser@5.47.1))':
|
||||
'@preact/preset-vite@2.10.5(@babel/core@7.29.0)(preact@10.29.1)(rollup@4.59.0)(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1))':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0)
|
||||
'@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.29.0)
|
||||
'@prefresh/vite': 2.4.12(preact@10.29.1)(vite@8.0.12(@types/node@25.7.0)(terser@5.47.1))
|
||||
'@prefresh/vite': 2.4.12(preact@10.29.1)(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1))
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.59.0)
|
||||
babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.29.0)
|
||||
debug: 4.4.3
|
||||
magic-string: 0.30.21
|
||||
picocolors: 1.1.1
|
||||
vite: 8.0.12(@types/node@25.7.0)(terser@5.47.1)
|
||||
vite-prerender-plugin: 0.5.13(vite@8.0.12(@types/node@25.7.0)(terser@5.47.1))
|
||||
vite: 8.0.13(@types/node@25.8.0)(terser@5.47.1)
|
||||
vite-prerender-plugin: 0.5.13(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1))
|
||||
zimmerframe: 1.1.4
|
||||
transitivePeerDependencies:
|
||||
- preact
|
||||
@@ -3631,7 +3631,7 @@ snapshots:
|
||||
|
||||
'@prefresh/utils@1.2.1': {}
|
||||
|
||||
'@prefresh/vite@2.4.12(preact@10.29.1)(vite@8.0.12(@types/node@25.7.0)(terser@5.47.1))':
|
||||
'@prefresh/vite@2.4.12(preact@10.29.1)(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1))':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@prefresh/babel-plugin': 0.5.3
|
||||
@@ -3639,60 +3639,60 @@ snapshots:
|
||||
'@prefresh/utils': 1.2.1
|
||||
'@rollup/pluginutils': 4.2.1
|
||||
preact: 10.29.1
|
||||
vite: 8.0.12(@types/node@25.7.0)(terser@5.47.1)
|
||||
vite: 8.0.13(@types/node@25.8.0)(terser@5.47.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@rolldown/binding-android-arm64@1.0.0':
|
||||
'@rolldown/binding-android-arm64@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-darwin-arm64@1.0.0':
|
||||
'@rolldown/binding-darwin-arm64@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-darwin-x64@1.0.0':
|
||||
'@rolldown/binding-darwin-x64@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-freebsd-x64@1.0.0':
|
||||
'@rolldown/binding-freebsd-x64@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-linux-arm-gnueabihf@1.0.0':
|
||||
'@rolldown/binding-linux-arm-gnueabihf@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-linux-arm64-gnu@1.0.0':
|
||||
'@rolldown/binding-linux-arm64-gnu@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-linux-arm64-musl@1.0.0':
|
||||
'@rolldown/binding-linux-arm64-musl@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-linux-ppc64-gnu@1.0.0':
|
||||
'@rolldown/binding-linux-ppc64-gnu@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-linux-s390x-gnu@1.0.0':
|
||||
'@rolldown/binding-linux-s390x-gnu@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-linux-x64-gnu@1.0.0':
|
||||
'@rolldown/binding-linux-x64-gnu@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-linux-x64-musl@1.0.0':
|
||||
'@rolldown/binding-linux-x64-musl@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-openharmony-arm64@1.0.0':
|
||||
'@rolldown/binding-openharmony-arm64@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-wasm32-wasi@1.0.0':
|
||||
'@rolldown/binding-wasm32-wasi@1.0.1':
|
||||
dependencies:
|
||||
'@emnapi/core': 1.10.0
|
||||
'@emnapi/runtime': 1.10.0
|
||||
'@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-win32-arm64-msvc@1.0.0':
|
||||
'@rolldown/binding-win32-arm64-msvc@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-win32-x64-msvc@1.0.0':
|
||||
'@rolldown/binding-win32-x64-msvc@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@rolldown/pluginutils@1.0.0': {}
|
||||
'@rolldown/pluginutils@1.0.1': {}
|
||||
|
||||
'@rollup/pluginutils@4.2.1':
|
||||
dependencies:
|
||||
@@ -3822,7 +3822,7 @@ snapshots:
|
||||
'@types/glob@7.2.0':
|
||||
dependencies:
|
||||
'@types/minimatch': 6.0.0
|
||||
'@types/node': 25.7.0
|
||||
'@types/node': 25.8.0
|
||||
|
||||
'@types/imagemin-gifsicle@7.0.4':
|
||||
dependencies:
|
||||
@@ -3851,21 +3851,21 @@ snapshots:
|
||||
|
||||
'@types/imagemin@7.0.1':
|
||||
dependencies:
|
||||
'@types/node': 25.7.0
|
||||
'@types/node': 25.8.0
|
||||
|
||||
'@types/json-schema@7.0.15': {}
|
||||
|
||||
'@types/keyv@3.1.4':
|
||||
dependencies:
|
||||
'@types/node': 25.7.0
|
||||
'@types/node': 25.8.0
|
||||
|
||||
'@types/minimatch@6.0.0':
|
||||
dependencies:
|
||||
minimatch: 10.2.5
|
||||
|
||||
'@types/node@25.7.0':
|
||||
'@types/node@25.8.0':
|
||||
dependencies:
|
||||
undici-types: 7.21.0
|
||||
undici-types: 7.24.6
|
||||
|
||||
'@types/parse-json@4.0.2': {}
|
||||
|
||||
@@ -3885,21 +3885,21 @@ snapshots:
|
||||
|
||||
'@types/responselike@1.0.3':
|
||||
dependencies:
|
||||
'@types/node': 25.7.0
|
||||
'@types/node': 25.8.0
|
||||
|
||||
'@types/svgo@2.6.4':
|
||||
dependencies:
|
||||
'@types/node': 25.7.0
|
||||
'@types/node': 25.8.0
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.3.0)(typescript@6.0.3))(eslint@10.3.0)(typescript@6.0.3)':
|
||||
'@typescript-eslint/eslint-plugin@8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.4.0)(typescript@6.0.3))(eslint@10.4.0)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.2
|
||||
'@typescript-eslint/parser': 8.59.3(eslint@10.3.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/parser': 8.59.3(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/scope-manager': 8.59.3
|
||||
'@typescript-eslint/type-utils': 8.59.3(eslint@10.3.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.59.3(eslint@10.3.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/type-utils': 8.59.3(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.59.3(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/visitor-keys': 8.59.3
|
||||
eslint: 10.3.0
|
||||
eslint: 10.4.0
|
||||
ignore: 7.0.5
|
||||
natural-compare: 1.4.0
|
||||
ts-api-utils: 2.5.0(typescript@6.0.3)
|
||||
@@ -3907,14 +3907,14 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/parser@8.59.3(eslint@10.3.0)(typescript@6.0.3)':
|
||||
'@typescript-eslint/parser@8.59.3(eslint@10.4.0)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 8.59.3
|
||||
'@typescript-eslint/types': 8.59.3
|
||||
'@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3)
|
||||
'@typescript-eslint/visitor-keys': 8.59.3
|
||||
debug: 4.4.3
|
||||
eslint: 10.3.0
|
||||
eslint: 10.4.0
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -3937,13 +3937,13 @@ snapshots:
|
||||
dependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@typescript-eslint/type-utils@8.59.3(eslint@10.3.0)(typescript@6.0.3)':
|
||||
'@typescript-eslint/type-utils@8.59.3(eslint@10.4.0)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.59.3
|
||||
'@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.59.3(eslint@10.3.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.59.3(eslint@10.4.0)(typescript@6.0.3)
|
||||
debug: 4.4.3
|
||||
eslint: 10.3.0
|
||||
eslint: 10.4.0
|
||||
ts-api-utils: 2.5.0(typescript@6.0.3)
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
@@ -3966,13 +3966,13 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/utils@8.59.3(eslint@10.3.0)(typescript@6.0.3)':
|
||||
'@typescript-eslint/utils@8.59.3(eslint@10.4.0)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0)
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0)
|
||||
'@typescript-eslint/scope-manager': 8.59.3
|
||||
'@typescript-eslint/types': 8.59.3
|
||||
'@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3)
|
||||
eslint: 10.3.0
|
||||
eslint: 10.4.0
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -4109,7 +4109,7 @@ snapshots:
|
||||
dependencies:
|
||||
baseline-browser-mapping: 2.10.29
|
||||
caniuse-lite: 1.0.30001792
|
||||
electron-to-chromium: 1.5.353
|
||||
electron-to-chromium: 1.5.357
|
||||
node-releases: 2.0.44
|
||||
update-browserslist-db: 1.2.3(browserslist@4.28.2)
|
||||
|
||||
@@ -4468,7 +4468,7 @@ snapshots:
|
||||
|
||||
duplexer3@0.1.5: {}
|
||||
|
||||
electron-to-chromium@1.5.353: {}
|
||||
electron-to-chromium@1.5.357: {}
|
||||
|
||||
emoji-regex@10.6.0: {}
|
||||
|
||||
@@ -4584,9 +4584,9 @@ snapshots:
|
||||
|
||||
escape-string-regexp@4.0.0: {}
|
||||
|
||||
eslint-config-prettier@10.1.8(eslint@10.3.0):
|
||||
eslint-config-prettier@10.1.8(eslint@10.4.0):
|
||||
dependencies:
|
||||
eslint: 10.3.0
|
||||
eslint: 10.4.0
|
||||
|
||||
eslint-scope@9.1.2:
|
||||
dependencies:
|
||||
@@ -4599,12 +4599,12 @@ snapshots:
|
||||
|
||||
eslint-visitor-keys@5.0.1: {}
|
||||
|
||||
eslint@10.3.0:
|
||||
eslint@10.4.0:
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0)
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0)
|
||||
'@eslint-community/regexpp': 4.12.2
|
||||
'@eslint/config-array': 0.23.5
|
||||
'@eslint/config-helpers': 0.5.5
|
||||
'@eslint/config-helpers': 0.6.0
|
||||
'@eslint/core': 1.2.1
|
||||
'@eslint/plugin-kit': 0.7.1
|
||||
'@humanfs/node': 0.16.8
|
||||
@@ -5648,7 +5648,7 @@ snapshots:
|
||||
|
||||
react-is@19.2.6: {}
|
||||
|
||||
react-router@7.15.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6):
|
||||
react-router@7.15.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6):
|
||||
dependencies:
|
||||
cookie: 1.1.1
|
||||
react: 19.2.6
|
||||
@@ -5738,35 +5738,35 @@ snapshots:
|
||||
dependencies:
|
||||
glob: 7.2.3
|
||||
|
||||
rolldown@1.0.0:
|
||||
rolldown@1.0.1:
|
||||
dependencies:
|
||||
'@oxc-project/types': 0.129.0
|
||||
'@rolldown/pluginutils': 1.0.0
|
||||
'@oxc-project/types': 0.130.0
|
||||
'@rolldown/pluginutils': 1.0.1
|
||||
optionalDependencies:
|
||||
'@rolldown/binding-android-arm64': 1.0.0
|
||||
'@rolldown/binding-darwin-arm64': 1.0.0
|
||||
'@rolldown/binding-darwin-x64': 1.0.0
|
||||
'@rolldown/binding-freebsd-x64': 1.0.0
|
||||
'@rolldown/binding-linux-arm-gnueabihf': 1.0.0
|
||||
'@rolldown/binding-linux-arm64-gnu': 1.0.0
|
||||
'@rolldown/binding-linux-arm64-musl': 1.0.0
|
||||
'@rolldown/binding-linux-ppc64-gnu': 1.0.0
|
||||
'@rolldown/binding-linux-s390x-gnu': 1.0.0
|
||||
'@rolldown/binding-linux-x64-gnu': 1.0.0
|
||||
'@rolldown/binding-linux-x64-musl': 1.0.0
|
||||
'@rolldown/binding-openharmony-arm64': 1.0.0
|
||||
'@rolldown/binding-wasm32-wasi': 1.0.0
|
||||
'@rolldown/binding-win32-arm64-msvc': 1.0.0
|
||||
'@rolldown/binding-win32-x64-msvc': 1.0.0
|
||||
'@rolldown/binding-android-arm64': 1.0.1
|
||||
'@rolldown/binding-darwin-arm64': 1.0.1
|
||||
'@rolldown/binding-darwin-x64': 1.0.1
|
||||
'@rolldown/binding-freebsd-x64': 1.0.1
|
||||
'@rolldown/binding-linux-arm-gnueabihf': 1.0.1
|
||||
'@rolldown/binding-linux-arm64-gnu': 1.0.1
|
||||
'@rolldown/binding-linux-arm64-musl': 1.0.1
|
||||
'@rolldown/binding-linux-ppc64-gnu': 1.0.1
|
||||
'@rolldown/binding-linux-s390x-gnu': 1.0.1
|
||||
'@rolldown/binding-linux-x64-gnu': 1.0.1
|
||||
'@rolldown/binding-linux-x64-musl': 1.0.1
|
||||
'@rolldown/binding-openharmony-arm64': 1.0.1
|
||||
'@rolldown/binding-wasm32-wasi': 1.0.1
|
||||
'@rolldown/binding-win32-arm64-msvc': 1.0.1
|
||||
'@rolldown/binding-win32-x64-msvc': 1.0.1
|
||||
|
||||
rollup-plugin-visualizer@7.0.1(rolldown@1.0.0)(rollup@4.59.0):
|
||||
rollup-plugin-visualizer@7.0.1(rolldown@1.0.1)(rollup@4.59.0):
|
||||
dependencies:
|
||||
open: 11.0.0
|
||||
picomatch: 4.0.4
|
||||
source-map: 0.7.6
|
||||
yargs: 18.0.0
|
||||
optionalDependencies:
|
||||
rolldown: 1.0.0
|
||||
rolldown: 1.0.1
|
||||
rollup: 4.59.0
|
||||
|
||||
rollup@4.59.0:
|
||||
@@ -6070,13 +6070,13 @@ snapshots:
|
||||
dependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
typescript-eslint@8.59.3(eslint@10.3.0)(typescript@6.0.3):
|
||||
typescript-eslint@8.59.3(eslint@10.4.0)(typescript@6.0.3):
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.3.0)(typescript@6.0.3))(eslint@10.3.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/parser': 8.59.3(eslint@10.3.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/eslint-plugin': 8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.4.0)(typescript@6.0.3))(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/parser': 8.59.3(eslint@10.4.0)(typescript@6.0.3)
|
||||
'@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.59.3(eslint@10.3.0)(typescript@6.0.3)
|
||||
eslint: 10.3.0
|
||||
'@typescript-eslint/utils': 8.59.3(eslint@10.4.0)(typescript@6.0.3)
|
||||
eslint: 10.4.0
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -6088,7 +6088,7 @@ snapshots:
|
||||
buffer: 5.7.1
|
||||
through: 2.3.8
|
||||
|
||||
undici-types@7.21.0: {}
|
||||
undici-types@7.24.6: {}
|
||||
|
||||
universalify@2.0.1: {}
|
||||
|
||||
@@ -6121,7 +6121,7 @@ snapshots:
|
||||
spdx-correct: 3.2.0
|
||||
spdx-expression-parse: 3.0.1
|
||||
|
||||
vite-plugin-imagemin@0.6.1(vite@8.0.12(@types/node@25.7.0)(terser@5.47.1)):
|
||||
vite-plugin-imagemin@0.6.1(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1)):
|
||||
dependencies:
|
||||
'@types/imagemin': 7.0.1
|
||||
'@types/imagemin-gifsicle': 7.0.4
|
||||
@@ -6146,11 +6146,11 @@ snapshots:
|
||||
imagemin-webp: 6.1.0
|
||||
jpegtran-bin: 6.0.1
|
||||
pathe: 0.2.0
|
||||
vite: 8.0.12(@types/node@25.7.0)(terser@5.47.1)
|
||||
vite: 8.0.13(@types/node@25.8.0)(terser@5.47.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-prerender-plugin@0.5.13(vite@8.0.12(@types/node@25.7.0)(terser@5.47.1)):
|
||||
vite-prerender-plugin@0.5.13(vite@8.0.13(@types/node@25.8.0)(terser@5.47.1)):
|
||||
dependencies:
|
||||
kolorist: 1.8.0
|
||||
magic-string: 0.30.21
|
||||
@@ -6158,17 +6158,17 @@ snapshots:
|
||||
simple-code-frame: 1.3.0
|
||||
source-map: 0.7.6
|
||||
stack-trace: 1.0.0
|
||||
vite: 8.0.12(@types/node@25.7.0)(terser@5.47.1)
|
||||
vite: 8.0.13(@types/node@25.8.0)(terser@5.47.1)
|
||||
|
||||
vite@8.0.12(@types/node@25.7.0)(terser@5.47.1):
|
||||
vite@8.0.13(@types/node@25.8.0)(terser@5.47.1):
|
||||
dependencies:
|
||||
lightningcss: 1.32.0
|
||||
picomatch: 4.0.4
|
||||
postcss: 8.5.14
|
||||
rolldown: 1.0.0
|
||||
rolldown: 1.0.1
|
||||
tinyglobby: 0.2.16
|
||||
optionalDependencies:
|
||||
'@types/node': 25.7.0
|
||||
'@types/node': 25.8.0
|
||||
fsevents: 2.3.3
|
||||
terser: 5.47.1
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ const cz: Translation = {
|
||||
DISABLED: 'zakázáno',
|
||||
TX_MODE: 'EMS Tx režim',
|
||||
HARDWARE: 'Hardware',
|
||||
EMS_BUS: '{{BUS|EMS BUS}}',
|
||||
EMS_BUS: '{{Bus|EMS Bus}}',
|
||||
GENERAL_OPTIONS: 'Obecné možnosti',
|
||||
LANGUAGE_ENTITIES: 'Jazyk (pro entity zařízení)',
|
||||
HIDE_LED: 'Skrýt LED',
|
||||
|
||||
@@ -103,7 +103,7 @@ const de: Translation = {
|
||||
DISABLED: 'deaktiviert',
|
||||
TX_MODE: 'EMS Tx-Modus',
|
||||
HARDWARE: 'Hardware',
|
||||
EMS_BUS: '{{BUS|EMS BUS}}',
|
||||
EMS_BUS: '{{Bus|EMS Bus}}',
|
||||
GENERAL_OPTIONS: 'Allgemeine Optionen',
|
||||
LANGUAGE_ENTITIES: 'Sprache (für Geräteentitäten)',
|
||||
HIDE_LED: 'LED ausblenden',
|
||||
|
||||
@@ -103,7 +103,7 @@ const en: Translation = {
|
||||
DISABLED: 'disabled',
|
||||
TX_MODE: 'EMS Tx Mode',
|
||||
HARDWARE: 'Hardware',
|
||||
EMS_BUS: '{{BUS|EMS BUS}}',
|
||||
EMS_BUS: '{{Bus|EMS Bus}}',
|
||||
GENERAL_OPTIONS: 'General Options',
|
||||
LANGUAGE_ENTITIES: 'Language (for device entities)',
|
||||
HIDE_LED: 'Hide LED',
|
||||
|
||||
@@ -103,7 +103,7 @@ const fr: Translation = {
|
||||
DISABLED: 'désactivé',
|
||||
TX_MODE: 'EMS Tx Mode',
|
||||
HARDWARE: 'Hardware',
|
||||
EMS_BUS: '{{BUS|EMS BUS}}',
|
||||
EMS_BUS: '{{Bus|EMS Bus}}',
|
||||
GENERAL_OPTIONS: 'Options générales',
|
||||
LANGUAGE_ENTITIES: 'Langue (pour les entités du matériel)',
|
||||
HIDE_LED: 'Cacher la LED',
|
||||
|
||||
@@ -103,7 +103,7 @@ const it: Translation = {
|
||||
DISABLED: 'disattivato',
|
||||
TX_MODE: 'EMS Modo Tx ',
|
||||
HARDWARE: 'Hardware',
|
||||
EMS_BUS: '{{BUS|EMS BUS}}',
|
||||
EMS_BUS: '{{Bus|EMS Bus}}',
|
||||
GENERAL_OPTIONS: 'Opzioni Generali',
|
||||
LANGUAGE_ENTITIES: 'Lingua (per entità dispositivi)',
|
||||
HIDE_LED: 'Nascondi LED',
|
||||
|
||||
@@ -102,7 +102,7 @@ const nl: Translation = {
|
||||
PHY_TYPE: 'Eth PHY Type',
|
||||
TX_MODE: 'EMS Tx Mode',
|
||||
HARDWARE: 'Hardware',
|
||||
EMS_BUS: '{{BUS|EMS BUS}}',
|
||||
EMS_BUS: '{{Bus|EMS Bus}}',
|
||||
DISABLED: 'Uitgeschakeld',
|
||||
GENERAL_OPTIONS: 'Algemene Opties',
|
||||
LANGUAGE_ENTITIES: 'Taal (voor apparaat entiteiten)',
|
||||
|
||||
@@ -103,7 +103,7 @@ const no: Translation = {
|
||||
DISABLED: 'avslått',
|
||||
TX_MODE: 'EMS Tx Mode',
|
||||
HARDWARE: 'Hardware',
|
||||
EMS_BUS: '{{BUS|EMS BUS}}',
|
||||
EMS_BUS: '{{Bus|EMS Bus}}',
|
||||
GENERAL_OPTIONS: 'Generelle Innstillinger',
|
||||
LANGUAGE_ENTITIES: 'Språk (for objekter)',
|
||||
HIDE_LED: 'Skjul LED',
|
||||
|
||||
@@ -103,7 +103,7 @@ const sk: Translation = {
|
||||
DISABLED: 'zakázané',
|
||||
TX_MODE: 'EMS Tx režim',
|
||||
HARDWARE: 'Hardware',
|
||||
EMS_BUS: '{{BUS|EMS BUS}}',
|
||||
EMS_BUS: '{{Bus|EMS Bus}}',
|
||||
GENERAL_OPTIONS: 'Všeobecné možnosti',
|
||||
LANGUAGE_ENTITIES: 'Jazyk (pre entity zariadenia)',
|
||||
HIDE_LED: 'Skryť LED',
|
||||
|
||||
@@ -103,7 +103,7 @@ const sv: Translation = {
|
||||
DISABLED: 'inaktiverad',
|
||||
TX_MODE: 'EMS Tx-läge',
|
||||
HARDWARE: 'Hårdvara',
|
||||
EMS_BUS: '{{BUSS|EMS-BUSS}}',
|
||||
EMS_BUS: '{{Buss|EMS-Buss}}',
|
||||
GENERAL_OPTIONS: 'Allmänna inställningar',
|
||||
LANGUAGE_ENTITIES: 'Språk (för entiteter)',
|
||||
HIDE_LED: 'Inaktivera LED',
|
||||
|
||||
@@ -103,7 +103,7 @@ const tr: Translation = {
|
||||
DISABLED: 'devre dışı',
|
||||
TX_MODE: 'EMS Tx Modu',
|
||||
HARDWARE: 'Donanım',
|
||||
EMS_BUS: '{{HAT|EMS HATTI}}',
|
||||
EMS_BUS: '{{Hat|EMS Hatti}}',
|
||||
GENERAL_OPTIONS: 'Genel Seçenekler',
|
||||
LANGUAGE_ENTITIES: 'Dil (cihaz varlıkları için)',
|
||||
HIDE_LED: 'LEDi kapa',
|
||||
|
||||
@@ -43,7 +43,7 @@ StateUpdateResult NetworkSettings::update(JsonObject root, NetworkSettings & set
|
||||
settings.ssid = root["ssid"] | FACTORY_WIFI_SSID;
|
||||
settings.bssid = root["bssid"] | "";
|
||||
settings.password = root["password"] | FACTORY_WIFI_PASSWORD;
|
||||
settings.hostname = root["hostname"] | FACTORY_WIFI_HOSTNAME;
|
||||
settings.hostname = root["hostname"] | FACTORY_NETWORK_HOSTNAME;
|
||||
settings.staticIPConfig = root["static_ip_config"];
|
||||
settings.bandwidth20 = root["bandwidth20"];
|
||||
settings.tx_power = static_cast<uint8_t>(root["tx_power"] | 0);
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#define FACTORY_WIFI_PASSWORD ""
|
||||
#endif
|
||||
|
||||
#ifndef FACTORY_WIFI_HOSTNAME
|
||||
#define FACTORY_WIFI_HOSTNAME ""
|
||||
#ifndef FACTORY_NETWORK_HOSTNAME
|
||||
#define FACTORY_NETWORK_HOSTNAME ""
|
||||
#endif
|
||||
|
||||
class NetworkSettings {
|
||||
@@ -31,7 +31,7 @@ class NetworkSettings {
|
||||
String ssid = FACTORY_WIFI_SSID;
|
||||
String bssid = "";
|
||||
String password = FACTORY_WIFI_PASSWORD;
|
||||
String hostname = FACTORY_WIFI_HOSTNAME;
|
||||
String hostname = FACTORY_NETWORK_HOSTNAME;
|
||||
bool staticIPConfig = false;
|
||||
bool bandwidth20 = false;
|
||||
uint8_t tx_power = 0;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include <esp_app_format.h>
|
||||
#include <esp_ota_ops.h>
|
||||
// #include <esp_partition.h>
|
||||
|
||||
static String getFilenameExtension(const String & filename) {
|
||||
const auto pos = filename.lastIndexOf('.');
|
||||
@@ -49,7 +48,7 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
|
||||
// LittleFS filesystem image
|
||||
_is_filesystem = true;
|
||||
_md5[0] = '\0'; // clear any stale md5 so Update.end() doesn't compare against it
|
||||
} else if ((extension == "bin") && (filesize > 2000000)) {
|
||||
} else if ((extension == "bin") && (filesize > 1900000)) {
|
||||
_is_firmware = true;
|
||||
} else if (extension == "json") {
|
||||
_md5[0] = '\0'; // clear md5
|
||||
@@ -61,6 +60,7 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
|
||||
return;
|
||||
} else {
|
||||
_md5.front() = '\0';
|
||||
emsesp::EMSESP::logger().err("Unsupported file type: %s, size: %u", filename.c_str(), filesize);
|
||||
handleError(request, 406); // Not Acceptable - unsupported file type
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ void AnalogSensor::reload(bool get_nvs) {
|
||||
uint8_t r = v / 10000;
|
||||
uint8_t g = (v - r * 10000) / 100;
|
||||
uint8_t b = v % 100;
|
||||
EMSESP_RGB_WRITE(sensor.gpio(), 2 * r, 2 * g, 2 * b);
|
||||
rgbLedWrite(sensor.gpio(), 2 * r, 2 * g, 2 * b);
|
||||
LOG_DEBUG("RGB set to %d, %d, %d", r, g, b);
|
||||
} else if (sensor.type() == AnalogType::DIGITAL_OUT) {
|
||||
LOG_DEBUG("Digital Write on GPIO %02d", sensor.gpio());
|
||||
@@ -989,7 +989,7 @@ bool AnalogSensor::command_setvalue(const char * value, const int8_t gpio) {
|
||||
uint8_t r = v / 10000;
|
||||
uint8_t g = (v - r * 10000) / 100;
|
||||
uint8_t b = v % 100;
|
||||
EMSESP_RGB_WRITE(sensor.gpio(), 2 * r, 2 * g, 2 * b);
|
||||
rgbLedWrite(sensor.gpio(), 2 * r, 2 * g, 2 * b);
|
||||
LOG_DEBUG("RGB set to %d, %d, %d", r, g, b);
|
||||
} else if (sensor.type() == AnalogType::PULSE) {
|
||||
uint8_t v = val;
|
||||
|
||||
@@ -2312,7 +2312,6 @@ std::string EMSdevice::name() {
|
||||
// returns true on success.
|
||||
int EMSdevice::get_modbus_value(uint8_t tag, const std::string & shortname, std::vector<uint16_t> & result) {
|
||||
// find device value by shortname
|
||||
// TODO replace linear search which is inefficient
|
||||
const auto & it = std::find_if(devicevalues_.begin(), devicevalues_.end(), [&](const DeviceValue & x) { return x.tag == tag && x.short_name == shortname; });
|
||||
if (it == devicevalues_.end() && (it->short_name != shortname || it->tag != tag)) {
|
||||
return -1;
|
||||
|
||||
@@ -90,6 +90,7 @@ Network EMSESP::network_; // network services
|
||||
TemperatureSensor EMSESP::temperaturesensor_; // Temperature sensors
|
||||
AnalogSensor EMSESP::analogsensor_; // Analog sensors
|
||||
Shower EMSESP::shower_; // Shower logic
|
||||
LED EMSESP::led_; // LED handler
|
||||
Preferences EMSESP::nvs_; // NV Storage
|
||||
|
||||
// for a specific EMS device go and request data values
|
||||
@@ -177,21 +178,6 @@ void EMSESP::clear_all_devices() {
|
||||
// emsdevices.clear(); // remove entries, but doesn't delete actual devices
|
||||
}
|
||||
|
||||
// return number of devices of a known type
|
||||
uint8_t EMSESP::count_devices(const uint8_t device_type) {
|
||||
if (emsdevices.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t count = 0;
|
||||
for (const auto & emsdevice : emsdevices) {
|
||||
if (emsdevice && emsdevice->device_type() == device_type) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// return total number of devices excluding the Controller
|
||||
uint8_t EMSESP::count_devices() {
|
||||
if (emsdevices.empty()) {
|
||||
@@ -207,27 +193,6 @@ uint8_t EMSESP::count_devices() {
|
||||
return count;
|
||||
}
|
||||
|
||||
// returns the index of a device if there are more of the same type
|
||||
// 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 count = 0;
|
||||
uint8_t index = 0;
|
||||
uint8_t current_index = 1;
|
||||
|
||||
for (const auto & emsdevice : emsdevices) {
|
||||
if (emsdevice->device_type() == device_type) {
|
||||
count++;
|
||||
if (emsdevice->unique_id() == unique_id) {
|
||||
index = current_index;
|
||||
}
|
||||
current_index++;
|
||||
}
|
||||
}
|
||||
|
||||
// Return 0 if only one device exists or not found
|
||||
return (count <= 1) ? 0 : index;
|
||||
}
|
||||
|
||||
// scans for new devices
|
||||
void EMSESP::scan_devices() {
|
||||
EMSESP::clear_all_devices();
|
||||
@@ -265,6 +230,7 @@ uint8_t EMSESP::bus_status() {
|
||||
// show the EMS bus status plus both Rx and Tx queues
|
||||
void EMSESP::show_ems(uuid::console::Shell & shell) {
|
||||
// EMS bus information
|
||||
shell.printfln("EMS Bus ID: %02X", EMSbus::ems_bus_id());
|
||||
switch (bus_status()) {
|
||||
case BUS_STATUS_OFFLINE:
|
||||
shell.printfln("EMS Bus is disconnected.");
|
||||
@@ -585,7 +551,7 @@ void EMSESP::publish_all(bool force) {
|
||||
publish_other_values(); // switch and heat pump, ...
|
||||
publish_sensor_values(true); // includes temperature and analog sensors
|
||||
|
||||
system_.send_heartbeat();
|
||||
system_.send_heartbeat(); // send MQTT heartbeat topic
|
||||
}
|
||||
}
|
||||
|
||||
@@ -626,7 +592,7 @@ void EMSESP::publish_all_loop() {
|
||||
if (Mqtt::ha_enabled()) {
|
||||
Mqtt::ha_status();
|
||||
}
|
||||
system_.send_heartbeat();
|
||||
system_.send_heartbeat(); // send MQTT heartbeat topic
|
||||
break;
|
||||
default:
|
||||
// all finished
|
||||
@@ -1532,7 +1498,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
|
||||
Roomctrl::check(data[1], data, length);
|
||||
#ifdef EMSESP_UART_DEBUG
|
||||
// get_uptime is only updated once per loop, does not give the right time
|
||||
LOG_TRACE("[UART_DEBUG] Echo after %d ms: %s", ::millis() - rx_time_, Helpers::data_to_hex(data, length).c_str());
|
||||
LOG_TRACE("[UART_DEBUG] Echo after %d ms: %s", uuid::get_uptime_ms() - rx_time_, Helpers::data_to_hex(data, length).c_str());
|
||||
#endif
|
||||
// add to RxQueue for log/watch
|
||||
rxservice_.add(data, length);
|
||||
@@ -1616,11 +1582,11 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
|
||||
#ifdef EMSESP_UART_DEBUG
|
||||
char s[4];
|
||||
if (first_value & 0x80) {
|
||||
LOG_TRACE("[UART_DEBUG] next Poll %s after %d ms", Helpers::hextoa(s, first_value), ::millis() - rx_time_);
|
||||
LOG_TRACE("[UART_DEBUG] next Poll %s after %d ms", Helpers::hextoa(s, first_value), uuid::get_uptime_ms() - rx_time_);
|
||||
// time measurement starts here, use millis because get_uptime is only updated once per loop
|
||||
rx_time_ = ::millis();
|
||||
rx_time_ = uuid::get_uptime_ms();
|
||||
} else {
|
||||
LOG_TRACE("[UART_DEBUG] Poll ack %s after %d ms", Helpers::hextoa(s, first_value), ::millis() - rx_time_);
|
||||
LOG_TRACE("[UART_DEBUG] Poll ack %s after %d ms", Helpers::hextoa(s, first_value), uuid::get_uptime_ms() - rx_time_);
|
||||
}
|
||||
#endif
|
||||
// check for poll to us, if so send top message from Tx queue immediately and quit
|
||||
@@ -1634,7 +1600,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
|
||||
return;
|
||||
} else {
|
||||
#ifdef EMSESP_UART_DEBUG
|
||||
LOG_TRACE("[UART_DEBUG] Reply after %d ms: %s", ::millis() - rx_time_, Helpers::data_to_hex(data, length).c_str());
|
||||
LOG_TRACE("[UART_DEBUG] Reply after %d ms: %s", uuid::get_uptime_ms() - rx_time_, Helpers::data_to_hex(data, length).c_str());
|
||||
#endif
|
||||
Roomctrl::check(data[1], data, length); // check if there is a message for the roomcontroller
|
||||
|
||||
@@ -1711,10 +1677,10 @@ void EMSESP::start() {
|
||||
bool factory_settings = false;
|
||||
#endif
|
||||
|
||||
#if defined(EMSESP_DEBUG)
|
||||
// LOG_DEBUG("Listing root directory before:");
|
||||
// system_.listDir("/", 3); // show the contents of the root directory
|
||||
#endif
|
||||
// #if defined(EMSESP_DEBUG)
|
||||
// LOG_DEBUG("Listing root directory before:");
|
||||
// system_.listDir("/", 3); // show the contents of the root directory
|
||||
// #endif
|
||||
|
||||
// start NVS storage
|
||||
if (!nvs_.begin("ems-esp", false, "nvs1")) { // try bigger nvs partition on 16M flash first
|
||||
@@ -1730,10 +1696,10 @@ void EMSESP::start() {
|
||||
// loads core system services settings (mqtt, ap, ntp etc)
|
||||
esp32React.begin();
|
||||
|
||||
#if defined(EMSESP_DEBUG)
|
||||
// LOG_DEBUG("Listing root directory after:");
|
||||
// system_.listDir("/", 3); // show the contents of the root directory
|
||||
#endif
|
||||
// #if defined(EMSESP_DEBUG)
|
||||
// LOG_DEBUG("Listing root directory after:");
|
||||
// system_.listDir("/", 3); // show the contents of the root directory
|
||||
// #endif
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
if (factory_settings) {
|
||||
@@ -1866,7 +1832,7 @@ void EMSESP::loop() {
|
||||
|
||||
// handles LED and checks system health, and syslog service
|
||||
if (system_.loop()) {
|
||||
return; // LED flashing is active, skip the rest of the loop
|
||||
return; // LED flashing is active meaning its about to reboot, skip the rest of the loop
|
||||
}
|
||||
|
||||
esp32React.loop(); // core services: Network, AP, MQTT and NTP
|
||||
|
||||
@@ -138,9 +138,7 @@ class EMSESP {
|
||||
static void device_active(const uint8_t device_id, const bool active);
|
||||
static bool cmd_is_readonly(const uint8_t device_type, const uint8_t device_id, const char * cmd, const int8_t id);
|
||||
static uint8_t device_id_from_cmd(const uint8_t device_type, const char * cmd, const int8_t id);
|
||||
static uint8_t count_devices(const uint8_t device_type);
|
||||
static uint8_t count_devices();
|
||||
static uint8_t device_index(const uint8_t device_type, const uint8_t unique_id);
|
||||
static bool get_device_value_info(JsonObject root, const char * cmd, const int8_t id, const uint8_t devicetype);
|
||||
|
||||
static void show_device_values(uuid::console::Shell & shell);
|
||||
@@ -233,6 +231,7 @@ class EMSESP {
|
||||
static TemperatureSensor temperaturesensor_;
|
||||
static AnalogSensor analogsensor_;
|
||||
static Shower shower_;
|
||||
static LED led_;
|
||||
static RxService rxservice_;
|
||||
static TxService txservice_;
|
||||
static Preferences nvs_;
|
||||
|
||||
316
src/core/led.cpp
Normal file
316
src/core/led.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2025 emsesp.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "led.h"
|
||||
#include "emsesp.h"
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
uuid::log::Logger LED::logger_{F_(led), uuid::log::Facility::KERN};
|
||||
|
||||
// initialise the LED, fetching the settings from the WebSettingsService
|
||||
// set the LED to on or off when in normal operating mode
|
||||
void LED::init() {
|
||||
// copy the application settings
|
||||
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
||||
led_gpio_ = settings.led_gpio;
|
||||
led_type_ = settings.led_type;
|
||||
hide_led_ = settings.hide_led;
|
||||
});
|
||||
|
||||
if (!led_gpio_) { // 0 means disabled
|
||||
LOG_INFO("LED disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
// for safety
|
||||
if (!led_type_) {
|
||||
pinMode(led_gpio_, OUTPUT);
|
||||
}
|
||||
|
||||
reset_led(); // start with LED in default state, depending on if it's hidden or not
|
||||
}
|
||||
|
||||
// handle LED routine
|
||||
// called from the System::loop()
|
||||
// returns true if the LED flash is active, i.e its a lock down state
|
||||
bool LED::loop(uint8_t healthcheck, bool button_busy) {
|
||||
// if LED flashing is active it means its about to perform a factory reset, so don't do anything else and keep it flashing
|
||||
if (led_fast_flash_timer_) {
|
||||
led_fast_flash();
|
||||
return true;
|
||||
}
|
||||
|
||||
// the user-requested LED blink always has preference
|
||||
if (!is_user_led_blink_) {
|
||||
// check for button press.
|
||||
// if button is pressed, show LED (yellow on RGB LED, on/off on standard LED)
|
||||
// it will turn off on the next loop cycle
|
||||
if (last_button_busy_ != button_busy) {
|
||||
last_button_busy_ = button_busy;
|
||||
set_led(button_busy ? Color::OFF : Color::YELLOW); // Yellow
|
||||
return false;
|
||||
}
|
||||
|
||||
// check the system health.
|
||||
// Set the sequence accordingly, only if the healthcheck is not 0 and has changed
|
||||
if (healthcheck != previous_healthcheck_) {
|
||||
previous_healthcheck_ = healthcheck;
|
||||
color_steps_[0] = Color::OFF;
|
||||
color_steps_[1] = Color::OFF;
|
||||
color_steps_[2] = Color::OFF;
|
||||
|
||||
// if the healthcheck is 0, i.e. system is healthy, reset the LED
|
||||
if (healthcheck == 0) {
|
||||
reset_led();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 1 flash (blue) is the EMS bus is not connected
|
||||
// 2 flashes (red, red) if the network (wifi or ethernet) is not connected
|
||||
// 3 flashes (red, red, blue) is both the bus and the network are not connected
|
||||
bool no_network = (healthcheck & System::HEALTHCHECK_NO_NETWORK) == System::HEALTHCHECK_NO_NETWORK;
|
||||
bool no_bus = (healthcheck & System::HEALTHCHECK_NO_BUS) == System::HEALTHCHECK_NO_BUS;
|
||||
|
||||
// set step 1
|
||||
if (no_network) {
|
||||
color_steps_[0] = Color::RED; // red, no network
|
||||
} else if (no_bus) {
|
||||
color_steps_[0] = Color::BLUE; // blue, no bus
|
||||
}
|
||||
|
||||
// set step 2
|
||||
if (no_network) {
|
||||
color_steps_[1] = Color::RED; // red, no network
|
||||
}
|
||||
|
||||
// set step 3
|
||||
if (no_network && no_bus) {
|
||||
color_steps_[2] = Color::BLUE; // blue, no network and no bus
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// show the LED status based on the healthcheck and button busy status
|
||||
sequence_led();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// turn the LED back it's default state depending on if it's hidden or not
|
||||
void LED::reset_led() {
|
||||
is_user_led_blink_ = false;
|
||||
set_led(hide_led_ ? Color::OFF : Color::GREEN); // Green
|
||||
color_steps_[0] = Color::OFF;
|
||||
color_steps_[1] = Color::OFF;
|
||||
color_steps_[2] = Color::OFF;
|
||||
}
|
||||
|
||||
// LED flash every few ms and then perform a factory reset
|
||||
void LED::led_fast_flash() {
|
||||
uint32_t current_time = uuid::get_uptime();
|
||||
|
||||
if (current_time - last_toggle_time_ >= LED_FLASH_INTERVAL_MS) {
|
||||
led_flash_state_ = !led_flash_state_;
|
||||
last_toggle_time_ = current_time;
|
||||
set_led(led_flash_state_ ? Color::YELLOW : Color::OFF); // Yellow
|
||||
}
|
||||
|
||||
// after duration, turn off the LED
|
||||
if (current_time - led_flash_start_time_ >= led_flash_duration_) {
|
||||
set_led(Color::OFF);
|
||||
led_fast_flash_timer_ = false;
|
||||
#ifndef EMSESP_DEBUG
|
||||
System::command_format(nullptr, 0); // Execute format operation, unless in debug mode
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// set LED on/off or RGB color
|
||||
// ignores whether the LED is hidden or not (if hide_led_ is set)
|
||||
void LED::set_led(Color color) {
|
||||
if (!led_gpio_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// RGB lookup table indexed by Color enum (must match enum order in led.h)
|
||||
static constexpr uint8_t B = RGB_LED_BRIGHTNESS;
|
||||
static constexpr uint8_t H = RGB_LED_BRIGHTNESS / 2;
|
||||
static constexpr uint8_t rgb_table[][3] = {
|
||||
{0, 0, 0}, // OFF
|
||||
{B, B, B}, // ON (white)
|
||||
{B, 0, 0}, // RED
|
||||
{0, B, 0}, // GREEN
|
||||
{0, 0, B}, // BLUE
|
||||
{B, B, 0}, // YELLOW
|
||||
{B, H, 0}, // ORANGE
|
||||
{0, B, B}, // CYAN
|
||||
{H, 0, H} // PINK
|
||||
};
|
||||
|
||||
const uint8_t color_idx = static_cast<uint8_t>(color);
|
||||
const uint8_t idx = (color_idx < sizeof(rgb_table) / sizeof(rgb_table[0])) ? color_idx : static_cast<uint8_t>(Color::OFF);
|
||||
const uint8_t red = rgb_table[idx][0];
|
||||
const uint8_t green = rgb_table[idx][1];
|
||||
const uint8_t blue = rgb_table[idx][2];
|
||||
|
||||
if (led_type_) {
|
||||
rgbLedWrite(led_gpio_, red, green, blue);
|
||||
} else {
|
||||
digitalWrite(led_gpio_, (red == 0 && green == 0 && blue == 0) || color == Color::OFF ? !LED_ON : LED_ON);
|
||||
}
|
||||
}
|
||||
|
||||
// set LED custom routine
|
||||
// For example: /api/system/led?data=red:blink1
|
||||
// For older non-RGB models, the colour would default to just being on.
|
||||
bool LED::set_custom_led_routine(std::string color, std::string pattern) {
|
||||
static constexpr struct {
|
||||
const char * name;
|
||||
Color value;
|
||||
} color_map[] = {
|
||||
{"off", Color::OFF},
|
||||
{"on", Color::ON},
|
||||
{"white", Color::ON},
|
||||
{"red", Color::RED},
|
||||
{"green", Color::GREEN},
|
||||
{"blue", Color::BLUE},
|
||||
{"yellow", Color::YELLOW},
|
||||
{"orange", Color::ORANGE},
|
||||
{"cyan", Color::CYAN},
|
||||
{"pink", Color::PINK},
|
||||
};
|
||||
|
||||
Color color_type = Color::OFF;
|
||||
bool color_matched = false;
|
||||
for (const auto & entry : color_map) {
|
||||
if (color == entry.name) {
|
||||
color_type = entry.value;
|
||||
color_matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!color_matched) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// reset the color steps
|
||||
color_steps_[0] = Color::OFF;
|
||||
color_steps_[1] = Color::OFF;
|
||||
color_steps_[2] = Color::OFF;
|
||||
|
||||
// blink patterns
|
||||
if (pattern == "blink1") {
|
||||
color_steps_[0] = color_type;
|
||||
} else if (pattern == "blink2") {
|
||||
color_steps_[0] = color_type;
|
||||
color_steps_[1] = color_type;
|
||||
} else if (pattern == "blink3") {
|
||||
color_steps_[0] = color_type;
|
||||
color_steps_[1] = color_type;
|
||||
color_steps_[2] = color_type;
|
||||
|
||||
// special patterns, ignores the user color
|
||||
} else if (pattern == "rgb") {
|
||||
color_steps_[0] = Color::RED;
|
||||
color_steps_[1] = Color::GREEN;
|
||||
color_steps_[2] = Color::BLUE;
|
||||
} else if (pattern == "cpc") {
|
||||
color_steps_[0] = Color::CYAN;
|
||||
color_steps_[1] = Color::PINK;
|
||||
color_steps_[2] = Color::CYAN;
|
||||
} else {
|
||||
return false; // pattern not recognized
|
||||
}
|
||||
|
||||
is_user_led_blink_ = true; // user routine is active
|
||||
|
||||
// when this is called we want the sequence_led to restart immediately and skip the long pause
|
||||
led_long_timer_ = uuid::get_uptime() + HEALTHCHECK_LED_FLASH_FAST_DURATION + 200UL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// uses LED to show system health and user-requested LED blinks
|
||||
// it works in a batch of 3 configured flashes, then a long pause
|
||||
// the timing is different for user-requested LED blink and for system healthcheck
|
||||
void LED::sequence_led() {
|
||||
// first long pause before we start flashing
|
||||
auto current_time = uuid::get_uptime();
|
||||
if (led_long_timer_
|
||||
&& (uint32_t)(current_time - led_long_timer_) >= (is_user_led_blink_ ? HEALTHCHECK_LED_LONG_FAST_DURATION : HEALTHCHECK_LED_LONG_DURATION)) {
|
||||
led_short_timer_ = current_time; // start the short timer
|
||||
led_long_timer_ = 0; // stop long timer
|
||||
led_flash_step_ = 1; // enable the short flash timer
|
||||
}
|
||||
|
||||
// the flash timer which starts after the long pause
|
||||
if (led_flash_step_
|
||||
&& (uint32_t)(current_time - led_short_timer_) >= (is_user_led_blink_ ? HEALTHCHECK_LED_FLASH_FAST_DURATION : HEALTHCHECK_LED_FLASH_DURATION)) {
|
||||
led_long_timer_ = 0; // stop the long timer
|
||||
led_short_timer_ = current_time;
|
||||
|
||||
if (++led_flash_step_ == 8) {
|
||||
// finished first iteration, reset the whole sequence, turn off LED
|
||||
led_long_timer_ = uuid::get_uptime();
|
||||
led_flash_step_ = 0;
|
||||
set_led(Color::OFF); // turn off the LED
|
||||
|
||||
// if we're running a user-requested LED blink, turn it off and go back to the healthcheck sequence
|
||||
if (is_user_led_blink_) {
|
||||
is_user_led_blink_ = false;
|
||||
previous_healthcheck_ = System::HEALTHCHECK_RESET; // this will force the healthcheck to be checked again
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (led_flash_step_ % 2) {
|
||||
// handle the three step events (on odd numbers 3,5,7 etc). see if we need to set a LED color
|
||||
switch (led_flash_step_) {
|
||||
case 3: // first flash
|
||||
set_led(color_steps_[0]);
|
||||
break;
|
||||
case 5: // second flash
|
||||
set_led(color_steps_[1]);
|
||||
break;
|
||||
case 7: // third flash
|
||||
set_led(color_steps_[2]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
set_led(Color::OFF); // turn off on even number count, to make it flash
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start the LED flash timer - duration in seconds
|
||||
void LED::start_led_fast_flash(uint8_t duration) {
|
||||
// Don't start if already running
|
||||
if (led_fast_flash_timer_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset counter and state
|
||||
led_flash_start_time_ = uuid::get_uptime(); // current time
|
||||
led_flash_duration_ = (uint32_t)duration * 1000; // duration in milliseconds
|
||||
led_fast_flash_timer_ = true; // it's active
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
93
src/core/led.h
Normal file
93
src/core/led.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2025 emsesp.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef EMSESP_LED_H_
|
||||
#define EMSESP_LED_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <uuid/log.h>
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
class LED {
|
||||
public:
|
||||
enum Color : uint8_t {
|
||||
OFF = 0, // 0
|
||||
ON = 1, // 1 - white
|
||||
RED = 2, // 2
|
||||
GREEN = 3, // 3
|
||||
BLUE = 4, // 4
|
||||
YELLOW = 5, // 5
|
||||
ORANGE = 6, // 6
|
||||
CYAN = 7, // 7
|
||||
PINK = 8 // 8
|
||||
};
|
||||
|
||||
void init();
|
||||
bool loop(uint8_t healthcheck, bool button_busy);
|
||||
|
||||
void start_led_fast_flash(uint8_t duration); // duration in seconds
|
||||
bool set_custom_led_routine(std::string color, std::string pattern);
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void sequence_led();
|
||||
void led_fast_flash();
|
||||
void reset_led(); // turn the LED back it's default state depending on if it's hidden or not
|
||||
void set_led(Color color);
|
||||
|
||||
static constexpr uint32_t HEALTHCHECK_LED_LONG_DURATION = 1000; // 1 second between flash sequences
|
||||
static constexpr uint32_t HEALTHCHECK_LED_LONG_FAST_DURATION = 500; // 1/2 second between flash sequences
|
||||
static constexpr uint32_t HEALTHCHECK_LED_FLASH_DURATION = 150; // 150ms
|
||||
static constexpr uint32_t HEALTHCHECK_LED_FLASH_FAST_DURATION = 150;
|
||||
static constexpr uint32_t LED_FLASH_INTERVAL_MS = 100; // LED toggle period during factory-reset flash
|
||||
static constexpr uint8_t RGB_LED_BRIGHTNESS = 20; // 255 is max brightness
|
||||
static constexpr uint8_t LED_ON = HIGH; // LED on
|
||||
|
||||
// local copies of the application settings
|
||||
uint8_t led_gpio_ = 0;
|
||||
uint8_t led_type_ = 0;
|
||||
bool hide_led_ = false;
|
||||
|
||||
bool led_fast_flash_timer_ = false;
|
||||
uint32_t led_flash_start_time_ = 0;
|
||||
uint32_t led_flash_duration_ = 0;
|
||||
|
||||
// led_flash() state
|
||||
bool led_flash_state_ = false;
|
||||
uint32_t last_toggle_time_ = 0;
|
||||
|
||||
// sequence_led() state
|
||||
bool last_button_busy_ = false;
|
||||
uint32_t led_long_timer_ = 1; // 1 will kick it off immediately
|
||||
uint32_t led_short_timer_ = 0;
|
||||
uint8_t led_flash_step_ = 0; // 0 means we're not in the short flash timer
|
||||
|
||||
// set_led_routine() state
|
||||
Color color_steps_[3] = {Color::OFF, Color::OFF, Color::OFF};
|
||||
|
||||
// if true, the user has requested a custom LED blink, this always has preference over the button or showing the system health
|
||||
bool is_user_led_blink_ = false;
|
||||
|
||||
uint8_t previous_healthcheck_ = 0;
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
#endif
|
||||
@@ -43,6 +43,7 @@ MAKE_WORD(fetch)
|
||||
MAKE_WORD(restart)
|
||||
MAKE_WORD(format)
|
||||
MAKE_WORD(txpause)
|
||||
MAKE_WORD(led)
|
||||
MAKE_WORD(raw)
|
||||
MAKE_WORD(watch)
|
||||
MAKE_WORD(syslog)
|
||||
@@ -171,7 +172,6 @@ MAKE_WORD_CUSTOM(password_prompt, "Password: ")
|
||||
MAKE_WORD_CUSTOM(unset, "<unset>")
|
||||
MAKE_WORD_CUSTOM(enable_mandatory, "<enable | disable>")
|
||||
MAKE_WORD_CUSTOM(service_mandatory, "<ap | mqtt | ntp>")
|
||||
MAKE_WORD_CUSTOM(txpause_cmd, "enable/disable TX")
|
||||
|
||||
// more common names that don't need translations
|
||||
MAKE_NOTRANSLATION(1x3min, "1x3min")
|
||||
|
||||
@@ -85,6 +85,7 @@ MAKE_WORD_TRANSLATION(system_cmd, "system setting", "System Einstellung", "syste
|
||||
MAKE_WORD_TRANSLATION(showertimer_cmd, "enable shower timer", "aktiviere Duschzeitmessung", "activeer douche timer", "aktivera duschtimer", "aktywuj czasomierz prysznica", "aktiver dusjtimer", "activer minuteur de douche", "duş zamanlayıcısını etkinleştir", "abilita timer doccia", "povoliť časovač sprchovania", "povolit časovač sprchy")
|
||||
MAKE_WORD_TRANSLATION(showeralert_cmd, "enable shower alert", "aktiviere Duschzeitwarnung", "activeer douche alarm", "aktivera duschvarning", "aktywuj alarm prysznica", "aktiver dusjvarsel", "activer alerte de douche", "duş uyarısını etkinleştir", "abilita allarme doccia", "povoliť upozornenie na sprchu", "povolit alarm sprchy")
|
||||
MAKE_WORD_TRANSLATION(txpause_cmd, "pause EMS Tx", "EMS Tx pausieren", "pauzeer EMS Tx", "pausa EMS Tx", "wstrzymaj EMS Tx", "pause EMS Tx", "pause EMS Tx", "EMS Tx'i duraklat", "pausa EMS Tx", "pozastaviť EMS Tx", "pauzovat EMS Tx")
|
||||
MAKE_WORD_TRANSLATION(led_cmd, "flash the LED", "LED blinken", "LED knipperen", "LED blinka", "LED błyska", "LED blink", "LED clignote", "LED yanıp söner", "LED lampeggia", "LED bliká", "LED bliká")
|
||||
|
||||
// tags
|
||||
MAKE_WORD_TRANSLATION(tag_hc1, "hc1", "HK1", "hc1", "VK1", "OG1", "hc1", "hc1", "ID1", "hc1", "hc1", "hc1")
|
||||
|
||||
@@ -53,7 +53,6 @@ std::vector<Mqtt::MQTTSubFunction, AllocatorPSRAM<Mqtt::MQTTSubFunction>> Mqtt::
|
||||
uint32_t Mqtt::mqtt_publish_fails_ = 0;
|
||||
bool Mqtt::connecting_ = false;
|
||||
bool Mqtt::initialized_ = false;
|
||||
bool Mqtt::ha_climate_reset_ = false;
|
||||
uint16_t Mqtt::queuecount_ = 0;
|
||||
uint8_t Mqtt::connectcount_ = 0;
|
||||
uint32_t Mqtt::mqtt_message_id_ = 0;
|
||||
@@ -131,10 +130,10 @@ void Mqtt::loop() {
|
||||
|
||||
uint32_t currentMillis = uuid::get_uptime();
|
||||
|
||||
// send heartbeat
|
||||
// send heartbeat per the frequency in the MQTT settings
|
||||
if (currentMillis - last_publish_heartbeat_ > publish_time_heartbeat_) {
|
||||
last_publish_heartbeat_ = currentMillis;
|
||||
EMSESP::system_.send_heartbeat(); // send heartbeat
|
||||
EMSESP::system_.send_heartbeat(); // send MQTT heartbeat topic
|
||||
}
|
||||
|
||||
// temperature and analog sensor publish on change
|
||||
@@ -493,7 +492,6 @@ void Mqtt::on_connect() {
|
||||
queue_unsubscribe_message(discovery_prefix_ + "/+/" + Mqtt::basename() + "/#");
|
||||
EMSESP::reset_mqtt_ha(); // re-create all HA devices if there are any
|
||||
ha_status(); // create the EMS-ESP device in HA, which is MQTT retained
|
||||
ha_climate_reset(true);
|
||||
} else {
|
||||
// with disabled HA we subscribe and the broker sends all stored HA-emsesp-configs.
|
||||
// Around line 272 they are removed (search for "// remove HA topics if we don't use discover")
|
||||
@@ -511,7 +509,6 @@ void Mqtt::on_connect() {
|
||||
|
||||
// send initial MQTT messages for some of our services
|
||||
EMSESP::system_.send_heartbeat(); // send heartbeat
|
||||
// for publish on change publish the initial complete list
|
||||
EMSESP::webCustomEntityService.publish(true);
|
||||
EMSESP::webSchedulerService.publish(true);
|
||||
EMSESP::analogsensor_.publish_values(true);
|
||||
|
||||
@@ -138,10 +138,6 @@ class Mqtt {
|
||||
};
|
||||
}
|
||||
|
||||
static MqttClient * client() {
|
||||
return mqttClient_;
|
||||
}
|
||||
|
||||
static bool enabled() {
|
||||
return mqtt_enabled_;
|
||||
}
|
||||
@@ -231,14 +227,6 @@ class Mqtt {
|
||||
ha_enabled_ = ha_enabled;
|
||||
}
|
||||
|
||||
static bool ha_climate_reset() {
|
||||
return ha_climate_reset_;
|
||||
}
|
||||
|
||||
static void ha_climate_reset(bool reset) {
|
||||
ha_climate_reset_ = reset;
|
||||
}
|
||||
|
||||
static std::string get_response() {
|
||||
return lastresponse_;
|
||||
}
|
||||
@@ -317,7 +305,6 @@ class Mqtt {
|
||||
static uint32_t mqtt_publish_fails_;
|
||||
static uint16_t queuecount_;
|
||||
static uint8_t connectcount_;
|
||||
static bool ha_climate_reset_;
|
||||
|
||||
static std::string lastresponse_;
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ NetPhase Network::initialPhase() const {
|
||||
void Network::loop() {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
// if we already have a Wifi or Ethernet connection then re-check every NETWORK_RECONNECTION_DELAY_LONG, otherwise NETWORK_RECONNECTION_DELAY_SHORT
|
||||
const unsigned long currentMillis = millis();
|
||||
const unsigned long currentMillis = uuid::get_uptime_ms();
|
||||
const uint32_t reconnectDelay =
|
||||
(network_iface_ == NetIface::WIFI || network_iface_ == NetIface::ETHERNET) ? NETWORK_RECONNECTION_DELAY_LONG : NETWORK_RECONNECTION_DELAY_SHORT;
|
||||
if (!lastConnectionAttempt_ || static_cast<uint32_t>(currentMillis - lastConnectionAttempt_) >= reconnectDelay) {
|
||||
|
||||
@@ -88,13 +88,6 @@ bool System::test_set_all_active_ = false;
|
||||
uint32_t System::max_alloc_mem_;
|
||||
uint32_t System::heap_mem_;
|
||||
|
||||
// LED flash timer
|
||||
uint8_t System::led_flash_gpio_ = 0;
|
||||
uint8_t System::led_flash_type_ = 0;
|
||||
uint32_t System::led_flash_start_time_ = 0;
|
||||
uint32_t System::led_flash_duration_ = 0;
|
||||
bool System::led_flash_timer_ = false;
|
||||
|
||||
// GPIOs
|
||||
std::vector<uint8_t, AllocatorPSRAM<uint8_t>> System::valid_system_gpios_;
|
||||
std::vector<System::GpioUsage, AllocatorPSRAM<System::GpioUsage>> System::used_gpios_;
|
||||
@@ -670,18 +663,11 @@ void System::modbus_init() {
|
||||
|
||||
// read specific major system settings to store locally for faster access
|
||||
void System::store_settings(WebSettings & settings) {
|
||||
version_ = settings.version;
|
||||
|
||||
rx_gpio_ = settings.rx_gpio;
|
||||
tx_gpio_ = settings.tx_gpio;
|
||||
pbutton_gpio_ = settings.pbutton_gpio;
|
||||
dallas_gpio_ = settings.dallas_gpio;
|
||||
led_gpio_ = settings.led_gpio;
|
||||
|
||||
analog_enabled_ = settings.analog_enabled;
|
||||
low_clock_ = settings.low_clock;
|
||||
hide_led_ = settings.hide_led;
|
||||
led_type_ = settings.led_type;
|
||||
board_profile_ = settings.board_profile;
|
||||
telnet_enabled_ = settings.telnet_enabled;
|
||||
|
||||
@@ -733,23 +719,25 @@ void System::start() {
|
||||
hostname(networkSettings.hostname.c_str()); // sets the hostname
|
||||
});
|
||||
|
||||
commands_init(); // console & api commands
|
||||
led_init(); // init LED
|
||||
button_init(); // button
|
||||
|
||||
last_system_check_ = 0; // force the LED to go from fast flash to pulse
|
||||
uart_init(); // start UART
|
||||
syslog_init(); // start syslog
|
||||
modbus_init(); // start modbus
|
||||
commands_init(); // console & api commands
|
||||
EMSESP::led_.init(); // init LED
|
||||
button_init(); // button
|
||||
uart_init(); // start UART
|
||||
syslog_init(); // start syslog
|
||||
modbus_init(); // start modbus
|
||||
}
|
||||
|
||||
// button single click
|
||||
// button single click - does nothing in normal operation
|
||||
// in debug mode, it will trigger a special healthcheck to test the LED monitoring and sequence_led
|
||||
void System::button_OnClick(PButton & b) {
|
||||
LOG_NOTICE("Button pressed - single click");
|
||||
|
||||
#ifdef EMSESP_DEBUG
|
||||
#ifndef EMSESP_STANDALONE
|
||||
// show filesystem
|
||||
listDir("/", 3);
|
||||
listDir("/", 3); // show filesystem
|
||||
#endif
|
||||
// used to test LED monitoring and sequence_led. See system_check() for more details.
|
||||
EMSESP::system_.healthcheck(99); // 99 = special trigger
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -757,7 +745,7 @@ void System::button_OnClick(PButton & b) {
|
||||
// reconnect to AP by removing the SSID from the network settings
|
||||
// note: in v3.9 this is normal behaviour to fallback to AP if the Wifi or Ethernet connection fails
|
||||
void System::button_OnDblClick(PButton & b) {
|
||||
LOG_NOTICE("Button pressed - double click - wifi reconnect to AP");
|
||||
LOG_NOTICE("Button pressed - double click - reset network");
|
||||
#ifndef EMSESP_STANDALONE
|
||||
// set AP mode to always so will join AP if wifi ssid fails to connect
|
||||
EMSESP::esp32React.getAPSettingsService()->update([&](APSettings & apSettings) {
|
||||
@@ -773,55 +761,6 @@ void System::button_OnDblClick(PButton & b) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// LED flash every 100ms
|
||||
void System::led_flash() {
|
||||
static bool led_flash_state_ = false;
|
||||
static uint32_t last_toggle_time_ = 0;
|
||||
uint32_t current_time = uuid::get_uptime();
|
||||
|
||||
if (current_time - last_toggle_time_ >= 100) { // every 100ms
|
||||
led_flash_state_ = !led_flash_state_;
|
||||
last_toggle_time_ = current_time;
|
||||
|
||||
if (led_flash_type_) {
|
||||
uint8_t intensity = led_flash_state_ ? RGB_LED_BRIGHTNESS : 0;
|
||||
EMSESP_RGB_WRITE(led_flash_gpio_, intensity, intensity, 0); // RGB LED - Yellow
|
||||
} else {
|
||||
digitalWrite(led_flash_gpio_, led_flash_state_ ? LED_ON : !LED_ON); // Standard LED
|
||||
}
|
||||
}
|
||||
|
||||
// after duration, turn off the LED
|
||||
if (current_time - led_flash_start_time_ >= led_flash_duration_) {
|
||||
if (led_flash_type_) {
|
||||
EMSESP_RGB_WRITE(led_flash_gpio_, 0, 0, 0);
|
||||
} else {
|
||||
digitalWrite(led_flash_gpio_, !LED_ON);
|
||||
}
|
||||
led_flash_timer_ = false;
|
||||
command_format(nullptr, 0); // Execute format operation
|
||||
}
|
||||
}
|
||||
|
||||
// Start the LED flash timer - duration in seconds
|
||||
void System::start_led_flash(uint8_t duration) {
|
||||
// Don't start if already running
|
||||
if (led_flash_timer_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get LED settings
|
||||
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
||||
led_flash_type_ = settings.led_type;
|
||||
led_flash_gpio_ = settings.led_gpio;
|
||||
});
|
||||
|
||||
// Reset counter and state
|
||||
led_flash_start_time_ = uuid::get_uptime(); // current time
|
||||
led_flash_duration_ = duration * 1000; // duration in milliseconds
|
||||
led_flash_timer_ = true; // it's active
|
||||
}
|
||||
|
||||
// button long press
|
||||
void System::button_OnLongPress(PButton & b) {
|
||||
LOG_NOTICE("Button pressed - long press - restart EMS-ESP");
|
||||
@@ -831,7 +770,7 @@ void System::button_OnLongPress(PButton & b) {
|
||||
// button indefinite press
|
||||
void System::button_OnVLongPress(PButton & b) {
|
||||
LOG_NOTICE("Button pressed - very long press - perform factory reset");
|
||||
start_led_flash(5); // Start LED flash timer for 5 seconds
|
||||
EMSESP::led_.start_led_fast_flash(5); // Start LED flash timer for 5 seconds
|
||||
}
|
||||
|
||||
// push button
|
||||
@@ -850,21 +789,7 @@ void System::button_init() {
|
||||
#endif
|
||||
}
|
||||
|
||||
// set the LED to on or off when in normal operating mode
|
||||
void System::led_init() {
|
||||
if (!led_gpio_) { // 0 means disabled
|
||||
LOG_INFO("LED disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if (led_type_) {
|
||||
EMSESP_RGB_WRITE(led_gpio_, 0, 0, 0);
|
||||
} else {
|
||||
pinMode(led_gpio_, OUTPUT);
|
||||
digitalWrite(led_gpio_, !LED_ON); // start with LED off
|
||||
}
|
||||
}
|
||||
|
||||
// init UART
|
||||
void System::uart_init() {
|
||||
EMSuart::stop();
|
||||
EMSuart::start(tx_mode_, rx_gpio_, tx_gpio_); // start UART, GPIOs have already been checked
|
||||
@@ -879,18 +804,16 @@ bool System::loop() {
|
||||
system_restart();
|
||||
}
|
||||
|
||||
// if LED flashing is active, run the LED flash
|
||||
if (led_flash_timer_) {
|
||||
led_flash();
|
||||
return true; // is active
|
||||
myPButton_.check(); // check button press
|
||||
system_check(); // System health check
|
||||
|
||||
// handle the LED
|
||||
if (EMSESP::led_.loop(healthcheck_, myPButton_.button_busy())) {
|
||||
return true; // restart is pending, skip the rest of the loop
|
||||
}
|
||||
|
||||
led_monitor(); // check status and report back using the LED
|
||||
myPButton_.check(); // check button press
|
||||
system_check(); // check system health
|
||||
|
||||
// syslog
|
||||
#ifndef EMSESP_STANDALONE
|
||||
// syslog service
|
||||
if (syslog_enabled_) {
|
||||
syslog_.loop();
|
||||
}
|
||||
@@ -898,7 +821,7 @@ bool System::loop() {
|
||||
|
||||
send_info_mqtt();
|
||||
|
||||
return false; // LED flashing is not active
|
||||
return false;
|
||||
}
|
||||
|
||||
// send MQTT info topic appended with the version information as JSON, as a retained flag
|
||||
@@ -1047,41 +970,22 @@ void System::system_check() {
|
||||
LOG_NOTICE("Ping test, #%d", ping_count++);
|
||||
#endif
|
||||
|
||||
// check if we have a valid network connection
|
||||
if (!EMSESP::network_.network_connected()) {
|
||||
healthcheck_ |= HEALTHCHECK_NO_NETWORK;
|
||||
if (healthcheck_ != 99) { // skip if we're testing
|
||||
// check if we have a valid network connection
|
||||
healthcheck_ = (healthcheck_ & ~HEALTHCHECK_NO_NETWORK) | (EMSESP::network_.network_connected() ? 0 : HEALTHCHECK_NO_NETWORK);
|
||||
|
||||
// check if we have a bus connection
|
||||
healthcheck_ = (healthcheck_ & ~HEALTHCHECK_NO_BUS) | (EMSbus::bus_connected() ? 0 : HEALTHCHECK_NO_BUS);
|
||||
} else {
|
||||
healthcheck_ &= ~HEALTHCHECK_NO_NETWORK;
|
||||
LOG_DEBUG("Healthcheck: testing mode");
|
||||
healthcheck_ = 0; // make it all look healthy - this is temporary for one cycle
|
||||
}
|
||||
|
||||
// check if we have a bus connection
|
||||
if (!EMSbus::bus_connected()) {
|
||||
healthcheck_ |= HEALTHCHECK_NO_BUS;
|
||||
} else {
|
||||
healthcheck_ &= ~HEALTHCHECK_NO_BUS;
|
||||
}
|
||||
|
||||
// see if the healthcheck state has changed
|
||||
// see if the healthcheck state has changed, if so send out the new heartbeat
|
||||
static uint8_t last_healthcheck_ = 0;
|
||||
if (healthcheck_ != last_healthcheck_) {
|
||||
last_healthcheck_ = healthcheck_;
|
||||
|
||||
EMSESP::system_.send_heartbeat(); // send MQTT heartbeat immediately when connected
|
||||
|
||||
// see if we're better now
|
||||
if (healthcheck_ == 0) {
|
||||
// everything is healthy, show LED permanently on or off depending on setting
|
||||
// Green on RGB LED, on/off on standard LED
|
||||
if (led_gpio_) {
|
||||
led_type_ ? EMSESP_RGB_WRITE(led_gpio_, 0, hide_led_ ? 0 : RGB_LED_BRIGHTNESS, 0)
|
||||
: digitalWrite(led_gpio_, hide_led_ ? !LED_ON : LED_ON); // Green
|
||||
}
|
||||
} else {
|
||||
// turn off LED so we're ready for the warning flashes
|
||||
if (led_gpio_) {
|
||||
led_type_ ? EMSESP_RGB_WRITE(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON);
|
||||
}
|
||||
}
|
||||
EMSESP::system_.send_heartbeat();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1096,6 +1000,7 @@ void System::commands_init() {
|
||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(restart), System::command_restart, FL_(restart_cmd), CommandFlag::ADMIN_ONLY);
|
||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(format), System::command_format, FL_(format_cmd), CommandFlag::ADMIN_ONLY);
|
||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(txpause), System::command_txpause, FL_(txpause_cmd), CommandFlag::ADMIN_ONLY);
|
||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(led), System::command_led, FL_(led_cmd), CommandFlag::ADMIN_ONLY);
|
||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(watch), System::command_watch, FL_(watch_cmd));
|
||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(message), System::command_message, FL_(message_cmd));
|
||||
#if defined(EMSESP_TEST)
|
||||
@@ -1109,98 +1014,6 @@ void System::commands_init() {
|
||||
Mqtt::subscribe(EMSdevice::DeviceType::SYSTEM, "system/#", nullptr); // use empty function callback
|
||||
}
|
||||
|
||||
// uses LED to show system health
|
||||
void System::led_monitor() {
|
||||
// if button is pressed, show LED (yellow on RGB LED, on/off on standard LED)
|
||||
static bool button_busy_ = false;
|
||||
if (button_busy_ != myPButton_.button_busy()) {
|
||||
button_busy_ = myPButton_.button_busy();
|
||||
if (led_type_) {
|
||||
EMSESP_RGB_WRITE(led_gpio_, button_busy_ ? RGB_LED_BRIGHTNESS : 0, button_busy_ ? RGB_LED_BRIGHTNESS : 0, 0); // Yellow
|
||||
} else {
|
||||
digitalWrite(led_gpio_, button_busy_ ? LED_ON : !LED_ON);
|
||||
}
|
||||
}
|
||||
|
||||
// we only need to run the LED healthcheck if there are errors
|
||||
// skip if we're in the led_flash_timer or if a button has been pressed
|
||||
if (!healthcheck_ || !led_gpio_ || button_busy_ || led_flash_timer_) {
|
||||
return; // all good
|
||||
}
|
||||
|
||||
static uint32_t led_long_timer_ = 1; // 1 will kick it off immediately
|
||||
static uint32_t led_short_timer_ = 0;
|
||||
static uint8_t led_flash_step_ = 0; // 0 means we're not in the short flash timer
|
||||
|
||||
auto current_time = uuid::get_uptime();
|
||||
|
||||
// first long pause before we start flashing
|
||||
if (led_long_timer_ && (uint32_t)(current_time - led_long_timer_) >= HEALTHCHECK_LED_LONG_DUARATION) {
|
||||
led_short_timer_ = current_time; // start the short timer
|
||||
led_long_timer_ = 0; // stop long timer
|
||||
led_flash_step_ = 1; // enable the short flash timer
|
||||
}
|
||||
|
||||
// the flash timer which starts after the long pause
|
||||
if (led_flash_step_ && (uint32_t)(current_time - led_short_timer_) >= HEALTHCHECK_LED_FLASH_DUARATION) {
|
||||
led_long_timer_ = 0; // stop the long timer
|
||||
led_short_timer_ = current_time;
|
||||
static bool led_on_ = false;
|
||||
|
||||
if (++led_flash_step_ == 8) {
|
||||
// reset the whole sequence
|
||||
led_long_timer_ = uuid::get_uptime();
|
||||
led_flash_step_ = 0;
|
||||
led_type_ ? EMSESP_RGB_WRITE(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); // LED off
|
||||
} else if (led_flash_step_ % 2) {
|
||||
// handle the step events (on odd numbers 3,5,7,etc). see if we need to turn on a LED
|
||||
// 1 flash (blue) is the EMS bus is not connected
|
||||
// 2 flashes (red, red) if the network (wifi or ethernet) is not connected
|
||||
// 3 flashes (red, red, blue) is both the bus and the network are not connected
|
||||
bool no_network = (healthcheck_ & HEALTHCHECK_NO_NETWORK) == HEALTHCHECK_NO_NETWORK;
|
||||
bool no_bus = (healthcheck_ & HEALTHCHECK_NO_BUS) == HEALTHCHECK_NO_BUS;
|
||||
|
||||
if (led_type_) {
|
||||
if (led_flash_step_ == 3) {
|
||||
if (no_network) {
|
||||
EMSESP_RGB_WRITE(led_gpio_, RGB_LED_BRIGHTNESS, 0, 0); // red
|
||||
} else if (no_bus) {
|
||||
EMSESP_RGB_WRITE(led_gpio_, 0, 0, RGB_LED_BRIGHTNESS); // blue
|
||||
}
|
||||
}
|
||||
if (led_flash_step_ == 5 && no_network) {
|
||||
EMSESP_RGB_WRITE(led_gpio_, RGB_LED_BRIGHTNESS, 0, 0); // red
|
||||
}
|
||||
if ((led_flash_step_ == 7) && no_network && no_bus) {
|
||||
EMSESP_RGB_WRITE(led_gpio_, 0, 0, RGB_LED_BRIGHTNESS); // blue
|
||||
}
|
||||
} else {
|
||||
if ((led_flash_step_ == 3) && (no_network || no_bus)) {
|
||||
led_on_ = true;
|
||||
}
|
||||
|
||||
if ((led_flash_step_ == 5) && no_network) {
|
||||
led_on_ = true;
|
||||
}
|
||||
|
||||
if ((led_flash_step_ == 7) && no_network && no_bus) {
|
||||
led_on_ = true;
|
||||
}
|
||||
|
||||
if (led_on_) {
|
||||
digitalWrite(led_gpio_, LED_ON); // LED on
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// turn the led off after the flash, on even number count
|
||||
if (led_on_) {
|
||||
led_type_ ? EMSESP_RGB_WRITE(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON);
|
||||
led_on_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the quality (Received Signal Strength Indicator) of the WiFi network as a %
|
||||
// High quality: 90% ~= -55dBm
|
||||
// Medium quality: 50% ~= -75dBm
|
||||
@@ -1406,7 +1219,6 @@ void System::show_system(uuid::console::Shell & shell) {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// see if there is a restore of an older settings file that needs to be applied
|
||||
// note there can be only one file at a time
|
||||
bool System::check_restore() {
|
||||
@@ -1436,6 +1248,22 @@ bool System::check_restore() {
|
||||
saveSettings(MQTT_SETTINGS_FILE, section);
|
||||
saveSettings(NTP_SETTINGS_FILE, section);
|
||||
saveSettings(SECURITY_SETTINGS_FILE, section);
|
||||
|
||||
// next is application settings
|
||||
// we need to set the EMS Bus ID to 0x49 if it's 0x0B and coming from a version which is < v3.9.0
|
||||
std::string settingsVersion = section["Settings"]["version"];
|
||||
FirmwareVersion settings_version(settingsVersion);
|
||||
if (settings_version < FirmwareVersion("3.9.0")) {
|
||||
if (section["Settings"]["ems_bus_id"].is<int>()) {
|
||||
int ems_bus_id = section["Settings"]["ems_bus_id"];
|
||||
if (ems_bus_id == 0x0B) {
|
||||
// set to EMSESP_DEFAULT_EMS_BUS_ID
|
||||
section["Settings"]["ems_bus_id"] = EMSESP_DEFAULT_EMS_BUS_ID;
|
||||
LOG_INFO("Overriding EMS Bus ID to %02X (was %02X)", EMSESP_DEFAULT_EMS_BUS_ID, ems_bus_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
// continue processing the rest of the sections
|
||||
saveSettings(EMSESP_SETTINGS_FILE, section);
|
||||
}
|
||||
if (section_type == "schedule") {
|
||||
@@ -1685,7 +1513,11 @@ bool System::check_upgrade() {
|
||||
// force web buffer to 25 for those boards without psram
|
||||
if ((EMSESP::system_.PSram() == 0) && (settings.weblog_buffer != 25)) {
|
||||
settings.weblog_buffer = 25;
|
||||
return StateUpdateResult::CHANGED;
|
||||
// if we're coming from < v3.9.0 and the Bus ID is the service key (0x0B), set it to the new default
|
||||
if (settings.ems_bus_id == 0x0B && settings_version.major() <= 3 && settings_version.minor() < 9) {
|
||||
settings.ems_bus_id = EMSESP_DEFAULT_EMS_BUS_ID;
|
||||
return StateUpdateResult::CHANGED;
|
||||
}
|
||||
}
|
||||
return StateUpdateResult::UNCHANGED;
|
||||
});
|
||||
@@ -1944,14 +1776,12 @@ bool System::command_service(const char * cmd, const char * value) {
|
||||
settings.hide_led = b;
|
||||
return StateUpdateResult::CHANGED;
|
||||
});
|
||||
EMSESP::system_.hide_led(b);
|
||||
ok = true;
|
||||
} else if (!strcmp(cmd, "settings/analogenabled")) {
|
||||
EMSESP::webSettingsService.update([&](WebSettings & settings) {
|
||||
settings.analog_enabled = b;
|
||||
return StateUpdateResult::CHANGED;
|
||||
});
|
||||
EMSESP::system_.analog_enabled(b);
|
||||
ok = true;
|
||||
} else if (!strcmp(cmd, "mqtt/enabled")) {
|
||||
EMSESP::esp32React.getMqttSettingsService()->update([&](MqttSettings & Settings) {
|
||||
@@ -2663,11 +2493,11 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output
|
||||
node["ethPhyAddr"] = settings.eth_phy_addr;
|
||||
node["ethClockMmode"] = settings.eth_clock_mode;
|
||||
}
|
||||
node["rxGPIO"] = EMSESP::system_.rx_gpio_;
|
||||
node["txGPIO"] = EMSESP::system_.tx_gpio_;
|
||||
node["dallasGPIO"] = EMSESP::system_.dallas_gpio_;
|
||||
node["pbuttonGPIO"] = EMSESP::system_.pbutton_gpio_;
|
||||
node["ledGPIO"] = EMSESP::system_.led_gpio_;
|
||||
node["rxGPIO"] = settings.rx_gpio;
|
||||
node["txGPIO"] = settings.tx_gpio;
|
||||
node["dallasGPIO"] = settings.dallas_gpio;
|
||||
node["pbuttonGPIO"] = settings.pbutton_gpio;
|
||||
node["ledGPIO"] = settings.led_gpio;
|
||||
node["ledType"] = settings.led_type;
|
||||
}
|
||||
node["hideLed"] = settings.hide_led;
|
||||
@@ -2842,6 +2672,39 @@ bool System::load_board_profile(std::vector<int8_t> & data, const std::string &
|
||||
return true;
|
||||
}
|
||||
|
||||
// led command
|
||||
// https://github.com/emsesp/EMS-ESP32/issues/3063
|
||||
// /api//system/led command that takes an argument in the form [color]:[pattern]
|
||||
// color is red, green, blue, yellow, white
|
||||
// pattern is
|
||||
// blink1 for 1 time
|
||||
// blink2 for 2 times
|
||||
// blink3 for 3 times
|
||||
// rgb for RGB
|
||||
// For example: /api/system/led?data=red:blink1
|
||||
// For older non-RGB models, the colour would default to just being on.
|
||||
bool System::command_led(const char * value, const int8_t id) {
|
||||
if (!value) {
|
||||
return false; // no argument
|
||||
}
|
||||
|
||||
std::string arg = value;
|
||||
if (arg.find(':') == std::string::npos) {
|
||||
LOG_ERROR("LED command must be in the form [color]:[pattern]");
|
||||
return false; // not in the form [color]:[pattern]
|
||||
}
|
||||
std::string color = arg.substr(0, arg.find(':'));
|
||||
std::string pattern = arg.substr(arg.find(':') + 1);
|
||||
|
||||
// set and validate the color and pattern
|
||||
if (!EMSESP::led_.set_custom_led_routine(color, pattern)) {
|
||||
LOG_ERROR("Invalid color or pattern.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// txpause command - temporarily pause the TX, by setting Txmode to 0 (disabled)
|
||||
bool System::command_txpause(const char * value, const int8_t id) {
|
||||
bool arg;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "console.h"
|
||||
#include "mqtt.h"
|
||||
#include "telegram.h"
|
||||
#include "led.h"
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
#include <esp_wifi.h>
|
||||
@@ -37,8 +38,6 @@
|
||||
#include <uuid/log.h>
|
||||
#include <PButton.h>
|
||||
|
||||
#define EMSESP_RGB_WRITE rgbLedWrite
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
// there is no official API available on the original ESP32
|
||||
extern "C" {
|
||||
@@ -54,8 +53,6 @@ using uuid::console::Shell;
|
||||
|
||||
#define EMSESP_CUSTOMSUPPORT_FILE "/config/customSupport.json"
|
||||
|
||||
#define RGB_LED_BRIGHTNESS 20 // 255 is max brightness
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
enum PHY_type : uint8_t { PHY_TYPE_NONE = 0, PHY_TYPE_LAN8720, PHY_TYPE_TLK110, PHY_TYPE_RTL8201 };
|
||||
@@ -98,6 +95,7 @@ class System {
|
||||
static bool command_service(const char * cmd, const char * value);
|
||||
static bool command_sendmail(const char * value, const int8_t id);
|
||||
static bool command_txpause(const char * value, const int8_t id);
|
||||
static bool command_led(const char * value, const int8_t id);
|
||||
|
||||
static bool get_value_info(JsonObject root, const char * cmd);
|
||||
static void get_value_json(JsonObject output, const std::string & circuit, const std::string & name, JsonVariant val);
|
||||
@@ -144,7 +142,6 @@ class System {
|
||||
|
||||
static bool uploadFirmwareURL(const char * url = nullptr);
|
||||
|
||||
void led_init();
|
||||
void button_init();
|
||||
void commands_init();
|
||||
void uart_init();
|
||||
@@ -166,10 +163,6 @@ class System {
|
||||
|
||||
static String get_ip_or_hostname();
|
||||
|
||||
void dallas_gpio(uint8_t gpio) {
|
||||
dallas_gpio_ = gpio;
|
||||
}
|
||||
|
||||
bool telnet_enabled() {
|
||||
return telnet_enabled_;
|
||||
}
|
||||
@@ -190,18 +183,6 @@ class System {
|
||||
return modbus_timeout_;
|
||||
}
|
||||
|
||||
bool analog_enabled() {
|
||||
return analog_enabled_;
|
||||
}
|
||||
|
||||
void analog_enabled(bool b) {
|
||||
analog_enabled_ = b;
|
||||
}
|
||||
|
||||
void hide_led(bool b) {
|
||||
hide_led_ = b;
|
||||
}
|
||||
|
||||
bool readonly_mode() {
|
||||
return readonly_mode_;
|
||||
}
|
||||
@@ -354,6 +335,11 @@ class System {
|
||||
|
||||
static bool set_partition(const char * partitionname);
|
||||
|
||||
// healthcheck flags - shared with LED for status visualization
|
||||
static constexpr uint8_t HEALTHCHECK_NO_BUS = (1 << 0); // 1
|
||||
static constexpr uint8_t HEALTHCHECK_NO_NETWORK = (1 << 1); // 2
|
||||
static constexpr uint8_t HEALTHCHECK_RESET = (1 << 7); // 128
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
@@ -374,15 +360,6 @@ class System {
|
||||
static constexpr uint32_t BUTTON_Debounce = 40; // Debounce period to prevent flickering when pressing or releasing the button (in ms)
|
||||
static constexpr uint32_t BUTTON_DblClickDelay = 250; // Max period between clicks for a double click event (in ms)
|
||||
|
||||
// LED flash timer
|
||||
static bool led_flash_timer_;
|
||||
static uint8_t led_flash_gpio_;
|
||||
static uint8_t led_flash_type_;
|
||||
static uint32_t led_flash_start_time_;
|
||||
static uint32_t led_flash_duration_;
|
||||
static void start_led_flash(uint8_t duration);
|
||||
static void led_flash();
|
||||
|
||||
// button press delays
|
||||
static constexpr uint32_t BUTTON_LongPressDelay = 3000; // Hold period for a long press event (in ms) - ~3 seconds
|
||||
static constexpr uint32_t BUTTON_VLongPressDelay = 9500; // Hold period for a very long press event (in ms) - !10 seconds
|
||||
@@ -393,17 +370,11 @@ class System {
|
||||
#else
|
||||
static constexpr uint32_t SYSTEM_CHECK_FREQUENCY = 5000; // do a system check every 5 seconds
|
||||
#endif
|
||||
static constexpr uint32_t HEALTHCHECK_LED_LONG_DUARATION = 1500; // 1.5 seconds
|
||||
static constexpr uint32_t HEALTHCHECK_LED_FLASH_DUARATION = 150; // 150ms
|
||||
static constexpr uint8_t HEALTHCHECK_NO_BUS = (1 << 0); // 1
|
||||
static constexpr uint8_t HEALTHCHECK_NO_NETWORK = (1 << 1); // 2
|
||||
static constexpr uint8_t LED_ON = HIGH; // LED on
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
static uuid::syslog::SyslogService syslog_;
|
||||
#endif
|
||||
|
||||
void led_monitor();
|
||||
void system_check();
|
||||
|
||||
static std::vector<uint8_t, AllocatorPSRAM<uint8_t>> string_range_to_vector(const std::string & range, const std::string & exclude = "");
|
||||
@@ -429,17 +400,12 @@ class System {
|
||||
// EMS-ESP settings
|
||||
std::string hostname_;
|
||||
String locale_;
|
||||
bool hide_led_;
|
||||
uint8_t led_type_;
|
||||
uint8_t led_gpio_;
|
||||
bool analog_enabled_;
|
||||
bool low_clock_;
|
||||
String board_profile_;
|
||||
uint8_t pbutton_gpio_;
|
||||
uint8_t rx_gpio_;
|
||||
uint8_t tx_gpio_;
|
||||
uint8_t tx_mode_;
|
||||
uint8_t dallas_gpio_;
|
||||
bool telnet_enabled_;
|
||||
bool syslog_enabled_;
|
||||
int8_t syslog_level_;
|
||||
@@ -451,7 +417,6 @@ class System {
|
||||
uint8_t bool_format_;
|
||||
uint8_t enum_format_;
|
||||
bool readonly_mode_;
|
||||
String version_;
|
||||
bool modbus_enabled_;
|
||||
uint16_t modbus_port_;
|
||||
uint8_t modbus_max_clients_;
|
||||
|
||||
@@ -257,7 +257,7 @@ void RxService::add_empty(const uint8_t src, const uint8_t dest, const uint16_t
|
||||
// start and initialize Tx
|
||||
// send out request to EMS bus for all devices
|
||||
void TxService::start() {
|
||||
// grab the bus ID and tx_mode
|
||||
// grab the EMS Bus ID and tx_mode
|
||||
EMSESP::webSettingsService.read([&](WebSettings const & settings) {
|
||||
ems_bus_id(settings.ems_bus_id);
|
||||
tx_mode(settings.tx_mode);
|
||||
|
||||
@@ -174,7 +174,7 @@ class EMSbus {
|
||||
}
|
||||
|
||||
static void set_ems2() {
|
||||
isEMS2_ = true;;
|
||||
isEMS2_ = true;
|
||||
}
|
||||
|
||||
static uint8_t ems_mask() {
|
||||
@@ -203,7 +203,7 @@ class EMSbus {
|
||||
|
||||
// checks every 30 seconds if the EMS bus is still alive
|
||||
static bool bus_connected() {
|
||||
#if defined(EMSESP_STANDALONE) || defined(EMSESP_TEST)
|
||||
#if defined(EMSESP_STANDALONE)
|
||||
return true;
|
||||
#else
|
||||
if ((uuid::get_uptime() - last_bus_activity_) > EMS_BUS_TIMEOUT) {
|
||||
@@ -247,7 +247,7 @@ class EMSbus {
|
||||
static uint32_t bus_uptime_start_; // timestamp of first time we connected to the bus
|
||||
static bool bus_connected_; // start assuming the bus hasn't been connected
|
||||
static uint8_t ems_mask_; // unset=0xFF, buderus=0x00, junkers/ht3=0x80
|
||||
static uint8_t ems_bus_id_; // the bus id, which configurable and stored in settings
|
||||
static uint8_t ems_bus_id_; // the EMS Bus id, which configurable and stored in settings
|
||||
static uint8_t tx_mode_; // local copy of the tx mode
|
||||
static uint8_t tx_state_; // state of the Tx line (NONE or waiting on a TX_READ or TX_WRITE)
|
||||
static bool isEMS2_;
|
||||
|
||||
@@ -47,13 +47,10 @@ void TemperatureSensor::start(const bool factory_settings) {
|
||||
|
||||
// load settings
|
||||
void TemperatureSensor::reload() {
|
||||
// load the service settings
|
||||
EMSESP::system_.dallas_gpio(0); // reset in system to check valid sensor
|
||||
EMSESP::webSettingsService.read([&](WebSettings const & settings) {
|
||||
dallas_gpio_ = settings.dallas_gpio;
|
||||
parasite_ = settings.dallas_parasite;
|
||||
});
|
||||
EMSESP::system_.dallas_gpio(dallas_gpio_); // set to system for checks
|
||||
|
||||
for (auto & sensor : sensors_) {
|
||||
remove_ha_topic(sensor.id());
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define EMSESP_APP_VERSION "3.9.0-dev.7"
|
||||
#define EMSESP_APP_VERSION "3.9.0-dev.8"
|
||||
|
||||
@@ -450,7 +450,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
// THESE ONLY WORK WITH AN ESP32, not in standalone/native mode
|
||||
#ifndef EMSESP_STANDALONE
|
||||
if (command == "ls") {
|
||||
listDir(LittleFS, "/", 3);
|
||||
EMSESP::system_.listDir("/", 3);
|
||||
ok = true;
|
||||
}
|
||||
|
||||
@@ -1091,6 +1091,22 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
shell.invoke_command("call boiler circpump/value");
|
||||
}
|
||||
|
||||
if (command == "led") {
|
||||
shell.printfln("Testing LED...");
|
||||
|
||||
JsonDocument doc;
|
||||
AsyncWebServerRequest request;
|
||||
|
||||
request.method(HTTP_POST);
|
||||
char data1[] = "{\"data\":\"red:blink1\"}";
|
||||
deserializeJson(doc, data1);
|
||||
JsonVariant json = doc.as<JsonVariant>();
|
||||
request.url("/api/system/led");
|
||||
EMSESP::webAPIService.webAPIService(&request, json);
|
||||
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (command == "shuntingyard") {
|
||||
shell.printfln("Testing shunting yard...");
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace emsesp {
|
||||
// #define EMSESP_DEBUG_DEFAULT "hpmode"
|
||||
// #define EMSESP_DEBUG_DEFAULT "shuntingyard"
|
||||
// #define EMSESP_DEBUG_DEFAULT "src"
|
||||
#define EMSESP_DEBUG_DEFAULT "led"
|
||||
|
||||
#ifndef EMSESP_DEBUG_DEFAULT
|
||||
#define EMSESP_DEBUG_DEFAULT "general"
|
||||
|
||||
@@ -387,7 +387,7 @@ void WebSettingsService::onUpdate() {
|
||||
}
|
||||
|
||||
if (WebSettings::has_flags(WebSettings::ChangeFlags::LED)) {
|
||||
EMSESP::system_.led_init();
|
||||
EMSESP::led_.init();
|
||||
}
|
||||
|
||||
if (WebSettings::has_flags(WebSettings::ChangeFlags::MQTT)) {
|
||||
|
||||
@@ -295,19 +295,19 @@ uint8_t WebStatusService::upgradeImportantMessages(std::string & version) {
|
||||
|
||||
FirmwareVersion current_version(current_version_s); // get current version
|
||||
|
||||
if ((current_version.major() <= 3 && current_version.minor() <= 8) && (latest_version.major() == 3 && latest_version.minor() == 9)) {
|
||||
return 1; // if moving from below 3.8.x to 3.9.x return 1
|
||||
if (!(latest_version > current_version)) {
|
||||
return 0; // no upgrade (same version or downgrade)
|
||||
}
|
||||
|
||||
if (latest_version > current_version && current_version.major() < latest_version.major()) {
|
||||
return 2; // if it's a major version upgrade return 2
|
||||
if (current_version < FirmwareVersion("3.9.0") && latest_version.major() == 3 && latest_version.minor() == 9) {
|
||||
return 1; // upgrading to 3.9.x from anything older - new partition layout warning
|
||||
}
|
||||
|
||||
if (latest_version > current_version && current_version.minor() < latest_version.minor()) {
|
||||
return 0; // if it's just a minor version upgrade return 0
|
||||
if (current_version.major() < latest_version.major()) {
|
||||
return 2; // major version upgrade
|
||||
}
|
||||
|
||||
return 0; // if it's not a valid version upgrade return 0
|
||||
return 0; // minor or patch upgrade, no special message
|
||||
}
|
||||
|
||||
// action = getVersions
|
||||
|
||||
Reference in New Issue
Block a user