Merge pull request #1428 from MichaelDvP/dev2x

latest changes
This commit is contained in:
Proddy
2023-11-15 12:08:18 +01:00
committed by GitHub
45 changed files with 1201 additions and 1039 deletions

View File

@@ -9,16 +9,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Github Releases To Discord
uses: SethCohen/github-releases-to-discord@v1.13.1
with:
webhook_url: ${{ secrets.WEBHOOK_URL }}
color: "2105893"
username: "Release Changelog"
avatar_url: "https://cdn.discordapp.com/icons/816637840644505620/0b14718532d855c452903851b4f0c9a2.png"
content: "||@everyone||"
footer_title: "Changelog"
footer_icon_url: "https://cdn.discordapp.com/icons/816637840644505620/0b14718532d855c452903851b4f0c9a2.png"
color: '2105893'
username: 'Release Changelog'
avatar_url: 'https://cdn.discordapp.com/icons/816637840644505620/0b14718532d855c452903851b4f0c9a2.png'
content: '||@everyone||'
footer_title: 'Changelog'
footer_icon_url: 'https://cdn.discordapp.com/icons/816637840644505620/0b14718532d855c452903851b4f0c9a2.png'
footer_timestamp: true

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.11'

View File

@@ -14,7 +14,7 @@ jobs:
env:
BUILD_WRAPPER_OUT_DIR: bw-output
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Install sonar-scanner and build-wrapper

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.11'

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.11'

47
.vscode/settings.json vendored
View File

