mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 00:09:51 +03:00
Merge branch 'dev' of https://github.com/proddy/EMS-ESP32 into dev
This commit is contained in:
@@ -33,6 +33,8 @@
|
|||||||
- scheduler can use web get/post for values and commands [#1806](https://github.com/emsesp/EMS-ESP32/issues/1806)
|
- scheduler can use web get/post for values and commands [#1806](https://github.com/emsesp/EMS-ESP32/issues/1806)
|
||||||
- RT800 remote emulation [#1867](https://github.com/emsesp/EMS-ESP32/issues/1867)
|
- RT800 remote emulation [#1867](https://github.com/emsesp/EMS-ESP32/issues/1867)
|
||||||
- RC310 cooling parameters [#1857](https://github.com/emsesp/EMS-ESP32/issues/1857)
|
- RC310 cooling parameters [#1857](https://github.com/emsesp/EMS-ESP32/issues/1857)
|
||||||
|
- command `api/device/entities` [#1897](https://github.com/emsesp/EMS-ESP32/issues/1897)
|
||||||
|
- switchprogmode [#1903]<https://github.com/emsesp/EMS-ESP32/discussions/1903>
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
|
|||||||
@@ -23,14 +23,14 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alova/adapter-xhr": "^1.0.6",
|
"@alova/adapter-xhr": "^1.0.6",
|
||||||
"@alova/scene-react": "^1.6.1",
|
"@alova/scene-react": "^1.6.2",
|
||||||
"@emotion/react": "^11.13.0",
|
"@emotion/react": "^11.13.0",
|
||||||
"@emotion/styled": "^11.13.0",
|
"@emotion/styled": "^11.13.0",
|
||||||
"@mui/icons-material": "^5.16.5",
|
"@mui/icons-material": "^5.16.6",
|
||||||
"@mui/material": "^5.16.5",
|
"@mui/material": "^5.16.6",
|
||||||
"@table-library/react-table-library": "4.1.7",
|
"@table-library/react-table-library": "4.1.7",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^20.14.12",
|
"@types/node": "^22.0.2",
|
||||||
"@types/react": "^18.3.3",
|
"@types/react": "^18.3.3",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
@@ -44,13 +44,13 @@
|
|||||||
"react-dom": "latest",
|
"react-dom": "latest",
|
||||||
"react-dropzone": "^14.2.3",
|
"react-dropzone": "^14.2.3",
|
||||||
"react-icons": "^5.2.1",
|
"react-icons": "^5.2.1",
|
||||||
"react-router-dom": "^6.25.1",
|
"react-router-dom": "^6.26.0",
|
||||||
"react-toastify": "^10.0.5",
|
"react-toastify": "^10.0.5",
|
||||||
"typesafe-i18n": "^5.26.2",
|
"typesafe-i18n": "^5.26.2",
|
||||||
"typescript": "^5.5.4"
|
"typescript": "^5.5.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.24.9",
|
"@babel/core": "^7.25.2",
|
||||||
"@eslint/js": "^9.8.0",
|
"@eslint/js": "^9.8.0",
|
||||||
"@preact/compat": "^17.1.2",
|
"@preact/compat": "^17.1.2",
|
||||||
"@preact/preset-vite": "^2.9.0",
|
"@preact/preset-vite": "^2.9.0",
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"rollup-plugin-visualizer": "^5.12.0",
|
"rollup-plugin-visualizer": "^5.12.0",
|
||||||
"terser": "^5.31.3",
|
"terser": "^5.31.3",
|
||||||
"typescript-eslint": "8.0.0-alpha.10",
|
"typescript-eslint": "8.0.0",
|
||||||
"vite": "^5.3.5",
|
"vite": "^5.3.5",
|
||||||
"vite-plugin-imagemin": "^0.6.1",
|
"vite-plugin-imagemin": "^0.6.1",
|
||||||
"vite-tsconfig-paths": "^4.3.2"
|
"vite-tsconfig-paths": "^4.3.2"
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@alova/scene-react@npm:^1.6.1":
|
"@alova/scene-react@npm:^1.6.2":
|
||||||
version: 1.6.1
|
version: 1.6.2
|
||||||
resolution: "@alova/scene-react@npm:1.6.1"
|
resolution: "@alova/scene-react@npm:1.6.2"
|
||||||
checksum: 10c0/aa9503da4872ba6c78bc48fd60c643ae62d31845e806f840f4eb59400d25a7735f26e7f8e2debf4485dd0bd1bb63ffc48bbb504d617f45fa4c3cff0681dad135
|
checksum: 10c0/dac01605df824e66dba92c5d7073e33f98ad47367a7180bd0ddc78c01f1e672ac665c1ff0445df7299be1426ca92e325cf0b9fa459984125d6391e9e9eb9d439
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -56,10 +56,10 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@babel/compat-data@npm:^7.24.8":
|
"@babel/compat-data@npm:^7.25.2":
|
||||||
version: 7.24.8
|
version: 7.25.2
|
||||||
resolution: "@babel/compat-data@npm:7.24.8"
|
resolution: "@babel/compat-data@npm:7.25.2"
|
||||||
checksum: 10c0/7f465e9d8e44c5b516eeb3001362a3cd9a6df51dd90d3ac9868e1e7fa631ac57fc781cec6700110d4f555ba37fe59c4a71927b445106fe0062e79e79ffe11091
|
checksum: 10c0/5bf1f14d6e5f0d37c19543e99209ff4a94bb97915e1ce01e5334a144aa08cd56b6e62ece8135dac77e126723d63d4d4b96fc603a12c43b88c28f4b5e070270c5
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -86,26 +86,26 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@babel/core@npm:^7.24.9":
|
"@babel/core@npm:^7.25.2":
|
||||||
version: 7.24.9
|
version: 7.25.2
|
||||||
resolution: "@babel/core@npm:7.24.9"
|
resolution: "@babel/core@npm:7.25.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@ampproject/remapping": "npm:^2.2.0"
|
"@ampproject/remapping": "npm:^2.2.0"
|
||||||
"@babel/code-frame": "npm:^7.24.7"
|
"@babel/code-frame": "npm:^7.24.7"
|
||||||
"@babel/generator": "npm:^7.24.9"
|
"@babel/generator": "npm:^7.25.0"
|
||||||
"@babel/helper-compilation-targets": "npm:^7.24.8"
|
"@babel/helper-compilation-targets": "npm:^7.25.2"
|
||||||
"@babel/helper-module-transforms": "npm:^7.24.9"
|
"@babel/helper-module-transforms": "npm:^7.25.2"
|
||||||
"@babel/helpers": "npm:^7.24.8"
|
"@babel/helpers": "npm:^7.25.0"
|
||||||
"@babel/parser": "npm:^7.24.8"
|
"@babel/parser": "npm:^7.25.0"
|
||||||
"@babel/template": "npm:^7.24.7"
|
"@babel/template": "npm:^7.25.0"
|
||||||
"@babel/traverse": "npm:^7.24.8"
|
"@babel/traverse": "npm:^7.25.2"
|
||||||
"@babel/types": "npm:^7.24.9"
|
"@babel/types": "npm:^7.25.2"
|
||||||
convert-source-map: "npm:^2.0.0"
|
convert-source-map: "npm:^2.0.0"
|
||||||
debug: "npm:^4.1.0"
|
debug: "npm:^4.1.0"
|
||||||
gensync: "npm:^1.0.0-beta.2"
|
gensync: "npm:^1.0.0-beta.2"
|
||||||
json5: "npm:^2.2.3"
|
json5: "npm:^2.2.3"
|
||||||
semver: "npm:^6.3.1"
|
semver: "npm:^6.3.1"
|
||||||
checksum: 10c0/e104ec6efbf099f55184933e9ab078eb5821c792ddfef3e9c6561986ec4ff103f5c11e3d7d6e5e8929e50e2c58db1cc80e5b6f14b530335b6622095ec4b4124c
|
checksum: 10c0/a425fa40e73cb72b6464063a57c478bc2de9dbcc19c280f1b55a3d88b35d572e87e8594e7d7b4880331addb6faef641bbeb701b91b41b8806cd4deae5d74f401
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -144,27 +144,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@babel/generator@npm:^7.24.8":
|
"@babel/generator@npm:^7.25.0":
|
||||||
version: 7.24.8
|
version: 7.25.0
|
||||||
resolution: "@babel/generator@npm:7.24.8"
|
resolution: "@babel/generator@npm:7.25.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types": "npm:^7.24.8"
|
"@babel/types": "npm:^7.25.0"
|
||||||
"@jridgewell/gen-mapping": "npm:^0.3.5"
|
"@jridgewell/gen-mapping": "npm:^0.3.5"
|
||||||
"@jridgewell/trace-mapping": "npm:^0.3.25"
|
"@jridgewell/trace-mapping": "npm:^0.3.25"
|
||||||
jsesc: "npm:^2.5.1"
|
jsesc: "npm:^2.5.1"
|
||||||
checksum: 10c0/e8a278e75a895f13a7b17dd79abe1e894fe82a5ed3abb127c33c14c66773d69993762521c094c6c364723f8f7375683b0d4a96097781175a29407baedf67b769
|
checksum: 10c0/d0e2dfcdc8bdbb5dded34b705ceebf2e0bc1b06795a1530e64fb6a3ccf313c189db7f60c1616effae48114e1a25adc75855bc4496f3779a396b3377bae718ce7
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@babel/generator@npm:^7.24.9":
|
|
||||||
version: 7.24.9
|
|
||||||
resolution: "@babel/generator@npm:7.24.9"
|
|
||||||
dependencies:
|
|
||||||
"@babel/types": "npm:^7.24.9"
|
|
||||||
"@jridgewell/gen-mapping": "npm:^0.3.5"
|
|
||||||
"@jridgewell/trace-mapping": "npm:^0.3.25"
|
|
||||||
jsesc: "npm:^2.5.1"
|
|
||||||
checksum: 10c0/cd1f7edce7717462546c349e15289d1267a3ed627c6f6583fbf51e78eacacc6500ec2f0024f08f1cc7138989e575635b931acf4549f9e728017a22176a9ea6b6
|
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -190,16 +178,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@babel/helper-compilation-targets@npm:^7.24.8":
|
"@babel/helper-compilation-targets@npm:^7.25.2":
|
||||||
version: 7.24.8
|
version: 7.25.2
|
||||||
resolution: "@babel/helper-compilation-targets@npm:7.24.8"
|
resolution: "@babel/helper-compilation-targets@npm:7.25.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/compat-data": "npm:^7.24.8"
|
"@babel/compat-data": "npm:^7.25.2"
|
||||||
"@babel/helper-validator-option": "npm:^7.24.8"
|
"@babel/helper-validator-option": "npm:^7.24.8"
|
||||||
browserslist: "npm:^4.23.1"
|
browserslist: "npm:^4.23.1"
|
||||||
lru-cache: "npm:^5.1.1"
|
lru-cache: "npm:^5.1.1"
|
||||||
semver: "npm:^6.3.1"
|
semver: "npm:^6.3.1"
|
||||||
checksum: 10c0/2885c44ef6aaf82b7e4352b30089bb09fbe08ed5ec24eb452c2bdc3c021e2a65ab412f74b3d67ec1398da0356c730b33a2ceca1d67d34c85080d31ca6efa9aec
|
checksum: 10c0/de10e986b5322c9f807350467dc845ec59df9e596a5926a3b5edbb4710d8e3b8009d4396690e70b88c3844fe8ec4042d61436dd4b92d1f5f75655cf43ab07e99
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -291,18 +279,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@babel/helper-module-transforms@npm:^7.24.9":
|
"@babel/helper-module-transforms@npm:^7.25.2":
|
||||||
version: 7.24.9
|
version: 7.25.2
|
||||||
resolution: "@babel/helper-module-transforms@npm:7.24.9"
|
resolution: "@babel/helper-module-transforms@npm:7.25.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-environment-visitor": "npm:^7.24.7"
|
|
||||||
"@babel/helper-module-imports": "npm:^7.24.7"
|
"@babel/helper-module-imports": "npm:^7.24.7"
|
||||||
"@babel/helper-simple-access": "npm:^7.24.7"
|
"@babel/helper-simple-access": "npm:^7.24.7"
|
||||||
"@babel/helper-split-export-declaration": "npm:^7.24.7"
|
|
||||||
"@babel/helper-validator-identifier": "npm:^7.24.7"
|
"@babel/helper-validator-identifier": "npm:^7.24.7"
|
||||||
|
"@babel/traverse": "npm:^7.25.2"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
"@babel/core": ^7.0.0
|
"@babel/core": ^7.0.0
|
||||||
checksum: 10c0/e27bca43bc113731ee4f2b33a4c5bf9c7eebf4d64487b814c305cbd5feb272c29fcd3d79634ba03131ade171e5972bc7ede8dbc83ba0deb02f1e62d318c87770
|
checksum: 10c0/adaa15970ace0aee5934b5a633789b5795b6229c6a9cf3e09a7e80aa33e478675eee807006a862aa9aa517935d81f88a6db8a9f5936e3a2a40ec75f8062bc329
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -410,13 +397,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@babel/helpers@npm:^7.24.8":
|
"@babel/helpers@npm:^7.25.0":
|
||||||
version: 7.24.8
|
version: 7.25.0
|
||||||
resolution: "@babel/helpers@npm:7.24.8"
|
resolution: "@babel/helpers@npm:7.25.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/template": "npm:^7.24.7"
|
"@babel/template": "npm:^7.25.0"
|
||||||
"@babel/types": "npm:^7.24.8"
|
"@babel/types": "npm:^7.25.0"
|
||||||
checksum: 10c0/42b8939b0a0bf72d6df9721973eb0fd7cd48f42641c5c9c740916397faa586255c06d36c6e6a7e091860723096281c620f6ffaee0011a3bb254a6f5475d89a12
|
checksum: 10c0/b7fe007fc4194268abf70aa3810365085e290e6528dcb9fbbf7a765d43c74b6369ce0f99c5ccd2d44c413853099daa449c9a0123f0b212ac8d18643f2e8174b8
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -462,12 +449,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@babel/parser@npm:^7.24.8":
|
"@babel/parser@npm:^7.25.0, @babel/parser@npm:^7.25.3":
|
||||||
version: 7.24.8
|
version: 7.25.3
|
||||||
resolution: "@babel/parser@npm:7.24.8"
|
resolution: "@babel/parser@npm:7.25.3"
|
||||||
|
dependencies:
|
||||||
|
"@babel/types": "npm:^7.25.2"
|
||||||
bin:
|
bin:
|
||||||
parser: ./bin/babel-parser.js
|
parser: ./bin/babel-parser.js
|
||||||
checksum: 10c0/ce69671de8fa6f649abf849be262707ac700b573b8b1ce1893c66cc6cd76aeb1294a19e8c290b0eadeb2f47d3f413a2e57a281804ffbe76bfb9fa50194cf3c52
|
checksum: 10c0/874b01349aedb805d6694f867a752fdc7469778fad76aca4548d2cc6ce96087c3ba5fb917a6f8d05d2d1a74aae309b5f50f1a4dba035f5a2c9fcfe6e106d2c4e
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -539,6 +528,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@babel/template@npm:^7.25.0":
|
||||||
|
version: 7.25.0
|
||||||
|
resolution: "@babel/template@npm:7.25.0"
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame": "npm:^7.24.7"
|
||||||
|
"@babel/parser": "npm:^7.25.0"
|
||||||
|
"@babel/types": "npm:^7.25.0"
|
||||||
|
checksum: 10c0/4e31afd873215744c016e02b04f43b9fa23205d6d0766fb2e93eb4091c60c1b88897936adb895fb04e3c23de98dfdcbe31bc98daaa1a4e0133f78bb948e1209b
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@babel/traverse@npm:7.23.2":
|
"@babel/traverse@npm:7.23.2":
|
||||||
version: 7.23.2
|
version: 7.23.2
|
||||||
resolution: "@babel/traverse@npm:7.23.2"
|
resolution: "@babel/traverse@npm:7.23.2"
|
||||||
@@ -593,21 +593,18 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@babel/traverse@npm:^7.24.8":
|
"@babel/traverse@npm:^7.25.2":
|
||||||
version: 7.24.8
|
version: 7.25.3
|
||||||
resolution: "@babel/traverse@npm:7.24.8"
|
resolution: "@babel/traverse@npm:7.25.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame": "npm:^7.24.7"
|
"@babel/code-frame": "npm:^7.24.7"
|
||||||
"@babel/generator": "npm:^7.24.8"
|
"@babel/generator": "npm:^7.25.0"
|
||||||
"@babel/helper-environment-visitor": "npm:^7.24.7"
|
"@babel/parser": "npm:^7.25.3"
|
||||||
"@babel/helper-function-name": "npm:^7.24.7"
|
"@babel/template": "npm:^7.25.0"
|
||||||
"@babel/helper-hoist-variables": "npm:^7.24.7"
|
"@babel/types": "npm:^7.25.2"
|
||||||
"@babel/helper-split-export-declaration": "npm:^7.24.7"
|
|
||||||
"@babel/parser": "npm:^7.24.8"
|
|
||||||
"@babel/types": "npm:^7.24.8"
|
|
||||||
debug: "npm:^4.3.1"
|
debug: "npm:^4.3.1"
|
||||||
globals: "npm:^11.1.0"
|
globals: "npm:^11.1.0"
|
||||||
checksum: 10c0/67a5cc35824455cdb54fb9e196a44b3186283e29018a9c2331f51763921e18e891b3c60c283615a27540ec8eb4c8b89f41c237b91f732a7aa518b2eb7a0d434d
|
checksum: 10c0/4c8a1966fa90b53a783a4afd2fcdaa6ab1a912e6621dca9fcc6633e80ccb9491620e88caf73b537da4e16cefd537b548c87d7087868d5b0066414dea375c0e9b
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -643,25 +640,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@babel/types@npm:^7.24.8":
|
"@babel/types@npm:^7.25.0, @babel/types@npm:^7.25.2":
|
||||||
version: 7.24.8
|
version: 7.25.2
|
||||||
resolution: "@babel/types@npm:7.24.8"
|
resolution: "@babel/types@npm:7.25.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-string-parser": "npm:^7.24.8"
|
"@babel/helper-string-parser": "npm:^7.24.8"
|
||||||
"@babel/helper-validator-identifier": "npm:^7.24.7"
|
"@babel/helper-validator-identifier": "npm:^7.24.7"
|
||||||
to-fast-properties: "npm:^2.0.0"
|
to-fast-properties: "npm:^2.0.0"
|
||||||
checksum: 10c0/2d7bf561ae993e794cb052c5a81d3a6d1877da13e1e2eb2a59ae75a8fb1c965b618fb3e4abd42548f5f9a4587d3a149185a32d6c4c4ea82195da7dd86f2da0f1
|
checksum: 10c0/e489435856be239f8cc1120c90a197e4c2865385121908e5edb7223cfdff3768cba18f489adfe0c26955d9e7bbb1fb10625bc2517505908ceb0af848989bd864
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@babel/types@npm:^7.24.9":
|
|
||||||
version: 7.24.9
|
|
||||||
resolution: "@babel/types@npm:7.24.9"
|
|
||||||
dependencies:
|
|
||||||
"@babel/helper-string-parser": "npm:^7.24.8"
|
|
||||||
"@babel/helper-validator-identifier": "npm:^7.24.7"
|
|
||||||
to-fast-properties: "npm:^2.0.0"
|
|
||||||
checksum: 10c0/4970b3481cab39c5c3fdb7c28c834df5c7049f3c7f43baeafe121bb05270ebf0da7c65b097abf314877f213baa591109c82204f30d66cdd46c22ece4a2f32415
|
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -1187,16 +1173,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@mui/core-downloads-tracker@npm:^5.16.5":
|
"@mui/core-downloads-tracker@npm:^5.16.6":
|
||||||
version: 5.16.5
|
version: 5.16.6
|
||||||
resolution: "@mui/core-downloads-tracker@npm:5.16.5"
|
resolution: "@mui/core-downloads-tracker@npm:5.16.6"
|
||||||
checksum: 10c0/f8052e42e0694b4c95b0edf1893325417ac76fbe9b7714ddad56f607f251d5edbdecf3e7ae34b28ecd7e6d9eee4d3f958d3ff743db98cb35d4e69eef30dd0e23
|
checksum: 10c0/ee7655eda56e8eeb18ae600b24182c10caab4468d33179de3e76a783a827be9577afe114750835f7c9c7f555c0de0845c0500e91ed2e669b16399a1ffe41c33d
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@mui/icons-material@npm:^5.16.5":
|
"@mui/icons-material@npm:^5.16.6":
|
||||||
version: 5.16.5
|
version: 5.16.6
|
||||||
resolution: "@mui/icons-material@npm:5.16.5"
|
resolution: "@mui/icons-material@npm:5.16.6"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime": "npm:^7.23.9"
|
"@babel/runtime": "npm:^7.23.9"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -1206,19 +1192,19 @@ __metadata:
|
|||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
"@types/react":
|
"@types/react":
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/6ba9cbb5bc7a5d3fbc297683973c7c15c4a95f8b12cf55cadd069d4ecbaf5639bb9044da82ddc029c04203ee81a8ac691ea5ada769dc86fef3f25a13fcec44fe
|
checksum: 10c0/9d24d95e8b4606b5fa2a2e40319255e2e6da52845db50d2d3ca6fd526102be3c498ec1aa9be8d33aad52cf531749b15d490abca5f23af92afc86cf45dc62ce24
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@mui/material@npm:^5.16.5":
|
"@mui/material@npm:^5.16.6":
|
||||||
version: 5.16.5
|
version: 5.16.6
|
||||||
resolution: "@mui/material@npm:5.16.5"
|
resolution: "@mui/material@npm:5.16.6"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime": "npm:^7.23.9"
|
"@babel/runtime": "npm:^7.23.9"
|
||||||
"@mui/core-downloads-tracker": "npm:^5.16.5"
|
"@mui/core-downloads-tracker": "npm:^5.16.6"
|
||||||
"@mui/system": "npm:^5.16.5"
|
"@mui/system": "npm:^5.16.6"
|
||||||
"@mui/types": "npm:^7.2.15"
|
"@mui/types": "npm:^7.2.15"
|
||||||
"@mui/utils": "npm:^5.16.5"
|
"@mui/utils": "npm:^5.16.6"
|
||||||
"@popperjs/core": "npm:^2.11.8"
|
"@popperjs/core": "npm:^2.11.8"
|
||||||
"@types/react-transition-group": "npm:^4.4.10"
|
"@types/react-transition-group": "npm:^4.4.10"
|
||||||
clsx: "npm:^2.1.0"
|
clsx: "npm:^2.1.0"
|
||||||
@@ -1239,16 +1225,16 @@ __metadata:
|
|||||||
optional: true
|
optional: true
|
||||||
"@types/react":
|
"@types/react":
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/d147f4c0b8b7cb640da2c4e2511bb8a8dd4152caaf49dc4f380dc37bac4960722b30e7fc310f3339e34a560a3c873f764cac6c37295407ca1f771d4e0854febb
|
checksum: 10c0/52cbffd87a36b9f8e16ba59030e89501e680ddea4d3dcf3db5d8fb7b86205444b00162e656c79571824a74769f879f39df2e7671d1e7ca8bc23602a7bf588dc5
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@mui/private-theming@npm:^5.16.5":
|
"@mui/private-theming@npm:^5.16.6":
|
||||||
version: 5.16.5
|
version: 5.16.6
|
||||||
resolution: "@mui/private-theming@npm:5.16.5"
|
resolution: "@mui/private-theming@npm:5.16.6"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime": "npm:^7.23.9"
|
"@babel/runtime": "npm:^7.23.9"
|
||||||
"@mui/utils": "npm:^5.16.5"
|
"@mui/utils": "npm:^5.16.6"
|
||||||
prop-types: "npm:^15.8.1"
|
prop-types: "npm:^15.8.1"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
"@types/react": ^17.0.0 || ^18.0.0
|
"@types/react": ^17.0.0 || ^18.0.0
|
||||||
@@ -1256,13 +1242,13 @@ __metadata:
|
|||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
"@types/react":
|
"@types/react":
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/4850ff47b5a4b1b19356fbd30ed675db6f688eda02bebf16d8b23bebc67bd55baaf4fdba1acae7d5b5e6bbdc2ac0f01c1c85005886b1ba098df65a9b26d4d4c7
|
checksum: 10c0/0a09afd6c2be37197973a856049f97e2f17f3e5e6cf6387af036055342efbfcd7d7066dcad587886f25f491e5940e4e9bb7d732d5099eb85b53b84ef120e9555
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@mui/styled-engine@npm:^5.16.4":
|
"@mui/styled-engine@npm:^5.16.6":
|
||||||
version: 5.16.4
|
version: 5.16.6
|
||||||
resolution: "@mui/styled-engine@npm:5.16.4"
|
resolution: "@mui/styled-engine@npm:5.16.6"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime": "npm:^7.23.9"
|
"@babel/runtime": "npm:^7.23.9"
|
||||||
"@emotion/cache": "npm:^11.11.0"
|
"@emotion/cache": "npm:^11.11.0"
|
||||||
@@ -1277,19 +1263,19 @@ __metadata:
|
|||||||
optional: true
|
optional: true
|
||||||
"@emotion/styled":
|
"@emotion/styled":
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/5dbd656aedfbf308dbbbb651a589c12b85ba1af2b6b351a657ee5af1210eab9629cee0781b2dc33b14b0a9482f7a6fa6e8b695d94f7cc5f1f7df7efe88034372
|
checksum: 10c0/b15e653c8756059c8ae2891ca54900573e22f6ed1aaf65a389ec838f2aca3252aeeb9a79aec4a43f080152b161a416e60b31a62595ba86ad5f72eda5642caaf2
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@mui/system@npm:^5.16.5":
|
"@mui/system@npm:^5.16.6":
|
||||||
version: 5.16.5
|
version: 5.16.6
|
||||||
resolution: "@mui/system@npm:5.16.5"
|
resolution: "@mui/system@npm:5.16.6"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime": "npm:^7.23.9"
|
"@babel/runtime": "npm:^7.23.9"
|
||||||
"@mui/private-theming": "npm:^5.16.5"
|
"@mui/private-theming": "npm:^5.16.6"
|
||||||
"@mui/styled-engine": "npm:^5.16.4"
|
"@mui/styled-engine": "npm:^5.16.6"
|
||||||
"@mui/types": "npm:^7.2.15"
|
"@mui/types": "npm:^7.2.15"
|
||||||
"@mui/utils": "npm:^5.16.5"
|
"@mui/utils": "npm:^5.16.6"
|
||||||
clsx: "npm:^2.1.0"
|
clsx: "npm:^2.1.0"
|
||||||
csstype: "npm:^3.1.3"
|
csstype: "npm:^3.1.3"
|
||||||
prop-types: "npm:^15.8.1"
|
prop-types: "npm:^15.8.1"
|
||||||
@@ -1305,7 +1291,7 @@ __metadata:
|
|||||||
optional: true
|
optional: true
|
||||||
"@types/react":
|
"@types/react":
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/af3eccfa96e78e00a8b5a71c025b57baeb85b02adb44a7e1e96779ddcb3f0070d9880dcb6b8a7bdb78339fa1bbf892b63ef80b81d0497c9bbd45f5ea14958c91
|
checksum: 10c0/493900594f51d1fc84994042e5cfa000b2d7664f86c8c0d62b87dbbb51cf7e789a700512f98e18c82e605beab38c20d0714ec25c46e2f6a5024f79f16db743f7
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -1321,9 +1307,9 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@mui/utils@npm:^5.16.5":
|
"@mui/utils@npm:^5.16.6":
|
||||||
version: 5.16.5
|
version: 5.16.6
|
||||||
resolution: "@mui/utils@npm:5.16.5"
|
resolution: "@mui/utils@npm:5.16.6"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime": "npm:^7.23.9"
|
"@babel/runtime": "npm:^7.23.9"
|
||||||
"@mui/types": "npm:^7.2.15"
|
"@mui/types": "npm:^7.2.15"
|
||||||
@@ -1337,7 +1323,7 @@ __metadata:
|
|||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
"@types/react":
|
"@types/react":
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/8b51190232c192db7dfd9fd33e054a789bf162d7ccfb40ee21d6b2636f07aa69d60e3f5bdc6ded1b3520fa4f93134101a5c4158772f589e56eff3a04f1a59a10
|
checksum: 10c0/2db3d11a83d7216fb8ceb459d4b30c795922c04cd8fabc26c721dd7b4f5ed5c4f3f3ace6ea70227bf3b79361bd58f13b723562cfd40255424d979ab238ab2e91
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -1476,10 +1462,10 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@remix-run/router@npm:1.18.0":
|
"@remix-run/router@npm:1.19.0":
|
||||||
version: 1.18.0
|
version: 1.19.0
|
||||||
resolution: "@remix-run/router@npm:1.18.0"
|
resolution: "@remix-run/router@npm:1.19.0"
|
||||||
checksum: 10c0/3ec7e441a0e54932a3d3bf932432094420f2c117715d80a5454bc7e55d13b91250749942aab032cd07aee191f1c1de33fede8682025bfd3a453dd207c016e140
|
checksum: 10c0/8c1503a535035f43747fea063b027aa841690c19a6bd8b6251c53d3aab4d4cae89b0bd4809dc7ab69fdbe61897f43c2683b82fc4cdc5785f9166cf2ea60e5932
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -1792,13 +1778,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@types/json-schema@npm:^7.0.15":
|
|
||||||
version: 7.0.15
|
|
||||||
resolution: "@types/json-schema@npm:7.0.15"
|
|
||||||
checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@types/keyv@npm:^3.1.1":
|
"@types/keyv@npm:^3.1.1":
|
||||||
version: 3.1.4
|
version: 3.1.4
|
||||||
resolution: "@types/keyv@npm:3.1.4"
|
resolution: "@types/keyv@npm:3.1.4"
|
||||||
@@ -1840,12 +1819,12 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@types/node@npm:^20.14.12":
|
"@types/node@npm:^22.0.2":
|
||||||
version: 20.14.12
|
version: 22.0.2
|
||||||
resolution: "@types/node@npm:20.14.12"
|
resolution: "@types/node@npm:22.0.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: "npm:~5.26.4"
|
undici-types: "npm:~6.11.1"
|
||||||
checksum: 10c0/59bc5fa11fdd23fd517f859063118f54a1ab53d3399ef63c926f8902429d7453abc0db22ef4b0a6110026b6ab81b6472fee894e1d235c24b01a0b3e10cfae0bb
|
checksum: 10c0/59ee26fb1104674b2e23981d7569ad113aa8ee23c8449af8e4312aa9352ac738c5ffd0ae4d8077db0467704a3b9ccc662048e39716cb5ad51cdb24d106c7871b
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -1931,13 +1910,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@types/semver@npm:^7.5.8":
|
|
||||||
version: 7.5.8
|
|
||||||
resolution: "@types/semver@npm:7.5.8"
|
|
||||||
checksum: 10c0/8663ff927234d1c5fcc04b33062cb2b9fcfbe0f5f351ed26c4d1e1581657deebd506b41ff7fdf89e787e3d33ce05854bc01686379b89e9c49b564c4cfa988efa
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@types/svgo@npm:2, @types/svgo@npm:^2.6.1":
|
"@types/svgo@npm:2, @types/svgo@npm:^2.6.1":
|
||||||
version: 2.6.4
|
version: 2.6.4
|
||||||
resolution: "@types/svgo@npm:2.6.4"
|
resolution: "@types/svgo@npm:2.6.4"
|
||||||
@@ -1947,87 +1919,85 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin@npm:8.0.0-alpha.10":
|
"@typescript-eslint/eslint-plugin@npm:8.0.0":
|
||||||
version: 8.0.0-alpha.10
|
version: 8.0.0
|
||||||
resolution: "@typescript-eslint/eslint-plugin@npm:8.0.0-alpha.10"
|
resolution: "@typescript-eslint/eslint-plugin@npm:8.0.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@eslint-community/regexpp": "npm:^4.10.0"
|
"@eslint-community/regexpp": "npm:^4.10.0"
|
||||||
"@typescript-eslint/scope-manager": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/scope-manager": "npm:8.0.0"
|
||||||
"@typescript-eslint/type-utils": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/type-utils": "npm:8.0.0"
|
||||||
"@typescript-eslint/utils": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/utils": "npm:8.0.0"
|
||||||
"@typescript-eslint/visitor-keys": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/visitor-keys": "npm:8.0.0"
|
||||||
debug: "npm:^4.3.4"
|
|
||||||
graphemer: "npm:^1.4.0"
|
graphemer: "npm:^1.4.0"
|
||||||
ignore: "npm:^5.3.1"
|
ignore: "npm:^5.3.1"
|
||||||
natural-compare: "npm:^1.4.0"
|
natural-compare: "npm:^1.4.0"
|
||||||
semver: "npm:^7.6.0"
|
|
||||||
ts-api-utils: "npm:^1.3.0"
|
ts-api-utils: "npm:^1.3.0"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
"@typescript-eslint/parser": ^7.0.0
|
"@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0
|
||||||
eslint: ^8.57.0 || ^9.0.0
|
eslint: ^8.57.0 || ^9.0.0
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/8fe37477435f21507e6839328666ffe858254c21ea143c8885f5d299c15e66b0f222ef428174619e307c71d74e2ed394d315de281dc73e4656eff4376f328398
|
checksum: 10c0/e98304410039bbb7104fdd8ad7a70f2fb81430c117b66d609b44d10cc8937c8a936a4e5993b0b6df5361c00df43a146e89632a37f2407ce9bed3555733c71fc2
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@typescript-eslint/parser@npm:8.0.0-alpha.10":
|
"@typescript-eslint/parser@npm:8.0.0":
|
||||||
version: 8.0.0-alpha.10
|
version: 8.0.0
|
||||||
resolution: "@typescript-eslint/parser@npm:8.0.0-alpha.10"
|
resolution: "@typescript-eslint/parser@npm:8.0.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/scope-manager": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/scope-manager": "npm:8.0.0"
|
||||||
"@typescript-eslint/types": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/types": "npm:8.0.0"
|
||||||
"@typescript-eslint/typescript-estree": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/typescript-estree": "npm:8.0.0"
|
||||||
"@typescript-eslint/visitor-keys": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/visitor-keys": "npm:8.0.0"
|
||||||
debug: "npm:^4.3.4"
|
debug: "npm:^4.3.4"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0
|
eslint: ^8.57.0 || ^9.0.0
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/38ef1acbee833f98ad9d72dea434c952d015afc407d1b67b376a6a7574d54da07e09533a1bc1143a13dcc9537b217968f57be965e235e3e87772bf814868d08c
|
checksum: 10c0/7b462bc975c8e0c0d9fbc4955186d61b73aad9d5b9392e8fa68ad4b7c631582edc05176fcbfbebee603695421225e8c5f5ee28812fa47e3060fc7854b84497d5
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@typescript-eslint/scope-manager@npm:8.0.0-alpha.10":
|
"@typescript-eslint/scope-manager@npm:8.0.0":
|
||||||
version: 8.0.0-alpha.10
|
version: 8.0.0
|
||||||
resolution: "@typescript-eslint/scope-manager@npm:8.0.0-alpha.10"
|
resolution: "@typescript-eslint/scope-manager@npm:8.0.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/types": "npm:8.0.0"
|
||||||
"@typescript-eslint/visitor-keys": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/visitor-keys": "npm:8.0.0"
|
||||||
checksum: 10c0/10420acebd84fce1b8bf57b33c53a88c15bc32a8a44e8d928ef9ede7152f8eb4ef18f62163f1b598770907c463c8a0195fe1ed339670cabc39d1e9da2b48258f
|
checksum: 10c0/d8397055f046be54302b603a59d358c74292f72af3d12ca1e652316a785400d3e2fd20d79e3e316e3278ff7f1c1ffb271f9f6a7a265b88041c5a4e8332f550a0
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@typescript-eslint/type-utils@npm:8.0.0-alpha.10":
|
"@typescript-eslint/type-utils@npm:8.0.0":
|
||||||
version: 8.0.0-alpha.10
|
version: 8.0.0
|
||||||
resolution: "@typescript-eslint/type-utils@npm:8.0.0-alpha.10"
|
resolution: "@typescript-eslint/type-utils@npm:8.0.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/typescript-estree": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/typescript-estree": "npm:8.0.0"
|
||||||
"@typescript-eslint/utils": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/utils": "npm:8.0.0"
|
||||||
debug: "npm:^4.3.4"
|
debug: "npm:^4.3.4"
|
||||||
ts-api-utils: "npm:^1.3.0"
|
ts-api-utils: "npm:^1.3.0"
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/582aad57448d0bc2f1b50586aaed0e5d9e3b2e7cdac10b59d8ad4c1f4b5e6d2a672d1c086908711a367d4a2033d020d5688e544e039cbef6515a0e7bdf33223b
|
checksum: 10c0/96ba2a58ceff420dac79a9c3c2bde15e0a56e8c47baf441a62886c9d8df3db6e9d886cd5c717c6f9a8cfceb545a511c7d452aa1537c2cd3b127bd47509e559ae
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@typescript-eslint/types@npm:8.0.0-alpha.10":
|
"@typescript-eslint/types@npm:8.0.0":
|
||||||
version: 8.0.0-alpha.10
|
version: 8.0.0
|
||||||
resolution: "@typescript-eslint/types@npm:8.0.0-alpha.10"
|
resolution: "@typescript-eslint/types@npm:8.0.0"
|
||||||
checksum: 10c0/5b9c6702c40c0299ca6c9954574383d35a16ae1cfdc9480a64bd5b238c47c58f60448dc9a5f7eeb47d2c9a7997a410a7bcbbfc33e2bb6bd5c91018ac1aaa0904
|
checksum: 10c0/c15efce96e4b80c2bef7ea4fa7f046609816ae8bc3a4e31d9d671e237520f6b96595e1330a891ec7042bc7b09fc16d265bad49fd878d5fb8be4b59b8a752e5b5
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree@npm:8.0.0-alpha.10":
|
"@typescript-eslint/typescript-estree@npm:8.0.0":
|
||||||
version: 8.0.0-alpha.10
|
version: 8.0.0
|
||||||
resolution: "@typescript-eslint/typescript-estree@npm:8.0.0-alpha.10"
|
resolution: "@typescript-eslint/typescript-estree@npm:8.0.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/types": "npm:8.0.0"
|
||||||
"@typescript-eslint/visitor-keys": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/visitor-keys": "npm:8.0.0"
|
||||||
debug: "npm:^4.3.4"
|
debug: "npm:^4.3.4"
|
||||||
globby: "npm:^11.1.0"
|
globby: "npm:^11.1.0"
|
||||||
is-glob: "npm:^4.0.3"
|
is-glob: "npm:^4.0.3"
|
||||||
@@ -2037,34 +2007,31 @@ __metadata:
|
|||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/4f5ef1929d4c2e8aa3bbe64d84f02bf13c07a39d329793017fa48b6f6ae5310cee011df15e25761020d5e810250753d071639c782a7cecad2133e6c848ce81f2
|
checksum: 10c0/a82f3eb2a66a4b2715d09f8f9547c1f0c27ea60c1d10d0777c8ce998b760dbb8ef14466fc2056220b8a236c2d2dc3ee99f482502f5c268bd40909b272bb47eb4
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@typescript-eslint/utils@npm:8.0.0-alpha.10":
|
"@typescript-eslint/utils@npm:8.0.0":
|
||||||
version: 8.0.0-alpha.10
|
version: 8.0.0
|
||||||
resolution: "@typescript-eslint/utils@npm:8.0.0-alpha.10"
|
resolution: "@typescript-eslint/utils@npm:8.0.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@eslint-community/eslint-utils": "npm:^4.4.0"
|
"@eslint-community/eslint-utils": "npm:^4.4.0"
|
||||||
"@types/json-schema": "npm:^7.0.15"
|
"@typescript-eslint/scope-manager": "npm:8.0.0"
|
||||||
"@types/semver": "npm:^7.5.8"
|
"@typescript-eslint/types": "npm:8.0.0"
|
||||||
"@typescript-eslint/scope-manager": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/typescript-estree": "npm:8.0.0"
|
||||||
"@typescript-eslint/types": "npm:8.0.0-alpha.10"
|
|
||||||
"@typescript-eslint/typescript-estree": "npm:8.0.0-alpha.10"
|
|
||||||
semver: "npm:^7.6.0"
|
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0
|
eslint: ^8.57.0 || ^9.0.0
|
||||||
checksum: 10c0/1ea9b78e616c35fc817ce6e9f42a59712d7a151d73fa39384f3e2d0217787ebf5111cd27af70905cf30fbc5151c2c8054a50a4e39677e26ce77d0b3fba0ac03a
|
checksum: 10c0/ecba01996d1aa330c640c41c1212fed2328a47768348ab6886080e0e55bc3b2041939a635a7440d47db533f0c4b21e1eb8b58535a9eaebbbe2c035906e12ba06
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@typescript-eslint/visitor-keys@npm:8.0.0-alpha.10":
|
"@typescript-eslint/visitor-keys@npm:8.0.0":
|
||||||
version: 8.0.0-alpha.10
|
version: 8.0.0
|
||||||
resolution: "@typescript-eslint/visitor-keys@npm:8.0.0-alpha.10"
|
resolution: "@typescript-eslint/visitor-keys@npm:8.0.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/types": "npm:8.0.0"
|
||||||
eslint-visitor-keys: "npm:^3.4.3"
|
eslint-visitor-keys: "npm:^3.4.3"
|
||||||
checksum: 10c0/a4ab419cb6e4050edaeaafeb8e2e0338d1851cb8bf076c8e2815b12529eb0d4d60553cadf478ddd289dbd2a89d67346fc96d620a5463d69e9359ca62fb8180a1
|
checksum: 10c0/8c59a2e971370c2b9a5727541c72d6b64fd0448ab03dd8b4274a26bddea5e1b4c560dd7856e1f48577cd333f7bbbed7a0f1849d39e2d1b48a748a3668c1a3723
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -2073,20 +2040,20 @@ __metadata:
|
|||||||
resolution: "EMS-ESP@workspace:."
|
resolution: "EMS-ESP@workspace:."
|
||||||
dependencies:
|
dependencies:
|
||||||
"@alova/adapter-xhr": "npm:^1.0.6"
|
"@alova/adapter-xhr": "npm:^1.0.6"
|
||||||
"@alova/scene-react": "npm:^1.6.1"
|
"@alova/scene-react": "npm:^1.6.2"
|
||||||
"@babel/core": "npm:^7.24.9"
|
"@babel/core": "npm:^7.25.2"
|
||||||
"@emotion/react": "npm:^11.13.0"
|
"@emotion/react": "npm:^11.13.0"
|
||||||
"@emotion/styled": "npm:^11.13.0"
|
"@emotion/styled": "npm:^11.13.0"
|
||||||
"@eslint/js": "npm:^9.8.0"
|
"@eslint/js": "npm:^9.8.0"
|
||||||
"@mui/icons-material": "npm:^5.16.5"
|
"@mui/icons-material": "npm:^5.16.6"
|
||||||
"@mui/material": "npm:^5.16.5"
|
"@mui/material": "npm:^5.16.6"
|
||||||
"@preact/compat": "npm:^17.1.2"
|
"@preact/compat": "npm:^17.1.2"
|
||||||
"@preact/preset-vite": "npm:^2.9.0"
|
"@preact/preset-vite": "npm:^2.9.0"
|
||||||
"@table-library/react-table-library": "npm:4.1.7"
|
"@table-library/react-table-library": "npm:4.1.7"
|
||||||
"@trivago/prettier-plugin-sort-imports": "npm:^4.3.0"
|
"@trivago/prettier-plugin-sort-imports": "npm:^4.3.0"
|
||||||
"@types/babel__core": "npm:^7"
|
"@types/babel__core": "npm:^7"
|
||||||
"@types/lodash-es": "npm:^4.17.12"
|
"@types/lodash-es": "npm:^4.17.12"
|
||||||
"@types/node": "npm:^20.14.12"
|
"@types/node": "npm:^22.0.2"
|
||||||
"@types/react": "npm:^18.3.3"
|
"@types/react": "npm:^18.3.3"
|
||||||
"@types/react-dom": "npm:^18.3.0"
|
"@types/react-dom": "npm:^18.3.0"
|
||||||
"@types/react-router-dom": "npm:^5.3.3"
|
"@types/react-router-dom": "npm:^5.3.3"
|
||||||
@@ -2105,13 +2072,13 @@ __metadata:
|
|||||||
react-dom: "npm:latest"
|
react-dom: "npm:latest"
|
||||||
react-dropzone: "npm:^14.2.3"
|
react-dropzone: "npm:^14.2.3"
|
||||||
react-icons: "npm:^5.2.1"
|
react-icons: "npm:^5.2.1"
|
||||||
react-router-dom: "npm:^6.25.1"
|
react-router-dom: "npm:^6.26.0"
|
||||||
react-toastify: "npm:^10.0.5"
|
react-toastify: "npm:^10.0.5"
|
||||||
rollup-plugin-visualizer: "npm:^5.12.0"
|
rollup-plugin-visualizer: "npm:^5.12.0"
|
||||||
terser: "npm:^5.31.3"
|
terser: "npm:^5.31.3"
|
||||||
typesafe-i18n: "npm:^5.26.2"
|
typesafe-i18n: "npm:^5.26.2"
|
||||||
typescript: "npm:^5.5.4"
|
typescript: "npm:^5.5.4"
|
||||||
typescript-eslint: "npm:8.0.0-alpha.10"
|
typescript-eslint: "npm:8.0.0"
|
||||||
vite: "npm:^5.3.5"
|
vite: "npm:^5.3.5"
|
||||||
vite-plugin-imagemin: "npm:^0.6.1"
|
vite-plugin-imagemin: "npm:^0.6.1"
|
||||||
vite-tsconfig-paths: "npm:^4.3.2"
|
vite-tsconfig-paths: "npm:^4.3.2"
|
||||||
@@ -6247,27 +6214,27 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"react-router-dom@npm:^6.25.1":
|
"react-router-dom@npm:^6.26.0":
|
||||||
version: 6.25.1
|
version: 6.26.0
|
||||||
resolution: "react-router-dom@npm:6.25.1"
|
resolution: "react-router-dom@npm:6.26.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@remix-run/router": "npm:1.18.0"
|
"@remix-run/router": "npm:1.19.0"
|
||||||
react-router: "npm:6.25.1"
|
react-router: "npm:6.26.0"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ">=16.8"
|
react: ">=16.8"
|
||||||
react-dom: ">=16.8"
|
react-dom: ">=16.8"
|
||||||
checksum: 10c0/15e2b5bf89a26db9a108d19a4e0e2054180bfb1f5f62662dd93ad697ee1bdc91a8041efd762d552c95e65fc06ca0cb0c1e88acdeeaf03aba37f7a29e470c7cc4
|
checksum: 10c0/f59a5b72b1dab6480f97f20fa49b601cb1366e6e1c8def7fd727ccbc4e8cf527f64f7aedd2889534de222dc86634a23e2ed108b99e5443e7b5401a4db104e611
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"react-router@npm:6.25.1":
|
"react-router@npm:6.26.0":
|
||||||
version: 6.25.1
|
version: 6.26.0
|
||||||
resolution: "react-router@npm:6.25.1"
|
resolution: "react-router@npm:6.26.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@remix-run/router": "npm:1.18.0"
|
"@remix-run/router": "npm:1.19.0"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ">=16.8"
|
react: ">=16.8"
|
||||||
checksum: 10c0/a7e824c1f6d9641beabc23111865ddd2525b3794403e07b297fc2bdd4cddec93e166aacdb9d2602768864d70f3bf490f59eeab8474a04ae1f13a832f305eeec3
|
checksum: 10c0/498b97cac077170096715609e65e0039b64e497612ed585b8d3b88733310d23e7ca76ce189b09b6fbc65ca8df1595ca20ccac05a84006803843dfa05107d9540
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -7284,17 +7251,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"typescript-eslint@npm:8.0.0-alpha.10":
|
"typescript-eslint@npm:8.0.0":
|
||||||
version: 8.0.0-alpha.10
|
version: 8.0.0
|
||||||
resolution: "typescript-eslint@npm:8.0.0-alpha.10"
|
resolution: "typescript-eslint@npm:8.0.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/eslint-plugin": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/eslint-plugin": "npm:8.0.0"
|
||||||
"@typescript-eslint/parser": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/parser": "npm:8.0.0"
|
||||||
"@typescript-eslint/utils": "npm:8.0.0-alpha.10"
|
"@typescript-eslint/utils": "npm:8.0.0"
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/695149b15ea7910a1c05dbb6601096c6f2c5d4c074715517f34a208a3b5b9e4dedad5c4d2c4c9a3f41ac984c4507d84fb4e91a3e792f95f759c658b7cd0f78f9
|
checksum: 10c0/138ba4767e16bcb1bde3e6becbe92a548091d27c5584cf60d5c78d599085e06172791ab297447b9245f5387c9777b76683c2afd0e0234ed20d67a1de1192a7c9
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -7335,6 +7302,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"undici-types@npm:~6.11.1":
|
||||||
|
version: 6.11.1
|
||||||
|
resolution: "undici-types@npm:6.11.1"
|
||||||
|
checksum: 10c0/d8f5739a8e6c779d72336c82deb49c56d5ac9f9f6e0eb2e8dd4d3f6929ae9db7cde370d2e46516fe6cad04ea53e790c5e16c4c75eed7cd0f9bd31b0763bb2fa3
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"unique-filename@npm:^3.0.0":
|
"unique-filename@npm:^3.0.0":
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
resolution: "unique-filename@npm:3.0.0"
|
resolution: "unique-filename@npm:3.0.0"
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ unbuild_flags =
|
|||||||
${common.core_unbuild_flags}
|
${common.core_unbuild_flags}
|
||||||
|
|
||||||
[espressi32_base]
|
[espressi32_base]
|
||||||
platform = espressif32@6.8.0
|
platform = espressif32@6.8.1
|
||||||
framework = arduino
|
framework = arduino
|
||||||
board_build.filesystem = littlefs
|
board_build.filesystem = littlefs
|
||||||
build_flags =
|
build_flags =
|
||||||
|
|||||||
@@ -648,78 +648,39 @@ void AnalogSensor::publish_values(const bool force) {
|
|||||||
// called from emsesp.cpp for commands
|
// called from emsesp.cpp for commands
|
||||||
// searches sensor by name
|
// searches sensor by name
|
||||||
bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int8_t id) {
|
bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int8_t id) {
|
||||||
// check of it a 'commands' command
|
|
||||||
if (Helpers::toLower(cmd) == F_(commands)) {
|
|
||||||
return Command::list(EMSdevice::DeviceType::ANALOGSENSOR, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sensors_.empty()) {
|
if (sensors_.empty()) {
|
||||||
return true; // no sensors, return true
|
return true; // no sensors, return true
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t show_all = 0;
|
if (!strcmp(cmd, F_(info)) || !strcmp(cmd, F_(values))) {
|
||||||
if (Helpers::hasValue(cmd)) {
|
for (const auto & sensor : sensors_) {
|
||||||
show_all = (strncmp(cmd, F_(info), 4) == 0) ? 1 : (strncmp(cmd, F_(values), 6) == 0) ? 2 : 0;
|
output[sensor.name()] = sensor.value();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// see if we're showing all sensors
|
if (!strcmp(cmd, F_(entities))) {
|
||||||
if (show_all) {
|
|
||||||
for (const auto & sensor : sensors_) {
|
for (const auto & sensor : sensors_) {
|
||||||
if (show_all == 1) {
|
get_value_json(output[sensor.name()].to<JsonObject>(), sensor);
|
||||||
// info
|
|
||||||
JsonObject dataSensor = output[sensor.name()].to<JsonObject>();
|
|
||||||
addSensorJson(dataSensor, sensor);
|
|
||||||
} else {
|
|
||||||
// values, shortname version. Also used in 'system allvalues'
|
|
||||||
output[sensor.name()] = sensor.value();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is for a specific sensor
|
// this is for a specific sensor
|
||||||
// make a copy of the string command for parsing, and lowercase it
|
const char * attribute_s = Command::get_attribute(cmd);
|
||||||
char sensor_name[COMMAND_MAX_LENGTH] = {'\0'};
|
|
||||||
char * attribute_s = nullptr;
|
|
||||||
strlcpy(sensor_name, Helpers::toLower(cmd).c_str(), sizeof(sensor_name));
|
|
||||||
|
|
||||||
// check specific attribute to fetch instead of the complete record
|
|
||||||
char * breakp = strchr(sensor_name, '/');
|
|
||||||
if (breakp) {
|
|
||||||
*breakp = '\0';
|
|
||||||
attribute_s = breakp + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto & sensor : sensors_) {
|
for (const auto & sensor : sensors_) {
|
||||||
if (sensor_name == Helpers::toLower(sensor.name()) || Helpers::atoint(sensor_name) == sensor.gpio()) {
|
// match custom name or sensor GPIO
|
||||||
// add the details
|
if (cmd == Helpers::toLower(sensor.name()) || Helpers::atoint(cmd) == sensor.gpio()) {
|
||||||
addSensorJson(output, sensor);
|
get_value_json(output, sensor);
|
||||||
|
return Command::set_attirbute(output, cmd, attribute_s);
|
||||||
/*
|
|
||||||
// if someone wants gpio numbers
|
|
||||||
char gpio_str[9];
|
|
||||||
snprintf(gpio_str, sizeof(gpio_str), "gpio_%02d", sensor.gpio());
|
|
||||||
output[gpio_str] = sensor.value();
|
|
||||||
*/
|
|
||||||
|
|
||||||
// if we're filtering on an attribute, go find it
|
|
||||||
if (attribute_s) {
|
|
||||||
if (output.containsKey(attribute_s)) {
|
|
||||||
std::string data = output[attribute_s].as<std::string>();
|
|
||||||
output.clear();
|
|
||||||
output["api_data"] = data; // always as a string
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return EMSESP::return_not_found(output, attribute_s, sensor_name); // not found
|
|
||||||
}
|
|
||||||
return true; // found a match, exit
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false; // not found
|
return false; // not found
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogSensor::addSensorJson(JsonObject output, const Sensor & sensor) {
|
void AnalogSensor::get_value_json(JsonObject output, const Sensor & sensor) {
|
||||||
output["gpio"] = sensor.gpio();
|
output["gpio"] = sensor.gpio();
|
||||||
output["type"] = F_(number);
|
output["type"] = F_(number);
|
||||||
output["analog"] = FL_(list_sensortype)[sensor.type()];
|
output["analog"] = FL_(list_sensortype)[sensor.type()];
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ class AnalogSensor {
|
|||||||
bool command_setvalue(const char * value, const int8_t gpio);
|
bool command_setvalue(const char * value, const int8_t gpio);
|
||||||
void measure();
|
void measure();
|
||||||
void addSensorJson(JsonObject output, const Sensor & sensor);
|
void addSensorJson(JsonObject output, const Sensor & sensor);
|
||||||
|
void get_value_json(JsonObject output, const Sensor & sensor);
|
||||||
|
|
||||||
std::vector<Sensor> sensors_; // our list of sensors
|
std::vector<Sensor> sensors_; // our list of sensors
|
||||||
|
|
||||||
|
|||||||
@@ -103,9 +103,9 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec
|
|||||||
}
|
}
|
||||||
if (command_p == nullptr) {
|
if (command_p == nullptr) {
|
||||||
// handle dead endpoints like api/system or api/boiler
|
// handle dead endpoints like api/system or api/boiler
|
||||||
// default to 'info' for SYSTEM, the other devices to 'values' for shortname version
|
// default to 'value' for all devices
|
||||||
if (num_paths < (id_n > 0 ? 4 : 3)) {
|
if (num_paths < (id_n > 0 ? 4 : 3)) {
|
||||||
command_p = device_type == EMSdevice::DeviceType::SYSTEM ? F_(info) : F_(values);
|
command_p = F_(values);
|
||||||
} else {
|
} else {
|
||||||
return json_message(CommandRet::NOT_FOUND, "missing or bad command", output);
|
return json_message(CommandRet::NOT_FOUND, "missing or bad command", output);
|
||||||
}
|
}
|
||||||
@@ -284,6 +284,29 @@ const char * Command::parse_command_string(const char * command, int8_t & id) {
|
|||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if command contains an attribute
|
||||||
|
const char * Command::get_attribute(const char * cmd) {
|
||||||
|
char * breakp = strchr(cmd, '/');
|
||||||
|
if (breakp) {
|
||||||
|
*breakp = '\0';
|
||||||
|
return breakp + 1;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Command::set_attirbute(JsonObject output, const char * cmd, const char * attribute) {
|
||||||
|
if (attribute == nullptr) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (output.containsKey(attribute)) {
|
||||||
|
std::string data = output[attribute].as<std::string>();
|
||||||
|
output.clear();
|
||||||
|
output["api_data"] = data; // always as a string
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return EMSESP::return_not_found(output, attribute, cmd); // not found
|
||||||
|
}
|
||||||
|
|
||||||
// calls a command directly
|
// calls a command directly
|
||||||
uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id) {
|
uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id) {
|
||||||
// create a temporary buffer
|
// create a temporary buffer
|
||||||
@@ -297,10 +320,12 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
|||||||
// calls a command. Takes a json object for output.
|
// calls a command. Takes a json object for output.
|
||||||
// id may be used to represent a heating circuit for example
|
// id may be used to represent a heating circuit for example
|
||||||
// returns 0 if the command errored, 1 (TRUE) if ok, 2 if not found, 3 if error or 4 if not allowed
|
// returns 0 if the command errored, 1 (TRUE) if ok, 2 if not found, 3 if error or 4 if not allowed
|
||||||
uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * value, const bool is_admin, const int8_t id, JsonObject output) {
|
uint8_t Command::call(const uint8_t device_type, const char * command, const char * value, const bool is_admin, const int8_t id, JsonObject output) {
|
||||||
if (cmd == nullptr) {
|
if (command == nullptr) {
|
||||||
return CommandRet::NOT_FOUND;
|
return CommandRet::NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
char cmd[COMMAND_MAX_LENGTH];
|
||||||
|
strcpy(cmd, Helpers::toLower(command).c_str());
|
||||||
|
|
||||||
auto dname = EMSdevice::device_type_2_device_name(device_type); // device name, not translated
|
auto dname = EMSdevice::device_type_2_device_name(device_type); // device name, not translated
|
||||||
|
|
||||||
@@ -309,6 +334,9 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
|||||||
// or a special command like 'info', 'values', 'commands', 'entities' etc
|
// or a special command like 'info', 'values', 'commands', 'entities' etc
|
||||||
bool single_command = (!value || !strlen(value));
|
bool single_command = (!value || !strlen(value));
|
||||||
if (single_command) {
|
if (single_command) {
|
||||||
|
if (!strcmp(cmd, F_(commands))) {
|
||||||
|
return Command::list(device_type, output);
|
||||||
|
}
|
||||||
if (EMSESP::get_device_value_info(output, cmd, id, device_type)) { // entity = cmd
|
if (EMSESP::get_device_value_info(output, cmd, id, device_type)) { // entity = cmd
|
||||||
LOG_DEBUG("Fetched device entity/attributes for %s/%s", dname, cmd);
|
LOG_DEBUG("Fetched device entity/attributes for %s/%s", dname, cmd);
|
||||||
return CommandRet::OK;
|
return CommandRet::OK;
|
||||||
@@ -319,17 +347,14 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
|||||||
|
|
||||||
// determine flags based on id (which is the tag)
|
// determine flags based on id (which is the tag)
|
||||||
uint8_t flag = CommandFlag::CMD_FLAG_DEFAULT;
|
uint8_t flag = CommandFlag::CMD_FLAG_DEFAULT;
|
||||||
// info and values works with all tags, keep it default
|
if (id >= DeviceValueTAG::TAG_HC1 && id <= DeviceValueTAG::TAG_HC8) {
|
||||||
if (std::string(cmd) != F_(values) && std::string(cmd) != F_(info)) {
|
flag = CommandFlag::CMD_FLAG_HC;
|
||||||
if (id >= DeviceValueTAG::TAG_HC1 && id <= DeviceValueTAG::TAG_HC8) {
|
} else if (id >= DeviceValueTAG::TAG_DHW1 && id <= DeviceValueTAG::TAG_DHW10) {
|
||||||
flag = CommandFlag::CMD_FLAG_HC;
|
flag = CommandFlag::CMD_FLAG_DHW;
|
||||||
} else if (id >= DeviceValueTAG::TAG_DHW1 && id <= DeviceValueTAG::TAG_DHW10) {
|
} else if (id >= DeviceValueTAG::TAG_HS1 && id <= DeviceValueTAG::TAG_HS16) {
|
||||||
flag = CommandFlag::CMD_FLAG_DHW;
|
flag = CommandFlag::CMD_FLAG_HS;
|
||||||
} else if (id >= DeviceValueTAG::TAG_HS1 && id <= DeviceValueTAG::TAG_HS16) {
|
} else if (id >= DeviceValueTAG::TAG_AHS1 && id <= DeviceValueTAG::TAG_AHS1) {
|
||||||
flag = CommandFlag::CMD_FLAG_HS;
|
flag = CommandFlag::CMD_FLAG_AHS;
|
||||||
} else if (id >= DeviceValueTAG::TAG_AHS1 && id <= DeviceValueTAG::TAG_AHS1) {
|
|
||||||
flag = CommandFlag::CMD_FLAG_AHS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// see if there is a command registered and it's valid
|
// see if there is a command registered and it's valid
|
||||||
@@ -500,15 +525,11 @@ std::string Command::tagged_cmd(const std::string & cmd, const uint8_t flag) {
|
|||||||
|
|
||||||
// list all commands for a specific device, output as json
|
// list all commands for a specific device, output as json
|
||||||
bool Command::list(const uint8_t device_type, JsonObject output) {
|
bool Command::list(const uint8_t device_type, JsonObject output) {
|
||||||
// check of it a 'commands' command
|
// common commands
|
||||||
if (device_type == EMSdevice::DeviceType::TEMPERATURESENSOR || device_type == EMSdevice::DeviceType::ANALOGSENSOR) {
|
output[F_(info)] = Helpers::translated_word(FL_(info_cmd));
|
||||||
output[F_(info)] = Helpers::translated_word(FL_(info_cmd));
|
output[F_(values)] = Helpers::translated_word(FL_(values_cmd));
|
||||||
output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd));
|
output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd));
|
||||||
output[F_(values)] = Helpers::translated_word(FL_(values_cmd));
|
output[F_(entities)] = Helpers::translated_word(FL_(entities_cmd));
|
||||||
} else if (cmdfunctions_.empty()) {
|
|
||||||
output["message"] = "no commands available";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a list of commands we have registered, and sort them
|
// create a list of commands we have registered, and sort them
|
||||||
std::list<std::string> sorted_cmds;
|
std::list<std::string> sorted_cmds;
|
||||||
|
|||||||
@@ -135,6 +135,8 @@ class Command {
|
|||||||
static uint8_t process(const char * path, const bool is_admin, const JsonObject input, JsonObject output);
|
static uint8_t process(const char * path, const bool is_admin, const JsonObject input, JsonObject output);
|
||||||
|
|
||||||
static const char * parse_command_string(const char * command, int8_t & id);
|
static const char * parse_command_string(const char * command, int8_t & id);
|
||||||
|
static const char * get_attribute(const char * cmd);
|
||||||
|
static bool set_attirbute(JsonObject output, const char * cmd, const char * attirbute);
|
||||||
|
|
||||||
static const char * return_code_string(const uint8_t return_code);
|
static const char * return_code_string(const uint8_t return_code);
|
||||||
|
|
||||||
|
|||||||
@@ -1607,7 +1607,11 @@ void Boiler::process_UBAEnergySupplied(std::shared_ptr<const Telegram> telegram)
|
|||||||
//XR1A050001 A05 Pump Heat circuit (1.0 ) 1 >> 1 & 0x01 ?
|
//XR1A050001 A05 Pump Heat circuit (1.0 ) 1 >> 1 & 0x01 ?
|
||||||
//XR1A040001 A04 Pump Cold circuit (1.0 ) 1 & 0x1 ?
|
//XR1A040001 A04 Pump Cold circuit (1.0 ) 1 & 0x1 ?
|
||||||
void Boiler::process_HpPower(std::shared_ptr<const Telegram> telegram) {
|
void Boiler::process_HpPower(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
has_bitupdate(telegram, VC0valve_, 0, 7);
|
||||||
|
has_bitupdate(telegram, hp3wayValve_, 0, 6);
|
||||||
|
// has_bitupdate(telegram, heating_, 0, 0); // heating on? https://github.com/emsesp/EMS-ESP32/discussions/1898
|
||||||
has_bitupdate(telegram, hpSwitchValve_, 0, 4);
|
has_bitupdate(telegram, hpSwitchValve_, 0, 4);
|
||||||
|
|
||||||
has_bitupdate(telegram, hpCompOn_, 3, 4);
|
has_bitupdate(telegram, hpCompOn_, 3, 4);
|
||||||
has_bitupdate(telegram, hpEA0_, 3, 6);
|
has_bitupdate(telegram, hpEA0_, 3, 6);
|
||||||
has_update(telegram, hpCircSpd_, 4);
|
has_update(telegram, hpCircSpd_, 4);
|
||||||
@@ -1953,10 +1957,10 @@ void Boiler::process_HpSettings2(std::shared_ptr<const Telegram> telegram) {
|
|||||||
// Boiler(0x08) -B-> All(0x00), ?(0x049D), data: 00 00 00 00 00 00 00 00 00 00 00 00
|
// Boiler(0x08) -B-> All(0x00), ?(0x049D), data: 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
void Boiler::process_HpSettings3(std::shared_ptr<const Telegram> telegram) {
|
void Boiler::process_HpSettings3(std::shared_ptr<const Telegram> telegram) {
|
||||||
has_update(telegram, heatCable_, 2);
|
has_update(telegram, heatCable_, 2);
|
||||||
has_update(telegram, VC0valve_, 3);
|
// has_update(telegram, VC0valve_, 3); // read in 48D
|
||||||
has_update(telegram, primePump_, 4);
|
has_update(telegram, primePump_, 4);
|
||||||
has_update(telegram, primePumpMod_, 5);
|
has_update(telegram, primePumpMod_, 5);
|
||||||
has_update(telegram, hp3wayValve_, 6);
|
// has_update(telegram, hp3wayValve_, 6); // read in 48D
|
||||||
has_update(telegram, elHeatStep1_, 7);
|
has_update(telegram, elHeatStep1_, 7);
|
||||||
has_update(telegram, elHeatStep2_, 8);
|
has_update(telegram, elHeatStep2_, 8);
|
||||||
has_update(telegram, elHeatStep3_, 9);
|
has_update(telegram, elHeatStep3_, 9);
|
||||||
|
|||||||
@@ -1106,7 +1106,8 @@ void Thermostat::process_RC300Set(std::shared_ptr<const Telegram> telegram) {
|
|||||||
has_enumupdate(telegram, hc->reducemode, 5, 1); // 1-outdoor temp threshold, 2-room temp threshold, 3-reduced mode
|
has_enumupdate(telegram, hc->reducemode, 5, 1); // 1-outdoor temp threshold, 2-room temp threshold, 3-reduced mode
|
||||||
has_update(telegram, hc->reducetemp, 9);
|
has_update(telegram, hc->reducetemp, 9);
|
||||||
has_update(telegram, hc->noreducetemp, 12);
|
has_update(telegram, hc->noreducetemp, 12);
|
||||||
has_update(telegram, hc->remoteseltemp, 17); // see https://github.com/emsesp/EMS-ESP32/issues/590
|
has_enumupdate(telegram, hc->switchProgMode, 13, 1); // 1-level, 2-absolute
|
||||||
|
has_update(telegram, hc->remoteseltemp, 17); // see https://github.com/emsesp/EMS-ESP32/issues/590
|
||||||
has_update(telegram, hc->boost, 23);
|
has_update(telegram, hc->boost, 23);
|
||||||
has_update(telegram, hc->boosttime, 24);
|
has_update(telegram, hc->boosttime, 24);
|
||||||
has_update(telegram, hc->cooling, 28);
|
has_update(telegram, hc->cooling, 28);
|
||||||
@@ -2280,6 +2281,19 @@ bool Thermostat::set_cooloffdelay(const char * value, const int8_t id) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Thermostat::set_switchProgMode(const char * value, const int8_t id) {
|
||||||
|
auto hc = heating_circuit(id);
|
||||||
|
if (hc == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint8_t set;
|
||||||
|
if (!Helpers::value2enum(value, set, FL_(enum_switchProgMode))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write_command(set_typeids[hc->hc()], 13, set + 1, set_typeids[hc->hc()]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// sets the thermostat ww circulation working mode, where mode is a string
|
// sets the thermostat ww circulation working mode, where mode is a string
|
||||||
bool Thermostat::set_wwcircmode(const char * value, const int8_t id) {
|
bool Thermostat::set_wwcircmode(const char * value, const int8_t id) {
|
||||||
uint8_t dhw = id2dhw(id);
|
uint8_t dhw = id2dhw(id);
|
||||||
@@ -4511,6 +4525,8 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
|
|||||||
register_device_value(tag, &hc->coolstart, DeviceValueType::UINT8, FL_(coolstart), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_coolstart), 20, 35);
|
register_device_value(tag, &hc->coolstart, DeviceValueType::UINT8, FL_(coolstart), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_coolstart), 20, 35);
|
||||||
register_device_value(tag, &hc->coolondelay, DeviceValueType::UINT8, FL_(coolondelay), DeviceValueUOM::HOURS, MAKE_CF_CB(set_coolondelay), 1, 48);
|
register_device_value(tag, &hc->coolondelay, DeviceValueType::UINT8, FL_(coolondelay), DeviceValueUOM::HOURS, MAKE_CF_CB(set_coolondelay), 1, 48);
|
||||||
register_device_value(tag, &hc->cooloffdelay, DeviceValueType::UINT8, FL_(cooloffdelay), DeviceValueUOM::HOURS, MAKE_CF_CB(set_cooloffdelay), 1, 48);
|
register_device_value(tag, &hc->cooloffdelay, DeviceValueType::UINT8, FL_(cooloffdelay), DeviceValueUOM::HOURS, MAKE_CF_CB(set_cooloffdelay), 1, 48);
|
||||||
|
register_device_value(
|
||||||
|
tag, &hc->switchProgMode, DeviceValueType::ENUM, FL_(enum_switchProgMode), FL_(control), DeviceValueUOM::NONE, MAKE_CF_CB(set_switchProgMode));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case EMSdevice::EMS_DEVICE_FLAG_CRF:
|
case EMSdevice::EMS_DEVICE_FLAG_CRF:
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ class Thermostat : public EMSdevice {
|
|||||||
uint8_t climate;
|
uint8_t climate;
|
||||||
uint8_t switchonoptimization;
|
uint8_t switchonoptimization;
|
||||||
uint8_t statusbyte; // from RC300monitor
|
uint8_t statusbyte; // from RC300monitor
|
||||||
|
uint8_t switchProgMode;
|
||||||
// RC 10
|
// RC 10
|
||||||
uint8_t reducehours; // night reduce duration
|
uint8_t reducehours; // night reduce duration
|
||||||
uint16_t reduceminutes; // remaining minutes to night->day
|
uint16_t reduceminutes; // remaining minutes to night->day
|
||||||
@@ -655,6 +656,7 @@ class Thermostat : public EMSdevice {
|
|||||||
bool set_cooling(const char * value, const int8_t id);
|
bool set_cooling(const char * value, const int8_t id);
|
||||||
bool set_coolondelay(const char * value, const int8_t id);
|
bool set_coolondelay(const char * value, const int8_t id);
|
||||||
bool set_cooloffdelay(const char * value, const int8_t id);
|
bool set_cooloffdelay(const char * value, const int8_t id);
|
||||||
|
bool set_switchProgMode(const char * value, const int8_t id);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -389,6 +389,7 @@ bool EMSdevice::has_cmd(const char * cmd, const int8_t id) const {
|
|||||||
|
|
||||||
// list of registered device entries
|
// list of registered device entries
|
||||||
// called from the command 'entities'
|
// called from the command 'entities'
|
||||||
|
/*
|
||||||
void EMSdevice::list_device_entries(JsonObject output) const {
|
void EMSdevice::list_device_entries(JsonObject output) const {
|
||||||
for (const auto & dv : devicevalues_) {
|
for (const auto & dv : devicevalues_) {
|
||||||
auto fullname = dv.get_fullname();
|
auto fullname = dv.get_fullname();
|
||||||
@@ -414,6 +415,7 @@ void EMSdevice::list_device_entries(JsonObject output) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// list all the telegram type IDs for this device
|
// list all the telegram type IDs for this device
|
||||||
void EMSdevice::show_telegram_handlers(uuid::console::Shell & shell) const {
|
void EMSdevice::show_telegram_handlers(uuid::console::Shell & shell) const {
|
||||||
@@ -1435,187 +1437,182 @@ void EMSdevice::dump_telegram_info(std::vector<TelegramFunctionDump> & telegram_
|
|||||||
// cmd is the endpoint or name of the device entity
|
// cmd is the endpoint or name of the device entity
|
||||||
// returns false if failed, otherwise true
|
// returns false if failed, otherwise true
|
||||||
bool EMSdevice::get_value_info(JsonObject output, const char * cmd, const int8_t tag) {
|
bool EMSdevice::get_value_info(JsonObject output, const char * cmd, const int8_t tag) {
|
||||||
JsonObject json = output;
|
if (!strcmp(cmd, F_(info))) {
|
||||||
|
return export_values(device_type(), output, tag, EMSdevice::OUTPUT_TARGET::API_VERBOSE);
|
||||||
// make a copy of the string command for parsing
|
}
|
||||||
char command_s[30];
|
if (!strcmp(cmd, F_(values))) {
|
||||||
strlcpy(command_s, cmd, sizeof(command_s));
|
return export_values(device_type(), output, tag, EMSdevice::OUTPUT_TARGET::API_SHORTNAMES);
|
||||||
char * attribute_s = nullptr;
|
}
|
||||||
|
if (!strcmp(cmd, F_(entities))) {
|
||||||
// check specific attribute to fetch instead of the complete record
|
char name[30];
|
||||||
char * breakp = strchr(command_s, '/');
|
for (auto & dv : devicevalues_) {
|
||||||
if (breakp) {
|
if (tag < 0 || tag == dv.tag) {
|
||||||
*breakp = '\0';
|
strlcpy(name, tag < 0 ? tag_to_mqtt(dv.tag) : "", sizeof(name));
|
||||||
attribute_s = breakp + 1;
|
strlcat(name, tag < 0 && dv.tag > 0 ? "." : "", sizeof(name));
|
||||||
|
strlcat(name, dv.short_name, sizeof(name));
|
||||||
|
get_value_json(output[name].to<JsonObject>(), dv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// search device value with this tag
|
// search device value with this tag
|
||||||
|
const char * attribute_s = Command::get_attribute(cmd);
|
||||||
for (auto & dv : devicevalues_) {
|
for (auto & dv : devicevalues_) {
|
||||||
if (Helpers::toLower(command_s) == Helpers::toLower(dv.short_name) && (tag <= 0 || tag == dv.tag)) {
|
if (cmd == Helpers::toLower(dv.short_name) && (tag <= 0 || tag == dv.tag)) {
|
||||||
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
|
get_value_json(output, dv);
|
||||||
|
|
||||||
const char * type = "type";
|
|
||||||
const char * value = "value";
|
|
||||||
|
|
||||||
json["name"] = dv.short_name;
|
|
||||||
|
|
||||||
auto fullname = dv.get_fullname();
|
|
||||||
if (!fullname.empty()) {
|
|
||||||
json["fullname"] = dv.has_tag() ? fullname + " " + tag_to_string(dv.tag) : fullname; // suffix tag
|
|
||||||
|
|
||||||
// TAG https://github.com/emsesp/EMS-ESP32/issues/1338
|
|
||||||
json["fullname"] = dv.has_tag() ? std::string(tag_to_string(dv.tag)) + " " + fullname.c_str() : fullname; // prefix tag
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dv.tag != DeviceValueTAG::TAG_NONE) {
|
|
||||||
json["circuit"] = tag_to_mqtt(dv.tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
char val[10];
|
|
||||||
switch (dv.type) {
|
|
||||||
case DeviceValueType::ENUM: {
|
|
||||||
if (*(uint8_t *)(dv.value_p) < dv.options_size) {
|
|
||||||
if (EMSESP::system_.enum_format() == ENUM_FORMAT_INDEX) {
|
|
||||||
json[value] = (uint8_t)(*(uint8_t *)(dv.value_p));
|
|
||||||
} else {
|
|
||||||
json[value] = Helpers::translated_word(dv.options[*(uint8_t *)(dv.value_p)]); // text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
json[type] = F_(enum);
|
|
||||||
JsonArray enum_ = json[F_(enum)].to<JsonArray>();
|
|
||||||
for (uint8_t i = 0; i < dv.options_size; i++) {
|
|
||||||
enum_.add(Helpers::translated_word(dv.options[i]));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case DeviceValueType::UINT16:
|
|
||||||
if (Helpers::hasValue(*(uint16_t *)(dv.value_p))) {
|
|
||||||
json[value] = serialized(Helpers::render_value(val, *(uint16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
|
||||||
}
|
|
||||||
json[type] = F_(number);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceValueType::UINT8:
|
|
||||||
if (Helpers::hasValue(*(uint8_t *)(dv.value_p))) {
|
|
||||||
json[value] = serialized(Helpers::render_value(val, *(uint8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
|
||||||
}
|
|
||||||
json[type] = F_(number);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceValueType::INT16:
|
|
||||||
if (Helpers::hasValue(*(int16_t *)(dv.value_p))) {
|
|
||||||
json[value] = serialized(Helpers::render_value(val, *(int16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
|
||||||
}
|
|
||||||
json[type] = F_(number);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceValueType::INT8:
|
|
||||||
if (Helpers::hasValue(*(int8_t *)(dv.value_p))) {
|
|
||||||
json[value] = serialized(Helpers::render_value(val, *(int8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
|
||||||
}
|
|
||||||
json[type] = F_(number);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceValueType::UINT24:
|
|
||||||
case DeviceValueType::UINT32:
|
|
||||||
if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
|
||||||
json[value] = serialized(Helpers::render_value(val, *(uint32_t *)(dv.value_p), dv.numeric_operator));
|
|
||||||
}
|
|
||||||
json[type] = F_(number);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceValueType::BOOL:
|
|
||||||
if (Helpers::hasValue(*(uint8_t *)(dv.value_p), EMS_VALUE_BOOL)) {
|
|
||||||
auto value_b = (bool)*(uint8_t *)(dv.value_p);
|
|
||||||
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
|
||||||
json[value] = value_b;
|
|
||||||
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
|
||||||
json[value] = value_b ? 1 : 0;
|
|
||||||
} else {
|
|
||||||
char s[12];
|
|
||||||
json[value] = Helpers::render_boolean(s, value_b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
json[type] = ("boolean");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceValueType::TIME:
|
|
||||||
if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
|
||||||
json[value] = serialized(Helpers::render_value(val, *(uint32_t *)(dv.value_p), dv.numeric_operator));
|
|
||||||
}
|
|
||||||
json[type] = F_(number);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceValueType::STRING:
|
|
||||||
if (Helpers::hasValue((char *)(dv.value_p))) {
|
|
||||||
json[value] = (char *)(dv.value_p);
|
|
||||||
}
|
|
||||||
json[type] = ("string");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceValueType::CMD:
|
|
||||||
if (dv.options_size > 1) {
|
|
||||||
json[type] = F_(enum);
|
|
||||||
JsonArray enum_ = json[F_(enum)].to<JsonArray>();
|
|
||||||
for (uint8_t i = 0; i < dv.options_size; i++) {
|
|
||||||
enum_.add(Helpers::translated_word(dv.options[i]));
|
|
||||||
}
|
|
||||||
} else if (dv.uom != DeviceValueUOM::NONE) {
|
|
||||||
json[type] = F_(number);
|
|
||||||
} else {
|
|
||||||
json[type] = F_(command);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
json[type] = Helpers::translated_word(FL_(unknown));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the min and max only for commands
|
|
||||||
if (dv.has_cmd) {
|
|
||||||
int16_t dv_set_min;
|
|
||||||
uint32_t dv_set_max;
|
|
||||||
if (dv.get_min_max(dv_set_min, dv_set_max)) {
|
|
||||||
json["min"] = dv_set_min;
|
|
||||||
json["max"] = dv_set_max;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add uom if it's not a " " (single space)
|
|
||||||
if (dv.uom != DeviceValueUOM::NONE) {
|
|
||||||
json["uom"] = uom_to_string(dv.uom);
|
|
||||||
}
|
|
||||||
|
|
||||||
json["readable"] = !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE);
|
|
||||||
json["writeable"] = dv.has_cmd && !dv.has_state(DeviceValueState::DV_READONLY);
|
|
||||||
json["visible"] = !dv.has_state(DeviceValueState::DV_WEB_EXCLUDE);
|
|
||||||
|
|
||||||
// TODO refactor to remove containsKey as it's costly and not advisable to use it
|
|
||||||
// https://arduinojson.org/v7/api/jsonobject/containskey/#avoid
|
|
||||||
|
|
||||||
// commented out, leads to issues if type is set to number
|
|
||||||
// if there is no value, mention it
|
|
||||||
// if (!json.containsKey(value)) {
|
|
||||||
// json[value] = "not set";
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if we're filtering on an attribute, go find it
|
// if we're filtering on an attribute, go find it
|
||||||
if (attribute_s) {
|
return Command::set_attirbute(output, cmd, attribute_s);
|
||||||
if (json.containsKey(attribute_s)) {
|
}
|
||||||
std::string data = json[attribute_s].as<std::string>();
|
}
|
||||||
output.clear();
|
return false; // not found, but don't return a message error yet
|
||||||
output["api_data"] = data; // always as string
|
}
|
||||||
return true;
|
|
||||||
}
|
// build the json for a specific entity
|
||||||
return EMSESP::return_not_found(output, attribute_s, command_s); // not found
|
void EMSdevice::get_value_json(JsonObject json, DeviceValue & dv) {
|
||||||
|
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
|
||||||
|
|
||||||
|
const char * type = "type";
|
||||||
|
const char * value = "value";
|
||||||
|
|
||||||
|
json["name"] = dv.short_name;
|
||||||
|
|
||||||
|
auto fullname = dv.get_fullname();
|
||||||
|
if (!fullname.empty()) {
|
||||||
|
json["fullname"] = dv.has_tag() ? fullname + " " + tag_to_string(dv.tag) : fullname; // suffix tag
|
||||||
|
|
||||||
|
// TAG https://github.com/emsesp/EMS-ESP32/issues/1338
|
||||||
|
json["fullname"] = dv.has_tag() ? std::string(tag_to_string(dv.tag)) + " " + fullname.c_str() : fullname; // prefix tag
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dv.tag != DeviceValueTAG::TAG_NONE) {
|
||||||
|
json["circuit"] = tag_to_mqtt(dv.tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
char val[10];
|
||||||
|
switch (dv.type) {
|
||||||
|
case DeviceValueType::ENUM: {
|
||||||
|
if (*(uint8_t *)(dv.value_p) < dv.options_size) {
|
||||||
|
json["index"] = (uint8_t)(*(uint8_t *)(dv.value_p));
|
||||||
|
json["enum"] = Helpers::translated_word(dv.options[*(uint8_t *)(dv.value_p)]); // text
|
||||||
|
if (EMSESP::system_.enum_format() == ENUM_FORMAT_INDEX) {
|
||||||
|
json[value] = (uint8_t)(*(uint8_t *)(dv.value_p));
|
||||||
|
} else {
|
||||||
|
json[value] = Helpers::translated_word(dv.options[*(uint8_t *)(dv.value_p)]); // text
|
||||||
}
|
}
|
||||||
return true;
|
}
|
||||||
|
json[type] = F_(enum);
|
||||||
|
JsonArray enum_ = json[F_(enum)].to<JsonArray>();
|
||||||
|
for (uint8_t i = 0; i < dv.options_size; i++) {
|
||||||
|
enum_.add(Helpers::translated_word(dv.options[i]));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case DeviceValueType::UINT16:
|
||||||
|
if (Helpers::hasValue(*(uint16_t *)(dv.value_p))) {
|
||||||
|
json[value] = serialized(Helpers::render_value(val, *(uint16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
||||||
|
}
|
||||||
|
json[type] = F_(number);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DeviceValueType::UINT8:
|
||||||
|
if (Helpers::hasValue(*(uint8_t *)(dv.value_p))) {
|
||||||
|
json[value] = serialized(Helpers::render_value(val, *(uint8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
||||||
|
}
|
||||||
|
json[type] = F_(number);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DeviceValueType::INT16:
|
||||||
|
if (Helpers::hasValue(*(int16_t *)(dv.value_p))) {
|
||||||
|
json[value] = serialized(Helpers::render_value(val, *(int16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
||||||
|
}
|
||||||
|
json[type] = F_(number);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DeviceValueType::INT8:
|
||||||
|
if (Helpers::hasValue(*(int8_t *)(dv.value_p))) {
|
||||||
|
json[value] = serialized(Helpers::render_value(val, *(int8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
|
||||||
|
}
|
||||||
|
json[type] = F_(number);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DeviceValueType::UINT24:
|
||||||
|
case DeviceValueType::UINT32:
|
||||||
|
if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
||||||
|
json[value] = serialized(Helpers::render_value(val, *(uint32_t *)(dv.value_p), dv.numeric_operator));
|
||||||
|
}
|
||||||
|
json[type] = F_(number);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DeviceValueType::BOOL:
|
||||||
|
if (Helpers::hasValue(*(uint8_t *)(dv.value_p), EMS_VALUE_BOOL)) {
|
||||||
|
auto value_b = (bool)*(uint8_t *)(dv.value_p);
|
||||||
|
json["bool"] = value_b;
|
||||||
|
json["index"] = value_b ? 1 : 0;
|
||||||
|
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
||||||
|
json[value] = value_b;
|
||||||
|
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
||||||
|
json[value] = value_b ? 1 : 0;
|
||||||
|
} else {
|
||||||
|
char s[12];
|
||||||
|
json[value] = Helpers::render_boolean(s, value_b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
json[type] = ("boolean");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DeviceValueType::TIME:
|
||||||
|
if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
||||||
|
json[value] = serialized(Helpers::render_value(val, *(uint32_t *)(dv.value_p), dv.numeric_operator));
|
||||||
|
}
|
||||||
|
json[type] = F_(number);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DeviceValueType::STRING:
|
||||||
|
if (Helpers::hasValue((char *)(dv.value_p))) {
|
||||||
|
json[value] = (char *)(dv.value_p);
|
||||||
|
}
|
||||||
|
json[type] = ("string");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DeviceValueType::CMD:
|
||||||
|
if (dv.options_size > 1) {
|
||||||
|
json[type] = F_(enum);
|
||||||
|
JsonArray enum_ = json[F_(enum)].to<JsonArray>();
|
||||||
|
for (uint8_t i = 0; i < dv.options_size; i++) {
|
||||||
|
enum_.add(Helpers::translated_word(dv.options[i]));
|
||||||
|
}
|
||||||
|
} else if (dv.uom != DeviceValueUOM::NONE) {
|
||||||
|
json[type] = F_(number);
|
||||||
|
} else {
|
||||||
|
json[type] = F_(command);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
json[type] = Helpers::translated_word(FL_(unknown));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the min and max only for commands
|
||||||
|
if (dv.has_cmd) {
|
||||||
|
int16_t dv_set_min;
|
||||||
|
uint32_t dv_set_max;
|
||||||
|
if (dv.get_min_max(dv_set_min, dv_set_max)) {
|
||||||
|
json["min"] = dv_set_min;
|
||||||
|
json["max"] = dv_set_max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false; // not found, but don't return a message error yet
|
// add uom if it's not a " " (single space)
|
||||||
|
if (dv.uom != DeviceValueUOM::NONE) {
|
||||||
|
json["uom"] = uom_to_string(dv.uom);
|
||||||
|
}
|
||||||
|
|
||||||
|
json["readable"] = !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE);
|
||||||
|
json["writeable"] = dv.has_cmd && !dv.has_state(DeviceValueState::DV_READONLY);
|
||||||
|
json["visible"] = !dv.has_state(DeviceValueState::DV_WEB_EXCLUDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mqtt publish all single values from one device (used for time schedule)
|
// mqtt publish all single values from one device (used for time schedule)
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ class EMSdevice {
|
|||||||
void show_telegram_handlers(uuid::console::Shell & shell) const;
|
void show_telegram_handlers(uuid::console::Shell & shell) const;
|
||||||
char * show_telegram_handlers(char * result, const size_t len, const uint8_t handlers);
|
char * show_telegram_handlers(char * result, const size_t len, const uint8_t handlers);
|
||||||
void show_mqtt_handlers(uuid::console::Shell & shell) const;
|
void show_mqtt_handlers(uuid::console::Shell & shell) const;
|
||||||
void list_device_entries(JsonObject output) const;
|
// void list_device_entries(JsonObject output) const;
|
||||||
void add_handlers_ignored(const uint16_t handler);
|
void add_handlers_ignored(const uint16_t handler);
|
||||||
|
|
||||||
void set_climate_minmax(int8_t tag, int16_t min, uint32_t max);
|
void set_climate_minmax(int8_t tag, int16_t min, uint32_t max);
|
||||||
@@ -227,6 +227,7 @@ class EMSdevice {
|
|||||||
std::string get_value_uom(const std::string & shortname) const;
|
std::string get_value_uom(const std::string & shortname) const;
|
||||||
|
|
||||||
bool get_value_info(JsonObject root, const char * cmd, const int8_t id);
|
bool get_value_info(JsonObject root, const char * cmd, const int8_t id);
|
||||||
|
void get_value_json(JsonObject output, DeviceValue & dv);
|
||||||
void get_dv_info(JsonObject json);
|
void get_dv_info(JsonObject json);
|
||||||
|
|
||||||
enum OUTPUT_TARGET : uint8_t { API_VERBOSE, API_SHORTNAMES, MQTT, CONSOLE };
|
enum OUTPUT_TARGET : uint8_t { API_VERBOSE, API_SHORTNAMES, MQTT, CONSOLE };
|
||||||
@@ -353,8 +354,7 @@ class EMSdevice {
|
|||||||
ANALOGSENSOR, // for internal analog sensors
|
ANALOGSENSOR, // for internal analog sensors
|
||||||
SCHEDULER, // for internal schedule
|
SCHEDULER, // for internal schedule
|
||||||
CUSTOM, // for user defined entities
|
CUSTOM, // for user defined entities
|
||||||
|
BOILER, // frome here on enum the ems-devices
|
||||||
BOILER,
|
|
||||||
THERMOSTAT,
|
THERMOSTAT,
|
||||||
MIXER,
|
MIXER,
|
||||||
SOLAR,
|
SOLAR,
|
||||||
|
|||||||
@@ -1343,38 +1343,12 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
// Print to LOG showing we've added a new device
|
// Print to LOG showing we've added a new device
|
||||||
LOG_INFO("Recognized new %s with deviceID 0x%02X", EMSdevice::device_type_2_device_name(device_type), device_id);
|
LOG_INFO("Recognized new %s with deviceID 0x%02X", EMSdevice::device_type_2_device_name(device_type), device_id);
|
||||||
|
|
||||||
// add commands 'info', 'commands', 'values', 'entities' for all EMS devices
|
// register the MQTT subscribe topic for this device
|
||||||
// and register the MQTT subscribe topic for this device
|
|
||||||
// except for connect, controller and gateway
|
// except for connect, controller and gateway
|
||||||
if ((device_type == DeviceType::CONNECT) || (device_type == DeviceType::CONTROLLER) || (device_type == DeviceType::GATEWAY)) {
|
if ((device_type == DeviceType::CONNECT) || (device_type == DeviceType::CONTROLLER) || (device_type == DeviceType::GATEWAY)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::add(
|
|
||||||
device_type,
|
|
||||||
F_(info),
|
|
||||||
[device_type](const char * value, const int8_t id, JsonObject output) {
|
|
||||||
return EMSdevice::export_values(device_type, output, id, EMSdevice::OUTPUT_TARGET::API_VERBOSE);
|
|
||||||
},
|
|
||||||
FL_(info_cmd));
|
|
||||||
Command::add(
|
|
||||||
device_type,
|
|
||||||
F_(values),
|
|
||||||
[device_type](const char * value, const int8_t id, JsonObject output) {
|
|
||||||
return EMSdevice::export_values(device_type, output, id, EMSdevice::OUTPUT_TARGET::API_SHORTNAMES);
|
|
||||||
},
|
|
||||||
FL_(values_cmd));
|
|
||||||
Command::add(
|
|
||||||
device_type,
|
|
||||||
F_(commands),
|
|
||||||
[device_type](const char * value, const int8_t id, JsonObject output) { return command_commands(device_type, output, id); },
|
|
||||||
FL_(commands_cmd));
|
|
||||||
Command::add(
|
|
||||||
device_type,
|
|
||||||
F_(entities),
|
|
||||||
[device_type](const char * value, const int8_t id, JsonObject output) { return command_entities(device_type, output, id); },
|
|
||||||
FL_(entities_cmd));
|
|
||||||
|
|
||||||
// MQTT subscribe to the device e.g. "ems-esp/boiler/#"
|
// MQTT subscribe to the device e.g. "ems-esp/boiler/#"
|
||||||
auto topic = std::string(EMSdevice::device_type_2_device_name(device_type)) + "/#";
|
auto topic = std::string(EMSdevice::device_type_2_device_name(device_type)) + "/#";
|
||||||
Mqtt::subscribe(device_type, topic, nullptr);
|
Mqtt::subscribe(device_type, topic, nullptr);
|
||||||
@@ -1382,25 +1356,6 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// list device entities
|
|
||||||
bool EMSESP::command_entities(uint8_t device_type, JsonObject output, const int8_t id) {
|
|
||||||
JsonObject node;
|
|
||||||
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
|
||||||
if (emsdevice && (emsdevice->device_type() == device_type)) {
|
|
||||||
emsdevice->list_device_entries(output);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// list all available commands, return as json
|
|
||||||
bool EMSESP::command_commands(uint8_t device_type, JsonObject output, const int8_t id) {
|
|
||||||
return Command::list(device_type, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
// send a read request, passing it into to the Tx Service, with optional offset and length
|
// send a read request, passing it into to the Tx Service, with optional offset and length
|
||||||
void EMSESP::send_read_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, const uint8_t length, const bool front) {
|
void EMSESP::send_read_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, const uint8_t length, const bool front) {
|
||||||
txservice_.read_request(type_id, dest, offset, length, front);
|
txservice_.read_request(type_id, dest, offset, length, front);
|
||||||
|
|||||||
@@ -251,8 +251,6 @@ class EMSESP {
|
|||||||
static void process_version(std::shared_ptr<const Telegram> telegram);
|
static void process_version(std::shared_ptr<const Telegram> telegram);
|
||||||
static void publish_response(std::shared_ptr<const Telegram> telegram);
|
static void publish_response(std::shared_ptr<const Telegram> telegram);
|
||||||
static void publish_all_loop();
|
static void publish_all_loop();
|
||||||
static bool command_commands(uint8_t device_type, JsonObject output, const int8_t id);
|
|
||||||
static bool command_entities(uint8_t device_type, JsonObject output, const int8_t id);
|
|
||||||
|
|
||||||
static constexpr uint32_t EMS_FETCH_FREQUENCY = 60000; // check every minute
|
static constexpr uint32_t EMS_FETCH_FREQUENCY = 60000; // check every minute
|
||||||
static constexpr uint8_t EMS_WAIT_KM_TIMEOUT = 60; // wait one minute
|
static constexpr uint8_t EMS_WAIT_KM_TIMEOUT = 60; // wait one minute
|
||||||
|
|||||||
@@ -349,6 +349,7 @@ MAKE_ENUM(enum_control1, FL_(rc310), FL_(rc200), FL_(rc100), FL_(rc100h), FL_(tc
|
|||||||
MAKE_ENUM(enum_control2, FL_(off), FL_(dash), FL_(rc100), FL_(rc100h), FL_(dash), FL_(rc120rf), FL_(rc220), FL_(single)) // BC400
|
MAKE_ENUM(enum_control2, FL_(off), FL_(dash), FL_(rc100), FL_(rc100h), FL_(dash), FL_(rc120rf), FL_(rc220), FL_(single)) // BC400
|
||||||
|
|
||||||
MAKE_ENUM(enum_switchmode, FL_(off), FL_(eco), FL_(comfort), FL_(heat))
|
MAKE_ENUM(enum_switchmode, FL_(off), FL_(eco), FL_(comfort), FL_(heat))
|
||||||
|
MAKE_ENUM(enum_switchProgMode, FL_(level), FL_(absolute))
|
||||||
|
|
||||||
MAKE_ENUM(enum_dayOfWeek, FL_(day_mo), FL_(day_tu), FL_(day_we), FL_(day_th), FL_(day_fr), FL_(day_sa), FL_(day_su), FL_(all))
|
MAKE_ENUM(enum_dayOfWeek, FL_(day_mo), FL_(day_tu), FL_(day_we), FL_(day_th), FL_(day_fr), FL_(day_sa), FL_(day_su), FL_(all))
|
||||||
MAKE_ENUM(enum_progMode2, FL_(own_1), FL_(family), FL_(morning), FL_(evening), FL_(am), FL_(pm), FL_(midday), FL_(singles), FL_(seniors), FL_(new), FL_(own_2))
|
MAKE_ENUM(enum_progMode2, FL_(own_1), FL_(family), FL_(morning), FL_(evening), FL_(am), FL_(pm), FL_(midday), FL_(singles), FL_(seniors), FL_(new), FL_(own_2))
|
||||||
|
|||||||
@@ -279,6 +279,8 @@ MAKE_WORD_TRANSLATION(functioning_mode, "functioning mode", "Funktionsweise", "f
|
|||||||
MAKE_WORD_TRANSLATION(unmixed, "unmixed", "ungemischt", "", "", "niezmieszany", "", "", "", "", "") // TODO translate
|
MAKE_WORD_TRANSLATION(unmixed, "unmixed", "ungemischt", "", "", "niezmieszany", "", "", "", "", "") // TODO translate
|
||||||
MAKE_WORD_TRANSLATION(unmixedIPM, "unmixed IPM", "ungemischt IPM", "", "", "niezmieszany IPM", "", "", "", "", "") // TODO translate
|
MAKE_WORD_TRANSLATION(unmixedIPM, "unmixed IPM", "ungemischt IPM", "", "", "niezmieszany IPM", "", "", "", "", "") // TODO translate
|
||||||
MAKE_WORD_TRANSLATION(mixed, "mixed IPM", "gemischt IPM", "", "", "zmieszany IPM", "", "", "", "", "") // TODO translate
|
MAKE_WORD_TRANSLATION(mixed, "mixed IPM", "gemischt IPM", "", "", "zmieszany IPM", "", "", "", "", "") // TODO translate
|
||||||
|
MAKE_WORD_TRANSLATION(level, "level", "Level") // TODO translate
|
||||||
|
MAKE_WORD_TRANSLATION(absolute, "absolute", "Absolut") // TODO translate
|
||||||
|
|
||||||
// mixer
|
// mixer
|
||||||
MAKE_WORD_TRANSLATION(stopped, "stopped", "gestoppt", "gestopt", "stoppad", "zatrzymany", "stoppet", "arrêté", "durdu", "fermato", "zastavený")
|
MAKE_WORD_TRANSLATION(stopped, "stopped", "gestoppt", "gestopt", "stoppad", "zatrzymany", "stoppet", "arrêté", "durdu", "fermato", "zastavený")
|
||||||
|
|||||||
126
src/system.cpp
126
src/system.cpp
@@ -108,31 +108,40 @@ bool System::command_response(const char * value, const int8_t id, JsonObject ou
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// output all the EMS devices and their values, plus the sensors and any custom entities
|
// output all the devices and the values
|
||||||
// not scheduler as these are records with no output data
|
// not system info
|
||||||
bool System::command_allvalues(const char * value, const int8_t id, JsonObject output) {
|
bool System::command_allvalues(const char * value, const int8_t id, JsonObject output) {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
JsonObject device_output;
|
JsonObject device_output;
|
||||||
|
// default to values
|
||||||
|
if (value == nullptr || strlen(value) == 0) {
|
||||||
|
value = F_(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
// System Entities
|
||||||
|
// device_output = output["System"].to<JsonObject>();
|
||||||
|
// get_value_info(device_output, value);
|
||||||
|
|
||||||
|
// EMS-Device Entities
|
||||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||||
std::string title = emsdevice->device_type_2_device_name_translated() + std::string(" ") + emsdevice->to_string();
|
std::string title = emsdevice->device_type_2_device_name_translated() + std::string(" ") + emsdevice->to_string();
|
||||||
device_output = output[title].to<JsonObject>();
|
device_output = output[title].to<JsonObject>();
|
||||||
emsdevice->generate_values(device_output, DeviceValueTAG::TAG_NONE, true, EMSdevice::OUTPUT_TARGET::API_VERBOSE); // use nested for id -1 and 0
|
emsdevice->get_value_info(device_output, value, DeviceValueTAG::TAG_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom Entities
|
// Custom Entities
|
||||||
device_output = output["Custom Entities"].to<JsonObject>();
|
device_output = output["Custom Entities"].to<JsonObject>();
|
||||||
EMSESP::webCustomEntityService.get_value_info(device_output, "");
|
EMSESP::webCustomEntityService.get_value_info(device_output, value);
|
||||||
|
|
||||||
// Scheduler
|
// Scheduler
|
||||||
device_output = output["Scheduler"].to<JsonObject>();
|
device_output = output["Scheduler"].to<JsonObject>();
|
||||||
EMSESP::webSchedulerService.get_value_info(device_output, "");
|
EMSESP::webSchedulerService.get_value_info(device_output, value);
|
||||||
|
|
||||||
// Sensors
|
// Sensors
|
||||||
device_output = output["Analog Sensors"].to<JsonObject>();
|
device_output = output["Analog Sensors"].to<JsonObject>();
|
||||||
EMSESP::analogsensor_.get_value_info(device_output, "values");
|
EMSESP::analogsensor_.get_value_info(device_output, value);
|
||||||
device_output = output["Temperature Sensors"].to<JsonObject>();
|
device_output = output["Temperature Sensors"].to<JsonObject>();
|
||||||
EMSESP::temperaturesensor_.get_value_info(device_output, "values");
|
EMSESP::temperaturesensor_.get_value_info(device_output, value);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -848,8 +857,6 @@ void System::commands_init() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// these commands will return data in JSON format
|
// these commands will return data in JSON format
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(info), System::command_info, FL_(system_info_cmd));
|
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(commands), System::command_commands, FL_(commands_cmd));
|
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F("response"), System::command_response, FL_(commands_response));
|
Command::add(EMSdevice::DeviceType::SYSTEM, F("response"), System::command_response, FL_(commands_response));
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F("allvalues"), System::command_allvalues, FL_(allvalues_cmd));
|
Command::add(EMSdevice::DeviceType::SYSTEM, F("allvalues"), System::command_allvalues, FL_(allvalues_cmd));
|
||||||
|
|
||||||
@@ -1250,11 +1257,6 @@ bool System::check_upgrade(bool factory_settings) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// list commands
|
|
||||||
bool System::command_commands(const char * value, const int8_t id, JsonObject output) {
|
|
||||||
return Command::list(EMSdevice::DeviceType::SYSTEM, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert settings file into json object
|
// convert settings file into json object
|
||||||
void System::extractSettings(const char * filename, const char * section, JsonObject output) {
|
void System::extractSettings(const char * filename, const char * section, JsonObject output) {
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
@@ -1292,27 +1294,41 @@ bool System::saveSettings(const char * filename, const char * section, JsonObjec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// return back a system value
|
// return back a system value
|
||||||
bool System::get_value_info(JsonObject root, const char * command) {
|
bool System::get_value_info(JsonObject output, const char * cmd) {
|
||||||
if (command == nullptr || strlen(command) == 0) {
|
if (cmd == nullptr || strlen(cmd) == 0) {
|
||||||
LOG_ERROR("empty system command");
|
LOG_ERROR("empty system command");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// cmd is lower case of the command
|
// check for hardcoded "info"/"value"
|
||||||
char cmd[COMMAND_MAX_LENGTH];
|
if (!strcmp(cmd, F_(info)) || !strcmp(cmd, F_(values))) {
|
||||||
strlcpy(cmd, Helpers::toLower(command).c_str(), sizeof(cmd));
|
return command_info("", 0, output);
|
||||||
|
}
|
||||||
|
|
||||||
// fetch all the data from the system
|
// fetch all the data from the system in a different json
|
||||||
|
JsonDocument doc;
|
||||||
|
JsonObject root = doc.to<JsonObject>();
|
||||||
(void)command_info("", 0, root);
|
(void)command_info("", 0, root);
|
||||||
|
|
||||||
// check for hardcoded "info"
|
// list all entities
|
||||||
if (!strcmp(cmd, F_(info)) || !strcmp(cmd, F_(value))) {
|
if (!strcmp(cmd, F_(entities))) {
|
||||||
|
for (JsonPair p : root) {
|
||||||
|
if (p.value().is<JsonObject>()) {
|
||||||
|
// String prefix = p.key().c_str();
|
||||||
|
for (JsonPair p1 : p.value().as<JsonObject>()) {
|
||||||
|
JsonObject entity = output[String(p.key().c_str()) + '.' + p1.key().c_str()].to<JsonObject>();
|
||||||
|
get_value_json(entity, p.key().c_str(), p1.key().c_str(), p1.value());
|
||||||
|
}
|
||||||
|
} // else { // we don't have pairs in json root object
|
||||||
|
// get_value_json(entity, "", p.key().c_str(), p.value());
|
||||||
|
// }
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char * val = strstr(cmd, "/value");
|
char * val = strstr(cmd, "/value");
|
||||||
if (val) {
|
if (val) {
|
||||||
val[0] = '\0';
|
*val = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
char * slash = strchr(cmd, '/');
|
char * slash = strchr(cmd, '/');
|
||||||
@@ -1321,40 +1337,58 @@ bool System::get_value_info(JsonObject root, const char * command) {
|
|||||||
slash++;
|
slash++;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string s;
|
// list values for a jsonObject in system, e.g. /api/system/network
|
||||||
|
if (!slash || !strcmp(slash, F_(info)) || !strcmp(slash, F_(values))) {
|
||||||
|
for (JsonPair p : root) {
|
||||||
|
if (Helpers::toLower(p.key().c_str()) == cmd && p.value().is<JsonObject>()) {
|
||||||
|
for (JsonPair p1 : p.value().as<JsonObject>()) {
|
||||||
|
output[p1.key().c_str()] = p1.value().as<std::string>();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// value info or api_data for a single value
|
||||||
// Loop through all the key-value pairs in root to find the key, case independent
|
// Loop through all the key-value pairs in root to find the key, case independent
|
||||||
if (slash) { // search the top level first
|
if (slash) { // search the top level first
|
||||||
for (JsonPair p : root) {
|
for (JsonPair p : root) {
|
||||||
if (p.value().is<JsonObject>() && Helpers::toLower(p.key().c_str()) == cmd) {
|
if (p.value().is<JsonObject>() && Helpers::toLower(p.key().c_str()) == cmd) {
|
||||||
for (JsonPair p1 : p.value().as<JsonObject>()) {
|
for (JsonPair p1 : p.value().as<JsonObject>()) {
|
||||||
if (Helpers::toLower(p1.key().c_str()) == slash && !p1.value().is<JsonObject>()) {
|
if (Helpers::toLower(p1.key().c_str()) == slash && !p1.value().is<JsonObject>()) {
|
||||||
s = p1.value().as<std::string>();
|
if (val) {
|
||||||
break;
|
output["api_data"] = p1.value().as<std::string>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
get_value_json(output, p.key().c_str(), p1.key().c_str(), p1.value());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // else skipt, but we don't have value pairs in system root
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::get_value_json(JsonObject output, const std::string & circuit, const std::string & name, JsonVariant val) {
|
||||||
|
output["name"] = name;
|
||||||
|
if (circuit.length()) {
|
||||||
|
output["circuit"] = circuit;
|
||||||
|
}
|
||||||
|
output["readable"] = true;
|
||||||
|
output["writable"] = false;
|
||||||
|
output["visible"] = true;
|
||||||
|
if (val.is<bool>()) {
|
||||||
|
output["value"] = val.as<bool>();
|
||||||
|
output["type"] = "boolean";
|
||||||
|
} else if (val.is<String>() || val.is<const char *>() || val.is<std::string>()) {
|
||||||
|
output["value"] = val.as<std::string>();
|
||||||
|
output["type"] = "string";
|
||||||
} else {
|
} else {
|
||||||
for (JsonPair p : root) {
|
output["value"] = val.as<float>();
|
||||||
if (Helpers::toLower(p.key().c_str()) == cmd && !p.value().is<JsonObject>()) {
|
output["type"] = "number";
|
||||||
s = p.value().as<std::string>();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
root.clear(); // clear json, we only one a single value
|
|
||||||
|
|
||||||
if (!s.empty()) {
|
|
||||||
if (val) {
|
|
||||||
root["api_data"] = s;
|
|
||||||
} else {
|
|
||||||
root["value"] = s;
|
|
||||||
}
|
|
||||||
return true; // found
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // not found
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// export status information including the device information
|
// export status information including the device information
|
||||||
|
|||||||
@@ -59,10 +59,10 @@ class System {
|
|||||||
static bool command_watch(const char * value, const int8_t id);
|
static bool command_watch(const char * value, const int8_t id);
|
||||||
static bool command_message(const char * value, const int8_t id);
|
static bool command_message(const char * value, const int8_t id);
|
||||||
static bool command_info(const char * value, const int8_t id, JsonObject output);
|
static bool command_info(const char * value, const int8_t id, JsonObject output);
|
||||||
static bool command_commands(const char * value, const int8_t id, JsonObject output);
|
|
||||||
static bool command_response(const char * value, const int8_t id, JsonObject output);
|
static bool command_response(const char * value, const int8_t id, JsonObject output);
|
||||||
static bool command_allvalues(const char * value, const int8_t id, JsonObject output);
|
static bool command_allvalues(const char * value, const int8_t id, JsonObject output);
|
||||||
static bool get_value_info(JsonObject root, const char * cmd);
|
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);
|
||||||
|
|
||||||
#if defined(EMSESP_TEST)
|
#if defined(EMSESP_TEST)
|
||||||
static bool command_test(const char * value, const int8_t id);
|
static bool command_test(const char * value, const int8_t id);
|
||||||
|
|||||||
@@ -343,75 +343,43 @@ bool TemperatureSensor::updated_values() {
|
|||||||
|
|
||||||
// called from emsesp.cpp for commands
|
// called from emsesp.cpp for commands
|
||||||
bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, const int8_t id) {
|
bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, const int8_t id) {
|
||||||
// check of it a 'commands' command
|
|
||||||
if (Helpers::toLower(cmd) == F_(commands)) {
|
|
||||||
return Command::list(EMSdevice::DeviceType::TEMPERATURESENSOR, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
// return empty json if there are no sensors
|
// return empty json if there are no sensors
|
||||||
if (sensors_.empty()) {
|
if (sensors_.empty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t show_all = 0;
|
if (!strcmp(cmd, F_(info)) || !strcmp(cmd, F_(values))) {
|
||||||
if (Helpers::hasValue(cmd)) {
|
|
||||||
show_all = (strncmp(cmd, F_(info), 4) == 0) ? 1 : (strncmp(cmd, F_(values), 6) == 0) ? 2 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// see if we're showing all sensors
|
|
||||||
if (show_all) {
|
|
||||||
for (const auto & sensor : sensors_) {
|
for (const auto & sensor : sensors_) {
|
||||||
if (show_all == 1) {
|
if (Helpers::hasValue(sensor.temperature_c)) {
|
||||||
// info
|
char val[10];
|
||||||
JsonObject dataSensor = output[sensor.name()].to<JsonObject>();
|
output[sensor.name()] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
|
||||||
addSensorJson(dataSensor, sensor);
|
|
||||||
} else {
|
|
||||||
// values, shortname version. Also used in 'system allvalues'
|
|
||||||
if (Helpers::hasValue(sensor.temperature_c)) {
|
|
||||||
char val[10];
|
|
||||||
output[sensor.name()] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is for a specific sensor
|
if (!strcmp(cmd, F_(entities))) {
|
||||||
// make a copy of the string command for parsing, and lowercase it
|
for (const auto & sensor : sensors_) {
|
||||||
char sensor_name[COMMAND_MAX_LENGTH] = {'\0'};
|
get_value_json(output[sensor.name()].to<JsonObject>(), sensor);
|
||||||
char * attribute_s = nullptr;
|
}
|
||||||
strlcpy(sensor_name, Helpers::toLower(cmd).c_str(), sizeof(sensor_name));
|
return true;
|
||||||
|
|
||||||
// check for a specific attribute to fetch instead of the complete record
|
|
||||||
char * breakp = strchr(sensor_name, '/');
|
|
||||||
if (breakp) {
|
|
||||||
*breakp = '\0';
|
|
||||||
attribute_s = breakp + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is for a specific sensor
|
||||||
|
const char * attribute_s = Command::get_attribute(cmd);
|
||||||
|
|
||||||
for (const auto & sensor : sensors_) {
|
for (const auto & sensor : sensors_) {
|
||||||
// match custom name or sensor ID
|
// match custom name or sensor ID
|
||||||
if (sensor_name == Helpers::toLower(sensor.name()) || sensor_name == Helpers::toLower(sensor.id())) {
|
if (cmd == Helpers::toLower(sensor.name()) || cmd == Helpers::toLower(sensor.id())) {
|
||||||
// add all the data elements
|
get_value_json(output, sensor);
|
||||||
addSensorJson(output, sensor);
|
return Command::set_attirbute(output, cmd, attribute_s);
|
||||||
// if we're filtering on an attribute, go find it
|
|
||||||
if (attribute_s) {
|
|
||||||
if (output.containsKey(attribute_s)) {
|
|
||||||
std::string data = output[attribute_s].as<std::string>();
|
|
||||||
output.clear();
|
|
||||||
output["api_data"] = data; // always as string
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return EMSESP::return_not_found(output, attribute_s, sensor_name); // not found
|
|
||||||
}
|
|
||||||
return true; // found a match, exit
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false; // not found
|
return false; // not found
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemperatureSensor::addSensorJson(JsonObject output, const Sensor & sensor) {
|
void TemperatureSensor::get_value_json(JsonObject output, const Sensor & sensor) {
|
||||||
output["id"] = sensor.id();
|
output["id"] = sensor.id();
|
||||||
output["name"] = sensor.name();
|
output["name"] = sensor.name();
|
||||||
if (Helpers::hasValue(sensor.temperature_c)) {
|
if (Helpers::hasValue(sensor.temperature_c)) {
|
||||||
|
|||||||
@@ -151,8 +151,8 @@ class TemperatureSensor {
|
|||||||
bool temperature_convert_complete();
|
bool temperature_convert_complete();
|
||||||
int16_t get_temperature_c(const uint8_t addr[]);
|
int16_t get_temperature_c(const uint8_t addr[]);
|
||||||
uint64_t get_id(const uint8_t addr[]);
|
uint64_t get_id(const uint8_t addr[]);
|
||||||
|
void get_value_json(JsonObject output, const Sensor & sensor);
|
||||||
void remove_ha_topic(const std::string & id);
|
void remove_ha_topic(const std::string & id);
|
||||||
void addSensorJson(JsonObject output, const Sensor & sensor);
|
|
||||||
|
|
||||||
std::vector<Sensor> sensors_; // our list of active sensors
|
std::vector<Sensor> sensors_; // our list of active sensors
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "3.7.0-dev.28"
|
#define EMSESP_APP_VERSION "3.7.0-dev.29"
|
||||||
|
|||||||
@@ -256,20 +256,6 @@ void WebCustomEntityService::show_values(JsonObject output) {
|
|||||||
|
|
||||||
// process json output for info/commands and value_info
|
// process json output for info/commands and value_info
|
||||||
bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd) {
|
bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd) {
|
||||||
// check of it a 'commands' command
|
|
||||||
if (Helpers::toLower(cmd) == F_(commands)) {
|
|
||||||
output[F_(info)] = Helpers::translated_word(FL_(info_cmd));
|
|
||||||
output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd));
|
|
||||||
output[F_(values)] = Helpers::translated_word(FL_(values_cmd));
|
|
||||||
|
|
||||||
for (const auto & entity : *customEntityItems_) {
|
|
||||||
if (entity.writeable) {
|
|
||||||
output[entity.name] = "custom entity";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if no custom entries, return empty json
|
// if no custom entries, return empty json
|
||||||
// even if we're looking for a specific entity
|
// even if we're looking for a specific entity
|
||||||
// https://github.com/emsesp/EMS-ESP32/issues/1297
|
// https://github.com/emsesp/EMS-ESP32/issues/1297
|
||||||
@@ -278,7 +264,7 @@ bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if it's info or values...
|
// if it's info or values...
|
||||||
if (strlen(cmd) == 0 || Helpers::toLower(cmd) == F_(values) || Helpers::toLower(cmd) == F_(info)) {
|
if (!strlen(cmd) || !strcmp(cmd, F_(values)) || !strcmp(cmd, F_(info))) {
|
||||||
// list all names
|
// list all names
|
||||||
for (const CustomEntityItem & entity : *customEntityItems_) {
|
for (const CustomEntityItem & entity : *customEntityItems_) {
|
||||||
render_value(output, entity);
|
render_value(output, entity);
|
||||||
@@ -286,59 +272,50 @@ bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char command_s[COMMAND_MAX_LENGTH];
|
// list all entities
|
||||||
strlcpy(command_s, Helpers::toLower(cmd).c_str(), sizeof(command_s));
|
if (!strcmp(cmd, F_(entities))) {
|
||||||
char * attribute_s = nullptr;
|
for (const auto & entity : *customEntityItems_) {
|
||||||
|
auto nest = output[entity.name].to<JsonObject>();
|
||||||
// check specific attribute to fetch instead of the complete record
|
get_value_json(nest, entity);
|
||||||
char * breakp = strchr(command_s, '/');
|
}
|
||||||
if (breakp) {
|
return true;
|
||||||
*breakp = '\0';
|
|
||||||
attribute_s = breakp + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// specific value info
|
||||||
|
const char * attribute_s = Command::get_attribute(cmd);
|
||||||
for (const auto & entity : *customEntityItems_) {
|
for (const auto & entity : *customEntityItems_) {
|
||||||
if (Helpers::toLower(entity.name) == command_s) {
|
if (Helpers::toLower(entity.name) == cmd) {
|
||||||
output["name"] = entity.name;
|
get_value_json(output, entity);
|
||||||
output["ram"] = entity.ram;
|
return Command::set_attirbute(output, cmd, attribute_s);
|
||||||
output["type"] = entity.value_type == DeviceValueType::BOOL ? "boolean" : entity.value_type == DeviceValueType::STRING ? "string" : F_(number);
|
|
||||||
if (entity.uom > 0) {
|
|
||||||
output["uom"] = EMSdevice::uom_to_string(entity.uom);
|
|
||||||
}
|
|
||||||
output["readable"] = true;
|
|
||||||
output["writeable"] = entity.writeable;
|
|
||||||
output["visible"] = true;
|
|
||||||
if (entity.ram == 0) {
|
|
||||||
output["device_id"] = Helpers::hextoa(entity.device_id);
|
|
||||||
output["type_id"] = Helpers::hextoa(entity.type_id);
|
|
||||||
output["offset"] = entity.offset;
|
|
||||||
if (entity.value_type != DeviceValueType::BOOL && entity.value_type != DeviceValueType::STRING) {
|
|
||||||
output["factor"] = entity.factor;
|
|
||||||
} else if (entity.value_type == DeviceValueType::STRING) {
|
|
||||||
output["bytes"] = (uint8_t)entity.factor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
render_value(output, entity, true); // create the "value" field
|
|
||||||
|
|
||||||
if (attribute_s) {
|
|
||||||
if (output.containsKey(attribute_s)) {
|
|
||||||
std::string data = output[attribute_s].as<std::string>();
|
|
||||||
output.clear();
|
|
||||||
output["api_data"] = data; // always as string
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return EMSESP::return_not_found(output, attribute_s, command_s); // not found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output.size()) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false; // not found
|
return false; // not found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// build the json for specific entity
|
||||||
|
void WebCustomEntityService::get_value_json(JsonObject output, const CustomEntityItem & entity) {
|
||||||
|
output["name"] = entity.name;
|
||||||
|
output["storage"] = entity.ram ? "ram" : "ems";
|
||||||
|
output["type"] = entity.value_type == DeviceValueType::BOOL ? "boolean" : entity.value_type == DeviceValueType::STRING ? "string" : F_(number);
|
||||||
|
if (entity.uom > 0) {
|
||||||
|
output["uom"] = EMSdevice::uom_to_string(entity.uom);
|
||||||
|
}
|
||||||
|
output["readable"] = true;
|
||||||
|
output["writeable"] = entity.writeable;
|
||||||
|
output["visible"] = true;
|
||||||
|
if (entity.ram == 0) {
|
||||||
|
output["device_id"] = Helpers::hextoa(entity.device_id);
|
||||||
|
output["type_id"] = Helpers::hextoa(entity.type_id);
|
||||||
|
output["offset"] = entity.offset;
|
||||||
|
if (entity.value_type != DeviceValueType::BOOL && entity.value_type != DeviceValueType::STRING) {
|
||||||
|
output["factor"] = entity.factor;
|
||||||
|
} else if (entity.value_type == DeviceValueType::STRING) {
|
||||||
|
output["bytes"] = (uint8_t)entity.factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render_value(output, entity, true); // create the "value" field
|
||||||
|
}
|
||||||
|
|
||||||
// publish single value
|
// publish single value
|
||||||
void WebCustomEntityService::publish_single(const CustomEntityItem & entity) {
|
void WebCustomEntityService::publish_single(const CustomEntityItem & entity) {
|
||||||
if (!Mqtt::enabled() || !Mqtt::publish_single()) {
|
if (!Mqtt::enabled() || !Mqtt::publish_single()) {
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ class WebCustomEntityService : public StatefulService<WebCustomEntity> {
|
|||||||
void publish(const bool force = false);
|
void publish(const bool force = false);
|
||||||
bool command_setvalue(const char * value, const int8_t id, const char * name);
|
bool command_setvalue(const char * value, const int8_t id, const char * name);
|
||||||
bool get_value_info(JsonObject output, const char * cmd);
|
bool get_value_info(JsonObject output, const char * cmd);
|
||||||
|
void get_value_json(JsonObject output, const CustomEntityItem & entity);
|
||||||
bool get_value(std::shared_ptr<const Telegram> telegram);
|
bool get_value(std::shared_ptr<const Telegram> telegram);
|
||||||
void fetch();
|
void fetch();
|
||||||
void render_value(JsonObject output, CustomEntityItem entity, const bool useVal = false, const bool web = false, const bool add_uom = false);
|
void render_value(JsonObject output, CustomEntityItem entity, const bool useVal = false, const bool web = false, const bool add_uom = false);
|
||||||
|
|||||||
@@ -51,9 +51,9 @@ void WebScheduler::read(WebScheduler & webScheduler, JsonObject root) {
|
|||||||
for (const ScheduleItem & scheduleItem : webScheduler.scheduleItems) {
|
for (const ScheduleItem & scheduleItem : webScheduler.scheduleItems) {
|
||||||
JsonObject si = schedule.add<JsonObject>();
|
JsonObject si = schedule.add<JsonObject>();
|
||||||
si["id"] = counter++; // id is only used to render the table and must be unique
|
si["id"] = counter++; // id is only used to render the table and must be unique
|
||||||
si["active"] = scheduleItem.flags ? scheduleItem.active : false;
|
|
||||||
si["flags"] = scheduleItem.flags;
|
si["flags"] = scheduleItem.flags;
|
||||||
si["time"] = scheduleItem.time;
|
si["active"] = scheduleItem.flags != SCHEDULEFLAG_SCHEDULE_IMMEDIATE ? scheduleItem.active : false;
|
||||||
|
si["time"] = scheduleItem.flags != SCHEDULEFLAG_SCHEDULE_IMMEDIATE ? scheduleItem.time : "";
|
||||||
si["cmd"] = scheduleItem.cmd;
|
si["cmd"] = scheduleItem.cmd;
|
||||||
si["value"] = scheduleItem.value;
|
si["value"] = scheduleItem.value;
|
||||||
si["name"] = scheduleItem.name;
|
si["name"] = scheduleItem.name;
|
||||||
@@ -76,7 +76,7 @@ StateUpdateResult WebScheduler::update(JsonObject root, WebScheduler & webSchedu
|
|||||||
auto si = ScheduleItem();
|
auto si = ScheduleItem();
|
||||||
si.active = schedule["active"];
|
si.active = schedule["active"];
|
||||||
si.flags = schedule["flags"];
|
si.flags = schedule["flags"];
|
||||||
si.time = schedule["time"].as<std::string>();
|
si.time = si.flags == SCHEDULEFLAG_SCHEDULE_IMMEDIATE ? "" : schedule["time"].as<std::string>();
|
||||||
si.cmd = schedule["cmd"].as<std::string>();
|
si.cmd = schedule["cmd"].as<std::string>();
|
||||||
si.value = schedule["value"].as<std::string>();
|
si.value = schedule["value"].as<std::string>();
|
||||||
si.name = schedule["name"].as<std::string>();
|
si.name = schedule["name"].as<std::string>();
|
||||||
@@ -132,26 +132,11 @@ bool WebSchedulerService::command_setvalue(const char * value, const int8_t id,
|
|||||||
|
|
||||||
// process json output for info/commands and value_info
|
// process json output for info/commands and value_info
|
||||||
bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) {
|
bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) {
|
||||||
// check of it a 'commands' command
|
|
||||||
if (Helpers::toLower(cmd) == F_(commands)) {
|
|
||||||
output[F_(info)] = Helpers::translated_word(FL_(info_cmd));
|
|
||||||
output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd));
|
|
||||||
output[F_(values)] = Helpers::translated_word(FL_(values_cmd));
|
|
||||||
|
|
||||||
for (const ScheduleItem & scheduleItem : *scheduleItems_) {
|
|
||||||
if (!scheduleItem.name.empty()) {
|
|
||||||
output[scheduleItem.name] = "activate schedule";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scheduleItems_->size() == 0) {
|
if (scheduleItems_->size() == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(cmd) == 0 || Helpers::toLower(cmd) == F_(values) || Helpers::toLower(cmd) == F_(info)) {
|
if (!strlen(cmd) || !strcmp(cmd, F_(values)) || !strcmp(cmd, F_(info))) {
|
||||||
// list all names
|
// list all names
|
||||||
for (const ScheduleItem & scheduleItem : *scheduleItems_) {
|
for (const ScheduleItem & scheduleItem : *scheduleItems_) {
|
||||||
if (!scheduleItem.name.empty()) {
|
if (!scheduleItem.name.empty()) {
|
||||||
@@ -165,68 +150,59 @@ bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char command_s[COMMAND_MAX_LENGTH];
|
const char * attribute_s = Command::get_attribute(cmd);
|
||||||
strlcpy(command_s, Helpers::toLower(cmd).c_str(), sizeof(command_s));
|
|
||||||
char * attribute_s = nullptr;
|
|
||||||
|
|
||||||
// check specific attribute to fetch instead of the complete record
|
if (!strcmp(cmd, F_(entities))) {
|
||||||
char * breakp = strchr(command_s, '/');
|
uint8_t i = 0;
|
||||||
if (breakp) {
|
char name[30];
|
||||||
*breakp = '\0';
|
for (const ScheduleItem & scheduleItem : *scheduleItems_) {
|
||||||
attribute_s = breakp + 1;
|
strlcpy(name, scheduleItem.name == "" ? Helpers::smallitoa(name, i++) : scheduleItem.name.c_str(), sizeof(name));
|
||||||
|
get_value_json(output[name].to<JsonObject>(), scheduleItem);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const ScheduleItem & scheduleItem : *scheduleItems_) {
|
for (const ScheduleItem & scheduleItem : *scheduleItems_) {
|
||||||
if (Helpers::toLower(scheduleItem.name) == command_s) {
|
if (Helpers::toLower(scheduleItem.name) == cmd) {
|
||||||
output["name"] = scheduleItem.name;
|
get_value_json(output, scheduleItem);
|
||||||
output["type"] = "boolean";
|
return Command::set_attirbute(output, cmd, attribute_s);
|
||||||
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
|
||||||
output["value"] = scheduleItem.active;
|
|
||||||
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
|
||||||
output["value"] = scheduleItem.active ? 1 : 0;
|
|
||||||
} else {
|
|
||||||
char result[12];
|
|
||||||
output["value"] = Helpers::render_boolean(result, scheduleItem.active);
|
|
||||||
}
|
|
||||||
if (scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_CONDITION) {
|
|
||||||
output["condition"] = scheduleItem.time;
|
|
||||||
} else if (scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_ONCHANGE) {
|
|
||||||
output["onchange"] = scheduleItem.time;
|
|
||||||
} else if (scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_TIMER) {
|
|
||||||
output["timer"] = scheduleItem.time;
|
|
||||||
} else if (scheduleItem.flags != 0) {
|
|
||||||
output["time"] = scheduleItem.time;
|
|
||||||
}
|
|
||||||
output["command"] = scheduleItem.cmd;
|
|
||||||
output["cmd_data"] = scheduleItem.value;
|
|
||||||
output["readable"] = true;
|
|
||||||
output["writeable"] = true;
|
|
||||||
output["visible"] = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attribute_s) {
|
|
||||||
if (output.containsKey(attribute_s)) {
|
|
||||||
std::string data = output[attribute_s].as<std::string>();
|
|
||||||
output.clear();
|
|
||||||
output["api_data"] = data; // always as a string
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return EMSESP::return_not_found(output, attribute_s, command_s); // not found
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output.size()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // not found
|
return false; // not found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// build the json for specific entity
|
||||||
|
void WebSchedulerService::get_value_json(JsonObject output, const ScheduleItem & scheduleItem) {
|
||||||
|
output["name"] = scheduleItem.name;
|
||||||
|
output["type"] = "boolean";
|
||||||
|
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
||||||
|
output["value"] = scheduleItem.active;
|
||||||
|
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
||||||
|
output["value"] = scheduleItem.active ? 1 : 0;
|
||||||
|
} else {
|
||||||
|
char result[12];
|
||||||
|
output["value"] = Helpers::render_boolean(result, scheduleItem.active);
|
||||||
|
}
|
||||||
|
if (scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_CONDITION) {
|
||||||
|
output["condition"] = scheduleItem.time;
|
||||||
|
} else if (scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_ONCHANGE) {
|
||||||
|
output["onchange"] = scheduleItem.time;
|
||||||
|
} else if (scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_TIMER) {
|
||||||
|
output["timer"] = scheduleItem.time;
|
||||||
|
} else if (scheduleItem.flags != SCHEDULEFLAG_SCHEDULE_IMMEDIATE) {
|
||||||
|
output["time"] = scheduleItem.time;
|
||||||
|
}
|
||||||
|
output["command"] = scheduleItem.cmd;
|
||||||
|
output["cmd_data"] = scheduleItem.value;
|
||||||
|
bool hasName = scheduleItem.name != "";
|
||||||
|
output["readable"] = hasName;
|
||||||
|
output["writeable"] = hasName;
|
||||||
|
output["visible"] = hasName;
|
||||||
|
}
|
||||||
|
|
||||||
// publish single value
|
// publish single value
|
||||||
void WebSchedulerService::publish_single(const char * name, const bool state) {
|
void WebSchedulerService::publish_single(const char * name, const bool state) {
|
||||||
if (!Mqtt::enabled() || !Mqtt::publish_single() || name == nullptr || name[0] == '\0') {
|
if (!Mqtt::enabled() || !Mqtt::publish_single() || name == nullptr || name[0] == '\0') {
|
||||||
@@ -346,6 +322,8 @@ bool WebSchedulerService::has_commands() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "shuntingYard.hpp"
|
||||||
|
|
||||||
// execute scheduled command
|
// execute scheduled command
|
||||||
bool WebSchedulerService::command(const char * name, const std::string & command, const std::string & data) {
|
bool WebSchedulerService::command(const char * name, const std::string & command, const std::string & data) {
|
||||||
std::string cmd = Helpers::toLower(command);
|
std::string cmd = Helpers::toLower(command);
|
||||||
@@ -355,13 +333,19 @@ bool WebSchedulerService::command(const char * name, const std::string & command
|
|||||||
// shelly(get): http://<shellyIP>/relais/0?turn=on
|
// shelly(get): http://<shellyIP>/relais/0?turn=on
|
||||||
// parse json
|
// parse json
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
if (DeserializationError::Ok == deserializeJson(doc, cmd)) {
|
if (deserializeJson(doc, cmd) == DeserializationError::Ok) {
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
int httpResult = 0;
|
int httpResult = 0;
|
||||||
String url = doc["url"];
|
String url = doc["url"] | "";
|
||||||
if (http.begin(url)) {
|
// for a GET with parameters replace commands with values
|
||||||
// It's an HTTP call
|
auto q = url.indexOf('?');
|
||||||
|
if (q != -1) {
|
||||||
|
auto s = url.substring(q + 1);
|
||||||
|
std::string v = s.c_str();
|
||||||
|
commands(v, false);
|
||||||
|
url.replace(s, v.c_str());
|
||||||
|
}
|
||||||
|
if (url.startsWith("http") && http.begin(url)) {
|
||||||
// add any given headers
|
// add any given headers
|
||||||
for (JsonPair p : doc["header"].as<JsonObject>()) {
|
for (JsonPair p : doc["header"].as<JsonObject>()) {
|
||||||
http.addHeader(p.key().c_str(), p.value().as<String>().c_str());
|
http.addHeader(p.key().c_str(), p.value().as<String>().c_str());
|
||||||
@@ -448,8 +432,6 @@ bool WebSchedulerService::onChange(const char * cmd) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "shuntingYard.hpp"
|
|
||||||
|
|
||||||
// handle condition schedules, parse string stored in schedule.time field
|
// handle condition schedules, parse string stored in schedule.time field
|
||||||
void WebSchedulerService::condition() {
|
void WebSchedulerService::condition() {
|
||||||
for (ScheduleItem & scheduleItem : *scheduleItems_) {
|
for (ScheduleItem & scheduleItem : *scheduleItems_) {
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ class WebSchedulerService : public StatefulService<WebScheduler> {
|
|||||||
bool has_commands();
|
bool has_commands();
|
||||||
bool command_setvalue(const char * value, const int8_t id, const char * name);
|
bool command_setvalue(const char * value, const int8_t id, const char * name);
|
||||||
bool get_value_info(JsonObject output, const char * cmd);
|
bool get_value_info(JsonObject output, const char * cmd);
|
||||||
|
void get_value_json(JsonObject output, const ScheduleItem & scheduleItem);
|
||||||
void ha_reset() {
|
void ha_reset() {
|
||||||
ha_registered_ = false;
|
ha_registered_ = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
class Token {
|
class Token {
|
||||||
public:
|
public:
|
||||||
enum class Type {
|
enum class Type : uint8_t {
|
||||||
Unknown,
|
Unknown,
|
||||||
Number,
|
Number,
|
||||||
String,
|
String,
|
||||||
@@ -332,12 +332,13 @@ bool isnum(const std::string & s) {
|
|||||||
|
|
||||||
|
|
||||||
// replace commands like "<device>/<hc>/<cmd>" with its value"
|
// replace commands like "<device>/<hc>/<cmd>" with its value"
|
||||||
std::string commands(std::string & expr) {
|
std::string commands(std::string & expr, bool quotes = true) {
|
||||||
for (uint8_t device = 0; device < emsesp::EMSdevice::DeviceType::UNKNOWN; device++) {
|
for (uint8_t device = 0; device < emsesp::EMSdevice::DeviceType::UNKNOWN; device++) {
|
||||||
const char * d = emsesp::EMSdevice::device_type_2_device_name(device);
|
const char * d = emsesp::EMSdevice::device_type_2_device_name(device);
|
||||||
auto f = expr.find(d);
|
auto f = expr.find(d);
|
||||||
while (f != std::string::npos) {
|
while (f != std::string::npos) {
|
||||||
auto e = expr.find_first_of(")=<>|&+-*!", f);
|
// entity names are alphanumeric or _
|
||||||
|
auto e = expr.find_first_not_of("/._abcdefghijklmnopqrstuvwxyz0123456789", f);
|
||||||
if (e == std::string::npos) {
|
if (e == std::string::npos) {
|
||||||
e = expr.length();
|
e = expr.length();
|
||||||
}
|
}
|
||||||
@@ -361,7 +362,7 @@ std::string commands(std::string & expr) {
|
|||||||
emsesp::Command::process(cmd_s.c_str(), true, input, output);
|
emsesp::Command::process(cmd_s.c_str(), true, input, output);
|
||||||
if (output.containsKey("api_data")) {
|
if (output.containsKey("api_data")) {
|
||||||
std::string data = output["api_data"].as<std::string>();
|
std::string data = output["api_data"].as<std::string>();
|
||||||
if (!isnum(data)) {
|
if (!isnum(data) && quotes) {
|
||||||
data.insert(data.begin(), '"');
|
data.insert(data.begin(), '"');
|
||||||
data.insert(data.end(), '"');
|
data.insert(data.end(), '"');
|
||||||
}
|
}
|
||||||
@@ -596,7 +597,7 @@ std::string compute(const std::string & expr) {
|
|||||||
auto expr_new = emsesp::Helpers::toLower(expr);
|
auto expr_new = emsesp::Helpers::toLower(expr);
|
||||||
|
|
||||||
// search json with url:
|
// search json with url:
|
||||||
auto f = expr_new.find_first_of("{");
|
auto f = expr_new.find_first_of('{');
|
||||||
while (f != std::string::npos) {
|
while (f != std::string::npos) {
|
||||||
auto e = f + 1;
|
auto e = f + 1;
|
||||||
for (uint8_t i = 1; i > 0; e++) {
|
for (uint8_t i = 1; i > 0; e++) {
|
||||||
@@ -612,8 +613,8 @@ std::string compute(const std::string & expr) {
|
|||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
if (DeserializationError::Ok == deserializeJson(doc, cmd)) {
|
if (DeserializationError::Ok == deserializeJson(doc, cmd)) {
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
String url = doc["url"];
|
String url = doc["url"] | "";
|
||||||
if (http.begin(url)) {
|
if (url.startsWith("http") && http.begin(url)) {
|
||||||
int httpResult = 0;
|
int httpResult = 0;
|
||||||
for (JsonPair p : doc["header"].as<JsonObject>()) {
|
for (JsonPair p : doc["header"].as<JsonObject>()) {
|
||||||
http.addHeader(p.key().c_str(), p.value().as<std::string>().c_str());
|
http.addHeader(p.key().c_str(), p.value().as<std::string>().c_str());
|
||||||
@@ -647,20 +648,22 @@ std::string compute(const std::string & expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// positions: q-questionmark, c-colon
|
// positions: q-questionmark, c-colon
|
||||||
auto q = expr_new.find_first_of("?");
|
auto q = expr_new.find_first_of('?');
|
||||||
while (q != std::string::npos) {
|
while (q != std::string::npos) {
|
||||||
// find corresponding colon
|
// find corresponding colon
|
||||||
auto c1 = expr_new.find_first_of(":", q + 1);
|
auto c1 = expr_new.find_first_of(':', q + 1);
|
||||||
auto q1 = expr_new.find_first_of("?", q + 1);
|
auto q1 = expr_new.find_first_of('?', q + 1);
|
||||||
while (q1 < c1 && q1 != std::string::npos && c1 != std::string::npos) {
|
while (q1 < c1 && q1 != std::string::npos && c1 != std::string::npos) {
|
||||||
q1 = expr_new.find_first_of("?", q1 + 1);
|
q1 = expr_new.find_first_of('?', q1 + 1);
|
||||||
c1 = expr_new.find_first_of(":", c1 + 1);
|
c1 = expr_new.find_first_of(':', c1 + 1);
|
||||||
}
|
}
|
||||||
if (c1 == std::string::npos) {
|
if (c1 == std::string::npos) {
|
||||||
return ""; // error: missing colon
|
return ""; // error: missing colon
|
||||||
}
|
}
|
||||||
std::string cond = calculate(expr_new.substr(0, q));
|
std::string cond = calculate(expr_new.substr(0, q));
|
||||||
if (cond[0] == '1') {
|
if (cond.length() == 0) {
|
||||||
|
return "";
|
||||||
|
} else if (cond[0] == '1') {
|
||||||
expr_new.erase(c1); // remove second expression after colon
|
expr_new.erase(c1); // remove second expression after colon
|
||||||
expr_new.erase(0, q + 1); // remove condition before questionmark
|
expr_new.erase(0, q + 1); // remove condition before questionmark
|
||||||
} else if (cond[0] == '0') {
|
} else if (cond[0] == '0') {
|
||||||
@@ -668,7 +671,7 @@ std::string compute(const std::string & expr) {
|
|||||||
} else {
|
} else {
|
||||||
return ""; // error
|
return ""; // error
|
||||||
}
|
}
|
||||||
q = expr_new.find_first_of("?"); // search next instance
|
q = expr_new.find_first_of('?'); // search next instance
|
||||||
}
|
}
|
||||||
|
|
||||||
return calculate(expr_new);
|
return calculate(expr_new);
|
||||||
|
|||||||
Reference in New Issue
Block a user