mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-12 10:49:54 +03:00
4
Makefile
4
Makefile
@@ -47,8 +47,8 @@ MAKEFLAGS += -j$(JOBS) -l$(shell echo $$(($(JOBS) * 2)))
|
||||
#----------------------------------------------------------------------
|
||||
TARGET := emsesp
|
||||
BUILD := build
|
||||
SOURCES := src/core src/devices src/web src/test lib_standalone lib/semver lib/espMqttClient/src lib/espMqttClient/src/* lib/ArduinoJson/src lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src lib/PButton
|
||||
INCLUDES := src/core src/devices src/web src/test lib/* lib_standalone lib/semver lib/espMqttClient/src lib/espMqttClient/src/Transport lib/ArduinoJson/src lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src lib/uuid-telnet/src lib/uuid-syslog/src
|
||||
SOURCES := src/core src/devices src/web src/test lib_standalone lib/semver lib/espMqttClient/src lib/espMqttClient/src/* lib/ArduinoJson/src lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src lib/PButton
|
||||
INCLUDES := src/core src/devices src/web src/test lib_standalone lib/* lib/semver lib/espMqttClient/src lib/espMqttClient/src/Transport lib/ArduinoJson/src lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src lib/uuid-telnet/src lib/uuid-syslog/src
|
||||
LIBRARIES :=
|
||||
|
||||
CPPCHECK = cppcheck
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"sdkconfig.*",
|
||||
"managed_components/**",
|
||||
"pnpm-*.yaml",
|
||||
"vite.config.ts"
|
||||
"vite.config.ts",
|
||||
"lib/esp32-psram/**"
|
||||
]
|
||||
}
|
||||
@@ -38,8 +38,8 @@
|
||||
"magic-string": "^0.30.21",
|
||||
"mime-types": "^3.0.2",
|
||||
"preact": "^10.28.0",
|
||||
"react": "^19.2.1",
|
||||
"react-dom": "^19.2.1",
|
||||
"react": "^19.2.2",
|
||||
"react-dom": "^19.2.2",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-router": "^7.10.1",
|
||||
"react-toastify": "^11.0.5",
|
||||
@@ -52,7 +52,7 @@
|
||||
"@preact/compat": "^18.3.1",
|
||||
"@preact/preset-vite": "^2.10.2",
|
||||
"@trivago/prettier-plugin-sort-imports": "^6.0.0",
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/node": "^25.0.0",
|
||||
"@types/react": "^19.2.7",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"axe-core": "^4.11.0",
|
||||
@@ -62,10 +62,10 @@
|
||||
"prettier": "^3.7.4",
|
||||
"rollup-plugin-visualizer": "^6.0.5",
|
||||
"terser": "^5.44.1",
|
||||
"typescript-eslint": "^8.48.1",
|
||||
"vite": "^7.2.6",
|
||||
"typescript-eslint": "^8.49.0",
|
||||
"vite": "^7.2.7",
|
||||
"vite-plugin-imagemin": "^0.6.1",
|
||||
"vite-tsconfig-paths": "^5.1.4"
|
||||
},
|
||||
"packageManager": "pnpm@10.24.0+sha512.01ff8ae71b4419903b65c60fb2dc9d34cf8bb6e06d03bde112ef38f7a34d6904c424ba66bea5cdcf12890230bf39f9580473140ed9c946fef328b6e5238a345a"
|
||||
"packageManager": "pnpm@10.25.0+sha512.5e82639027af37cf832061bcc6d639c219634488e0f2baebe785028a793de7b525ffcd3f7ff574f5e9860654e098fe852ba8ac5dd5cefe1767d23a020a92f501"
|
||||
}
|
||||
|
||||
388
interface/pnpm-lock.yaml
generated
388
interface/pnpm-lock.yaml
generated
@@ -13,22 +13,22 @@ importers:
|
||||
version: 2.3.0(alova@3.4.0)
|
||||
'@emotion/react':
|
||||
specifier: ^11.14.0
|
||||
version: 11.14.0(@types/react@19.2.7)(react@19.2.1)
|
||||
version: 11.14.0(@types/react@19.2.7)(react@19.2.2)
|
||||
'@emotion/styled':
|
||||
specifier: ^11.14.1
|
||||
version: 11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1)
|
||||
version: 11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2)
|
||||
'@mui/icons-material':
|
||||
specifier: ^7.3.6
|
||||
version: 7.3.6(@mui/material@7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(@types/react@19.2.7)(react@19.2.1)
|
||||
version: 7.3.6(@mui/material@7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react-dom@19.2.2(react@19.2.2))(react@19.2.2))(@types/react@19.2.7)(react@19.2.2)
|
||||
'@mui/material':
|
||||
specifier: ^7.3.6
|
||||
version: 7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)
|
||||
version: 7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)
|
||||
'@preact/compat':
|
||||
specifier: ^18.3.1
|
||||
version: 18.3.1(preact@10.28.0)
|
||||
'@table-library/react-table-library':
|
||||
specifier: 4.1.15
|
||||
version: 4.1.15(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1)
|
||||
version: 4.1.15(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(react-dom@19.2.2(react@19.2.2))(react@19.2.2)
|
||||
alova:
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0
|
||||
@@ -54,20 +54,20 @@ importers:
|
||||
specifier: ^10.28.0
|
||||
version: 10.28.0
|
||||
react:
|
||||
specifier: ^19.2.1
|
||||
version: 19.2.1
|
||||
specifier: ^19.2.2
|
||||
version: 19.2.2
|
||||
react-dom:
|
||||
specifier: ^19.2.1
|
||||
version: 19.2.1(react@19.2.1)
|
||||
specifier: ^19.2.2
|
||||
version: 19.2.2(react@19.2.2)
|
||||
react-icons:
|
||||
specifier: ^5.5.0
|
||||
version: 5.5.0(react@19.2.1)
|
||||
version: 5.5.0(react@19.2.2)
|
||||
react-router:
|
||||
specifier: ^7.10.1
|
||||
version: 7.10.1(react-dom@19.2.1(react@19.2.1))(react@19.2.1)
|
||||
version: 7.10.1(react-dom@19.2.2(react@19.2.2))(react@19.2.2)
|
||||
react-toastify:
|
||||
specifier: ^11.0.5
|
||||
version: 11.0.5(react-dom@19.2.1(react@19.2.1))(react@19.2.1)
|
||||
version: 11.0.5(react-dom@19.2.2(react@19.2.2))(react@19.2.2)
|
||||
typesafe-i18n:
|
||||
specifier: ^5.26.2
|
||||
version: 5.26.2(typescript@5.9.3)
|
||||
@@ -83,13 +83,13 @@ importers:
|
||||
version: 9.39.1
|
||||
'@preact/preset-vite':
|
||||
specifier: ^2.10.2
|
||||
version: 2.10.2(@babel/core@7.28.5)(preact@10.28.0)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1))
|
||||
version: 2.10.2(@babel/core@7.28.5)(preact@10.28.0)(vite@7.2.7(@types/node@25.0.0)(terser@5.44.1))
|
||||
'@trivago/prettier-plugin-sort-imports':
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.0(prettier@3.7.4)
|
||||
'@types/node':
|
||||
specifier: ^24.10.1
|
||||
version: 24.10.1
|
||||
specifier: ^25.0.0
|
||||
version: 25.0.0
|
||||
'@types/react':
|
||||
specifier: ^19.2.7
|
||||
version: 19.2.7
|
||||
@@ -118,17 +118,17 @@ importers:
|
||||
specifier: ^5.44.1
|
||||
version: 5.44.1
|
||||
typescript-eslint:
|
||||
specifier: ^8.48.1
|
||||
version: 8.48.1(eslint@9.39.1)(typescript@5.9.3)
|
||||
specifier: ^8.49.0
|
||||
version: 8.49.0(eslint@9.39.1)(typescript@5.9.3)
|
||||
vite:
|
||||
specifier: ^7.2.6
|
||||
version: 7.2.6(@types/node@24.10.1)(terser@5.44.1)
|
||||
specifier: ^7.2.7
|
||||
version: 7.2.7(@types/node@25.0.0)(terser@5.44.1)
|
||||
vite-plugin-imagemin:
|
||||
specifier: ^0.6.1
|
||||
version: 0.6.1(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1))
|
||||
version: 0.6.1(vite@7.2.7(@types/node@25.0.0)(terser@5.44.1))
|
||||
vite-tsconfig-paths:
|
||||
specifier: ^5.1.4
|
||||
version: 5.1.4(typescript@5.9.3)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1))
|
||||
version: 5.1.4(typescript@5.9.3)(vite@7.2.7(@types/node@25.0.0)(terser@5.44.1))
|
||||
|
||||
packages:
|
||||
|
||||
@@ -860,8 +860,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@24.10.1':
|
||||
resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==}
|
||||
'@types/node@25.0.0':
|
||||
resolution: {integrity: sha512-rl78HwuZlaDIUSeUKkmogkhebA+8K1Hy7tddZuJ3D0xV8pZSfsYGTsliGUol1JPzu9EKnTxPC4L1fiWouStRew==}
|
||||
|
||||
'@types/parse-json@4.0.2':
|
||||
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
|
||||
@@ -888,63 +888,63 @@ packages:
|
||||
'@types/svgo@2.6.4':
|
||||
resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.48.1':
|
||||
resolution: {integrity: sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==}
|
||||
'@typescript-eslint/eslint-plugin@8.49.0':
|
||||
resolution: {integrity: sha512-JXij0vzIaTtCwu6SxTh8qBc66kmf1xs7pI4UOiMDFVct6q86G0Zs7KRcEoJgY3Cav3x5Tq0MF5jwgpgLqgKG3A==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': ^8.48.1
|
||||
'@typescript-eslint/parser': ^8.49.0
|
||||
eslint: ^8.57.0 || ^9.0.0
|
||||
typescript: '>=4.8.4 <6.0.0'
|
||||
|
||||
'@typescript-eslint/parser@8.48.1':
|
||||
resolution: {integrity: sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==}
|
||||
'@typescript-eslint/parser@8.49.0':
|
||||
resolution: {integrity: sha512-N9lBGA9o9aqb1hVMc9hzySbhKibHmB+N3IpoShyV6HyQYRGIhlrO5rQgttypi+yEeKsKI4idxC8Jw6gXKD4THA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0
|
||||
typescript: '>=4.8.4 <6.0.0'
|
||||
|
||||
'@typescript-eslint/project-service@8.48.1':
|
||||
resolution: {integrity: sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==}
|
||||
'@typescript-eslint/project-service@8.49.0':
|
||||
resolution: {integrity: sha512-/wJN0/DKkmRUMXjZUXYZpD1NEQzQAAn9QWfGwo+Ai8gnzqH7tvqS7oNVdTjKqOcPyVIdZdyCMoqN66Ia789e7g==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.0.0'
|
||||
|
||||
'@typescript-eslint/scope-manager@8.48.1':
|
||||
resolution: {integrity: sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==}
|
||||
'@typescript-eslint/scope-manager@8.49.0':
|
||||
resolution: {integrity: sha512-npgS3zi+/30KSOkXNs0LQXtsg9ekZ8OISAOLGWA/ZOEn0ZH74Ginfl7foziV8DT+D98WfQ5Kopwqb/PZOaIJGg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/tsconfig-utils@8.48.1':
|
||||
resolution: {integrity: sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==}
|
||||
'@typescript-eslint/tsconfig-utils@8.49.0':
|
||||
resolution: {integrity: sha512-8prixNi1/6nawsRYxet4YOhnbW+W9FK/bQPxsGB1D3ZrDzbJ5FXw5XmzxZv82X3B+ZccuSxo/X8q9nQ+mFecWA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.0.0'
|
||||
|
||||
'@typescript-eslint/type-utils@8.48.1':
|
||||
resolution: {integrity: sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==}
|
||||
'@typescript-eslint/type-utils@8.49.0':
|
||||
resolution: {integrity: sha512-KTExJfQ+svY8I10P4HdxKzWsvtVnsuCifU5MvXrRwoP2KOlNZ9ADNEWWsQTJgMxLzS5VLQKDjkCT/YzgsnqmZg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0
|
||||
typescript: '>=4.8.4 <6.0.0'
|
||||
|
||||
'@typescript-eslint/types@8.48.1':
|
||||
resolution: {integrity: sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==}
|
||||
'@typescript-eslint/types@8.49.0':
|
||||
resolution: {integrity: sha512-e9k/fneezorUo6WShlQpMxXh8/8wfyc+biu6tnAqA81oWrEic0k21RHzP9uqqpyBBeBKu4T+Bsjy9/b8u7obXQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.48.1':
|
||||
resolution: {integrity: sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==}
|
||||
'@typescript-eslint/typescript-estree@8.49.0':
|
||||
resolution: {integrity: sha512-jrLdRuAbPfPIdYNppHJ/D0wN+wwNfJ32YTAm10eJVsFmrVpXQnDWBn8niCSMlWjvml8jsce5E/O+86IQtTbJWA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.0.0'
|
||||
|
||||
'@typescript-eslint/utils@8.48.1':
|
||||
resolution: {integrity: sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==}
|
||||
'@typescript-eslint/utils@8.49.0':
|
||||
resolution: {integrity: sha512-N3W7rJw7Rw+z1tRsHZbK395TWSYvufBXumYtEGzypgMUthlg0/hmCImeA8hgO2d2G4pd7ftpxxul2J8OdtdaFA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0
|
||||
typescript: '>=4.8.4 <6.0.0'
|
||||
|
||||
'@typescript-eslint/visitor-keys@8.48.1':
|
||||
resolution: {integrity: sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==}
|
||||
'@typescript-eslint/visitor-keys@8.49.0':
|
||||
resolution: {integrity: sha512-LlKaciDe3GmZFphXIc79THF/YYBugZ7FS1pO581E/edlVVNbZKDy93evqmrfQ9/Y4uN0vVhX4iuchq26mK/iiA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
acorn-jsx@5.3.2:
|
||||
@@ -1027,8 +1027,8 @@ packages:
|
||||
base64-js@1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
|
||||
baseline-browser-mapping@2.9.2:
|
||||
resolution: {integrity: sha512-PxSsosKQjI38iXkmb3d0Y32efqyA0uW4s41u4IVBsLlWLhCiYNpH/AfNOVWRqCQBlD8TFJTz6OUWNd4DFJCnmw==}
|
||||
baseline-browser-mapping@2.9.6:
|
||||
resolution: {integrity: sha512-v9BVVpOTLB59C9E7aSnmIF8h7qRsFpx+A2nugVMTszEOMcfjlZMsXRm4LF23I3Z9AJxc8ANpIvzbzONoX9VJlg==}
|
||||
hasBin: true
|
||||
|
||||
bin-build@3.0.0:
|
||||
@@ -1117,8 +1117,8 @@ packages:
|
||||
resolution: {integrity: sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
caniuse-lite@1.0.30001759:
|
||||
resolution: {integrity: sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==}
|
||||
caniuse-lite@1.0.30001760:
|
||||
resolution: {integrity: sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==}
|
||||
|
||||
caw@2.0.1:
|
||||
resolution: {integrity: sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==}
|
||||
@@ -1337,8 +1337,8 @@ packages:
|
||||
duplexer3@0.1.5:
|
||||
resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==}
|
||||
|
||||
electron-to-chromium@1.5.265:
|
||||
resolution: {integrity: sha512-B7IkLR1/AE+9jR2LtVF/1/6PFhY5TlnEHnlrKmGk7PvkJibg5jr+mLXLLzq3QYl6PA1T/vLDthQPqIPAlS/PPA==}
|
||||
electron-to-chromium@1.5.267:
|
||||
resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==}
|
||||
|
||||
emoji-regex@8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
@@ -1815,9 +1815,6 @@ packages:
|
||||
graceful-fs@4.2.11:
|
||||
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||
|
||||
graphemer@1.4.0:
|
||||
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
|
||||
|
||||
has-ansi@2.0.0:
|
||||
resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -2512,10 +2509,10 @@ packages:
|
||||
rate-limiter-flexible@5.0.5:
|
||||
resolution: {integrity: sha512-+/dSQfo+3FYwYygUs/V2BBdwGa9nFtakDwKt4l0bnvNB53TNT++QSFewwHX9qXrZJuMe9j+TUaU21lm5ARgqdQ==}
|
||||
|
||||
react-dom@19.2.1:
|
||||
resolution: {integrity: sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==}
|
||||
react-dom@19.2.2:
|
||||
resolution: {integrity: sha512-fhyD2BLrew6qYf4NNtHff1rLXvzR25rq49p+FeqByOazc6TcSi2n8EYulo5C1PbH+1uBW++5S1SG7FcUU6mlDg==}
|
||||
peerDependencies:
|
||||
react: ^19.2.1
|
||||
react: ^19.2.2
|
||||
|
||||
react-icons@5.5.0:
|
||||
resolution: {integrity: sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==}
|
||||
@@ -2525,8 +2522,8 @@ packages:
|
||||
react-is@16.13.1:
|
||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||
|
||||
react-is@19.2.1:
|
||||
resolution: {integrity: sha512-L7BnWgRbMwzMAubQcS7sXdPdNLmKlucPlopgAzx7FtYbksWZgEWiuYM5x9T6UqS2Ne0rsgQTq5kY2SGqpzUkYA==}
|
||||
react-is@19.2.2:
|
||||
resolution: {integrity: sha512-ADrk8mxPwhyj+IB8EnMMRzxnon5hJrOdEZl+mCrrHXfPGGPYHdRm1962fvXUiWAu/ZC1G+OTgBN3Puq57iS4Yg==}
|
||||
|
||||
react-router@7.10.1:
|
||||
resolution: {integrity: sha512-gHL89dRa3kwlUYtRQ+m8NmxGI6CgqN+k4XyGjwcFoQwwCWF6xXpOCUlDovkXClS0d0XJN/5q7kc5W3kiFEd0Yw==}
|
||||
@@ -2563,8 +2560,8 @@ packages:
|
||||
react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
|
||||
react@19.2.1:
|
||||
resolution: {integrity: sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==}
|
||||
react@19.2.2:
|
||||
resolution: {integrity: sha512-BdOGOY8OKRBcgoDkwqA8Q5XvOIhoNx/Sh6BnGJlet2Abt0X5BK0BDrqGyQgLhAVjD2nAg5f6o01u/OPUhG022Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
read-pkg-up@1.0.1:
|
||||
@@ -2927,8 +2924,8 @@ packages:
|
||||
peerDependencies:
|
||||
typescript: '>=3.5.1'
|
||||
|
||||
typescript-eslint@8.48.1:
|
||||
resolution: {integrity: sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==}
|
||||
typescript-eslint@8.49.0:
|
||||
resolution: {integrity: sha512-zRSVH1WXD0uXczCXw+nsdjGPUdx4dfrs5VQoHnUWmv1U3oNlAKv4FUNdLDhVUg+gYn+a5hUESqch//Rv5wVhrg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0
|
||||
@@ -2999,8 +2996,8 @@ packages:
|
||||
vite:
|
||||
optional: true
|
||||
|
||||
vite@7.2.6:
|
||||
resolution: {integrity: sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==}
|
||||
vite@7.2.7:
|
||||
resolution: {integrity: sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@@ -3268,17 +3265,17 @@ snapshots:
|
||||
|
||||
'@emotion/memoize@0.9.0': {}
|
||||
|
||||
'@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1)':
|
||||
'@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.4
|
||||
'@emotion/babel-plugin': 11.13.5
|
||||
'@emotion/cache': 11.14.0
|
||||
'@emotion/serialize': 1.3.3
|
||||
'@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.1)
|
||||
'@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.2)
|
||||
'@emotion/utils': 1.4.2
|
||||
'@emotion/weak-memoize': 0.4.0
|
||||
hoist-non-react-statics: 3.3.2
|
||||
react: 19.2.1
|
||||
react: 19.2.2
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.7
|
||||
transitivePeerDependencies:
|
||||
@@ -3294,16 +3291,16 @@ snapshots:
|
||||
|
||||
'@emotion/sheet@1.4.0': {}
|
||||
|
||||
'@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1)':
|
||||
'@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.4
|
||||
'@emotion/babel-plugin': 11.13.5
|
||||
'@emotion/is-prop-valid': 1.4.0
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.7)(react@19.2.1)
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.7)(react@19.2.2)
|
||||
'@emotion/serialize': 1.3.3
|
||||
'@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.1)
|
||||
'@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.2)
|
||||
'@emotion/utils': 1.4.2
|
||||
react: 19.2.1
|
||||
react: 19.2.2
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.7
|
||||
transitivePeerDependencies:
|
||||
@@ -3311,9 +3308,9 @@ snapshots:
|
||||
|
||||
'@emotion/unitless@0.10.0': {}
|
||||
|
||||
'@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.2.1)':
|
||||
'@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.2.2)':
|
||||
dependencies:
|
||||
react: 19.2.1
|
||||
react: 19.2.2
|
||||
|
||||
'@emotion/utils@1.4.2': {}
|
||||
|
||||
@@ -3489,45 +3486,45 @@ snapshots:
|
||||
|
||||
'@mui/core-downloads-tracker@7.3.6': {}
|
||||
|
||||
'@mui/icons-material@7.3.6(@mui/material@7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(@types/react@19.2.7)(react@19.2.1)':
|
||||
'@mui/icons-material@7.3.6(@mui/material@7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react-dom@19.2.2(react@19.2.2))(react@19.2.2))(@types/react@19.2.7)(react@19.2.2)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.4
|
||||
'@mui/material': 7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)
|
||||
react: 19.2.1
|
||||
'@mui/material': 7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)
|
||||
react: 19.2.2
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.7
|
||||
|
||||
'@mui/material@7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)':
|
||||
'@mui/material@7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.4
|
||||
'@mui/core-downloads-tracker': 7.3.6
|
||||
'@mui/system': 7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1)
|
||||
'@mui/system': 7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2)
|
||||
'@mui/types': 7.4.9(@types/react@19.2.7)
|
||||
'@mui/utils': 7.3.6(@types/react@19.2.7)(react@19.2.1)
|
||||
'@mui/utils': 7.3.6(@types/react@19.2.7)(react@19.2.2)
|
||||
'@popperjs/core': 2.11.8
|
||||
'@types/react-transition-group': 4.4.12(@types/react@19.2.7)
|
||||
clsx: 2.1.1
|
||||
csstype: 3.2.3
|
||||
prop-types: 15.8.1
|
||||
react: 19.2.1
|
||||
react-dom: 19.2.1(react@19.2.1)
|
||||
react-is: 19.2.1
|
||||
react-transition-group: 4.4.5(react-dom@19.2.1(react@19.2.1))(react@19.2.1)
|
||||
react: 19.2.2
|
||||
react-dom: 19.2.2(react@19.2.2)
|
||||
react-is: 19.2.2
|
||||
react-transition-group: 4.4.5(react-dom@19.2.2(react@19.2.2))(react@19.2.2)
|
||||
optionalDependencies:
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.7)(react@19.2.1)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1)
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.7)(react@19.2.2)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2)
|
||||
'@types/react': 19.2.7
|
||||
|
||||
'@mui/private-theming@7.3.6(@types/react@19.2.7)(react@19.2.1)':
|
||||
'@mui/private-theming@7.3.6(@types/react@19.2.7)(react@19.2.2)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.4
|
||||
'@mui/utils': 7.3.6(@types/react@19.2.7)(react@19.2.1)
|
||||
'@mui/utils': 7.3.6(@types/react@19.2.7)(react@19.2.2)
|
||||
prop-types: 15.8.1
|
||||
react: 19.2.1
|
||||
react: 19.2.2
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.7
|
||||
|
||||
'@mui/styled-engine@7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1))(react@19.2.1)':
|
||||
'@mui/styled-engine@7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(react@19.2.2)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.4
|
||||
'@emotion/cache': 11.14.0
|
||||
@@ -3535,25 +3532,25 @@ snapshots:
|
||||
'@emotion/sheet': 1.4.0
|
||||
csstype: 3.2.3
|
||||
prop-types: 15.8.1
|
||||
react: 19.2.1
|
||||
react: 19.2.2
|
||||
optionalDependencies:
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.7)(react@19.2.1)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1)
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.7)(react@19.2.2)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2)
|
||||
|
||||
'@mui/system@7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1)':
|
||||
'@mui/system@7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.4
|
||||
'@mui/private-theming': 7.3.6(@types/react@19.2.7)(react@19.2.1)
|
||||
'@mui/styled-engine': 7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1))(react@19.2.1)
|
||||
'@mui/private-theming': 7.3.6(@types/react@19.2.7)(react@19.2.2)
|
||||
'@mui/styled-engine': 7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(react@19.2.2)
|
||||
'@mui/types': 7.4.9(@types/react@19.2.7)
|
||||
'@mui/utils': 7.3.6(@types/react@19.2.7)(react@19.2.1)
|
||||
'@mui/utils': 7.3.6(@types/react@19.2.7)(react@19.2.2)
|
||||
clsx: 2.1.1
|
||||
csstype: 3.2.3
|
||||
prop-types: 15.8.1
|
||||
react: 19.2.1
|
||||
react: 19.2.2
|
||||
optionalDependencies:
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.7)(react@19.2.1)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(@types/react@19.2.7)(react@19.2.1)
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.7)(react@19.2.2)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2)
|
||||
'@types/react': 19.2.7
|
||||
|
||||
'@mui/types@7.4.9(@types/react@19.2.7)':
|
||||
@@ -3562,15 +3559,15 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.7
|
||||
|
||||
'@mui/utils@7.3.6(@types/react@19.2.7)(react@19.2.1)':
|
||||
'@mui/utils@7.3.6(@types/react@19.2.7)(react@19.2.2)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.4
|
||||
'@mui/types': 7.4.9(@types/react@19.2.7)
|
||||
'@types/prop-types': 15.7.15
|
||||
clsx: 2.1.1
|
||||
prop-types: 15.8.1
|
||||
react: 19.2.1
|
||||
react-is: 19.2.1
|
||||
react: 19.2.2
|
||||
react-is: 19.2.2
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.7
|
||||
|
||||
@@ -3598,18 +3595,18 @@ snapshots:
|
||||
dependencies:
|
||||
preact: 10.28.0
|
||||
|
||||
'@preact/preset-vite@2.10.2(@babel/core@7.28.5)(preact@10.28.0)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1))':
|
||||
'@preact/preset-vite@2.10.2(@babel/core@7.28.5)(preact@10.28.0)(vite@7.2.7(@types/node@25.0.0)(terser@5.44.1))':
|
||||
dependencies:
|
||||
'@babel/core': 7.28.5
|
||||
'@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.5)
|
||||
'@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.5)
|
||||
'@prefresh/vite': 2.4.11(preact@10.28.0)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1))
|
||||
'@prefresh/vite': 2.4.11(preact@10.28.0)(vite@7.2.7(@types/node@25.0.0)(terser@5.44.1))
|
||||
'@rollup/pluginutils': 4.2.1
|
||||
babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.28.5)
|
||||
debug: 4.4.3
|
||||
picocolors: 1.1.1
|
||||
vite: 7.2.6(@types/node@24.10.1)(terser@5.44.1)
|
||||
vite-prerender-plugin: 0.5.12(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1))
|
||||
vite: 7.2.7(@types/node@25.0.0)(terser@5.44.1)
|
||||
vite-prerender-plugin: 0.5.12(vite@7.2.7(@types/node@25.0.0)(terser@5.44.1))
|
||||
transitivePeerDependencies:
|
||||
- preact
|
||||
- supports-color
|
||||
@@ -3622,7 +3619,7 @@ snapshots:
|
||||
|
||||
'@prefresh/utils@1.2.1': {}
|
||||
|
||||
'@prefresh/vite@2.4.11(preact@10.28.0)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1))':
|
||||
'@prefresh/vite@2.4.11(preact@10.28.0)(vite@7.2.7(@types/node@25.0.0)(terser@5.44.1))':
|
||||
dependencies:
|
||||
'@babel/core': 7.28.5
|
||||
'@prefresh/babel-plugin': 0.5.2
|
||||
@@ -3630,7 +3627,7 @@ snapshots:
|
||||
'@prefresh/utils': 1.2.1
|
||||
'@rollup/pluginutils': 4.2.1
|
||||
preact: 10.28.0
|
||||
vite: 7.2.6(@types/node@24.10.1)(terser@5.44.1)
|
||||
vite: 7.2.7(@types/node@25.0.0)(terser@5.44.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -3707,14 +3704,14 @@ snapshots:
|
||||
|
||||
'@sindresorhus/is@0.7.0': {}
|
||||
|
||||
'@table-library/react-table-library@4.1.15(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1)':
|
||||
'@table-library/react-table-library@4.1.15(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(react-dom@19.2.2(react@19.2.2))(react@19.2.2)':
|
||||
dependencies:
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.7)(react@19.2.1)
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.7)(react@19.2.2)
|
||||
clsx: 1.1.1
|
||||
react: 19.2.1
|
||||
react-dom: 19.2.1(react@19.2.1)
|
||||
react-virtualized-auto-sizer: 1.0.26(react-dom@19.2.1(react@19.2.1))(react@19.2.1)
|
||||
react-window: 1.8.11(react-dom@19.2.1(react@19.2.1))(react@19.2.1)
|
||||
react: 19.2.2
|
||||
react-dom: 19.2.2(react@19.2.2)
|
||||
react-virtualized-auto-sizer: 1.0.26(react-dom@19.2.2(react@19.2.2))(react@19.2.2)
|
||||
react-window: 1.8.11(react-dom@19.2.2(react@19.2.2))(react@19.2.2)
|
||||
|
||||
'@trivago/prettier-plugin-sort-imports@6.0.0(prettier@3.7.4)':
|
||||
dependencies:
|
||||
@@ -3737,7 +3734,7 @@ snapshots:
|
||||
'@types/glob@7.2.0':
|
||||
dependencies:
|
||||
'@types/minimatch': 6.0.0
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.0
|
||||
|
||||
'@types/imagemin-gifsicle@7.0.4':
|
||||
dependencies:
|
||||
@@ -3766,19 +3763,19 @@ snapshots:
|
||||
|
||||
'@types/imagemin@7.0.1':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.0
|
||||
|
||||
'@types/json-schema@7.0.15': {}
|
||||
|
||||
'@types/keyv@3.1.4':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.0
|
||||
|
||||
'@types/minimatch@6.0.0':
|
||||
dependencies:
|
||||
minimatch: 10.1.1
|
||||
|
||||
'@types/node@24.10.1':
|
||||
'@types/node@25.0.0':
|
||||
dependencies:
|
||||
undici-types: 7.16.0
|
||||
|
||||
@@ -3800,22 +3797,21 @@ snapshots:
|
||||
|
||||
'@types/responselike@1.0.3':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.0
|
||||
|
||||
'@types/svgo@2.6.4':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.0
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)':
|
||||
'@typescript-eslint/eslint-plugin@8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.2
|
||||
'@typescript-eslint/parser': 8.48.1(eslint@9.39.1)(typescript@5.9.3)
|
||||
'@typescript-eslint/scope-manager': 8.48.1
|
||||
'@typescript-eslint/type-utils': 8.48.1(eslint@9.39.1)(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.48.1(eslint@9.39.1)(typescript@5.9.3)
|
||||
'@typescript-eslint/visitor-keys': 8.48.1
|
||||
'@typescript-eslint/parser': 8.49.0(eslint@9.39.1)(typescript@5.9.3)
|
||||
'@typescript-eslint/scope-manager': 8.49.0
|
||||
'@typescript-eslint/type-utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3)
|
||||
'@typescript-eslint/visitor-keys': 8.49.0
|
||||
eslint: 9.39.1
|
||||
graphemer: 1.4.0
|
||||
ignore: 7.0.5
|
||||
natural-compare: 1.4.0
|
||||
ts-api-utils: 2.1.0(typescript@5.9.3)
|
||||
@@ -3823,41 +3819,41 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/parser@8.48.1(eslint@9.39.1)(typescript@5.9.3)':
|
||||
'@typescript-eslint/parser@8.49.0(eslint@9.39.1)(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 8.48.1
|
||||
'@typescript-eslint/types': 8.48.1
|
||||
'@typescript-eslint/typescript-estree': 8.48.1(typescript@5.9.3)
|
||||
'@typescript-eslint/visitor-keys': 8.48.1
|
||||
'@typescript-eslint/scope-manager': 8.49.0
|
||||
'@typescript-eslint/types': 8.49.0
|
||||
'@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3)
|
||||
'@typescript-eslint/visitor-keys': 8.49.0
|
||||
debug: 4.4.3
|
||||
eslint: 9.39.1
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/project-service@8.48.1(typescript@5.9.3)':
|
||||
'@typescript-eslint/project-service@8.49.0(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/tsconfig-utils': 8.48.1(typescript@5.9.3)
|
||||
'@typescript-eslint/types': 8.48.1
|
||||
'@typescript-eslint/tsconfig-utils': 8.49.0(typescript@5.9.3)
|
||||
'@typescript-eslint/types': 8.49.0
|
||||
debug: 4.4.3
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/scope-manager@8.48.1':
|
||||
'@typescript-eslint/scope-manager@8.49.0':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.48.1
|
||||
'@typescript-eslint/visitor-keys': 8.48.1
|
||||
'@typescript-eslint/types': 8.49.0
|
||||
'@typescript-eslint/visitor-keys': 8.49.0
|
||||
|
||||
'@typescript-eslint/tsconfig-utils@8.48.1(typescript@5.9.3)':
|
||||
'@typescript-eslint/tsconfig-utils@8.49.0(typescript@5.9.3)':
|
||||
dependencies:
|
||||
typescript: 5.9.3
|
||||
|
||||
'@typescript-eslint/type-utils@8.48.1(eslint@9.39.1)(typescript@5.9.3)':
|
||||
'@typescript-eslint/type-utils@8.49.0(eslint@9.39.1)(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.48.1
|
||||
'@typescript-eslint/typescript-estree': 8.48.1(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.48.1(eslint@9.39.1)(typescript@5.9.3)
|
||||
'@typescript-eslint/types': 8.49.0
|
||||
'@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3)
|
||||
debug: 4.4.3
|
||||
eslint: 9.39.1
|
||||
ts-api-utils: 2.1.0(typescript@5.9.3)
|
||||
@@ -3865,14 +3861,14 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/types@8.48.1': {}
|
||||
'@typescript-eslint/types@8.49.0': {}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.48.1(typescript@5.9.3)':
|
||||
'@typescript-eslint/typescript-estree@8.49.0(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/project-service': 8.48.1(typescript@5.9.3)
|
||||
'@typescript-eslint/tsconfig-utils': 8.48.1(typescript@5.9.3)
|
||||
'@typescript-eslint/types': 8.48.1
|
||||
'@typescript-eslint/visitor-keys': 8.48.1
|
||||
'@typescript-eslint/project-service': 8.49.0(typescript@5.9.3)
|
||||
'@typescript-eslint/tsconfig-utils': 8.49.0(typescript@5.9.3)
|
||||
'@typescript-eslint/types': 8.49.0
|
||||
'@typescript-eslint/visitor-keys': 8.49.0
|
||||
debug: 4.4.3
|
||||
minimatch: 9.0.5
|
||||
semver: 7.7.3
|
||||
@@ -3882,20 +3878,20 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/utils@8.48.1(eslint@9.39.1)(typescript@5.9.3)':
|
||||
'@typescript-eslint/utils@8.49.0(eslint@9.39.1)(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1)
|
||||
'@typescript-eslint/scope-manager': 8.48.1
|
||||
'@typescript-eslint/types': 8.48.1
|
||||
'@typescript-eslint/typescript-estree': 8.48.1(typescript@5.9.3)
|
||||
'@typescript-eslint/scope-manager': 8.49.0
|
||||
'@typescript-eslint/types': 8.49.0
|
||||
'@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3)
|
||||
eslint: 9.39.1
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/visitor-keys@8.48.1':
|
||||
'@typescript-eslint/visitor-keys@8.49.0':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.48.1
|
||||
'@typescript-eslint/types': 8.49.0
|
||||
eslint-visitor-keys: 4.2.1
|
||||
|
||||
acorn-jsx@5.3.2(acorn@8.15.0):
|
||||
@@ -3962,7 +3958,7 @@ snapshots:
|
||||
|
||||
base64-js@1.5.1: {}
|
||||
|
||||
baseline-browser-mapping@2.9.2: {}
|
||||
baseline-browser-mapping@2.9.6: {}
|
||||
|
||||
bin-build@3.0.0:
|
||||
dependencies:
|
||||
@@ -4019,9 +4015,9 @@ snapshots:
|
||||
|
||||
browserslist@4.28.1:
|
||||
dependencies:
|
||||
baseline-browser-mapping: 2.9.2
|
||||
caniuse-lite: 1.0.30001759
|
||||
electron-to-chromium: 1.5.265
|
||||
baseline-browser-mapping: 2.9.6
|
||||
caniuse-lite: 1.0.30001760
|
||||
electron-to-chromium: 1.5.267
|
||||
node-releases: 2.0.27
|
||||
update-browserslist-db: 1.2.2(browserslist@4.28.1)
|
||||
|
||||
@@ -4079,7 +4075,7 @@ snapshots:
|
||||
|
||||
camelcase@2.1.1: {}
|
||||
|
||||
caniuse-lite@1.0.30001759: {}
|
||||
caniuse-lite@1.0.30001760: {}
|
||||
|
||||
caw@2.0.1:
|
||||
dependencies:
|
||||
@@ -4366,7 +4362,7 @@ snapshots:
|
||||
|
||||
duplexer3@0.1.5: {}
|
||||
|
||||
electron-to-chromium@1.5.265: {}
|
||||
electron-to-chromium@1.5.267: {}
|
||||
|
||||
emoji-regex@8.0.0: {}
|
||||
|
||||
@@ -4895,8 +4891,6 @@ snapshots:
|
||||
|
||||
graceful-fs@4.2.11: {}
|
||||
|
||||
graphemer@1.4.0: {}
|
||||
|
||||
has-ansi@2.0.0:
|
||||
dependencies:
|
||||
ansi-regex: 2.1.1
|
||||
@@ -5518,55 +5512,55 @@ snapshots:
|
||||
|
||||
rate-limiter-flexible@5.0.5: {}
|
||||
|
||||
react-dom@19.2.1(react@19.2.1):
|
||||
react-dom@19.2.2(react@19.2.2):
|
||||
dependencies:
|
||||
react: 19.2.1
|
||||
react: 19.2.2
|
||||
scheduler: 0.27.0
|
||||
|
||||
react-icons@5.5.0(react@19.2.1):
|
||||
react-icons@5.5.0(react@19.2.2):
|
||||
dependencies:
|
||||
react: 19.2.1
|
||||
react: 19.2.2
|
||||
|
||||
react-is@16.13.1: {}
|
||||
|
||||
react-is@19.2.1: {}
|
||||
react-is@19.2.2: {}
|
||||
|
||||
react-router@7.10.1(react-dom@19.2.1(react@19.2.1))(react@19.2.1):
|
||||
react-router@7.10.1(react-dom@19.2.2(react@19.2.2))(react@19.2.2):
|
||||
dependencies:
|
||||
cookie: 1.1.1
|
||||
react: 19.2.1
|
||||
react: 19.2.2
|
||||
set-cookie-parser: 2.7.2
|
||||
optionalDependencies:
|
||||
react-dom: 19.2.1(react@19.2.1)
|
||||
react-dom: 19.2.2(react@19.2.2)
|
||||
|
||||
react-toastify@11.0.5(react-dom@19.2.1(react@19.2.1))(react@19.2.1):
|
||||
react-toastify@11.0.5(react-dom@19.2.2(react@19.2.2))(react@19.2.2):
|
||||
dependencies:
|
||||
clsx: 2.1.1
|
||||
react: 19.2.1
|
||||
react-dom: 19.2.1(react@19.2.1)
|
||||
react: 19.2.2
|
||||
react-dom: 19.2.2(react@19.2.2)
|
||||
|
||||
react-transition-group@4.4.5(react-dom@19.2.1(react@19.2.1))(react@19.2.1):
|
||||
react-transition-group@4.4.5(react-dom@19.2.2(react@19.2.2))(react@19.2.2):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.4
|
||||
dom-helpers: 5.2.1
|
||||
loose-envify: 1.4.0
|
||||
prop-types: 15.8.1
|
||||
react: 19.2.1
|
||||
react-dom: 19.2.1(react@19.2.1)
|
||||
react: 19.2.2
|
||||
react-dom: 19.2.2(react@19.2.2)
|
||||
|
||||
react-virtualized-auto-sizer@1.0.26(react-dom@19.2.1(react@19.2.1))(react@19.2.1):
|
||||
react-virtualized-auto-sizer@1.0.26(react-dom@19.2.2(react@19.2.2))(react@19.2.2):
|
||||
dependencies:
|
||||
react: 19.2.1
|
||||
react-dom: 19.2.1(react@19.2.1)
|
||||
react: 19.2.2
|
||||
react-dom: 19.2.2(react@19.2.2)
|
||||
|
||||
react-window@1.8.11(react-dom@19.2.1(react@19.2.1))(react@19.2.1):
|
||||
react-window@1.8.11(react-dom@19.2.2(react@19.2.2))(react@19.2.2):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.4
|
||||
memoize-one: 5.2.1
|
||||
react: 19.2.1
|
||||
react-dom: 19.2.1(react@19.2.1)
|
||||
react: 19.2.2
|
||||
react-dom: 19.2.2(react@19.2.2)
|
||||
|
||||
react@19.2.1: {}
|
||||
react@19.2.2: {}
|
||||
|
||||
read-pkg-up@1.0.1:
|
||||
dependencies:
|
||||
@@ -5918,12 +5912,12 @@ snapshots:
|
||||
dependencies:
|
||||
typescript: 5.9.3
|
||||
|
||||
typescript-eslint@8.48.1(eslint@9.39.1)(typescript@5.9.3):
|
||||
typescript-eslint@8.49.0(eslint@9.39.1)(typescript@5.9.3):
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)
|
||||
'@typescript-eslint/parser': 8.48.1(eslint@9.39.1)(typescript@5.9.3)
|
||||
'@typescript-eslint/typescript-estree': 8.48.1(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.48.1(eslint@9.39.1)(typescript@5.9.3)
|
||||
'@typescript-eslint/eslint-plugin': 8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)
|
||||
'@typescript-eslint/parser': 8.49.0(eslint@9.39.1)(typescript@5.9.3)
|
||||
'@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3)
|
||||
eslint: 9.39.1
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
@@ -5969,7 +5963,7 @@ snapshots:
|
||||
spdx-correct: 3.2.0
|
||||
spdx-expression-parse: 3.0.1
|
||||
|
||||
vite-plugin-imagemin@0.6.1(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)):
|
||||
vite-plugin-imagemin@0.6.1(vite@7.2.7(@types/node@25.0.0)(terser@5.44.1)):
|
||||
dependencies:
|
||||
'@types/imagemin': 7.0.1
|
||||
'@types/imagemin-gifsicle': 7.0.4
|
||||
@@ -5994,11 +5988,11 @@ snapshots:
|
||||
imagemin-webp: 6.1.0
|
||||
jpegtran-bin: 6.0.1
|
||||
pathe: 0.2.0
|
||||
vite: 7.2.6(@types/node@24.10.1)(terser@5.44.1)
|
||||
vite: 7.2.7(@types/node@25.0.0)(terser@5.44.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-prerender-plugin@0.5.12(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)):
|
||||
vite-prerender-plugin@0.5.12(vite@7.2.7(@types/node@25.0.0)(terser@5.44.1)):
|
||||
dependencies:
|
||||
kolorist: 1.8.0
|
||||
magic-string: 0.30.21
|
||||
@@ -6006,20 +6000,20 @@ snapshots:
|
||||
simple-code-frame: 1.3.0
|
||||
source-map: 0.7.6
|
||||
stack-trace: 1.0.0-pre2
|
||||
vite: 7.2.6(@types/node@24.10.1)(terser@5.44.1)
|
||||
vite: 7.2.7(@types/node@25.0.0)(terser@5.44.1)
|
||||
|
||||
vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)):
|
||||
vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.2.7(@types/node@25.0.0)(terser@5.44.1)):
|
||||
dependencies:
|
||||
debug: 4.4.3
|
||||
globrex: 0.1.2
|
||||
tsconfck: 3.1.6(typescript@5.9.3)
|
||||
optionalDependencies:
|
||||
vite: 7.2.6(@types/node@24.10.1)(terser@5.44.1)
|
||||
vite: 7.2.7(@types/node@25.0.0)(terser@5.44.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
vite@7.2.6(@types/node@24.10.1)(terser@5.44.1):
|
||||
vite@7.2.7(@types/node@25.0.0)(terser@5.44.1):
|
||||
dependencies:
|
||||
esbuild: 0.25.12
|
||||
fdir: 6.5.0(picomatch@4.0.3)
|
||||
@@ -6028,7 +6022,7 @@ snapshots:
|
||||
rollup: 4.53.3
|
||||
tinyglobby: 0.2.15
|
||||
optionalDependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 25.0.0
|
||||
fsevents: 2.3.3
|
||||
terser: 5.44.1
|
||||
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
"itty-router": "^5.0.22",
|
||||
"prettier": "^3.7.4"
|
||||
},
|
||||
"packageManager": "pnpm@10.24.0+sha512.01ff8ae71b4419903b65c60fb2dc9d34cf8bb6e06d03bde112ef38f7a34d6904c424ba66bea5cdcf12890230bf39f9580473140ed9c946fef328b6e5238a345a"
|
||||
"packageManager": "pnpm@10.25.0+sha512.5e82639027af37cf832061bcc6d639c219634488e0f2baebe785028a793de7b525ffcd3f7ff574f5e9860654e098fe852ba8ac5dd5cefe1767d23a020a92f501"
|
||||
}
|
||||
|
||||
@@ -192,6 +192,7 @@ build_src_flags =
|
||||
-std=gnu++17 -Og -ggdb
|
||||
-Wall -Wextra
|
||||
-Wno-unused-parameter -Wno-sign-compare -Wno-missing-braces
|
||||
-Wno-vla-cxx-extension -Wno-tautological-constant-out-of-range-compare
|
||||
-I./src/core
|
||||
-I./lib_standalone
|
||||
-I./lib/uuid-common/src
|
||||
|
||||
@@ -792,20 +792,15 @@ void AnalogSensor::publish_values(const bool force) {
|
||||
}
|
||||
|
||||
// see if we need to create the [devs] discovery section, as this needs only to be done once for all sensors
|
||||
bool is_ha_device_created = false;
|
||||
for (auto const & sensor : sensors_) {
|
||||
if (sensor.ha_registered) {
|
||||
is_ha_device_created = true;
|
||||
break;
|
||||
}
|
||||
if (std::none_of(sensors_.begin(), sensors_.end(), [](const auto & sensor) { return sensor.ha_registered; })) {
|
||||
Mqtt::add_ha_dev_section(config.as<JsonObject>(), "Analog Sensors", nullptr, nullptr, nullptr, false);
|
||||
}
|
||||
|
||||
// add default_entity_id
|
||||
std::string topic_str(topic);
|
||||
doc["def_ent_id"] = topic_str.substr(0, topic_str.find("/")) + "." + uniq_s;
|
||||
|
||||
Mqtt::add_ha_dev_section(config.as<JsonObject>(), "Analog Sensors", nullptr, nullptr, nullptr, false);
|
||||
Mqtt::add_ha_avail_section(config.as<JsonObject>(), stat_t, !is_ha_device_created, val_cond);
|
||||
Mqtt::add_ha_avty_section(config.as<JsonObject>(), stat_t, val_cond);
|
||||
|
||||
sensor.ha_registered = Mqtt::queue_ha(topic, config.as<JsonObject>());
|
||||
}
|
||||
|
||||
@@ -237,12 +237,20 @@ const char * Command::parse_command_string(const char * command, int8_t & id) {
|
||||
const char * cmd_org = command;
|
||||
int8_t id_org = id;
|
||||
|
||||
// convert cmd to lowercase and compare
|
||||
char * lowerCmd = strdup(command);
|
||||
for (char * p = lowerCmd; *p; p++) {
|
||||
*p = tolower(*p);
|
||||
// Optimized: Use stack buffer instead of strdup() to avoid heap allocation
|
||||
// Most command strings are short, 64 bytes is more than enough
|
||||
char lowerCmd[64];
|
||||
size_t len = strlen(command);
|
||||
if (len >= sizeof(lowerCmd)) {
|
||||
len = sizeof(lowerCmd) - 1; // truncate if too long (rare case)
|
||||
}
|
||||
|
||||
// Convert to lowercase in place using stack buffer
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
lowerCmd[i] = tolower(command[i]);
|
||||
}
|
||||
lowerCmd[len] = '\0';
|
||||
|
||||
// check prefix and valid number range, also check 'id'
|
||||
if (!strncmp(lowerCmd, "hc", 2) && command[2] >= '1' && command[2] <= '8') {
|
||||
id = command[2] - '0';
|
||||
@@ -279,7 +287,7 @@ const char * Command::parse_command_string(const char * command, int8_t & id) {
|
||||
command += 3;
|
||||
}
|
||||
|
||||
free(lowerCmd);
|
||||
// No free() needed - stack buffer is automatically cleaned up
|
||||
|
||||
// return original if no seperator
|
||||
if (command[0] != '/' && command[0] != '.') {
|
||||
|
||||
@@ -848,7 +848,7 @@ std::string EMSESP::device_tostring(const uint8_t device_id) {
|
||||
}
|
||||
}
|
||||
|
||||
// created a pretty print telegram as a text string
|
||||
// create a pretty print telegram as a text string
|
||||
// e.g. Boiler(0x08) -> Me(0x0B), Version(0x02), data: 7B 06 01 00 00 00 00 00 00 04 (offset 1)
|
||||
std::string EMSESP::pretty_telegram(std::shared_ptr<const Telegram> telegram) {
|
||||
uint8_t src = telegram->src & 0x7F;
|
||||
@@ -950,27 +950,58 @@ std::string EMSESP::pretty_telegram(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string str;
|
||||
str.reserve(200);
|
||||
// Optimized: Use stack buffer and build string once to avoid multiple temporary allocations
|
||||
char buf[250];
|
||||
if (telegram->operation == Telegram::Operation::RX_READ) {
|
||||
str = src_name + "(" + Helpers::hextoa(src) + ") R " + dest_name + "(" + Helpers::hextoa(dest) + "), " + type_name + "("
|
||||
+ Helpers::hextoa(telegram->type_id) + "), length: " + Helpers::itoa(telegram->message_data[0])
|
||||
+ ((telegram->message_length > 1) ? ", data: " + Helpers::data_to_hex(telegram->message_data + 1, telegram->message_length - 1) : "");
|
||||
auto pos = snprintf(buf,
|
||||
sizeof(buf),
|
||||
"%s(%s) R %s(%s), %s(%s), length: %d",
|
||||
src_name.c_str(),
|
||||
Helpers::hextoa(src).c_str(),
|
||||
dest_name.c_str(),
|
||||
Helpers::hextoa(dest).c_str(),
|
||||
type_name.c_str(),
|
||||
Helpers::hextoa(telegram->type_id).c_str(),
|
||||
telegram->message_data[0]);
|
||||
if (telegram->message_length > 1 && pos > 0 && pos < (int)sizeof(buf)) {
|
||||
std::string data_hex = Helpers::data_to_hex(telegram->message_data + 1, telegram->message_length - 1);
|
||||
snprintf(buf + pos, sizeof(buf) - pos, ", data: %s", data_hex.c_str());
|
||||
}
|
||||
} else if (telegram->dest == 0) {
|
||||
str = src_name + "(" + Helpers::hextoa(src) + ") B " + dest_name + "(" + Helpers::hextoa(dest) + "), " + type_name + "("
|
||||
+ Helpers::hextoa(telegram->type_id) + "), data: " + telegram->to_string_message();
|
||||
snprintf(buf,
|
||||
sizeof(buf),
|
||||
"%s(%s) B %s(%s), %s(%s), data: %s",
|
||||
src_name.c_str(),
|
||||
Helpers::hextoa(src).c_str(),
|
||||
dest_name.c_str(),
|
||||
Helpers::hextoa(dest).c_str(),
|
||||
type_name.c_str(),
|
||||
Helpers::hextoa(telegram->type_id).c_str(),
|
||||
telegram->to_string_message().c_str());
|
||||
} else {
|
||||
str = src_name + "(" + Helpers::hextoa(src) + ") W " + dest_name + "(" + Helpers::hextoa(dest) + "), " + type_name + "("
|
||||
+ Helpers::hextoa(telegram->type_id) + "), data: " + telegram->to_string_message();
|
||||
snprintf(buf,
|
||||
sizeof(buf),
|
||||
"%s(%s) W %s(%s), %s(%s), data: %s",
|
||||
src_name.c_str(),
|
||||
Helpers::hextoa(src).c_str(),
|
||||
dest_name.c_str(),
|
||||
Helpers::hextoa(dest).c_str(),
|
||||
type_name.c_str(),
|
||||
Helpers::hextoa(telegram->type_id).c_str(),
|
||||
telegram->to_string_message().c_str());
|
||||
}
|
||||
|
||||
if (offset) {
|
||||
str += " (offset " + Helpers::itoa(offset) + ")";
|
||||
size_t len = strlen(buf);
|
||||
if (len < sizeof(buf) - 20) {
|
||||
snprintf(buf + len, sizeof(buf) - len, " (offset %d)", offset);
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Type 0x07 - UBADevices - shows us the connected EMS devices
|
||||
* e.g. 08 00 07 00 0B 80 00 00 00 00 00 00 00 00 00 00 00
|
||||
|
||||
@@ -34,12 +34,19 @@ char * Helpers::hextoa(char * result, const uint8_t value) {
|
||||
}
|
||||
|
||||
// same as hextoa but uses to a hex std::string
|
||||
// Optimized: Avoid string concatenation to reduce temporary allocations
|
||||
std::string Helpers::hextoa(const uint8_t value, bool prefix) {
|
||||
char buf[3];
|
||||
if (prefix) {
|
||||
return std::string("0x") + hextoa(buf, value);
|
||||
char buf[5]; // "0x" + 2 hex chars + null
|
||||
buf[0] = '0';
|
||||
buf[1] = 'x';
|
||||
hextoa(&buf[2], value);
|
||||
return std::string(buf);
|
||||
} else {
|
||||
char buf[3];
|
||||
hextoa(buf, value);
|
||||
return std::string(buf);
|
||||
}
|
||||
return std::string(hextoa(buf, value));
|
||||
}
|
||||
|
||||
// same for 16 bit values
|
||||
@@ -53,12 +60,19 @@ char * Helpers::hextoa(char * result, const uint16_t value) {
|
||||
}
|
||||
|
||||
// same as above but to a hex string
|
||||
// Optimized: Avoid string concatenation to reduce temporary allocations
|
||||
std::string Helpers::hextoa(const uint16_t value, bool prefix) {
|
||||
char buf[5];
|
||||
if (prefix) {
|
||||
return std::string("0x") + hextoa(buf, value);
|
||||
char buf[7]; // "0x" + 4 hex chars + null
|
||||
buf[0] = '0';
|
||||
buf[1] = 'x';
|
||||
hextoa(&buf[2], value);
|
||||
return std::string(buf);
|
||||
} else {
|
||||
char buf[5];
|
||||
hextoa(buf, value);
|
||||
return std::string(buf);
|
||||
}
|
||||
return std::string(hextoa(buf, value));
|
||||
}
|
||||
|
||||
#ifdef EMSESP_STANDALONE
|
||||
@@ -100,29 +114,34 @@ char * Helpers::ultostr(char * ptr, uint32_t value, const uint8_t base) {
|
||||
|
||||
// fast itoa returning a std::string
|
||||
// http://www.strudel.org.uk/itoa/
|
||||
// Optimized: Use stack buffer to avoid heap allocation, then create string once
|
||||
std::string Helpers::itoa(int16_t value) {
|
||||
std::string buf;
|
||||
buf.reserve(25); // Pre-allocate enough space.
|
||||
int quotient = value;
|
||||
// int16_t max: -32768 to 32767 = max 6 chars + null
|
||||
char buf[8];
|
||||
char * p = buf + sizeof(buf) - 1;
|
||||
*p = '\0';
|
||||
|
||||
bool negative = value < 0;
|
||||
int32_t abs_val = negative ? -(int32_t)value : value; // cast to int32 to handle -32768
|
||||
|
||||
// Build string in reverse
|
||||
do {
|
||||
buf += "0123456789abcdef"[std::abs(quotient % 10)];
|
||||
quotient /= 10;
|
||||
} while (quotient);
|
||||
*--p = '0' + (abs_val % 10);
|
||||
abs_val /= 10;
|
||||
} while (abs_val > 0);
|
||||
|
||||
// Append the negative sign
|
||||
if (value < 0)
|
||||
buf += '-';
|
||||
if (negative) {
|
||||
*--p = '-';
|
||||
}
|
||||
|
||||
std::reverse(buf.begin(), buf.end());
|
||||
return buf;
|
||||
return std::string(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* fast itoa
|
||||
* written by Lukás Chmela, Released under GPLv3. http://www.strudel.org.uk/itoa/ version 0.4
|
||||
* optimized for ESP32
|
||||
*/
|
||||
* fast itoa
|
||||
* written by Lukás Chmela, Released under GPLv3. http://www.strudel.org.uk/itoa/ version 0.4
|
||||
* optimized for ESP32
|
||||
*/
|
||||
char * Helpers::itoa(int32_t value, char * result, const uint8_t base) {
|
||||
// check that the base if valid
|
||||
if (base < 2 || base > 36) {
|
||||
@@ -470,25 +489,26 @@ char * Helpers::utf8tolatin1(char * result, const char * c, const uint8_t len) {
|
||||
*p = '\0'; // terminate result
|
||||
return result;
|
||||
}
|
||||
|
||||
// creates string of hex values from an array of bytes
|
||||
std::string Helpers::data_to_hex(const uint8_t * data, const uint8_t length) {
|
||||
if (length == 0) {
|
||||
return "<empty>";
|
||||
}
|
||||
|
||||
std::string str;
|
||||
str.reserve(length * 3 + 1);
|
||||
std::vector<char> str(length * 3);
|
||||
memset(str.data(), 0, str.size());
|
||||
|
||||
char buffer[4];
|
||||
char buffer[4];
|
||||
char * p = str.data();
|
||||
for (uint8_t i = 0; i < length; i++) {
|
||||
str.append(Helpers::hextoa(buffer, data[i]));
|
||||
str.push_back(' ');
|
||||
Helpers::hextoa(buffer, data[i]);
|
||||
*p++ = buffer[0];
|
||||
*p++ = buffer[1];
|
||||
*p++ = ' '; // space
|
||||
}
|
||||
if (!str.empty()) {
|
||||
str.pop_back();
|
||||
}
|
||||
return str;
|
||||
*--p = '\0'; // null terminate just in case, loosing the trailing space
|
||||
|
||||
return std::string(str.data());
|
||||
}
|
||||
|
||||
// takes a hex string and convert it to an unsigned 32bit number (max 8 hex digits)
|
||||
|
||||
@@ -222,9 +222,11 @@ void Mqtt::on_message(const char * topic, const uint8_t * payload, size_t len) {
|
||||
// the payload is not terminated
|
||||
// convert payload to a null-terminated char string
|
||||
// see https://www.emelis.net/espMqttClient/#code-samples
|
||||
char message[len + 1];
|
||||
memcpy(message, payload, len);
|
||||
message[len] = '\0';
|
||||
// fix variable-length arrays (VLAs) "char message[len + 1]" as they are not standard C++; they're a Clang/GCC extension.
|
||||
std::vector<char> message_buffer(len + 1);
|
||||
memcpy(message_buffer.data(), payload, len);
|
||||
message_buffer[len] = '\0';
|
||||
char * message = message_buffer.data();
|
||||
|
||||
#if defined(EMSESP_DEBUG)
|
||||
if (len) {
|
||||
@@ -596,15 +598,17 @@ void Mqtt::ha_status() {
|
||||
// add sub or pub task to the queue.
|
||||
// the base is not included in the topic
|
||||
bool Mqtt::queue_message(const uint8_t operation, const std::string & topic, const std::string & payload, const bool retain) {
|
||||
if (!mqtt_enabled_ || topic.empty() || !connected()) {
|
||||
return false; // quit, not using MQTT
|
||||
}
|
||||
|
||||
if (topic == "response" && operation == Operation::PUBLISH) {
|
||||
lastresponse_ = payload;
|
||||
if (!send_response_) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!mqtt_enabled_ || topic.empty() || !connected()) {
|
||||
return false; // quit, not using MQTT
|
||||
}
|
||||
|
||||
// check free mem
|
||||
#ifndef EMSESP_STANDALONE
|
||||
// if (ESP.getFreeHeap() < 60 * 1024 || ESP.getMaxAllocHeap() < 40 * 1024) {
|
||||
@@ -1094,10 +1098,7 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
||||
// don't bother with value template conditions if using Domoticz which doesn't fully support MQTT Discovery
|
||||
if (discovery_type() == discoveryType::HOMEASSISTANT) {
|
||||
doc["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else " + sample_val + "}}";
|
||||
|
||||
// adds availability, dev, ids to the config section to HA Discovery config
|
||||
// except for commands
|
||||
add_ha_avail_section(doc.as<JsonObject>(), stat_t, false, val_cond);
|
||||
add_ha_avty_section(doc.as<JsonObject>(), stat_t, val_cond); // adds availability section
|
||||
} else {
|
||||
// Domoticz doesn't support value templates, so we just use the value directly
|
||||
// Also omit the uom and other state classes
|
||||
@@ -1367,8 +1368,8 @@ bool Mqtt::publish_ha_climate_config(const int8_t tag, const bool has_roomtemp,
|
||||
modes.add("heat");
|
||||
modes.add("off");
|
||||
|
||||
add_ha_dev_section(doc.as<JsonObject>(), devicename, nullptr, nullptr, nullptr, false); // add dev section
|
||||
add_ha_avail_section(doc.as<JsonObject>(), topic_t, false, seltemp_cond, has_roomtemp ? currtemp_cond : nullptr, hc_mode_cond); // add availability section
|
||||
add_ha_dev_section(doc.as<JsonObject>(), devicename, nullptr, nullptr, nullptr, false); // add dev section
|
||||
add_ha_avty_section(doc.as<JsonObject>(), topic_t, seltemp_cond, has_roomtemp ? currtemp_cond : nullptr, hc_mode_cond); // add availability section
|
||||
|
||||
return queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
}
|
||||
@@ -1434,59 +1435,59 @@ void Mqtt::add_ha_dev_section(JsonObject doc, const char * name, const char * mo
|
||||
}
|
||||
}
|
||||
|
||||
// adds sections for HA Discovery to an existing JSON doc
|
||||
// adds dev section with ids, name, mf, mdl, via_device
|
||||
// adds optional availability section
|
||||
void Mqtt::add_ha_avail_section(JsonObject doc, const char * state_t, const bool is_first, const char * cond1, const char * cond2, const char * negcond) {
|
||||
// adds avty section for HA Discovery to an existing JSON doc
|
||||
void Mqtt::add_ha_avty_section(JsonObject doc, const char * state_t, const char * cond1, const char * cond2, const char * negcond) {
|
||||
// only works for HA
|
||||
if (discovery_type() != discoveryType::HOMEASSISTANT) {
|
||||
return;
|
||||
}
|
||||
|
||||
// skip availability section if no conditions set
|
||||
if (!cond1 && !cond2 && !negcond) {
|
||||
return;
|
||||
}
|
||||
|
||||
// adds "availability" section to HA Discovery config
|
||||
JsonArray avty = doc["avty"].to<JsonArray>();
|
||||
JsonDocument avty_json;
|
||||
|
||||
// make local copy of state, as the pointer will get de-referenced
|
||||
char state[50];
|
||||
strlcpy(state, state_t, sizeof(state));
|
||||
if (state_t != nullptr) {
|
||||
// make local copy of state, as the pointer will get de-referenced
|
||||
char state[40];
|
||||
strlcpy(state, state_t, sizeof(state));
|
||||
|
||||
char tpl[150];
|
||||
const char * tpl_draft = "{{'online' if %s else 'offline'}}";
|
||||
char tpl[150];
|
||||
|
||||
// condition 1
|
||||
if (cond1 != nullptr) {
|
||||
avty_json.clear();
|
||||
avty_json["t"] = state;
|
||||
snprintf(tpl, sizeof(tpl), tpl_draft, cond1);
|
||||
avty_json["val_tpl"] = tpl;
|
||||
avty.add(avty_json); // returns 0 if no mem
|
||||
// condition 1
|
||||
if (cond1 != nullptr) {
|
||||
avty_json.clear();
|
||||
avty_json["t"] = state;
|
||||
snprintf(tpl, sizeof(tpl), "{{'online' if %s else 'offline'}}", cond1);
|
||||
avty_json["val_tpl"] = tpl;
|
||||
if (!avty.add(avty_json)) {
|
||||
LOG_WARNING("Failed to add availability condition 1 (low memory)");
|
||||
}
|
||||
}
|
||||
|
||||
// condition 2
|
||||
if (cond2 != nullptr) {
|
||||
avty_json.clear();
|
||||
avty_json["t"] = state;
|
||||
snprintf(tpl, sizeof(tpl), "{{'online' if %s else 'offline'}}", cond2);
|
||||
avty_json["val_tpl"] = tpl;
|
||||
if (!avty.add(avty_json)) {
|
||||
LOG_WARNING("Failed to add availability condition 2 (low memory)");
|
||||
}
|
||||
}
|
||||
|
||||
// negative condition
|
||||
if (negcond != nullptr) {
|
||||
avty_json.clear();
|
||||
avty_json["t"] = state;
|
||||
snprintf(tpl, sizeof(tpl), "{{'offline' if %s else 'online'}}", negcond);
|
||||
avty_json["val_tpl"] = tpl;
|
||||
if (!avty.add(avty_json)) {
|
||||
LOG_WARNING("Failed to add negative availability condition (low memory)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// condition 2
|
||||
if (cond2 != nullptr) {
|
||||
avty_json.clear();
|
||||
avty_json["t"] = state;
|
||||
snprintf(tpl, sizeof(tpl), tpl_draft, cond2);
|
||||
avty_json["val_tpl"] = tpl;
|
||||
avty.add(avty_json); // returns 0 if no mem
|
||||
}
|
||||
|
||||
// negative condition
|
||||
if (negcond != nullptr) {
|
||||
avty_json.clear();
|
||||
avty_json["t"] = state;
|
||||
snprintf(tpl, sizeof(tpl), "{{'offline' if %s else 'online'}}", negcond);
|
||||
avty_json["val_tpl"] = tpl;
|
||||
avty.add(avty_json); // returns 0 if no mem
|
||||
}
|
||||
|
||||
// add LWT (Last Will and Testament)
|
||||
// always add LWT (Last Will and Testament)
|
||||
avty_json.clear();
|
||||
avty_json["t"] = "~/status"; // as a topic
|
||||
avty.add(avty_json);
|
||||
|
||||
@@ -256,12 +256,11 @@ class Mqtt {
|
||||
static void
|
||||
add_ha_classes(JsonObject doc, const uint8_t device_type, const uint8_t type, const uint8_t uom, const char * entity = nullptr, bool is_discovery = true);
|
||||
static void add_ha_dev_section(JsonObject doc, const char * name, const char * model, const char * brand, const char * version, const bool create_model);
|
||||
static void add_ha_avail_section(JsonObject doc,
|
||||
const char * state_t,
|
||||
const bool is_first,
|
||||
const char * cond1 = nullptr,
|
||||
const char * cond2 = nullptr,
|
||||
const char * negcond = nullptr);
|
||||
static void add_ha_avty_section(JsonObject doc,
|
||||
const char * state_t = nullptr,
|
||||
const char * cond1 = nullptr,
|
||||
const char * cond2 = nullptr,
|
||||
const char * negcond = nullptr);
|
||||
static void add_ha_bool(JsonObject doc);
|
||||
static void add_value_bool(JsonObject doc, const char * name, bool value);
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ void Shower::create_ha_discovery() {
|
||||
|
||||
Mqtt::add_ha_bool(doc.as<JsonObject>());
|
||||
Mqtt::add_ha_dev_section(doc.as<JsonObject>(), "Shower Sensor", nullptr, nullptr, nullptr, false);
|
||||
Mqtt::add_ha_avail_section(doc.as<JsonObject>(), "~/shower_active", true); // no conditions
|
||||
Mqtt::add_ha_avty_section(doc.as<JsonObject>()); // no conditions
|
||||
|
||||
snprintf(topic, sizeof(topic), "binary_sensor/%s/shower_active/config", Mqtt::basename().c_str());
|
||||
ha_configdone_ = Mqtt::queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
@@ -240,7 +240,7 @@ void Shower::create_ha_discovery() {
|
||||
// doc["ent_cat"] = "diagnostic";
|
||||
|
||||
Mqtt::add_ha_dev_section(doc.as<JsonObject>(), "Shower Sensor", nullptr, nullptr, nullptr, false);
|
||||
Mqtt::add_ha_avail_section(doc.as<JsonObject>(), "~/shower_data", false, "value_json.duration is defined");
|
||||
Mqtt::add_ha_avty_section(doc.as<JsonObject>(), "~/shower_data", "value_json.duration is defined");
|
||||
|
||||
snprintf(topic, sizeof(topic), "sensor/%s/shower_duration/config", Mqtt::basename().c_str());
|
||||
Mqtt::queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
|
||||
@@ -1565,7 +1565,7 @@ void System::get_value_json(JsonObject output, const std::string & circuit, cons
|
||||
|
||||
// generate Prometheus metrics format from system values
|
||||
std::string System::get_metrics_prometheus() {
|
||||
std::string result;
|
||||
std::string result;
|
||||
std::unordered_map<std::string, bool> seen_metrics;
|
||||
|
||||
// get system data
|
||||
@@ -1633,156 +1633,155 @@ std::string System::get_metrics_prometheus() {
|
||||
};
|
||||
|
||||
// helper function to process a JSON object recursively
|
||||
std::function<void(const JsonObject &, const std::string &)> process_object =
|
||||
[&](const JsonObject & obj, const std::string & prefix) {
|
||||
std::vector<std::pair<std::string, std::string>> local_info_labels;
|
||||
bool has_nested_objects = false;
|
||||
std::function<void(const JsonObject &, const std::string &)> process_object = [&](const JsonObject & obj, const std::string & prefix) {
|
||||
std::vector<std::pair<std::string, std::string>> local_info_labels;
|
||||
bool has_nested_objects = false;
|
||||
|
||||
for (JsonPair p : obj) {
|
||||
std::string key = p.key().c_str();
|
||||
std::string path = prefix.empty() ? key : prefix + "." + key;
|
||||
std::string metric_name = prefix.empty() ? key : prefix + "_" + key;
|
||||
for (JsonPair p : obj) {
|
||||
std::string key = p.key().c_str();
|
||||
std::string path = prefix.empty() ? key : prefix + "." + key;
|
||||
std::string metric_name = prefix.empty() ? key : prefix + "_" + key;
|
||||
|
||||
if (should_ignore(prefix, key)) {
|
||||
continue;
|
||||
}
|
||||
if (should_ignore(prefix, key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p.value().is<JsonObject>()) {
|
||||
// recursive call for nested objects
|
||||
has_nested_objects = true;
|
||||
process_object(p.value().as<JsonObject>(), metric_name);
|
||||
} else if (p.value().is<JsonArray>()) {
|
||||
// handle arrays (devices)
|
||||
if (key == "devices") {
|
||||
JsonArray devices = p.value().as<JsonArray>();
|
||||
for (JsonObject device : devices) {
|
||||
std::vector<std::pair<std::string, std::string>> device_labels;
|
||||
if (p.value().is<JsonObject>()) {
|
||||
// recursive call for nested objects
|
||||
has_nested_objects = true;
|
||||
process_object(p.value().as<JsonObject>(), metric_name);
|
||||
} else if (p.value().is<JsonArray>()) {
|
||||
// handle arrays (devices)
|
||||
if (key == "devices") {
|
||||
JsonArray devices = p.value().as<JsonArray>();
|
||||
for (JsonObject device : devices) {
|
||||
std::vector<std::pair<std::string, std::string>> device_labels;
|
||||
|
||||
// collect labels from device object
|
||||
for (JsonPair dp : device) {
|
||||
std::string dkey = dp.key().c_str();
|
||||
if (dkey == "type" || dkey == "name" || dkey == "deviceID" || dkey == "brand" || dkey == "version") {
|
||||
if (dp.value().is<const char *>()) {
|
||||
std::string val = dp.value().as<const char *>();
|
||||
if (!val.empty()) {
|
||||
device_labels.push_back({to_lowercase(dkey), val});
|
||||
}
|
||||
// collect labels from device object
|
||||
for (JsonPair dp : device) {
|
||||
std::string dkey = dp.key().c_str();
|
||||
if (dkey == "type" || dkey == "name" || dkey == "deviceID" || dkey == "brand" || dkey == "version") {
|
||||
if (dp.value().is<const char *>()) {
|
||||
std::string val = dp.value().as<const char *>();
|
||||
if (!val.empty()) {
|
||||
device_labels.push_back({to_lowercase(dkey), val});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create productID metric
|
||||
if (device.containsKey("productID") && device["productID"].is<int>()) {
|
||||
std::string metric = "emsesp_device_productid";
|
||||
if (seen_metrics.find(metric) == seen_metrics.end()) {
|
||||
result += "# HELP emsesp_device_productid productID\n";
|
||||
result += "# TYPE emsesp_device_productid gauge\n";
|
||||
seen_metrics[metric] = true;
|
||||
}
|
||||
|
||||
result += metric;
|
||||
if (!device_labels.empty()) {
|
||||
result += "{";
|
||||
bool first = true;
|
||||
for (const auto & label : device_labels) {
|
||||
if (!first) {
|
||||
result += ", ";
|
||||
}
|
||||
result += label.first + "=\"" + escape_label(label.second) + "\"";
|
||||
first = false;
|
||||
}
|
||||
result += "}";
|
||||
}
|
||||
result += " " + std::to_string(device["productID"].as<int>()) + "\n";
|
||||
// create productID metric
|
||||
if (device["productID"].is<int>()) {
|
||||
std::string metric = "emsesp_device_productid";
|
||||
if (seen_metrics.find(metric) == seen_metrics.end()) {
|
||||
result += "# HELP emsesp_device_productid productID\n";
|
||||
result += "# TYPE emsesp_device_productid gauge\n";
|
||||
seen_metrics[metric] = true;
|
||||
}
|
||||
|
||||
// create entities metric
|
||||
if (device.containsKey("entities") && device["entities"].is<int>()) {
|
||||
std::string metric = "emsesp_device_entities";
|
||||
if (seen_metrics.find(metric) == seen_metrics.end()) {
|
||||
result += "# HELP emsesp_device_entities entities\n";
|
||||
result += "# TYPE emsesp_device_entities gauge\n";
|
||||
seen_metrics[metric] = true;
|
||||
}
|
||||
|
||||
result += metric;
|
||||
if (!device_labels.empty()) {
|
||||
result += "{";
|
||||
bool first = true;
|
||||
for (const auto & label : device_labels) {
|
||||
if (!first) {
|
||||
result += ", ";
|
||||
}
|
||||
result += label.first + "=\"" + escape_label(label.second) + "\"";
|
||||
first = false;
|
||||
result += metric;
|
||||
if (!device_labels.empty()) {
|
||||
result += "{";
|
||||
bool first = true;
|
||||
for (const auto & label : device_labels) {
|
||||
if (!first) {
|
||||
result += ", ";
|
||||
}
|
||||
result += "}";
|
||||
result += label.first + "=\"" + escape_label(label.second) + "\"";
|
||||
first = false;
|
||||
}
|
||||
result += " " + std::to_string(device["entities"].as<int>()) + "\n";
|
||||
result += "}";
|
||||
}
|
||||
result += " " + std::to_string(device["productID"].as<int>()) + "\n";
|
||||
}
|
||||
|
||||
// create entities metric
|
||||
if (device["entities"].is<int>()) {
|
||||
std::string metric = "emsesp_device_entities";
|
||||
if (seen_metrics.find(metric) == seen_metrics.end()) {
|
||||
result += "# HELP emsesp_device_entities entities\n";
|
||||
result += "# TYPE emsesp_device_entities gauge\n";
|
||||
seen_metrics[metric] = true;
|
||||
}
|
||||
|
||||
result += metric;
|
||||
if (!device_labels.empty()) {
|
||||
result += "{";
|
||||
bool first = true;
|
||||
for (const auto & label : device_labels) {
|
||||
if (!first) {
|
||||
result += ", ";
|
||||
}
|
||||
result += label.first + "=\"" + escape_label(label.second) + "\"";
|
||||
first = false;
|
||||
}
|
||||
result += "}";
|
||||
}
|
||||
result += " " + std::to_string(device["entities"].as<int>()) + "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// handle primitive values
|
||||
bool is_number = p.value().is<int>() || p.value().is<float>();
|
||||
bool is_bool = p.value().is<bool>();
|
||||
bool is_string = p.value().is<const char *>();
|
||||
}
|
||||
} else {
|
||||
// handle primitive values
|
||||
bool is_number = p.value().is<int>() || p.value().is<float>();
|
||||
bool is_bool = p.value().is<bool>();
|
||||
bool is_string = p.value().is<const char *>();
|
||||
|
||||
if (is_number || is_bool) {
|
||||
// add metric
|
||||
std::string full_metric_name = "emsesp_" + sanitize_name(metric_name);
|
||||
if (seen_metrics.find(full_metric_name) == seen_metrics.end()) {
|
||||
result += "# HELP emsesp_" + sanitize_name(metric_name) + " " + key + "\n";
|
||||
result += "# TYPE emsesp_" + sanitize_name(metric_name) + " gauge\n";
|
||||
seen_metrics[full_metric_name] = true;
|
||||
}
|
||||
if (is_number || is_bool) {
|
||||
// add metric
|
||||
std::string full_metric_name = "emsesp_" + sanitize_name(metric_name);
|
||||
if (seen_metrics.find(full_metric_name) == seen_metrics.end()) {
|
||||
result += "# HELP emsesp_" + sanitize_name(metric_name) + " " + key + "\n";
|
||||
result += "# TYPE emsesp_" + sanitize_name(metric_name) + " gauge\n";
|
||||
seen_metrics[full_metric_name] = true;
|
||||
}
|
||||
|
||||
result += full_metric_name + " ";
|
||||
if (is_bool) {
|
||||
result += p.value().as<bool>() ? "1" : "0";
|
||||
} else if (p.value().is<int>()) {
|
||||
result += std::to_string(p.value().as<int>());
|
||||
} else {
|
||||
char val_str[30];
|
||||
snprintf(val_str, sizeof(val_str), "%.2f", p.value().as<float>());
|
||||
result += val_str;
|
||||
}
|
||||
result += "\n";
|
||||
} else if (is_string) {
|
||||
// collect string for info metric (skip dynamic strings like uptime and timestamp)
|
||||
std::string val = p.value().as<const char *>();
|
||||
if (!val.empty() && key != "uptime" && key != "timestamp") {
|
||||
local_info_labels.push_back({to_lowercase(key), val});
|
||||
}
|
||||
result += full_metric_name + " ";
|
||||
if (is_bool) {
|
||||
result += p.value().as<bool>() ? "1" : "0";
|
||||
} else if (p.value().is<int>()) {
|
||||
result += std::to_string(p.value().as<int>());
|
||||
} else {
|
||||
char val_str[30];
|
||||
snprintf(val_str, sizeof(val_str), "%.2f", p.value().as<float>());
|
||||
result += val_str;
|
||||
}
|
||||
result += "\n";
|
||||
} else if (is_string) {
|
||||
// collect string for info metric (skip dynamic strings like uptime and timestamp)
|
||||
std::string val = p.value().as<const char *>();
|
||||
if (!val.empty() && key != "uptime" && key != "timestamp") {
|
||||
local_info_labels.push_back({to_lowercase(key), val});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create _info metric for this object level if we have labels and this is a leaf node (no nested objects)
|
||||
if (!local_info_labels.empty() && !prefix.empty() && !has_nested_objects) {
|
||||
std::string info_metric = "emsesp_" + sanitize_name(prefix) + "_info";
|
||||
if (seen_metrics.find(info_metric) == seen_metrics.end()) {
|
||||
result += "# HELP " + info_metric + " info\n";
|
||||
result += "# TYPE " + info_metric + " gauge\n";
|
||||
seen_metrics[info_metric] = true;
|
||||
}
|
||||
|
||||
result += info_metric;
|
||||
if (!local_info_labels.empty()) {
|
||||
result += "{";
|
||||
bool first = true;
|
||||
for (const auto & label : local_info_labels) {
|
||||
if (!first) {
|
||||
result += ", ";
|
||||
}
|
||||
result += label.first + "=\"" + escape_label(label.second) + "\"";
|
||||
first = false;
|
||||
}
|
||||
result += "}";
|
||||
}
|
||||
result += " 1\n";
|
||||
// create _info metric for this object level if we have labels and this is a leaf node (no nested objects)
|
||||
if (!local_info_labels.empty() && !prefix.empty() && !has_nested_objects) {
|
||||
std::string info_metric = "emsesp_" + sanitize_name(prefix) + "_info";
|
||||
if (seen_metrics.find(info_metric) == seen_metrics.end()) {
|
||||
result += "# HELP " + info_metric + " info\n";
|
||||
result += "# TYPE " + info_metric + " gauge\n";
|
||||
seen_metrics[info_metric] = true;
|
||||
}
|
||||
};
|
||||
|
||||
result += info_metric;
|
||||
if (!local_info_labels.empty()) {
|
||||
result += "{";
|
||||
bool first = true;
|
||||
for (const auto & label : local_info_labels) {
|
||||
if (!first) {
|
||||
result += ", ";
|
||||
}
|
||||
result += label.first + "=\"" + escape_label(label.second) + "\"";
|
||||
first = false;
|
||||
}
|
||||
result += "}";
|
||||
}
|
||||
result += " 1\n";
|
||||
}
|
||||
};
|
||||
|
||||
// process root object
|
||||
process_object(root, "");
|
||||
|
||||
@@ -336,7 +336,7 @@ bool TemperatureSensor::update(const char * id, const char * name, int16_t offse
|
||||
sensor.set_is_system(is_system);
|
||||
|
||||
// store the new name and offset in our configuration
|
||||
EMSESP::webCustomizationService.update([&id, &name, &offset, &sensor, &hide, &is_system](WebCustomization & settings) {
|
||||
EMSESP::webCustomizationService.update([&id, &name, &offset, &sensor, &is_system](WebCustomization & settings) {
|
||||
// look it up to see if it exists
|
||||
bool found = false;
|
||||
for (auto & SensorCustomization : settings.sensorCustomizations) {
|
||||
@@ -544,16 +544,11 @@ void TemperatureSensor::publish_values(const bool force) {
|
||||
config["name"] = sensor.name();
|
||||
|
||||
// see if we need to create the [devs] discovery section, as this needs only to be done once for all sensors
|
||||
bool is_ha_device_created = false;
|
||||
for (const auto & sensor : sensors_) {
|
||||
if (sensor.ha_registered) {
|
||||
is_ha_device_created = true;
|
||||
break;
|
||||
}
|
||||
if (std::none_of(sensors_.begin(), sensors_.end(), [](const auto & sensor) { return sensor.ha_registered; })) {
|
||||
Mqtt::add_ha_dev_section(config.as<JsonObject>(), "Temperature Sensors", nullptr, nullptr, nullptr, false);
|
||||
}
|
||||
|
||||
Mqtt::add_ha_dev_section(config.as<JsonObject>(), "Temperature Sensors", nullptr, nullptr, nullptr, false);
|
||||
Mqtt::add_ha_avail_section(config.as<JsonObject>(), stat_t, !is_ha_device_created, val_cond);
|
||||
Mqtt::add_ha_avty_section(config.as<JsonObject>(), stat_t, val_cond);
|
||||
|
||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||
snprintf(topic, sizeof(topic), "sensor/%s/%s_%s/config", Mqtt::basename().c_str(), F_(temperaturesensor), sensor.id());
|
||||
|
||||
@@ -464,8 +464,11 @@ void WebCustomEntityService::publish(const bool force) {
|
||||
config["def_ent_id"] = topic_str.substr(0, topic_str.find("/")) + "." + uniq_s;
|
||||
|
||||
Mqtt::add_ha_classes(config.as<JsonObject>(), EMSdevice::DeviceType::SYSTEM, entityItem.value_type, entityItem.uom);
|
||||
Mqtt::add_ha_dev_section(config.as<JsonObject>(), "Custom Entities", nullptr, nullptr, nullptr, false);
|
||||
Mqtt::add_ha_avail_section(config.as<JsonObject>(), stat_t, !ha_created, val_cond);
|
||||
|
||||
if (!ha_created) {
|
||||
Mqtt::add_ha_dev_section(config.as<JsonObject>(), "Custom Entities", nullptr, nullptr, nullptr, false);
|
||||
}
|
||||
Mqtt::add_ha_avty_section(config.as<JsonObject>(), stat_t, val_cond);
|
||||
|
||||
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());
|
||||
}
|
||||
@@ -700,13 +703,13 @@ void WebCustomEntityService::load_test_data() {
|
||||
auto entityItem = CustomEntityItem();
|
||||
|
||||
// test 1
|
||||
entityItem.id = 1;
|
||||
entityItem.ram = 0;
|
||||
entityItem.device_id = 8;
|
||||
entityItem.type_id = 24;
|
||||
entityItem.offset = 0;
|
||||
entityItem.factor = 1;
|
||||
strcpy(entityItem.name,"test_custom");
|
||||
entityItem.id = 1;
|
||||
entityItem.ram = 0;
|
||||
entityItem.device_id = 8;
|
||||
entityItem.type_id = 24;
|
||||
entityItem.offset = 0;
|
||||
entityItem.factor = 1;
|
||||
strcpy(entityItem.name, "test_custom");
|
||||
entityItem.uom = 1;
|
||||
entityItem.value_type = 1;
|
||||
entityItem.writeable = true;
|
||||
@@ -723,12 +726,12 @@ void WebCustomEntityService::load_test_data() {
|
||||
CommandFlag::ADMIN_ONLY);
|
||||
|
||||
// test 2
|
||||
entityItem.id = 2;
|
||||
entityItem.ram = 0;
|
||||
entityItem.device_id = 24;
|
||||
entityItem.type_id = 677;
|
||||
entityItem.offset = 3;
|
||||
entityItem.factor = 1;
|
||||
entityItem.id = 2;
|
||||
entityItem.ram = 0;
|
||||
entityItem.device_id = 24;
|
||||
entityItem.type_id = 677;
|
||||
entityItem.offset = 3;
|
||||
entityItem.factor = 1;
|
||||
strcpy(entityItem.name, "test_read_only");
|
||||
entityItem.uom = 0;
|
||||
entityItem.value_type = 2;
|
||||
@@ -737,12 +740,12 @@ void WebCustomEntityService::load_test_data() {
|
||||
webCustomEntity.customEntityItems.push_back(entityItem);
|
||||
|
||||
// test 3
|
||||
entityItem.id = 3;
|
||||
entityItem.ram = 1;
|
||||
entityItem.device_id = 0;
|
||||
entityItem.type_id = 0;
|
||||
entityItem.offset = 0;
|
||||
entityItem.factor = 1;
|
||||
entityItem.id = 3;
|
||||
entityItem.ram = 1;
|
||||
entityItem.device_id = 0;
|
||||
entityItem.type_id = 0;
|
||||
entityItem.offset = 0;
|
||||
entityItem.factor = 1;
|
||||
strcpy(entityItem.name, "test_ram");
|
||||
entityItem.uom = 0;
|
||||
entityItem.value_type = 8;
|
||||
@@ -759,12 +762,12 @@ void WebCustomEntityService::load_test_data() {
|
||||
CommandFlag::ADMIN_ONLY);
|
||||
|
||||
// test 4
|
||||
entityItem.id = 4;
|
||||
entityItem.ram = 1;
|
||||
entityItem.device_id = 0;
|
||||
entityItem.type_id = 0;
|
||||
entityItem.offset = 0;
|
||||
entityItem.factor = 1;
|
||||
entityItem.id = 4;
|
||||
entityItem.ram = 1;
|
||||
entityItem.device_id = 0;
|
||||
entityItem.type_id = 0;
|
||||
entityItem.offset = 0;
|
||||
entityItem.factor = 1;
|
||||
strcpy(entityItem.name, "test_seltemp");
|
||||
entityItem.uom = 0;
|
||||
entityItem.value_type = 8;
|
||||
|
||||
@@ -275,8 +275,10 @@ void WebSchedulerService::publish(const bool force) {
|
||||
config["cmd_t"] = command_topic;
|
||||
|
||||
Mqtt::add_ha_bool(config.as<JsonObject>());
|
||||
Mqtt::add_ha_dev_section(config.as<JsonObject>(), F_(scheduler), nullptr, nullptr, nullptr, false);
|
||||
Mqtt::add_ha_avail_section(config.as<JsonObject>(), stat_t, !ha_created, val_cond);
|
||||
if (!ha_created) {
|
||||
Mqtt::add_ha_dev_section(config.as<JsonObject>(), F_(scheduler), nullptr, nullptr, nullptr, false);
|
||||
}
|
||||
Mqtt::add_ha_avty_section(config.as<JsonObject>(), stat_t, val_cond);
|
||||
|
||||
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ class WebSchedulerService : public StatefulService<WebScheduler> {
|
||||
bool ha_registered_ = false;
|
||||
|
||||
std::list<ScheduleItem, AllocatorPSRAM<ScheduleItem>> * scheduleItems_; // pointer to the list of schedule events
|
||||
std::list<ScheduleItem *, AllocatorPSRAM<ScheduleItem *>> cmd_changed_; // pointer to commands in list that are triggert by change
|
||||
std::list<ScheduleItem *, AllocatorPSRAM<ScheduleItem *>> cmd_changed_; // pointer to commands in list that are triggered by change
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
Reference in New Issue
Block a user