@@ -10,7 +10,6 @@
"eslint.nodePath": "interface/.yarn/sdks",
"eslint.workingDirectories": ["interface"],
"prettier.prettierPath": "",
"typescript.tsdk": "interface/.yarn/sdks/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"files.associations": {
"*.tsx": "typescriptreact",
@@ -27,7 +26,51 @@
"type_traits": "cpp",
"utility": "cpp",
"string": "cpp",
"string_view": "cpp"
"string_view": "cpp",
"atomic": "cpp",
"bitset": "cpp",
"cctype": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"condition_variable": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"list": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"iterator": "cpp",
"map": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"random": "cpp",
"set": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"thread": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp"
},
"todo-tree.filtering.excludeGlobs": [
"**/vendor/**",

View File

@@ -4,7 +4,7 @@
## **IMPORTANT! BREAKING CHANGES**
Writeable Text entities have moved from type `sensor` to `text` in Home Assistant to make them also editable within an HA dashboard. Examples are `datetime`, `holidays`, `switchtime`, `vacations`, `maintenancedate`...). You will need to manually remove any old discovery topics from your MQTT broker using an application like MQTT Explorer.
Writeable Text entities have moved from type `sensor` to `text` in Home Assistant to make them also editable within an HA dashboard. Examples are `datetime`, `holidays`, `switchtime`, `vacations`, `maintenancedate`... You will need to manually remove any old discovery topics from your MQTT broker using an application like MQTT Explorer.
## Added
@@ -19,12 +19,15 @@ Writeable Text entities have moved from type `sensor` to `text` in Home Assistan
- heatpump high res energy counters [#1348, #1349. #1350](https://github.com/emsesp/EMS-ESP32/issues/1348)
- optional bssid in network settings
- extension module EM100 [#1315](https://github.com/emsesp/EMS-ESP32/discussions/1315)
- digital_out with new options for polarity and startup state
- Added 'system allvalues' command that dumps all the EMS device values, plus sensors and any custom entities
## Fixed
- remove command `remoteseltemp`, thermostat accept it only from remote thermostat
- shower_data MQTT payload contains the timestamp [#1329](https://github.com/emsesp/EMS-ESP32/issues/1329)
- fixed helper text in Web Device Entity dialog box for numerical ranges
- MQTT base with paths not working in HA [#1393](https://github.com/emsesp/EMS-ESP32/issues/1393)
## Changed

File diff suppressed because one or more lines are too long

View File

@@ -4,4 +4,4 @@ enableGlobalCache: false
nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-4.0.1.cjs
yarnPath: .yarn/releases/yarn-4.0.2.cjs

View File

@@ -23,8 +23,8 @@
"@babel/core": "^7.23.3",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.14.16",
"@mui/material": "^5.14.17",
"@mui/icons-material": "^5.14.18",
"@mui/material": "^5.14.18",
"@table-library/react-table-library": "4.1.7",
"@types/imagemin": "^8.0.4",
"@types/lodash-es": "^4.17.11",
@@ -41,7 +41,7 @@
"react": "latest",
"react-dom": "latest",
"react-dropzone": "^14.2.3",
"react-icons": "^4.11.0",
"react-icons": "^4.12.0",
"react-router-dom": "^6.18.0",
"react-toastify": "^9.1.3",
"sockette": "^2.0.6",
@@ -51,8 +51,8 @@
"devDependencies": {
"@preact/compat": "^17.1.2",
"@preact/preset-vite": "^2.6.0",
"@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/parser": "^6.10.0",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.11.0",
"concurrently": "^8.2.2",
"eslint": "^8.53.0",
"eslint-config-airbnb": "^19.0.4",
@@ -65,13 +65,13 @@
"eslint-plugin-prettier": "alpha",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"preact": "^10.18.2",
"prettier": "^3.0.3",
"preact": "^10.19.2",
"prettier": "^3.1.0",
"rollup-plugin-visualizer": "^5.9.2",
"terser": "^5.24.0",
"vite": "^4.5.0",
"vite-plugin-imagemin": "^0.6.1",
"vite-tsconfig-paths": "^4.2.1"
},
"packageManager": "yarn@4.0.1"
"packageManager": "yarn@4.0.2"
}

View File

@@ -350,7 +350,7 @@ const DashboardDevices: FC = () => {
const deviceValueDialogSave = async (devicevalue: DeviceValue) => {
const id = Number(device_select.state.id);
await writeDeviceValue({ id, devicevalue })
await writeDeviceValue({ id, c: devicevalue.c, v: devicevalue.v })
.then(() => {
toast.success(LL.WRITE_CMD_SENT());
})

View File

@@ -772,15 +772,15 @@ __metadata:
languageName: node
linkType: hard
"@floating-ui/react-dom@npm:^2.0.2":
version: 2.0.2
resolution: "@floating-ui/react-dom@npm:2.0.2"
"@floating-ui/react-dom@npm:^2.0.4":
version: 2.0.4
resolution: "@floating-ui/react-dom@npm:2.0.4"
dependencies:
"@floating-ui/dom": "npm:^1.5.1"
peerDependencies:
react: ">=16.8.0"
react-dom: ">=16.8.0"
checksum: 63a26f3c36f00a2bdede202cb7a3be74b3c6599463c0a069745f6aed3181a33ce72936158209f6fd1c284d85fd494aa656e6cbc4266c096f3189ce1c13f83dfe
checksum: 4240a718502c797fd2e174cd06dcd7321a6eda9c8966dbaf61864b9e16445e95649a59bfe7c19ee13f68c11f3693724d7970c7e618089a3d3915bd343639cfae
languageName: node
linkType: hard
@@ -882,14 +882,14 @@ __metadata:
languageName: node
linkType: hard
"@mui/base@npm:5.0.0-beta.23":
version: 5.0.0-beta.23
resolution: "@mui/base@npm:5.0.0-beta.23"
"@mui/base@npm:5.0.0-beta.24":
version: 5.0.0-beta.24
resolution: "@mui/base@npm:5.0.0-beta.24"
dependencies:
"@babel/runtime": "npm:^7.23.2"
"@floating-ui/react-dom": "npm:^2.0.2"
"@mui/types": "npm:^7.2.8"
"@mui/utils": "npm:^5.14.17"
"@floating-ui/react-dom": "npm:^2.0.4"
"@mui/types": "npm:^7.2.9"
"@mui/utils": "npm:^5.14.18"
"@popperjs/core": "npm:^2.11.8"
clsx: "npm:^2.0.0"
prop-types: "npm:^15.8.1"
@@ -900,20 +900,20 @@ __metadata:
peerDependenciesMeta:
"@types/react":
optional: true
checksum: 5219132b1e4ba027736cb8f2f22ecccc69a883016679f00db1cf79f82614b0cc6466b9f437bab67c043041ee9d5e01d84249896c2c8771a045da7e60639d4b44
checksum: 65d8a428d7e863885d5d5d6513ffa64982ebd7bd3a809b3024f669b907796c94a5d19ebac42ef383277acaccf30af3158c91f65c69fb0e7b2ddab925fc3293dd
languageName: node
linkType: hard
"@mui/core-downloads-tracker@npm:^5.14.17":
version: 5.14.17
resolution: "@mui/core-downloads-tracker@npm:5.14.17"
checksum: dfa5ffe6e370ad9490cbe03b964967271462f7fb74c09e29e6fe09042f15ddec9a976f5131ce01b003dba1d66b70a6af026b0a1929db50124c783d7df45b06b6
"@mui/core-downloads-tracker@npm:^5.14.18":
version: 5.14.18
resolution: "@mui/core-downloads-tracker@npm:5.14.18"
checksum: 3d367797282e4b93eacee997667d62bc4eeac979e9664724e9db8d632278d8629f2a141894cf53d706f1d2a9f19965bffe2858aa2bc9833722e674cd560b896e
languageName: node
linkType: hard
"@mui/icons-material@npm:^5.14.16":
version: 5.14.16
resolution: "@mui/icons-material@npm:5.14.16"
"@mui/icons-material@npm:^5.14.18":
version: 5.14.18
resolution: "@mui/icons-material@npm:5.14.18"
dependencies:
"@babel/runtime": "npm:^7.23.2"
peerDependencies:
@@ -923,20 +923,20 @@ __metadata:
peerDependenciesMeta:
"@types/react":
optional: true
checksum: e4dc4071eb68b06c54f25733cd00c749a18c69c16186defc467db5599ea46c32bfb8cc64e40b208e4b85f9186ab8b2e76f0553eac98727e8446c81461d665f58
checksum: 20da1445f033edf017d7d447c74fb27e90d4a9f3a631f617252a4806b69364792e01aa7010939c90e37d8ce7adf4218ec27066bd8ec0db40295f64365fd18a5e
languageName: node
linkType: hard
"@mui/material@npm:^5.14.17":
version: 5.14.17
resolution: "@mui/material@npm:5.14.17"
"@mui/material@npm:^5.14.18":
version: 5.14.18
resolution: "@mui/material@npm:5.14.18"
dependencies:
"@babel/runtime": "npm:^7.23.2"
"@mui/base": "npm:5.0.0-beta.23"
"@mui/core-downloads-tracker": "npm:^5.14.17"
"@mui/system": "npm:^5.14.17"
"@mui/types": "npm:^7.2.8"
"@mui/utils": "npm:^5.14.17"
"@mui/base": "npm:5.0.0-beta.24"
"@mui/core-downloads-tracker": "npm:^5.14.18"
"@mui/system": "npm:^5.14.18"
"@mui/types": "npm:^7.2.9"
"@mui/utils": "npm:^5.14.18"
"@types/react-transition-group": "npm:^4.4.8"
clsx: "npm:^2.0.0"
csstype: "npm:^3.1.2"
@@ -956,16 +956,16 @@ __metadata:
optional: true
"@types/react":
optional: true
checksum: 498797747d532f3909611aac04b07ac4067a70d282a238b7cfbebb1cf2004df40c51c10d9c5b1786916dc4c4c1cd722880aad3200c70ba13fc2610bf7bb72bab
checksum: 50c5ddbd8e6e39aa4cf904ea7061a1c9d91d906baa7b7626f3db22338872972bac8d176002e613f79e9171969e898ca268c024a143bc120f05e750035b25a8cb
languageName: node
linkType: hard
"@mui/private-theming@npm:^5.14.17":
version: 5.14.17
resolution: "@mui/private-theming@npm:5.14.17"
"@mui/private-theming@npm:^5.14.18":
version: 5.14.18
resolution: "@mui/private-theming@npm:5.14.18"
dependencies:
"@babel/runtime": "npm:^7.23.2"
"@mui/utils": "npm:^5.14.17"
"@mui/utils": "npm:^5.14.18"
prop-types: "npm:^15.8.1"
peerDependencies:
"@types/react": ^17.0.0 || ^18.0.0
@@ -973,13 +973,13 @@ __metadata:
peerDependenciesMeta:
"@types/react":
optional: true
checksum: a02bcf41de4d79f704b415e2d4346e84eb138e773a6ca622017d5631e25689eba2c860637cb8c8f0fd71032c52f2889a1b2ae33975929da77aca7cfe229aaf6b
checksum: cb2ae253c7aba571ae838b5c886f74cde0e4b3df49ed1d776ee355e87fc28efe6a23367d713ac6979378049aa67d3bffb65cba421818a11b65d4518742a8711b
languageName: node
linkType: hard
"@mui/styled-engine@npm:^5.14.17":
version: 5.14.17
resolution: "@mui/styled-engine@npm:5.14.17"
"@mui/styled-engine@npm:^5.14.18":
version: 5.14.18
resolution: "@mui/styled-engine@npm:5.14.18"
dependencies:
"@babel/runtime": "npm:^7.23.2"
"@emotion/cache": "npm:^11.11.0"
@@ -994,19 +994,19 @@ __metadata:
optional: true
"@emotion/styled":
optional: true
checksum: 0a86748dc45caffc7effab8e73dde31962f2f7b0cce063591e9ce1c7c096b1c02eb35cb29090ea23913a4e600d3bad4547af6ce63a8c922991cb01cf5fb2d0c7
checksum: 305128a623339cf0bb563cebb822363c19d9337221e7894c00130680e5b7a818c81a6df1d1f036a97641ce0f1bc336a0328ce3e2787d2dee1ff73bf0718aca63
languageName: node
linkType: hard
"@mui/system@npm:^5.14.17":
version: 5.14.17
resolution: "@mui/system@npm:5.14.17"
"@mui/system@npm:^5.14.18":
version: 5.14.18
resolution: "@mui/system@npm:5.14.18"
dependencies:
"@babel/runtime": "npm:^7.23.2"
"@mui/private-theming": "npm:^5.14.17"
"@mui/styled-engine": "npm:^5.14.17"
"@mui/types": "npm:^7.2.8"
"@mui/utils": "npm:^5.14.17"
"@mui/private-theming": "npm:^5.14.18"
"@mui/styled-engine": "npm:^5.14.18"
"@mui/types": "npm:^7.2.9"
"@mui/utils": "npm:^5.14.18"
clsx: "npm:^2.0.0"
csstype: "npm:^3.1.2"
prop-types: "npm:^15.8.1"
@@ -1022,28 +1022,28 @@ __metadata:
optional: true
"@types/react":
optional: true
checksum: 351040cfd4a698328e050397a8895e24ad93c37a2a72d6f8f4c8a652e43315a8ada26cc2b5dfda93b8cdf61b6e481474a7af7948d2752351184b99079f2f9c7b
checksum: 4e9a47342fc928506272a2b68d9f2592bbbc5a9f88176ee03b6050066f18f7d2df11355796d7ee5ef556d12779fe9e4d20520d0a0f1e24e2696193e4c13ce580
languageName: node
linkType: hard
"@mui/types@npm:^7.2.8":
version: 7.2.8
resolution: "@mui/types@npm:7.2.8"
"@mui/types@npm:^7.2.9":
version: 7.2.9
resolution: "@mui/types@npm:7.2.9"
peerDependencies:
"@types/react": ^17.0.0 || ^18.0.0
peerDependenciesMeta:
"@types/react":
optional: true
checksum: 47be368669d5bb5e43458d93d20c7e9f4f6ca2fec2bc7b541dcc7b59a0168ac6bfa6b88f51f5ad1d044c07a1fb247b803683bcaf969052aab559f25f11727ba5
checksum: f8a21c5a375373e03b9e7ef0c081fbcbfffb8e743955280d360ac37990448a587ac101b82e35539102ea46c994d23475c80be236b36deaabf38acc5e48c2bdef
languageName: node
linkType: hard
"@mui/utils@npm:^5.14.17":
version: 5.14.17
resolution: "@mui/utils@npm:5.14.17"
"@mui/utils@npm:^5.14.18":
version: 5.14.18
resolution: "@mui/utils@npm:5.14.18"
dependencies:
"@babel/runtime": "npm:^7.23.2"
"@types/prop-types": "npm:^15.7.9"
"@types/prop-types": "npm:^15.7.10"
prop-types: "npm:^15.8.1"
react-is: "npm:^18.2.0"
peerDependencies:
@@ -1052,7 +1052,7 @@ __metadata:
peerDependenciesMeta:
"@types/react":
optional: true
checksum: 98c8b38075a2e3c2882eee8dccbbd5648747af63688ff2200acb63a7c3589864b3ea8bc067380bb3e4f46b09cec8b0fa144309644c0b9166bf194f76d89bc6fe
checksum: abc699aab138a5650f7ba5f4c87511802bc35b8307331a9024d2d1769520a63ccccf952097ab8943104d6304107836cba580a7acbcc0138c263f77f97b1b3dd0
languageName: node
linkType: hard
@@ -1410,13 +1410,20 @@ __metadata:
languageName: node
linkType: hard
"@types/prop-types@npm:*, @types/prop-types@npm:^15.7.9":
"@types/prop-types@npm:*":
version: 15.7.9
resolution: "@types/prop-types@npm:15.7.9"
checksum: c7591d3ff7593e243908a07e1d3e2bb6e8879008af5800d8378115a90d0fdf669a1cae72a6d7f69e59c4fa7bb4c8ed61f6ebc1c520fe110c6f2b03ac02414072
languageName: node
linkType: hard
"@types/prop-types@npm:^15.7.10":
version: 15.7.10
resolution: "@types/prop-types@npm:15.7.10"
checksum: 39ecc2d9e439ed16b32937a08d98b84ed4a70f53bcd52c8564c0cd7a36fe1004ca83a1fb94b13c1b7a5c048760f06445c3c6a91a6972c8eff652c0b50c9424b1
languageName: node
linkType: hard
"@types/react-dom@npm:^18.2.15":
version: 18.2.15
resolution: "@types/react-dom@npm:18.2.15"
@@ -1510,15 +1517,15 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/eslint-plugin@npm:^6.10.0":
version: 6.10.0
resolution: "@typescript-eslint/eslint-plugin@npm:6.10.0"
"@typescript-eslint/eslint-plugin@npm:^6.11.0":
version: 6.11.0
resolution: "@typescript-eslint/eslint-plugin@npm:6.11.0"
dependencies:
"@eslint-community/regexpp": "npm:^4.5.1"
"@typescript-eslint/scope-manager": "npm:6.10.0"
"@typescript-eslint/type-utils": "npm:6.10.0"
"@typescript-eslint/utils": "npm:6.10.0"
"@typescript-eslint/visitor-keys": "npm:6.10.0"
"@typescript-eslint/scope-manager": "npm:6.11.0"
"@typescript-eslint/type-utils": "npm:6.11.0"
"@typescript-eslint/utils": "npm:6.11.0"
"@typescript-eslint/visitor-keys": "npm:6.11.0"
debug: "npm:^4.3.4"
graphemer: "npm:^1.4.0"
ignore: "npm:^5.2.4"
@@ -1531,44 +1538,44 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
checksum: 54fd83cff912bae212934aae5abcb810cf182771778e1062f2aaf75989d300c5f23bdb03b8b3d587ece799dfabebfdc5cf6356e1ce07398011d728a3d0d0d381
checksum: c9c9e7a918e2f3ef8cb200c9158b70553a1014529867411b35e141c1d26713dd281907af1a231e640e8c4c73c3245a20cfc0e56a1cc95874889ce88c04706c78
languageName: node
linkType: hard
"@typescript-eslint/parser@npm:^6.10.0":
version: 6.10.0
resolution: "@typescript-eslint/parser@npm:6.10.0"
"@typescript-eslint/parser@npm:^6.11.0":
version: 6.11.0
resolution: "@typescript-eslint/parser@npm:6.11.0"
dependencies:
"@typescript-eslint/scope-manager": "npm:6.10.0"
"@typescript-eslint/types": "npm:6.10.0"
"@typescript-eslint/typescript-estree": "npm:6.10.0"
"@typescript-eslint/visitor-keys": "npm:6.10.0"
"@typescript-eslint/scope-manager": "npm:6.11.0"
"@typescript-eslint/types": "npm:6.11.0"
"@typescript-eslint/typescript-estree": "npm:6.11.0"
"@typescript-eslint/visitor-keys": "npm:6.11.0"
debug: "npm:^4.3.4"
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
peerDependenciesMeta:
typescript:
optional: true
checksum: d24a981807ea1ee5e5bbd9be2996b06eb99908c717464c6274b596c094b0e2609c1d88fcb8bef3479a8e8d39bc61a7103651b23981e47a5d89f6dec77e3bec38
checksum: abb2aff0d4f06937337d1b2da77df4e1501d708b0bce1707c523206ee10e6aa732e1ae6548da56b9889459f23c375a6f0ae2e3a208e972dab8eb3b46680d839a
languageName: node
linkType: hard
"@typescript-eslint/scope-manager@npm:6.10.0":
version: 6.10.0
resolution: "@typescript-eslint/scope-manager@npm:6.10.0"
"@typescript-eslint/scope-manager@npm:6.11.0":
version: 6.11.0
resolution: "@typescript-eslint/scope-manager@npm:6.11.0"
dependencies:
"@typescript-eslint/types": "npm:6.10.0"
"@typescript-eslint/visitor-keys": "npm:6.10.0"
checksum: 518cd60f9e9f5eef24f566f6a43d05241593a4520db6a93df714adac7b04b8bc2a1a89764f7a0aa23432e35e5f57ab2a3129f8f67ef211fa808c6bda29c28c78
"@typescript-eslint/types": "npm:6.11.0"
"@typescript-eslint/visitor-keys": "npm:6.11.0"
checksum: 60702ab23710c59ab0b52ffc66f77e24382cec8f684e3e43d4269cc17f414d3cb3a3bb85e232ea9f1e0f7e85506529978a5eea3c08945c01ed7aed4d4997b472
languageName: node
linkType: hard
"@typescript-eslint/type-utils@npm:6.10.0":
version: 6.10.0
resolution: "@typescript-eslint/type-utils@npm:6.10.0"
"@typescript-eslint/type-utils@npm:6.11.0":
version: 6.11.0
resolution: "@typescript-eslint/type-utils@npm:6.11.0"
dependencies:
"@typescript-eslint/typescript-estree": "npm:6.10.0"
"@typescript-eslint/utils": "npm:6.10.0"
"@typescript-eslint/typescript-estree": "npm:6.11.0"
"@typescript-eslint/utils": "npm:6.11.0"
debug: "npm:^4.3.4"
ts-api-utils: "npm:^1.0.1"
peerDependencies:
@@ -1576,23 +1583,23 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
checksum: e4e5b119730fe615a60fb9118ab408a471dab11304a70d469393a0aac6d06238377cd87693129160c600b7a03804e2552d3a7192d291ea3db10d2390983b3628
checksum: 478819bbbab39a0d11dc6276fc9b90e0b2576d7e32d761c811369657dc12bfaf95084bf951714ea82015259d736dec70770d229d6547b066ea0fc4133039082f
languageName: node
linkType: hard
"@typescript-eslint/types@npm:6.10.0":
version: 6.10.0
resolution: "@typescript-eslint/types@npm:6.10.0"
checksum: bc8faf3d00f1d4eaad0760f64a7e428646e65adc5322f41dc9a2d15d5df23e53b09605d69126c373630851cb258c15ba82cf66d949897d3758844964b0e98087
"@typescript-eslint/types@npm:6.11.0":
version: 6.11.0
resolution: "@typescript-eslint/types@npm:6.11.0"
checksum: 3ea55101325950d9594f839b38aa1c0958c3b8401ca9a8d2e4247997bb30dff7ac5e760e888de48a3ea9af3cb656eafb3e2cddc837a523a300ebccb63e150185
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:6.10.0":
version: 6.10.0
resolution: "@typescript-eslint/typescript-estree@npm:6.10.0"
"@typescript-eslint/typescript-estree@npm:6.11.0":
version: 6.11.0
resolution: "@typescript-eslint/typescript-estree@npm:6.11.0"
dependencies:
"@typescript-eslint/types": "npm:6.10.0"
"@typescript-eslint/visitor-keys": "npm:6.10.0"
"@typescript-eslint/types": "npm:6.11.0"
"@typescript-eslint/visitor-keys": "npm:6.11.0"
debug: "npm:^4.3.4"
globby: "npm:^11.1.0"
is-glob: "npm:^4.0.3"
@@ -1601,34 +1608,34 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
checksum: 41fc6dd0cfe8fb4c7ddc30d91e71d23ea1e0cbc261e8022ab089ddde6589eefdb89f66492d2ab4ae20dd45f51657022d9278bccc64aef7c6be0df756a081c0b5
checksum: 9d2333e517d50035f2c962b3966ebf8b35db0ac139c537cf4f1c4fd7b8d8914671671ad3bccdd59ef88fc4d29f441c0412a6c119ac6463bd2fbe8059d5209219
languageName: node
linkType: hard
"@typescript-eslint/utils@npm:6.10.0":
version: 6.10.0
resolution: "@typescript-eslint/utils@npm:6.10.0"
"@typescript-eslint/utils@npm:6.11.0":
version: 6.11.0
resolution: "@typescript-eslint/utils@npm:6.11.0"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.4.0"
"@types/json-schema": "npm:^7.0.12"
"@types/semver": "npm:^7.5.0"
"@typescript-eslint/scope-manager": "npm:6.10.0"
"@typescript-eslint/types": "npm:6.10.0"
"@typescript-eslint/typescript-estree": "npm:6.10.0"
"@typescript-eslint/scope-manager": "npm:6.11.0"
"@typescript-eslint/types": "npm:6.11.0"
"@typescript-eslint/typescript-estree": "npm:6.11.0"
semver: "npm:^7.5.4"
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
checksum: acf55bc231483f8b8d2d64ad9a261d0499085277b5ce3506cf579297401f78d88253ae52a9afad35cc32a532b53794367e32449283c06b2e89602c63184f011e
checksum: 7b8c17bd191b06cc77fe341f32fb7b4126d47a6ec05e5112567d4424a1896cf851935ff867c825d7e3361c317a48fe5304f95e454089f9aecc182bd42b1e4176
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:6.10.0":
version: 6.10.0
resolution: "@typescript-eslint/visitor-keys@npm:6.10.0"
"@typescript-eslint/visitor-keys@npm:6.11.0":
version: 6.11.0
resolution: "@typescript-eslint/visitor-keys@npm:6.11.0"
dependencies:
"@typescript-eslint/types": "npm:6.10.0"
"@typescript-eslint/types": "npm:6.11.0"
eslint-visitor-keys: "npm:^3.4.1"
checksum: 17a6962e10ffbcc286d202c7dfcc0dfa489c76ab7838b3522e90b3e87cbe2cdd7a24ffab434d9ca6dfed361801f11c3349ba01f808093c65c5365a9179ee5eb0
checksum: d89ef8579737f23a1a81506724e2c5cfec92fa4431232f93c4b6970a21382c6c0ad09ba21ffe8d25725d43aecce351fee2797c9170012ef0c00e5be7592e8233
languageName: node
linkType: hard
@@ -1647,8 +1654,8 @@ __metadata:
"@babel/core": "npm:^7.23.3"
"@emotion/react": "npm:^11.11.1"
"@emotion/styled": "npm:^11.11.0"
"@mui/icons-material": "npm:^5.14.16"
"@mui/material": "npm:^5.14.17"
"@mui/icons-material": "npm:^5.14.18"
"@mui/material": "npm:^5.14.18"
"@preact/compat": "npm:^17.1.2"
"@preact/preset-vite": "npm:^2.6.0"
"@table-library/react-table-library": "npm:4.1.7"
@@ -1658,8 +1665,8 @@ __metadata:
"@types/react": "npm:^18.2.37"
"@types/react-dom": "npm:^18.2.15"
"@types/react-router-dom": "npm:^5.3.3"
"@typescript-eslint/eslint-plugin": "npm:^6.10.0"
"@typescript-eslint/parser": "npm:^6.10.0"
"@typescript-eslint/eslint-plugin": "npm:^6.11.0"
"@typescript-eslint/parser": "npm:^6.11.0"
alova: "npm:^2.13.1"
async-validator: "npm:^4.2.5"
concurrently: "npm:^8.2.2"
@@ -1678,12 +1685,12 @@ __metadata:
jwt-decode: "npm:^4.0.0"
lodash-es: "npm:^4.17.21"
mime-types: "npm:^2.1.35"
preact: "npm:^10.18.2"
prettier: "npm:^3.0.3"
preact: "npm:^10.19.2"
prettier: "npm:^3.1.0"
react: "npm:latest"
react-dom: "npm:latest"
react-dropzone: "npm:^14.2.3"
react-icons: "npm:^4.11.0"
react-icons: "npm:^4.12.0"
react-router-dom: "npm:^6.18.0"
react-toastify: "npm:^9.1.3"
rollup-plugin-visualizer: "npm:^5.9.2"
@@ -6758,10 +6765,10 @@ __metadata:
languageName: node
linkType: hard
"preact@npm:^10.18.2":
version: 10.18.2
resolution: "preact@npm:10.18.2"
checksum: c7dcd6ea812adb0bdc215366b14aadc44724b6dd6c4e9aadd986126d94abde62f3e02e18d6157a9984873be9877f206c0afa10a09346178c4c828a103a66a0e1
"preact@npm:^10.19.2":
version: 10.19.2
resolution: "preact@npm:10.19.2"
checksum: 1519050e79f0dec61aa85daa5dcba4a5294e89fb09ab53d5e1a215ef8526dd5ccdbe82a02842cc4875fa3ea076eee9697a7421c32ffcc6159007d27b13a60a8f
languageName: node
linkType: hard
@@ -6795,12 +6802,12 @@ __metadata:
languageName: node
linkType: hard
"prettier@npm:^3.0.3":
version: 3.0.3
resolution: "prettier@npm:3.0.3"
"prettier@npm:^3.1.0":
version: 3.1.0
resolution: "prettier@npm:3.1.0"
bin:
prettier: bin/prettier.cjs
checksum: ccf1ead9794b017be6b42d0873f459070beef2069eb393c8b4c0d11aa3430acefc54f6d5f44a5b7ce9af05ad8daf694b912f0aa2808d1c22dfa86e61e9d563f8
checksum: e95e8f93c6b9aea2ac1e86bebe329bee90c8c50d9a23d1f593eba8d7f39b33b3641eb28785001505b6723c47895a5322ad12a2fb855b289cb7bae450ffc34425
languageName: node
linkType: hard
@@ -6906,12 +6913,12 @@ __metadata:
languageName: node
linkType: hard
"react-icons@npm:^4.11.0":
version: 4.11.0
resolution: "react-icons@npm:4.11.0"
"react-icons@npm:^4.12.0":
version: 4.12.0
resolution: "react-icons@npm:4.12.0"
peerDependencies:
react: "*"
checksum: 61f84c7a3f59120659f984828cac72b11c4baf9b78fb71261ab1ab5b2a9df4debd9fa5e9c30ccca23e4f0d9c0713bb5a339390073a8a01f4fe72c024fc526b5f
checksum: 5cc20509ca0b182f1e7bf42c271846c48f688c8922e2439f48728805adc93ba18476a13588cbe91ee43a2d03b2787e0dc0b5cc4b9c4e4ae3426f4464b3c1b734
languageName: node
linkType: hard

File diff suppressed because one or more lines are too long

View File

@@ -4,4 +4,4 @@ enableGlobalCache: false
nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-4.0.1.cjs
yarnPath: .yarn/releases/yarn-4.0.2.cjs

View File

@@ -15,5 +15,5 @@
"express": "^4.18.2",
"multer": "^1.4.5-lts.1"
},
"packageManager": "yarn@4.0.1"
"packageManager": "yarn@4.0.2"
}

View File

@@ -2404,42 +2404,45 @@ rest_server.post(EMSESP_WRITE_ENTITIES_ENDPOINT, (req, res) => {
});
rest_server.post(EMSESP_WRITE_VALUE_ENDPOINT, async (req, res) => {
const devicevalue = req.body.devicevalue;
const command = req.body.c;
const value = req.body.v;
const id = req.body.id;
console.log('Write device value for id : ' + id);
console.log(' devicedata: ' + JSON.stringify(devicevalue));
console.log(' data: ' + JSON.stringify(req.body));
if (id === 1) {
objIndex = emsesp_devicedata_1.data.findIndex((obj) => obj.c == devicevalue.c);
emsesp_devicedata_1.data[objIndex] = devicevalue;
objIndex = emsesp_devicedata_1.data.findIndex((obj) => obj.c == command);
emsesp_devicedata_1.data[objIndex].v = value;
}
if (id === 2) {
objIndex = emsesp_devicedata_2.data.findIndex((obj) => obj.c == devicevalue.c);
emsesp_devicedata_2.data[objIndex] = devicevalue;
objIndex = emsesp_devicedata_2.data.findIndex((obj) => obj.c == command);
emsesp_devicedata_2.data[objIndex].v = value;
}
if (id === 3) {
objIndex = emsesp_devicedata_3.data.findIndex((obj) => obj.c == devicevalue.c);
emsesp_devicedata_3.data[objIndex] = devicevalue;
objIndex = emsesp_devicedata_3.data.findIndex((obj) => obj.c == command);
emsesp_devicedata_3.data[objIndex].v = value;
}
if (id === 4) {
objIndex = emsesp_devicedata_4.data.findIndex((obj) => obj.c == devicevalue.c);
emsesp_devicedata_4.data[objIndex] = devicevalue;
objIndex = emsesp_devicedata_4.data.findIndex((obj) => obj.c == command);
emsesp_devicedata_4.data[objIndex].v = value;
}
if (id === 5) {
objIndex = emsesp_devicedata_5.data.findIndex((obj) => obj.c == devicevalue.c);
emsesp_devicedata_5.data[objIndex] = devicevalue;
objIndex = emsesp_devicedata_5.data.findIndex((obj) => obj.c == command);
emsesp_devicedata_5.data[objIndex].v = value;
}
if (id === 6) {
objIndex = emsesp_devicedata_6.data.findIndex((obj) => obj.c == devicevalue.c);
emsesp_devicedata_6.data[objIndex] = devicevalue;
objIndex = emsesp_devicedata_6.data.findIndex((obj) => obj.c == command);
emsesp_devicedata_6.data[objIndex].v = value;
}
if (id === 7) {
objIndex = emsesp_devicedata_7.data.findIndex((obj) => obj.c == devicevalue.c);
emsesp_devicedata_7.data[objIndex] = devicevalue;
objIndex = emsesp_devicedata_7.data.findIndex((obj) => obj.c == command);
emsesp_devicedata_7.data[objIndex].v = value;
}
// custom entities
if (id === 99) {
objIndex = emsesp_devicedata_99.data.findIndex((obj) => obj.c == devicevalue.c);
emsesp_devicedata_99.data[objIndex] = devicevalue;
objIndex = emsesp_devicedata_99.data.findIndex((obj) => obj.c == command);
emsesp_devicedata_99.data[objIndex].v = value;
}
await delay(1000); // wait to show spinner

View File

@@ -616,7 +616,8 @@ void AnalogSensor::publish_values(const bool force) {
}
JsonObject dev = config.createNestedObject("dev");
JsonArray ids = dev.createNestedArray("ids");
dev["name"] = name;
JsonArray ids = dev.createNestedArray("ids");
ids.add(Mqtt::basename());
// add "availability" section

View File

@@ -156,6 +156,9 @@ class AnalogSensor {
bool get_value_info(JsonObject & output, const char * cmd, const int8_t id) const;
void store_counters();
bool command_info(const char * value, const int8_t id, JsonObject & output) const;
#if defined(EMSESP_TEST)
void test();
#endif
@@ -169,7 +172,6 @@ class AnalogSensor {
void remove_ha_topic(const int8_t type, const uint8_t id) const;
bool command_setvalue(const char * value, const int8_t gpio);
void measure();
bool command_info(const char * value, const int8_t id, JsonObject & output) const;
bool command_commands(const char * value, const int8_t id, JsonObject & output);
std::vector<Sensor> sensors_; // our list of sensors

View File

@@ -510,7 +510,7 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo
}
shell.print(cl);
// pad with spaces
while (i++ < 22) {
while (i++ < 30) {
shell.print(' ');
}
shell.print(COLOR_BRIGHT_CYAN);
@@ -521,7 +521,7 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo
shell.print(Helpers::translated_word(cf.description_));
if (!cf.has_flags(CommandFlag::ADMIN_ONLY)) {
shell.print(' ');
shell.print(COLOR_BRIGHT_RED);
shell.print(COLOR_BRIGHT_GREEN);
shell.print('*');
}
shell.print(COLOR_RESET);
@@ -601,7 +601,7 @@ void Command::show_devices(uuid::console::Shell & shell) {
// output list of all commands to console
// calls show with verbose mode set
void Command::show_all(uuid::console::Shell & shell) {
shell.println("Available commands (*=authorization not required): ");
shell.printfln("Showing all available commands (%s*%s=authentication not required):", COLOR_BRIGHT_GREEN, COLOR_RESET);
// show system first
shell.print(COLOR_BOLD_ON);
@@ -615,9 +615,9 @@ void Command::show_all(uuid::console::Shell & shell) {
shell.print(COLOR_YELLOW);
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::CUSTOM));
shell.println(COLOR_RESET);
shell.printf(" info: %slists all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_RED);
shell.printf(" info:\t\t\t\t%slists all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN);
shell.println(COLOR_RESET);
shell.printf(" commands: %slists all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_RED);
shell.printf(" commands:\t\t\t%slists all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN);
shell.print(COLOR_RESET);
show(shell, EMSdevice::DeviceType::CUSTOM, true);
@@ -626,9 +626,9 @@ void Command::show_all(uuid::console::Shell & shell) {
shell.print(COLOR_YELLOW);
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SCHEDULER));
shell.println(COLOR_RESET);
shell.printf(" info: %slists all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_RED);
shell.printf(" info:\t\t\t\t%slists all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN);
shell.println(COLOR_RESET);
shell.printf(" commands: %slists all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_RED);
shell.printf(" commands:\t\t\t%slists all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN);
shell.print(COLOR_RESET);
show(shell, EMSdevice::DeviceType::SCHEDULER, true);

View File

@@ -348,15 +348,6 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
"local");
});
commands->add_command(ShellContext::MAIN, CommandFlags::USER, string_vector{F_(set)}, [](Shell & shell, const std::vector<std::string> & arguments) {
to_app(shell).webSettingsService.read([&](WebSettings & settings) {
shell.printfln("Language: %s", settings.locale.c_str());
shell.printfln(F_(tx_mode_fmt), settings.tx_mode);
shell.printfln(F_(bus_id_fmt), settings.ems_bus_id);
shell.printfln(F_(board_profile_fmt), settings.board_profile.c_str());
});
});
//
// EMS device commands
//
@@ -539,7 +530,14 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
if (return_code == CommandRet::OK && json.size()) {
if (json.containsKey("api_data")) {
JsonVariant data = json["api_data"];
shell.println(data.as<const char *>());
if (data.is<int>()) {
shell.printfln("%d", data.as<int>());
} else if (data.is<float>()) {
char s[10];
shell.println(Helpers::render_value(s, data.as<float>(), 1));
} else {
shell.println(data.as<const char *>());
}
return;
}
serializeJsonPretty(doc, shell);
@@ -609,12 +607,13 @@ void EMSESPShell::stopped() {
// show welcome banner
void EMSESPShell::display_banner() {
println();
printfln("┌───────────────────────────────────────");
printfln("│ %sEMS-ESP version %-12s%s ", COLOR_BOLD_ON, EMSESP_APP_VERSION, COLOR_BOLD_OFF);
printfln("│ %s%shttps://github.com/emsesp/EMS-ESP32%s ", COLOR_BRIGHT_GREEN, COLOR_UNDERLINE, COLOR_RESET);
printfln(" ");
printfln("│ type %shelp%s to show available commands ", COLOR_UNDERLINE, COLOR_RESET);
printfln("└────────────────────────────────────────┘");
printfln("┌───────────────────────────────────────┐");
printfln("│ %sEMS-ESP version %-12s%s │", COLOR_BOLD_ON, EMSESP_APP_VERSION, COLOR_BOLD_OFF);
printfln("│ %s%shttps://github.com/emsesp/EMS-ESP32%s │", COLOR_BRIGHT_GREEN, COLOR_UNDERLINE, COLOR_RESET);
printfln("│ │");
printfln("│ type %shelp%s to show available commands │", COLOR_UNDERLINE, COLOR_RESET);
printfln("│ use %ssu%s to access Admin commands │", COLOR_UNDERLINE, COLOR_RESET);
printfln("└───────────────────────────────────────┘");
println();
// set console name

View File

@@ -118,6 +118,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
FL_(setReturnTemp),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_returnTemp));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &burnGas_, DeviceValueType::BOOL, FL_(heatingOn), DeviceValueUOM::NONE);
}
/*
@@ -219,6 +220,16 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
0,
120);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &absBurnPow_, DeviceValueType::UINT, FL_(absBurnPow), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&heatblock_,
DeviceValueType::USHORT,
DeviceValueNumOp::DV_NUMOP_DIV10,
FL_(heatblock),
DeviceValueUOM::DEGREES);
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &boilHystOn_, DeviceValueType::INT, FL_(boilHystOn), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_hyst_on), -20, 0);
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &boilHystOff_, DeviceValueType::INT, FL_(boilHystOff), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_hyst_off), 0, 20);
}
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&heatingActivated_,
@@ -236,16 +247,6 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &pumpDelay_, DeviceValueType::UINT, FL_(pumpDelay), DeviceValueUOM::MINUTES, MAKE_CF_CB(set_pump_delay), 0, 60);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &setFlowTemp_, DeviceValueType::UINT, FL_(setFlowTemp), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&heatblock_,
DeviceValueType::USHORT,
DeviceValueNumOp::DV_NUMOP_DIV10,
FL_(heatblock),
DeviceValueUOM::DEGREES);
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &boilHystOn_, DeviceValueType::INT, FL_(boilHystOn), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_hyst_on), -20, 0);
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &boilHystOff_, DeviceValueType::INT, FL_(boilHystOff), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_hyst_off), 0, 20);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &setBurnPow_, DeviceValueType::UINT, FL_(setBurnPow), DeviceValueUOM::PERCENT);
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &selBurnPow_, DeviceValueType::UINT, FL_(selBurnPow), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_burn_power), 0, 254);

View File

@@ -25,6 +25,7 @@ REGISTER_FACTORY(Extension, EMSdevice::DeviceType::EXTENSION);
Extension::Extension(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
register_telegram_type(0x935, "EM100SetMessage", true, MAKE_PF_CB(process_EM100SetMessage));
register_telegram_type(0x936, "EM100OutMessage", false, MAKE_PF_CB(process_EM100OutMessage));
register_telegram_type(0x937, "EM100TempMessage", false, MAKE_PF_CB(process_EM100TempMessage));
register_telegram_type(0x938, "EM100InputMessage", false, MAKE_PF_CB(process_EM100InputMessage));
register_telegram_type(0x939, "EM100MonitorMessage", false, MAKE_PF_CB(process_EM100MonitorMessage));
@@ -36,7 +37,7 @@ Extension::Extension(uint8_t device_type, uint8_t device_id, uint8_t product_id,
DeviceValueNumOp::DV_NUMOP_DIV10,
FL_(flowTempVf),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &input_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(input), DeviceValueUOM::VOLTS);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &input_, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(input), DeviceValueUOM::VOLTS);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &outPower_, DeviceValueType::UINT, FL_(outPower), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &setPower_, DeviceValueType::UINT, FL_(setPower), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &setPoint_, DeviceValueType::UINT, FL_(setPoint), DeviceValueUOM::DEGREES);
@@ -61,7 +62,8 @@ Extension::Extension(uint8_t device_type, uint8_t device_id, uint8_t product_id,
}
// 0x935 needs fetch
// extension(0x15) -W-> Me(0x0B), EM100SetMessage(0x0935), data: 00 00 64 50 14
// need to be fetched
void Extension::process_EM100SetMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, minV_, 1); // Input for off, is / 10
has_update(telegram, maxV_, 2); // Input for 100%, is / 10
@@ -69,18 +71,22 @@ void Extension::process_EM100SetMessage(std::shared_ptr<const Telegram> telegram
has_update(telegram, maxT_, 4); // max temp
}
// alert(0x15) -B-> All(0x00), ?(0x093A), data: 00 00 00 00 00 00 00 00 00 03 01
// extension(0x15) -B-> All(0x00), ?(0x0936), data: 00 00 00 00 28 00 (offset 1)
void Extension::process_EM100OutMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, outPower_, 5); // power monitor %
}
// extension(0x15) -B-> All(0x00), ?(0x093A), data: 00 00 00 00 00 00 00 00 00 03 01
void Extension::process_EM100ConfigMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, dip_, 9);
}
// alert(0x15) -B-> All(0x00), ?(0x0938), data: 01 62
// extension(0x15) -B-> All(0x00), ?(0x0938), data: 01 62
void Extension::process_EM100InputMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, outPower_, 0); // IO1
has_update(telegram, input_, 1);
}
// alert(0x15) -B-> All(0x00), ?(0x0939), data: 64 4E 00 00
// extension(0x15) -B-> All(0x00), ?(0x0939), data: 64 4E 00 00
void Extension::process_EM100MonitorMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, setPower_, 0); // percent
has_update(telegram, setPoint_, 1); // °C
@@ -88,7 +94,7 @@ void Extension::process_EM100MonitorMessage(std::shared_ptr<const Telegram> tele
// has_update(telegram, errorPump_, 3); // IE0
}
// alert(0x15) -B-> All(0x00), ?(0x0937), data: 80 00
// extension(0x15) -B-> All(0x00), ?(0x0937), data: 80 00
void Extension::process_EM100TempMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, headerTemp_, 0);
}
@@ -129,4 +135,4 @@ bool Extension::set_maxT(const char * value, const int8_t id) {
return true;
}
} // namespace emsesp
} // namespace emsesp

View File

@@ -29,6 +29,7 @@ class Extension : public EMSdevice {
private:
void process_EM100SetMessage(std::shared_ptr<const Telegram> telegram);
void process_EM100OutMessage(std::shared_ptr<const Telegram> telegram);
void process_EM100MonitorMessage(std::shared_ptr<const Telegram> telegram);
void process_EM100TempMessage(std::shared_ptr<const Telegram> telegram);
void process_EM100InputMessage(std::shared_ptr<const Telegram> telegram);
@@ -41,7 +42,7 @@ class Extension : public EMSdevice {
int16_t headerTemp_; // T0
int16_t input_; // IO1
uint8_t input_; // IO1
uint8_t errorState_; // OE1
uint8_t errorPump_; // IE0
uint8_t outPower_; // IO1

View File

@@ -976,7 +976,8 @@ void Thermostat::process_RC300Monitor(std::shared_ptr<const Telegram> telegram)
has_update(telegram, hc->roomTemp, 0); // is * 10
has_bitupdate(telegram, hc->modetype, 10, 1);
has_bitupdate(telegram, hc->mode, 10, 0); // bit 1, mode (auto=1 or manual=0)
// auto status, read mode in settings
// has_bitupdate(telegram, hc->mode, 10, 0); // bit 0, mode (auto=1 or manual=0)
// if manual, take the current setpoint temp at pos 6
// if auto, take the next setpoint temp at pos 7
@@ -990,7 +991,7 @@ void Thermostat::process_RC300Monitor(std::shared_ptr<const Telegram> telegram)
// summermode is bit 4 for boilers and bit 6 for heatpumps: 0:winter, 1:summer
telegram->read_value(hc->statusbyte, 2);
// use summertemp or hpoperatingstate, https://github.com/emsesp/EMS-ESP32/issues/747, #550, #503
if ((hc->statusbyte & 1) || !is_fetch(summer2_typeids[hc->hc()])) {
if ((hc->statusbyte & 1) || !is_received(summer2_typeids[hc->hc()])) {
has_update(hc->summermode, hc->statusbyte & 0x50 ? 1 : 0);
has_update(hc->hpoperatingstate, EMS_VALUE_UINT_NOTSET);
} else {
@@ -1021,8 +1022,15 @@ void Thermostat::process_RC300Set(std::shared_ptr<const Telegram> telegram) {
// has_update(telegram, hc->selTemp, 8, 1); // single byte conversion, value is * 2 - auto?
// has_update(telegram, hc->selTemp, 10, 1); // single byte conversion, value is * 2 - manual
// check why mode is both in the Monitor and Set for the RC300. It'll be read twice!
// has_update(telegram, hc->mode, 0); // Auto = xFF, Manual = x00 eg. 10 00 FF 08 01 B9 FF
telegram->read_value(hc->mode_new, 21); // 0-off, 1-manual, 2-auto
if (hc->mode_new <= 2) {
has_update(hc->mode, hc->mode_new);
} else {
uint8_t mode = hc->mode == 2 ? 0xFF : 0; // auto : manual
if (telegram->read_value(mode, 0)) {
has_update(hc->mode, mode == 0xFF ? 2 : 1);
}
}
has_update(telegram, hc->daytemp, 2); // is * 2
has_update(telegram, hc->nighttemp, 4); // is * 2
@@ -1057,7 +1065,7 @@ void Thermostat::process_RC300Summer(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, hc->roominfluence, 0);
has_update(telegram, hc->roominfl_factor, 1); // is * 10
has_update(telegram, hc->offsettemp, 2);
if (!is_fetch(summer2_typeids[hc->hc()])) {
if (!is_received(summer2_typeids[hc->hc()])) {
has_update(telegram, hc->summertemp, 6);
has_update(telegram, hc->summersetmode, 7);
}
@@ -2552,12 +2560,11 @@ bool Thermostat::set_mode_n(const uint8_t mode, const uint8_t hc_num) {
break;
case EMSdevice::EMS_DEVICE_FLAG_RC300:
case EMSdevice::EMS_DEVICE_FLAG_RC100:
offset = EMS_OFFSET_RCPLUSSet_mode;
validate_typeid = monitor_typeids[hc_p];
if (mode == HeatingCircuit::Mode::AUTO) {
set_mode_value = 0xFF; // special value for auto
if (Helpers::hasValue(hc->mode_new)) {
offset = EMS_OFFSET_RCPLUSSet_mode_new;
} else {
set_mode_value = 0; // everything else, like manual/day etc..
offset = EMS_OFFSET_RCPLUSSet_mode;
set_mode_value = set_mode_value == 2 ? 0xFF : 0;
}
break;
case EMSdevice::EMS_DEVICE_FLAG_JUNKERS:
@@ -2611,7 +2618,7 @@ bool Thermostat::set_summermode(const char * value, const int8_t id) {
uint8_t set;
if (is_fetch(summer2_typeids[hc->hc()])) {
if (is_received(summer2_typeids[hc->hc()])) {
if ((hc->statusbyte & 1) && Helpers::value2enum(value, set, FL_(enum_summermode))) {
write_command(summer2_typeids[hc->hc()], 0, set, summer2_typeids[hc->hc()]);
return true;
@@ -2912,7 +2919,7 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char
min_on = 0;
max_on = 1;
}
if (no > 41 || time > 0x90 || ((on < min_on || on > max_on) && on != 7)) {
if (no > 41 || time > 0x90 || day > 7 || ((on < min_on || on > max_on) && on != 7)) {
// LOG_WARNING("Setting switchtime: Invalid data: %s", value);
// LOG_WARNING("Setting switchtime: Invalid data: %02d.%1d.0x%02X.%1d", no, day, time, on);
return false;
@@ -3164,7 +3171,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
validate_typeid = set_typeids[hc->hc()];
switch (mode) {
case HeatingCircuit::Mode::SUMMER:
if (is_fetch(summer2_typeids[hc->hc()])) {
if (is_received(summer2_typeids[hc->hc()])) {
offset = 0x01;
set_typeid = summer2_typeids[hc->hc()];
} else {

View File

@@ -41,6 +41,7 @@ class Thermostat : public EMSdevice {
uint8_t tempautotemp;
int8_t remoteseltemp;
uint8_t mode;
uint8_t mode_new = EMS_VALUE_UINT_NOTSET; // not initialized by register_value
uint8_t modetype;
uint8_t summermode;
uint8_t holidaymode;
@@ -318,6 +319,7 @@ class Thermostat : public EMSdevice {
static constexpr uint8_t EMS_OFFSET_RCPLUSStatusMessage_curr = 0; // current temp
static constexpr uint8_t EMS_OFFSET_RCPLUSStatusMessage_currsetpoint = 6; // target setpoint temp
static constexpr uint8_t EMS_OFFSET_RCPLUSSet_mode = 0; // operation mode(Auto=0xFF, Manual=0x00)
static constexpr uint8_t EMS_OFFSET_RCPLUSSet_mode_new = 21; // operation mode(0-off, 1-manual, 2-auto)
static constexpr uint8_t EMS_OFFSET_RCPLUSSet_temp_comfort3 = 1; // comfort3 level
static constexpr uint8_t EMS_OFFSET_RCPLUSSet_temp_comfort2 = 2; // comfort2 level
static constexpr uint8_t EMS_OFFSET_RCPLUSSet_temp_comfort1 = 3; // comfort1 level

View File

@@ -333,6 +333,16 @@ bool EMSdevice::is_fetch(uint16_t telegram_id) const {
return false;
}
// get receive status of telegramID
bool EMSdevice::is_received(uint16_t telegram_id) const {
for (const auto & tf : telegram_functions_) {
if (tf.telegram_type_id_ == telegram_id) {
return tf.received_;
}
}
return false;
}
// check for a tag to create a nest
bool EMSdevice::has_tags(const uint8_t tag) const {
for (const auto & dv : devicevalues_) {
@@ -803,29 +813,9 @@ void EMSdevice::publish_value(void * value_p) const {
}
// looks up the UOM for a given key from the device value table
// key is the fullname
std::string EMSdevice::get_value_uom(const char * key) const {
// the key may have a TAG string prefixed at the beginning. If so, remove it
char new_key[80];
strlcpy(new_key, key, sizeof(new_key));
char * key_p = new_key;
for (uint8_t i = 0; i < DeviceValue::NUM_TAGS; i++) {
auto tag = Helpers::translated_word(DeviceValue::DeviceValueTAG_s[i]);
if (tag) {
std::string key2 = key; // copy string to a std::string so we can use the find function
uint8_t length = strlen(tag);
if ((key2.find(tag) != std::string::npos) && (key[length] == ' ')) {
key_p += length + 1; // remove the tag
break;
}
}
}
// look up key in our device value list
std::string EMSdevice::get_value_uom(const std::string & shortname) const {
for (const auto & dv : devicevalues_) {
auto fullname = dv.get_fullname();
if ((!dv.has_state(DeviceValueState::DV_WEB_EXCLUDE) && !fullname.empty()) && (fullname == key_p)) {
if ((!dv.has_state(DeviceValueState::DV_WEB_EXCLUDE)) && (dv.short_name == shortname)) {
// ignore TIME since "minutes" is already added to the string value
if ((dv.uom == DeviceValueUOM::NONE) || (dv.uom == DeviceValueUOM::MINUTES)) {
break;
@@ -837,6 +827,43 @@ std::string EMSdevice::get_value_uom(const char * key) const {
return std::string{}; // not found
}
bool EMSdevice::export_values(uint8_t unique_id, JsonObject & output, const int8_t id, const uint8_t output_target) {
bool has_value = false;
uint8_t tag;
if (id >= 1 && id <= (1 + DeviceValueTAG::TAG_HS16 - DeviceValueTAG::TAG_HC1)) {
tag = DeviceValueTAG::TAG_HC1 + id - 1; // this sets also WWC and HS
} else if (id == -1 || id == 0) {
tag = DeviceValueTAG::TAG_NONE;
} else {
return false;
}
if (id > 0 || output_target == EMSdevice::OUTPUT_TARGET::API_VERBOSE) {
for (const auto & emsdevice : EMSESP::emsdevices) {
if (emsdevice->unique_id() == unique_id) {
has_value |= emsdevice->generate_values(output, tag, (id < 1), output_target); // use nested for id -1 and 0
}
}
return has_value;
}
// for nested output add for each tag
for (tag = DeviceValueTAG::TAG_BOILER_DATA_WW; tag <= DeviceValueTAG::TAG_HS16; tag++) {
JsonObject output_hc = output;
bool nest_created = false;
for (const auto & emsdevice : EMSESP::emsdevices) {
if (emsdevice->unique_id() == unique_id) {
if (!nest_created && emsdevice->has_tags(tag)) {
output_hc = output.createNestedObject(EMSdevice::tag_to_mqtt(tag));
nest_created = true;
}
has_value |= emsdevice->generate_values(output_hc, tag, true, output_target); // use nested for id -1 and 0
}
}
}
return has_value;
}
// prepare array of device values used for the WebUI
// this is loosely based of the function generate_values used for the MQTT and Console
// except additional data is stored in the JSON document needed for the Web UI like the UOM and command
@@ -1794,7 +1821,8 @@ bool EMSdevice::handle_telegram(std::shared_ptr<const Telegram> telegram) {
#if defined(EMSESP_DEBUG)
EMSESP::logger().debug("This telegram (%s) is not recognized by the EMS bus", tf.telegram_type_name_);
#endif
tf.fetch_ = false;
// removing fetch causes issue: https://github.com/emsesp/EMS-ESP32/issues/1420
// tf.fetch_ = false;
return false;
}
if (telegram->message_length > 0) {

View File

@@ -47,12 +47,13 @@ class EMSdevice {
// static functions, used outside the class like in console.cpp, command.cpp, emsesp.cpp, mqtt.cpp
static const char * device_type_2_device_name(const uint8_t device_type);
static uint8_t device_name_2_device_type(const char * topic);
static const char * tag_to_string(uint8_t tag, const bool translate = true);
static const char * uom_to_string(uint8_t uom);
static const char * tag_to_mqtt(uint8_t tag);
static uint8_t decode_brand(uint8_t value);
static bool export_values(uint8_t device_type, JsonObject & output, const int8_t id, const uint8_t output_target);
static uint8_t decode_brand(uint8_t value);
// non static
const char * device_type_name(); // returns short non-translated device type name
const char * device_type_2_device_name_translated(); // returns translated device type name
@@ -213,9 +214,10 @@ class EMSdevice {
void register_telegram_type(const uint16_t telegram_type_id, const char * telegram_type_name, bool fetch, const process_function_p cb);
bool handle_telegram(std::shared_ptr<const Telegram> telegram);
std::string get_value_uom(const char * key) const;
bool get_value_info(JsonObject & root, const char * cmd, const int8_t id);
void get_dv_info(JsonObject & json);
std::string get_value_uom(const std::string & shortname) const;
bool get_value_info(JsonObject & root, const char * cmd, const int8_t id);
void get_dv_info(JsonObject & json);
enum OUTPUT_TARGET : uint8_t { API_VERBOSE, API_SHORTNAMES, MQTT, CONSOLE };
bool generate_values(JsonObject & output, const uint8_t tag_filter, const bool nested, const uint8_t output_target);
@@ -314,6 +316,7 @@ class EMSdevice {
void fetch_values();
void toggle_fetch(uint16_t telegram_id, bool toggle);
bool is_fetch(uint16_t telegram_id) const;
bool is_received(uint16_t telegram_id) const;
bool has_telegram_id(uint16_t id) const;
void ha_config_clear();

View File

@@ -386,28 +386,32 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) {
// print line
for (JsonPair p : json) {
const char * key = p.key().c_str();
shell.printf(" %s: ", key);
JsonVariant data = p.value();
shell.print(COLOR_BRIGHT_GREEN);
shell.print(data.as<std::string>());
// if there is a uom print it
std::string uom = emsdevice->get_value_uom(key);
if (uom == "°C" && EMSESP::system_.fahrenheit()) {
uom = "°F";
}
if (!uom.empty()) {
shell.print(' ');
shell.print(uom);
}
std::string key = p.key().c_str(); // this will be fullname and the shortname in brackets
shell.print(COLOR_RESET);
shell.println();
// extract the shortname from the key, which is in brackets
std::size_t first_bracket = key.find_last_of('(');
std::size_t last_bracket = key.find_last_of(')');
std::string shortname = key.substr(first_bracket + 1, last_bracket - first_bracket - 1);
std::string uom = emsdevice->get_value_uom(key.substr(first_bracket + 1, last_bracket - first_bracket - 1));
shell.printfln(" %s: %s%s %s%s", key.c_str(), COLOR_BRIGHT_GREEN, p.value().as<std::string>().c_str(), uom.c_str(), COLOR_RESET);
}
shell.println();
}
}
}
// show any custom entities
if (webCustomEntityService.count_entities() > 0) {
shell.printfln("Custom entities:");
StaticJsonDocument<EMSESP_JSON_SIZE_MEDIUM> custom_doc; // use max size
JsonObject custom_output = custom_doc.to<JsonObject>();
webCustomEntityService.show_values(custom_output);
for (JsonPair p : custom_output) {
shell.printfln(" %s: %s%s%s", p.key().c_str(), COLOR_BRIGHT_GREEN, p.value().as<std::string>().c_str(), COLOR_RESET);
}
shell.println();
}
}
// show temperature sensors and Analog sensors
@@ -1166,14 +1170,17 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
device_type,
F_(info),
[device_type](const char * value, const int8_t id, JsonObject & output) {
return command_info(device_type, output, id, EMSdevice::OUTPUT_TARGET::API_VERBOSE);
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 command_info(device_type, output, id, EMSdevice::OUTPUT_TARGET::API_SHORTNAMES); // HIDDEN command showing short names, used in e.g. /api/boiler
return EMSdevice::export_values(device_type,
output,
id,
EMSdevice::OUTPUT_TARGET::API_SHORTNAMES); // HIDDEN command showing short names, used in e.g. /api/boiler
},
nullptr,
CommandFlag::HIDDEN); // this command is hidden
@@ -1214,43 +1221,6 @@ bool EMSESP::command_commands(uint8_t device_type, JsonObject & output, const in
return Command::list(device_type, output);
}
// export all values for a specific device
bool EMSESP::command_info(uint8_t device_type, JsonObject & output, const int8_t id, const uint8_t output_target) {
bool has_value = false;
uint8_t tag;
if (id >= 1 && id <= (1 + DeviceValueTAG::TAG_HS16 - DeviceValueTAG::TAG_HC1)) {
tag = DeviceValueTAG::TAG_HC1 + id - 1; // this sets also WWC and HS
} else if (id == -1 || id == 0) {
tag = DeviceValueTAG::TAG_NONE;
} else {
return false;
}
if (id > 0 || output_target == EMSdevice::OUTPUT_TARGET::API_VERBOSE) {
for (const auto & emsdevice : emsdevices) {
if (emsdevice && (emsdevice->device_type() == device_type)) {
has_value |= emsdevice->generate_values(output, tag, (id < 1), output_target); // use nested for id -1 and 0
}
}
return has_value;
}
// for nested output add for each tag
for (tag = DeviceValueTAG::TAG_BOILER_DATA_WW; tag <= DeviceValueTAG::TAG_HS16; tag++) {
JsonObject output_hc = output;
bool nest_created = false;
for (const auto & emsdevice : emsdevices) {
if (emsdevice && (emsdevice->device_type() == device_type)) {
if (!nest_created && emsdevice->has_tags(tag)) {
output_hc = output.createNestedObject(EMSdevice::tag_to_mqtt(tag));
nest_created = true;
}
has_value |= emsdevice->generate_values(output_hc, tag, true, output_target); // use nested for id -1 and 0
}
}
}
return has_value;
}
// 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) {
txservice_.read_request(type_id, dest, offset, length, front);

View File

@@ -245,7 +245,6 @@ class EMSESP {
static void process_version(std::shared_ptr<const Telegram> telegram);
static void publish_response(std::shared_ptr<const Telegram> telegram);
static void publish_all_loop();
static bool command_info(uint8_t device_type, JsonObject & output, const int8_t id, const uint8_t output_target);
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);

View File

@@ -123,7 +123,6 @@ MAKE_WORD_CUSTOM(EMSESP, "EMS-ESP")
MAKE_WORD_CUSTOM(host_fmt, "Host: %s")
MAKE_WORD_CUSTOM(port_fmt, "Port: %d")
MAKE_WORD_CUSTOM(hostname_fmt, "Hostname: %s")
MAKE_WORD_CUSTOM(board_profile_fmt, "Board Profile: %s")
MAKE_WORD_CUSTOM(mark_interval_fmt, "Mark interval: %lus")
MAKE_WORD_CUSTOM(wifi_ssid_fmt, "WiFi SSID: %s")
MAKE_WORD_CUSTOM(wifi_password_fmt, "WiFi Password: %S")
@@ -303,7 +302,7 @@ MAKE_ENUM(enum_summer, FL_(winter), FL_(summer))
MAKE_ENUM(enum_operatingstate, FL_(heating), FL_(off), FL_(cooling))
MAKE_ENUM(enum_hpmode, FL_(heating), FL_(cooling), FL_(heatandcool))
MAKE_ENUM(enum_mode, FL_(manual), FL_(auto)) // RC100, RC300, RC310
MAKE_ENUM(enum_mode, FL_(off), FL_(manual), FL_(auto)) // RC100, RC300, RC310
MAKE_ENUM(enum_mode2, FL_(off), FL_(manual), FL_(auto)) // RC20, RC30
MAKE_ENUM(enum_mode3, FL_(night), FL_(day), FL_(auto)) // RC35, RC30_N, RC25, RC20_N
MAKE_ENUM(enum_mode4, FL_(nofrost), FL_(eco), FL_(heat), FL_(auto)) // JUNKERS

View File

@@ -57,7 +57,6 @@ MAKE_WORD_TRANSLATION(ventilation_device, "Ventilation", "Lüftung", "Ventilatie
// commands
// TODO translate
MAKE_WORD_TRANSLATION(info_cmd, "lists all values", "Liste aller Werte", "lijst van alle waardes", "", "wyświetl wszystkie wartości", "Viser alle verdier", "", "Tüm değerleri listele", "elenca tutti i valori") // TODO translate
MAKE_WORD_TRANSLATION(commands_cmd, "lists all commands", "Liste aller Kommandos", "lijst van alle commando's", "", "wyświetl wszystkie komendy", "Viser alle kommandoer", "", "Tüm komutları listele", "elencaa tutti i comandi") // TODO translate
MAKE_WORD_TRANSLATION(entities_cmd, "lists all entities", "Liste aller Entitäten", "lijst van alle entiteiten", "", "wyświetl wszsytkie encje", "Viser alle enheter", "", "Tüm varlıkları listele", "elenca tutte le entità") // TODO translate
@@ -73,6 +72,7 @@ MAKE_WORD_TRANSLATION(schedule_cmd, "enable schedule item", "Aktiviere Zeitplan"
MAKE_WORD_TRANSLATION(entity_cmd, "set custom value on ems", "Sende eigene Entitäten zu EMS", "verstuur custom waarde naar EMS", "", "wyślij własną wartość na EMS", "", "", "emp üzerinde özel değer ayarla", "imposta valori personalizzati su EMS") // TODO translate
MAKE_WORD_TRANSLATION(commands_response, "get response","Hole Antwort","Verzoek om antwoord", "", "", "", "uzyskaj odpowiedź", "", "", "gelen cevap", "") // TODO translate
MAKE_WORD_TRANSLATION(coldshot_cmd, "send a cold shot of water", "", "", "", "uruchom tryśnięcie zimnej wody", "", "", "soğuk su gönder", "") // TODO translate
MAKE_WORD_TRANSLATION(allvalues_cmd, "output all values", "", "", "", "", "", "", "", "") // TODO translate
// tags
MAKE_WORD_TRANSLATION(tag_boiler_data_ww, "dhw", "WW", "dhw", "VV", "CWU", "dhw", "ecs", "SKS", "dhw")
@@ -292,6 +292,7 @@ MAKE_TRANSLATION(wwtapactivated, "wwtapactivated", "turn on/off", "Durchlauferhi
MAKE_TRANSLATION(reset, "reset", "reset", "Reset", "Reset", "Nollställ", "kasowanie komunikatu", "nullstill", "reset", "Sıfırla", "Reset")
MAKE_TRANSLATION(oilPreHeat, "oilpreheat", "oil preheating", "Ölvorwärmung", "Olie voorverwarming", "Förvärmning olja", "podgrzewanie oleju", "oljeforvarming", "préchauffage de l'huile", "Yakıt Ön ısıtma devrede", "preriscaldamento olio")
MAKE_TRANSLATION(heatingActive, "heatingactive", "heating active", "Heizen aktiv", "Verwarming actief", "Uppvärmning aktiv", "c.o. aktywne", "oppvarming aktiv", "chauffage actif", "ısıtma devrede", "riscaldamento attivo")
MAKE_TRANSLATION(heatingOn, "heating", "heating", "Heizen", "verwarmen", "Uppvärmning", "ogrzewanie", "oppvarming", "chauffage", "ısıtma", "riscaldamento")
MAKE_TRANSLATION(tapwaterActive, "tapwateractive", "tapwater active", "Warmwasser aktiv", "Warm water actief", "Varmvatten aktiv", "c.w.u. aktywne", "varmtvann aktiv", "eau chaude active", "sıcak kullanım suyu devrede", "acqua calda attiva")
MAKE_TRANSLATION(selFlowTemp, "selflowtemp", "selected flow temperature", "Sollwert Vorlauftemperatur", "Ingestelde aanvoertemperatuur", "Börvärde Flödestemperatur", "wybrana temperatura zasilania", "valgt turtemperatur", "température de flux selectionnée", "seçili akış sıcaklığı", "flusso temperatura selezionato")
MAKE_TRANSLATION(selBurnPow, "selburnpow", "burner selected max power", "Sollwert Brennerleistung", "Ingestelde maximale brandervermogen", "Brännare vald maxeffekt", "wybrana moc źródła ciepła", "settpunkt brennerkapasitet", "puissance max du brûleur selectionnée", "seçili kazan maksimum güç", "Setpoint potenza bruciatore")
@@ -613,7 +614,7 @@ MAKE_TRANSLATION(wwChargeDuration, "wwchargeduration", "charge duration", "Laded
MAKE_TRANSLATION(wwDisinfect, "wwdisinfect", "disinfection", "Desinfektion", "Desinfectie", "Desinfektion", "dezynfekcja termiczna", "desinfeksjon", "désinfection", "dezenfeksiyon", "disinfezione")
MAKE_TRANSLATION(wwDisinfectDay, "wwdisinfectday", "disinfection day", "Desinfektionstag", "Desinfectiedag", "Desinfektionsdag", "dzień dezynfekcji termicznej", "desinfeksjonsdag", "jour désinfection", "dezenfeksiyon günü", "giorno disinfezione")
MAKE_TRANSLATION(wwDisinfectHour, "wwdisinfecthour", "disinfection hour", "Desinfektionsstunde", "Desinfectieuur", "Desinfektionstimme", "godzina dezynfekcji termicznej", "desinfeksjonstime", "heure désinfection", "dezenfeksiyon saati", "ora disinfezione")
MAKE_TRANSLATION(wwDisinfectTime, "wwdisinfecttime", "disinfection time", "Desinfektionsdauer", "Desinfectietijd", "Desinfektionstid", "maksymalny czas trwania dezynfekcji termicznej", "desinfeksjonstid", "durée désinfection", "dezenfeksiyon zamanı", "orario disinfezione")
MAKE_TRANSLATION(wwDisinfectTime, "wwdisinfecttime", "disinfection time", "Desinfektionszeit", "Desinfectietijd", "Desinfektionstid", "maksymalny czas trwania dezynfekcji termicznej", "desinfeksjonstid", "durée désinfection", "dezenfeksiyon zamanı", "orario disinfezione")
MAKE_TRANSLATION(wwDailyHeating, "wwdailyheating", "daily heating", "täglich Heizen", "Dagelijks opwarmen", "Daglig Uppvärmning", "codzienne nagrzewanie", "daglig oppvarming", "chauffage quotidien", "günlük ısıtma", "riscaldamento giornaliero")
MAKE_TRANSLATION(wwDailyHeatTime, "wwdailyheattime", "daily heating time", "tägliche Heizzeit", "Tijd dagelijkse opwarming", "Daglig Uppvärmningstid", "czas trwania codziennego nagrzewania", "daglig oppvarmingstid", "heure chauffage quotidien", "günlük ısıtma süresi", "orario riscaldamento giornaliero")

View File

@@ -730,21 +730,24 @@ bool Mqtt::queue_ha(const char * topic, const JsonObject & payload) {
bool Mqtt::publish_ha_sensor_config(DeviceValue & dv, const char * model, const char * brand, const bool remove, const bool create_device_config) {
StaticJsonDocument<EMSESP_JSON_SIZE_LARGE> dev_json;
// always create the ids
// always create the ids (discovery indentifiers)
// with the name always
// and the manufacturer and model if we're creating the device config for the first entity
JsonArray ids = dev_json.createNestedArray("ids");
char ha_device[40];
auto device_type_name = EMSdevice::device_type_2_device_name(dv.device_type);
snprintf(ha_device, sizeof(ha_device), "%s-%s", Mqtt::basename().c_str(), device_type_name);
ids.add(ha_device);
auto cap_name = strdup(device_type_name);
Helpers::CharToUpperUTF8(cap_name); // capitalize first letter
dev_json["name"] = Mqtt::basename() + " " + cap_name;
free(cap_name);
if (create_device_config) {
auto cap_name = strdup(device_type_name);
Helpers::CharToUpperUTF8(cap_name); // capitalize first letter
dev_json["name"] = Mqtt::basename() + " " + cap_name;
dev_json["mf"] = brand;
dev_json["mdl"] = model;
dev_json["via_device"] = "ems-esp";
free(cap_name);
}
// calculate the min and max
@@ -779,7 +782,8 @@ bool Mqtt::publish_system_ha_sensor_config(uint8_t type, const char * name, cons
StaticJsonDocument<EMSESP_JSON_SIZE_LARGE> doc;
JsonObject dev_json = doc.createNestedObject("dev");
JsonArray ids = dev_json.createNestedArray("ids");
dev_json["name"] = Mqtt::basename();
JsonArray ids = dev_json.createNestedArray("ids");
ids.add(Mqtt::basename());
return publish_ha_sensor_config(
@@ -1246,6 +1250,9 @@ bool Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp,
snprintf(ha_device, sizeof(ha_device), "%s-thermostat", Mqtt::basename().c_str());
ids.add(ha_device);
// device name must be different to the entity name, take the ids value we just created
dev["name"] = ha_device;
// add "availability" section
add_avty_to_doc(topic_t, doc.as<JsonObject>(), seltemp_cond, has_roomtemp ? currtemp_cond : nullptr, hc_mode_cond);

View File

@@ -211,7 +211,8 @@ void Shower::set_shower_state(bool state, bool force) {
}
JsonObject dev = doc.createNestedObject("dev");
JsonArray ids = dev.createNestedArray("ids");
dev["name"] = "EMS-ESP";
JsonArray ids = dev.createNestedArray("ids");
ids.add(Mqtt::basename());
Mqtt::add_avty_to_doc(stat_t, doc.as<JsonObject>()); // add "availability" section
@@ -240,7 +241,8 @@ void Shower::set_shower_state(bool state, bool force) {
doc["ent_cat"] = "diagnostic";
JsonObject dev2 = doc.createNestedObject("dev");
JsonArray ids2 = dev2.createNestedArray("ids");
dev2["name"] = "EMS-ESP";
JsonArray ids2 = dev2.createNestedArray("ids");
ids2.add(Mqtt::basename());
Mqtt::add_avty_to_doc(stat_t, doc.as<JsonObject>(), "value_json.duration is defined"); // add "availability" section
@@ -266,7 +268,8 @@ void Shower::set_shower_state(bool state, bool force) {
doc["ent_cat"] = "diagnostic";
JsonObject dev3 = doc.createNestedObject("dev");
JsonArray ids3 = dev3.createNestedArray("ids");
dev3["name"] = "EMS-ESP";
JsonArray ids3 = dev3.createNestedArray("ids");
ids3.add(Mqtt::basename());
Mqtt::add_avty_to_doc(stat_t, doc.as<JsonObject>(), "value_json.timestamp is defined"); // add "availability" section

View File

@@ -106,6 +106,31 @@ bool System::command_response(const char * value, const int8_t id, JsonObject &
return true;
}
// output all the EMS devices and their values, plus the sensors and any custom entities
// not scheduler as these are records with no output data
bool System::command_allvalues(const char * value, const int8_t id, JsonObject & output) {
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XXXLARGE);
JsonObject device_output;
for (const auto & emsdevice : EMSESP::emsdevices) {
std::string title = emsdevice->device_type_2_device_name_translated() + std::string(" ") + emsdevice->to_string();
device_output = output.createNestedObject(title);
emsesp::EMSdevice::export_values(emsdevice->unique_id(), device_output, id, EMSdevice::OUTPUT_TARGET::API_VERBOSE);
}
// Custom entities
device_output = output.createNestedObject("Custom Entities");
EMSESP::webCustomEntityService.get_value_info(device_output, "");
// Sensors
device_output = output.createNestedObject("Analog Sensors");
EMSESP::analogsensor_.command_info(nullptr, 0, device_output);
device_output = output.createNestedObject("Temperature Sensors");
EMSESP::temperaturesensor_.command_info(nullptr, 0, device_output);
return true;
}
// fetch device values
bool System::command_fetch(const char * value, const int8_t id) {
std::string value_s;
@@ -764,6 +789,7 @@ void System::commands_init() {
// restart and watch (and test) are also exposed as Console commands
Command::add(EMSdevice::DeviceType::SYSTEM, F_(restart), System::command_restart, FL_(restart_cmd), CommandFlag::ADMIN_ONLY);
Command::add(EMSdevice::DeviceType::SYSTEM, F_(watch), System::command_watch, FL_(watch_cmd));
#if defined(EMSESP_TEST)
Command::add(EMSdevice::DeviceType::SYSTEM, ("test"), System::command_test, FL_(test_cmd));
#endif
@@ -772,6 +798,8 @@ void System::commands_init() {
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("allvalues"), System::command_allvalues, FL_(allvalues_cmd));
// MQTT subscribe "ems-esp/system/#"
Mqtt::subscribe(EMSdevice::DeviceType::SYSTEM, "system/#", nullptr); // use empty function callback
@@ -903,6 +931,8 @@ void System::show_system(uuid::console::Shell & shell) {
refreshHeapMem(); // refresh free heap and max alloc heap
shell.println("System:");
shell.printfln(" Version: %s", EMSESP_APP_VERSION);
shell.printfln(" Language: %s", locale().c_str());
shell.printfln(" Board profile: %s", board_profile().c_str());
shell.printfln(" Uptime: %s", uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3).c_str());
#ifndef EMSESP_STANDALONE

View File

@@ -60,6 +60,8 @@ class System {
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_allvalues(const char * value, const int8_t id, JsonObject & output);
#if defined(EMSESP_TEST)
static bool command_test(const char * value, const int8_t id);
#endif

View File

@@ -544,7 +544,8 @@ void TemperatureSensor::publish_values(const bool force) {
config["name"] = name;
JsonObject dev = config.createNestedObject("dev");
JsonArray ids = dev.createNestedArray("ids");
dev["name"] = Mqtt::basename();
JsonArray ids = dev.createNestedArray("ids");
ids.add(Mqtt::basename());
// add "availability" section

View File

@@ -111,6 +111,8 @@ class TemperatureSensor {
bool update(const std::string & id, const std::string & name, int16_t offset);
bool command_info(const char * value, const int8_t id, JsonObject & output);
#if defined(EMSESP_TEST)
void test();
#endif
@@ -152,7 +154,6 @@ class TemperatureSensor {
uint64_t get_id(const uint8_t addr[]);
void remove_ha_topic(const std::string & id);
bool command_info(const char * value, const int8_t id, JsonObject & output);
bool command_commands(const char * value, const int8_t id, JsonObject & output);
std::vector<Sensor> sensors_; // our list of active sensors

View File

@@ -37,9 +37,8 @@ bool Test::run_test(const char * command, int8_t id) {
// simulate HansRemmerswaal's setup - see https://github.com/emsesp/EMS-ESP32/issues/859
add_device(0x08, 172); // 176 entities - boiler: Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i
// add_device(0x10, 158); // 62 entities - thermostat: RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410
// add_device(0x38, 200); // 4 entities - thermostat: RC100H
add_device(0x10, 158); // 62 entities - thermostat: RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410
add_device(0x38, 200); // 4 entities - thermostat: RC100H
return true;
}
@@ -47,9 +46,13 @@ bool Test::run_test(const char * command, int8_t id) {
if (strcmp(command, "general") == 0) {
EMSESP::logger().info("Testing general. Adding a Boiler and Thermostat");
// System::test_set_all_active(true); // uncomment if we want to show all entities and give them fake values
add_device(0x08, 123); // Nefit Trendline
add_device(0x18, 157); // Bosch CR100
// add_device(0x10, 158); // RC300 - there's no data here
// add some data
// Boiler -> Me, UBAMonitorFast(0x18), telegram: 08 00 18 00 00 02 5A 73 3D 0A 10 65 40 02 1A 80 00 01 E1 01 76 0E 3D 48 00 C9 44 02 00 (#data=25)
uart_telegram({0x08, 0x00, 0x18, 0x00, 0x00, 0x02, 0x5A, 0x73, 0x3D, 0x0A, 0x10, 0x65, 0x40, 0x02, 0x1A,
@@ -275,11 +278,17 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
bool ok = false;
if (command == "general") {
shell.printfln("Testing adding a general boiler & thermostat...");
shell.printfln("Testing adding a boiler, thermostat and sensors...");
run_test("general");
// add sensors
emsesp::EMSESP::analogsensor_.test();
emsesp::EMSESP::temperaturesensor_.test();
// shell.invoke_command("show devices");
shell.invoke_command("show values");
shell.invoke_command("call system publish");
shell.invoke_command("call system allvalues");
// shell.invoke_command("call system publish");
// shell.invoke_command("show mqtt");
ok = true;
}

View File

@@ -34,6 +34,7 @@ namespace emsesp {
static QueueHandle_t uart_queue;
uint8_t tx_mode_ = 0xFF;
uint32_t inverse_mask = 0;
/*
* receive task, wait for break and call incoming_telegram
@@ -82,8 +83,15 @@ void EMSuart::start(const uint8_t tx_mode, const uint8_t rx_gpio, const uint8_t
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
#if defined(EMSUART_RX_INVERT)
inverse_mask |= UART_SIGNAL_RXD_INV;
#endif
#if defined(EMSUART_TX_INVERT)
inverse_mask |= UART_SIGNAL_TXD_INV;
#endif
uart_param_config(EMSUART_NUM, &uart_config);
uart_set_pin(EMSUART_NUM, tx_gpio, rx_gpio, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_set_line_inverse(EMSUART_NUM, inverse_mask);
uart_driver_install(EMSUART_NUM, 129, 0, (EMS_MAXBUFFERSIZE + 1) * 2, &uart_queue, 0); // buffer must be > fifo
uart_set_rx_full_threshold(EMSUART_NUM, 1);
uart_set_rx_timeout(EMSUART_NUM, 0); // disable
@@ -136,9 +144,9 @@ uint16_t EMSuart::transmit(const uint8_t * buf, const uint8_t len) {
uart_write_bytes(EMSUART_NUM, &buf[i], 1);
delayMicroseconds(EMSUART_TX_WAIT_PLUS);
}
uart_set_line_inverse(EMSUART_NUM, UART_SIGNAL_TXD_INV);
uart_set_line_inverse(EMSUART_NUM, UART_SIGNAL_TXD_INV ^ inverse_mask);
delayMicroseconds(EMSUART_TX_BRK_PLUS);
uart_set_line_inverse(EMSUART_NUM, 0);
uart_set_line_inverse(EMSUART_NUM, inverse_mask);
return EMS_TX_STATUS_OK;
}
@@ -147,9 +155,9 @@ uint16_t EMSuart::transmit(const uint8_t * buf, const uint8_t len) {
uart_write_bytes(EMSUART_NUM, &buf[i], 1);
delayMicroseconds(EMSUART_TX_WAIT_HT3);
}
uart_set_line_inverse(EMSUART_NUM, UART_SIGNAL_TXD_INV);
uart_set_line_inverse(EMSUART_NUM, UART_SIGNAL_TXD_INV ^ inverse_mask);
delayMicroseconds(EMSUART_TX_BRK_HT3);
uart_set_line_inverse(EMSUART_NUM, 0);
uart_set_line_inverse(EMSUART_NUM, inverse_mask);
return EMS_TX_STATUS_OK;
}
@@ -164,9 +172,9 @@ uint16_t EMSuart::transmit(const uint8_t * buf, const uint8_t len) {
uart_get_buffered_data_len(EMSUART_NUM, &rx1);
} while ((rx1 == rx0) && (--timeoutcnt));
}
uart_set_line_inverse(EMSUART_NUM, UART_SIGNAL_TXD_INV);
uart_set_line_inverse(EMSUART_NUM, UART_SIGNAL_TXD_INV ^ inverse_mask);
delayMicroseconds(EMSUART_TX_BRK_EMS);
uart_set_line_inverse(EMSUART_NUM, 0);
uart_set_line_inverse(EMSUART_NUM, inverse_mask);
return EMS_TX_STATUS_OK;
}

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.6.3-test.7"
#define EMSESP_APP_VERSION "3.6.3-test.8"

View File

@@ -182,7 +182,8 @@ bool WebCustomEntityService::command_setvalue(const char * value, const std::str
}
// output of a single value
void WebCustomEntityService::render_value(JsonObject & output, CustomEntityItem entity, const bool useVal, const bool web) {
// if add_uom is true it will add the UOM string to the value
void WebCustomEntityService::render_value(JsonObject & output, CustomEntityItem entity, const bool useVal, const bool web, const bool add_uom) {
char payload[12];
std::string name = useVal ? "value" : entity.name;
switch (entity.value_type) {
@@ -201,28 +202,33 @@ void WebCustomEntityService::render_value(JsonObject & output, CustomEntityItem
break;
case DeviceValueType::INT:
if ((int8_t)entity.value != EMS_VALUE_INT_NOTSET) {
output[name] = serialized(Helpers::render_value(payload, entity.factor * (int8_t)entity.value, 2));
std::string v = Helpers::render_value(payload, entity.factor * (int8_t)entity.value, 2);
output[name] = add_uom ? serialized(v + ' ' + EMSdevice::uom_to_string(entity.uom)) : serialized(v);
}
break;
case DeviceValueType::UINT:
if ((uint8_t)entity.value != EMS_VALUE_UINT_NOTSET) {
output[name] = serialized(Helpers::render_value(payload, entity.factor * (uint8_t)entity.value, 2));
std::string v = Helpers::render_value(payload, entity.factor * (uint8_t)entity.value, 2);
output[name] = add_uom ? serialized(v + ' ' + EMSdevice::uom_to_string(entity.uom)) : serialized(v);
}
break;
case DeviceValueType::SHORT:
if ((int16_t)entity.value != EMS_VALUE_SHORT_NOTSET) {
output[name] = serialized(Helpers::render_value(payload, entity.factor * (int16_t)entity.value, 2));
std::string v = Helpers::render_value(payload, entity.factor * (int16_t)entity.value, 2);
output[name] = add_uom ? serialized(v + ' ' + EMSdevice::uom_to_string(entity.uom)) : serialized(v);
}
break;
case DeviceValueType::USHORT:
if ((uint16_t)entity.value != EMS_VALUE_USHORT_NOTSET) {
output[name] = serialized(Helpers::render_value(payload, entity.factor * (uint16_t)entity.value, 2));
std::string v = Helpers::render_value(payload, entity.factor * (uint16_t)entity.value, 2);
output[name] = add_uom ? serialized(v + ' ' + EMSdevice::uom_to_string(entity.uom)) : serialized(v);
}
break;
case DeviceValueType::ULONG:
case DeviceValueType::TIME:
if (entity.value != EMS_VALUE_ULONG_NOTSET) {
output[name] = serialized(Helpers::render_value(payload, entity.factor * entity.value, 2));
std::string v = Helpers::render_value(payload, entity.factor * entity.value, 2);
output[name] = add_uom ? serialized(v + ' ' + EMSdevice::uom_to_string(entity.uom)) : serialized(v);
}
break;
case DeviceValueType::STRING:
@@ -236,6 +242,15 @@ void WebCustomEntityService::render_value(JsonObject & output, CustomEntityItem
}
}
// display all custom entities
// adding each one, with UOM to a json object string
void WebCustomEntityService::show_values(JsonObject & output) {
for (const CustomEntityItem & entity : *customEntityItems) {
render_value(output, entity, false, false, true); // with add_uom
}
}
// process json output for info/commands and value_info
bool WebCustomEntityService::get_value_info(JsonObject & output, const char * cmd) {
EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; });
@@ -247,11 +262,13 @@ bool WebCustomEntityService::get_value_info(JsonObject & output, const char * cm
}
return true;
}
// if no entries, return empty json
// https://github.com/emsesp/EMS-ESP32/issues/1297
if (customEntityItems->size() == 0) {
return true;
}
if (strlen(cmd) == 0 || Helpers::toLower(cmd) == F_(values) || Helpers::toLower(cmd) == F_(info)) {
// list all names
for (const CustomEntityItem & entity : *customEntityItems) {
@@ -410,7 +427,8 @@ void WebCustomEntityService::publish(const bool force) {
}
}
JsonObject dev = config.createNestedObject("dev");
JsonArray ids = dev.createNestedArray("ids");
dev["name"] = Mqtt::basename();
JsonArray ids = dev.createNestedArray("ids");
ids.add(Mqtt::basename());
// add "availability" section

View File

@@ -52,22 +52,23 @@ class WebCustomEntityService : public StatefulService<WebCustomEntity> {
public:
WebCustomEntityService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager);
void begin();
void publish_single(const CustomEntityItem & entity);
void publish(const bool force = false);
bool command_setvalue(const char * value, const std::string name);
bool get_value_info(JsonObject & output, const char * cmd);
bool get_value(std::shared_ptr<const Telegram> telegram);
void fetch();
void render_value(JsonObject & output, CustomEntityItem entity, const bool useVal = false, const bool web = false);
void begin();
void publish_single(const CustomEntityItem & entity);
void publish(const bool force = false);
bool command_setvalue(const char * value, const std::string name);
bool get_value_info(JsonObject & output, const char * cmd);
bool get_value(std::shared_ptr<const Telegram> telegram);
void fetch();
void render_value(JsonObject & output, CustomEntityItem entity, const bool useVal = false, const bool web = false, const bool add_uom = false);
void show_values(JsonObject & output);
void generate_value_web(JsonObject & output);
uint8_t count_entities();
uint8_t has_commands();
void generate_value_web(JsonObject & output);
void ha_reset() {
ha_registered_ = false;
}
private:
HttpEndpoint<WebCustomEntity> _httpEndpoint;
FSPersistence<WebCustomEntity> _fsPersistence;

View File

@@ -99,7 +99,7 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization &
#ifdef EMSESP_STANDALONE
// invoke some fake data for testing
const char * json = "{\"ts\":[],\"as\":[],\"masked_entities\":[{\"product_id\":123,\"device_id\":8,\"entity_ids\":[\"08heatingactive|my custom "
"name for heating active\",\"08tapwateractive\"]}]}";
"name for heating active (HS1)\",\"08tapwateractive\"]}]}";
StaticJsonDocument<500> doc;
deserializeJson(doc, json);
root = doc.as<JsonObject>();

View File

@@ -230,17 +230,23 @@ void WebDataService::device_data(AsyncWebServerRequest * request) {
// assumes the service has been checked for admin authentication
void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVariant & json) {
if (json.is<JsonObject>()) {
JsonObject dv = json["devicevalue"];
uint8_t unique_id = json["id"];
uint8_t unique_id = json["id"]; // unique ID
const char * cmd = json["c"]; // the command
JsonVariant data = json["v"]; // the value in any format
// quit on bad values
if (strlen(cmd) == 0 || data.isNull()) {
AsyncWebServerResponse * response = request->beginResponse(400); // bad request
request->send(response);
return;
}
// using the unique ID from the web find the real device type
// id is the selected device
for (const auto & emsdevice : EMSESP::emsdevices) {
if (emsdevice->unique_id() == unique_id) {
// parse the command as it could have a hc or wwc prefixed, e.g. hc2/seltemp
const char * cmd = dv["c"]; // the command
int8_t id = -1; // default
cmd = Command::parse_command_string(cmd, id); // extract hc or wwc
int8_t id = -1; // default
cmd = Command::parse_command_string(cmd, id); // extract hc or wwc
// create JSON for output
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_SMALL);
@@ -248,9 +254,8 @@ void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVar
// the data could be in any format, but we need string
// authenticated is always true
JsonVariant data = dv["v"]; // the value in any format
uint8_t return_code = CommandRet::NOT_FOUND;
uint8_t device_type = emsdevice->device_type();
uint8_t return_code = CommandRet::NOT_FOUND;
uint8_t device_type = emsdevice->device_type();
if (data.is<const char *>()) {
return_code = Command::call(device_type, cmd, data.as<const char *>(), true, id, output);
} else if (data.is<int>()) {
@@ -278,16 +283,16 @@ void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVar
return;
}
}
// special check for custom entities (which have a unique id of 99)
if (unique_id == 99) {
// parse the command as it could have a hc or wwc prefixed, e.g. hc2/seltemp
const char * cmd = dv["c"];
int8_t id = -1;
cmd = Command::parse_command_string(cmd, id);
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_SMALL);
JsonObject output = response->getRoot();
JsonVariant data = dv["v"]; // the value in any format
uint8_t return_code = CommandRet::NOT_FOUND;
uint8_t device_type = EMSdevice::DeviceType::CUSTOM;
int8_t id = -1;
cmd = Command::parse_command_string(cmd, id);
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_SMALL);
JsonObject output = response->getRoot();
uint8_t return_code = CommandRet::NOT_FOUND;
uint8_t device_type = EMSdevice::DeviceType::CUSTOM;
if (data.is<const char *>()) {
return_code = Command::call(device_type, cmd, data.as<const char *>(), true, id, output);
} else if (data.is<int>()) {
@@ -304,6 +309,7 @@ void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVar
EMSESP::logger().debug("Write command successful");
#endif
}
response->setCode((return_code == CommandRet::OK) ? 200 : 400); // bad request
response->setLength();
request->send(response);
@@ -311,6 +317,7 @@ void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVar
}
}
// if we reach here, fail
AsyncWebServerResponse * response = request->beginResponse(400); // bad request
request->send(response);
}

View File

@@ -288,7 +288,8 @@ void WebSchedulerService::publish(const bool force) {
}
JsonObject dev = config.createNestedObject("dev");
JsonArray ids = dev.createNestedArray("ids");
dev["name"] = Mqtt::basename();
JsonArray ids = dev.createNestedArray("ids");
ids.add(Mqtt::basename());
// add "availability" section