diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index d3cb3a10b..91bc9e8cf 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -2,7 +2,7 @@ For more details go to [docs.emsesp.org](https://docs.emsesp.org/). -## [3.7.3] +## [3.8.0] ## Added @@ -38,6 +38,9 @@ For more details go to [docs.emsesp.org](https://docs.emsesp.org/). - added LWT (Last Will and Testament) to MQTT entities in Home Assistant - added api/metrics endpoint for prometheus integration by @gr3enk [#2774](https://github.com/emsesp/EMS-ESP32/pull/2774) - added RTL8201 to eth phy list [#2800](https://github.com/emsesp/EMS-ESP32/issues/2800) +- added partitions to Web UI Version page, so previous firmware versions can be installed [#2837](https://github.com/emsesp/EMS-ESP32/issues/2837) +- button pressures show LED. On a long press (10 seconds) the LED flashes for 5 seconds to indicate a factory reset is about to happen. [#2848](https://github.com/emsesp/EMS-ESP32/issues/2848) +- added `txpause` command to pause the TX, by setting Txmode to 0 (disabled) [#2850](https://github.com/emsesp/EMS-ESP32/issues/2850) ## Fixed @@ -59,6 +62,7 @@ For more details go to [docs.emsesp.org](https://docs.emsesp.org/). - syslog timestamp [#2704](https://github.com/emsesp/EMS-ESP32/issues/2704) - fixed FS format command [#2720](https://github.com/emsesp/EMS-ESP32/discussions/2720) - dhw priority setting to boiler and mixer, telegrams 0x2CC, 0x2CD, etc. +- check for valid GPIOs when board profile is changed [#2841](https://github.com/emsesp/EMS-ESP32/issues/2841) ## Changed @@ -81,3 +85,4 @@ For more details go to [docs.emsesp.org](https://docs.emsesp.org/). - move vectors and lists to PSRAM - removed unused last topic/payload echo-check - added Home Assistant device details to MQTT Discovery for all devices +- device_class and state_class changes for HA MQTT Discovery [#2825](https://github.com/emsesp/EMS-ESP32/issues/2825) diff --git a/Makefile b/Makefile index 51e990b4c..fdab1d661 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,7 @@ DEFINES += -DARDUINOJSON_ENABLE -DARDUINOJSON_ENABLE_ARDUINO_STRING -DARDUINOJSO DEFINES += -DEMSESP_STANDALONE -DEMSESP_TEST -DEMSESP_DEBUG -DEMC_RX_BUFFER_SIZE=1500 DEFINES += $(ARGS) -DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.7.3-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32S3\" +DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.8.0-dev.0\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32S3\" #---------------------------------------------------------------------- # Sources & Files diff --git a/interface/package.json b/interface/package.json index b32094173..60834c6ea 100644 --- a/interface/package.json +++ b/interface/package.json @@ -1,6 +1,6 @@ { "name": "EMS-ESP", - "version": "3.7.3", + "version": "3.8.0", "description": "EMS-ESP WebUI", "homepage": "https://emsesp.org", "author": "proddy, emsesp.org", @@ -37,7 +37,7 @@ "jwt-decode": "^4.0.0", "magic-string": "^0.30.21", "mime-types": "^3.0.2", - "preact": "^10.28.0", + "preact": "^10.28.1", "react": "^19.2.3", "react-dom": "^19.2.3", "react-icons": "^5.5.0", @@ -62,10 +62,10 @@ "prettier": "^3.7.4", "rollup-plugin-visualizer": "^6.0.5", "terser": "^5.44.1", - "typescript-eslint": "^8.50.0", + "typescript-eslint": "^8.50.1", "vite": "^7.3.0", "vite-plugin-imagemin": "^0.6.1", "vite-tsconfig-paths": "^6.0.3" }, - "packageManager": "pnpm@10.26.1+sha512.664074abc367d2c9324fdc18037097ce0a8f126034160f709928e9e9f95d98714347044e5c3164d65bd5da6c59c6be362b107546292a8eecb7999196e5ce58fa" + "packageManager": "pnpm@10.26.2+sha512.0e308ff2005fc7410366f154f625f6631ab2b16b1d2e70238444dd6ae9d630a8482d92a451144debc492416896ed16f7b114a86ec68b8404b2443869e68ffda6" } diff --git a/interface/pnpm-lock.yaml b/interface/pnpm-lock.yaml index d255316e1..c15ed5094 100644 --- a/interface/pnpm-lock.yaml +++ b/interface/pnpm-lock.yaml @@ -25,7 +25,7 @@ importers: version: 7.3.6(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.3))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.3))(@types/react@19.2.7)(react@19.2.3))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@preact/compat': specifier: ^18.3.1 - version: 18.3.1(preact@10.28.0) + version: 18.3.1(preact@10.28.1) '@table-library/react-table-library': specifier: 4.1.15 version: 4.1.15(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -51,8 +51,8 @@ importers: specifier: ^3.0.2 version: 3.0.2 preact: - specifier: ^10.28.0 - version: 10.28.0 + specifier: ^10.28.1 + version: 10.28.1 react: specifier: ^19.2.3 version: 19.2.3 @@ -83,7 +83,7 @@ importers: version: 9.39.2 '@preact/preset-vite': specifier: ^2.10.2 - version: 2.10.2(@babel/core@7.28.5)(preact@10.28.0)(vite@7.3.0(@types/node@25.0.3)(terser@5.44.1)) + version: 2.10.2(@babel/core@7.28.5)(preact@10.28.1)(vite@7.3.0(@types/node@25.0.3)(terser@5.44.1)) '@trivago/prettier-plugin-sort-imports': specifier: ^6.0.0 version: 6.0.0(prettier@3.7.4) @@ -118,8 +118,8 @@ importers: specifier: ^5.44.1 version: 5.44.1 typescript-eslint: - specifier: ^8.50.0 - version: 8.50.0(eslint@9.39.2)(typescript@5.9.3) + specifier: ^8.50.1 + version: 8.50.1(eslint@9.39.2)(typescript@5.9.3) vite: specifier: ^7.3.0 version: 7.3.0(@types/node@25.0.3)(terser@5.44.1) @@ -888,63 +888,63 @@ packages: '@types/svgo@2.6.4': resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==} - '@typescript-eslint/eslint-plugin@8.50.0': - resolution: {integrity: sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==} + '@typescript-eslint/eslint-plugin@8.50.1': + resolution: {integrity: sha512-PKhLGDq3JAg0Jk/aK890knnqduuI/Qj+udH7wCf0217IGi4gt+acgCyPVe79qoT+qKUvHMDQkwJeKW9fwl8Cyw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.50.0 + '@typescript-eslint/parser': ^8.50.1 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.50.0': - resolution: {integrity: sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==} + '@typescript-eslint/parser@8.50.1': + resolution: {integrity: sha512-hM5faZwg7aVNa819m/5r7D0h0c9yC4DUlWAOvHAtISdFTc8xB86VmX5Xqabrama3wIPJ/q9RbGS1worb6JfnMg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.50.0': - resolution: {integrity: sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==} + '@typescript-eslint/project-service@8.50.1': + resolution: {integrity: sha512-E1ur1MCVf+YiP89+o4Les/oBAVzmSbeRB0MQLfSlYtbWU17HPxZ6Bhs5iYmKZRALvEuBoXIZMOIRRc/P++Ortg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.50.0': - resolution: {integrity: sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==} + '@typescript-eslint/scope-manager@8.50.1': + resolution: {integrity: sha512-mfRx06Myt3T4vuoHaKi8ZWNTPdzKPNBhiblze5N50//TSHOAQQevl/aolqA/BcqqbJ88GUnLqjjcBc8EWdBcVw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.50.0': - resolution: {integrity: sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==} + '@typescript-eslint/tsconfig-utils@8.50.1': + resolution: {integrity: sha512-ooHmotT/lCWLXi55G4mvaUF60aJa012QzvLK0Y+Mp4WdSt17QhMhWOaBWeGTFVkb2gDgBe19Cxy1elPXylslDw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.50.0': - resolution: {integrity: sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==} + '@typescript-eslint/type-utils@8.50.1': + resolution: {integrity: sha512-7J3bf022QZE42tYMO6SL+6lTPKFk/WphhRPe9Tw/el+cEwzLz1Jjz2PX3GtGQVxooLDKeMVmMt7fWpYRdG5Etg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.50.0': - resolution: {integrity: sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==} + '@typescript-eslint/types@8.50.1': + resolution: {integrity: sha512-v5lFIS2feTkNyMhd7AucE/9j/4V9v5iIbpVRncjk/K0sQ6Sb+Np9fgYS/63n6nwqahHQvbmujeBL7mp07Q9mlA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.50.0': - resolution: {integrity: sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==} + '@typescript-eslint/typescript-estree@8.50.1': + resolution: {integrity: sha512-woHPdW+0gj53aM+cxchymJCrh0cyS7BTIdcDxWUNsclr9VDkOSbqC13juHzxOmQ22dDkMZEpZB+3X1WpUvzgVQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.50.0': - resolution: {integrity: sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==} + '@typescript-eslint/utils@8.50.1': + resolution: {integrity: sha512-lCLp8H1T9T7gPbEuJSnHwnSuO9mDf8mfK/Nion5mZmiEaQD9sWf9W4dfeFqRyqRjF06/kBuTmAqcs9sewM2NbQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.50.0': - resolution: {integrity: sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==} + '@typescript-eslint/visitor-keys@8.50.1': + resolution: {integrity: sha512-IrDKrw7pCRUR94zeuCSUWQ+w8JEf5ZX5jl/e6AHGSLi1/zIr0lgutfn/7JpfCey+urpgQEdrZVYzCaVVKiTwhQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} acorn-jsx@5.3.2: @@ -1614,8 +1614,8 @@ packages: resolution: {integrity: sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==} hasBin: true - fastq@1.19.1: - resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} @@ -2460,8 +2460,8 @@ packages: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} - preact@10.28.0: - resolution: {integrity: sha512-rytDAoiXr3+t6OIP3WGlDd0ouCUG1iCWzkcY3++Nreuoi17y6T5i/zRhe6uYfoVcxq6YU+sBtJouuRDsq8vvqA==} + preact@10.28.1: + resolution: {integrity: sha512-u1/ixq/lVQI0CakKNvLDEcW5zfCjUQfZdK9qqWuIJtsezuyG6pk9TWj75GMuI/EzRSZB/VAE43sNWWZfiy8psw==} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} @@ -2884,8 +2884,8 @@ packages: resolution: {integrity: sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==} engines: {node: '>=0.10.0'} - ts-api-utils@2.1.0: - resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + ts-api-utils@2.3.0: + resolution: {integrity: sha512-6eg3Y9SF7SsAvGzRHQvvc1skDAhwI4YQ32ui1scxD1Ccr0G5qIIbUBT3pFTKX8kmWIQClHobtUdNuaBgwdfdWg==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -2924,8 +2924,8 @@ packages: peerDependencies: typescript: '>=3.5.1' - typescript-eslint@8.50.0: - resolution: {integrity: sha512-Q1/6yNUmCpH94fbgMUMg2/BSAr/6U7GBk61kZTv1/asghQOWOjTlp9K8mixS5NcJmm2creY+UFfGeW/+OcA64A==} + typescript-eslint@8.50.1: + resolution: {integrity: sha512-ytTHO+SoYSbhAH9CrYnMhiLx8To6PSSvqnvXyPUgPETCvB6eBKmTI9w6XMPS3HsBRGkwTVBX+urA8dYQx6bHfQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -3583,7 +3583,7 @@ snapshots: '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.19.1 + fastq: 1.20.1 '@paralleldrive/cuid2@2.3.1': dependencies: @@ -3591,16 +3591,16 @@ snapshots: '@popperjs/core@2.11.8': {} - '@preact/compat@18.3.1(preact@10.28.0)': + '@preact/compat@18.3.1(preact@10.28.1)': dependencies: - preact: 10.28.0 + preact: 10.28.1 - '@preact/preset-vite@2.10.2(@babel/core@7.28.5)(preact@10.28.0)(vite@7.3.0(@types/node@25.0.3)(terser@5.44.1))': + '@preact/preset-vite@2.10.2(@babel/core@7.28.5)(preact@10.28.1)(vite@7.3.0(@types/node@25.0.3)(terser@5.44.1))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.5) '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.5) - '@prefresh/vite': 2.4.11(preact@10.28.0)(vite@7.3.0(@types/node@25.0.3)(terser@5.44.1)) + '@prefresh/vite': 2.4.11(preact@10.28.1)(vite@7.3.0(@types/node@25.0.3)(terser@5.44.1)) '@rollup/pluginutils': 4.2.1 babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.28.5) debug: 4.4.3 @@ -3613,20 +3613,20 @@ snapshots: '@prefresh/babel-plugin@0.5.2': {} - '@prefresh/core@1.5.9(preact@10.28.0)': + '@prefresh/core@1.5.9(preact@10.28.1)': dependencies: - preact: 10.28.0 + preact: 10.28.1 '@prefresh/utils@1.2.1': {} - '@prefresh/vite@2.4.11(preact@10.28.0)(vite@7.3.0(@types/node@25.0.3)(terser@5.44.1))': + '@prefresh/vite@2.4.11(preact@10.28.1)(vite@7.3.0(@types/node@25.0.3)(terser@5.44.1))': dependencies: '@babel/core': 7.28.5 '@prefresh/babel-plugin': 0.5.2 - '@prefresh/core': 1.5.9(preact@10.28.0) + '@prefresh/core': 1.5.9(preact@10.28.1) '@prefresh/utils': 1.2.1 '@rollup/pluginutils': 4.2.1 - preact: 10.28.0 + preact: 10.28.1 vite: 7.3.0(@types/node@25.0.3)(terser@5.44.1) transitivePeerDependencies: - supports-color @@ -3803,95 +3803,95 @@ snapshots: dependencies: '@types/node': 25.0.3 - '@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.50.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/type-utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/parser': 8.50.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.50.1 + '@typescript-eslint/type-utils': 8.50.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/utils': 8.50.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.50.1 eslint: 9.39.2 ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.9.3) + ts-api-utils: 2.3.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/scope-manager': 8.50.1 + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.50.1 debug: 4.4.3 eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.50.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.50.1(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3) - '@typescript-eslint/types': 8.50.0 + '@typescript-eslint/tsconfig-utils': 8.50.1(typescript@5.9.3) + '@typescript-eslint/types': 8.50.1 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.50.0': + '@typescript-eslint/scope-manager@8.50.1': dependencies: - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/visitor-keys': 8.50.1 - '@typescript-eslint/tsconfig-utils@8.50.0(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.50.1(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.50.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.50.1(eslint@9.39.2)(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.50.1(eslint@9.39.2)(typescript@5.9.3) debug: 4.4.3 eslint: 9.39.2 - ts-api-utils: 2.1.0(typescript@5.9.3) + ts-api-utils: 2.3.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.50.0': {} + '@typescript-eslint/types@8.50.1': {} - '@typescript-eslint/typescript-estree@8.50.0(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.50.1(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.50.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3) - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/project-service': 8.50.1(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.50.1(typescript@5.9.3) + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/visitor-keys': 8.50.1 debug: 4.4.3 minimatch: 9.0.5 semver: 7.7.3 tinyglobby: 0.2.15 - ts-api-utils: 2.1.0(typescript@5.9.3) + ts-api-utils: 2.3.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.50.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/utils@8.50.1(eslint@9.39.2)(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2) - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.50.1 + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.50.0': + '@typescript-eslint/visitor-keys@8.50.1': dependencies: - '@typescript-eslint/types': 8.50.0 + '@typescript-eslint/types': 8.50.1 eslint-visitor-keys: 4.2.1 acorn-jsx@5.3.2(acorn@8.15.0): @@ -4662,7 +4662,7 @@ snapshots: dependencies: strnum: 1.1.2 - fastq@1.19.1: + fastq@1.20.1: dependencies: reusify: 1.1.0 @@ -5473,7 +5473,7 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - preact@10.28.0: {} + preact@10.28.1: {} prelude-ls@1.2.1: {} @@ -5882,7 +5882,7 @@ snapshots: dependencies: escape-string-regexp: 1.0.5 - ts-api-utils@2.1.0(typescript@5.9.3): + ts-api-utils@2.3.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -5912,12 +5912,12 @@ snapshots: dependencies: typescript: 5.9.3 - typescript-eslint@8.50.0(eslint@9.39.2)(typescript@5.9.3): + typescript-eslint@8.50.1(eslint@9.39.2)(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.50.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/parser': 8.50.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.50.1(eslint@9.39.2)(typescript@5.9.3) eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: diff --git a/interface/src/app/status/Version.tsx b/interface/src/app/status/Version.tsx index f033224e4..17a452f4a 100644 --- a/interface/src/app/status/Version.tsx +++ b/interface/src/app/status/Version.tsx @@ -60,6 +60,13 @@ const DEV_RELNOTES_URL = 'https://github.com/emsesp/EMS-ESP32/blob/dev/CHANGELOG_LATEST.md'; // Types for better type safety +interface PartitionData { + partition: string; + version: string; + install_date?: string; + size: number; +} + interface VersionData { emsesp_version: string; arduino_version: string; @@ -67,6 +74,9 @@ interface VersionData { flash_chip_size: number; psram: boolean; build_flags?: string; + partition: string; + partitions: PartitionData[]; + developer_mode: boolean; } interface UpgradeCheckData { @@ -86,6 +96,10 @@ const VersionInfoDialog = memo( showVersionInfo, latestVersion, latestDevVersion, + partitionVersion, + partition, + currentPartition, + size, locale, LL, onClose @@ -93,6 +107,10 @@ const VersionInfoDialog = memo( showVersionInfo: number; latestVersion?: VersionInfo; latestDevVersion?: VersionInfo; + partitionVersion?: VersionInfo | undefined; + partition: string; + currentPartition: string; + size: number; locale: string; LL: TranslationFunctions; onClose: () => void; @@ -100,8 +118,19 @@ const VersionInfoDialog = memo( if (showVersionInfo === 0) return null; const isStable = showVersionInfo === 1; - const version = isStable ? latestVersion : latestDevVersion; - const relNotesUrl = isStable ? STABLE_RELNOTES_URL : DEV_RELNOTES_URL; + const isDev = showVersionInfo === 2; + const isPartition = showVersionInfo === 3; + + const version = isStable + ? latestVersion + : isDev + ? latestDevVersion + : partitionVersion; + const relNotesUrl = isStable + ? STABLE_RELNOTES_URL + : isDev + ? DEV_RELNOTES_URL + : ''; return ( @@ -118,14 +147,17 @@ const VersionInfoDialog = memo( borderBottom: 'none', pr: 1, py: 0.5, - fontSize: 13, - width: 90 + fontSize: 13 }} > - {LL.TYPE(0)} + {LL.VERSION()} - {isStable ? LL.STABLE() : LL.DEVELOPMENT()} + {isPartition + ? typeof version === 'string' + ? version + : version?.name + : version?.name} @@ -137,15 +169,61 @@ const VersionInfoDialog = memo( borderBottom: 'none', pr: 1, py: 0.5, - fontSize: 13 + fontSize: 13, + width: 140 }} > - {LL.VERSION()} + {isPartition ? LL.TYPE(0) : LL.RELEASE_TYPE()} - {version?.name} + {partition === currentPartition && LL.ACTIVE() + ' '} + {isStable + ? LL.STABLE() + : isDev + ? LL.DEVELOPMENT() + : 'Partition ' + LL.VERSION()} + {isPartition && ( + + + Partition + + + {partition} + + + )} + {isPartition && ( + + + Size + + + {size} KB + + + )} {version?.published_at && ( - Build Date + {isPartition ? 'Install Date' : 'Build Date'} {prettyDateTime(locale, new Date(version.published_at))} @@ -170,15 +248,17 @@ const VersionInfoDialog = memo( - + {!isPartition && ( + + )} @@ -224,7 +304,7 @@ const InstallDialog = memo( return ( - {`${LL.UPDATE()} ${fetchDevVersion ? LL.DEVELOPMENT() : LL.STABLE()} Firmware`} + {`${LL.INSTALL()} ${fetchDevVersion ? LL.DEVELOPMENT() : LL.STABLE()} Firmware`} @@ -269,6 +349,54 @@ const InstallDialog = memo( } ); +const InstallPartitionDialog = memo( + ({ + openInstallPartitionDialog, + version, + partition, + LL, + onClose, + onInstall + }: { + openInstallPartitionDialog: boolean; + version: string; + partition: string; + LL: TranslationFunctions; + onClose: () => void; + onInstall: (partition: string) => void; + }) => { + return ( + + + {LL.INSTALL()} {LL.STORED_VERSIONS()} + + + {LL.INSTALL_VERSION(LL.INSTALL(), version)} + + + + + + + + ); + } +); + // Helper function moved outside component const getPlatform = (data: VersionData): string => { return `${data.esp_platform}-${data.flash_chip_size >= 16384 ? '16MB' : '4MB'}${data.psram ? '+' : ''}`; @@ -281,6 +409,14 @@ const Version = () => { // State management const [restarting, setRestarting] = useState(false); const [openInstallDialog, setOpenInstallDialog] = useState(false); + + const [partitionVersion, setPartitionVersion] = useState( + undefined + ); + const [partition, setPartition] = useState(''); + const [openInstallPartitionDialog, setOpenInstallPartitionDialog] = + useState(false); + const [usingDevVersion, setUsingDevVersion] = useState(false); const [fetchDevVersion, setFetchDevVersion] = useState(false); const [devUpgradeAvailable, setDevUpgradeAvailable] = useState(false); @@ -288,7 +424,8 @@ const Version = () => { useState(false); const [internetLive, setInternetLive] = useState(false); const [downloadOnly, setDownloadOnly] = useState(false); - const [showVersionInfo, setShowVersionInfo] = useState(0); + const [showVersionInfo, setShowVersionInfo] = useState(0); // 1 = stable, 2 = dev, 3 = partition + const [firmwareSize, setFirmwareSize] = useState(0); const { send: sendCheckUpgrade } = useRequest( (versions: string) => callAction({ action: 'checkUpgrade', param: versions }), @@ -299,6 +436,13 @@ const Version = () => { setStableUpgradeAvailable(data.stable_upgradeable); }); + const { send: sendSetPartition } = useRequest( + (partition: string) => callAction({ action: 'setPartition', param: partition }), + { immediate: false } + ).onError((error) => { + toast.error(String(error.error?.message || 'An error occurred')); + }); + const { data, send: loadData, @@ -325,18 +469,38 @@ const Version = () => { // Memoized values const platform = useMemo(() => (data ? getPlatform(data) : ''), [data]); - const isDev = useMemo( - () => data?.emsesp_version.includes('dev') ?? false, - [data?.emsesp_version] + + // Memoize filtered partitions to avoid recomputing on every render + const otherPartitions = useMemo( + () => data?.partitions.filter((p) => p.partition !== data.partition) ?? [], + [data] + ); + + const setPartitionVersionInfo = useCallback( + (partition: string) => { + setShowVersionInfo(3); + + // search for the partition in the data.partitions array + const partitionData = data?.partitions.find((p) => p.partition === partition); + if (partitionData) { + setPartitionVersion({ + name: partitionData.version, + published_at: partitionData.install_date ?? '' + }); + setPartition(partitionData.partition); + setFirmwareSize(partitionData.size); + } + }, + [data] ); const doRestart = useCallback(async () => { - setRestarting(true); await sendAPI({ device: 'system', cmd: 'restart', id: 0 }).catch( (error: Error) => { toast.error(error.message); } ); + setRestarting(true); }, [sendAPI]); const installFirmwareURL = useCallback( @@ -344,9 +508,28 @@ const Version = () => { await sendUploadURL(url).catch((error: Error) => { toast.error(error.message); }); + await doRestart(); + }, + [sendUploadURL, doRestart] + ); + + const installPartitionFirmware = useCallback( + async (partition: string) => { + await sendSetPartition(partition).catch((error: Error) => { + toast.error(error.message); + }); setRestarting(true); }, - [sendUploadURL] + [sendSetPartition] + ); + + const showPartitionDialog = useCallback( + (version: string, partition: string, install_date: string) => { + setOpenInstallPartitionDialog(true); + setPartitionVersion({ name: version, published_at: install_date }); + setPartition(partition); + }, + [] ); const showFirmwareDialog = useCallback((useDevVersion: boolean) => { @@ -358,8 +541,14 @@ const Version = () => { setOpenInstallDialog(false); }, []); + const closeInstallPartitionDialog = useCallback(() => { + setOpenInstallPartitionDialog(false); + }, []); + const handleVersionInfoClose = useCallback(() => { setShowVersionInfo(0); + setPartitionVersion(undefined); + setPartition(''); }, []); // check upgrades - only once when both versions are available @@ -406,7 +595,7 @@ const Version = () => { {LL.LATEST_VERSION(usingDevVersion ? LL.DEVELOPMENT() : LL.STABLE())} + + ))} + + + )} {LL.STABLE()} @@ -576,7 +802,11 @@ const Version = () => { showVersionInfo={showVersionInfo} latestVersion={latestVersion} latestDevVersion={latestDevVersion} + partitionVersion={partitionVersion} locale={locale} + partition={partition} + currentPartition={data?.partition ?? ''} + size={firmwareSize} LL={LL} onClose={handleVersionInfoClose} /> @@ -591,6 +821,14 @@ const Version = () => { onClose={closeInstallDialog} onInstall={installFirmwareURL} /> + {LL.UPLOAD()} @@ -606,7 +844,6 @@ const Version = () => { loadData, LL, platform, - isDev, internetLive, latestVersion, latestDevVersion, @@ -620,7 +857,15 @@ const Version = () => { handleVersionInfoClose, closeInstallDialog, installFirmwareURL, - doRestart + doRestart, + otherPartitions, + setPartitionVersionInfo, + showPartitionDialog, + partitionVersion, + partition, + firmwareSize, + closeInstallPartitionDialog, + installPartitionFirmware ]); return {restarting ? : content}; diff --git a/interface/src/i18n/cz/index.ts b/interface/src/i18n/cz/index.ts index 704ba83cc..efc1c6887 100644 --- a/interface/src/i18n/cz/index.ts +++ b/interface/src/i18n/cz/index.ts @@ -355,7 +355,8 @@ const cz: Translation = { SWITCH_RELEASE_TYPE: 'Přepnout na {0} verzi', FIRMWARE_VERSION_INFO: 'Informace o verzi firmwaru', NO_DATA: 'Žádná data', - USER_PROFILE: 'Uživatelský profil' + USER_PROFILE: 'Uživatelský profil', + STORED_VERSIONS: 'Uložené verze' }; export default cz; diff --git a/interface/src/i18n/de/index.ts b/interface/src/i18n/de/index.ts index 1e578fc24..8aa4e1dc8 100644 --- a/interface/src/i18n/de/index.ts +++ b/interface/src/i18n/de/index.ts @@ -355,7 +355,8 @@ const de: Translation = { SWITCH_RELEASE_TYPE: 'Zum {0}-Release wechseln', FIRMWARE_VERSION_INFO: 'Firmware-Versionsinformation', NO_DATA: 'Keine Daten', - USER_PROFILE: 'Benutzerprofil' + USER_PROFILE: 'Benutzerprofil', + STORED_VERSIONS: 'Gespeicherte Versionen' }; export default de; diff --git a/interface/src/i18n/en/index.ts b/interface/src/i18n/en/index.ts index 38a6e3185..bdb05a480 100644 --- a/interface/src/i18n/en/index.ts +++ b/interface/src/i18n/en/index.ts @@ -355,7 +355,8 @@ const en: Translation = { SWITCH_RELEASE_TYPE: 'Switch to {0} release', FIRMWARE_VERSION_INFO: 'Firmware Version Information', NO_DATA: 'No data', - USER_PROFILE: 'User Profile' + USER_PROFILE: 'User Profile', + STORED_VERSIONS: 'Stored Versions' }; export default en; diff --git a/interface/src/i18n/fr/index.ts b/interface/src/i18n/fr/index.ts index cfbbaa81d..008df1fcd 100644 --- a/interface/src/i18n/fr/index.ts +++ b/interface/src/i18n/fr/index.ts @@ -355,7 +355,8 @@ const fr: Translation = { SWITCH_RELEASE_TYPE: 'Passer à la version {0}', FIRMWARE_VERSION_INFO: 'Informations sur la version du firmware', NO_DATA: 'Aucune donnée', - USER_PROFILE: 'Profil utilisateur' + USER_PROFILE: 'Profil utilisateur', + STORED_VERSIONS: 'Versions stockées' }; export default fr; diff --git a/interface/src/i18n/it/index.ts b/interface/src/i18n/it/index.ts index 3dba434f6..cd38ed18a 100644 --- a/interface/src/i18n/it/index.ts +++ b/interface/src/i18n/it/index.ts @@ -355,7 +355,8 @@ const it: Translation = { SWITCH_RELEASE_TYPE: 'Cambia in {0} rilascio', FIRMWARE_VERSION_INFO: 'Informazioni sulla versione del firmware', NO_DATA: 'Nessun dato', - USER_PROFILE: 'Profilo utente' + USER_PROFILE: 'Profilo utente', + STORED_VERSIONS: 'Versioni memorizzate' }; export default it; diff --git a/interface/src/i18n/nl/index.ts b/interface/src/i18n/nl/index.ts index 579202eb6..3f23c42db 100644 --- a/interface/src/i18n/nl/index.ts +++ b/interface/src/i18n/nl/index.ts @@ -355,7 +355,8 @@ const nl: Translation = { SWITCH_RELEASE_TYPE: 'Switch naar {0} release', FIRMWARE_VERSION_INFO: 'Informatie over firmwareversie', NO_DATA: 'Geen data', - USER_PROFILE: 'Gebruikersprofiel' + USER_PROFILE: 'Gebruikersprofiel', + STORED_VERSIONS: 'Opgeslagen versies' }; export default nl; \ No newline at end of file diff --git a/interface/src/i18n/no/index.ts b/interface/src/i18n/no/index.ts index a2fbbaa6c..88af2bc43 100644 --- a/interface/src/i18n/no/index.ts +++ b/interface/src/i18n/no/index.ts @@ -355,7 +355,8 @@ const no: Translation = { SWITCH_RELEASE_TYPE: 'Bytt til {0} utgivelse', FIRMWARE_VERSION_INFO: 'Informasjon om firmwareversjon', NO_DATA: 'Ingen data', - USER_PROFILE: 'Brukerprofil' + USER_PROFILE: 'Brukerprofil', + STORED_VERSIONS: 'Lagret versjoner' }; export default no; diff --git a/interface/src/i18n/pl/index.ts b/interface/src/i18n/pl/index.ts index d50d6cefa..07b003447 100644 --- a/interface/src/i18n/pl/index.ts +++ b/interface/src/i18n/pl/index.ts @@ -355,7 +355,8 @@ const pl: BaseTranslation = { SWITCH_RELEASE_TYPE: 'Zmień na {0} wydanie', FIRMWARE_VERSION_INFO: 'Informacje o wersji firmware', NO_DATA: 'Brak danych', - USER_PROFILE: 'Profil użytkownika' + USER_PROFILE: 'Profil użytkownika', + STORED_VERSIONS: 'Zapisane wersje' }; export default pl; diff --git a/interface/src/i18n/sk/index.ts b/interface/src/i18n/sk/index.ts index 52e6f9c75..7950f2e05 100644 --- a/interface/src/i18n/sk/index.ts +++ b/interface/src/i18n/sk/index.ts @@ -355,7 +355,8 @@ const sk: Translation = { SWITCH_RELEASE_TYPE: 'Prepnúť na {0} verziu', FIRMWARE_VERSION_INFO: 'Informácie o verzii firmware', NO_DATA: 'Žiadne dáta', - USER_PROFILE: 'Profil používateľa' + USER_PROFILE: 'Profil používateľa', + STORED_VERSIONS: 'Uložené verzie' }; export default sk; diff --git a/interface/src/i18n/sv/index.ts b/interface/src/i18n/sv/index.ts index 644484269..a8fd58d23 100644 --- a/interface/src/i18n/sv/index.ts +++ b/interface/src/i18n/sv/index.ts @@ -355,7 +355,8 @@ const sv: Translation = { SWITCH_RELEASE_TYPE: 'Byt till {0} utgåva', FIRMWARE_VERSION_INFO: 'Information om firmwareversion', NO_DATA: 'Ingen data', - USER_PROFILE: 'Användarprofil' + USER_PROFILE: 'Användarprofil', + STORED_VERSIONS: 'Lagrad versioner' }; export default sv; diff --git a/interface/src/i18n/tr/index.ts b/interface/src/i18n/tr/index.ts index 79824decd..d931077f1 100644 --- a/interface/src/i18n/tr/index.ts +++ b/interface/src/i18n/tr/index.ts @@ -355,7 +355,8 @@ const tr: Translation = { SWITCH_RELEASE_TYPE: '{0} sürümüne geç', FIRMWARE_VERSION_INFO: 'Firmware Sürüm Bilgisi', NO_DATA: 'Hiçbir veri yok', - USER_PROFILE: 'Kullanıcı Profili' + USER_PROFILE: 'Kullanıcı Profili', + STORED_VERSIONS: 'Kaydedilmiş Sürümler' }; export default tr; diff --git a/interface/src/types/system.ts b/interface/src/types/system.ts index ace517688..b68ce3ce1 100644 --- a/interface/src/types/system.ts +++ b/interface/src/types/system.ts @@ -52,7 +52,14 @@ export interface SystemStatus { model: string; has_loader: boolean; has_partition: boolean; + partitions: { + partition: string; + version: string; + size: number; + install_date?: string; + }[]; status: number; // System Status Codes which matches SYSTEM_STATUS in System.h + developer_mode: boolean; temperature?: number; } diff --git a/interface/src/utils/useRest.ts b/interface/src/utils/useRest.ts index aa4096623..0d57abff9 100644 --- a/interface/src/utils/useRest.ts +++ b/interface/src/utils/useRest.ts @@ -60,21 +60,28 @@ export const useRest = ({ read, update }: RestRequestOptions) => { // Reset states before saving setRestartNeeded(false); setErrorMessage(undefined); - setDirtyFlags([]); - setOrigData(data as D); try { await writeData(data as D); + // Only update origData on successful save (dirtyFlags cleared by onSuccess handler) + setOrigData(data as D); } catch (error) { const message = error instanceof Error ? error.message : String(error); + if (message === REBOOT_ERROR_MESSAGE) { setRestartNeeded(true); - } else { - toast.error(message); - setErrorMessage(message); + return; // Early return - save succeeded but needs reboot } + + // Restore original data on validation error + if (origData) { + updateData({ data: origData }); + } + toast.error(message); + setErrorMessage(message); + setDirtyFlags([]); // Clear flags so user can retry } - }, [data, writeData]); + }, [data, writeData, origData, updateData]); return useMemo( () => ({ diff --git a/lib/PButton/PButton.h b/lib/PButton/PButton.h index d7be73447..a7f85f9a0 100644 --- a/lib/PButton/PButton.h +++ b/lib/PButton/PButton.h @@ -36,6 +36,9 @@ class PButton { void onVLongPress(uint16_t, buttonEventHandler handler); bool init(uint8_t pin, bool pullMode); bool check(void); + bool button_busy() { + return buttonBusy_; + } private: uint16_t Debounce_; // Debounce period to prevent flickering when pressing or releasing the button (in ms) @@ -47,21 +50,21 @@ class PButton { bool pullMode_; bool enabled_; - bool state_; // Value read from button - bool lastState_; // Last value of button state - bool dblClickWaiting_; // whether we're waiting for a double click (down) - bool dblClickOnNextUp_; // whether to register a double click on next release, or whether to wait and click - bool singleClickOK_; // whether it's OK to do a single click + bool state_; // Value read from button + bool lastState_; // Last value of button state + bool dblClickWaiting_; // whether we're waiting for a double click (down) + bool dblClickOnNextUp_; // whether to register a double click on next release, or whether to wait and click + bool singleClickOK_; // whether it's OK to do a single click - uint32_t downTime_; // time the button was pressed down - uint32_t upTime_; // time the button was released + uint32_t downTime_; // time the button was pressed down + uint32_t upTime_; // time the button was released bool ignoreUP_; // whether to ignore the button release because the click+hold was triggered bool waitForUP_; // when held, whether to wait for the up event bool longPressHappened_; // whether or not the hold event happened already bool vLongPressHappened_; // whether or not the long hold event happened already - bool buttonBusy_; // false if idle + bool buttonBusy_; // false if idle buttonEventHandler cb_onClick, cb_onDblClick, cb_onLongPress, cb_onVLongPress; }; diff --git a/lib_standalone/Arduino.h b/lib_standalone/Arduino.h index 9fe2f9ec1..1ac2aea3b 100644 --- a/lib_standalone/Arduino.h +++ b/lib_standalone/Arduino.h @@ -59,6 +59,8 @@ typedef double double_t; #define snprintf snprintf_P // to keep backwards compatibility +#define IRAM_ATTR + void pinMode(uint8_t pin, uint8_t mode); void digitalWrite(uint8_t pin, uint8_t value); int digitalRead(uint8_t pin); diff --git a/lib_standalone/ESP32React.h b/lib_standalone/ESP32React.h index 4da6036a6..23e3a5736 100644 --- a/lib_standalone/ESP32React.h +++ b/lib_standalone/ESP32React.h @@ -26,7 +26,7 @@ class DummySettings { public: // SYSTEM bool bandwidth20 = false; - bool nosleep = false; + bool nosleep = true; // MQTT uint16_t publish_time = 10; diff --git a/lib_standalone/Preferences.h b/lib_standalone/Preferences.h index 227893420..07f24e8be 100644 --- a/lib_standalone/Preferences.h +++ b/lib_standalone/Preferences.h @@ -12,8 +12,8 @@ class Preferences { bool _readOnly; public: - Preferences(){}; - ~Preferences(){}; + Preferences() {}; + ~Preferences() {}; bool begin(const char * name, bool readOnly = false, const char * partition_label = NULL) { return true; @@ -26,44 +26,49 @@ class Preferences { return true; } + int getChar(const char * key, uint8_t defaultValue = 0) { + return 0; + } size_t putChar(const char * key, int8_t value) { return 0; } - size_t putUChar(const char * key, uint8_t value) { - return 0; - } - - size_t putDouble(const char * key, double value) { - return 0; - } uint8_t getUChar(const char * key, uint8_t defaultValue = 0) { return 0; } - - int getChar(const char * key, uint8_t defaultValue = 0) { + size_t putUChar(const char * key, uint8_t value) { return 0; } double getDouble(const char * key, double defaultValue = NAN) { return 0; } - - size_t putString(const char * key, const char * value) { + size_t putDouble(const char * key, double value) { return 0; } - size_t putString(const char * key, String value) { + + bool getBool(const char * key, bool defaultValue = false) { + return true; + } + size_t putBool(const char * key, bool value) { + return 0; + } + + String getString(const char * key, String defaultValue = String()) { + return ""; + } + size_t putString(const char * key, const char * value) { return 0; } size_t getString(const char * key, char * value, size_t maxLen) { return 0; } - String getString(const char * key, String defaultValue = String()) { - return ""; + size_t putString(const char * key, String value) { + return 0; } - // unused + // unused.... // void end(); // bool clear(); diff --git a/lib_standalone/emsuart_standalone.h b/lib_standalone/emsuart_standalone.h index dfab52a5c..6146f7372 100644 --- a/lib_standalone/emsuart_standalone.h +++ b/lib_standalone/emsuart_standalone.h @@ -21,6 +21,12 @@ #include "Arduino.h" +#define EMS_TXMODE_OFF 0 +#define EMS_TXMODE_DEFAULT 1 +#define EMS_TXMODE_EMSPLUS 2 +#define EMS_TXMODE_HT3 3 +#define EMS_TXMODE_HW 4 + namespace emsesp { #define EMS_TX_STATUS_ERR 0 diff --git a/mock-api/package.json b/mock-api/package.json index c281edffa..f2b33531f 100644 --- a/mock-api/package.json +++ b/mock-api/package.json @@ -1,6 +1,6 @@ { "name": "mock-api", - "version": "3.7.3", + "version": "3.8.0", "description": "mock api for EMS-ESP", "author": "proddy, emsesp.org", "license": "MIT", @@ -9,11 +9,11 @@ "format": "prettier -l -w '**/*.{ts,tsx,js,css,json,md}'" }, "dependencies": { - "@msgpack/msgpack": "^3.1.2", + "@msgpack/msgpack": "^3.1.3", "@trivago/prettier-plugin-sort-imports": "^6.0.0", "formidable": "^3.5.4", "itty-router": "^5.0.22", "prettier": "^3.7.4" }, - "packageManager": "pnpm@10.26.1+sha512.664074abc367d2c9324fdc18037097ce0a8f126034160f709928e9e9f95d98714347044e5c3164d65bd5da6c59c6be362b107546292a8eecb7999196e5ce58fa" + "packageManager": "pnpm@10.26.2+sha512.0e308ff2005fc7410366f154f625f6631ab2b16b1d2e70238444dd6ae9d630a8482d92a451144debc492416896ed16f7b114a86ec68b8404b2443869e68ffda6" } diff --git a/mock-api/pnpm-lock.yaml b/mock-api/pnpm-lock.yaml index ac74c52ec..0151c466c 100644 --- a/mock-api/pnpm-lock.yaml +++ b/mock-api/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@msgpack/msgpack': - specifier: ^3.1.2 - version: 3.1.2 + specifier: ^3.1.3 + version: 3.1.3 '@trivago/prettier-plugin-sort-imports': specifier: ^6.0.0 version: 6.0.0(prettier@3.7.4) @@ -76,8 +76,8 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@msgpack/msgpack@3.1.2': - resolution: {integrity: sha512-JEW4DEtBzfe8HvUYecLU9e6+XJnKDlUAIve8FvPzF3Kzs6Xo/KuZkZJsDH0wJXl/qEZbeeE7edxDNY3kMs39hQ==} + '@msgpack/msgpack@3.1.3': + resolution: {integrity: sha512-47XIizs9XZXvuJgoaJUIE2lFoID8ugvc0jzSHP+Ptfk8nTbnR8g788wv48N03Kx0UkAv559HWRQ3yzOgzlRNUA==} engines: {node: '>= 18'} '@noble/hashes@1.8.0': @@ -238,7 +238,7 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@msgpack/msgpack@3.1.2': {} + '@msgpack/msgpack@3.1.3': {} '@noble/hashes@1.8.0': {} diff --git a/mock-api/restServer.ts b/mock-api/restServer.ts index 5ee3e539c..c5974d417 100644 --- a/mock-api/restServer.ts +++ b/mock-api/restServer.ts @@ -106,6 +106,29 @@ let system_status = { psram_size: 8189, free_psram: 8166, has_loader: true, + has_partition: true, + partitions: [ + { + partition: 'app0', // this one is active + version: 'XX.XX.XX', // defined later + install_date: '2025-03-01T13:29:13.999Z', + size: 4672 + }, + { + partition: 'app1', + version: '3.7.3-dev.40', + install_date: '2025-03-01T13:29:13.999Z', + size: 4672 + }, + { + partition: 'factory', + version: '3.7.3-dev.39', + install_date: '2025-03-01T13:29:13.999Z', + size: 4672 + } + ], + // partitions: [], + developer_mode: true, model: '', // model: 'BBQKees Electronics EMS Gateway E32 V2 (E32 V2.0 P3/2024011)', // status: 0, @@ -116,8 +139,8 @@ let system_status = { let DEV_VERSION_IS_UPGRADEABLE: boolean; let STABLE_VERSION_IS_UPGRADEABLE: boolean; let THIS_VERSION: string; -let LATEST_STABLE_VERSION = '3.7.3'; -let LATEST_DEV_VERSION = '3.7.4-dev.2'; +let LATEST_STABLE_VERSION = '3.8.0'; +let LATEST_DEV_VERSION = '3.8.1-dev.2'; // scenarios for testing versioning let version_test = 0; // on latest stable, or switch to dev @@ -148,13 +171,13 @@ switch (version_test as number) { break; case 3: // upgrade dev to latest, or switch to stable - THIS_VERSION = '3.7.4-dev.3'; + THIS_VERSION = '3.8.0-dev.3'; STABLE_VERSION_IS_UPGRADEABLE = false; DEV_VERSION_IS_UPGRADEABLE = true; break; case 4: // downgrade to an older dev, or switch back to stable - THIS_VERSION = '3.7.3-dev.1'; + THIS_VERSION = '3.8.0-dev.1'; STABLE_VERSION_IS_UPGRADEABLE = true; DEV_VERSION_IS_UPGRADEABLE = false; break; @@ -162,6 +185,7 @@ switch (version_test as number) { // set the version system_status.emsesp_version = THIS_VERSION; +system_status.partitions[0].version = THIS_VERSION; // app0 // set the ESP platform - using ESP32 will disable OTA and automatic version downloading let emulate_esp: string; @@ -5135,6 +5159,10 @@ router // reset MQTT console.log('resetting MQTT...'); return status(200); + } else if (action === 'setPartition') { + // set partition + console.log('setting partition to', content.param); + return status(200); } } return status(404); // cmd not found diff --git a/platformio.ini b/platformio.ini index ef14a0ea5..5f8a3e87e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -228,7 +228,7 @@ build_src_flags = -DEMSESP_STANDALONE -DEMSESP_TEST -DEMSESP_UNITY -DARDUINOJSON_ENABLE_ARDUINO_STRING=1 - -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.7.3-dev.0\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\" + -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.8.0-dev.0\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\" -std=gnu++17 -Og -ggdb -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare -Wno-missing-braces @@ -284,7 +284,7 @@ build_flags = [env:standalone] extends = env:native build_flags = - -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.7.3-dev.0\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\" + -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.8.0-dev.0\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\" ; Modbus ; Creating the modbus registers is a multi-step process. Before it was in a shell script called generate_csv_and_headers.sh diff --git a/project-words.txt b/project-words.txt index 332acd06c..0ac36f9f6 100644 --- a/project-words.txt +++ b/project-words.txt @@ -1446,3 +1446,4 @@ intergral vchip SPIIO SPIDQS +txpause diff --git a/scripts/update_all.sh b/scripts/update_all.sh index a79211b48..31992ecd8 100644 --- a/scripts/update_all.sh +++ b/scripts/update_all.sh @@ -25,6 +25,6 @@ pnpm build_webUI cd .. npx cspell "**" -platformio run -e build_modbus -platformio run -e build_standalone -platformio run -e native-test -t exec +# platformio run -e build_modbus +# platformio run -e build_standalone +# platformio run -e native-test -t exec diff --git a/sonar-project.properties b/sonar-project.properties index 5d2d7e740..cee91ae32 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,7 +1,7 @@ sonar.organization=emsesp sonar.projectKey=emsesp_EMS-ESP32 sonar.projectName=EMS-ESP32 -sonar.projectVersion=3.7.3 +sonar.projectVersion=3.8.0 sonar.sources=./src sonar.cfamily.compile-commands=bw-output/compile_commands.json sonar.sourceEncoding=UTF-8 diff --git a/src/ESP32React/NetworkStatus.cpp b/src/ESP32React/NetworkStatus.cpp index 3d82cb57b..a67a356ba 100644 --- a/src/ESP32React/NetworkStatus.cpp +++ b/src/ESP32React/NetworkStatus.cpp @@ -55,7 +55,6 @@ void NetworkStatus::networkStatus(AsyncWebServerRequest * request) { } } else if (wifi_status == WL_CONNECTED) { root["local_ip"] = WiFi.localIP().toString(); -// #if ESP_ARDUINO_VERSION_MAJOR < 3 #if ESP_IDF_VERSION_MAJOR < 5 root["local_ipv6"] = WiFi.localIPv6().toString(); #else diff --git a/src/ESP32React/UploadFileService.cpp b/src/ESP32React/UploadFileService.cpp index 126d3e237..c86a6e31c 100644 --- a/src/ESP32React/UploadFileService.cpp +++ b/src/ESP32React/UploadFileService.cpp @@ -3,6 +3,7 @@ #include #include +#include static String getFilenameExtension(const String & filename) { const auto pos = filename.lastIndexOf('.'); @@ -81,6 +82,10 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri } #endif // it's firmware - initialize the ArduinoOTA updater + emsesp::EMSESP::logger().info("Uploading firmware file %s (size: %d bytes)", filename.c_str(), filesize); + // turn off UART to prevent interference with the upload + emsesp::EMSuart::stop(); + if (Update.begin(filesize - sizeof(esp_image_header_t))) { if (strlen(_md5.data()) == _md5.size() - 1) { Update.setMD5(_md5.data()); @@ -113,6 +118,8 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri } void UploadFileService::uploadComplete(AsyncWebServerRequest * request) { + emsesp::EMSESP::logger().info("Upload successful"); + // did we just complete uploading a json file? if (request->_tempFile) { request->_tempFile.close(); // close the file handle as the upload is now done @@ -126,6 +133,9 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) { // check if it was a firmware upgrade // if no error, send the success response as a JSON if (_is_firmware && !request->_tempObject) { + // set NVS to tell EMS-ESP this is a new fresh firmware on next restart + emsesp::EMSESP::nvs_.putBool(emsesp::EMSESP_NVS_BOOT_NEW_FIRMWARE, true); + AsyncWebServerResponse * response = request->beginResponse(200); request->send(response); emsesp::EMSESP::system_.systemStatus( @@ -133,6 +143,7 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) { return; } + // add MD5 to the response if (strlen(_md5.data()) == _md5.size() - 1) { auto * response = new AsyncJsonResponse(false); JsonObject root = response->getRoot(); @@ -146,6 +157,9 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) { } void UploadFileService::handleError(AsyncWebServerRequest * request, int code) { + emsesp::EMSESP::logger().info("Upload error: %d", code); + emsesp::EMSESP::system_.uart_init(); // re-enable UART + // if we have had an error already, do nothing if (request->_tempObject) { return; @@ -155,15 +169,19 @@ void UploadFileService::handleError(AsyncWebServerRequest * request, int code) { AsyncWebServerResponse * response = request->beginResponse(code); request->send(response); - // check for invalid extension and immediately kill the connection, which will through an error + // check for invalid extension and immediately kill the connection, which will throw an error // that is caught by the web code. Unfortunately the http error code is not sent to the client on fast network connections if (code == 406) { request->client()->close(true); - handleEarlyDisconnect(); + _is_firmware = false; + Update.abort(); } } void UploadFileService::handleEarlyDisconnect() { + emsesp::EMSESP::logger().info("Upload ended"); + emsesp::EMSESP::system_.uart_init(); // re-enable UART + _is_firmware = false; Update.abort(); } diff --git a/src/core/analogsensor.cpp b/src/core/analogsensor.cpp index 1bb66e64c..d62701ded 100644 --- a/src/core/analogsensor.cpp +++ b/src/core/analogsensor.cpp @@ -289,11 +289,7 @@ void AnalogSensor::reload(bool get_nvs) { uint8_t r = v / 10000; uint8_t g = (v - r * 10000) / 100; uint8_t b = v % 100; -#if ESP_ARDUINO_VERSION_MAJOR < 3 - neopixelWrite(sensor.gpio(), 2 * r, 2 * g, 2 * b); -#else - rgbLedWrite(sensor.gpio(), 2 * r, 2 * g, 2 * b); -#endif + EMSESP_RGB_WRITE(sensor.gpio(), 2 * r, 2 * g, 2 * b); LOG_DEBUG("RGB set to %d, %d, %d", r, g, b); } else if (sensor.type() == AnalogType::DIGITAL_OUT) { LOG_DEBUG("Digital Write on GPIO %02d", sensor.gpio()); @@ -809,9 +805,9 @@ void AnalogSensor::publish_values(const bool force) { std::string topic_str(topic); config["def_ent_id"] = topic_str.substr(0, topic_str.find("/")) + "." + uniq_s; + // add HA Discovery config Mqtt::add_ha_classes(config.as(), EMSdevice::DeviceType::ANALOGSENSOR, valueType, sensor.uom()); - // dev section with model is only created on the 1st sensor - Mqtt::add_ha_dev_section(config.as(), "Analog Sensors", !ha_dev_created); + Mqtt::add_ha_dev_section(config.as(), "Analog Sensors", !ha_dev_created); // dev section with model is only created on the 1st sensor Mqtt::add_ha_avty_section(config.as(), stat_t, val_cond); sensor.ha_registered = Mqtt::queue_ha(topic, config.as()); @@ -955,11 +951,7 @@ bool AnalogSensor::command_setvalue(const char * value, const int8_t gpio) { uint8_t r = v / 10000; uint8_t g = (v - r * 10000) / 100; uint8_t b = v % 100; -#if ESP_ARDUINO_VERSION_MAJOR < 3 - neopixelWrite(sensor.gpio(), 2 * r, 2 * g, 2 * b); -#else - rgbLedWrite(sensor.gpio(), 2 * r, 2 * g, 2 * b); -#endif + EMSESP_RGB_WRITE(sensor.gpio(), 2 * r, 2 * g, 2 * b); LOG_DEBUG("RGB set to %d, %d, %d", r, g, b); } else if (sensor.type() == AnalogType::PULSE) { uint8_t v = val; diff --git a/src/core/console.cpp b/src/core/console.cpp index 59ab70403..f0b45cf00 100644 --- a/src/core/console.cpp +++ b/src/core/console.cpp @@ -100,8 +100,6 @@ static void setup_commands(std::shared_ptr const & commands) { EMSESP::show_sensor_values(shell); } else if (command == F_(mqtt)) { Mqtt::show_mqtt(shell); - } else if (command == F_(gpio)) { - EMSESP::system_.show_gpio(shell); } else { shell.printfln("Unknown show command"); } @@ -369,6 +367,7 @@ static void setup_commands(std::shared_ptr const & commands) { commands->add_command(ShellContext::MAIN, CommandFlags::ADMIN, {F_(scan)}, [](Shell & shell, const std::vector & arguments) { EMSESP::scan_devices(); }); + /* removed scan deep commands->add_command(ShellContext::MAIN, CommandFlags::ADMIN, {F_(scan)}, {F_(deep_optional)}, [](Shell & shell, const std::vector & arguments) { if (arguments.empty()) { @@ -386,6 +385,7 @@ static void setup_commands(std::shared_ptr const & commands) { } }); */ + // read [offset] [length] commands->add_command(ShellContext::MAIN, CommandFlags::USER, diff --git a/src/core/emsdevice.cpp b/src/core/emsdevice.cpp index e62169ca6..8d07660d0 100644 --- a/src/core/emsdevice.cpp +++ b/src/core/emsdevice.cpp @@ -1687,7 +1687,7 @@ void EMSdevice::get_value_json(JsonObject json, DeviceValue & dv) { } // add uom, state class and device class - Mqtt::add_ha_classes(json, device_type(), dv.type, dv.uom, dv.short_name, false); // no icon + Mqtt::add_ha_classes(json, device_type(), dv.type, dv.uom, dv.short_name, true); // display only json["readable"] = dv.type != DeviceValueType::CMD && !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE); json["writeable"] = dv.has_cmd && !dv.has_state(DeviceValueState::DV_READONLY); diff --git a/src/core/emsdevicevalue.h b/src/core/emsdevicevalue.h index f6dcb3827..04d28809c 100644 --- a/src/core/emsdevicevalue.h +++ b/src/core/emsdevicevalue.h @@ -47,36 +47,37 @@ class DeviceValue { // Unit Of Measurement mapping - maps to DeviceValueUOM_s in emsdevicevalue.cpp. Sequence is important!! // also used with HA as uom + // shows also the HA device class being used enum DeviceValueUOM : uint8_t { NONE = 0, // 0 - DEGREES, // 1 - °C - DEGREES_R, // 2 - °C (relative temperature) - PERCENT, // 3 - % - LMIN, // 4 - l/min - KWH, // 5 - kWh - WH, // 6 - Wh - HOURS, // 7 - h - MINUTES, // 8 - m - UA, // 9 - µA - BAR, // 10 - bar - KW, // 11 - kW - W, // 12 - W - KB, // 13 - kB - SECONDS, // 14 - s - DBM, // 15 - dBm - FAHRENHEIT, // 16 - °F - MV, // 17 - mV - SQM, // 18 - m² - M3, // 19 - m³ - L, // 20 - L + DEGREES, // 1 - °C - temperature + DEGREES_R, // 2 - °C (relative temperature) - temperature + PERCENT, // 3 - % - power factor + LMIN, // 4 - l/min - volume flow rate + KWH, // 5 - kWh - energy + WH, // 6 - Wh - energy + HOURS, // 7 - h - duration + MINUTES, // 8 - m - duration + UA, // 9 - µA - current + BAR, // 10 - bar - pressure + KW, // 11 - kW - power + W, // 12 - W - power + KB, // 13 - kB - data size + SECONDS, // 14 - s - duration + DBM, // 15 - dBm - signal strength + FAHRENHEIT, // 16 - °F - temperature + MV, // 17 - mV - voltage + SQM, // 18 - m² - area + M3, // 19 - m³ - volume + L, // 20 - L - volume KMIN, // 21 - K*min - K, // 22 - K - VOLTS, // 23 - V - MBAR, // 24 - mbar - LH, // 25 - l/h - CTKWH, // 26 - ct/kWh - HZ, // 27 - Hz - CONNECTIVITY // 28 - used in HA + K, // 22 - K - temperature + VOLTS, // 23 - V - voltage + MBAR, // 24 - mbar - atmospheric pressure + LH, // 25 - l/h - volume flow rate + CTKWH, // 26 - ct/kWh - monetary + HZ, // 27 - Hz - frequency + CONNECTIVITY // 28 - used in HA - connectivity }; // TAG mapping - maps to DeviceValueTAG_s in emsdevicevalue.cpp diff --git a/src/core/emsesp.cpp b/src/core/emsesp.cpp index 081390993..adf1c776e 100644 --- a/src/core/emsesp.cpp +++ b/src/core/emsesp.cpp @@ -1591,6 +1591,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) { connect_time = uuid::get_uptime_sec(); } if (poll_id == EMSbus::ems_bus_id()) { + // TODO this could also be by coincidence, so we should add a counter to the EMSbus class to check if the poll_id is the same as the EMS_BUS_ID for a certain number of times EMSbus::last_bus_activity(uuid::get_uptime()); // set the flag indication the EMS bus is active } if (wait_km_) { @@ -1719,6 +1720,14 @@ void EMSESP::start() { #else LOG_INFO("EMS-ESP version %s", EMSESP_APP_VERSION); #endif + + // check if the firmware is fresh + // this is set in UploadFileService::uploadComplete() + // and reset in System::set_partition_install_date() + if (!EMSESP::nvs_.getBool(EMSESP_NVS_BOOT_NEW_FIRMWARE)) { + LOG_DEBUG("Firmware is fresh"); + } + LOG_DEBUG("System is running in Debug mode"); LOG_INFO("Last system reset reason Core0: %s, Core1: %s", system_.reset_reason(0).c_str(), system_.reset_reason(1).c_str()); @@ -1810,9 +1819,14 @@ void EMSESP::shell_prompt() { // main loop calling all services void EMSESP::loop() { - uuid::loop(); // store system uptime - esp32React.loop(); // web services - system_.loop(); // does LED and checks system health, and syslog service + uuid::loop(); // store system uptime + + // handles LED and checks system health, and syslog service + if (system_.loop()) { + return; // LED flashing is active, skip the rest of the loop + } + + esp32React.loop(); // web services like network, AP, MQTT webLogService.loop(); // log in Web UI // run the loop, unless we're in the middle of an OTA upload diff --git a/src/core/emsesp.h b/src/core/emsesp.h index 5fe7cfb99..c094f7f7a 100644 --- a/src/core/emsesp.h +++ b/src/core/emsesp.h @@ -96,6 +96,8 @@ using DeviceValueNumOp = DeviceValue::DeviceValueNumOp; class EMSESPShell; class Shower; +static constexpr const char * EMSESP_NVS_BOOT_NEW_FIRMWARE = "fresh_firmware"; // max 15 characters + class EMSESP { public: EMSESP(); diff --git a/src/core/helpers.cpp b/src/core/helpers.cpp index 207167ac8..9bd6d3d27 100644 --- a/src/core/helpers.cpp +++ b/src/core/helpers.cpp @@ -696,6 +696,7 @@ bool Helpers::value2string(const char * value, std::string & value_s) { // checks to see if a string (usually a command or payload cmd) looks like a boolean // on, off, true, false, 1, 0 +// uses translated words for on/off bool Helpers::value2bool(const char * value, bool & value_b) { if ((value == nullptr) || (strlen(value) == 0)) { return false; diff --git a/src/core/locale_common.h b/src/core/locale_common.h index 71f00e681..48eca147d 100644 --- a/src/core/locale_common.h +++ b/src/core/locale_common.h @@ -42,6 +42,7 @@ MAKE_WORD(system) MAKE_WORD(fetch) MAKE_WORD(restart) MAKE_WORD(format) +MAKE_WORD(txpause) MAKE_WORD(raw) MAKE_WORD(watch) MAKE_WORD(syslog) @@ -159,7 +160,7 @@ MAKE_WORD_CUSTOM(deviceid_mandatory, "") MAKE_WORD_CUSTOM(device_type_optional, "[device]") MAKE_WORD_CUSTOM(invalid_log_level, "Invalid log level") MAKE_WORD_CUSTOM(log_level_optional, "[level]") -MAKE_WORD_CUSTOM(show_commands, "[system | users | devices | log | ems | values | mqtt | commands | gpio]") +MAKE_WORD_CUSTOM(show_commands, "[system | users | devices | log | ems | values | mqtt | commands]") MAKE_WORD_CUSTOM(name_mandatory, "") MAKE_WORD_CUSTOM(name_optional, "[name]") MAKE_WORD_CUSTOM(new_password_prompt1, "Enter new password: ") @@ -168,6 +169,7 @@ MAKE_WORD_CUSTOM(password_prompt, "Password: ") MAKE_WORD_CUSTOM(unset, "") MAKE_WORD_CUSTOM(enable_mandatory, "") MAKE_WORD_CUSTOM(service_mandatory, "") +MAKE_WORD_CUSTOM(txpause_cmd, "enable/disable TX") // more common names that don't need translations MAKE_NOTRANSLATION(1x3min, "1x3min") diff --git a/src/core/locale_translations.h b/src/core/locale_translations.h index b6470c8de..48aa28dd5 100644 --- a/src/core/locale_translations.h +++ b/src/core/locale_translations.h @@ -37,52 +37,53 @@ // if there is no translation, it will default to en // // device types, as display in Web and Console -MAKE_WORD_TRANSLATION(boiler_hp_device, "Boiler/HP", "Kessel/WP", "CV ketel/WP", "Värmepanna/VP", "Kocioł/PC", "Varmekjele/VP", "", "Kazan/IP", "Caldaia/PC", "Kotol/TČ", "Kotel/TČ") // TODO translate -MAKE_WORD_TRANSLATION(boiler_device, "Boiler", "Kessel", "CV ketel", "Värmepanna", "Kocioł", "Varmekjele", "", "Kazan", "Caldaia", "Kotol", "Kotel") // TODO translate -MAKE_WORD_TRANSLATION(thermostat_device, "Thermostat", "Thermostat", "Thermostaat", "Termostat", "Termostat", "Termostat", "", "Termostat", "Termostato", "Termostat", "Termostat") // TODO translate -MAKE_WORD_TRANSLATION(heatpump_device, "Heat Pump", "Wärmepumpe", "Warmtepomp", "Värmepump", "Pompa ciepła", "Varmepumpe", "", "Isı Pompası", "Pompa di Calore", "Tepelné čerpadlo", "Tepelné čerpadlo") // TODO translate -MAKE_WORD_TRANSLATION(solar_device, "Solar Module", "Solarmodul", "Solar Module", "Solmodul", "Moduł solarny", "Solmodul", "", "Güneş Enerjisi Cihazı", "Modulo Solare", "Solárny modul", "Solární modul") // TODO translate -MAKE_WORD_TRANSLATION(connect_device, "Connect Module", "Verbindungsmodul", "Connect Module", "Uppkopplingsmodul", "Moduł przyłączeń", "Sammenkoblingsmodul", "", "Güneş Enerjisi Cihazı", "Modulo connessione", "Pripojte modul", "Modul připojení") // TODO translate -MAKE_WORD_TRANSLATION(mixer_device, "Mixer Module", "Mischermodul", "Mixer Module", "Blandarmodul", "Moduł mieszacza", "Miksermodul", "", "Karışım Cihazı", "Modulo Miscela", "Modul mixera", "Směšovací modul") // TODO translate -MAKE_WORD_TRANSLATION(controller_device, "Controller Module", "Regelmodul", "Controller Module", "Styrmodul", "Moduł sterujący", "Styremodul", "", "Kontrol Ünitesi", "Modulo Controllo", "Modul ovládača", "Řídicí modul") // TODO translate -MAKE_WORD_TRANSLATION(switch_device, "Switch Module", "Schaltmodul", "Switch Module", "Relämodul", "Moduł przełączający", "Switch modul", "", "Anahtar", "Modulo Switch", "Spínací modul", "Spínací modul") // TODO translate -MAKE_WORD_TRANSLATION(gateway_device, "Gateway Module", "Gateway-Modul", "Gateway Module", "Gateway", "Moduł IP", "Gateway", "", "Ağ Geçidi", "Modulo Gateway", "Modul brány", "Modul brány") // TODO translate -MAKE_WORD_TRANSLATION(alert_device, "Alert Module", "Alarmmodul", "Alert Module", "Larmmodul", "Moduł alarmowy", "Alarmmodul", "", "Alarm Cihazı", "Module Avviso", "Modul upozornení", "Modul upozornění") // TODO translate -//MAKE_WORD_TRANSLATION(pump_device, "Pump Module", "Pumpenmodul", "Pump Module", "Pumpmodul", "Moduł pompy", "Pumpemodul", "", "Pompa", "Module Pompa", "Modul čerpadla", "Modul čerpadla") // TODO translate -MAKE_WORD_TRANSLATION(extension_device, "Extension Module", "Erweiterungsnmodul", "Module", "Utökningsmodul", "Moduł rozszerzeń", "Modul", "", "", "Module", "Rozširujúci modul", "Rozšiřující modul") // TODO translate -MAKE_WORD_TRANSLATION(heatsource_device, "Heatsource", "Wärmequelle", "Heatsource", "Värmekälla", "Źródło ciepła", "Varmekilde", "", "Isı Kaynağı", "Fonte di calore", "Tepelný zdroj", "Zdroj tepla") // TODO translate +MAKE_WORD_TRANSLATION(boiler_hp_device, "Boiler/HP", "Kessel/WP", "CV ketel/WP", "Värmepanna/VP", "Kocioł/PC", "Varmekjele/VP", "Chaudière/PC", "Kazan/IP", "Caldaia/PC", "Kotol/TČ", "Kotel/TČ") +MAKE_WORD_TRANSLATION(boiler_device, "Boiler", "Kessel", "CV ketel", "Värmepanna", "Kocioł", "Varmekjele", "Chaudière", "Kazan", "Caldaia", "Kotol", "Kotel") +MAKE_WORD_TRANSLATION(thermostat_device, "Thermostat", "Thermostat", "Thermostaat", "Termostat", "Termostat", "Termostat", "Thermostat", "Termostat", "Termostato", "Termostat", "Termostat") +MAKE_WORD_TRANSLATION(heatpump_device, "Heat Pump", "Wärmepumpe", "Warmtepomp", "Värmepump", "Pompa ciepła", "Varmepumpe", "Pompe à chaleur", "Isı Pompası", "Pompa di Calore", "Tepelné čerpadlo", "Tepelné čerpadlo") +MAKE_WORD_TRANSLATION(solar_device, "Solar Module", "Solarmodul", "Solar Module", "Solmodul", "Moduł solarny", "Solmodul", "Module solaire", "Güneş Enerjisi Cihazı", "Modulo Solare", "Solárny modul", "Solární modul") +MAKE_WORD_TRANSLATION(connect_device, "Connect Module", "Verbindungsmodul", "Connect Module", "Uppkopplingsmodul", "Moduł przyłączeń", "Sammenkoblingsmodul", "Module de connexion", "Bağlantı Modülü", "Modulo connessione", "Pripojte modul", "Modul připojení") +MAKE_WORD_TRANSLATION(mixer_device, "Mixer Module", "Mischermodul", "Mixer Module", "Blandarmodul", "Moduł mieszacza", "Miksermodul", "Module mélangeur", "Karışım Cihazı", "Modulo Miscela", "Modul mixera", "Směšovací modul") +MAKE_WORD_TRANSLATION(controller_device, "Controller Module", "Regelmodul", "Controller Module", "Styrmodul", "Moduł sterujący", "Styremodul", "Module de contrôle", "Kontrol Ünitesi", "Modulo Controllo", "Modul ovládača", "Řídicí modul") +MAKE_WORD_TRANSLATION(switch_device, "Switch Module", "Schaltmodul", "Switch Module", "Relämodul", "Moduł przełączający", "Switch modul", "Module commutateur", "Anahtar", "Modulo Switch", "Spínací modul", "Spínací modul") +MAKE_WORD_TRANSLATION(gateway_device, "Gateway Module", "Gateway-Modul", "Gateway Module", "Gateway", "Moduł IP", "Gateway", "Module passerelle", "Ağ Geçidi", "Modulo Gateway", "Modul brány", "Modul brány") +MAKE_WORD_TRANSLATION(alert_device, "Alert Module", "Alarmmodul", "Alert Module", "Larmmodul", "Moduł alarmowy", "Alarmmodul", "Module d'alerte", "Alarm Cihazı", "Module Avviso", "Modul upozornení", "Modul upozornění") +//MAKE_WORD_TRANSLATION(pump_device, "Pump Module", "Pumpenmodul", "Pump Module", "Pumpmodul", "Moduł pompy", "Pumpemodul", "", "Pompa", "Module Pompa", "Modul čerpadla", "Modul čerpadla") +MAKE_WORD_TRANSLATION(extension_device, "Extension Module", "Erweiterungsnmodul", "Module", "Utökningsmodul", "Moduł rozszerzeń", "Modul", "Module d'extension", "Genişletme Modülü", "Module", "Rozširujúci modul", "Rozšiřující modul") +MAKE_WORD_TRANSLATION(heatsource_device, "Heatsource", "Wärmequelle", "Heatsource", "Värmekälla", "Źródło ciepła", "Varmekilde", "Source de chaleur", "Isı Kaynağı", "Fonte di calore", "Tepelný zdroj", "Zdroj tepla") MAKE_WORD_TRANSLATION(sensors_device, "Sensors", "Sensoren", "Sensoren", "Sensorer", "Czujniki", "Sensorer", "Capteurs", "Sensör Cihazı", "Sensori", "Snímače", "Senzory") MAKE_WORD_TRANSLATION(unknown_device, "Unknown", "Unbekannt", "Onbekend", "Okänt", "Nieznane urządzenie", "Ukjent", "Inconnu", "Bilinmeyen", "Sconosciuto", "Neznámy", "Neznámé") -MAKE_WORD_TRANSLATION(custom_device, "Custom", "Nutzerdefiniert", "Aangepast", "Anpassad", "Niestandardowe", "", "", "Özel", "Personalizzato", "Vlastné", "Vlastní") // TODO translate -MAKE_WORD_TRANSLATION(custom_device_name, "Custom Entities", "Nutzer deklarierte Entitäten", "Gebruiker gedefineerd", "Egendefinierade entiteter", "Encje zdefiniowane przez użytkownika", "", "", "Kullanıcı tarafından tanımlanmış varlıklar", "Entità definita da utente", "Používateľom definované entity", "Vlastní entity") // TODO translate -MAKE_WORD_TRANSLATION(ventilation_device, "Ventilation", "Belüftung", "Ventilatie", "Ventilation", "Wentylacja", "", "", "Havalandırma", "Ventilazione", "Vetranie", "Větrání") // TODO translate -MAKE_WORD_TRANSLATION(water_device, "Water Module", "Wassermodul", "", "Vattenmodul", "Moduł wodny", "", "", "", "", "Modul vody", "Modul vody") // TODO translate -MAKE_WORD_TRANSLATION(pool_device, "Pool Module", "Poolmodul", "", "Poolmodul", "Moduł basenu", "", "", "", "", "Modul bazéna", "Modul bazénu") // TODO translate +MAKE_WORD_TRANSLATION(custom_device, "Custom", "Nutzerdefiniert", "Aangepast", "Anpassad", "Niestandardowe", "Tilpasset", "Personnalisé", "Özel", "Personalizzato", "Vlastné", "Vlastní") +MAKE_WORD_TRANSLATION(custom_device_name, "Custom Entities", "Nutzer deklarierte Entitäten", "Gebruiker gedefineerd", "Egendefinierade entiteter", "Encje zdefiniowane przez użytkownika", "Brukerdefinerte enheter", "Entités personnalisées", "Kullanıcı tarafından tanımlanmış varlıklar", "Entità definita da utente", "Používateľom definované entity", "Vlastní entity") +MAKE_WORD_TRANSLATION(ventilation_device, "Ventilation", "Belüftung", "Ventilatie", "Ventilation", "Wentylacja", "Ventilasjon", "Ventilation", "Havalandırma", "Ventilazione", "Vetranie", "Větrání") +MAKE_WORD_TRANSLATION(water_device, "Water Module", "Wassermodul", "Water Module", "Vattenmodul", "Moduł wodny", "Vannmodul", "Module d'eau", "Su Modülü", "Modulo Acqua", "Modul vody", "Modul vody") +MAKE_WORD_TRANSLATION(pool_device, "Pool Module", "Poolmodul", "Pool Module", "Poolmodul", "Moduł basenu", "Bassengmodul", "Module piscine", "Havuz Modülü", "Modulo Piscina", "Modul bazéna", "Modul bazénu") // commands -MAKE_WORD_TRANSLATION(info_cmd, "list all values (verbose)", "Liste aller Werte", "lijst van alle waardes", "lista alla värden", "wyświetl wszystkie wartości", "Viser alle verdier", "", "Tüm değerleri listele", "elenca tutti i valori", "zobraziť všetky hodnoty", "vypsat všechny hodnoty (podrobně)") // TODO translate -MAKE_WORD_TRANSLATION(commands_cmd, "list all commands", "Liste aller Kommandos", "lijst van alle commando's", "lista alla kommandon", "wyświetl wszystkie komendy", "Viser alle kommandoer", "", "Tüm komutları listele", "elencaa tutti i comandi", "zobraziť všetky príkazy", "vypsat všechny příkazy") // TODO translate -MAKE_WORD_TRANSLATION(entities_cmd, "list all entities", "Liste aller Entitäten", "lijst van alle entiteiten", "lista all entiteter", "wyświetl wszsytkie encje", "Viser alle enheter", "", "Tüm varlıkları listele", "elenca tutte le entità", "zobraziť všetky entity", "vypsat všechny entity") // TODO translate -MAKE_WORD_TRANSLATION(metrics_cmd, "list all prometheus metrics", "Liste aller Prometheus Metriken", "lijst van alle Prometheus metriken", "lista alla Prometheus metriker", "wyświetl wszystkie Prometheus metryki", "Viser alle Prometheus metrikker", "", "Tüm Prometheus metriklerini listele", "elenca tutte le metriche Prometheus", "zobraziť všetky Prometheus metriky", "vypsat všechny Prometheus metriky") // TODO translate -MAKE_WORD_TRANSLATION(send_cmd, "send a telegram", "Sende EMS-Telegramm", "stuur een telegram", "skicka ett telegram", "wyślij telegram", "send et telegram", "", "Bir telegram gönder", "invia un telegramma", "poslať telegram", "odeslat telegram") // TODO translate -MAKE_WORD_TRANSLATION(read_cmd, "send read request", "", "", "skicka en läsförfrågan", "", "", "", "", "", "odoslať žiadosť o prečítanie", "odeslat požadavek na čtení") // TODO translate -MAKE_WORD_TRANSLATION(setiovalue_cmd, "set I/O value", "Setze Werte E/A", "instellen standaardwaarde", "sätt ett I/O-värde", "ustaw wartość", "sett en io verdi", "", "Giriş/Çıkış değerlerini ayarla", "imposta valore io", "nastaviť hodnotu io", "nastavit hodnotu I/O") // TODO translate -MAKE_WORD_TRANSLATION(changeloglevel_cmd, "change log level", "Ändere Protokollebene", "aanpassen log niveau", "ändra logg-nivå", "zmień poziom log-u", "endre loggnivå", "", "Kayıt seviyesini değiştir", "cambia livello registrazione", "zmeniť úroveň protokolu", "změnit úroveň protokolování") // TODO translate -MAKE_WORD_TRANSLATION(fetch_cmd, "refresh all EMS values", "Aktualisiere alle EMS-Werte", "Verversen alle EMS waardes", "uppdatera alla EMS-värden", "odśwież wszystkie wartości EMS", "oppfrisk alle EMS verdier", "", "Bütün EMS değerlerini yenile", "aggiornare tutti i valori EMS", "obnoviť všetky hodnoty EMS", "aktualizovat všechny EMS hodnoty") // TODO translate -MAKE_WORD_TRANSLATION(restart_cmd, "restart EMS-ESP", "Neustart", "opnieuw opstarten", "starta om EMS-ESP", "uruchom ponownie EMS-ESP", "restart EMS-ESP", "redémarrer EMS-ESP", "EMS-ESPyi yeniden başlat", "riavvia EMS-ESP", "reštart EMS-ESP", "restartovat EMS-ESP") // TODO translate -MAKE_WORD_TRANSLATION(format_cmd, "factory reset EMS-ESP", "EMS-ESP auf Werkseinstellungen zurücksetzen", "fabriksåterställ EMS-ESP", "", "", "", "", "", "", "továrenske nastavenie EMS-ESP", "tovární nastavení EMS-ESP") // TODO translate -MAKE_WORD_TRANSLATION(watch_cmd, "watch incoming telegrams", "Beobachte eingehende Telegramme", "inkomende telegrammen bekijken", "visa inkommande telegram", "obserwuj przyczodzące telegramy", "se innkommende telegrammer", "", "Gelen telegramları", "guardare i telegrammi in arrivo", "sledovať prichádzajúce telegramy", "sledovat příchozí telegramy") // TODO translate -MAKE_WORD_TRANSLATION(publish_cmd, "publish all to MQTT", "Publiziere MQTT", "publiceer alles naar MQTT", "publicera allt till MQTT", "opublikuj wszystko na MQTT", "Publiser alt til MQTT", "", "Hepsini MQTTye gönder", "pubblica tutto su MQTT", "zverejniť všetko na MQTT", "publikovat vše do MQTT") // TODO translate -MAKE_WORD_TRANSLATION(system_info_cmd, "show system info", "Zeige Systeminformationen", "toon systeemstatus", "visa systeminformation", "pokaż status systemu", "vis system status", "", "Sistem Durumunu Göster", "visualizza stati di sistema", "zobraziť stav systému", "zobrazit informace o systému") // TODO translate -MAKE_WORD_TRANSLATION(schedule_cmd, "enable schedule item", "Aktiviere Zeitplanelemente", "activeer tijdschema item", "aktivera schemalagt objekt", "aktywuj wybrany harmonogram", "", "", "program öğesini etkinleştir", "abilitare l'elemento programmato", "povoliť položku plánovania", "povolit položku plánování") // TODO translate -MAKE_WORD_TRANSLATION(entity_cmd, "set custom value", "Sende eigene Entitäten", "verstuur custom waarde", "sätt ett eget värde", "wyślij własną wartość", "", "", "emp üzerinde özel değer ayarla", "imposta valori personalizzati", "nastaviť vlastnú hodnotu", "nastavit vlastní hodnotu") // TODO translate -MAKE_WORD_TRANSLATION(commands_response, "get response", "Hole Antwort", "Verzoek om antwoord", "hämta svar", "uzyskaj odpowiedź", "", "", "gelen cevap", "", "získať odpoveď", "získat odpověď") // TODO translate -MAKE_WORD_TRANSLATION(coldshot_cmd, "send a cold shot of water", "Zugabe einer Menge kalten Wassers", "", "sckicka en liten mängd kallvatten", "uruchom tryśnięcie zimnej wody", "", "", "soğuk su gönder", "", "pošlite studenú dávku vody", "poslat studenou vodu") // TODO translate -MAKE_WORD_TRANSLATION(message_cmd, "send a message", "Eine Nachricht senden", "", "skicka ett meddelande", "", "", "", "", "", "poslať správu", "odeslat zprávu") // TODO translate -MAKE_WORD_TRANSLATION(values_cmd, "list all values", "Liste alle Werte auf", "", "lista alla värden", "", "", "", "", "", "vypísať všetky hodnoty", "vypsat všechny hodnoty") // TODO translate -MAKE_WORD_TRANSLATION(system_cmd, "system setting", "System Einstellung", "", "systeminställning", "", "", "", "", "", "vypísať všetky hodnoty", "vypsat všechny hodnoty") // TODO translate -MAKE_WORD_TRANSLATION(showertimer_cmd, "enable shower timer", "aktiviere Duschzeitmessung", "", "aktivera duschtimer", "", "", "", "", "", "povoliť časovač sprchovania", "povolit časovač sprchy") // TODO translate -MAKE_WORD_TRANSLATION(showeralert_cmd, "enable shower alert", "aktiviere Duschzeitwarnung", "", "aktivera duschvarning", "", "", "", "", "", "povoliť upozornenie na sprchu", "povolit alarm sprchy") // TODO translate +MAKE_WORD_TRANSLATION(info_cmd, "list all values (verbose)", "Liste aller Werte", "lijst van alle waardes", "lista alla värden", "wyświetl wszystkie wartości", "Viser alle verdier", "lister toutes les valeurs", "Tüm değerleri listele", "elenca tutti i valori", "zobraziť všetky hodnoty", "vypsat všechny hodnoty (podrobně)") +MAKE_WORD_TRANSLATION(commands_cmd, "list all commands", "Liste aller Kommandos", "lijst van alle commando's", "lista alla kommandon", "wyświetl wszystkie komendy", "Viser alle kommandoer", "lister toutes les commandes", "Tüm komutları listele", "elencaa tutti i comandi", "zobraziť všetky príkazy", "vypsat všechny příkazy") +MAKE_WORD_TRANSLATION(entities_cmd, "list all entities", "Liste aller Entitäten", "lijst van alle entiteiten", "lista all entiteter", "wyświetl wszsytkie encje", "Viser alle enheter", "lister toutes les entités", "Tüm varlıkları listele", "elenca tutte le entità", "zobraziť všetky entity", "vypsat všechny entity") +MAKE_WORD_TRANSLATION(metrics_cmd, "list all prometheus metrics", "Liste aller Prometheus Metriken", "lijst van alle Prometheus metriken", "lista alla Prometheus metriker", "wyświetl wszystkie Prometheus metryki", "Viser alle Prometheus metrikker", "lister toutes les métriques Prometheus", "Tüm Prometheus metriklerini listele", "elenca tutte le metriche Prometheus", "zobraziť všetky Prometheus metriky", "vypsat všechny Prometheus metriky") +MAKE_WORD_TRANSLATION(send_cmd, "send a telegram", "Sende EMS-Telegramm", "stuur een telegram", "skicka ett telegram", "wyślij telegram", "send et telegram", "envoyer un télégramme", "Bir telegram gönder", "invia un telegramma", "poslať telegram", "odeslat telegram") +MAKE_WORD_TRANSLATION(read_cmd, "send read request", "Sende Leseanfrage", "stuur leesaanvraag", "skicka en läsförfrågan", "wyślij żądanie odczytu", "send leseforespørsel", "envoyer une demande de lecture", "okuma isteği gönder", "invia richiesta di lettura", "odoslať žiadosť o prečítanie", "odeslat požadavek na čtení") +MAKE_WORD_TRANSLATION(setiovalue_cmd, "set I/O value", "Setze Werte E/A", "instellen standaardwaarde", "sätt ett I/O-värde", "ustaw wartość", "sett en io verdi", "définir valeur E/S", "Giriş/Çıkış değerlerini ayarla", "imposta valore io", "nastaviť hodnotu io", "nastavit hodnotu I/O") +MAKE_WORD_TRANSLATION(changeloglevel_cmd, "change log level", "Ändere Protokollebene", "aanpassen log niveau", "ändra logg-nivå", "zmień poziom log-u", "endre loggnivå", "changer le niveau de journal", "Kayıt seviyesini değiştir", "cambia livello registrazione", "zmeniť úroveň protokolu", "změnit úroveň protokolování") +MAKE_WORD_TRANSLATION(fetch_cmd, "refresh all EMS values", "Aktualisiere alle EMS-Werte", "Verversen alle EMS waardes", "uppdatera alla EMS-värden", "odśwież wszystkie wartości EMS", "oppfrisk alle EMS verdier", "actualiser toutes les valeurs EMS", "Bütün EMS değerlerini yenile", "aggiornare tutti i valori EMS", "obnoviť všetky hodnoty EMS", "aktualizovat všechny EMS hodnoty") +MAKE_WORD_TRANSLATION(restart_cmd, "restart EMS-ESP", "Neustart", "opnieuw opstarten", "starta om EMS-ESP", "uruchom ponownie EMS-ESP", "restart EMS-ESP", "redémarrer EMS-ESP", "EMS-ESPyi yeniden başlat", "riavvia EMS-ESP", "reštart EMS-ESP", "restartovat EMS-ESP") +MAKE_WORD_TRANSLATION(format_cmd, "factory reset EMS-ESP", "EMS-ESP auf Werkseinstellungen zurücksetzen", "fabrieksinstellingen EMS-ESP", "fabriksåterställ EMS-ESP", "zresetuj EMS-ESP do ustawień fabrycznych", "tilbakestill EMS-ESP til fabrikkinnstillinger", "réinitialisation EMS-ESP", "EMS-ESP fabrika ayarları", "ripristino di fabbrica EMS-ESP", "továrenske nastavenie EMS-ESP", "tovární nastavení EMS-ESP") +MAKE_WORD_TRANSLATION(watch_cmd, "watch incoming telegrams", "Beobachte eingehende Telegramme", "inkomende telegrammen bekijken", "visa inkommande telegram", "obserwuj przyczodzące telegramy", "se innkommende telegrammer", "surveiller les télégrammes entrants", "Gelen telegramları izle", "guardare i telegrammi in arrivo", "sledovať prichádzajúce telegramy", "sledovat příchozí telegramy") +MAKE_WORD_TRANSLATION(publish_cmd, "publish all to MQTT", "Publiziere MQTT", "publiceer alles naar MQTT", "publicera allt till MQTT", "opublikuj wszystko na MQTT", "Publiser alt til MQTT", "publier tout vers MQTT", "Hepsini MQTTye gönder", "pubblica tutto su MQTT", "zverejniť všetko na MQTT", "publikovat vše do MQTT") +MAKE_WORD_TRANSLATION(system_info_cmd, "show system info", "Zeige Systeminformationen", "toon systeemstatus", "visa systeminformation", "pokaż status systemu", "vis system status", "afficher les informations système", "Sistem Durumunu Göster", "visualizza stati di sistema", "zobraziť stav systému", "zobrazit informace o systému") +MAKE_WORD_TRANSLATION(schedule_cmd, "enable schedule item", "Aktiviere Zeitplanelemente", "activeer tijdschema item", "aktivera schemalagt objekt", "aktywuj wybrany harmonogram", "aktiver planlagt element", "activer élément programmé", "program öğesini etkinleştir", "abilitare l'elemento programmato", "povoliť položku plánovania", "povolit položku plánování") +MAKE_WORD_TRANSLATION(entity_cmd, "set custom value", "Sende eigene Entitäten", "verstuur custom waarde", "sätt ett eget värde", "wyślij własną wartość", "sett egendefinert verdi", "définir valeur personnalisée", "özel değer ayarla", "imposta valori personalizzati", "nastaviť vlastnú hodnotu", "nastavit vlastní hodnotu") +MAKE_WORD_TRANSLATION(commands_response, "get response", "Hole Antwort", "Verzoek om antwoord", "hämta svar", "uzyskaj odpowiedź", "få svar", "obtenir réponse", "yanıt al", "ottieni risposta", "získať odpoveď", "získat odpověď") +MAKE_WORD_TRANSLATION(coldshot_cmd, "send a cold shot of water", "Zugabe einer Menge kalten Wassers", "stuur koud water", "sckicka en liten mängd kallvatten", "uruchom tryśnięcie zimnej wody", "send kaldtvannspuls", "envoyer de l'eau froide", "soğuk su gönder", "invia acqua fredda", "pošlite studenú dávku vody", "poslat studenou vodu") +MAKE_WORD_TRANSLATION(message_cmd, "send a message", "Eine Nachricht senden", "stuur een bericht", "skicka ett meddelande", "wyślij wiadomość", "send en melding", "envoyer un message", "mesaj gönder", "invia un messaggio", "poslať správu", "odeslat zprávu") +MAKE_WORD_TRANSLATION(values_cmd, "list all values", "Liste alle Werte auf", "lijst alle waardes", "lista alla värden", "wyświetl wszystkie wartości", "list alle verdier", "lister toutes les valeurs", "tüm değerleri listele", "elenca tutti i valori", "vypísať všetky hodnoty", "vypsat všechny hodnoty") +MAKE_WORD_TRANSLATION(system_cmd, "system setting", "System Einstellung", "systeem instelling", "systeminställning", "ustawienie systemowe", "systeminnstilling", "paramètre système", "sistem ayarı", "impostazione di sistema", "nastavenie systému", "nastavení systému") +MAKE_WORD_TRANSLATION(showertimer_cmd, "enable shower timer", "aktiviere Duschzeitmessung", "activeer douche timer", "aktivera duschtimer", "aktywuj czasomierz prysznica", "aktiver dusjtimer", "activer minuteur de douche", "duş zamanlayıcısını etkinleştir", "abilita timer doccia", "povoliť časovač sprchovania", "povolit časovač sprchy") +MAKE_WORD_TRANSLATION(showeralert_cmd, "enable shower alert", "aktiviere Duschzeitwarnung", "activeer douche alarm", "aktivera duschvarning", "aktywuj alarm prysznica", "aktiver dusjvarsel", "activer alerte de douche", "duş uyarısını etkinleştir", "abilita allarme doccia", "povoliť upozornenie na sprchu", "povolit alarm sprchy") +MAKE_WORD_TRANSLATION(txpause_cmd, "pause EMS Tx", "EMS Tx pausieren", "pauzeer EMS Tx", "pausa EMS Tx", "wstrzymaj EMS Tx", "pause EMS Tx", "pause EMS Tx", "EMS Tx'i duraklat", "pausa EMS Tx", "pozastaviť EMS Tx", "pauzovat EMS Tx") // tags MAKE_WORD_TRANSLATION(tag_hc1, "hc1", "HK1", "hc1", "VK1", "OG1", "hc1", "hc1", "ID1", "hc1", "hc1", "hc1") @@ -186,7 +187,7 @@ MAKE_WORD_TRANSLATION(vacuum, "vacuum", "Vakuum", "vacuum", "Vakuum", "próżnia MAKE_WORD_TRANSLATION(co2_optimized, "co2 optimized", "CO2 optimiert", "CO2 geoptimaliseerd", "CO2-optimerad", "optymalizacja CO2", "co2 optimalisert", "optimisé en CO2", "CO2 verimli", "CO2 ottimizzato", "co2 optimalizované", "optimalizace CO2") MAKE_WORD_TRANSLATION(cost_optimized, "cost optimized", "kostenoptimiert", "kosten geoptimaliseerd", "kostnadsoptimerad", "optymalizacja kosztów", "kostnadsoptimalisert", "optimisé en coût", "maliyet odaklı", "costo ottimizzato", "nákladovo optimalizované", "optimalizace nákladů") MAKE_WORD_TRANSLATION(outside_temp_switched, "outside temp switched", "Außentemp. gesteuert", "buitentemp. gestuurd", "Utomhustemp korrigerad", "temperatura zewn. przeł.", "utetemp optimalisert", "contrôle par temp. ext.", "dış hava sıcaklığına bağlı", "temperatura esterna cambiata", "prepnuta vonkajsia teplota", "venkovní teplota přepnuta") -MAKE_WORD_TRANSLATION(co2_cost_mix, "co2 cost mix", "CO2-Kostenmix", "CO2-kostenmix", "CO2-Kostnadsmix", "mieszany koszt CO2", "", "coût mixte CO2", "karışık maliyet", "co2 cost mix", "co2 náklady mix", "mix nákladů CO2") // TODO translate +MAKE_WORD_TRANSLATION(co2_cost_mix, "co2 cost mix", "CO2-Kostenmix", "CO2-kostenmix", "CO2-Kostnadsmix", "mieszany koszt CO2", "CO2-kostnadsmiks", "coût mixte CO2", "karışık maliyet", "co2 cost mix", "co2 náklady mix", "mix nákladů CO2") MAKE_WORD_TRANSLATION(analog, "analog", "analog", "analoog", "analog", "analogowy", "analog", "analogique", "analog", "analogico", "analógový", "analogový") MAKE_WORD_TRANSLATION(normal, "normal", "normal", "normaal", "normal", "normalny", "normal", "normal", "normal", "normale", "normálny", "normální") MAKE_WORD_TRANSLATION(blocking, "blocking", "Blockierung", "blokkering", "Blockering", "blokowanie", "blokkering", "bloquant", "engelleme", "bloccaggio", "blokovanie", "blokování") @@ -194,10 +195,10 @@ MAKE_WORD_TRANSLATION(extern, "extern", "extern", "extern", "extern", "zewnętrz MAKE_WORD_TRANSLATION(intern, "intern", "intern", "intern", "intern", "wewnętrzny", "intern", "interne", "iç", "interno", "interný", "interní") MAKE_WORD_TRANSLATION(lower, "lower", "niedriger", "lager", "lägre", "mniejszy", "nedre", "inférieur", "daha düşük", "basso", "nízky", "nízký") MAKE_WORD_TRANSLATION(error, "error", "Fehler", "error", "Fel", "błąd", "feil", "erreur", "Hata", "errore", "error", "chyba") -MAKE_WORD_TRANSLATION(history, "history", "Fehlerspeicher", "", "historik", "historia", "", "", "", "", "história", "historie") // TODO translate +MAKE_WORD_TRANSLATION(history, "history", "Fehlerspeicher", "geschiedenis", "historik", "historia", "historikk", "historique", "geçmiş", "storico", "história", "historie") MAKE_WORD_TRANSLATION(message, "message", "Meldung", "melding", "meddelande", "komunikat", "melding", "message", "mesajı", "messaggio", "správa", "zpráva") MAKE_WORD_TRANSLATION(na, "n/a", "n/a", "n/a", "n/a", "nd.", "n/a", "n/c", "mevcut değil", "n/a", "n/a", "n/a") -MAKE_WORD_TRANSLATION(inverted, "inverted", "invertiert", "", "inverterad", "odwrócony", "", "", "", "", "invertovaný", "invertovaný") // TODO translate +MAKE_WORD_TRANSLATION(inverted, "inverted", "invertiert", "omgekeerd", "inverterad", "odwrócony", "invertert", "inversé", "ters", "invertito", "invertovaný", "invertovaný") // boiler MAKE_WORD_TRANSLATION(time, "time", "Zeit", "tijd", "Tid", "godzina", "tid", "heure", "zaman", "ora", "čas", "čas") @@ -213,27 +214,27 @@ MAKE_WORD_TRANSLATION(intelligent, "intelligent", "Intelligent", "intelligent", MAKE_WORD_TRANSLATION(flow, "flow", "Durchfluss", "volumestroom", "Flöde", "przepływ", "strømme", "débit", "akım", "flusso", "tok", "průtok") MAKE_WORD_TRANSLATION(manual, "manual", "Manuell", "handmatig", "Manuell", "ręczny", "manuell", "manuel", "manuel", "manuale", "manuálny", "manuální") MAKE_WORD_TRANSLATION(buffer, "buffer", "Speicher", "buffer", "Buffert", "bufor", "buffer", "buffer", "tampon", "Buffer", "zásobník", "zásobník") -MAKE_WORD_TRANSLATION(bufferedflow, "buffered flow", "Durchlaufspeicher", "doorstroombuffer", "Buffertflöde", "przepływ buforowany", "bufret strømning", "", "tampon akım", "memoria flusso", "zásobníkový prietok", "zásobníkový průtok") // TODO translate -MAKE_WORD_TRANSLATION(layeredbuffer, "layered buffer", "Schichtspeicher", "gelaagde buffer", "Lagrad buffert", "bufor warstwowy", "lagdelt buffer", "", "katmanlı akım", "strato memoria", "vrstvený zásobník", "vrstvený zásobník") // TODO translate +MAKE_WORD_TRANSLATION(bufferedflow, "buffered flow", "Durchlaufspeicher", "doorstroombuffer", "Buffertflöde", "przepływ buforowany", "bufret strømning", "flux tamponné", "tampon akım", "memoria flusso", "zásobníkový prietok", "zásobníkový průtok") +MAKE_WORD_TRANSLATION(layeredbuffer, "layered buffer", "Schichtspeicher", "gelaagde buffer", "Lagrad buffert", "bufor warstwowy", "lagdelt buffer", "tampon stratifié", "katmanlı tampon", "strato memoria", "vrstvený zásobník", "vrstvený zásobník") MAKE_WORD_TRANSLATION(maintenance, "maintenance", "Wartung", "onderhoud", "Underhåll", "przegląd", "vedlikehold", "maintenance", "bakım", "servizio", "údržba", "údržba") MAKE_WORD_TRANSLATION(heating, "heating", "Heizen", "verwarmen", "Uppvärmning", "ogrzewanie", "oppvarming", "chauffage", "ısıtma", "riscaldamento", "kúrenie", "topení") MAKE_WORD_TRANSLATION(cooling, "cooling", "Kühlen", "koelen", "Kyler", "chłodzenie", "kjøling", "refroidissement", "soğuma", "raffreddamento", "chladenie", "chlazení") -MAKE_WORD_TRANSLATION(heatandcool, "heating & cooling", "Heizen & Kühlen", "verwarmen & koelen", "Uppvärmning & Kyla", "ogrzewanie i chłodzenie", "", "", "ısıtma & soğutma", "", "kúrenie a chladenie", "topení a chlazení") // TODO translate +MAKE_WORD_TRANSLATION(heatandcool, "heating & cooling", "Heizen & Kühlen", "verwarmen & koelen", "Uppvärmning & Kyla", "ogrzewanie i chłodzenie", "oppvarming & kjøling", "chauffage et refroidissement", "ısıtma & soğutma", "riscaldamento e raffreddamento", "kúrenie a chladenie", "topení a chlazení") MAKE_WORD_TRANSLATION(disinfecting, "disinfecting", "Desinfizieren", "desinfecteren", "Desinficerar", "dezynfekcja termiczna", "desinfisering", "désinfection", "dezenfeksiyon", "disinfezione", "dezinfekcia", "dezinfekce") MAKE_WORD_TRANSLATION(no_heat, "no heat", "keine Wärme", "geen warmte", "Ingen värme", "brak ciepła", "ingen varme", "pas de chauffage", "ısınma yok", "nessun calore", "žiadne teplo", "bez tepla") MAKE_WORD_TRANSLATION(heatrequest, "heat request", "Wärmeanforderung", "verwarmingsverzoek", "Värmeförfrågan", "zapotrzebowanie na ciepło", "varmeforespørsel", "demande de chauffage", "ısınma ihtiyacı", "richiesta calore", "požiadavka na teplo", "požadavek na teplo") MAKE_WORD_TRANSLATION(valve, "valve", "Ventil", "klep", "Ventil", "zawór", "ventil", "valve", "vana", "valvola", "ventil", "ventil") -MAKE_WORD_TRANSLATION(proportional, "proportional", "proportional", "proportioneel", "proportionell", "proporcjonalny", "proposjonal", "", "oransal", "proporzionale", "proporcionálne", "proporcionální") // TODO translate -MAKE_WORD_TRANSLATION(deltaP1, "deltaP-1", "deltaP-1", "deltaP-1", "deltaP-1", "delta P-1", "deltaP-1", "", "deltaP-1", "deltaP-1", "deltaP-1", "deltaP-1") // TODO translate -MAKE_WORD_TRANSLATION(deltaP2, "deltaP-2", "deltaP-2", "deltaP-2", "deltaP-2", "delta P-2", "deltaP-2", "", "deltaP-2", "deltaP-2", "deltaP-2", "deltaP-2") // TODO translate -MAKE_WORD_TRANSLATION(deltaP3, "deltaP-3", "deltaP-3", "deltaP-3", "deltaP-3", "delta P-3", "deltaP-3", "", "deltaP-3", "deltaP-3", "deltaP-3", "deltaP-3") // TODO translate -MAKE_WORD_TRANSLATION(deltaP4, "deltaP-4", "deltaP-4", "deltaP-4", "deltaP-4", "delta P-4", "deltaP-4", "", "deltaP-4", "deltaP-4", "deltaP-4", "deltaP-4") // TODO translate -MAKE_WORD_TRANSLATION(pressure1, "150mbar", "150mbar", "150mbar", "150mbar", "150mbar", "150mbar", "150mbar", "150mbar", "150mbar", "150mbar", "150mbar") // TODO translate -MAKE_WORD_TRANSLATION(pressure2, "200mbar", "200mbar", "200mbar", "200mbar", "200mbar", "200mbar", "200mbar", "200mbar", "200mbar", "200mbar", "200mbar") // TODO translate -MAKE_WORD_TRANSLATION(pressure3, "250mbar", "250mbar", "250mbar", "250mbar", "250mbar", "250mbar", "250mbar", "250mbar", "250mbar", "250mbar", "250mbar") // TODO translate -MAKE_WORD_TRANSLATION(pressure4, "300mbar", "300mbar", "300mbar", "300mbar", "300mbar", "300mbar", "300mbar", "300mbar", "300mbar", "300mbar", "300mbar") // TODO translate -MAKE_WORD_TRANSLATION(pressure5, "350mbar", "350mbar", "350mbar", "350mbar", "350mbar", "350mbar", "350mbar", "350mbar", "350mbar", "350mbar", "350mbar") // TODO translate -MAKE_WORD_TRANSLATION(pressure6, "400mbar", "400mbar", "400mbar", "400mbar", "400mbar", "400mbar", "400mbar", "400mbar", "400mbar", "400mbar", "400mbar") // TODO translate +MAKE_WORD_TRANSLATION(proportional, "proportional", "proportional", "proportioneel", "proportionell", "proporcjonalny", "proposjonal", "proportionnel", "oransal", "proporzionale", "proporcionálne", "proporcionální") +MAKE_WORD_TRANSLATION(deltaP1, "deltaP-1", "deltaP-1", "deltaP-1", "deltaP-1", "delta P-1", "deltaP-1", "deltaP-1", "deltaP-1", "deltaP-1", "deltaP-1", "deltaP-1") +MAKE_WORD_TRANSLATION(deltaP2, "deltaP-2", "deltaP-2", "deltaP-2", "deltaP-2", "delta P-2", "deltaP-2", "deltaP-2", "deltaP-2", "deltaP-2", "deltaP-2", "deltaP-2") +MAKE_WORD_TRANSLATION(deltaP3, "deltaP-3", "deltaP-3", "deltaP-3", "deltaP-3", "delta P-3", "deltaP-3", "deltaP-3", "deltaP-3", "deltaP-3", "deltaP-3", "deltaP-3") +MAKE_WORD_TRANSLATION(deltaP4, "deltaP-4", "deltaP-4", "deltaP-4", "deltaP-4", "delta P-4", "deltaP-4", "deltaP-4", "deltaP-4", "deltaP-4", "deltaP-4", "deltaP-4") +MAKE_WORD_TRANSLATION(pressure1, "150mbar", "150mbar", "150mbar", "150mbar", "150mbar", "150mbar", "150mbar", "150mbar", "150mbar", "150mbar", "150mbar") +MAKE_WORD_TRANSLATION(pressure2, "200mbar", "200mbar", "200mbar", "200mbar", "200mbar", "200mbar", "200mbar", "200mbar", "200mbar", "200mbar", "200mbar") +MAKE_WORD_TRANSLATION(pressure3, "250mbar", "250mbar", "250mbar", "250mbar", "250mbar", "250mbar", "250mbar", "250mbar", "250mbar", "250mbar", "250mbar") +MAKE_WORD_TRANSLATION(pressure4, "300mbar", "300mbar", "300mbar", "300mbar", "300mbar", "300mbar", "300mbar", "300mbar", "300mbar", "300mbar", "300mbar") +MAKE_WORD_TRANSLATION(pressure5, "350mbar", "350mbar", "350mbar", "350mbar", "350mbar", "350mbar", "350mbar", "350mbar", "350mbar", "350mbar", "350mbar") +MAKE_WORD_TRANSLATION(pressure6, "400mbar", "400mbar", "400mbar", "400mbar", "400mbar", "400mbar", "400mbar", "400mbar", "400mbar", "400mbar", "400mbar") MAKE_WORD_TRANSLATION(pumpstep, "pumpstep", "Stufen") MAKE_WORD_TRANSLATION(consthigh, "const.high", "konst.hoch") MAKE_WORD_TRANSLATION(constmed, "const.medium", "konst.mittel") @@ -245,7 +246,7 @@ MAKE_WORD_TRANSLATION(proplow, "propo.low", "prop.niedrig") MAKE_WORD_TRANSLATION(none, "none", "keine", "geen", "ingen", "brak", "ingen", "aucun", "hiçbiri", "nessuno", "žiadny", "žádné") MAKE_WORD_TRANSLATION(hot_water, "hot water", "Warmwasser", "warm water", "varmvatten", "c.w.u.", "varmtvann", "eau chaude", "sıcak su", "acqua calda", "horúca voda", "horká voda") MAKE_WORD_TRANSLATION(pool, "pool", "Pool", "zwembad", "pool", "basen", "basseng", "piscine", "havuz", "piscina", "bazén", "bazén") -MAKE_WORD_TRANSLATION(pool_heating, "pool heating", "Pool beheizen", "", "", "", "", "", "", "", "ohrev bazéna", "ohřev bazénu") +MAKE_WORD_TRANSLATION(pool_heating, "pool heating", "Pool beheizen", "zwembadverwarming", "uppvärmning av pool", "ogrzewanie basenu", "bassengoppvarming", "chauffage piscine", "havuz ısıtma", "riscaldamento piscina", "ohrev bazéna", "ohřev bazénu") MAKE_WORD_TRANSLATION(outside_temp_alt, "outside temperature alt.", "Außentemp. alternativ", "alternatieve buitentemperatuur", "Alternativ utomhustemp.", "temp. zewn. alternat.", "alternativ utendørstemp.", "température extérieure alternative", "alternatif dış sıcaklık", "temperatura esterna alternativa", "vonkajšia teplota altern.", "venkovní teplota alt.") MAKE_WORD_TRANSLATION(outside_temp_par, "outside temperature parallel", "Außentemp. parallel", "buitentemperatuur parallel", "Parallell utomhustemp.", "temp. zewn. równoległa", "parallell utendørstemp.", "température extérieure parallèle", "paralel dış sıcaklık", "temperatura esterna parallela", "paralelne s vonkajšou teplotou", "paralelně s venkovní teplotou") MAKE_WORD_TRANSLATION(hp_preferred, "heatpump preferred", "Wärmepumpe bevorzugt", "voorkeur warmtepomp", "Värmepump föredraget", "preferowana pompa ciepła", "varmepumpe prioritert", "pompe à chaleur préférée", "tercih edilen pompa", "pompa di calore preferita", "preferované tepelné čerpadlo", "preferované tepelné čerpadlo") @@ -253,14 +254,14 @@ MAKE_WORD_TRANSLATION(boiler_only, "boiler only", "nur Kessel", "uitsluitend cv MAKE_WORD_TRANSLATION(reduced_output, "reduced output", "Reduzierte Leistung", "gereduceerde output", "Reducerad produktion", "zmniejszona wydajność", "redusert ytelse", "sortie réduite", "düşürülmüş çıkış", "riduzione uscita", "znížený výkon", "snížený výkon") MAKE_WORD_TRANSLATION(switchoff, "switch off hp", "WP ausschalten", "WP uitschakelen", "Värmepump avstängd", "wyłącz pompę ciepła", "slå av varmepumpe", "éteindre la PAC", "ısı pompasını kapat", "spegnimento pompa calore", "vypnúť tep. čerpadlo", "vypnout tepelné čerpadlo") MAKE_WORD_TRANSLATION(perm, "perm. reduced", "perm. reduziert", "permanent gereduceerd", "Permanent reducerad", "stale zmniejszona wydajność", "permanent redusert", "réduction permanente", "sürekli azaltılmış", "riduzione permanente", "trvalo znížené", "trvale sníženo") -MAKE_WORD_TRANSLATION(heat_ww, "heating & dhw", "Heizen & Warmwasser", "", "Uppvärmning & Varmvatten", "ogrzewanie i c.w.u.", "", "", "", "", "kúrenie a TÚV", "topení a TUV") -MAKE_WORD_TRANSLATION(cool_defrost, "cooling & defrost", "Kühlen & Abtauen", "", "Kyla & Avfrostning", "chłodzenie i odladzanie", "", "", "", "", "chladenie a rozmrazovanie", "chlazení a odmrazování") -MAKE_WORD_TRANSLATION(compressor_alarm, "compressor alarm", "Alarm Kompressor", "", "", "", "", "", "", "", "alarm kompresora", "alarm kompresoru") -MAKE_WORD_TRANSLATION(not_installed, "not installed", "Nicht installiert", "", "", "", "", "", "", "", "nenainštalované", "není nainstalováno") // TODO translate -MAKE_WORD_TRANSLATION(el_heater, "electric heater", "Elektroheizer", "", "", "", "", "", "", "", "elektrický ohrev", "elektrický ohřev") // TODO translate -MAKE_WORD_TRANSLATION(exclusive, "exclusive", "Exklusiv", "", "", "", "", "", "", "", "ekluzívne", "exkluzivní") // TODO translate -MAKE_WORD_TRANSLATION(parallel, "parallel", "Parallel", "", "", "", "", "", "", "", "paralelné", "paralelní") // TODO translate -MAKE_WORD_TRANSLATION(hybrid, "hybrid", "Hybrid", "", "", "", "", "", "", "", "hybridné", "hybridní") // TODO translate +MAKE_WORD_TRANSLATION(heat_ww, "heating & dhw", "Heizen & Warmwasser", "verwarmen & warmwater", "Uppvärmning & Varmvatten", "ogrzewanie i c.w.u.", "oppvarming & varmtvann", "chauffage et eau chaude sanitaire", "ısıtma ve sıcak su", "riscaldamento e acqua calda", "kúrenie a TÚV", "topení a TUV") +MAKE_WORD_TRANSLATION(cool_defrost, "cooling & defrost", "Kühlen & Abtauen", "koelen & ontdooien", "Kyla & Avfrostning", "chłodzenie i odladzanie", "kjøling & avriming", "refroidissement et dégivrage", "soğutma ve buz çözme", "raffreddamento e sbrinamento", "chladenie a rozmrazovanie", "chlazení a odmrazování") +MAKE_WORD_TRANSLATION(compressor_alarm, "compressor alarm", "Alarm Kompressor", "compressor alarm", "kompressorlarm", "alarm kompresora", "kompressoralarm", "alarme compresseur", "kompresör alarmı", "allarme compressore", "alarm kompresora", "alarm kompresoru") +MAKE_WORD_TRANSLATION(not_installed, "not installed", "Nicht installiert", "niet geïnstalleerd", "inte installerad", "nie zainstalowane", "ikke installert", "non installé", "kurulu değil", "non installato", "nenainštalované", "není nainstalováno") +MAKE_WORD_TRANSLATION(el_heater, "electric heater", "Elektroheizer", "elektrische verwarming", "elvärmare", "grzałka elektryczna", "elektrisk varmer", "chauffage électrique", "elektrikli ısıtıcı", "riscaldatore elettrico", "elektrický ohrev", "elektrický ohřev") +MAKE_WORD_TRANSLATION(exclusive, "exclusive", "Exklusiv", "exclusief", "exklusiv", "wyłączny", "eksklusiv", "exclusif", "özel", "esclusivo", "ekluzívne", "exkluzivní") +MAKE_WORD_TRANSLATION(parallel, "parallel", "Parallel", "parallel", "parallell", "równoległy", "parallell", "parallèle", "paralel", "parallelo", "paralelné", "paralelní") +MAKE_WORD_TRANSLATION(hybrid, "hybrid", "Hybrid", "hybride", "hybrid", "hybrydowy", "hybrid", "hybride", "hibrit", "ibrido", "hybridné", "hybridní") // thermostat MAKE_WORD_TRANSLATION(seltemp, "selTemp", "Solltemperatur", "doeltemperatuur", "Börtemperatur", "temperatura zadana", "innstilt temperatur", "consigne température", "ayarlanmış sıcaklık", "temperatura di consegna", "zadaná teplota", "zvolená teplota") @@ -281,16 +282,16 @@ MAKE_WORD_TRANSLATION(french, "french", "Französisch", "Frans", "Franska", "fra MAKE_WORD_TRANSLATION(italian, "italian", "Italienisch", "Italiaans", "Italienska", "włoski", "italiensk", "italien", "İtalyanca", "Italiano", "taliansky", "italština") MAKE_WORD_TRANSLATION(high, "high", "hoch", "hoog", "Hög", "wysoki", "høy", "haut", "yüksek", "alto", "vysoký", "vysoký") MAKE_WORD_TRANSLATION(low, "low", "niedrig", "laag", "Låg", "niski", "lav", "bas", "düşük", "basso", "nízky", "nízký") -MAKE_WORD_TRANSLATION(curve, "heatingcurve", "Heizkurve", "", "värmekurva", "krzywa grzania", "", "", "", "", "vykurovacia krivka", "křivka topení") // TODO translate +MAKE_WORD_TRANSLATION(curve, "heatingcurve", "Heizkurve", "stookkromme", "värmekurva", "krzywa grzania", "varmekurve", "courbe de chauffage", "ısıtma eğrisi", "curva di riscaldamento", "vykurovacia krivka", "křivka topení") MAKE_WORD_TRANSLATION(radiator, "radiator", "Heizkörper", "radiator", "Radiator", "grzejniki", "radiator", "radiateur", "radyatör", "radiatore", "radiátor", "radiátor") MAKE_WORD_TRANSLATION(convector, "convector", "Konvektor", "convector", "Konvektor", "konwektory", "konvektor", "convecteur", "convector", "convettore", "konvektor", "konvektor") MAKE_WORD_TRANSLATION(floor, "floor", "Fussboden", "vloer", "Golv", "podłoga", "gulv", "sol", "yer", "pavimento", "podlaha", "podlaha") -MAKE_WORD_TRANSLATION(roomflow, "roomflow", "Raum Fluß", "", "Rumsflöde", "", "", "", "", "", "prúdenie miestnosti", "průtok mistnosti") // TODO translate -MAKE_WORD_TRANSLATION(roomload, "roomload", "Raum Bedarf", "", "Rumsbehov", "", "", "", "", "", "izbová zaťaž", "zatížení místnosti") // TODO translate +MAKE_WORD_TRANSLATION(roomflow, "roomflow", "Raum Fluß", "kamer doorstroming", "Rumsflöde", "przepływ w pomieszczeniu", "romstrøm", "flux de la pièce", "oda akışı", "flusso della stanza", "prúdenie miestnosti", "průtok mistnosti") +MAKE_WORD_TRANSLATION(roomload, "roomload", "Raum Bedarf", "kamer behoefte", "Rumsbehov", "zapotrzebowanie pomieszczenia", "rombelastning", "charge de la pièce", "oda yükü", "carico della stanza", "izbová zaťaž", "zatížení místnosti") MAKE_WORD_TRANSLATION(summer, "summer", "Sommer", "zomer", "Sommar", "lato", "sommer", "été", "yaz", "estate", "leto", "léto") MAKE_WORD_TRANSLATION(winter, "winter", "Winter", "winter", "Vinter", "zima", "vinter", "hiver", "kış", "inverno", "zima", "zima") MAKE_WORD_TRANSLATION(outdoor, "outdoor", "Außen", "buiten", "Utomhus", "temp. zewnętrzna", "utendørs", "extérieur", "dış", "esterno", "vonku", "venkovní") -MAKE_WORD_TRANSLATION(room, "room", "Raum", "kamer", "Rum", "temp. w pomieszczeniu", "", "pièce", "oda", "camera", "izba", "dle teploty prostoru") // TODO translate +MAKE_WORD_TRANSLATION(room, "room", "Raum", "kamer", "Rum", "temp. w pomieszczeniu", "rom", "pièce", "oda", "camera", "izba", "dle teploty prostoru") MAKE_WORD_TRANSLATION(room_outdoor, "room outdoor", "Raum + Außen", "kamer + buiten", "Rum + Ute", "temp. w pom. i zewn.", "rom utendørs", "pièce extérieure", "oda ve dış", "camera esterna", "miestnosť vonku", "místnost venku") MAKE_WORD_TRANSLATION(power, "power", "Leistung", "vermogen", "Effekt", "moc", "effekt", "puissance", "güç", "potenza", "výkon", "výkon") MAKE_WORD_TRANSLATION(constant, "constant", "konstant", "constant", "Konstant", "stały", "konstant", "constant", "sabit", "costante", "konštantný", "konstantní") @@ -319,11 +320,11 @@ MAKE_WORD_TRANSLATION(smoke_temperature, "smoke temperature", "Abgastemperatur", MAKE_WORD_TRANSLATION(weather_compensated, "weather compensated", "Wetter kompensiert", "weer gecompenseerd", "Väderkompenserad", "skompensow. pogodą", "værkompensert", "compensation par l'extérieur", "hava durumuna göre dengelenmiş", "acqua compensata", "kompenzácia počasia", "dle venkovní teploty") MAKE_WORD_TRANSLATION(outside_basepoint, "outside basepoint", "Basispunkt Außentemp.", "buiten basispunt", "Utomhus baspunkt", "temp. zewn. z pkt. pocz.", "utendørs basispunkt", "point de base temp. ext.", "dış hava sıcaklığı taban noktası", "basepoint esterno", "vonkajší základný bod", "venkovní teplota s patním bodem") MAKE_WORD_TRANSLATION(functioning_mode, "functioning mode", "Funktionsweise", "functiemodus", "Driftläge", "tryb pracy", "driftsmodus", "mode de fonctionnement", "işletme konumu", "modalità di funzionamento", "funkčný režim", "provozní režim") -MAKE_WORD_TRANSLATION(unmixed, "unmixed", "ungemischt", "", "oshuntad", "niezmieszany", "", "", "", "", "nezmiešaný", "nemíchaný") // TODO translate -MAKE_WORD_TRANSLATION(unmixedIPM, "unmixed IPM", "ungemischt IPM", "", "oshuntad IPM", "niezmieszany IPM", "", "", "", "", "nezmiešaný IPM", "nemíchaný IPM") // TODO translate -MAKE_WORD_TRANSLATION(mixed, "mixed IPM", "gemischt IPM", "", "shuntad IPM", "zmieszany IPM", "", "", "", "", "zmiešaný IPM", "míchaný IPM") // TODO translate -MAKE_WORD_TRANSLATION(level, "level", "Level", "", "nivå", "", "", "", "", "", "úroveň", "úroveň") // TODO translate -MAKE_WORD_TRANSLATION(absolute, "absolute", "Absolut", "", "absolut", "", "", "", "", "", "absolútny", "absolutní") // TODO translate +MAKE_WORD_TRANSLATION(unmixed, "unmixed", "ungemischt", "ongemengd", "oshuntad", "niezmieszany", "umiksert", "non mélangé", "karışmamış", "non miscelato", "nezmiešaný", "nemíchaný") +MAKE_WORD_TRANSLATION(unmixedIPM, "unmixed IPM", "ungemischt IPM", "ongemengd IPM", "oshuntad IPM", "niezmieszany IPM", "umiksert IPM", "IPM non mélangé", "karışmamış IPM", "IPM non miscelato", "nezmiešaný IPM", "nemíchaný IPM") +MAKE_WORD_TRANSLATION(mixed, "mixed IPM", "gemischt IPM", "gemengd IPM", "shuntad IPM", "zmieszany IPM", "mikset IPM", "IPM mélangé", "karışık IPM", "IPM miscelato", "zmiešaný IPM", "míchaný IPM") +MAKE_WORD_TRANSLATION(level, "level", "Level", "niveau", "nivå", "poziom", "nivå", "niveau", "seviye", "livello", "úroveň", "úroveň") +MAKE_WORD_TRANSLATION(absolute, "absolute", "Absolut", "absoluut", "absolut", "absolutny", "absolutt", "absolu", "mutlak", "assoluto", "absolútny", "absolutní") // mixer MAKE_WORD_TRANSLATION(stopped, "stopped", "gestoppt", "gestopt", "stoppad", "zatrzymany", "stoppet", "arrêté", "durdu", "fermato", "zastavený", "zastavené") @@ -333,15 +334,15 @@ MAKE_WORD_TRANSLATION(open, "open", "offen", "open", "Öppen", "otwórz", "åpen MAKE_WORD_TRANSLATION(close, "close", "geschlossen", "Gesloten", "Stängd", "zamknij", "stengt", "fermé", "kapalı", "chiudere", "zatvoriť", "zavřít") // solar dhw -MAKE_WORD_TRANSLATION(cyl1, "cyl 1", "Zyl_1", "Cil 1", "Cyl 1", "cyl 1", "cyl 1", "cyl 1", "cly 1", "Cil 1", "cyl 1", "") -MAKE_WORD_TRANSLATION(cyl2, "cyl 2", "Zyl_2", "Cil 2", "Cyl 2", "cyl 2", "cyl 2", "cyl 2", "cly 1", "Cil 2", "cyl 2", "") +MAKE_WORD_TRANSLATION(cyl1, "cyl 1", "Zyl_1", "Cil 1", "Cyl 1", "cyl 1", "cyl 1", "cyl 1", "cly 1", "Cil 1", "cyl 1", "cyl 1") +MAKE_WORD_TRANSLATION(cyl2, "cyl 2", "Zyl_2", "Cil 2", "Cyl 2", "cyl 2", "cyl 2", "cyl 2", "cly 2", "Cil 2", "cyl 2", "cyl 2") // ventilation -MAKE_WORD_TRANSLATION(demand, "demand", "Bedarf", "vereist", "behov", "zapotrzebowanie", "", "", "talep", "richiesta", "požiadavka", "poptávka") // TODO translate -MAKE_WORD_TRANSLATION(intense, "intense", "Intensiv", "intensief", "intensiv", "intensywne", "", "", "yoğun", "intensivo", "intenzívne", "intenzivní") // TODO translate -MAKE_WORD_TRANSLATION(sleep, "sleep", "Einschlafen", "slaapmodus", "sova", "sen", "", "", "uyku", "notturno", "spiace", "spánek") // TODO translate -MAKE_WORD_TRANSLATION(partymode, "party", "Party", "party", "party", "impreza", "", "", "parti", "festa", "párty režim", "párty") // TODO translate -MAKE_WORD_TRANSLATION(fireplace, "fireplace", "Kamin", "haard", "Kamin", "kominek", "", "", "şömine", "camino", "krb", "krb") // TODO translate +MAKE_WORD_TRANSLATION(demand, "demand", "Bedarf", "vereist", "behov", "zapotrzebowanie", "krav", "demande", "talep", "richiesta", "požiadavka", "poptávka") +MAKE_WORD_TRANSLATION(intense, "intense", "Intensiv", "intensief", "intensiv", "intensywne", "intensiv", "intense", "yoğun", "intensivo", "intenzívne", "intenzivní") +MAKE_WORD_TRANSLATION(sleep, "sleep", "Einschlafen", "slaapmodus", "sova", "sen", "sove", "sommeil", "uyku", "notturno", "spiace", "spánek") +MAKE_WORD_TRANSLATION(partymode, "party", "Party", "party", "party", "impreza", "fest", "fête", "parti", "festa", "párty režim", "párty") +MAKE_WORD_TRANSLATION(fireplace, "fireplace", "Kamin", "haard", "Kamin", "kominek", "peis", "cheminée", "şömine", "camino", "krb", "krb") // SRC plus MAKE_WORD_TRANSLATION(chefhat, "mdi:chef-hat", "mdi:chef-hat") @@ -358,13 +359,13 @@ MAKE_WORD_TRANSLATION(washingmachine, "mdi:washing-machine", "mdi:washing-machin MAKE_WORD_TRANSLATION(bookshelf, "mdi:bookshelf", "mdi:bookshelf") // MQTT Discovery - this is special device entity for 'climate' -MAKE_TRANSLATION(haclimate, "haclimate", "mqtt discovery current room temperature", "Discovery aktuelle Raumtemperatur", "Discovery huidige kamertemperatuur", "MQTT Discovery för aktuell rumstemperatur", "termostat w HA", "HA Avlest temp", "", "Güncel osa sıcaklığı", "verifica temperatura ambiente attuale", "mqtt discovery aktuálna teplota v miestnosti", "mqtt discovery aktuální pokojová teplota") // TODO translate +MAKE_TRANSLATION(haclimate, "haclimate", "mqtt discovery current room temperature", "Discovery aktuelle Raumtemperatur", "Discovery huidige kamertemperatuur", "MQTT Discovery för aktuell rumstemperatur", "termostat w HA", "HA Avlest temp", "découverte mqtt température actuelle", "Güncel osa sıcaklığı", "verifica temperatura ambiente attuale", "mqtt discovery aktuálna teplota v miestnosti", "mqtt discovery aktuální pokojová teplota") // Entity translations: tag, mqtt, en, de, nl, sv, pl, no, fr, tr, it, sk, cz // Boiler -MAKE_TRANSLATION(chimneysweeper, "chimneysweeper", "chimney sweeper", "Schornsteinfeger", "", "", "", "", "", "", "kominár", "kominík") // TODO translate +MAKE_TRANSLATION(chimneysweeper, "chimneysweeper", "chimney sweeper", "Schornsteinfeger", "schoorsteenveger", "Sotare", "tryb kominiarza", "feier", "ramoneur", "baca temizleyici", "spazzacamino", "kominár", "kominík") MAKE_TRANSLATION(reset, "reset", "reset", "Reset", "Reset", "Återställ", "kasowanie komunikatu", "nullstill", "reset", "Sıfırla", "Reset", "reset", "reset") -MAKE_TRANSLATION(forceHeatingOff, "heatingoff", "force heating off", "Heizen abschalten", "", "Uppvärmning avstängd", "wymuś wyłączenie grzania", "", "", "", "", "vynútené vypnutie kúrenia", "vynutit vypnutí vytápění") // TODO translate +MAKE_TRANSLATION(forceHeatingOff, "heatingoff", "force heating off", "Heizen abschalten", "verwarming forceren uit", "Uppvärmning avstängd", "wymuś wyłączenie grzania", "tvungen oppvarming av", "forcer chauffage éteint", "ısıtmayı zorla kapat", "forzare riscaldamento spento", "vynútené vypnutie kúrenia", "vynutit vypnutí vytápění") MAKE_TRANSLATION(wwtapactivated, "tapactivated", "turn on/off", "Durchlauferhitzer aktiv", "zet aan/uit", "på/av", "system przygotowywania", "Varmtvann active", "ecs activée", "aç/kapa", "commuta on/off", "zapnúť/vypnúť", "zapnout/vypnout") 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", "predohrev oleja", "předehřev oleje") 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", "vykurovanie aktívne", "Vytápění aktivní") @@ -397,7 +398,7 @@ MAKE_TRANSLATION(burnMinPower, "burnminpower", "burner min power", "Minimale Bre MAKE_TRANSLATION(burnMaxPower, "burnmaxpower", "burner max power", "Maximale Brennerleistung", "Maximaal brandervermogen", "Värmepanna Max Effekt", "maksymalna moc źródła ciepła", "varmekjele maks effekt", "puissance max brûleur", "kazan maksimum güç", "potenza massima bruciatore", "max. výkon horáka", "maximální výkon hořáku") MAKE_TRANSLATION(boilHystOn, "boilhyston", "hysteresis on temperature", "Einschaltdifferenz", "ketel aan hysterese verschil", "Hysteres aktiveringstemperatur", "histereza załączania", "hysterese på temperatur", "hysteresis température d'allumage", "gecikme sıcaklığı devrede", "isteresi sulla temperatura", "hysterézia teploty pri zapnutí", "hystereze teploty při zapnutí") MAKE_TRANSLATION(boilHystOff, "boilhystoff", "hysteresis off temperature", "Ausschaltdifferenz", "ketel uit hysterese verschil", "Hysteres inaktiveringstemperatur", "histereza wyłączania", "hysterese av temperatur", "hysteresis température d'extinction", "gecikme sıcaklığı kapalı", "isteresi fuori temperatura", "hysterézia teploty pri vypnutí", "hystereze teploty při vypnutí") -MAKE_TRANSLATION(boil2HystOn, "boil2hyston", "hysteresis stage 2 on temperature", "Einschaltdifferenz Stufe 2", "ketel aan hysterese verschil 2", "Hysteres aktiveringstemperatur 2", "histereza załączania stopnia 2", "", "hysteresis état 2 température d'allumage", "2. seviye gecikme sıcaklığı devrede", "stadio di isteresi 2 sulla temperatura", "2. stupeň hysterézie pri teplote", "hystereze teploty při zapnutí 2.stupeň") // TODO translate +MAKE_TRANSLATION(boil2HystOn, "boil2hyston", "hysteresis stage 2 on temperature", "Einschaltdifferenz Stufe 2", "ketel aan hysterese verschil 2", "Hysteres aktiveringstemperatur 2", "histereza załączania stopnia 2", "hysterese på temperatur 2", "hysteresis état 2 température d'allumage", "2. seviye gecikme sıcaklığı devrede", "stadio di isteresi 2 sulla temperatura", "2. stupeň hysterézie pri teplote", "hystereze teploty při zapnutí 2.stupeň") MAKE_TRANSLATION(boil2HystOff, "boil2hystoff", "hysteresis stage 2 off temperature", "Ausschaltdifferenz Stufe 2", "ketel uit hysterese verschil 2", "Hysteres inaktiveringstemperatur 2", "histereza wyłączania stopnia 2", "hysterese inaktiveringstemperatur 2", "hysteresis état 2 température d'extinction", "2. seviye gecikme sıcaklığı kapalı", "isteresi stadio 2 fuori temperatura", "teplota vypnutia hysterézneho stupňa 2", "hystereze teploty při vypnutí 2.stupeň") MAKE_TRANSLATION(setFlowTemp, "setflowtemp", "set flow temperature", "Sollwert Vorlauftemperatur", "Ingestelde aanvoertemperatuur", "Börvärde Flödestemperatur", "zadana temperatura zasilania", "innstilt turtemperatur", "température du flux définie", "akış sıcaklığını ayarla", "impostare temperatura di mandata", "nastavená teplota výstupu", "nastavená teplota výstupu") MAKE_TRANSLATION(setBurnPow, "setburnpow", "burner set power", "Sollwert Brennerleistung", "Ingesteld brandervermogen", "Värmepanna vald Effekt", "zadana moc palnika", "varmekjele valgt effekt", "puissance du brûleur définie", "kazan gücünü ayarla", "impostare potenza bruciatore", "nastavenie výkonu horáka", "nastavený výkon hořáku") @@ -417,18 +418,18 @@ MAKE_TRANSLATION(maintenanceType, "maintenance", "maintenance scheduled", "Wartu MAKE_TRANSLATION(maintenanceTime, "maintenancetime", "time to next maintenance", "Wartung in", "Onderhoud in", "Tid till nästa underhall", "czas do kolejnego przeglądu", "vedlikeholdstid", "durée avant la prochaine maintenance", "bakıma kalan süre", "tempo alla prossima manutenzione", "čas do ďalšej údržby", "čas do další údržby") MAKE_TRANSLATION(emergencyOps, "emergencyops", "emergency operation", "Notbetrieb", "Noodoperatie", "Nöddrift", "praca w trybie awaryjnym", "nøddrift", "opération d'urgence", "acil durum çalışması", "operazione di emergenza", "núdzová prevádzka", "nouzový provoz") MAKE_TRANSLATION(emergencyTemp, "emergencytemp", "emergency temperature", "Notfalltemperatur", "Noodtemperatuur", "Nöddrift temperatur", "temperatura w trybie awaryjnym", "nødtemperatur", "température d'urgence", "acil durum sıcaklığı", "temperatura di emergenza", "núdzová teplota", "nouzová teplota") -MAKE_TRANSLATION(pumpMode, "pumpmode", "boiler pump mode", "Kesselpumpenmodus", "Ketelpomp modus", "", "tryb pracy pompy kotła", "pumpemodus", "", "pompa modu", "modalità pompa caldaia", "režim kotlového čerpadla", "režim čerpadla kotle") // TODO translate -MAKE_TRANSLATION(pumpCharacter, "pumpcharacter", "boiler pump characteristic", "Charakteristik der Kesselpumpe", "karakteristiek ketelpomp", "pannpumpsegenskaper", "charakterystyka pompy kotłowej", "kjelepumpekarakteristikk", "caractéristique de la pompe de la chaudière", "gazan nasosy", "caratteristica della pompa della caldaia", "charakteristika kotlového čerpadla", "charakteristika čerpadla kotle") // TODO translate -MAKE_TRANSLATION(pumpOnTemp, "pumpontemp", "pump logic temperature", "Pumpenlogiktemperatur", "", "Pumplogiktemperatur", "", "", "", "", "", "teplota logiky čerpadla", "teplota logiky čerpadla") // TODO translate -MAKE_TRANSLATION(headertemp, "headertemp", "low loss header", "Hydr. Weiche", "open verdeler", "Fördelare", "sprzęgło hydrauliczne", "", "bouteille de déc. hydr.", "isı bloğu gidiş suyu sıc.", "comp. idr.", "nízkostratová hlavica", "hydraulický oddělovač") // TODO translate -MAKE_TRANSLATION(heatblock, "heatblock", "heating block", "Wärmezelle", "Aanvoertemp. warmtecel", "Värmeblock", "blok grzewczy", "", "départ corps de chauffe", "Hid.denge kabı sıcaklığı", "mandata scamb. pr.", "vykurovací blok", "blok topení") // TODO translate +MAKE_TRANSLATION(pumpMode, "pumpmode", "boiler pump mode", "Kesselpumpenmodus", "Ketelpomp modus", "Pannpumpsläge", "tryb pracy pompy kotła", "pumpemodus", "mode pompe chaudière", "kazan pompa modu", "modalità pompa caldaia", "režim kotlového čerpadla", "režim čerpadla kotle") +MAKE_TRANSLATION(pumpCharacter, "pumpcharacter", "boiler pump characteristic", "Charakteristik der Kesselpumpe", "karakteristiek ketelpomp", "pannpumpsegenskaper", "charakterystyka pompy kotłowej", "kjelepumpekarakteristikk", "caractéristique de la pompe de la chaudière", "kazan pompası karakteristiği", "caratteristica della pompa della caldaia", "charakteristika kotlového čerpadla", "charakteristika čerpadla kotle") +MAKE_TRANSLATION(pumpOnTemp, "pumpontemp", "pump logic temperature", "Pumpenlogiktemperatur", "pomplogica temperatuur", "Pumplogiktemperatur", "temperatura logiki pompy", "pumpelogikktemperatur", "température logique pompe", "pompa mantık sıcaklığı", "temperatura logica pompa", "teplota logiky čerpadla", "teplota logiky čerpadla") +MAKE_TRANSLATION(headertemp, "headertemp", "low loss header", "Hydr. Weiche", "open verdeler", "Fördelare", "sprzęgło hydrauliczne", "lav tap header", "bouteille de déc. hydr.", "isı bloğu gidiş suyu sıc.", "comp. idr.", "nízkostratová hlavica", "hydraulický oddělovač") +MAKE_TRANSLATION(heatblock, "heatblock", "heating block", "Wärmezelle", "Aanvoertemp. warmtecel", "Värmeblock", "blok grzewczy", "varmeblokk", "départ corps de chauffe", "Hid.denge kabı sıcaklığı", "mandata scamb. pr.", "vykurovací blok", "blok topení") -MAKE_TRANSLATION(curveOn, "curveon", "heatingcurve on", "Heizkurve an", "", "Värmekurva På", "", "", "", "", "", "vykurovacia krivka zapnutá", "topná křivka zapnutá") // TODO translate -MAKE_TRANSLATION(curveBase, "curvebase", "heatingcurve base", "Heizkurve Basis", "", "Värmekurva Bas", "", "", "", "", "", "základňa vykurovacej krivky", "základ topné křivky") // TODO translate -MAKE_TRANSLATION(curveEnd, "curveend", "heatingcurve end", "Heizkurve Ende", "", "Värmekurva Slut", "", "", "", "", "", "koniec vykurovacej krivky", "konec topné křivky") // TODO translate +MAKE_TRANSLATION(curveOn, "curveon", "heatingcurve on", "Heizkurve an", "stookkromme aan", "Värmekurva På", "krzywa grzewcza włączona", "varmekurve på", "courbe de chauffage activée", "ısıtma eğrisi açık", "curva di riscaldamento attiva", "vykurovacia krivka zapnutá", "topná křivka zapnutá") +MAKE_TRANSLATION(curveBase, "curvebase", "heatingcurve base", "Heizkurve Basis", "stookkromme basis", "Värmekurva Bas", "podstawa krzywej grzewczej", "varmekurve basis", "base de courbe de chauffage", "ısıtma eğrisi tabanı", "base curva di riscaldamento", "základňa vykurovacej krivky", "základ topné křivky") +MAKE_TRANSLATION(curveEnd, "curveend", "heatingcurve end", "Heizkurve Ende", "stookkromme einde", "Värmekurva Slut", "koniec krzywej grzewczej", "varmekurve slutt", "fin de courbe de chauffage", "ısıtma eğrisi sonu", "fine curva di riscaldamento", "koniec vykurovacej krivky", "konec topné křivky") // heatpump/compress specific -MAKE_TRANSLATION(upTimeTotal, "uptimetotal", "heatpump total uptime", "Gesamtbetriebszeit Wärmepumpe", "", "Total tid värmepump", "łączny czas pracy pompy ciepła", "", "", "", "", "celková doba prevádzky tepelného čerpadla", "celková doba provozu tepelného čerpadla") // TODO translate +MAKE_TRANSLATION(upTimeTotal, "uptimetotal", "heatpump total uptime", "Gesamtbetriebszeit Wärmepumpe", "totale bedrijfstijd warmtepomp", "Total tid värmepump", "łączny czas pracy pompy ciepła", "total driftstid varmepumpe", "temps de fonctionnement total pompe à chaleur", "toplam çalışma süresi ısı pompası", "tempo di funzionamento totale pompa di calore", "celková doba prevádzky tepelného čerpadla", "celková doba provozu tepelného čerpadla") MAKE_TRANSLATION(upTimeControl, "uptimecontrol", "total operating time heat", "Gesamtbetriebszeit Heizen", "Totale bedrijfstijd", "Total tid uppvärmning", "łączny czas generowania ciepła", "total driftstid", "durée totale de fonctionnement chauffage", "ısınma toplam işletme süresi", "Tempo di funzionamento totale riscaldamento", "celkový prevádzkový čas tepla", "celková provozní doba topení") MAKE_TRANSLATION(upTimeCompHeating, "uptimecompheating", "operating time compressor heating", "Betriebszeit Kompressor heizen", "Bedrijfstijd compressor verwarmingsbedrijf", "Total tid kompressor uppvärmning", "łączny czas ogrzewania (sprężarka)", "totaltid kompressor", "durée de fonctionnement compresseur chauffage", "ısı pompası ısınma işletme süresi", "tempo di funzionamento del compressore riscaldamento", "prevádzková doba vykurovania kompresora", "provozní doba kompresoru pro topení") MAKE_TRANSLATION(upTimeCompCooling, "uptimecompcooling", "operating time compressor cooling", "Betriebszeit Kompressor kühlen", "Bedrijfstijd compressor koelbedrijf", "Total tid kompressor kyla", "łączny czas chłodzenia (sprężarka)", "Total tid kompressor kjøling", "durée de fonctionnement compresseur refroidissement", "ısı pompası soğuma işletme süresi", "tempo di funzionamento del compressore raffreddamento", "doba prevádzky chladenia kompresora", "provozní doba kompresoru pro chlazení") @@ -455,7 +456,7 @@ MAKE_TRANSLATION(auxElecHeatNrgConsWw, "auxelecheatnrgcons", "aux elec. heater e MAKE_TRANSLATION(auxElecHeatNrgConsPool, "auxelecheatnrgconspool", "aux elec. heater energy consumption pool", "Energieverbrauch el. Zusatzheizung Pool", "Energieverbruik electrisch verwarmingselement voor zwembadbedrijf", "Energiförbrukning Eltillskott Pool", "energia pobrana przez grzałki na podgrzewanie basenu", "energiforbruk el. tilleggsvarme basseng", "consommation énergie electrique auxiliaire chauffage piscine", "ilave elektrikli ısıtıcı havuz toplam enerji tüketimi", "consumo di energia riscaldamento elettrico ausiliario piscina", "bazén spotreby energie pomocného elektrického ohrievača", "spotřeba energie pomocného el. ohřívače pro bazén") MAKE_TRANSLATION(hpCompOn, "hpcompon", "hp compressor", "WP Kompressor", "WP compressor", "VP Kompressor", "sprężarka pompy ciepła", "vp kompressor", "compresseur pompe à chaleur", "hp ısı pompası", "compressore pompa calore", "tč kompresor", "tč kompresor") -MAKE_TRANSLATION(coolingOn, "coolingon", "cooling on", "Kühlung an", "koelbedrijf", "Kyla", "chłodzenie włączone", "kjøling", "refroidissement", "soğutma", "", "chladenie", "chlazení zapnuto") // TODO translate +MAKE_TRANSLATION(coolingOn, "coolingon", "cooling on", "Kühlung an", "koelbedrijf", "Kyla", "chłodzenie włączone", "kjøling", "refroidissement", "soğutma", "", "chladenie", "chlazení zapnuto") // MAKE_TRANSLATION(hpHeatingOn, "hpheatingon", "hp heating", "WP Heizen", "WP verwarmingsbedrijf", "VP Uppvärmning", "pompa ciepła, ogrzewanie", "vp oppvarmning", "hp ısınıyor", "riscaldamento pompa calore", "vykurovanie hp", "topení hp") // MAKE_TRANSLATION(hpCoolingOn, "hpcoolingon", "hp cooling", "WP Kühlen", "WP koelbedrijf", "VP Kyla", "pompa ciepła, chłodzenie", "vp kjøling", "hp soğuyor", "raffreddamento pompa calore", "chladenie hp", "chlazení hp") // MAKE_TRANSLATION(hpWwOn, "hpdhwon", "hp", "WP", "WP", "VP Varmvatten", "pompa ciepła", "vp", "pompe à chaleur", "hp", "pompa calore", "hp", "hp") @@ -467,12 +468,12 @@ MAKE_TRANSLATION(hpBrineIn, "hpbrinein", "brine in/evaporator", "Sole in/Verdamp MAKE_TRANSLATION(hpBrineOut, "hpbrineout", "brine out/condenser", "Sole aus/Kondensator", "pekel uit/condensor", "Brine ut (kondensor)", "temperatura glikolu na wyjściu kolektora (TB1)", "Brine ut/kondensor", "sortie saumure/condenseur", "anahtar valfi", "salamoia nell uscita evaporatore", "výstup soľanky/kondenzátor", "solanka out/kondenzátor") MAKE_TRANSLATION(hpSwitchValve, "hpswitchvalve", "switch valve", "Schaltventil", "schakelklep", "Växelventil", "zawór przełączający", "skifteventil", "valve de commutation", "ısı pompası aktivitesi", "valvola commutazione pompa di calore", "prepínací ventil", "přepínací ventil") MAKE_TRANSLATION(hpActivity, "hpactivity", "compressor activity", "Kompressoraktivität", "Compressoractiviteit", "Kompressoraktivitet", "pompa ciepła, aktywność sprężarki", "kompressoraktivitet", "hp ısı pompası", "attività compressore", "činnosť kompresora", "činnost kompresoru") -MAKE_TRANSLATION(hpTargetSpd, "hptargetspd", "compressor target speed", "Kompressorsolldrehzahl", "", "", "", "", "", "", "", "kompresor cieľové otáčky", "cílová rychlost kompresoru") // TODO translate -MAKE_TRANSLATION(receiverValveVr0, "recvalve", "receiver valve VR0", "Eingangsventil VR0", "", "", "", "", "", "", "", "prijímač ventil VR0", "přijímací ventil VR0") // TODO translate -MAKE_TRANSLATION(expansionValveVr1, "expvalve", "expansion valve VR1", "Ausdehnungsventil VR1", "", "", "", "", "", "", "", "prijímač ventil VR1", "přijímací ventil VR1") // TODO translate +MAKE_TRANSLATION(hpTargetSpd, "hptargetspd", "compressor target speed", "Kompressorsolldrehzahl", "", "", "", "", "", "", "", "kompresor cieľové otáčky", "cílová rychlost kompresoru") +MAKE_TRANSLATION(receiverValveVr0, "recvalve", "receiver valve VR0", "Eingangsventil VR0", "", "", "", "", "", "", "", "prijímač ventil VR0", "přijímací ventil VR0") +MAKE_TRANSLATION(expansionValveVr1, "expvalve", "expansion valve VR1", "Ausdehnungsventil VR1", "", "", "", "", "", "", "", "prijímač ventil VR1", "přijímací ventil VR1") -MAKE_TRANSLATION(hpMaxPower, "hpmaxpower", "compressor max power", "max. Kompressorleistung", "", "Max. Kompressoreffekt", "maksymalna wydajność sprężarki", "", "", "", "", "max výkon kompresora", "maximální výkon kompresoru") // TODO translate -MAKE_TRANSLATION(pvMaxComp, "pvmaxcomp", "pv compressor max power", "PV max. Kompressorleistung", "", "PV Max. Kompressoreffekt", "maksymalna wydajność sprężarki", "", "", "", "", "pv max výkon kompresora", "maximální výkon PV kompresoru") // TODO translate +MAKE_TRANSLATION(hpMaxPower, "hpmaxpower", "compressor max power", "max. Kompressorleistung", "", "Max. Kompressoreffekt", "maksymalna wydajność sprężarki", "", "", "", "", "max výkon kompresora", "maximální výkon kompresoru") +MAKE_TRANSLATION(pvMaxComp, "pvmaxcomp", "pv compressor max power", "PV max. Kompressorleistung", "", "PV Max. Kompressoreffekt", "maksymalna wydajność sprężarki", "", "", "", "", "pv max výkon kompresora", "maximální výkon PV kompresoru") MAKE_TRANSLATION(hpPower, "hppower", "compressor power output", "Kompressorleistung", "Compressorvermogen", "Kompressoreffekt", "moc wyjściowa sprężarki", "kompressoreffekt", "puissance de sortie compresseur", "ısı pompası güç çıkışı", "potenza uscita compressore", "výkon kompresora", "výstupní výkon kompresoru") MAKE_TRANSLATION(hpTc0, "hptc0", "heat carrier return (TC0)", "Kältemittelrücklauf (TC0)", "Koudemiddel retour (TC0)", "Värmebärare Retur (TC0)", "temperatura nośnika ciepła na powrocie (TC0)", "kjølemiddel retur (TC0)", "retour caloporteur (TC0)", "sıcak su dönüşü (TC0)", "ritorno del refrigerante (TC0)", "návrat nosiča tepla (TC0)", "návrat teplonosné látky (TC0)") MAKE_TRANSLATION(hpTc1, "hptc1", "heat carrier forward (TC1)", "Kältemittelvorlauf (TC1)", "Koudemiddel aanvoer (TC1)", "Värmebärare Framledning (TC1)", "temperatura nośnika ciepła pierwotna (TC1)", "kjølemiddel tur (TC1)", "avance caloporteur (TC1)", "sıcak su çıkışı (TC1)", "flusso di refrigerante (TC1)", "nosič tepla vpred (TC1)", "předání teplonosné látky (TC1)") @@ -486,8 +487,8 @@ MAKE_TRANSLATION(hpTr7, "hptr7", "refrigerant temperature gas side (condenser in MAKE_TRANSLATION(hpTl2, "hptl2", "air inlet temperature (TL2)", "Außenlufteintrittstemperatur (TL2)", "Temperatuur luchtinlaat (TL2)", "Luftintagstemperatur (TL2)", "temperatura wlotu powietrza (TL2)", "luftinntakstemperatur (TL2)", "température entrée air (TL2)", "hava giriş sıcaklığı (TL2)", "temperatura ingresso aria (TL2)", "teplota prívodu vzduchu (TL2)", "teplota vzduchu na vstupu (TL2)") MAKE_TRANSLATION(hpPl1, "hppl1", "low pressure side temperature (PL1)", "Niederdrucktemperatur (PL1)", "Temperatuur lage drukzijde (PL1)", "Temperatur Lågtryckssidan (PL1)", "temperatura po stronie niskiego ciśnienia (PL1)", "temperatur lavtrykksiden (PL1)", "température côté basse pression (PL1)", "düşük basınç tarafı sıcaklığı (PL1)", "temperatura lato bassa pressione (PL1)", "teplota na strane nízkeho tlaku (PL1)", "teplota na nízkotlaké straně (PL1)") MAKE_TRANSLATION(hpPh1, "hpph1", "high pressure side temperature (PH1)", "Hochdrucktemperatur (PH1)", "Temperatuur hoge drukzijde (PH1)", "Temperatur Högtryckssidan (PH1)", "temperatura po stronie wysokiego ciśnienia (PH1)", "Temperatur Høytrykksiden (PH1)", "température côté bhauteasse pression (PH1)", "yüksek basınç tarafı sıcaklığı (PH1)", "temperatura lato alta pressione (PH1)", "teplota na strane vysokého tlaku (PH1)", "teplota na vysokotlaké straně (PH1)") -MAKE_TRANSLATION(hpTa4, "hpta4", "drain pan temp (TA4)", "Kondensatorwanne (TA4)", "Temperatuur condensorafvoerbak (TA4)", " (TA4)", "temperatura ociekacza (TA4)", "kondenstråg temperatur (TA4)", " (TA4)", "tahliye sıcaklığı (TA4)", "temperatura condensatore (TA4)", "teplota vypúšťacej misky (TA4)", "teplota odvodňovací vany (TA4)") // TODO translate -MAKE_TRANSLATION(hpTw1, "hptw1", "reservoir temp (TW1)", "DHW Reservoir (TW1)", "(TW1)", "Varmvattentank Temperatur (TW1)", "temperatura zbiornika (TW1)", "(TW1)", "(TW1)", "(TW1)", "(TW1)", "teplota zásobníka (TW1)", "teplota v nádrži (TW1)") // TODO translate +MAKE_TRANSLATION(hpTa4, "hpta4", "drain pan temp (TA4)", "Kondensatorwanne (TA4)", "Temperatuur condensorafvoerbak (TA4)", " (TA4)", "temperatura ociekacza (TA4)", "kondenstråg temperatur (TA4)", " (TA4)", "tahliye sıcaklığı (TA4)", "temperatura condensatore (TA4)", "teplota vypúšťacej misky (TA4)", "teplota odvodňovací vany (TA4)") +MAKE_TRANSLATION(hpTw1, "hptw1", "reservoir temp (TW1)", "DHW Reservoir (TW1)", "(TW1)", "Varmvattentank Temperatur (TW1)", "temperatura zbiornika (TW1)", "(TW1)", "(TW1)", "(TW1)", "(TW1)", "teplota zásobníka (TW1)", "teplota v nádrži (TW1)") MAKE_TRANSLATION(hpInput1, "hpin1", "input 1 state", "Status Eingang 1", "Status input 1", "Status Ingång 1", "stan wejścia 1", "status inggang 1", "état entrée 1", "giriş 1 durumu", "stato ingresso 1", "stav vstupu 1", "stav vstupu 1") MAKE_TRANSLATION(hpInput2, "hpin2", "input 2 state", "Status Eingang 2", "Status input 2", "Status Ingång 2", "stan wejścia 2", "status inggang 2", "état entrée 2", "giriş 2 durumu", "stato ingresso 2", "stav vstupu 2", "stav vstupu 2") @@ -508,60 +509,60 @@ MAKE_TRANSLATION(auxHeaterOnly, "auxheateronly", "aux heater only", "nur Zusatzh MAKE_TRANSLATION(auxHeaterDelay, "auxheaterdelay", "aux heater on delay", "Zusatzheizer verzögert ein", "Bijverw. vertraagd aan", "Eltillskottfördröjning på", "opóźnienie włączenia dogrzewacza", "Tilleggsvarmer forsinket på", "Chauff app tempo marche", "ilave ısıtıcı beklemede", "ritardo riscaldatori addizionali", "oneskorenie prídavného ohrievača", "zpoždění zapnutí pomocného topení") MAKE_TRANSLATION(silentMode, "silentmode", "silent mode", "Silentmodus", "Stiller gebruik", "Tyst drift", "tryb cichy", "stille modus", "Fct silencieux", "sessiz mod", "modalità silenziosa", "tichý režim", "tichý režim") MAKE_TRANSLATION(minTempSilent, "mintempsilent", "min outside temp for silent mode", "Minimale Außentemperatur Silentmodus", "Stiller gebruik min. buitentemp", "Tyst drift min temp", "minimalna temperatura zewnętrzna dla trybu cichego", "atille modus min temp", "Fct silencieux: Temp. extérieure min.", "sessiz mod için min. dış ortam sıcaklığı", "modalità silenziosa temperatura esterna minima", "min. vonkajšia teplota pre tichý režim", "minimální venkovní teplota pro tichý režim") -MAKE_TRANSLATION(tempParMode, "tempparmode", "outside temp parallel mode", "Heizstab Parallelbetrieb", "Buitentemp. parallelbedr", "Parallelläge Utomhustemp.", "maksymalna temperatura zewnętrzna dla dogrzewacza", "", "Temp. ext. fct parallèle", "paralel mod dış ortam sıcaklığı", "modalità parallela temperatura esterna", "paralelný režim mimo teploty", "venkovní teplota pro paralelní režim") // TODO translate +MAKE_TRANSLATION(tempParMode, "tempparmode", "outside temp parallel mode", "Heizstab Parallelbetrieb", "Buitentemp. parallelbedr", "Parallelläge Utomhustemp.", "maksymalna temperatura zewnętrzna dla dogrzewacza", "", "Temp. ext. fct parallèle", "paralel mod dış ortam sıcaklığı", "modalità parallela temperatura esterna", "paralelný režim mimo teploty", "venkovní teplota pro paralelní režim") MAKE_TRANSLATION(auxHeatMixValve, "auxheatmix", "aux heater mixing valve", "Mischventil Zusatzheizer", "Bijverwarming menger", "Eltillskott Blandarventil", "mieszacz dogrzewacza", "eltilskudd blandeventil", "Chauffage auxiliaire mélangeur", "ilave ısıtıcı karışım vanası", "miscela riscaldatori addizionali", "zmiešavací ventil pomocného ohrievača", "směšovací ventil pomocného topení") MAKE_TRANSLATION(hpHystHeat, "hphystheat", "on/off hyst heat", "Schalthysterese Heizen", "Aan/uit-hysteresis in verw. bedrijf", "Hysteres Uppvärmning", "histereza wł./wył. ogrzewania", "På/av hysterese Oppvar.", "Hystérésis Marche en mode chauffage", "ısıtma gecikmesi", "isteresi di commutazione riscaldamento", "zapnutie/vypnutie hyst ohrevu", "hystereze zapnutí/vypnutí pro topení") MAKE_TRANSLATION(hpHystCool, "hphystcool", "on/off hyst cool", "Schalthysterese Kühlen", "Aan/uit-hysteresis in koelbedrijf", "Hysteres Kyla", "histereza wł./wył. chłodzenia", "hystrese kjøling", "Hystérésis Marche en mode refroidissement", "soğutma gecikmesi", "isteresi di commutazione raffreddamento", "zapnutie/vypnutie hyst chladenia", "hystereze zapnutí/vypnutí pro chlazení") MAKE_TRANSLATION(hpHystPool, "hphystpool", "on/off hyst pool", "Schalthysterese Pool", "an/uit-hysteresis in zwembadbedri", "Hysteres Pool", "histereza wł./wył. podgrzewania basenu", "hystrese basseng", "Hystérésis Marche en mode piscine", "havuz gecikmesi", "isteresi di commutazione piscina", "zapnutie/vypnutie hyst bazénu", "hystereze zapnutí/vypnutí pro bazén") MAKE_TRANSLATION(tempDiffHeat, "tempdiffheat", "temp diff TC3/TC0 heat", "Temp.diff. TC3/TC0 Heizen", "Temp.vers. TC3/TC0 verw", "Temperaturskillnad TC3/TC0 Uppvärmning", "różnica temperatur TC3/TC0 w trakcie ogrzewania", "temp. diff. TC3/TC0 oppvarm", "Delta T TC3/TC0 Chauff", "TC3-TC0 ısıtma sıcaklık farkı", "Delta T riscaldamento TC3/TC0", "teplotný rozdiel TC3/TC0 tepla", "rozdíl teplot TC3/TC0 pro topení") MAKE_TRANSLATION(tempDiffCool, "tempdiffcool", "temp diff TC3/TC0 cool", "Temp.diff. TC3/TC0 Kühlen", "Temp.vers. TC3/TC0 koel.", "Temperaturskillnad TC3/TC0 Kyla", "różnica temperatur TC3/TC0 w trakcie chłodzenia", "temp. diff. TC3/TC0 kjøling", "Delta T TC3/TC0 Refroid.", "TC3-TC0 soğutma sıcaklık farkı", "Delta T raffreddamento TC3/TC0", "teplotný rozdiel TC3/TC0 chladenie", "rozdíl teplot TC3/TC0 pro chlazení") -MAKE_TRANSLATION(silentFrom, "silentfrom", "silent mode from", "Silentmodus Start", "Start stille modus", "Tyst drift starttid", "początek trybu cichego", "stillemodus starter", "", "sessiz mod başlangıcı", "avvio della modalità silenziosa", "tichý režim od", "tichý režim od") // TODO translate -MAKE_TRANSLATION(silentTo, "silentto", "silent mode to", "Silentmodus Ende", "Einde stille modus", "Tyst drift stopptid", "koniec trybu cichego", "komfortmodus av", "", "sessiz mod bitişi", "spegnere modalità silenziosa", "tichý režim do", "tichý režim do") // TODO translate +MAKE_TRANSLATION(silentFrom, "silentfrom", "silent mode from", "Silentmodus Start", "Start stille modus", "Tyst drift starttid", "początek trybu cichego", "stillemodus starter", "", "sessiz mod başlangıcı", "avvio della modalità silenziosa", "tichý režim od", "tichý režim od") +MAKE_TRANSLATION(silentTo, "silentto", "silent mode to", "Silentmodus Ende", "Einde stille modus", "Tyst drift stopptid", "koniec trybu cichego", "komfortmodus av", "", "sessiz mod bitişi", "spegnere modalità silenziosa", "tichý režim do", "tichý režim do") MAKE_TRANSLATION(wwComfOffTemp, "comfoff", "comfort switch off", "Komfort Ausschalttemp.", "Comfort Uitschakeltemp.", "Komfort frånkopplingstemperatur", "temperatura wyłączania w trybie komfort", "eco modus utkoblingstem", "Confort Temp. d'arrêt", "konfor kapalı", "spegnimento modalità comfort", "komfortné vypnutie", "komfortní vypnutí") MAKE_TRANSLATION(wwEcoOffTemp, "ecooff", "eco switch off", "ECO Ausschalttemp.", "Eco Uitschakeltemp.", "Eko frånkopplingstemperatur", "temperatura wyłączania w trybie eko", "Øko avstengningstemp.", "Eco Temp. d'arrêt", "eko kapalı", "spegnimento modalità ECO", "eko vypínač", "eko vypnutí") MAKE_TRANSLATION(wwEcoPlusOffTemp, "ecoplusoff", "eco+ switch off", "ECO+ Ausschalttemp.", "Eco+ Uitschakeltemp.", "Eko+ frånkopplingstemperatur", "temperatura wyłączania w trybie eko+", "Øko+ avstengningstemp.", "Eco+ Temp. d'arrêt", "eko+ kapalı", "spegnimento modalità ECO+", "eko+ vypnutie", "eko+ vypnutí") -MAKE_TRANSLATION(wwComfDiffTemp, "comfdiff", "comfort diff", "Komfort Differenztemp.", "", "Komfort temperaturskillnad", "", "", "", "", "", "Komfortný rozdiel teploty", "komfortní rozdíl") // TODO translate -MAKE_TRANSLATION(wwEcoDiffTemp, "ecodiff", "eco diff", "ECO Differenztemp.", "", "Eko temperaturskillnad", "", "", "", "", "", "ECO rozdiel teploty", "eko rozdíl") // TODO translate -MAKE_TRANSLATION(wwEcoPlusDiffTemp, "ecoplusdiff", "eco+ diff", "ECO+ Differenztemp.", "", "Eko+ temperaturskillnad", "", "", "", "", "", "ECO+ rozdiel teploty", "eko+ rozdíl") // TODO translate -MAKE_TRANSLATION(wwComfStopTemp, "comfstop", "comfort stop temp", "Komfort Stopptemp.", "", "Komfort stopptemperatur", "", "", "", "", "", "komfortná stop teplota", "komfortní teplota vypnutí") // TODO translate -MAKE_TRANSLATION(wwEcoStopTemp, "ecostop", "eco stop temp", "ECO Stopptemp.", "", "Eko stopptemperatur", "", "", "", "", "", "ECO stop teplota", "eko teplota vypnutí") // TODO translate -MAKE_TRANSLATION(wwEcoPlusStopTemp, "ecoplusstop", "eco+ stop temp", "ECO+ Stopptemp.", "", "Eko+ stopptemperatur", "", "", "", "", "", "ECO+ stop teplota", "eko+ teplota vypnutí") // TODO translate +MAKE_TRANSLATION(wwComfDiffTemp, "comfdiff", "comfort diff", "Komfort Differenztemp.", "", "Komfort temperaturskillnad", "", "", "", "", "", "Komfortný rozdiel teploty", "komfortní rozdíl") +MAKE_TRANSLATION(wwEcoDiffTemp, "ecodiff", "eco diff", "ECO Differenztemp.", "", "Eko temperaturskillnad", "", "", "", "", "", "ECO rozdiel teploty", "eko rozdíl") +MAKE_TRANSLATION(wwEcoPlusDiffTemp, "ecoplusdiff", "eco+ diff", "ECO+ Differenztemp.", "", "Eko+ temperaturskillnad", "", "", "", "", "", "ECO+ rozdiel teploty", "eko+ rozdíl") +MAKE_TRANSLATION(wwComfStopTemp, "comfstop", "comfort stop temp", "Komfort Stopptemp.", "", "Komfort stopptemperatur", "", "", "", "", "", "komfortná stop teplota", "komfortní teplota vypnutí") +MAKE_TRANSLATION(wwEcoStopTemp, "ecostop", "eco stop temp", "ECO Stopptemp.", "", "Eko stopptemperatur", "", "", "", "", "", "ECO stop teplota", "eko teplota vypnutí") +MAKE_TRANSLATION(wwEcoPlusStopTemp, "ecoplusstop", "eco+ stop temp", "ECO+ Stopptemp.", "", "Eko+ stopptemperatur", "", "", "", "", "", "ECO+ stop teplota", "eko+ teplota vypnutí") -MAKE_TRANSLATION(auxHeatMode, "auxheatrmode", "aux heater mode", "Zusatzheizungsmodus", "Modus bijverwarmer", "Eltillskott Läge", "tryb pracy dogrzewacza po blokadzie z Zakładu Energetycznego", "tilleggsvarmer modus", "", "ilave ısıtıcı modu", "modalità riscaldatore addizionale", "režim pomocného ohrievača", "režim pomocného topení") // TODO translate +MAKE_TRANSLATION(auxHeatMode, "auxheatrmode", "aux heater mode", "Zusatzheizungsmodus", "Modus bijverwarmer", "Eltillskott Läge", "tryb pracy dogrzewacza po blokadzie z Zakładu Energetycznego", "tilleggsvarmer modus", "", "ilave ısıtıcı modu", "modalità riscaldatore addizionale", "režim pomocného ohrievača", "režim pomocného topení") MAKE_TRANSLATION(auxMaxLimit, "auxmaxlimit", "aux heater max limit", "Zusatzheizer max. Grenze", "Bijverwarmer grensinstelling maximaal", "Eltillskott max begränsning", "dogrzewacz, maksymalny limit", "tillegsvarme maksgrense", "ilave ısıtıcı maks limit", "limite massimo riscaldatore addizionale", "maximálny limit pomocného ohrievača", "maximální limit pomocného topení") MAKE_TRANSLATION(auxLimitStart, "auxlimitstart", "aux heater limit start", "Zusatzheizer Grenze Start", "Bijverwarmer grens voor start", "Eltillskott begränsningsstart", "dogrzewacz, początek ograniczenia", "tillegsvarme startgrense", "ilave ısıtıcı limir başlangıcı", "avvio limite massimo riscaldatore addizionale", "spustenie limitu pomocného ohrievača", "startovací limit pomocného topení") -MAKE_TRANSLATION(auxHeaterSource, "auxheatersource", "aux heater source", "Quelle Zusatzheizer", "", "", "", "", "", "", "", "pomocný zdroj tepla", "pomocný zdroj tepla") // TODO translate -MAKE_TRANSLATION(manDefrost, "mandefrost", "manual defrost", "Manuelle Enteisung", "Handmatige ontdooicyclus", "Manuell avfrostning", "ręczne odladzanie", "manuell avisning", "", "manuel buz çözme", "sbrinamento manuale", "manuálne odmrazovanie", "ruční odmrazování") // TODO translate -MAKE_TRANSLATION(pvCooling, "pvcooling", "cooling only with PV", "Kühlen nur mit PV", "Koelen alleen met solar PV", "Kyla endast med solpanel", "chłodzenie tylko z PV", "kjøling med solpanel", "", "sadece PV ile soğutma", "solo raffrescamento con solare", "Chladenie len s FV", "chlazení pouze s FV") // TODO translate -MAKE_TRANSLATION(hpCircPumpWw, "hpcircpump", "circulation pump available during dhw", "Zirkulation möglich bei WW-Bereitung", "Circulatiepomp WP beschikbaar tijdens ww", "Värmebärarpump på vid varmvattenberedning", "pompa cyrkulacji dostępna w trakcie c.w.u.", "sirkulasjonspumpe tilgjengelig under varmtvann", "", "SKS esnasında sirkülasyon pompasu uygun", "pompa di circolazione disponibile durante ACS", "obehové čerpadlo k dispozícii počas TÚV", "oběhové čerpadlo dostupné během TUV") // TODO translate -MAKE_TRANSLATION(vp_cooling, "vpcooling", "valve/pump cooling", "Ventil/Pumpe für Kühlen", "Klep koeling", "Ventil/Pump kyla", "zawór/pompa chłodzenia", "varmepumpe kjøling", "", "vana/pompa soğuyor", "valvola/pompa raffrescamento", "chladenie ventilu/čerpadla", "ventil/čerpadlo chlazení") // TODO translate -MAKE_TRANSLATION(VC0valve, "vc0valve", "VC0 valve", "VC0 Ventil", "Klep VC0", "VC0 Ventil", "zawór VC0", "vc0 ventil", "", "VC0 vana", "valvola VC0", "VC0 ventil", "ventil VC0") // TODO translate -MAKE_TRANSLATION(primePump, "primepump", "primary heatpump", "Hauptpumpe", "Hoofdpomp", "Primär Pump", "główna pompa ciepła", "primærpumpe", "", "ana ısı pompası", "pompa principale riscaldamento", "primárne tepelné čerpadlo", "primární tepelný čerpadlo") // TODO translate -MAKE_TRANSLATION(primePumpMod, "primepumpmod", "primary heatpump modulation", "Modulation Hauptpumpe", "Modulatie hoofdpomp", "Modulation Primär Pump", "wysterowanie głównej pompy ciepła", "primærpumpelast", "", "ana ısı pompası modülasyon", "pompa principale modulazione riscaldamento", "primárna modulácia tepelného čerpadla", "modulace primárního tepelného čerpadla") // TODO translate -MAKE_TRANSLATION(hp3wayValve, "hp3way", "3-way valve", "3-Wege-Ventil", "3-weg klep", "3-vägsventil", "zawór 3-drogowy pompy ciepła", "3-veisventil", "", "3 yollu vana", "valvola 3-vie", "3-cestný ventil", "3-cestný ventil") // TODO translate -MAKE_TRANSLATION(hp4wayValve, "hp4way", "4-way valve (VR4)", "4-Wege-Ventil (VR4)", "4-weg klep (VR4)", "4-vägsventil (VR4)", "zawór 4-drogowy pompy ciepła (VR4)", "4-veisventil (VR4)", "(VR4)", "4 yollu vana (VR4)", "valvola 4-vie (VR4)", "4-cestný ventil (VR4)", "4-cestný ventil (VR4)") // TODO translate -MAKE_TRANSLATION(elHeatStep1, "elheatstep1", "el. heater step 1", "El. Heizer Stufe 1", "Electrische bijverwarmer niveau 1", "Eltillskott Steg 1", "dogrzewacz poziom 1", "el-kolbe steg 1", "", "el.ısıtıcı adım 1", "riscaldatore elettrico livello 1", "krok 1 elektrického ohrievača", "elektrický ohřívač stupeň 1") // TODO translate -MAKE_TRANSLATION(elHeatStep2, "elheatstep2", "el. heater step 2", "El. Heizer Stufe 2", "Electrische bijverwarmer niveau 2", "Eltillskott Steg 2", "dogrzewacz poziom 2", "el-kolbe steg 2", "", "el.ısıtıcı adım 2", "riscaldatore elettrico livello 2", "krok 2 elektrického ohrievača", "elektrický ohřívač stupeň 2") // TODO translate -MAKE_TRANSLATION(elHeatStep3, "elheatstep3", "el. heater step 3", "El. Heizer Stufe 3", "Electrische bijverwarmer niveau 3", "Eltillskott Steg 3", "dogrzewacz poziom 3", "el-kolbe steg 3", "", "el.ısıtıcı adım 3", "riscaldatore elettrico livello 3", "krok 3 elektrického ohrievača", "elektrický ohřívač stupeň 3") // TODO translate -MAKE_TRANSLATION(wwAlternatingOper, "alternatingop", "alternating operation", "Wechselbetrieb", "Wisselbedrijf ww", "Växeldrift", "praca naprzemienna", "alternativ drift", "", "sıcak kullanım suyu alternatif işletim", "funzionamento alternato", "striedavá prevádzka", "střídavý provoz") // TODO translate -MAKE_TRANSLATION(wwAltOpPrioHeat, "altopprioheat", "prioritise heating during dhw", "Heizen bevorzugt vor WW", "Proriteit verwarming boven ww", "Varmvattenprioritet", "czas na ogrzewanie w trakcie c.w.u", "prioritert oppvarmning", "", "sıcak kullanım suyu esnasında ısıtmayı öne al", "dare la priorità al riscaldamento durante l'ACS", "Uprednostniť ohrev počas TÚV", "prioritizace vytápění během TUV") // TODO translate -MAKE_TRANSLATION(wwAltOpPrioWw, "altopprio", "prioritise dhw during heating", "bevorzugt vor Heizen", "Prioriteit ww boven verwarming", "Värmeprioritet", "czas na c.w.u w trakcie ogrzewania", "prioritert varmtvann", "", "ısıtma esnasında sıcak kullanım suyunu öne al", "dare priorità all'acqua calda durante il riscaldamento", "uprednostniť TÚV počas ohrevu", "prioritizace TUV během vytápění") // TODO translate -MAKE_TRANSLATION(hpEA0, "hpea0", "condensate reservoir heating (EA0)", "Heizung Kondensatwanne (EA0)", "", "Värme kondenstråg (EA0)", "ogrzewanie zbiornika kondensatu (EA0)", "", "", "", "", "ohrievanie zásobníka kondenzátu (EA0)", "ohřev kondenzátní nádrže (EA0)") // TODO translate -MAKE_TRANSLATION(boost, "boost", "boost mode", "Boost", "", "Boost-läge", "tryb wzmocnienia (boost)", "", "", "", "", "boost režim", "režim boost") // TODO translate -MAKE_TRANSLATION(boosttime, "boosttime", "boost time", "Boost-Dauer", "", "Boost-tid", "czas trwania wzmocnienia", "", "", "", "", "čas trvania posilnenia", "čas trvání režimu boost") // TODO translate -MAKE_TRANSLATION(hpPumpMode, "hppumpmode", "primary heatpump mode", "primärer Wärmepumpenmodus", "", "Driftläge värmebärarpump", "tryb pracy głównej pompy ciepła", "", "", "", "", "režim primárneho tepelného čerpadla", "režim primárního tepelného čerpadla") // TODO translate -MAKE_TRANSLATION(instantstart, "instantstart", "instant start", "Sofortstart", "", "Gränsvärde direktstart värme", "natychmiastowy start", "", "", "", "", "okamžité spustenie", "okamžité spuštění") // TODO translate -MAKE_TRANSLATION(heatondelay, "heatondelay", "heat-on delay", "Einschaltverzögerung Heizen", "", "Inkopplingsfördröjning värme", "opóźnienie włączania ogrzewania", "", "", "", "", "Oneskorenie zapnutia kúreni", "zpoždění zapnutí topení") // TODO translate -MAKE_TRANSLATION(heatoffdelay, "heatoffdelay", "heat-off delay", "Ausschaltverzögerung Heizen", "", "Frånkopplingsfördröjning värme", "opóźnienie włączania ogrzewania", "", "", "", "", "Oneskorenie vypnutia kúrenia", "zpoždění vypnutí topení") // TODO translate -MAKE_TRANSLATION(hpSetDiffPress, "hpsetdiffpress", "set differential pressure", "Pumpensolldruck", "", "VP Tryckskillnad", "różnica ciśnień", "", "", "", "", "nastaviť diferenčný tlak", "nastavení rozdílového tlaku") // TODO translate -MAKE_TRANSLATION(hpFan, "fan", "fan", "Lüfter", "", "Fläkt", "wentylator", "", "", "", "", "ventilátor", "ventilátor") // TODO translate -MAKE_TRANSLATION(fanSpd, "fanspd", "fan speed", "Lüfter Geschw.", "", "Fläkt", "wentylator", "", "", "", "", "ventilátor", "ventilátor") // TODO translate -MAKE_TRANSLATION(hpShutdown, "shutdown", "shutdown", "Abschalten", "", "Stäng av", "wyłączenie", "", "", "", "", "vypnutie", "vypnutí") // TODO translate -MAKE_TRANSLATION(pc0Flow, "pc0flow", "Flow PC0", "Durchfluss PC0", "", "Flöde värmebärarpump", "", "", "", "", "", "prietok PC0", "průtok PC0") // TODO translate -MAKE_TRANSLATION(pc1Flow, "pc1flow", "Flow PC1", "Durchfluss PC1", "", "Flöde cirkulationspump", "", "", "", "", "", "prietok PC1", "průtok PC1") // TODO translate -MAKE_TRANSLATION(pc1On, "pc1on", "PC1", "PC1", "", "Cirkulationspump", "", "", "", "", "", "PC1", "PC1") // TODO translate -MAKE_TRANSLATION(pc1Rate, "pc1rate", "PC1 rate", "PC1 Rate", "", "Hastighet cirkulationspump", "", "", "", "", "", "sadzba PC1", "míra PC1") // TODO translate +MAKE_TRANSLATION(auxHeaterSource, "auxheatersource", "aux heater source", "Quelle Zusatzheizer", "", "", "", "", "", "", "", "pomocný zdroj tepla", "pomocný zdroj tepla") +MAKE_TRANSLATION(manDefrost, "mandefrost", "manual defrost", "Manuelle Enteisung", "Handmatige ontdooicyclus", "Manuell avfrostning", "ręczne odladzanie", "manuell avisning", "", "manuel buz çözme", "sbrinamento manuale", "manuálne odmrazovanie", "ruční odmrazování") +MAKE_TRANSLATION(pvCooling, "pvcooling", "cooling only with PV", "Kühlen nur mit PV", "Koelen alleen met solar PV", "Kyla endast med solpanel", "chłodzenie tylko z PV", "kjøling med solpanel", "", "sadece PV ile soğutma", "solo raffrescamento con solare", "Chladenie len s FV", "chlazení pouze s FV") +MAKE_TRANSLATION(hpCircPumpWw, "hpcircpump", "circulation pump available during dhw", "Zirkulation möglich bei WW-Bereitung", "Circulatiepomp WP beschikbaar tijdens ww", "Värmebärarpump på vid varmvattenberedning", "pompa cyrkulacji dostępna w trakcie c.w.u.", "sirkulasjonspumpe tilgjengelig under varmtvann", "", "SKS esnasında sirkülasyon pompasu uygun", "pompa di circolazione disponibile durante ACS", "obehové čerpadlo k dispozícii počas TÚV", "oběhové čerpadlo dostupné během TUV") +MAKE_TRANSLATION(vp_cooling, "vpcooling", "valve/pump cooling", "Ventil/Pumpe für Kühlen", "Klep koeling", "Ventil/Pump kyla", "zawór/pompa chłodzenia", "varmepumpe kjøling", "", "vana/pompa soğuyor", "valvola/pompa raffrescamento", "chladenie ventilu/čerpadla", "ventil/čerpadlo chlazení") +MAKE_TRANSLATION(VC0valve, "vc0valve", "VC0 valve", "VC0 Ventil", "Klep VC0", "VC0 Ventil", "zawór VC0", "vc0 ventil", "", "VC0 vana", "valvola VC0", "VC0 ventil", "ventil VC0") +MAKE_TRANSLATION(primePump, "primepump", "primary heatpump", "Hauptpumpe", "Hoofdpomp", "Primär Pump", "główna pompa ciepła", "primærpumpe", "", "ana ısı pompası", "pompa principale riscaldamento", "primárne tepelné čerpadlo", "primární tepelný čerpadlo") +MAKE_TRANSLATION(primePumpMod, "primepumpmod", "primary heatpump modulation", "Modulation Hauptpumpe", "Modulatie hoofdpomp", "Modulation Primär Pump", "wysterowanie głównej pompy ciepła", "primærpumpelast", "", "ana ısı pompası modülasyon", "pompa principale modulazione riscaldamento", "primárna modulácia tepelného čerpadla", "modulace primárního tepelného čerpadla") +MAKE_TRANSLATION(hp3wayValve, "hp3way", "3-way valve", "3-Wege-Ventil", "3-weg klep", "3-vägsventil", "zawór 3-drogowy pompy ciepła", "3-veisventil", "", "3 yollu vana", "valvola 3-vie", "3-cestný ventil", "3-cestný ventil") +MAKE_TRANSLATION(hp4wayValve, "hp4way", "4-way valve (VR4)", "4-Wege-Ventil (VR4)", "4-weg klep (VR4)", "4-vägsventil (VR4)", "zawór 4-drogowy pompy ciepła (VR4)", "4-veisventil (VR4)", "(VR4)", "4 yollu vana (VR4)", "valvola 4-vie (VR4)", "4-cestný ventil (VR4)", "4-cestný ventil (VR4)") +MAKE_TRANSLATION(elHeatStep1, "elheatstep1", "el. heater step 1", "El. Heizer Stufe 1", "Electrische bijverwarmer niveau 1", "Eltillskott Steg 1", "dogrzewacz poziom 1", "el-kolbe steg 1", "", "el.ısıtıcı adım 1", "riscaldatore elettrico livello 1", "krok 1 elektrického ohrievača", "elektrický ohřívač stupeň 1") +MAKE_TRANSLATION(elHeatStep2, "elheatstep2", "el. heater step 2", "El. Heizer Stufe 2", "Electrische bijverwarmer niveau 2", "Eltillskott Steg 2", "dogrzewacz poziom 2", "el-kolbe steg 2", "", "el.ısıtıcı adım 2", "riscaldatore elettrico livello 2", "krok 2 elektrického ohrievača", "elektrický ohřívač stupeň 2") +MAKE_TRANSLATION(elHeatStep3, "elheatstep3", "el. heater step 3", "El. Heizer Stufe 3", "Electrische bijverwarmer niveau 3", "Eltillskott Steg 3", "dogrzewacz poziom 3", "el-kolbe steg 3", "", "el.ısıtıcı adım 3", "riscaldatore elettrico livello 3", "krok 3 elektrického ohrievača", "elektrický ohřívač stupeň 3") +MAKE_TRANSLATION(wwAlternatingOper, "alternatingop", "alternating operation", "Wechselbetrieb", "Wisselbedrijf ww", "Växeldrift", "praca naprzemienna", "alternativ drift", "", "sıcak kullanım suyu alternatif işletim", "funzionamento alternato", "striedavá prevádzka", "střídavý provoz") +MAKE_TRANSLATION(wwAltOpPrioHeat, "altopprioheat", "prioritise heating during dhw", "Heizen bevorzugt vor WW", "Proriteit verwarming boven ww", "Varmvattenprioritet", "czas na ogrzewanie w trakcie c.w.u", "prioritert oppvarmning", "", "sıcak kullanım suyu esnasında ısıtmayı öne al", "dare la priorità al riscaldamento durante l'ACS", "Uprednostniť ohrev počas TÚV", "prioritizace vytápění během TUV") +MAKE_TRANSLATION(wwAltOpPrioWw, "altopprio", "prioritise dhw during heating", "bevorzugt vor Heizen", "Prioriteit ww boven verwarming", "Värmeprioritet", "czas na c.w.u w trakcie ogrzewania", "prioritert varmtvann", "", "ısıtma esnasında sıcak kullanım suyunu öne al", "dare priorità all'acqua calda durante il riscaldamento", "uprednostniť TÚV počas ohrevu", "prioritizace TUV během vytápění") +MAKE_TRANSLATION(hpEA0, "hpea0", "condensate reservoir heating (EA0)", "Heizung Kondensatwanne (EA0)", "", "Värme kondenstråg (EA0)", "ogrzewanie zbiornika kondensatu (EA0)", "", "", "", "", "ohrievanie zásobníka kondenzátu (EA0)", "ohřev kondenzátní nádrže (EA0)") +MAKE_TRANSLATION(boost, "boost", "boost mode", "Boost", "", "Boost-läge", "tryb wzmocnienia (boost)", "", "", "", "", "boost režim", "režim boost") +MAKE_TRANSLATION(boosttime, "boosttime", "boost time", "Boost-Dauer", "", "Boost-tid", "czas trwania wzmocnienia", "", "", "", "", "čas trvania posilnenia", "čas trvání režimu boost") +MAKE_TRANSLATION(hpPumpMode, "hppumpmode", "primary heatpump mode", "primärer Wärmepumpenmodus", "", "Driftläge värmebärarpump", "tryb pracy głównej pompy ciepła", "", "", "", "", "režim primárneho tepelného čerpadla", "režim primárního tepelného čerpadla") +MAKE_TRANSLATION(instantstart, "instantstart", "instant start", "Sofortstart", "", "Gränsvärde direktstart värme", "natychmiastowy start", "", "", "", "", "okamžité spustenie", "okamžité spuštění") +MAKE_TRANSLATION(heatondelay, "heatondelay", "heat-on delay", "Einschaltverzögerung Heizen", "", "Inkopplingsfördröjning värme", "opóźnienie włączania ogrzewania", "", "", "", "", "Oneskorenie zapnutia kúreni", "zpoždění zapnutí topení") +MAKE_TRANSLATION(heatoffdelay, "heatoffdelay", "heat-off delay", "Ausschaltverzögerung Heizen", "", "Frånkopplingsfördröjning värme", "opóźnienie włączania ogrzewania", "", "", "", "", "Oneskorenie vypnutia kúrenia", "zpoždění vypnutí topení") +MAKE_TRANSLATION(hpSetDiffPress, "hpsetdiffpress", "set differential pressure", "Pumpensolldruck", "", "VP Tryckskillnad", "różnica ciśnień", "", "", "", "", "nastaviť diferenčný tlak", "nastavení rozdílového tlaku") +MAKE_TRANSLATION(hpFan, "fan", "fan", "Lüfter", "", "Fläkt", "wentylator", "", "", "", "", "ventilátor", "ventilátor") +MAKE_TRANSLATION(fanSpd, "fanspd", "fan speed", "Lüfter Geschw.", "", "Fläkt", "wentylator", "", "", "", "", "ventilátor", "ventilátor") +MAKE_TRANSLATION(hpShutdown, "shutdown", "shutdown", "Abschalten", "", "Stäng av", "wyłączenie", "", "", "", "", "vypnutie", "vypnutí") +MAKE_TRANSLATION(pc0Flow, "pc0flow", "Flow PC0", "Durchfluss PC0", "", "Flöde värmebärarpump", "", "", "", "", "", "prietok PC0", "průtok PC0") +MAKE_TRANSLATION(pc1Flow, "pc1flow", "Flow PC1", "Durchfluss PC1", "", "Flöde cirkulationspump", "", "", "", "", "", "prietok PC1", "průtok PC1") +MAKE_TRANSLATION(pc1On, "pc1on", "PC1", "PC1", "", "Cirkulationspump", "", "", "", "", "", "PC1", "PC1") +MAKE_TRANSLATION(pc1Rate, "pc1rate", "PC1 rate", "PC1 Rate", "", "Hastighet cirkulationspump", "", "", "", "", "", "sadzba PC1", "míra PC1") // hybrid heatpump MAKE_TRANSLATION(hybridStrategy, "hybridstrategy", "hybrid control strategy", "Hybrid-Steuerungsstrategie", "Hybride strategie", "Hybrid kontrollstrategi", "strategia sterowania hybrydowego", "hybrid kontrollstrategi", "stratégie contrôle hybride", "hibrit kontrol stratejisi", "strategia comtrollo ibrido", "hybridná stratégia riadenia", "strategie hybridního řízení") @@ -599,11 +600,11 @@ MAKE_TRANSLATION(valveReturn, "valvereturn", "return valve", "Rückflussventil", MAKE_TRANSLATION(aPumpMod, "apumpmod", "alternative hs pump modulation", "Alternative WE-Pumpenmodulation", "Alternatieve warmtebron pomp modulatie", "Alternativ Pumpmodulering Värmekälla", "modulacja pompy alternatywnego źródła ciepła", "alternativ pumpemodulering varmekilde", "modulation alternative pompe hs", "alternatif ısı kaynağı pompa modülasyonu", "pompa modulazione alternativa hs", "alternatívna modulácia čerpadla hs", "alternativní modulace čerpadla hs") MAKE_TRANSLATION(heatSource, "heatsource", "alternative heating active", "Alternativer Wärmeerzeuger aktiv", "Alternatieve warmtebron aktief", "Alternativ Värmekälla aktiv", "aktywne alternatywne źródło ciepła", "alternativ varmekilde aktiv", "chauffage alternatif actif", "alternatif ısınma devrede", "riscaldamento alternativo attivo", "alternatívne kúrenie aktívne", "alternativní vytápění aktivní") MAKE_TRANSLATION(aPump, "apump", "alternative hs pump", "Alternative WE-Pumpe", "Alternatieve warmtebron pomp", "Alternativ Pump Värmekälla", "pompy alternatywnego źródła ciepła", "alternativ pumpe varmekilde", "alternative pompe hs", "alternatif ısı kaynağı pompası", "pompa alternativa hs", "alternatívne čerpadlo hs", "alternativní čerpadlo hs") -MAKE_TRANSLATION(burner, "burner", "burner", "Brenner", "Brander", "Brännare", "palnik", "", "", "kazan", "bruciatore", "horák", "hořák") // TODO translate -MAKE_TRANSLATION(heatRequest, "heatrequest", "heat request", "Wärmeanforderung", "Warmtevraag", "Värmebehov", "zapotrzebowanie na ciepło", "varmeforespørsel", "", "ısı talebi", "richiesta calore", "požiadavka na teplo", "požadavek na teplo") // TODO translate -MAKE_TRANSLATION(blockRemain, "blockremain", "remaining blocktime", "verbleibende Sperrzeit", "Resterende bloktijd", "Återstående blockeringstid", "czas do końca blokady", "gjenstående blokkeringstid", "", "kalan blok süresi", "tempo di blocco rimanente", "zostávajúci čas blokovania", "zbývající doba blokace") // TODO translate -MAKE_TRANSLATION(blockRemainWw, "blockremaindhw", "remaining blocktime dhw", "verbleibende Sperrzeit WW", "Resterende bloktijd ww", "Återstående blockeringstid varmvatten", "czas do końca blokady c.w.u.", "gjenværende blokkeringstid bereder", "", "kalan sıcak kullanım suyu blok süresi", "tempo di blocco rimanente ACS", "zostávajúci čas blokovania TÚV", "zbývající doba blokace TUV") // TODO translate -MAKE_TRANSLATION(flueGasTemp, "fluegastemp", "flue gas temperature", "Abgastemperatur", "Rookafvoertemperatuur", "Rökgastemperatur", "temperatura spalin", "røykgasstemperatur", "", "baca gazı sıcaklığı", "temperatura gas di scarico", "teplota spalín", "teplota spalin") // TODO translate +MAKE_TRANSLATION(burner, "burner", "burner", "Brenner", "Brander", "Brännare", "palnik", "", "", "kazan", "bruciatore", "horák", "hořák") +MAKE_TRANSLATION(heatRequest, "heatrequest", "heat request", "Wärmeanforderung", "Warmtevraag", "Värmebehov", "zapotrzebowanie na ciepło", "varmeforespørsel", "", "ısı talebi", "richiesta calore", "požiadavka na teplo", "požadavek na teplo") +MAKE_TRANSLATION(blockRemain, "blockremain", "remaining blocktime", "verbleibende Sperrzeit", "Resterende bloktijd", "Återstående blockeringstid", "czas do końca blokady", "gjenstående blokkeringstid", "", "kalan blok süresi", "tempo di blocco rimanente", "zostávajúci čas blokovania", "zbývající doba blokace") +MAKE_TRANSLATION(blockRemainWw, "blockremaindhw", "remaining blocktime dhw", "verbleibende Sperrzeit WW", "Resterende bloktijd ww", "Återstående blockeringstid varmvatten", "czas do końca blokady c.w.u.", "gjenværende blokkeringstid bereder", "", "kalan sıcak kullanım suyu blok süresi", "tempo di blocco rimanente ACS", "zostávajúci čas blokovania TÚV", "zbývající doba blokace TUV") +MAKE_TRANSLATION(flueGasTemp, "fluegastemp", "flue gas temperature", "Abgastemperatur", "Rookafvoertemperatuur", "Rökgastemperatur", "temperatura spalin", "røykgasstemperatur", "", "baca gazı sıcaklığı", "temperatura gas di scarico", "teplota spalín", "teplota spalin") MAKE_TRANSLATION(vr2Config, "vr2config", "vr2 configuration", "VR2 Konfiguration", "VR2 configuratie", "VR2 Konfiguration", "konfiguracja VR2", "vr2 konfigurasjon", "configuration vr2", "vr2 ayarı", "configurazione VR2", "konfigurácia vr2", "konfigurace VR2") MAKE_TRANSLATION(ahsActivated, "ahsactivated", "alternate heat source activation", "Alt. Wärmeerzeuger aktiviert", "Altenatieve warmtebron geactiveerd", "Alternativ värmekälla aktivering", "aktywacja alternatywnego źródła ciepła", "alternativ varmekilde aktivering", "activation source chaleur alternative", "alternatif ısı kaynağı devrede", "attivazione fonte di calore alternativa", "aktivácia alternatívneho zdroja tepla", "aktivace alternativního zdroje tepla") @@ -622,37 +623,37 @@ MAKE_TRANSLATION(blockHyst, "blockhyst", "hyst. for boiler block", "Hysterese Sp MAKE_TRANSLATION(releaseWait, "releasewait", "boiler release wait time", "Wartezeit Kesselfreigabe", "Wachttijd ketel vrijgave", "Väntetid Frisläppning", "czas oczekiwania na zwolnienie kotła", "kjele frigjøringsventetid", "temps attente libération chaudière", "kazan tahliyesi bekleme süresi", "tempo di attesa sblocco caldaia", "doba čakania na uvoľnenie kotla", "doba čekání na uvolnění kotle") // energy -MAKE_TRANSLATION(nrgTotal, "nrgtotal", "total energy", "Gesamtenergie", "", "Avgiven energi totalt", "całkowita energia", "", "", "", "", "celková energia", "celková energie") // TODO translate -MAKE_TRANSLATION(nrgHeat, "nrgheat", "energy heating", "Energie Heizen", "", "Avgiven energi värme", "energia na ogrzewanie", "", "", "ısıtma enerjisi", "energia vykurovania", "energetické vykurovanie", "energie pro vytápění") // TODO translate -MAKE_TRANSLATION(nrgCool, "nrgcool", "energy cooling", "Energie Kühlen", "", "Avgiven energi kyla", "", "", "", "", "", "energia chladenia", "energie pro chlazení") // TODO translate -MAKE_TRANSLATION(nrgWw, "nrg", "energy", "Energie", "", "Avgiven energi varmvatten", "energia", "", "", "sıcak kullanım suyu enerjisi", "", "energia", "energie") // TODO translate -MAKE_TRANSLATION(nrgHeat2, "nrgheat2", "energy heating 2", "Energie Heizen 2", "", "Avgiven energi värme 2", "energia na ogrzewanie 2", "", "", "ısıtma enerjisi 2", "", "energia vykurovania 2", "energie pro vytápění 2") // TODO translate -MAKE_TRANSLATION(nrgWw2, "nrg2", "energy 2", "Energie 2", "", "", "energia 2", "", "Avgiven energi varmvatten 2", "sıcak kullanım suyu enerjisi 2", "", "energia 2", "energie 2") // TODO translate -MAKE_TRANSLATION(nomPower, "nompower", "nominal Power", "Brennerleistung", "", "Nominell effekt", "moc nominalna", "", "", "nominal güç", "", "nominálny výkon", "nominální výkon") // TODO translate -MAKE_TRANSLATION(meterTotal, "metertotal", "meter total", "Gesamtmessung", "", "Förbrukad energi totalt", "licznik całkowity", "", "", "", "", "počítadlo celkom", "počítadlo celkem") // TODO translate -MAKE_TRANSLATION(meterComp, "metercomp", "meter compressor", "Messung Kompressor", "", "Förbrukad energi kompressor", "licznik sprężarki", "", "", "", "", "počítadlo kompresor", "počítadlo kompresoru") // TODO translate -MAKE_TRANSLATION(meterEHeat, "metereheat", "meter e-heater", "Messung E-Heizer", "", "Förbrukad energi eltillskott", "licznik dogrzewacza", "", "", "", "", "počítadlo e-ohrievača", "počítadlo elektrického topení") // TODO translate -MAKE_TRANSLATION(meterHeat, "meterheat", "meter heating", "Messung Heizen", "", "Förbrukad energi värme", "licznik ogrzewania", "", "", "", "", "počítadlo kúrenia", "počítadlo vytápění") // TODO translate -MAKE_TRANSLATION(meterCool, "metercool", "meter cooling", "Messung Kühlen", "", "Förbrukad energi kyla", "", "", "", "", "", "počítadlo chladenia", "počítadlo chlazení") // TODO translate -MAKE_TRANSLATION(meterWw, "meter", "meter", "Messung", "", "", "licznik", "", "Förbrukad energi varmvatten", "", "", "počítadlo", "počítadlo") // TODO translate -MAKE_TRANSLATION(gasMeterHeat, "gasmeterheat", "gas meter heating", "Gaszähler Heizen", "", "Gasförbrukning värme", "licznik gazu na ogrzewanie", "", "", "", "", "počítadlo plynu kúrenia", "počítadlo plynu pro vytápění") // TODO translate -MAKE_TRANSLATION(gasMeterWw, "gasmeter", "gas meter", "Gaszähler", "", "Gasförbrukning varmvatten", "licznik gazu", "", "", "", "", "počítadlo plynu", "počítadlo plynu") // TODO translate -MAKE_TRANSLATION(hpCurrPower, "hpcurrpower", "compressor current power", "akt. Kompressorleistung", "", "Kompressoreffekt", "", "", "", "", "", "aktuálny výkon kompresoru", "aktuální výkon kompresoru") // TODO translate -MAKE_TRANSLATION(hpPowerLimit, "hppowerlimit", "power limit", "Leistungsgrenze", "", "Begränsning kompressoreffekt", "", "", "", "", "", "obmedzenie výkonu", "omezení výkonu") // TODO translate -MAKE_TRANSLATION(powerReduction, "powerreduction", "power reduction", "Leistungsverringerung", "", "Reducerad kompressoreffekt", "", "", "", "", "", "obmedzenie výkonu", "omezení výkonu") // TODO translate -MAKE_TRANSLATION(fuelHeat, "fuelheat", "fuel consumption heating", "Verbrauch Heizen", "", "Bränsleförbrukning värme", "", "", "", "", "", "obmedzenie výkonu", "omezení výkonu") // TODO translate -MAKE_TRANSLATION(fuelDhw, "fueldhw", "fuel consumption", "Verbrauch", "", "Bränsleförbrukning varmvatten", "", "", "", "", "", "spotreba paliva", "spotřeba paliva") // TODO translate -MAKE_TRANSLATION(elHeat, "elheat", "el. consumption heating", "el. Verbrauch Heizen", "", "Elförbrukning värme", "", "", "", "", "", "el. spotreba kúrenie", "") // TODO translate -MAKE_TRANSLATION(elDhw, "eldhw", "el. consumption", "el. Verbrauch", "", "Elförbrukning varmvatten", "", "", "", "", "", "el. spotreba", "") // TODO translate -MAKE_TRANSLATION(elGenHeat, "elgenheat", "el. generation heating", "el. Erzeugung Heizen", "", "Elgenerering värme", "", "", "", "", "", "el. generovanie kúrenia", "") // TODO translate -MAKE_TRANSLATION(elGenDhw, "elgendhw", "el generation", "el. Erzeugung", "", "Elgenerering varmvatten", "", "", "", "", "", "el. generovanie", "") // TODO translate +MAKE_TRANSLATION(nrgTotal, "nrgtotal", "total energy", "Gesamtenergie", "", "Avgiven energi totalt", "całkowita energia", "", "", "", "", "celková energia", "celková energie") +MAKE_TRANSLATION(nrgHeat, "nrgheat", "energy heating", "Energie Heizen", "", "Avgiven energi värme", "energia na ogrzewanie", "", "", "ısıtma enerjisi", "energia vykurovania", "energetické vykurovanie", "energie pro vytápění") +MAKE_TRANSLATION(nrgCool, "nrgcool", "energy cooling", "Energie Kühlen", "", "Avgiven energi kyla", "", "", "", "", "", "energia chladenia", "energie pro chlazení") +MAKE_TRANSLATION(nrgWw, "nrg", "energy", "Energie", "", "Avgiven energi varmvatten", "energia", "", "", "sıcak kullanım suyu enerjisi", "", "energia", "energie") +MAKE_TRANSLATION(nrgHeat2, "nrgheat2", "energy heating 2", "Energie Heizen 2", "", "Avgiven energi värme 2", "energia na ogrzewanie 2", "", "", "ısıtma enerjisi 2", "", "energia vykurovania 2", "energie pro vytápění 2") +MAKE_TRANSLATION(nrgWw2, "nrg2", "energy 2", "Energie 2", "", "", "energia 2", "", "Avgiven energi varmvatten 2", "sıcak kullanım suyu enerjisi 2", "", "energia 2", "energie 2") +MAKE_TRANSLATION(nomPower, "nompower", "nominal Power", "Brennerleistung", "", "Nominell effekt", "moc nominalna", "", "", "nominal güç", "", "nominálny výkon", "nominální výkon") +MAKE_TRANSLATION(meterTotal, "metertotal", "meter total", "Gesamtmessung", "", "Förbrukad energi totalt", "licznik całkowity", "", "", "", "", "počítadlo celkom", "počítadlo celkem") +MAKE_TRANSLATION(meterComp, "metercomp", "meter compressor", "Messung Kompressor", "", "Förbrukad energi kompressor", "licznik sprężarki", "", "", "", "", "počítadlo kompresor", "počítadlo kompresoru") +MAKE_TRANSLATION(meterEHeat, "metereheat", "meter e-heater", "Messung E-Heizer", "", "Förbrukad energi eltillskott", "licznik dogrzewacza", "", "", "", "", "počítadlo e-ohrievača", "počítadlo elektrického topení") +MAKE_TRANSLATION(meterHeat, "meterheat", "meter heating", "Messung Heizen", "", "Förbrukad energi värme", "licznik ogrzewania", "", "", "", "", "počítadlo kúrenia", "počítadlo vytápění") +MAKE_TRANSLATION(meterCool, "metercool", "meter cooling", "Messung Kühlen", "", "Förbrukad energi kyla", "", "", "", "", "", "počítadlo chladenia", "počítadlo chlazení") +MAKE_TRANSLATION(meterWw, "meter", "meter", "Messung", "", "", "licznik", "", "Förbrukad energi varmvatten", "", "", "počítadlo", "počítadlo") +MAKE_TRANSLATION(gasMeterHeat, "gasmeterheat", "gas meter heating", "Gaszähler Heizen", "", "Gasförbrukning värme", "licznik gazu na ogrzewanie", "", "", "", "", "počítadlo plynu kúrenia", "počítadlo plynu pro vytápění") +MAKE_TRANSLATION(gasMeterWw, "gasmeter", "gas meter", "Gaszähler", "", "Gasförbrukning varmvatten", "licznik gazu", "", "", "", "", "počítadlo plynu", "počítadlo plynu") +MAKE_TRANSLATION(hpCurrPower, "hpcurrpower", "compressor current power", "akt. Kompressorleistung", "", "Kompressoreffekt", "", "", "", "", "", "aktuálny výkon kompresoru", "aktuální výkon kompresoru") +MAKE_TRANSLATION(hpPowerLimit, "hppowerlimit", "power limit", "Leistungsgrenze", "", "Begränsning kompressoreffekt", "", "", "", "", "", "obmedzenie výkonu", "omezení výkonu") +MAKE_TRANSLATION(powerReduction, "powerreduction", "power reduction", "Leistungsverringerung", "", "Reducerad kompressoreffekt", "", "", "", "", "", "obmedzenie výkonu", "omezení výkonu") +MAKE_TRANSLATION(fuelHeat, "fuelheat", "fuel consumption heating", "Verbrauch Heizen", "", "Bränsleförbrukning värme", "", "", "", "", "", "obmedzenie výkonu", "omezení výkonu") +MAKE_TRANSLATION(fuelDhw, "fueldhw", "fuel consumption", "Verbrauch", "", "Bränsleförbrukning varmvatten", "", "", "", "", "", "spotreba paliva", "spotřeba paliva") +MAKE_TRANSLATION(elHeat, "elheat", "el. consumption heating", "el. Verbrauch Heizen", "", "Elförbrukning värme", "", "", "", "", "", "el. spotreba kúrenie", "") +MAKE_TRANSLATION(elDhw, "eldhw", "el. consumption", "el. Verbrauch", "", "Elförbrukning varmvatten", "", "", "", "", "", "el. spotreba", "") +MAKE_TRANSLATION(elGenHeat, "elgenheat", "el. generation heating", "el. Erzeugung Heizen", "", "Elgenerering värme", "", "", "", "", "", "el. generovanie kúrenia", "") +MAKE_TRANSLATION(elGenDhw, "elgendhw", "el generation", "el. Erzeugung", "", "Elgenerering varmvatten", "", "", "", "", "", "el. generovanie", "") // HIU -MAKE_TRANSLATION(netFlowTemp, "netflowtemp", "heat network flow temp", "Systemvorlauftemperatur", "Netto aanvoertemperatuur", "Temperatur fjärrvärmenät", "temp. zasilania sieci cieplnej", "", "", "ısıtma şebekesi akış derecesi", "temperatura di mandata della rete di riscaldamento", "teplota prívodu tepelnej siete", "teplota přívodu tepelné sítě") // TODO translate -// MAKE_TRANSLATION(cwFlowRate, "cwflowrate", "cold water flow rate", "Kaltwasser Durchfluss", "Stroomsnelheid koud water", "Kallvattensflöde", "przepływ zimnej wody", "", "", "soğuk su akış hızı", "portata acqua fredda", "prietok studenej vody", "průtok studené vody") // TODO translate -MAKE_TRANSLATION(keepWarmTemp, "keepwarmtemp", "keep warm temperature", "Warmhaltetemperatur", "Warmhoudtemperatuur", "", "Varmhållningstemperatur", "temperatura podtrzymywania ciepła", "", "sıcaklığı koruma derecesi", "mantenere la temperatura calda", "udržať teplú teplotu", "udržovací teplota") // TODO translate -MAKE_TRANSLATION(heatValve, "heatvalve", "heating valve", "Heizungsventil", "", "Ventil uppvärmning", "zawór ogrzewania", "", "", "", "", "vykurovací ventil", "ventil pro vytápění") // TODO translate -MAKE_TRANSLATION(wwValve, "dhwvalve", "valve", "Ventil", "", "Ventil varmvatten", "zawór", "", "", "", "", "ventil", "ventil") // TODO translate +MAKE_TRANSLATION(netFlowTemp, "netflowtemp", "heat network flow temp", "Systemvorlauftemperatur", "Netto aanvoertemperatuur", "Temperatur fjärrvärmenät", "temp. zasilania sieci cieplnej", "", "", "ısıtma şebekesi akış derecesi", "temperatura di mandata della rete di riscaldamento", "teplota prívodu tepelnej siete", "teplota přívodu tepelné sítě") +// MAKE_TRANSLATION(cwFlowRate, "cwflowrate", "cold water flow rate", "Kaltwasser Durchfluss", "Stroomsnelheid koud water", "Kallvattensflöde", "przepływ zimnej wody", "", "", "soğuk su akış hızı", "portata acqua fredda", "prietok studenej vody", "průtok studené vody") +MAKE_TRANSLATION(keepWarmTemp, "keepwarmtemp", "keep warm temperature", "Warmhaltetemperatur", "Warmhoudtemperatuur", "", "Varmhållningstemperatur", "temperatura podtrzymywania ciepła", "", "sıcaklığı koruma derecesi", "mantenere la temperatura calda", "udržať teplú teplotu", "udržovací teplota") +MAKE_TRANSLATION(heatValve, "heatvalve", "heating valve", "Heizungsventil", "", "Ventil uppvärmning", "zawór ogrzewania", "", "", "", "", "vykurovací ventil", "ventil pro vytápění") +MAKE_TRANSLATION(wwValve, "dhwvalve", "valve", "Ventil", "", "Ventil varmvatten", "zawór", "", "", "", "", "ventil", "ventil") // the following are dhw for the boiler and automatically tagged with 'dhw' MAKE_TRANSLATION(wwSelTemp, "seltemp", "selected temperature", "gewählte Temperatur", "Geselecteerd temperatuur", "Vald Temperatur", "temperatura wyższa/komfort", "valgt temperatur", "température sélectionnée", "seçili sıcaklık", "temperatura selezionata", "zvolená teplota", "nastavená teplota") @@ -681,7 +682,7 @@ MAKE_TRANSLATION(wwStorageTemp2, "storagetemp2", "storage extern temperature", " MAKE_TRANSLATION(wwActivated, "activated", "activated", "aktiviert", "geactiveerd", "Aktiverad", "system przygotowywania c.w.u.", "aktivert", "activé", "devreye girdi", "attivato", "aktivovaný", "aktivováno") MAKE_TRANSLATION(wwDisinfecting, "disinfecting", "disinfecting", "Desinfizieren", "Desinfectie", "Desinficerar", "dezynfekcja termiczna", "desinfiserer", "désinfection", "dezenfekte ediliyor", "disinfezione", "dezinfekcia", "dezinfekce") MAKE_TRANSLATION(wwDisinfectionTemp, "disinfectiontemp", "disinfection temperature", "Desinfektionstemperatur", "Desinfectietemperatuur", "Desinfektionstemperatur", "temperatura dezynfekcji termicznej", "desinfeksjonstemperatur", "température désinfection", "dezenfeksiyon sıcaklığı", "temperatura disinfezione", "teplota dezinfekcie", "dezinfekční teplota") -MAKE_TRANSLATION(wwChargePump, "chargepump", "charge pump", "Ladepumpe", "", "", "", "", "", "", "", "nabíjacie čerpadlo", "nabíjecí čerpadlo") // TODO Translate +MAKE_TRANSLATION(wwChargePump, "chargepump", "charge pump", "Ladepumpe", "", "", "", "", "", "", "", "nabíjacie čerpadlo", "nabíjecí čerpadlo") MAKE_TRANSLATION(wwCharging, "charging", "charging", "Laden", "Laden", "Värmer", "grzanie", "varmer", "chargement", "dolduruluyor", "caricamento", "nabíjanie", "nabíjení") MAKE_TRANSLATION(wwChargeOptimization, "chargeoptimization", "charge optimization", "Ladungsoptimierung", "laadoptimalisatie", "Laddningsoptimering", "optymalizacja grzania", "oppvarmingsoptimalisering", "optimisation charge", "dolum optimizasyonu", "ottimizzazione carica", "optimalizácia poplatkov", "optimalizace nabíjení") MAKE_TRANSLATION(wwRecharging, "recharging", "recharging", "Nachladen", "herladen", "Laddar om", "ponowne grzanie", "varm på nytt", "en recharge", "tekrar dolduruluyor", "in ricarica", "nabíjanie", "dobíjení") @@ -690,7 +691,7 @@ MAKE_TRANSLATION(wwActive, "active", "active", "aktiv", "Actief", "Aktiv", "akty MAKE_TRANSLATION(ww3wayValve, "3wayvalve", "3-way valve active", "3-Wege-Ventil aktiv", "3-wegklep actief", "Trevägsventil aktiv", "zawór 3-drogowy aktywny", "aktiv trevisventil", "vanne 3 voies active", "3 yollu vana", "valvola 3-vie", "3-cestný ventil aktívny", "aktivní 3-cestný ventil") MAKE_TRANSLATION(wwMixerTemp, "mixertemp", "mixer temperature", "Mischertemperatur", "Mixertemperatuur", "Blandningsventil tempertur", "temperatura mieszacza", "temperatur blandeventil", "température mélangeur", "karıştırıcı sıcaklığı", "temperatura miscelatore", "teplota mixéra", "teplota směšovače") MAKE_TRANSLATION(wwStarts, "starts", "starts", "Anzahl Starts", "Aantal starts", "Antal starter", "liczba załączeń", "antall starter", "démarrages", "başlıyor", "avvii", "Počet štartov", "Počet startů") -MAKE_TRANSLATION(wwStartsHp, "startshp", "starts hp", "Anzahl Starts WP", "", "Antal starter VP", "", "", "", "", "", "Počet spustení TČ", "počet spuštění TČ") // TODO translate +MAKE_TRANSLATION(wwStartsHp, "startshp", "starts hp", "Anzahl Starts WP", "", "Antal starter VP", "", "", "", "", "", "Počet spustení TČ", "počet spuštění TČ") MAKE_TRANSLATION(wwWorkM, "workm", "active time", "aktive Zeit", "Actieve tijd", "Aktiv Tid", "czas aktywności", "driftstid", "temps actif", "aktif zaman", "tempo attivo", "aktívny čas", "aktivní čas") MAKE_TRANSLATION(wwHystOn, "hyston", "hysteresis on temperature", "Einschalttemperaturdifferenz", "Inschakeltemperatuurverschil", "Hysteres PÅ-temperatur", "histereza załączania", "innkoblingstemperaturforskjell", "hystérésis température allumage", "çalışma sıcaklığı farkı", "differenza di temperatura di accensione", "hysterézia teploty", "hystereze zapnutí") MAKE_TRANSLATION(wwHystOff, "hystoff", "hysteresis off temperature", "Ausschalttemperaturdifferenz", "Uitschakeltemperatuurverschil", "Hysteres AV-temperatur", "histereza wyłączania", "utkoblingstemperaturforskjell", "hystérésis température extinction", "kapatma sıcaklığı farkı", "differenza di temperatura di spegnimento", "teplota hysterézie", "hystereze vypnutí") @@ -711,9 +712,9 @@ MAKE_TRANSLATION(ibaLanguage, "language", "language", "Sprache", "Taal", "Sprak" MAKE_TRANSLATION(ibaClockOffset, "clockoffset", "clock offset", "Uhrkorrektur", "Klokcorrectie", "Tidskorrigering", "korekta zegara", "tidskorrigering", "offset horloge", "saat farkı", "correzione orario", "korekcia času", "posun hodin") MAKE_TRANSLATION(ibaBuildingType, "building", "building type", "Gebäudetyp", "Type gebouw", "Byggnadstyp", "typ budynku", "bygningstype", "type bâtiment", "bina tipi", "tipo di edificio", "typ budovy", "typ budovy") MAKE_TRANSLATION(heatingPID, "heatingpid", "heating PID", "Heizungs-PID", "PID verwarming", "Uppvärmning PID", "PID ogrzewania", "oppvarmings PID", "PID chauffage", "PID ısınıyor", "PID-riscaldamento", "PID kúrenia", "PID regulace vytápění") -MAKE_TRANSLATION(pumpopt, "pumpopt", "pump optimization", "Pumpenoptimierung") // ToDo translate -MAKE_TRANSLATION(inttime, "inttime", "integral time", "Integralzeit") // ToDo translate -MAKE_TRANSLATION(inttimefloor, "inttimefloor", "integral time floor", "Integralzeit Fußbodenheizung") // ToDo translate +MAKE_TRANSLATION(pumpopt, "pumpopt", "pump optimization", "Pumpenoptimierung") +MAKE_TRANSLATION(inttime, "inttime", "integral time", "Integralzeit") +MAKE_TRANSLATION(inttimefloor, "inttimefloor", "integral time floor", "Integralzeit Fußbodenheizung") MAKE_TRANSLATION(ibaCalIntTemperature, "intoffset", "internal temperature offset", "Korrektur interner Temperatur", "Offset interne temperatuur", "Korrigering interntemperatur", "korekta temperatury w pomieszczeniu", "Korrigering interntemperatur", "offset température interne", "iç sıcaklık artışı", "scostamento della temperatura interna", "odchýlka vnútornej teploty", "kompenzace vnitřní teploty") MAKE_TRANSLATION(ibaMinExtTemperature, "minexttemp", "minimal external temperature", "Min. Außentemperatur", "Min. buitentemperatuur", "Min Extern Temperatur", "minimalna miejscowa temperatura zewnętrzna", "minimal eksterntemperatur", "température extérieure minimale", "en düşük sış sıcaklık", "temperatura esterna minima", "minimálna vonkajšia teplota", "minimální venkovní teplota") MAKE_TRANSLATION(backlight, "backlight", "key backlight", "Tastenbeleuchtung", "Toetsverlichting", "Bakgrundsbelysning", "podświetlenie klawiatury", "bakgrunnsbelysning", "rétroéclairage touches", "tuş takımı aydınlatması", "retroilluminazione dei tasti", "podsvietenie kláves", "podsvícení kláves") @@ -728,10 +729,10 @@ MAKE_TRANSLATION(autodst, "autodst", "automatic change daylight saving time", "A MAKE_TRANSLATION(preheating, "preheating", "preheating in the clock program", "Vorheizen im Zeitprogramm", "Voorverwarming in het klokprogramma", "Förvärmning i tidsprogram", "podgrzewanie w programie czasowym", "forvarming i tidsprogram", "préchauffage dans programme horloge", "saat programında ön ısıtma", "preriscaldamento nel programma orologio", "predohrev v programe hodín", "předehřev v programovaném režimu") MAKE_TRANSLATION(offtemp, "offtemp", "temperature when mode is off", "Temperatur bei AUS", "Temperatuur bij UIT", "Temperatur Avslagen", "temperatura w trybie \"wył.\"", "temperatur avslått", "température lorsque mode désactivé", "mod kapalı iken sıcaklık", "temperatura quando la modalità è disattivata", "teplota, keď je režim vypnutý", "teplota při vypnutém režimu") MAKE_TRANSLATION(mixingvalves, "mixingvalves", "mixing valves", "Mischventile", "Mengkleppen", "Blandningsventiler", "zawory mieszające", "blandeventiler", "vannes mélange", "karışım vanaları", "valvole miscela", "zmiešavacie ventily", "směšovací ventily") -MAKE_TRANSLATION(pvEnableWw, "pvenabledhw", "enable raise dhw", "aktiviere WW-Anhebung", "Verhoging WW activeren", "Höj varmvatten med solpanel", "podwyższenie c.w.u. z PV", "aktivere hevet temperatur bereder", "", "sıcak kullanım suyu yükseltmeyi etkinleştir", "abilitare aumento ACS", "povoliť zvýšenie TÚV", "povolit zvýšení TUV") // TODO translate -MAKE_TRANSLATION(pvRaiseHeat, "pvraiseheat", "raise heating with PV", "Anhebung Heizen mit PV", "Verwarmen met PV activeren", "Höj värmen med solpanel", "podwyższenie grzania z PV", "heve varmen med solpanel", "", "ısıtmayı G.E. İle yükselt", "Aumentare il riscaldamento con il solare", "zvýšiť kúrenie s FV", "zvýšení vytápění s FV") // TODO translate -MAKE_TRANSLATION(pvLowerCool, "pvlowercool", "lower cooling with PV", "Absenkung Kühlen mit PV", "Verlagen koeling met PV activeren", "Sänk kylning med solpanel", "obniżenie chłodzenia z PV", "nedre kjøling solpanel", "", "soğutmayı G.E. İle düşür", "Riduzione del raffreddamento con il solare", "nižšie chladenie s PV", "snížení chlazení s FV") // TODO translate -MAKE_TRANSLATION(hasSolar, "solar", "solar", "Solar", "", "Solpaneler", "", "", "", "", "", "solár", "solár") // TODO translate +MAKE_TRANSLATION(pvEnableWw, "pvenabledhw", "enable raise dhw", "aktiviere WW-Anhebung", "Verhoging WW activeren", "Höj varmvatten med solpanel", "podwyższenie c.w.u. z PV", "aktivere hevet temperatur bereder", "", "sıcak kullanım suyu yükseltmeyi etkinleştir", "abilitare aumento ACS", "povoliť zvýšenie TÚV", "povolit zvýšení TUV") +MAKE_TRANSLATION(pvRaiseHeat, "pvraiseheat", "raise heating with PV", "Anhebung Heizen mit PV", "Verwarmen met PV activeren", "Höj värmen med solpanel", "podwyższenie grzania z PV", "heve varmen med solpanel", "", "ısıtmayı G.E. İle yükselt", "Aumentare il riscaldamento con il solare", "zvýšiť kúrenie s FV", "zvýšení vytápění s FV") +MAKE_TRANSLATION(pvLowerCool, "pvlowercool", "lower cooling with PV", "Absenkung Kühlen mit PV", "Verlagen koeling met PV activeren", "Sänk kylning med solpanel", "obniżenie chłodzenia z PV", "nedre kjøling solpanel", "", "soğutmayı G.E. İle düşür", "Riduzione del raffreddamento con il solare", "nižšie chladenie s PV", "snížení chlazení s FV") +MAKE_TRANSLATION(hasSolar, "solar", "solar", "Solar", "", "Solpaneler", "", "", "", "", "", "solár", "solár") // thermostat dhw MAKE_TRANSLATION(wwMode, "mode", "operating mode", "Betriebsart", "Modus", "Läge", "tryb pracy", "modus", "mode", "mod", "modalità", "režim", "provozní režim") @@ -798,12 +799,12 @@ MAKE_TRANSLATION(vacreducetemp, "vacreducetemp", "vacations off/reduce switch te MAKE_TRANSLATION(vacreducemode, "vacreducemode", "vacations reduce mode", "Urlaub Absenkmodus", "Vakantie afschakelmodus", "Helg reduceringsläge", "redukcja w trakcie urlopu", "ferieavstengningsmodus", "mode réduction vacances", "tail düşürme modu", "modalita riduzione vacanze", "režim zníženia dovoleniek", "redukční režim během dovolené") MAKE_TRANSLATION(nofrostmode, "nofrostmode", "nofrost mode", "Frostschutzmodus", "Vorstbeveiligingsmodus", "Frostskyddsläge", "temperatura wiodąca dla ochrony przed zamarzaniem", "frostbeskyttelsesmodus", "mode protection gel", "donma koruması modu", "Modalità protezione antigelo", "nofrost režim", "režim proti zamrznutí") MAKE_TRANSLATION(remotetemp, "remotetemp", "room temperature from remote", "Raumtemperatur Remote", "Ruimtetemperatuur van afstandsbediening", "Rumstemperatur från fjärr", "temperatura w pomieszczeniu (z termostatu)", "romstemperatur fra fjernbetjening", "température pièce depuis télécommande", "uzaktan oda sıcaklığı", "temperatura ambiente da remoto", "izbová teplota z diaľkového ovládania", "teplota místnosti z dálkového ovladače") -MAKE_TRANSLATION(remotehum, "remotehum", "room humidity from remote", "Raumfeuchte Remote", "", "Rumsluftfuktighet från fjärr", "wilgotność w pomieszczeniu (z termostatu)", "", "", "uzaktan kumandadan oda nemi", "", "Vlhkosť v miestnosti z diaľkového ovládania", "vlhkost místnosti z dálkového ovladače") // TODO translate +MAKE_TRANSLATION(remotehum, "remotehum", "room humidity from remote", "Raumfeuchte Remote", "", "Rumsluftfuktighet från fjärr", "wilgotność w pomieszczeniu (z termostatu)", "", "", "uzaktan kumandadan oda nemi", "", "Vlhkosť v miestnosti z diaľkového ovládania", "vlhkost místnosti z dálkového ovladače") MAKE_TRANSLATION(wwHolidays, "holidays", "holiday dates", "Feiertage", "Feestdagen", "Helgdagar", "dni świąteczne", "feriedager varmtvann", "dates vacances", "tatil günleri", "feste pubbliche", "sviatočné termíny", "data pro dovolenou") MAKE_TRANSLATION(wwVacations, "vacations", "vacation dates", "Urlaubstage", "Vakantiedagen", "Semesterdatum Varmvatten", "dni urlopowe", "ferie dato varmtvann", "dates vacances", "izin günleri", "date vacanze", "termíny dovolenky", "data pro prázdniny") MAKE_TRANSLATION(holidays, "holidays", "holiday dates", "Feiertage", "Feestdagen", "Helgdatum", "święta", "helligdager", "dates vacances", "tatil günleri", "date feste pubbliche", "sviatočné termíny", "data pro dovolenou") MAKE_TRANSLATION(vacations, "vacations", "vacation dates", "Urlaubstage", "Vakantiedagen", "Semesterdatum", "urlop", "feriedager", "dates vacances", "izin günleri", "date vacanze", "termíny dovolenky", "data pro prázdniny") -MAKE_TRANSLATION(vacationmode, "vacationmode", "vacation mode", "Urlaubsmodus", "", "", "", "", "", "", "", "dovolenkový režim", "režim dovolené") // ToDo Translate +MAKE_TRANSLATION(vacationmode, "vacationmode", "vacation mode", "Urlaubsmodus", "", "", "", "", "", "", "", "dovolenkový režim", "režim dovolené") MAKE_TRANSLATION(wwprio, "dhwprio", "dhw priority", "WW-Vorrang", "Prioriteit warm water", "Prioritera Varmvatten", "priorytet dla c.w.u.", "prioroter varmtvann", "priorité ecs", "sıcak kullanım suyu önceliği", "priorita acqua calda", "Priorita TÚV", "přednost ohřevu TUV") MAKE_TRANSLATION(nofrostmode1, "nofrostmode1", "nofrost mode", "Frostschutz", "Vorstbeveiligingsmodus", "Frostskyddsläge", "ochrona przed zamarzaniem", "frostbeskyttelse", "mode protection gel", "donma koruması modu 1", "modalita protezione antigelo", "nofrost režim", "režim proti zamrznutí") MAKE_TRANSLATION(reducehours, "reducehours", "duration for nighttemp", "Dauer Nachttemp.", "Duur nachtverlaging", "Timmar Nattsänkning", "czas trwania trybu nocnego", "timer nattsenkning", "durée température nuit", "gece sıcaklığı süresi", "durata temperatura notturna", "trvanie nočnej teploty", "délka trvání noční teploty") @@ -817,25 +818,25 @@ MAKE_TRANSLATION(vacations5, "vacations5", "vacation dates 5", "Urlaubstage 5", MAKE_TRANSLATION(vacations6, "vacations6", "vacation dates 6", "Urlaubstage 6", "Vakantiedagen 6", "Semesterdatum 6", "urlop 6", "feriedager 6", "dates vacances 6", "izin günleri 6", "date vacanze 6", "termíny dovolenky 6", "data prázdnin 6") MAKE_TRANSLATION(vacations7, "vacations7", "vacation dates 7", "Urlaubstage 7", "Vakantiedagen 7", "Semesterdatum 7", "urlop 7", "feriedager 7", "dates vacances 7", "izin günleri 7", "date vacanze 7", "termíny dovolenky 7", "data prázdnin 7") MAKE_TRANSLATION(vacations8, "vacations8", "vacation dates 8", "Urlaubstage 8", "Vakantiedagen 8", "Semesterdatum 8", "urlop 8", "feriedager 8", "dates vacances 8", "izin günleri 8", "date vacanze 8", "termíny dovolenky 8", "data prázdnin 8") -MAKE_TRANSLATION(absent, "absent", "absent", "Abwesend", "", "Frånvarande", "", "", "", "", "", "chýbajúci", "chybějící") // TODO translate -MAKE_TRANSLATION(redthreshold, "redthreshold", "reduction threshold", "Absenkschwelle", "", "Tröskel för sänkning", "", "", "", "", "", "zníženie tresholdu", "práh snížení") // TODO translate -MAKE_TRANSLATION(solarinfl, "solarinfl", "solar influence", "Solareinfluß", "", "", "", "", "", "", "", "slnečný vplyv", "sluneční vliv") // TODO translate -MAKE_TRANSLATION(currsolarinfl, "currsolarinfl", "curent solar influence", "akt. Solareinfluß", "", "", "", "", "", "", "", "aktuálny slnečný vplyv", "aktuální sluneční vliv") // TODO translate +MAKE_TRANSLATION(absent, "absent", "absent", "Abwesend", "", "Frånvarande", "", "", "", "", "", "chýbajúci", "chybějící") +MAKE_TRANSLATION(redthreshold, "redthreshold", "reduction threshold", "Absenkschwelle", "", "Tröskel för sänkning", "", "", "", "", "", "zníženie tresholdu", "práh snížení") +MAKE_TRANSLATION(solarinfl, "solarinfl", "solar influence", "Solareinfluß", "", "", "", "", "", "", "", "slnečný vplyv", "sluneční vliv") +MAKE_TRANSLATION(currsolarinfl, "currsolarinfl", "curent solar influence", "akt. Solareinfluß", "", "", "", "", "", "", "", "aktuálny slnečný vplyv", "aktuální sluneční vliv") -MAKE_TRANSLATION(hpmode, "hpmode", "HP Mode", "WP-Modus", "Modus warmtepomp", "Värmepumpsläge", "tryb pracy pompy ciepła", "", "", "yüksek güç modu", "Modalità Termopompa", "Režim TČ", "režim tepelného čerpadla") // TODO translate -MAKE_TRANSLATION(dewoffset, "dewoffset", "dew point offset", "Taupunktdifferenz", "Offset dauwpunt", "Daggpunktsförskjutning", "przesunięcie punktu rosy", "", "", "çiğ noktası göreli", "differenza del punto di rugiada", "posun rosného bodu", "offset rosného bodu") // TODO translate -MAKE_TRANSLATION(roomtempdiff, "roomtempdiff", "room temp difference", "Raumtemperaturdifferenz", "Verschiltemperatuur kamertemp", "Rumstemperaturskillnad", "różnica temp. pomieszczenia", "", "", "oda sıcaklığı farkı", "differenza temperatura ambiente", "rozdiel izbovej teploty", "rozdíl teploty místnosti") // TODO translate -MAKE_TRANSLATION(hpminflowtemp, "hpminflowtemp", "HP min. flow temp.", "WP minimale Vorlauftemperatur", "Minimale aanvoertemperatuur WP", "VP min flödestemperatur", "pompa ciepła, min. temperatura przepływu", "", "yüksek güç minimum akış sıcaklığı", "temperatura minima di mandata", "VT min. teplota prietoku.", "minimální teplota přívodu tepelného čerpadla") // TODO translate +MAKE_TRANSLATION(hpmode, "hpmode", "HP Mode", "WP-Modus", "Modus warmtepomp", "Värmepumpsläge", "tryb pracy pompy ciepła", "", "", "yüksek güç modu", "Modalità Termopompa", "Režim TČ", "režim tepelného čerpadla") +MAKE_TRANSLATION(dewoffset, "dewoffset", "dew point offset", "Taupunktdifferenz", "Offset dauwpunt", "Daggpunktsförskjutning", "przesunięcie punktu rosy", "", "", "çiğ noktası göreli", "differenza del punto di rugiada", "posun rosného bodu", "offset rosného bodu") +MAKE_TRANSLATION(roomtempdiff, "roomtempdiff", "room temp difference", "Raumtemperaturdifferenz", "Verschiltemperatuur kamertemp", "Rumstemperaturskillnad", "różnica temp. pomieszczenia", "", "", "oda sıcaklığı farkı", "differenza temperatura ambiente", "rozdiel izbovej teploty", "rozdíl teploty místnosti") +MAKE_TRANSLATION(hpminflowtemp, "hpminflowtemp", "HP min. flow temp.", "WP minimale Vorlauftemperatur", "Minimale aanvoertemperatuur WP", "VP min flödestemperatur", "pompa ciepła, min. temperatura przepływu", "", "yüksek güç minimum akış sıcaklığı", "temperatura minima di mandata", "VT min. teplota prietoku.", "minimální teplota přívodu tepelného čerpadla") MAKE_TRANSLATION(hpcooling, "hpcooling", "hp cooling", "WP Kühlen", "WP koelbedrijf", "VP Kyla", "pompa ciepła, chłodzenie", "vp kjøling", "hp soğuyor", "raffreddamento pompa calore", "chladenie TČ", "chlazení tepelného čerpadla") -MAKE_TRANSLATION(coolstart, "coolstart", "cooling starttemp", "Kühlbetrieb ab", "", "Kyla starttemperatur", "", "", "", "", "", "teplota spustenia chladenia", "teplota spuštění chlazení") // TODO translate -MAKE_TRANSLATION(coolondelay, "coolondelay", "cooling on delay", "Einschaltverzögerung Kühlen", "", "Inkopplingsfördröjning Kyla", "", "", "", "", "", "oneskorenie zapnutie chladenia", "zpoždění zapnutí chlazení") // TODO translate -MAKE_TRANSLATION(cooloffdelay, "cooloffdelay", "cooling off delay", "Ausschaltverzögerung Kühlen", "", "Frånkopplingsfördröjning Kyla", "", "", "", "", "", "oneskorenie vypnutie chladenia", "zpoždění vypnutí chlazení") // TODO translate -MAKE_TRANSLATION(switchProgMode, "switchprogmode", "switch program mode", "Schaltprogrammmodus", "", "Byt programläge", "", "", "", "", "", "prepnúť režim programu", "přepínací režim programu") // TODO translate +MAKE_TRANSLATION(coolstart, "coolstart", "cooling starttemp", "Kühlbetrieb ab", "", "Kyla starttemperatur", "", "", "", "", "", "teplota spustenia chladenia", "teplota spuštění chlazení") +MAKE_TRANSLATION(coolondelay, "coolondelay", "cooling on delay", "Einschaltverzögerung Kühlen", "", "Inkopplingsfördröjning Kyla", "", "", "", "", "", "oneskorenie zapnutie chladenia", "zpoždění zapnutí chlazení") +MAKE_TRANSLATION(cooloffdelay, "cooloffdelay", "cooling off delay", "Ausschaltverzögerung Kühlen", "", "Frånkopplingsfördröjning Kyla", "", "", "", "", "", "oneskorenie vypnutie chladenia", "zpoždění vypnutí chlazení") +MAKE_TRANSLATION(switchProgMode, "switchprogmode", "switch program mode", "Schaltprogrammmodus", "", "Byt programläge", "", "", "", "", "", "prepnúť režim programu", "přepínací režim programu") // heatpump and RC100H MAKE_TRANSLATION(airHumidity, "airhumidity", "relative air humidity", "relative Luftfeuchte", "Relatieve luchtvochtigheid", "Relativ Luftfuktighet", "wilgotność względna w pomieszczeniu", "luftfuktighet", "humidité relative air", "havadaki bağıl nem", "umidità relativa aria", "relatívna vlhkosť vzduchu", "relativní vlhkost vzduchu") MAKE_TRANSLATION(dewTemperature, "dewtemperature", "dew point temperature", "Taupunkttemperatur", "Dauwpunttemperatuur", "Daggpunkt", "punkt rosy w pomieszczeniu", "duggtemperatur", "température point rosée", "çiğ noktası sıcaklığı", "temperatura del punto di rugiada", "teplota rosného bodu", "teplota rosného bodu") -MAKE_TRANSLATION(battery, "battery", "battery", "Batterie", "", "Batteri", "bateria", "", "", "", "", "batéria", "baterie") // TODO translate +MAKE_TRANSLATION(battery, "battery", "battery", "Batterie", "", "Batteri", "bateria", "", "", "", "", "batéria", "baterie") // mixer MAKE_TRANSLATION(flowSetTemp, "flowsettemp", "setpoint flow temperature", "Sollwert Vorlauftemperatur", "Streefwaarde aanvoertemperatuur", "Vald flödestemperatur", "zadana temperatura zasilania", "valgt turtemperatur", "consigne température flux", "akış sıcaklığı ayarı", "Setpoint temperatura di mandata", "požadovaná hodnota výstupnej teploty", "cílová teplota vstupní vody") @@ -844,7 +845,7 @@ MAKE_TRANSLATION(pumpStatus, "pumpstatus", "pump status (PC1)", "Pumpenstatus HK MAKE_TRANSLATION(mixerStatus, "valvestatus", "mixing valve actuator (VC1)", "Mischerventilposition (VC1)", "positie mixerklep (VC1)", "Shuntventil Status (VC1)", "siłownik zaworu mieszającego (VC1)", "shuntventil status (VC1)", "actionnement vanne mélangeur (VC1)", "karışım vanası aktüatörü (VC1)", "posizione valvola miscela (VC1)", "pohon zmiešavacieho ventilu (VC1)", "pohon směšovacího ventilu (VC1)") MAKE_TRANSLATION(flowTempVf, "flowtempvf", "flow temperature in header (T0/Vf)", "Vorlauftemperatur am Verteiler (T0/Vf)", "aanvoertemperatuur verdeler (T0/Vf)", "Flödestemperatur Fördelare (T0/Vf)", "temperatura zasilania na rozdzielaczu (T0/Vf)", "turtemperatur ved fordeleren (T0/Vf)", "température départ collecteur (T0/Vf)", "başlıkta akış sıcaklığı", "Temperatura di mandata al distributore (T0/Vf)", "teplota prívodu v zberači (T0/Vf)", "teplota přívodu v hlavici (T0/Vf)") MAKE_TRANSLATION(mixerSetTime, "valvesettime", "time to set valve", "Zeit zum einstellen des Ventils", "Inschakeltijd mengklep", "Inställningstid Shuntventil", "czas na ustawienie zaworu", "instillningstid ventil", "délai activation vanne", "vana ayar zamanı", "ritardo attivazione valvola", "čas na nastavenie ventilu", "čas pro nastavení ventilu") -MAKE_TRANSLATION(setDiffPress, "setdiffpress", "set differential pressure", "Pumpensolldruck", "", "Tryckskillnad", "różnica ciśnień", "", "", "", "", "nastaviť diferenčný tlak", "nastavení rozdílového tlaku") // TODO translate +MAKE_TRANSLATION(setDiffPress, "setdiffpress", "set differential pressure", "Pumpensolldruck", "", "Tryckskillnad", "różnica ciśnień", "", "", "", "", "nastaviť diferenčný tlak", "nastavení rozdílového tlaku") // mixer pool MAKE_TRANSLATION(poolSetTemp, "poolsettemp", "pool set temperature", "Sollwert Pooltemperatur", "Streeftemperatuur zwembad", "Pool Temperatur Börvärde", "zadana temperatura basenu", "valgt temp basseng", "température consigne piscine", "hedef havuz sıcaklığı", "temperatura nominale piscina", "nastavená teplota bazéna", "cílová teplota bazénu") @@ -892,33 +893,33 @@ MAKE_TRANSLATION(m1WorkTime, "m1worktime", "differential control working time", MAKE_TRANSLATION(energyLastHour, "energylasthour", "energy last hour", "Energie letzte Std", "Energie laatste uur", "Energi Senaste Timmen", "energia w ciągu ostatniej godziny", "energi siste time", "énergie dernière heure", "son saat enerji", "Eenergia ultima ora", "energia za poslednú hodinu", "energie za poslední hodinu") MAKE_TRANSLATION(energyTotal, "energytotal", "total energy", "Gesamtenergie", "Totale energie", "Total Energi", "energia całkowita", "total energi", "énergie totale", "toplam enerji", "energia totale", "celková energia", "celková energie") MAKE_TRANSLATION(energyToday, "energytoday", "total energy today", "Energie heute", "Energie vandaag", "Total Energi Idag", "energia całkowita dzisiaj", "total energi i dag", "énergie totale aujourd'hui", "bugün toplam enerji", "totale energia giornaliera", "celková energia dnes", "celková energie dnes") -MAKE_TRANSLATION(cyl3BottomTemp, "cyl3bottomtemp", "third cylinder bottom temperature (TS11)", "Speichertemperatur unten (TS11)", "", "Tredje Cylindertemperatur Botten (TS11)", "", "", "", "", "", "spodná teplota tretieho valca (TS11)", "") // TODO translate -MAKE_TRANSLATION(cylTopTemp, "cyltoptemp", "cylinder top temperature (TS10)", "Speichertemperatur oben (TS10)", "", "Cylindertemperatur Toppen (TS10)", "", "", "", "", "", "horná teplota valca (TS10)", "") // TODO translate -MAKE_TRANSLATION(transferPumpMod, "transferpumpmod", "transfer pump modulation", "Transferpumpenmodulation", "", "Överföringspumpmodulering", "", "", "", "", "", "modulácia prenosového čerpadla", "") // TODO translate -MAKE_TRANSLATION(transferPump, "transferpump", "transfer pump", "Transferpumpe", "", "Överföringspump", "", "", "", "", "", "prenosové čerpadlo", "oběhové čerpadlo") // TODO translate +MAKE_TRANSLATION(cyl3BottomTemp, "cyl3bottomtemp", "third cylinder bottom temperature (TS11)", "Speichertemperatur unten (TS11)", "", "Tredje Cylindertemperatur Botten (TS11)", "", "", "", "", "", "spodná teplota tretieho valca (TS11)", "") +MAKE_TRANSLATION(cylTopTemp, "cyltoptemp", "cylinder top temperature (TS10)", "Speichertemperatur oben (TS10)", "", "Cylindertemperatur Toppen (TS10)", "", "", "", "", "", "horná teplota valca (TS10)", "") +MAKE_TRANSLATION(transferPumpMod, "transferpumpmod", "transfer pump modulation", "Transferpumpenmodulation", "", "Överföringspumpmodulering", "", "", "", "", "", "modulácia prenosového čerpadla", "") +MAKE_TRANSLATION(transferPump, "transferpump", "transfer pump", "Transferpumpe", "", "Överföringspump", "", "", "", "", "", "prenosové čerpadlo", "oběhové čerpadlo") MAKE_TRANSLATION(heatAssistOn, "heatassiston", "heat assistance on", "Einschaltdiff. Rücklaufanh.") MAKE_TRANSLATION(heatAssistOff, "heatassistoff", "heat assistance off", "Ausschaltdiff. Rücklaufanh.") // solar dhw -MAKE_TRANSLATION(wwColdTemp, "coldtemp", "cold water", "Kaltwasser", "", "kallvatten", "zimna woda", "", "", "", "", "studená voda", "studená voda") // TODO translate +MAKE_TRANSLATION(wwColdTemp, "coldtemp", "cold water", "Kaltwasser", "", "kallvatten", "zimna woda", "", "", "", "", "studená voda", "studená voda") MAKE_TRANSLATION(wwTemp5, "temp5", "temperature 5", "Temperatur 5", "Temperatuur 5", "Temperatur 5", "temperatura 5", "Temperatur 5", "température 5", "sıcaklık 5", "Temperatura 5", "teplota 5", "teplota 5") MAKE_TRANSLATION(wwTemp6, "temp6", "temperature 6", "Temperatur 6", "Temperatuur 6", "Temperatur 6", "temperatura 6", "temperatur 6", "température 6", "sıcaklık 6", "Temperatura 6", "teplota 6", "teplota 6") // MAKE_TRANSLATION(wwTemp7, "temp7", "temperature 7", "Temperatur 7", "Temperatuur 7", "Temperatur 7", "temperatura 7", "Temperatur 7", "température 7", "sıcaklık 7", "Temperatura 7", "teplota 7", "teplota 7") MAKE_TRANSLATION(wwPump, "pump", "pump", "Pumpe", "Pomp", "Pump", "pompa", "pumpe", "pompe", "pompa", "Pompa", "čerpadlo", "čerpadlo") -MAKE_TRANSLATION(wwCircTc, "circtc", "circulation time controled", "zeitgesteuerte Zirkulation", "", "Tidsstyrd cirkulation", "", "", "", "", "", "riadená doba cirkulácie", "řízený čas cirkulace") // TODO translate -MAKE_TRANSLATION(errorDisp, "errordisp", "error display", "Fehleranzeige", "", "Feldisplay", "wyświetlanie błędów", "", "", "", "", "zobrazenie chyby", "zobrazení chyb") // TODO translate -MAKE_TRANSLATION(deltaTRet, "deltatret", "temp. diff. return valve", "Temperaturdifferenz Rücklaufventil", "", "Temperaturskillnad returventil", "różnica temp. zaworu powrotnego", "", "", "", "", "rozdiel teplôt spätného ventilu", "rozdíl teploty zpátečního ventilu") // TODO translate +MAKE_TRANSLATION(wwCircTc, "circtc", "circulation time controled", "zeitgesteuerte Zirkulation", "", "Tidsstyrd cirkulation", "", "", "", "", "", "riadená doba cirkulácie", "řízený čas cirkulace") +MAKE_TRANSLATION(errorDisp, "errordisp", "error display", "Fehleranzeige", "", "Feldisplay", "wyświetlanie błędów", "", "", "", "", "zobrazenie chyby", "zobrazení chyb") +MAKE_TRANSLATION(deltaTRet, "deltatret", "temp. diff. return valve", "Temperaturdifferenz Rücklaufventil", "", "Temperaturskillnad returventil", "różnica temp. zaworu powrotnego", "", "", "", "", "rozdiel teplôt spätného ventilu", "rozdíl teploty zpátečního ventilu") // solar dhw and mixer dhw MAKE_TRANSLATION(wwMinTemp, "mintemp", "minimum temperature", "minimale Temperatur", "Minimale temperatuur", "Min. Temperatur", "temperatura minimalna", "min. temperatur", "température min.", "minimum sıcaklık", "temperatura minima", "minimálna teplota", "minimální teplota") MAKE_TRANSLATION(wwRedTemp, "redtemp", "reduced temperature", "reduzierte Temperatur", "Gereduceerde temperatuur", "Reducerad Temperatur", "temperatura zredukowana", "reducert temperatur", "température réduite", "düşürülmüş sıcaklık", "temperatura ridotta", "znížená teplota", "snížená teplota") MAKE_TRANSLATION(wwDailyTemp, "dailytemp", "daily temperature", "tägl. Temperatur", "Dagelijkse temperatuur", "Daglig temperatur", "temperatura dzienna", "dagtemperatur", "température en journée", "günlük sıcaklık", "temperatura giornaliera", "denná teplota", "denní teplota") -MAKE_TRANSLATION(wwHotTemp, "hottemp", "extra hot temperature", "sehr heiße Temperatur", "", "Mycket varm temperatur", "", "", "", "", "", "extra vysoká teplota", "teplota extra horká") // TODO translate +MAKE_TRANSLATION(wwHotTemp, "hottemp", "extra hot temperature", "sehr heiße Temperatur", "", "Mycket varm temperatur", "", "", "", "", "", "extra vysoká teplota", "teplota extra horká") MAKE_TRANSLATION(wwKeepWarm, "keepwarm", "keep warm", "Warmhalten", "Warm houde", "Varmhållning", "utrzymywanie ciepła", "holde varmen", "maintenir chaleur", "ılık tut", "mantenimento calore", "udržovať v teple", "udržení tepla") MAKE_TRANSLATION(wwStatus2, "status2", "status 2", "Status 2", "Status 2", "Status 2", "status 2", "status 2", "statut 2", "durum 2", "Status 2", "stav 2", "stav 2") MAKE_TRANSLATION(wwPumpMod, "pumpmod", "pump modulation", "Pumpenmodulation", "Pompmodulatie", "Pumpmodulering", "modulacja pompy", "pumpemodulering", "modulation de pompe", "pompa modülasyonu", "modulazione pompa", "modulácia čerpadla", "modulace čerpadla") MAKE_TRANSLATION(wwFlow, "flow", "flow rate", "Volumenstrom", "Doorstroomsnelheid", "Flöde", "przepływ", "strømningshastighet", "débit", "akış hızı", "portata flusso", "prietok", "průtok") -// MAKE_TRANSLATION(wwRetValve, "retvalve", "return valve", "Rücklauf Ventil", "", "Returventil", "", "", "", "", "", "spätný ventil", "zpětný ventil") // TODO translate +// MAKE_TRANSLATION(wwRetValve, "retvalve", "return valve", "Rücklauf Ventil", "", "Returventil", "", "", "", "", "", "spätný ventil", "zpětný ventil") // extra mixer dhw MAKE_TRANSLATION(wwRequiredTemp, "requiredtemp", "required temperature", "benötigte Temperatur", "Benodigde temperatuur", "Nödvändig Temperatur", "temperatura wymagana", "nødvendig temperatur", "température requise", "gerekli sıcaklık", "temperatura richiesta", "požadovaná teplota", "požadovaná teplota") @@ -972,37 +973,37 @@ MAKE_TRANSLATION(childlock, "childlock", "child lock", "Kindersicherung") MAKE_TRANSLATION(icon, "icon", "icon", "Icon") // ventilation -MAKE_TRANSLATION(outFresh, "outfresh", "outdoor fresh air", "Außenlufttemp.", "temperatuur buitenlucht", "Utelufttemperatur", "świeże powietrze z zewnątrz", "", "", "dış ortam taze hava", "aria fresca esterna", "čerstvý vzduch vonku", "venkovní čerstvý vzduch") // TODO translate -MAKE_TRANSLATION(inFresh, "infresh", "indoor fresh air", "Zulufttemp.", "temperatuur aanvoer", "Tillufttemperatur", "nawiew", "", "", "iç ortam taze hava", "aria fresca interna", "čerstvý vzduch v interiéri", "vnitřní čerstvý vzduch") // TODO translate -MAKE_TRANSLATION(outEx, "outexhaust", "outdoor exhaust air", "Fortlufttemp.", "uitlaatemperatuur buiten", "Utgående lufttemperatur", "zużyte powietrze z wewnątrz", "", "", "dış ortam egsoz", "aria di scarico esterna", "vonkajší odpadový vzduch", "venkovní odpadní vzduch") // TODO translate -MAKE_TRANSLATION(inEx, "inexhaust", "indoor exhaust air", "Ablufttemp.", "uitlaattemperatuur binnen", "Frånlufttemperatur", "wywiew", "", "", "iç ortam egsoz", "aria di scarico interna", "vnútorný odpadový vzduch", "vnitřní odpadní vzduch") // TODO translate -MAKE_TRANSLATION(ventMode, "ventmode", "ventilation mode", "Belüftungsmodus", "ventilatiemodus", "ventilationsläge", "tryb wentylacji", "", "", "havalandırma modu", "modalità di ventilazione", "režim vetrania", "režim ventilace") // TODO translate -MAKE_TRANSLATION(ventInSpeed, "ventinspeed", "in blower speed", "Zuluftdrehzahl", "toerental aanvoerventilator", "Tilluftflöde", "prędkość wentylatora nawiewu", "", "", "iç fan hızı", "velocità aria di alimentazione", "rýchlosť ventilátora", "rychlost vnitřního ventilátoru") // TODO translate -MAKE_TRANSLATION(ventOutSpeed, "ventoutspeed", "out blower speed", "Abluftdrehzahl", "toerental afvoerventilator", "Frånluftflöde", "prędkość wentylatora wywiewu", "", "", "dış fan hızı", "velocità aria di scarico", "rýchlosť výstupného ventilátora", "rychlost venkovního ventilátoru") // TODO translate -MAKE_TRANSLATION(airquality, "airquality", "air quality (voc)", "Luftqualität (VOC)", "luchtkwaliteit (VOC)", "Luftkvalitet (VOC)", "jakość powietrza", "", "", "hava kalitesi(voc)", "qualità aria (VOC)", "kvalita vzduchu (voc)", "kvalita vzduchu (VOC)") // TODO translate +MAKE_TRANSLATION(outFresh, "outfresh", "outdoor fresh air", "Außenlufttemp.", "temperatuur buitenlucht", "Utelufttemperatur", "świeże powietrze z zewnątrz", "", "", "dış ortam taze hava", "aria fresca esterna", "čerstvý vzduch vonku", "venkovní čerstvý vzduch") +MAKE_TRANSLATION(inFresh, "infresh", "indoor fresh air", "Zulufttemp.", "temperatuur aanvoer", "Tillufttemperatur", "nawiew", "", "", "iç ortam taze hava", "aria fresca interna", "čerstvý vzduch v interiéri", "vnitřní čerstvý vzduch") +MAKE_TRANSLATION(outEx, "outexhaust", "outdoor exhaust air", "Fortlufttemp.", "uitlaatemperatuur buiten", "Utgående lufttemperatur", "zużyte powietrze z wewnątrz", "", "", "dış ortam egsoz", "aria di scarico esterna", "vonkajší odpadový vzduch", "venkovní odpadní vzduch") +MAKE_TRANSLATION(inEx, "inexhaust", "indoor exhaust air", "Ablufttemp.", "uitlaattemperatuur binnen", "Frånlufttemperatur", "wywiew", "", "", "iç ortam egsoz", "aria di scarico interna", "vnútorný odpadový vzduch", "vnitřní odpadní vzduch") +MAKE_TRANSLATION(ventMode, "ventmode", "ventilation mode", "Belüftungsmodus", "ventilatiemodus", "ventilationsläge", "tryb wentylacji", "", "", "havalandırma modu", "modalità di ventilazione", "režim vetrania", "režim ventilace") +MAKE_TRANSLATION(ventInSpeed, "ventinspeed", "in blower speed", "Zuluftdrehzahl", "toerental aanvoerventilator", "Tilluftflöde", "prędkość wentylatora nawiewu", "", "", "iç fan hızı", "velocità aria di alimentazione", "rýchlosť ventilátora", "rychlost vnitřního ventilátoru") +MAKE_TRANSLATION(ventOutSpeed, "ventoutspeed", "out blower speed", "Abluftdrehzahl", "toerental afvoerventilator", "Frånluftflöde", "prędkość wentylatora wywiewu", "", "", "dış fan hızı", "velocità aria di scarico", "rýchlosť výstupného ventilátora", "rychlost venkovního ventilátoru") +MAKE_TRANSLATION(airquality, "airquality", "air quality (voc)", "Luftqualität (VOC)", "luchtkwaliteit (VOC)", "Luftkvalitet (VOC)", "jakość powietrza", "", "", "hava kalitesi(voc)", "qualità aria (VOC)", "kvalita vzduchu (voc)", "kvalita vzduchu (VOC)") MAKE_TRANSLATION(airbypass, "bypass", "bypass", "Bypass", "Bypass", "Bypass", "obejścia", "bypass", "dérivation", "baypas", "Bypass", "obtokový", "bypassový") // EM100 -MAKE_TRANSLATION(minV, "minv", "min volt.", "min. Spannung", "", "min. spänning", "minimalne napięcie", "", "", "", "", "min. napätie", "minimální napětí") // TODO translate -MAKE_TRANSLATION(maxV, "maxv", "max volt.", "max. Spannung", "", "max. spänning", "maksymalne napięcie", "", "", "", "", "max. napätie", "maximální napětí") // TODO translate -MAKE_TRANSLATION(minT, "mint", "min temp.", "min. Temperatur", "", "min. temperatur", "minimalna temperatura", "", "", "", "", "min. tepl.", "minimální teplota") // TODO translate -MAKE_TRANSLATION(maxT, "maxt", "max temp.", "max. Temperatur", "", "max. temperatur", "maksymalna temperatura", "", "", "", "", "max. tepl.", "maximální teplota") // TODO translate -MAKE_TRANSLATION(setPoint, "setpoint", "set temp.", "Solltemperatur", "", "Börvärde", "temperatura nastawu", "", "", "", "", "pož. teplota", "nastavená teplota") // TODO translate -MAKE_TRANSLATION(setPower, "setpower", "request power", "Sollleistung", "", "Böreffekt", "zadana moc", "", "", "", "", "pož. výkon", "požadovaný výkon") // TODO translate -MAKE_TRANSLATION(dip, "dip", "dip switch", "DIP-Schalter", "", "DIP-strömställare", "przełącznik DIP", "", "", "", "", "dip prepínač", "přepínač DIP") // TODO translate -MAKE_TRANSLATION(outPower, "outpow", "output IO1", "Ausgang IO1", "", "Utgångsffekt", "wyjście IO1", "", "", "", "", "výstup IO1", "výstup IO1") // TODO translate -MAKE_TRANSLATION(input, "input", "input", "Eingang", "", "Ingång", "wejście", "", "", "", "", "vstup", "vstup") // TODO translate +MAKE_TRANSLATION(minV, "minv", "min volt.", "min. Spannung", "", "min. spänning", "minimalne napięcie", "", "", "", "", "min. napätie", "minimální napětí") +MAKE_TRANSLATION(maxV, "maxv", "max volt.", "max. Spannung", "", "max. spänning", "maksymalne napięcie", "", "", "", "", "max. napätie", "maximální napětí") +MAKE_TRANSLATION(minT, "mint", "min temp.", "min. Temperatur", "", "min. temperatur", "minimalna temperatura", "", "", "", "", "min. tepl.", "minimální teplota") +MAKE_TRANSLATION(maxT, "maxt", "max temp.", "max. Temperatur", "", "max. temperatur", "maksymalna temperatura", "", "", "", "", "max. tepl.", "maximální teplota") +MAKE_TRANSLATION(setPoint, "setpoint", "set temp.", "Solltemperatur", "", "Börvärde", "temperatura nastawu", "", "", "", "", "pož. teplota", "nastavená teplota") +MAKE_TRANSLATION(setPower, "setpower", "request power", "Sollleistung", "", "Böreffekt", "zadana moc", "", "", "", "", "pož. výkon", "požadovaný výkon") +MAKE_TRANSLATION(dip, "dip", "dip switch", "DIP-Schalter", "", "DIP-strömställare", "przełącznik DIP", "", "", "", "", "dip prepínač", "přepínač DIP") +MAKE_TRANSLATION(outPower, "outpow", "output IO1", "Ausgang IO1", "", "Utgångsffekt", "wyjście IO1", "", "", "", "", "výstup IO1", "výstup IO1") +MAKE_TRANSLATION(input, "input", "input", "Eingang", "", "Ingång", "wejście", "", "", "", "", "vstup", "vstup") /* // unknown fields to track (SM10), only for testing // **** NO TRANSLATION NEEDED **** -MAKE_TRANSLATION(data11, "data11", "unknown datafield 11", "", "", "okänt datafält 11", "nieznane pole danych 11", "", "", "", "", "neznáme dátové pole 11", "") // TODO translate -MAKE_TRANSLATION(data12, "data12", "unknown datafield 12", "", "", "okänt datafält 12", "nieznane pole danych 12", "", "", "", "", "neznáme dátové pole 12", "") // TODO translate -MAKE_TRANSLATION(data8, "data8", "unknown datafield 8", "", "", "okänt datafält 8", "nieznane pole danych 8", "", "", "", "", "neznáme dátové pole 8", "") // TODO translate -MAKE_TRANSLATION(data0, "data0", "unknown datafield 0", "", "", "okänt datafält 0", "nieznane pole danych 0", "", "", "", "", "neznáme dátové pole 0", "") // TODO translate -MAKE_TRANSLATION(data1, "data1", "unknown datafield 1", "", "", "okänt datafält 1", "nieznane pole danych 1", "", "", "", "", "neznáme dátové pole 1", "") // TODO translate -MAKE_TRANSLATION(setting3, "setting3", "unknown setting 3", "", "", "okänd inställning 3", "nieznane ustawienie 3", "", "", "", "", "neznáme dátové pole 3", "") // TODO translate -MAKE_TRANSLATION(setting4, "setting4", "unknown setting 4", "", "", "okänd inställning 4", "nieznane ustawienie 4", "", "", "", "", "neznáme dátové pole 4", "") // TODO translate +MAKE_TRANSLATION(data11, "data11", "unknown datafield 11", "", "", "okänt datafält 11", "nieznane pole danych 11", "", "", "", "", "neznáme dátové pole 11", "") +MAKE_TRANSLATION(data12, "data12", "unknown datafield 12", "", "", "okänt datafält 12", "nieznane pole danych 12", "", "", "", "", "neznáme dátové pole 12", "") +MAKE_TRANSLATION(data8, "data8", "unknown datafield 8", "", "", "okänt datafält 8", "nieznane pole danych 8", "", "", "", "", "neznáme dátové pole 8", "") +MAKE_TRANSLATION(data0, "data0", "unknown datafield 0", "", "", "okänt datafält 0", "nieznane pole danych 0", "", "", "", "", "neznáme dátové pole 0", "") +MAKE_TRANSLATION(data1, "data1", "unknown datafield 1", "", "", "okänt datafält 1", "nieznane pole danych 1", "", "", "", "", "neznáme dátové pole 1", "") +MAKE_TRANSLATION(setting3, "setting3", "unknown setting 3", "", "", "okänd inställning 3", "nieznane ustawienie 3", "", "", "", "", "neznáme dátové pole 3", "") +MAKE_TRANSLATION(setting4, "setting4", "unknown setting 4", "", "", "okänd inställning 4", "nieznane ustawienie 4", "", "", "", "", "neznáme dátové pole 4", "") */ // clang-format on diff --git a/src/core/mqtt.cpp b/src/core/mqtt.cpp index 5fc577b72..17e8a1acb 100644 --- a/src/core/mqtt.cpp +++ b/src/core/mqtt.cpp @@ -62,8 +62,6 @@ std::string Mqtt::lastresponse_ = ""; // Home Assistant specific // icons from https://materialdesignicons.com used with the UOMs (unit of measurements) -MAKE_WORD(measurement) -MAKE_WORD(total_increasing) // MAKE_WORD_CUSTOM(icondegrees, "mdi:coolant-temperature") // DeviceValueUOM::DEGREES MAKE_WORD_CUSTOM(iconpercent, "mdi:percent-outline") // DeviceValueUOM::PERCENT MAKE_WORD_CUSTOM(iconkb, "mdi:memory") // DeviceValueUOM::KB @@ -1124,19 +1122,30 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev return queue_ha(topic, doc.as()); } -// Add the uom, state class, device class and an optional icon based on the uom -void Mqtt::add_ha_classes(JsonObject doc, const uint8_t device_type, const uint8_t type, const uint8_t uom, const char * entity, bool is_discovery) { +// Add the uom, state class, device class and an optional icon based on the uom (unless display_only is true) +// https://developers.home-assistant.io/docs/core/entity/sensor/ +// Home Assistant tracks the min, max and mean value during the statistics period +// For statistics, the sensor must have state_class set to either MEASUREMENT, TOTAL or TOTAL_INCREASING +// When set to MEASUREMENT the device_class must cannot be DATE, ENUM, ENERGY, GAS, MONETARY, TIMESTAMP, VOLUME or WATER +// +void Mqtt::add_ha_classes(JsonObject doc, const uint8_t device_type, const uint8_t type, const uint8_t uom, const char * entity, bool display_only) { if (device_type == EMSdevice::DeviceType::SYSTEM) { doc["ent_cat"] = "diagnostic"; // instead of 'config' } - // for HA discovery we use different namings - const char * dc_ha = is_discovery ? "dev_cla" : "device_class"; // device class - const char * sc_ha = is_discovery ? "stat_cla" : "state_class"; // state class - const char * uom_ha = is_discovery ? "unit_of_meas" : "uom"; // unit of measure + // For display_only, we don't use the aliases, also we don't display the icon + const char * dc_ha = display_only ? "device_class" : "dev_cla"; // device class, dev_cla + const char * sc_ha = display_only ? "state_class" : "stat_cla"; // state class, stat_cla + const char * uom_ha = display_only ? "uom" : "unit_of_meas"; // unit of measure, unit_of_meas + const char * ic_ha = display_only ? "icon" : "ic"; // icon, ic - // set uom, unless boolean - // using HA uom specific codes from https://github.com/home-assistant/core/blob/dev/homeassistant/const.py + // state class constants + const char * sc_ha_measurement = "measurement"; + const char * sc_ha_total = "total"; + const char * sc_ha_total_increasing = "total_increasing"; + + // set uom, unless boolean - as HA is fussy with the naming + // map too HA uom specific codes from https://github.com/home-assistant/core/blob/dev/homeassistant/const.py if (type != DeviceValueType::BOOL) { if (uom == DeviceValueUOM::HOURS) { doc[uom_ha] = "h"; @@ -1144,6 +1153,10 @@ void Mqtt::add_ha_classes(JsonObject doc, const uint8_t device_type, const uint8 doc[uom_ha] = "min"; } else if (uom == DeviceValueUOM::SECONDS) { doc[uom_ha] = "s"; + } else if (uom == DeviceValueUOM::KB) { + doc[uom_ha] = "kB"; + } else if (uom == DeviceValueUOM::LMIN) { + doc[uom_ha] = "L/min"; } else if (uom != DeviceValueUOM::NONE) { doc[uom_ha] = EMSdevice::uom_to_string(uom); // use default } else if (discovery_type() != discoveryType::HOMEASSISTANT) { @@ -1151,99 +1164,136 @@ void Mqtt::add_ha_classes(JsonObject doc, const uint8_t device_type, const uint8 } } - // set state and device class - // also icon, when there is no device class that sets one + // set state and device class - always + // see https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes switch (uom) { case DeviceValueUOM::DEGREES: case DeviceValueUOM::DEGREES_R: case DeviceValueUOM::K: - doc[sc_ha] = F_(measurement); + doc[sc_ha] = sc_ha_measurement; doc[dc_ha] = "temperature"; // override uom if fahrenheit doc[uom_ha] = EMSESP::system_.fahrenheit() ? DeviceValue::DeviceValueUOM_s[DeviceValueUOM::FAHRENHEIT] : DeviceValue::DeviceValueUOM_s[uom]; break; case DeviceValueUOM::PERCENT: - doc[sc_ha] = F_(measurement); + if (display_only) { + doc[ic_ha] = F_(iconpercent); // set icon + } + doc[sc_ha] = sc_ha_measurement; doc[dc_ha] = "power_factor"; - if (is_discovery) - doc["ic"] = F_(iconpercent); // icon break; case DeviceValueUOM::SECONDS: case DeviceValueUOM::MINUTES: case DeviceValueUOM::HOURS: if (type == DeviceValueType::TIME) { - doc[sc_ha] = F_(total_increasing); + doc[sc_ha] = sc_ha_total_increasing; } else { - doc[sc_ha] = F_(measurement); + doc[sc_ha] = sc_ha_measurement; } doc[dc_ha] = "duration"; // https://github.com/emsesp/EMS-ESP32/issues/822 break; case DeviceValueUOM::KB: - if (is_discovery) - doc["ic"] = F_(iconkb); + if (display_only) { + doc[ic_ha] = F_(iconkb); + } + doc[dc_ha] = "data_size"; break; case DeviceValueUOM::LMIN: case DeviceValueUOM::LH: - if (is_discovery) - doc["ic"] = F_(iconlmin); - doc[sc_ha] = F_(measurement); + if (display_only) { + doc[ic_ha] = F_(iconlmin); + } + doc[sc_ha] = sc_ha_measurement; + doc[dc_ha] = "volume_flow_rate"; break; case DeviceValueUOM::WH: // https://github.com/emsesp/EMS-ESP32/issues/1796 if (entity == FL_(energyToday)[0]) { - doc[sc_ha] = F_(total_increasing); + doc[sc_ha] = sc_ha_total_increasing; + doc[dc_ha] = "energy"; } else if (entity == FL_(energyLastHour)[0]) { - doc[sc_ha] = "total"; + doc[sc_ha] = sc_ha_total; + doc[dc_ha] = "energy"; } else { - doc[sc_ha] = F_(measurement); + doc[sc_ha] = sc_ha_measurement; // no device class for this } - doc[dc_ha] = "energy"; break; case DeviceValueUOM::KWH: - doc[sc_ha] = F_(total_increasing); + doc[sc_ha] = sc_ha_total_increasing; doc[dc_ha] = "energy"; break; case DeviceValueUOM::UA: - if (is_discovery) - doc["ic"] = F_(iconua); - doc[sc_ha] = F_(measurement); + if (display_only) { + doc[ic_ha] = F_(iconua); + } + doc[sc_ha] = sc_ha_measurement; + // doc[dc_ha] = "current"; // there is no uA in HA, only mA break; case DeviceValueUOM::BAR: - doc[sc_ha] = F_(measurement); + doc[sc_ha] = sc_ha_measurement; doc[dc_ha] = "pressure"; break; case DeviceValueUOM::W: case DeviceValueUOM::KW: - doc[sc_ha] = F_(measurement); + doc[sc_ha] = sc_ha_measurement; doc[dc_ha] = "power"; break; case DeviceValueUOM::DBM: - doc[sc_ha] = F_(measurement); + doc[sc_ha] = sc_ha_measurement; doc[dc_ha] = "signal_strength"; break; case DeviceValueUOM::CONNECTIVITY: - doc[sc_ha] = F_(measurement); + doc[sc_ha] = sc_ha_measurement; doc[dc_ha] = "connectivity"; break; - case DeviceValueUOM::NONE: + case DeviceValueUOM::MV: + case DeviceValueUOM::VOLTS: + doc[sc_ha] = sc_ha_measurement; + doc[dc_ha] = "voltage"; + break; + case DeviceValueUOM::MBAR: + doc[sc_ha] = sc_ha_measurement; + doc[dc_ha] = "atmospheric_pressure"; + break; + case DeviceValueUOM::CTKWH: + doc[sc_ha] = sc_ha_total_increasing; + doc[dc_ha] = "monetary"; + break; + case DeviceValueUOM::HZ: + doc[sc_ha] = sc_ha_measurement; + doc[dc_ha] = "frequency"; + break; + case DeviceValueUOM::M3: + case DeviceValueUOM::L: + // this could be Gas or Water, so going with the generic 'volume' for now + // state_class can't be a Measurement + doc[sc_ha] = sc_ha_total_increasing; + doc[dc_ha] = "volume"; + break; + case DeviceValueUOM::SQM: + doc[sc_ha] = sc_ha_measurement; + doc[dc_ha] = "area"; + break; + default: + // DeviceValueUOM::NONE: + // DeviceValueUOM::KMIN: // for device entities which have numerical values, with no UOM if ((type != DeviceValueType::STRING) && (type == DeviceValueType::INT8 || type == DeviceValueType::UINT8 || type == DeviceValueType::INT16 || type == DeviceValueType::UINT16 || type == DeviceValueType::UINT24 || type == DeviceValueType::UINT32)) { - if (is_discovery) - doc["ic"] = F_(iconnum); // set icon + if (display_only) { + doc[ic_ha] = F_(iconnum); // set icon + } // determine if its a measurement or total increasing // most of the values are measurement. for example Tx Reads will increment but can be reset to 0 after a restart // all the starts are increasing, and they are ULONGs if (type == DeviceValueType::UINT24 || type == DeviceValueType::UINT32) { - doc[sc_ha] = F_(total_increasing); + doc[sc_ha] = sc_ha_total_increasing; } else { - doc[sc_ha] = F_(measurement); // default to measurement + doc[sc_ha] = sc_ha_measurement; // default to measurement } } break; - default: - break; } } @@ -1444,9 +1494,8 @@ std::string Mqtt::tag_to_topic(uint8_t device_type, int8_t tag) { } } -// add devs section to an existing doc, only for HA -// under devs node it will create ids and name and optional mf, mdl, via_device -// name could be EMSdevice::device_type_2_device_name(dv.device_type)); +// adds dev section for HA Discovery to an existing JSON doc +// under devs node it will create ids and optional name, mf, mdl, sw and via_device void Mqtt::add_ha_dev_section(JsonObject doc, const char * name, const bool create_model, const char * model, const char * brand, const char * version) { // only works for HA if (discovery_type() != discoveryType::HOMEASSISTANT) { @@ -1488,6 +1537,7 @@ void Mqtt::add_ha_dev_section(JsonObject doc, const char * name, const bool crea } // adds avty section for HA Discovery to an existing JSON doc +// also adds LWT (Last Will and Testament) void Mqtt::add_ha_avty_section(JsonObject doc, const char * state_t, const char * cond1, const char * cond2, const char * negcond) { // only works for HA if (discovery_type() != discoveryType::HOMEASSISTANT) { diff --git a/src/core/mqtt.h b/src/core/mqtt.h index e51e16fac..8a2f82137 100644 --- a/src/core/mqtt.h +++ b/src/core/mqtt.h @@ -258,7 +258,7 @@ class Mqtt { static std::string tag_to_topic(uint8_t device_type, int8_t tag); static void - add_ha_classes(JsonObject doc, const uint8_t device_type, const uint8_t type, const uint8_t uom, const char * entity = nullptr, bool is_discovery = true); + add_ha_classes(JsonObject doc, const uint8_t device_type, const uint8_t type, const uint8_t uom, const char * entity = nullptr, bool display_only = false); static void add_ha_dev_section(JsonObject doc, const char * name = nullptr, const bool create_model = false, diff --git a/src/core/shuntingYard.cpp b/src/core/shuntingYard.cpp index 703befea0..62e738bfb 100644 --- a/src/core/shuntingYard.cpp +++ b/src/core/shuntingYard.cpp @@ -399,17 +399,23 @@ std::string commands(std::string & expr, bool quotes) { // checks for logic value int to_logic(const std::string & s) { - if (s.empty()) { - return -1; + bool value_b; + if (!Helpers::value2bool(s.c_str(), value_b)) { + return -1; // invalid } - auto l = Helpers::toLower(s); - if (s[0] == '1' || l == "on" || l == "true") { - return 1; - } - if (s[0] == '0' || l == "off" || l == "false") { - return 0; - } - return -1; + return value_b; + + // if (s.empty()) { + // return -1; + // } + // auto l = Helpers::toLower(s); + // if (s[0] == '1' || l == "on" || l == "true") { + // return 1; + // } + // if (s[0] == '0' || l == "off" || l == "false") { + // return 0; + // } + // return -1; } // number to string, remove trailing zeros diff --git a/src/core/system.cpp b/src/core/system.cpp index be231c9cf..b2ab4de79 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -21,9 +21,11 @@ #ifndef EMSESP_STANDALONE #include "esp_ota_ops.h" +#include "esp_partition.h" #endif #include +#include #include @@ -90,12 +92,23 @@ uuid::syslog::SyslogService System::syslog_; uuid::log::Logger System::logger_{F_(system), uuid::log::Facility::KERN}; // init statics -PButton System::myPButton_; -bool System::test_set_all_active_ = false; -uint32_t System::max_alloc_mem_; -uint32_t System::heap_mem_; +PButton System::myPButton_; +bool System::test_set_all_active_ = false; +uint32_t System::max_alloc_mem_; +uint32_t System::heap_mem_; + +// LED flash timer +uint8_t System::led_flash_gpio_ = 0; +uint8_t System::led_flash_type_ = 0; +uint32_t System::led_flash_start_time_ = 0; +uint32_t System::led_flash_duration_ = 0; +bool System::led_flash_timer_ = false; + +// GPIOs std::vector> System::valid_system_gpios_; std::vector> System::used_gpios_; +std::vector> System::snapshot_used_gpios_; +std::vector> System::snapshot_valid_system_gpios_; // find the index of the language // 0 = EN, 1 = DE, etc... @@ -291,33 +304,164 @@ void System::store_nvs_values() { EMSESP::nvs_.end(); } +// Build up a list of all partitions and their version info +void System::get_partition_info() { + partition_info_.clear(); // clear existing data + +#ifdef EMSESP_STANDALONE + // dummy data for standalone mode - version, size, install_date + partition_info_["app0"] = {EMSESP_APP_VERSION, 0, ""}; + partition_info_["app1"] = {"", 0, ""}; + partition_info_["factory"] = {"", 0, ""}; + partition_info_["boot"] = {"", 0, ""}; +#else + + auto current_partition = (const char *)esp_ota_get_running_partition()->label; + + // update the current version and partition name in NVS if not already set (saves on flash wearing) + if (EMSESP::nvs_.isKey(current_partition)) { + if (EMSESP::nvs_.getString(current_partition) != EMSESP_APP_VERSION) { + EMSESP::nvs_.putString(current_partition, EMSESP_APP_VERSION); + } + } else { + EMSESP::nvs_.putString(current_partition, EMSESP_APP_VERSION); // create new entry + } + + // Loop through all available partitions and update map with the version info pulled from NVS + // Partitions can be app0, app1, factory, boot + esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, nullptr); + uint64_t buffer; + + while (it != nullptr) { + bool is_valid = true; + const esp_partition_t * part = esp_partition_get(it); + + if (part->label != nullptr && part->label[0] != '\0') { + // check if partition is valid and not empty + esp_partition_read(part, 0, &buffer, 8); + if (buffer == 0xFFFFFFFFFFFFFFFF) { + is_valid = false; // skip this partition + } + } + + // get the version from the NVS store, and add to map + if (is_valid) { + PartitionInfo p_info; + p_info.version = ""; + p_info.install_date = ""; // this will be added later when NTP is connected + + p_info.size = part->size / 1024; // set size in KB + + // if there is an entry for this partition in NVS, get it's version from NVS + if (EMSESP::nvs_.isKey(part->label)) { + p_info.version = EMSESP::nvs_.getString(part->label).c_str(); + } + + partition_info_[part->label] = p_info; + } + + it = esp_partition_next(it); // loop to next partition + } + esp_partition_iterator_release(it); +#endif +} + +// set NTP install time/date for the current partition +// assumes NTP is connected and working +void System::set_partition_install_date(bool override) { +#ifndef EMSESP_STANDALONE + auto current_partition = (const char *)esp_ota_get_running_partition()->label; + if (current_partition == nullptr) { + return; // fail-safe + } + + // skip if it already has an install date, unless override is true + if (!partition_info_[current_partition].install_date.empty() && !override) { + return; + } + + // EMSESP_NVS_BOOT_NEW_FIRMWARE is set in UploadFileService::uploadComplete() + auto is_fresh_firmware = EMSESP::nvs_.getBool(EMSESP_NVS_BOOT_NEW_FIRMWARE); + // always reset flag after setting the install date + EMSESP::nvs_.putBool(EMSESP_NVS_BOOT_NEW_FIRMWARE, false); + + // check if the firmware is a new upload + if (is_fresh_firmware) { + LOG_DEBUG("Firmware is fresh, setting the new install date in partition %s", current_partition); + } else { + return; // skip, not new + } + + // set current date/time from NTP + char time_string[25]; + time_t now = time(nullptr); + strftime(time_string, sizeof(time_string), "%FT%T", localtime(&now)); + partition_info_[current_partition].install_date = time_string; + LOG_DEBUG("Adding NTP install date %s to partition %s", time_string, current_partition); +#endif +} + +// sets the partition to use on the next restart +bool System::set_partition(const char * partitionname) { +#ifdef EMSESP_STANDALONE + return true; +#else + if (partitionname == nullptr) { + return false; + } + + // Find the partition by label + esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, partitionname); + if (it == nullptr) { + return false; // partition not found + } + + const esp_partition_t * partition = esp_partition_get(it); + esp_partition_iterator_release(it); + + if (partition == nullptr) { + return false; + } + + // Set the boot partition + esp_err_t err = esp_ota_set_boot_partition(partition); + if (err != ESP_OK) { + return false; + } + + // initiate the restart + EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_RESTART_REQUESTED); + return true; +#endif +} + // restart EMS-ESP -// app0 or app1 -// on 16MB we have the additional boot and factory partitions +// app0 or app1, or boot/factory on 16MB boards void System::system_restart(const char * partitionname) { #ifndef EMSESP_STANDALONE // see if we are forcing a partition to use if (partitionname != nullptr) { // Factory partition - label will be "factory" const esp_partition_t * partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); - if (partition && strcmp(partition->label, partitionname) == 0) { + if (partition && !strcmp(partition->label, partitionname)) { esp_ota_set_boot_partition(partition); } else // try and find the partition by name - if (strcmp(esp_ota_get_running_partition()->label, partitionname) != 0) { + if (strcmp(esp_ota_get_running_partition()->label, partitionname)) { + // not found, get next one in cycle partition = esp_ota_get_next_update_partition(nullptr); if (!partition) { LOG_ERROR("Partition '%s' not found", partitionname); return; } - if (strcmp(partition->label, partitionname) != 0 && strcmp(partitionname, "boot") != 0) { + if (strcmp(partition->label, partitionname) && strcmp(partitionname, "boot") != 0) { partition = esp_ota_get_next_update_partition(partition); if (!partition || strcmp(partition->label, partitionname)) { LOG_ERROR("Partition '%s' not found", partitionname); return; } } - // check if partition is empty + // error if partition is empty uint64_t buffer; esp_partition_read(partition, 0, &buffer, 8); if (buffer == 0xFFFFFFFFFFFFFFFF) { @@ -338,8 +482,9 @@ void System::system_restart(const char * partitionname) { store_nvs_values(); // save any NVS values Shell::loop_all(); // flush log to output Mqtt::disconnect(); // gracefully disconnect MQTT, needed for QOS1 + EMSuart::stop(); // stop UART so there is no interference delay(1000); // wait 1 second - ESP.restart(); + ESP.restart(); // ka-boom! #else EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_NORMAL); if (partitionname != nullptr) { @@ -452,8 +597,10 @@ void System::store_settings(WebSettings & settings) { developer_mode_ = settings.developer_mode; } -// Starts up the UART Serial bridge +// Starts up core services void System::start() { + get_partition_info(); // get the partition info + #ifndef EMSESP_STANDALONE // disable bluetooth module // periph_module_disable(PERIPH_BT_MODULE); @@ -527,20 +674,67 @@ void System::button_OnDblClick(PButton & b) { EMSESP::esp32React.getNetworkSettingsService()->callUpdateHandlers(); // in case we've changed ssid or password } -// button long press -void System::button_OnLongPress(PButton & b) { - LOG_NOTICE("Button pressed - long press - perform factory reset"); -#ifndef EMSESP_STANDALONE - System::command_format(nullptr, 0); -#endif +// LED flash every 100ms +void System::led_flash() { + static bool led_flash_state_ = false; + static uint32_t last_toggle_time_ = 0; + uint32_t current_time = uuid::get_uptime(); + + if (current_time - last_toggle_time_ >= 100) { // every 100ms + led_flash_state_ = !led_flash_state_; + last_toggle_time_ = current_time; + + if (led_flash_type_) { + uint8_t intensity = led_flash_state_ ? RGB_LED_BRIGHTNESS : 0; + EMSESP_RGB_WRITE(led_flash_gpio_, intensity, intensity, 0); // RGB LED - Yellow + } else { + digitalWrite(led_flash_gpio_, led_flash_state_ ? LED_ON : !LED_ON); // Standard LED + } + } + + // after duration, turn off the LED + if (current_time - led_flash_start_time_ >= led_flash_duration_) { + if (led_flash_type_) { + EMSESP_RGB_WRITE(led_flash_gpio_, 0, 0, 0); + } else { + digitalWrite(led_flash_gpio_, !LED_ON); + } + led_flash_timer_ = false; + command_format(nullptr, 0); // Execute format operation + } } -// button indefinite press - do nothing for now -void System::button_OnVLongPress(PButton & b) { - LOG_NOTICE("Button pressed - very long press - restart from factory/boot partition"); +// Start the LED flash timer - duration in seconds +void System::start_led_flash(uint8_t duration) { + // Don't start if already running + if (led_flash_timer_) { + return; + } + + // Get LED settings + EMSESP::webSettingsService.read([&](WebSettings & settings) { + led_flash_type_ = settings.led_type; + led_flash_gpio_ = settings.led_gpio; + }); + + // Reset counter and state + led_flash_start_time_ = uuid::get_uptime(); // current time + led_flash_duration_ = duration * 1000; // duration in milliseconds + led_flash_timer_ = true; // it's active +} + +// button long press +void System::button_OnLongPress(PButton & b) { + LOG_NOTICE("Button pressed - long press - restart EMS-ESP"); EMSESP::system_.system_restart("boot"); } +// button indefinite press +void System::button_OnVLongPress(PButton & b) { + LOG_NOTICE("Button pressed - very long press - perform factory reset"); + start_led_flash(5); // Start LED flash timer for 5 seconds +} + // push button void System::button_init() { #ifndef EMSESP_STANDALONE @@ -560,20 +754,12 @@ void System::button_init() { // set the LED to on or off when in normal operating mode void System::led_init() { // disabled old led port before setting new one -#if ESP_ARDUINO_VERSION_MAJOR < 3 - led_type_ ? neopixelWrite(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); -#else - led_type_ ? rgbLedWrite(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); -#endif + led_type_ ? EMSESP_RGB_WRITE(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); if ((led_gpio_)) { // 0 means disabled if (led_type_) { // rgb LED WS2812B, use Neopixel -#if ESP_ARDUINO_VERSION_MAJOR < 3 - neopixelWrite(led_gpio_, 0, 0, 0); -#else - rgbLedWrite(led_gpio_, 0, 0, 0); -#endif + EMSESP_RGB_WRITE(led_gpio_, 0, 0, 0); } else { pinMode(led_gpio_, OUTPUT); digitalWrite(led_gpio_, !LED_ON); // start with LED off @@ -585,32 +771,38 @@ void System::led_init() { void System::uart_init() { EMSuart::stop(); - - // start UART, GPIOs have already been checked - EMSuart::start(tx_mode_, rx_gpio_, tx_gpio_); - - EMSESP::txservice_.start(); // reset counters and send devices request + EMSuart::start(tx_mode_, rx_gpio_, tx_gpio_); // start UART, GPIOs have already been checked + EMSESP::txservice_.start(); // reset counters and send devices request } // checks system health and handles LED flashing wizardry -void System::loop() { +// returns true if the LED flash is active +bool System::loop() { // check if we're supposed to do a reset/restart if (systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_RESTART_REQUESTED) { system_restart(); } -#ifndef EMSESP_STANDALONE - myPButton_.check(); // check button press + // if LED flashing is active, run the LED flash + if (led_flash_timer_) { + led_flash(); + return true; // is active + } - // syslog + led_monitor(); // check status and report back using the LED + myPButton_.check(); // check button press + system_check(); // check system health + +// syslog +#ifndef EMSESP_STANDALONE if (syslog_enabled_) { syslog_.loop(); } - - led_monitor(); // check status and report back using the LED - system_check(); // check system health - send_info_mqtt(); #endif + + send_info_mqtt(); + + return false; // LED flashing is not active } // send MQTT info topic appended with the version information as JSON, as a retained flag @@ -789,8 +981,9 @@ void System::network_init() { // check health of system, done every 5 seconds void System::system_check() { - if (!last_system_check_ || ((uint32_t)(uuid::get_uptime() - last_system_check_) >= SYSTEM_CHECK_FREQUENCY)) { - last_system_check_ = uuid::get_uptime(); + uint32_t current_uptime = uuid::get_uptime(); + if (!last_system_check_ || ((uint32_t)(current_uptime - last_system_check_) >= SYSTEM_CHECK_FREQUENCY)) { + last_system_check_ = current_uptime; #ifndef EMSESP_STANDALONE #if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 @@ -831,21 +1024,15 @@ void System::system_check() { // see if we're better now if (healthcheck_ == 0) { // everything is healthy, show LED permanently on or off depending on setting + // Green on RGB LED, on/off on standard LED if (led_gpio_) { -#if ESP_ARDUINO_VERSION_MAJOR < 3 - led_type_ ? neopixelWrite(led_gpio_, 0, hide_led_ ? 0 : RGB_LED_BRIGHTNESS, 0) : digitalWrite(led_gpio_, hide_led_ ? !LED_ON : LED_ON); -#else - led_type_ ? rgbLedWrite(led_gpio_, 0, hide_led_ ? 0 : RGB_LED_BRIGHTNESS, 0) : digitalWrite(led_gpio_, hide_led_ ? !LED_ON : LED_ON); -#endif + led_type_ ? EMSESP_RGB_WRITE(led_gpio_, 0, hide_led_ ? 0 : RGB_LED_BRIGHTNESS, 0) + : digitalWrite(led_gpio_, hide_led_ ? !LED_ON : LED_ON); // Green } } else { - // turn off LED so we're ready to the flashes + // turn off LED so we're ready for the warning flashes if (led_gpio_) { -#if ESP_ARDUINO_VERSION_MAJOR < 3 - led_type_ ? neopixelWrite(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); -#else - led_type_ ? rgbLedWrite(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); -#endif + led_type_ ? EMSESP_RGB_WRITE(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); } } } @@ -860,6 +1047,7 @@ void System::commands_init() { Command::add(EMSdevice::DeviceType::SYSTEM, F_(fetch), System::command_fetch, FL_(fetch_cmd), CommandFlag::ADMIN_ONLY); Command::add(EMSdevice::DeviceType::SYSTEM, F_(restart), System::command_restart, FL_(restart_cmd), CommandFlag::ADMIN_ONLY); Command::add(EMSdevice::DeviceType::SYSTEM, F_(format), System::command_format, FL_(format_cmd), CommandFlag::ADMIN_ONLY); + Command::add(EMSdevice::DeviceType::SYSTEM, F_(txpause), System::command_txpause, FL_(txpause_cmd), CommandFlag::ADMIN_ONLY); Command::add(EMSdevice::DeviceType::SYSTEM, F_(watch), System::command_watch, FL_(watch_cmd)); Command::add(EMSdevice::DeviceType::SYSTEM, F_(message), System::command_message, FL_(message_cmd)); #if defined(EMSESP_TEST) @@ -874,19 +1062,29 @@ void System::commands_init() { } // uses LED to show system health -// 1 x flash = the EMS bus is not connected -// 2 x flash = the network (wifi or ethernet) is not connected -// 3 x flash = both EMS bus and network are failing. This is a critical error! void System::led_monitor() { + // if button is pressed, show LED (yellow on RGB LED, on/off on standard LED) + static bool button_busy_ = false; + if (button_busy_ != myPButton_.button_busy()) { + button_busy_ = myPButton_.button_busy(); + if (led_type_) { + EMSESP_RGB_WRITE(led_gpio_, button_busy_ ? RGB_LED_BRIGHTNESS : 0, button_busy_ ? RGB_LED_BRIGHTNESS : 0, 0); // Yellow + } else { + digitalWrite(led_gpio_, button_busy_ ? LED_ON : !LED_ON); + } + } + // we only need to run the LED healthcheck if there are errors - if (!healthcheck_ || !led_gpio_) { + // skip if we're in the led_flash_timer or if a button has been pressed + if (!healthcheck_ || !led_gpio_ || button_busy_ || led_flash_timer_) { return; // all good } static uint32_t led_long_timer_ = 1; // 1 will kick it off immediately static uint32_t led_short_timer_ = 0; static uint8_t led_flash_step_ = 0; // 0 means we're not in the short flash timer - auto current_time = uuid::get_uptime(); + + auto current_time = uuid::get_uptime(); // first long pause before we start flashing if (led_long_timer_ && (uint32_t)(current_time - led_long_timer_) >= HEALTHCHECK_LED_LONG_DUARATION) { @@ -905,74 +1103,50 @@ void System::led_monitor() { // reset the whole sequence led_long_timer_ = uuid::get_uptime(); led_flash_step_ = 0; -#if ESP_ARDUINO_VERSION_MAJOR < 3 - led_type_ ? neopixelWrite(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); // LED off -#else - led_type_ ? rgbLedWrite(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); // LED off -#endif + led_type_ ? EMSESP_RGB_WRITE(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); // LED off } else if (led_flash_step_ % 2) { // handle the step events (on odd numbers 3,5,7,etc). see if we need to turn on a LED - // 1 flash is the EMS bus is not connected - // 2 flashes if the network (wifi or ethernet) is not connected - // 3 flashes is both the bus and the network are not connected. Then you know you're truly f*cked. + // 1 flash (blue) is the EMS bus is not connected + // 2 flashes (red, red) if the network (wifi or ethernet) is not connected + // 3 flashes (red, red, blue) is both the bus and the network are not connected + bool no_network = (healthcheck_ & HEALTHCHECK_NO_NETWORK) == HEALTHCHECK_NO_NETWORK; + bool no_bus = (healthcheck_ & HEALTHCHECK_NO_BUS) == HEALTHCHECK_NO_BUS; + if (led_type_) { if (led_flash_step_ == 3) { - if ((healthcheck_ & HEALTHCHECK_NO_NETWORK) == HEALTHCHECK_NO_NETWORK) { -#if ESP_ARDUINO_VERSION_MAJOR < 3 - neopixelWrite(led_gpio_, RGB_LED_BRIGHTNESS, 0, 0); // red -#else - rgbLedWrite(led_gpio_, RGB_LED_BRIGHTNESS, 0, 0); // red -#endif - } else if ((healthcheck_ & HEALTHCHECK_NO_BUS) == HEALTHCHECK_NO_BUS) { -#if ESP_ARDUINO_VERSION_MAJOR < 3 - neopixelWrite(led_gpio_, 0, 0, RGB_LED_BRIGHTNESS); // blue -#else - rgbLedWrite(led_gpio_, 0, 0, RGB_LED_BRIGHTNESS); // blue -#endif + if (no_network) { + EMSESP_RGB_WRITE(led_gpio_, RGB_LED_BRIGHTNESS, 0, 0); // red + } else if (no_bus) { + EMSESP_RGB_WRITE(led_gpio_, 0, 0, RGB_LED_BRIGHTNESS); // blue } } - if (led_flash_step_ == 5 && (healthcheck_ & HEALTHCHECK_NO_NETWORK) == HEALTHCHECK_NO_NETWORK) { -#if ESP_ARDUINO_VERSION_MAJOR < 3 - neopixelWrite(led_gpio_, RGB_LED_BRIGHTNESS, 0, 0); // red -#else - rgbLedWrite(led_gpio_, RGB_LED_BRIGHTNESS, 0, 0); // red -#endif + if (led_flash_step_ == 5 && no_network) { + EMSESP_RGB_WRITE(led_gpio_, RGB_LED_BRIGHTNESS, 0, 0); // red } - if ((led_flash_step_ == 7) && ((healthcheck_ & HEALTHCHECK_NO_NETWORK) == HEALTHCHECK_NO_NETWORK) - && ((healthcheck_ & HEALTHCHECK_NO_BUS) == HEALTHCHECK_NO_BUS)) { -#if ESP_ARDUINO_VERSION_MAJOR < 3 - neopixelWrite(led_gpio_, 0, 0, RGB_LED_BRIGHTNESS); // blue -#else - rgbLedWrite(led_gpio_, 0, 0, RGB_LED_BRIGHTNESS); // blue -#endif + if ((led_flash_step_ == 7) && no_network && no_bus) { + EMSESP_RGB_WRITE(led_gpio_, 0, 0, RGB_LED_BRIGHTNESS); // blue } } else { - if ((led_flash_step_ == 3) - && (((healthcheck_ & HEALTHCHECK_NO_NETWORK) == HEALTHCHECK_NO_NETWORK) || ((healthcheck_ & HEALTHCHECK_NO_BUS) == HEALTHCHECK_NO_BUS))) { + if ((led_flash_step_ == 3) && (no_network || no_bus)) { led_on_ = true; } - if ((led_flash_step_ == 5) && ((healthcheck_ & HEALTHCHECK_NO_NETWORK) == HEALTHCHECK_NO_NETWORK)) { + if ((led_flash_step_ == 5) && no_network) { led_on_ = true; } - if ((led_flash_step_ == 7) && ((healthcheck_ & HEALTHCHECK_NO_NETWORK) == HEALTHCHECK_NO_NETWORK) - && ((healthcheck_ & HEALTHCHECK_NO_BUS) == HEALTHCHECK_NO_BUS)) { + if ((led_flash_step_ == 7) && no_network && no_bus) { led_on_ = true; } if (led_on_) { - digitalWrite(led_gpio_, LED_ON); // LED off + digitalWrite(led_gpio_, LED_ON); // LED on } } } else { // turn the led off after the flash, on even number count if (led_on_) { -#if ESP_ARDUINO_VERSION_MAJOR < 3 - led_type_ ? neopixelWrite(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); -#else - led_type_ ? rgbLedWrite(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); -#endif + led_type_ ? EMSESP_RGB_WRITE(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); led_on_ = false; } } @@ -1015,22 +1189,6 @@ void System::show_users(uuid::console::Shell & shell) { shell.println(); } -// print GPIO available and used pins to console -void System::show_gpio(uuid::console::Shell & shell) { - shell.printfln("GPIO:"); - shell.printf(" In use (%d):", used_gpios_.size()); - for (const auto & gpio : used_gpios_) { - shell.printf(" %d", gpio); - } - shell.println(); - auto available = available_gpios(); - shell.printf(" Available (%d):", available.size()); - for (const auto & gpio : available) { - shell.printf(" %d", gpio); - } - shell.println(); -} - // shell command 'show system' void System::show_system(uuid::console::Shell & shell) { refreshHeapMem(); // refresh free heap and max alloc heap @@ -1041,7 +1199,6 @@ void System::show_system(uuid::console::Shell & shell) { #ifndef EMSESP_STANDALONE shell.printfln(" Platform: %s (%s)", EMSESP_PLATFORM, ESP.getChipModel()); shell.printfln(" Model: %s", getBBQKeesGatewayDetails().c_str()); - shell.printfln(" Partition: %s", esp_ota_get_running_partition()->label); #endif shell.printfln(" Language: %s", locale().c_str()); shell.printfln(" Board profile: %s", board_profile().c_str()); @@ -1068,10 +1225,35 @@ void System::show_system(uuid::console::Shell & shell) { } else { shell.printfln(" PSRAM: not available"); } + // GPIOs + shell.println(" GPIOs:"); + shell.printf(" in use:"); + for (const auto & gpio : used_gpios_) { + shell.printf(" %d", gpio); + } + shell.printfln(" (total %d)", used_gpios_.size()); + auto available = available_gpios(); + shell.printf(" available:"); + for (const auto & gpio : available) { + shell.printf(" %d", gpio); + } + shell.printfln(" (total %d)", available.size()); + // List all partitions and their version info + shell.println(" Partitions:"); + for (const auto & partition : partition_info_) { + if (partition.second.version.empty()) { + continue; // no version, empty string + } + shell.printfln(" %s: v%s (%d KB%s) %s", + partition.first.c_str(), + partition.second.version.c_str(), + partition.second.size, + partition.second.install_date.empty() ? "" : (std::string(", installed ") + partition.second.install_date).c_str(), + (strcmp(esp_ota_get_running_partition()->label, partition.first.c_str()) == 0) ? "** active **" : ""); + } shell.println(); shell.println("Network:"); - switch (WiFi.status()) { case WL_IDLE_STATUS: shell.printfln(" Status: Idle"); @@ -1259,12 +1441,13 @@ bool System::check_upgrade(bool factory_settings) { } if (factory_settings) { - return false; // fresh install, do nothing + return true; // fresh install, do nothing, no reboot required } version::Semver200_version this_version(EMSESP_APP_VERSION); - bool save_version = true; + bool save_version = true; + bool reboot_required = false; // compare versions if (this_version > settings_version) { @@ -1305,25 +1488,31 @@ bool System::check_upgrade(bool factory_settings) { }); } - // changes to Network - EMSESP::esp32React.getNetworkSettingsService()->update([&](NetworkSettings & networkSettings) { - // Network Settings Wifi tx_power is now using the value * 4. - if (networkSettings.tx_power == 20) { - networkSettings.tx_power = WIFI_POWER_19_5dBm; // use 19.5 as we don't have 20 anymore - LOG_INFO("Upgrade: Setting WiFi TX Power to Auto"); - } - - // force WiFi sleep to off (was default on < 3.7.0-dev-33) - networkSettings.nosleep = true; - LOG_INFO("Upgrade: Disabling WiFi nosleep"); - - return StateUpdateResult::CHANGED; - }); + // changes pre < v3.7.0 + if (settings_version.major() == 3 && settings_version.minor() < 7) { + // network changes + // 1) WiFi Tx Power is now using the value * 4 (was 20) + // 2) WiFi sleep is now off by default (was on) + EMSESP::esp32React.getNetworkSettingsService()->update([&](NetworkSettings & networkSettings) { + auto changed = StateUpdateResult::UNCHANGED; + if (networkSettings.tx_power == 20) { + networkSettings.tx_power = WIFI_POWER_19_5dBm; // use 19.5 as we don't have 20 anymore + LOG_INFO("Upgrade: Setting WiFi TX Power to Auto"); + changed = StateUpdateResult::CHANGED; + } + if (networkSettings.nosleep != true) { + networkSettings.nosleep = true; + LOG_INFO("Upgrade: Disabling WiFi nosleep"); + changed = StateUpdateResult::CHANGED; + } + return changed; + }); + } // changes to application settings EMSESP::webSettingsService.update([&](WebSettings & settings) { // force web buffer to 25 for those boards without psram - if (EMSESP::system_.PSram() == 0) { + if ((EMSESP::system_.PSram() == 0) && (settings.weblog_buffer != 25)) { settings.weblog_buffer = 25; return StateUpdateResult::CHANGED; } @@ -1332,24 +1521,27 @@ bool System::check_upgrade(bool factory_settings) { } else if (this_version < settings_version) { - // need downgrade + // downgrading LOG_NOTICE("Downgrading to version %d.%d.%d-%s", this_version.major(), this_version.minor(), this_version.patch(), this_version.prerelease().c_str()); } else { - // same version, do nothing - save_version = false; + save_version = false; // same version, do nothing } - // if we did a change, set the new version and save it, then reboot + // if we did a change, set the new version and save it, no need to reboot if (save_version) { EMSESP::webSettingsService.update([&](WebSettings & settings) { settings.version = EMSESP_APP_VERSION; + LOG_DEBUG("Upgrade: Setting version to %s", EMSESP_APP_VERSION); return StateUpdateResult::CHANGED; }); - // LOG_INFO("Upgrade: Setting version to %s", EMSESP_APP_VERSION); + } + + if (reboot_required) { + LOG_INFO("Upgrade: Rebooting to apply changes"); return true; // need reboot } - return false; + return false; // no reboot required } // convert settings file into json object @@ -1505,9 +1697,11 @@ bool System::get_value_info(JsonObject output, const char * cmd) { if (!strcmp(cmd, F_(entities))) { for (JsonPair p : root) { if (p.value().is()) { + const char * p_key = p.key().c_str(); // Cache the key for (JsonPair p1 : p.value().as()) { - JsonObject entity = output[std::string(p.key().c_str()) + "." + p1.key().c_str()].to(); - get_value_json(entity, p.key().c_str(), p1.key().c_str(), p1.value()); + const char * p1_key = p1.key().c_str(); // Cache the key + JsonObject entity = output[std::string(p_key) + "." + p1_key].to(); + get_value_json(entity, p_key, p1_key, p1.value()); } } } @@ -1542,14 +1736,16 @@ bool System::get_value_info(JsonObject output, const char * cmd) { // Loop through all the key-value pairs in root to find the key, case independent if (slash) { // search the top level first for (JsonPair p : root) { - if (p.value().is() && Helpers::toLower(p.key().c_str()) == cmd) { + const char * p_key = p.key().c_str(); // Cache the key + if (p.value().is() && Helpers::toLower(p_key) == cmd) { for (JsonPair p1 : p.value().as()) { - if (Helpers::toLower(p1.key().c_str()) == slash && !p1.value().is()) { + const char * p1_key = p1.key().c_str(); // Cache the key + if (Helpers::toLower(p1_key) == slash && !p1.value().is()) { if (val) { output["api_data"] = p1.value().as(); return true; } - get_value_json(output, p.key().c_str(), p1.key().c_str(), p1.value()); + get_value_json(output, p_key, p1_key, p1.value()); return true; } } @@ -2092,7 +2288,6 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output node["pbuttonGPIO"] = EMSESP::system_.pbutton_gpio_; node["ledGPIO"] = EMSESP::system_.led_gpio_; node["ledType"] = settings.led_type; - node["ledType"] = settings.led_type; } node["hideLed"] = settings.hide_led; node["noTokenApi"] = settings.notoken_api; @@ -2239,15 +2434,50 @@ bool System::load_board_profile(std::vector & data, const std::string & return true; } +// txpause command - temporarily pause the TX, by setting Txmode to 0 (disabled) +bool System::command_txpause(const char * value, const int8_t id) { + bool arg; + if (!Helpers::value2bool(value, arg)) { + return false; // argument not recognized + } + + if (!arg) { + // arg = false: Tx mode to 0 (disabled) to pause + if (EMSbus::tx_mode() == EMS_TXMODE_OFF) { + EMSESP::webSettingsService.read([&](WebSettings & settings) { + EMSbus::tx_mode(settings.tx_mode); +#ifdef EMSESP_DEBUG + LOG_INFO("TX mode restored (value %d)", settings.tx_mode); +#else + LOG_INFO("TX active"); +#endif + }); + } + } else { + // pause = true: Tx mode to 0 (disabled) to pause + if (EMSbus::tx_mode() != EMS_TXMODE_OFF) { + EMSbus::tx_mode(EMS_TXMODE_OFF); +#ifdef EMSESP_DEBUG + LOG_INFO("TX mode set to OFF (value %d)", EMS_TXMODE_OFF); +#else + LOG_INFO("TX paused"); +#endif + } + } + return true; +} + // format command - factory reset, removing all config files bool System::command_format(const char * value, const int8_t id) { - LOG_INFO("Formatting FS, removing all config files"); -#ifndef EMSESP_STANDALONE +#if !defined(EMSESP_STANDALONE) && !defined(EMSESP_DEBUG) + // don't really format the filesystem in debug or standalone mode if (LittleFS.format()) { - LOG_INFO("FS formatted successfully"); + LOG_INFO("Filesystem formatted successfully. All config files removed."); } else { LOG_ERROR("Format failed"); } +#else + LOG_INFO("Format command not available in standalone or debug mode"); #endif // restart will be handled by the main loop @@ -2321,6 +2551,11 @@ void System::ntp_connected(bool b) { if (b != ntp_connected_) { if (b) { LOG_INFO("NTP connected"); +#ifdef EMSESP_DEBUG // reset the install date on startup if in debug mode + set_partition_install_date(true); +#else + set_partition_install_date(false); +#endif } else { LOG_WARNING("NTP disconnected"); // if turned off report it } @@ -2688,4 +2923,38 @@ std::vector System::available_gpios() { return gpios; } +// make a snapshot of the current GPIOs +void System::make_snapshot_gpios() { + snapshot_used_gpios_.clear(); + for (const auto & gpio : used_gpios_) { + snapshot_used_gpios_.push_back(gpio); + } + + snapshot_valid_system_gpios_.clear(); + for (const auto & gpio : valid_system_gpios_) { + snapshot_valid_system_gpios_.push_back(gpio); + } +} + +// restore the GPIOs from the snapshot +void System::restore_snapshot_gpios() { + used_gpios_.clear(); + for (const auto & gpio : snapshot_used_gpios_) { + used_gpios_.push_back(gpio); + } + + valid_system_gpios_.clear(); + for (const auto & gpio : snapshot_valid_system_gpios_) { + valid_system_gpios_.push_back(gpio); + } + + // clear the snapshot + clear_snapshot_gpios(); +} + +void System::clear_snapshot_gpios() { + snapshot_used_gpios_.clear(); + snapshot_valid_system_gpios_.clear(); +} + } // namespace emsesp diff --git a/src/core/system.h b/src/core/system.h index 5e6fbd779..91ee58722 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -37,6 +37,12 @@ #include #include +#if ESP_ARDUINO_VERSION_MAJOR < 3 +#define EMSESP_RGB_WRITE neopixelWrite +#else +#define EMSESP_RGB_WRITE rgbLedWrite +#endif + #if CONFIG_IDF_TARGET_ESP32 // there is no official API available on the original ESP32 extern "C" { @@ -56,7 +62,7 @@ using uuid::console::Shell; #define EMSESP_CUSTOMSUPPORT_FILE "/config/customSupport.json" -#define RGB_LED_BRIGHTNESS 20 +#define RGB_LED_BRIGHTNESS 20 // 255 is max brightness namespace emsesp { @@ -74,10 +80,16 @@ enum SYSTEM_STATUS : uint8_t { enum FUSE_VALUE : uint8_t { ALL = 0, MFG = 1, MODEL = 2, BOARD = 3, REV = 4, BATCH = 5, FUSE = 6 }; +struct PartitionInfo { + std::string version; + size_t size; + std::string install_date; // optional, only available if NTP is connected +}; + class System { public: void start(); - void loop(); + bool loop(); // returns true if the LED flash is active // commands static bool command_read(const char * value, const int8_t id); @@ -91,6 +103,7 @@ class System { static bool command_info(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_service(const char * cmd, const char * value); + static bool command_txpause(const char * value, const int8_t id); static bool get_value_info(JsonObject root, const char * cmd); static void get_value_json(JsonObject output, const std::string & circuit, const std::string & name, JsonVariant val); @@ -104,6 +117,7 @@ class System { void store_nvs_values(); void system_restart(const char * partition = nullptr); + void get_partition_info(); void show_mem(const char * note); void store_settings(class WebSettings & settings); @@ -145,9 +159,13 @@ class System { static void extractSettings(const char * filename, const char * section, JsonObject output); static bool saveSettings(const char * filename, const char * section, JsonObject input); + // GPIOs static bool add_gpio(uint8_t pin, const char * source_name); static std::vector available_gpios(); static bool load_board_profile(std::vector & data, const std::string & board_profile); + static void make_snapshot_gpios(); + static void restore_snapshot_gpios(); + static void clear_snapshot_gpios(); static bool readCommand(const char * data); @@ -301,7 +319,6 @@ class System { void show_system(uuid::console::Shell & shell); void show_users(uuid::console::Shell & shell); - void show_gpio(uuid::console::Shell & shell); void wifi_reconnect(); @@ -361,6 +378,11 @@ class System { static void remove_gpio(uint8_t pin, bool also_system = false); // remove a gpio from both valid (optional) and used lists + // Partition info map: partition name -> {version, size, install_date} + std::map, AllocatorPSRAM>> partition_info_; + + static bool set_partition(const char * partitionname); + private: static uuid::log::Logger logger_; @@ -370,16 +392,29 @@ class System { uint8_t systemStatus_; // uses SYSTEM_STATUS enum + void set_partition_install_date(bool override = false); + // button static PButton myPButton_; // PButton instance static void button_OnClick(PButton & b); static void button_OnDblClick(PButton & b); static void button_OnLongPress(PButton & b); static void button_OnVLongPress(PButton & b); - static constexpr uint32_t BUTTON_Debounce = 40; // Debounce period to prevent flickering when pressing or releasing the button (in ms) - static constexpr uint32_t BUTTON_DblClickDelay = 250; // Max period between clicks for a double click event (in ms) - static constexpr uint32_t BUTTON_LongPressDelay = 9500; // Hold period for a long press event (in ms) - 10 seconds - static constexpr uint32_t BUTTON_VLongPressDelay = 20000; // Hold period for a very long press event (in ms) - 20 seconds + static constexpr uint32_t BUTTON_Debounce = 40; // Debounce period to prevent flickering when pressing or releasing the button (in ms) + static constexpr uint32_t BUTTON_DblClickDelay = 250; // Max period between clicks for a double click event (in ms) + + // LED flash timer + static bool led_flash_timer_; + static uint8_t led_flash_gpio_; + static uint8_t led_flash_type_; + static uint32_t led_flash_start_time_; + static uint32_t led_flash_duration_; + static void start_led_flash(uint8_t duration); + static void led_flash(); + + // button press delays + static constexpr uint32_t BUTTON_LongPressDelay = 3000; // Hold period for a long press event (in ms) - ~3 seconds + static constexpr uint32_t BUTTON_VLongPressDelay = 9500; // Hold period for a very long press event (in ms) - !10 seconds // healthcheck #ifdef EMSESP_PINGTEST @@ -387,8 +422,8 @@ class System { #else static constexpr uint32_t SYSTEM_CHECK_FREQUENCY = 5000; // do a system check every 5 seconds #endif - static constexpr uint32_t HEALTHCHECK_LED_LONG_DUARATION = 1500; - static constexpr uint32_t HEALTHCHECK_LED_FLASH_DUARATION = 150; + static constexpr uint32_t HEALTHCHECK_LED_LONG_DUARATION = 1500; // 1.5 seconds + static constexpr uint32_t HEALTHCHECK_LED_FLASH_DUARATION = 150; // 150ms static constexpr uint8_t HEALTHCHECK_NO_BUS = (1 << 0); // 1 static constexpr uint8_t HEALTHCHECK_NO_NETWORK = (1 << 1); // 2 static constexpr uint8_t LED_ON = HIGH; // LED on @@ -402,8 +437,11 @@ class System { static std::vector> string_range_to_vector(const std::string & range); - static std::vector> valid_system_gpios_; // list of valid GPIOs for the ESP32 board that can be used - static std::vector> used_gpios_; // list of GPIOs used by the application + // GPIOs + static std::vector> valid_system_gpios_; // list of valid GPIOs for the ESP32 board that can be used + static std::vector> used_gpios_; // list of GPIOs used by the application + static std::vector> snapshot_used_gpios_; // snapshot of the used GPIOs + static std::vector> snapshot_valid_system_gpios_; // snapshot of the valid GPIOs int8_t wifi_quality(int8_t dBm); diff --git a/src/core/telegram.cpp b/src/core/telegram.cpp index 0f3298e46..5d6b5d797 100644 --- a/src/core/telegram.cpp +++ b/src/core/telegram.cpp @@ -146,7 +146,7 @@ void RxService::add(uint8_t * data, uint8_t length) { } // ignore src==0, https://github.com/emsesp/EMS-ESP32/issues/2378 - if (!(data[0] & 0x7F)) { + if (!(data[0] & 0x7F) && bus_connected()) { LOG_WARNING("Invalid source: %s", Helpers::data_to_hex(data, length).c_str()); // include CRC return; } @@ -272,8 +272,8 @@ void TxService::start() { // sends a 1 byte poll which is our own deviceID void TxService::send_poll() const { - //LOG_DEBUG("Ack %02X",ems_bus_id() ^ ems_mask()); - if (tx_mode()) { + // LOG_DEBUG("Ack %02X",ems_bus_id() ^ ems_mask()); + if (tx_mode() != EMS_TXMODE_OFF) { EMSuart::send_poll(ems_bus_id() ^ ems_mask()); } } @@ -309,7 +309,7 @@ void TxService::send() { delayed_send_ = 0; // if we're in read-only mode (tx_mode 0) forget the Tx call - if (tx_mode() != 0) { + if (tx_mode() != EMS_TXMODE_OFF) { send_telegram(tx_telegrams_.front()); } diff --git a/src/core/telegram.h b/src/core/telegram.h index b6baeae71..99390f826 100644 --- a/src/core/telegram.h +++ b/src/core/telegram.h @@ -204,7 +204,6 @@ class EMSbus { #endif } - // sets the flag for EMS bus connected static void last_bus_activity(uint32_t timestamp) { // record the first time we connected to the BUS, as this will be our uptime diff --git a/src/devices/connect.cpp b/src/devices/connect.cpp index 29bc56c6a..78c615187 100644 --- a/src/devices/connect.cpp +++ b/src/devices/connect.cpp @@ -81,11 +81,10 @@ void Connect::process_RCTime(std::shared_ptr telegram) { has_update(dateTime_, time, sizeof(dateTime_)); } -/* other values from 0x50 RF base -(0x087F), data: 00 00 -(0x0880), data: 01 04 -(0x0889), data: 00 80 80 01 -*/ +// other values from 0x50 RF base +// (0x087F), data: 00 00 +// (0x0880), data: 01 04 +// (0x0889), data: 00 80 80 01 void Connect::register_device_values_room(std::shared_ptr room) { auto tag = DeviceValueTAG::TAG_SRC1 + room->room(); register_device_value(tag, &room->temp_, DeviceValueType::INT16, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(roomTemp), DeviceValueUOM::DEGREES); diff --git a/src/devices/solar.cpp b/src/devices/solar.cpp index 95f8a2861..28ba574c4 100644 --- a/src/devices/solar.cpp +++ b/src/devices/solar.cpp @@ -563,21 +563,19 @@ void Solar::process_SM100Differential(std::shared_ptr telegram) has_update(telegram, diffControl_, 0); // is *10 } -/* process_SM100ParamCfg - type 0xF9 EMS 1.0 - * This telegram is used to inquire the min, default, max, and current values of a value that is usually read and written with another telegram ID - * The CS200 uses this method extensively to find out which values may be set in the SM100 - * e.g. B0 10 F9 00 FF 02 5A 03 17 00 00 00 14 00 00 00 3C 00 00 00 5A 00 00 00 59 29 - requested with 90 B0 F9 00 11 FF 02 5A 03 AF - * byte 0 = 0xFF - * byte 1-2 = telegram ID used to write this value - * byte 3 = offset in telegram used to write this value - * byte 4 = unknown - * bytes 5..8 = minimum value - * bytes 9..12 = default value - * bytes 13..16 = maximum value - * bytes 17..20 = current value - * - * e.g. B0 0B F9 00 00 02 5A 00 00 6E - */ +// process_SM100ParamCfg - type 0xF9 EMS 1.0 +// This telegram is used to inquire the min, default, max, and current values of a value that is usually read and written with another telegram ID +// The CS200 uses this method extensively to find out which values may be set in the SM100 +// e.g. B0 10 F9 00 FF 02 5A 03 17 00 00 00 14 00 00 00 3C 00 00 00 5A 00 00 00 59 29 - requested with 90 B0 F9 00 11 FF 02 5A 03 AF +// byte 0 = 0xFF +// byte 1-2 = telegram ID used to write this value +// byte 3 = offset in telegram used to write this value +// byte 4 = unknown +// bytes 5..8 = minimum value +// bytes 9..12 = default value +// bytes 13..16 = maximum value +// bytes 17..20 = current value +// e.g. B0 0B F9 00 00 02 5A 00 00 6E void Solar::process_SM100ParamCfg(std::shared_ptr telegram) { uint16_t t_id = EMS_VALUE_UINT16_NOTSET; uint8_t of = EMS_VALUE_UINT8_NOTSET; diff --git a/src/devices/ventilation.h b/src/devices/ventilation.h index 9421f85c9..21a3ee028 100644 --- a/src/devices/ventilation.h +++ b/src/devices/ventilation.h @@ -51,68 +51,6 @@ class Ventilation : public EMSdevice { bool set_ventMode(const char * value, const int8_t id); bool set_bypass(const char * value, const int8_t id); bool set_filter(const char * value, const int8_t id); - - - /* Sensors: - outdoor air temp (außenluft) - supply air temp (zuluft) - extract air temp (abluft) - away air temp (fortluft) - supply blower (zuluftgebläse) - supply blower mod (zuluftebläse drehzahl) - away blower (abluftgebläse) - away blower mod (abluftgebläse drehzahl) - Anschlussvariante - el. vorheizer - ext. el. vorheizreg. - nachheiz zulufttemp - mischer öffnen - mischer schließen - mischerposition - zuluft temp soll - zuluft temp ist - leistung nachheizreg. - erdwärmetauscher klappe - solekreispumpe - abluftfeuchte - abluftqualität - raumluftfechte - raumluftqualität - luftfeuchte fernbed. 1..4 - */ - /* Parameters: - Gerätetyp, - Nennvolumentstrom, - Filterlaufzeit 1-6-12 m - Filterwechsel confirm CMD - Lüftungsfrostschutz: _el._preheat_, Disballance | Interval - Ext. Frostschutz: on/_off_ - Bypass _on_, off - min. outdoortemp 12 15 19 °C - max. outdoortemp 21-24-30 C - Enthalpie Wärmetauscher instaliert nein-ja - Feuchteschutz AUs/ 1-24 h - Lüfterstufe 1-4, Drehzahlanpassung - ext. Luftfeuchtefühler inst.? _nein_, ja - Abluftfeuchtefühler inst.? _nein_, ja - Luftfeuchte Fernbed. _nein_, ja - Luftfeuchte: trocken, _normal_, feucht - Abluftqualitätsfühler inst. _ja_, nein - ext. Luftqualfühl? _nein_, ja - Lufqualität: ausreichend, _normal_, hoch - el. Nachheizregister inst. _nein_, ja - Nachheiz-Zuluft temp: 10-22-30 °C - Erdwärmetauscher inst? _nein_, Luft, Sole - Taster Funktion: nein, einschlafen, intensiv, bypass, party, kamin - ext. Störung aktivieren: _nein_, ja, invertiert - Dauer einschlafen: 15-60-120 min - Dauer Intensiv: 5-15-60 min - Dauer Bypass Abluft: 1-8-12 h - Dauer Bypass: 1-8-12 h - Dauer PArty 1-8-12 h - Dauer Kamin: 5-10-15 min - Volumenstromabgleich 90-100-110 % - */ }; } // namespace emsesp diff --git a/src/emsesp_version.h b/src/emsesp_version.h index 6de79fa7e..6c48997c1 100644 --- a/src/emsesp_version.h +++ b/src/emsesp_version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.7.3-dev.39" +#define EMSESP_APP_VERSION "3.8.0-dev.0" diff --git a/src/test/test.cpp b/src/test/test.cpp index 73324533d..3681fef2a 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -1334,7 +1334,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // log shows first if you can upgrade to dev, and then if you can upgrade to stable // request.url("/rest/action"); // std::string LATEST_STABLE_VERSION = "3.7.2"; - // std::string LATEST_DEV_VERSION = "3.7.3-dev.3"; + // std::string LATEST_DEV_VERSION = "3.8.0-dev.3"; // std::string param = LATEST_DEV_VERSION + "," + LATEST_STABLE_VERSION; // std::string action = "{\"action\":\"checkUpgrade\", \"param\":\"" + param + "\"}"; // deserializeJson(doc, action); @@ -1352,7 +1352,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // EMSESP::webStatusService.action(&request, doc.as()); // // case 3: upgrade an older dev to latest dev, no stable upgrades available. So true, false - // EMSESP::webStatusService.set_current_version("3.7.3-dev.2"); + // EMSESP::webStatusService.set_current_version("3.8.0-dev.2"); // EMSESP::webStatusService.action(&request, doc.as()); // char data6[] = "{\"device\":\"system\", \"cmd\":\"read\",\"value\":\"8 2 27 1\"}"; diff --git a/src/uart/emsuart_esp32.cpp b/src/uart/emsuart_esp32.cpp index f4f0e0d17..3e1659e09 100644 --- a/src/uart/emsuart_esp32.cpp +++ b/src/uart/emsuart_esp32.cpp @@ -16,9 +16,7 @@ * along with this program. If not, see . */ -/* - * ESP32 UART port by @ArwedL and improved by @MichaelDvP. See https://github.com/emsesp/EMS-ESP/issues/380 - */ +// ESP32 UART port by @ArwedL and improved by @MichaelDvP. See https://github.com/emsesp/EMS-ESP/issues/380 #ifndef EMSESP_STANDALONE @@ -35,12 +33,10 @@ uint8_t EMSuart::last_tx_src_ = 0; static TaskHandle_t xHandle; static QueueHandle_t uart_queue; -uint8_t tx_mode_ = 0xFF; +uint8_t tx_mode_ = EMS_TXMODE_INIT; uint32_t inverse_mask = 0; -/* -* receive task, wait for break and call incoming_telegram -*/ +// receive task, wait for break and call incoming_telegram void EMSuart::uart_event_task(void * pvParameters) { uart_event_t event; uint8_t telegram[EMS_MAXBUFFERSIZE]; @@ -69,11 +65,9 @@ void EMSuart::uart_event_task(void * pvParameters) { vTaskDelete(NULL); } -/* - * init UART driver - */ +// initialize UART driver void EMSuart::start(const uint8_t tx_mode, const uint8_t rx_gpio, const uint8_t tx_gpio) { - if (tx_mode_ == 0xFF) { + if (tx_mode_ == EMS_TXMODE_INIT) { uart_config_t uart_config = {.baud_rate = EMSUART_BAUD, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, @@ -113,19 +107,15 @@ void EMSuart::start(const uint8_t tx_mode, const uint8_t rx_gpio, const uint8_t uart_enable_intr_mask(EMSUART_NUM, UART_BRK_DET_INT_ENA | UART_RXFIFO_FULL_INT_ENA); } -/* - * Stop, disable interrupt - */ +// Stop, disable interrupt void EMSuart::stop() { - if (tx_mode_ != 0xFF) { // only call after driver initialisation + if (tx_mode_ != EMS_TXMODE_INIT) { // only call after driver initialisation uart_disable_intr_mask(EMSUART_NUM, UART_BRK_DET_INT_ENA | UART_RXFIFO_FULL_INT_ENA); vTaskSuspend(xHandle); } }; -/* - * generate by inverting tx - */ +// generate by inverting tx void IRAM_ATTR EMSuart::uart_gen_break(uint32_t length_us) { portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; portENTER_CRITICAL(&mux); @@ -135,35 +125,34 @@ void IRAM_ATTR EMSuart::uart_gen_break(uint32_t length_us) { portEXIT_CRITICAL(&mux); } -/* - * Sends a 1-byte poll, ending with a - */ +// Sends a 1-byte poll, ending with a void EMSuart::send_poll(const uint8_t data) { transmit(&data, 1); } -/* - * Send data to Tx line, ending with a - * buf contains the CRC and len is #bytes including the CRC - * returns code, 1=success - */ +// Send data to Tx line, ending with a +// buf contains the CRC and len is #bytes including the CRC +// returns code, 1=success uint8_t EMSuart::transmit(const uint8_t * buf, const uint8_t len) { if (len == 0 || len >= EMS_MAXBUFFERSIZE) { return EMS_TX_STATUS_ERR; } - if (tx_mode_ == 0) { + // TXMODE is OFF + if (tx_mode_ == EMS_TXMODE_OFF) { return EMS_TX_STATUS_OK; } - last_tx_src_ = len < 4 ? 0 : buf[0]; + last_tx_src_ = len < 4 ? 0 : buf[0]; // update last tx source - if (tx_mode_ == EMS_TXMODE_HW) { // hardware controlled mode + // TXMODE is hardware controlled mode + if (tx_mode_ == EMS_TXMODE_HW) { uart_write_bytes_with_break(EMSUART_NUM, buf, len, 10); return EMS_TX_STATUS_OK; } - if (tx_mode_ == EMS_TXMODE_EMSPLUS) { // EMS+ with long delay + // TXMODE is EMS+ with long delay + if (tx_mode_ == EMS_TXMODE_EMSPLUS) { for (uint8_t i = 0; i < len; i++) { uart_write_bytes(EMSUART_NUM, &buf[i], 1); delayMicroseconds(EMSUART_TX_WAIT_PLUS); @@ -172,7 +161,8 @@ uint8_t EMSuart::transmit(const uint8_t * buf, const uint8_t len) { return EMS_TX_STATUS_OK; } - if (tx_mode_ == EMS_TXMODE_HT3) { // HT3 with 7 bittimes delay + // TXMODE is HT3 with 7 bittimes delay + if (tx_mode_ == EMS_TXMODE_HT3) { for (uint8_t i = 0; i < len; i++) { uart_write_bytes(EMSUART_NUM, &buf[i], 1); delayMicroseconds(EMSUART_TX_WAIT_HT3); @@ -181,7 +171,7 @@ uint8_t EMSuart::transmit(const uint8_t * buf, const uint8_t len) { return EMS_TX_STATUS_OK; } - // mode 1: wait for echo after each byte + // TXMODE default: wait for echo after each byte for (uint8_t i = 0; i < len; i++) { size_t rx0, rx1; uart_get_buffered_data_len(EMSUART_NUM, &rx0); diff --git a/src/uart/emsuart_esp32.h b/src/uart/emsuart_esp32.h index 6a6f2f2d1..d0727f3ee 100644 --- a/src/uart/emsuart_esp32.h +++ b/src/uart/emsuart_esp32.h @@ -40,6 +40,8 @@ #define EMSUART_NUM UART_NUM_1 // on C3 and S2 there is no UART2, use UART1 for all #define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit +#define EMS_TXMODE_INIT 0xFF +#define EMS_TXMODE_OFF 0 #define EMS_TXMODE_DEFAULT 1 #define EMS_TXMODE_EMSPLUS 2 #define EMS_TXMODE_HT3 3 diff --git a/src/web/WebCustomEntityService.cpp b/src/web/WebCustomEntityService.cpp index dcb3ff23b..2b25953c4 100644 --- a/src/web/WebCustomEntityService.cpp +++ b/src/web/WebCustomEntityService.cpp @@ -352,8 +352,8 @@ void WebCustomEntityService::get_value_json(JsonObject output, CustomEntityItem } } - // add uom state class and device class - Mqtt::add_ha_classes(output, EMSdevice::DeviceType::SYSTEM, entity.value_type, entity.uom, nullptr, false); + // add uom state class and device class to output json, excluding icon + Mqtt::add_ha_classes(output, EMSdevice::DeviceType::SYSTEM, entity.value_type, entity.uom, nullptr, true); // display only render_value(output, entity, true); // create the "value" field } diff --git a/src/web/WebSettingsService.cpp b/src/web/WebSettingsService.cpp index 934b62b3c..3564feeda 100644 --- a/src/web/WebSettingsService.cpp +++ b/src/web/WebSettingsService.cpp @@ -91,6 +91,9 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { // make a copy of the settings to compare to later const WebSettings original_settings(settings); + // make a snapshot of the current GPIOs + EMSESP::system_.make_snapshot_gpios(); + reset_flags(); settings.version = root["version"] | EMSESP_DEFAULT_VERSION; // save the version, we use it later in System::check_upgrade() @@ -147,8 +150,6 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { EMSESP::system_.remove_gpio(1, true); EMSESP::system_.remove_gpio(3, true); #endif - // if any of the GPIOs have changed and re-validate them - bool have_valid_gpios = true; // free old gpios from used list to allow remapping EMSESP::system_.remove_gpio(original_settings.led_gpio); @@ -157,27 +158,32 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { EMSESP::system_.remove_gpio(original_settings.rx_gpio); EMSESP::system_.remove_gpio(original_settings.tx_gpio); - // now add new gpio assignment, start with rx/tx + // if any of the GPIOs have changed and re-validate them + bool have_valid_gpios = true; + + // Helper lambda for optional GPIOs (can be 0 to disable) + auto add_optional_gpio = [&have_valid_gpios](uint8_t & gpio, const char * name) { + if (gpio != 0 && !EMSESP::system_.add_gpio(gpio, name)) { + gpio = 0; // 0 means disabled + have_valid_gpios = false; + } + }; + + // add new gpio assignment check_flag(original_settings.rx_gpio, settings.rx_gpio, ChangeFlags::UART); - have_valid_gpios = have_valid_gpios && EMSESP::system_.add_gpio(settings.rx_gpio, "UART Rx"); + have_valid_gpios &= EMSESP::system_.add_gpio(settings.rx_gpio, "UART Rx"); check_flag(original_settings.tx_gpio, settings.tx_gpio, ChangeFlags::UART); - have_valid_gpios = have_valid_gpios && EMSESP::system_.add_gpio(settings.tx_gpio, "UART Tx"); + have_valid_gpios &= EMSESP::system_.add_gpio(settings.tx_gpio, "UART Tx"); check_flag(original_settings.led_gpio, settings.led_gpio, ChangeFlags::LED); - if (settings.led_gpio != 0 && !EMSESP::system_.add_gpio(settings.led_gpio, "LED")) { - settings.led_gpio = 0; // 0 means disabled - have_valid_gpios = false; - } + add_optional_gpio(settings.led_gpio, "LED"); check_flag(original_settings.dallas_gpio, settings.dallas_gpio, ChangeFlags::TEMPERATURE_SENSOR); - if (settings.dallas_gpio != 0 && !EMSESP::system_.add_gpio(settings.dallas_gpio, "Dallas")) { - settings.dallas_gpio = 0; // 0 means disabled - have_valid_gpios = false; - } + add_optional_gpio(settings.dallas_gpio, "Dallas"); check_flag(original_settings.pbutton_gpio, settings.pbutton_gpio, ChangeFlags::BUTTON); - have_valid_gpios = have_valid_gpios && EMSESP::system_.add_gpio(settings.pbutton_gpio, "Button"); + have_valid_gpios &= EMSESP::system_.add_gpio(settings.pbutton_gpio, "Button"); // check if the LED type, eth_phy_addr or eth_clock_mode have changed check_flag(original_settings.led_type, settings.led_type, ChangeFlags::LED); @@ -303,19 +309,25 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { settings.weblog_buffer = root["weblog_buffer"] | 25; // limit to 25 messages if no psram } + // save the settings if changed from the webUI + // if we encountered an invalid GPIO, rollback changes and don't save settings, and report the error to WebUI + if (!have_valid_gpios) { + // replace settings with original settings + settings = original_settings; // the original settings are still valid + // restore the GPIOs from the snapshot + EMSESP::system_.restore_snapshot_gpios(); + + // report the error to WebUI + EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_INVALID_GPIO); + return StateUpdateResult::ERROR; // don't save the settings if the GPIOs are invalid + } + + // clean up snapshot of the GPIOs + EMSESP::system_.clear_snapshot_gpios(); + // save the setting internally, for reference later EMSESP::system_.store_settings(settings); - // save the settings if changed from the webUI - // if we encountered an invalid GPIO, don't save settings and report the error - if (!have_valid_gpios) { -#if defined(EMSESP_DEBUG) - EMSESP::logger().debug("Warning: one or more GPIOs are invalid"); -#endif - EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_INVALID_GPIO); - return StateUpdateResult::CHANGED; // save the settings anyway, without restart - } - if (has_flags(WebSettings::ChangeFlags::RESTART)) { return StateUpdateResult::CHANGED_RESTART; } @@ -503,7 +515,6 @@ void WebSettings::set_board_profile(WebSettings & settings) { settings.led_type = data[9]; // LED Type } - // returns true if the value was changed bool WebSettings::check_flag(int prev_v, int new_v, uint8_t flag) { if (prev_v != new_v) { diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp index e8d2a565b..48680e915 100644 --- a/src/web/WebStatusService.cpp +++ b/src/web/WebStatusService.cpp @@ -146,6 +146,23 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) { root["has_partition"] = false; } + // get the partition info for each partition, including the running one + // the partition data is done once in System::start() and stored in partition_info_ + JsonArray partitions = root["partitions"].to(); + for (const auto & partition : EMSESP::system_.partition_info_) { + // Skip partition if it has no version, or it's size is 0 + if (partition.second.version.empty() || partition.second.size == 0) { + continue; + } + JsonObject part = partitions.add(); + part["partition"] = partition.first; + part["version"] = partition.second.version; + part["size"] = partition.second.size; + part["install_date"] = partition.second.install_date; + } + + root["developer_mode"] = EMSESP::system_.developer_mode(); + // Also used in SystemMonitor.tsx root["status"] = EMSESP::system_.systemStatus(); // send the status. See System.h for status codes if (EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_PENDING_RESTART) { @@ -185,6 +202,8 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json) if (action == "checkUpgrade") { ok = checkUpgrade(root, param); // param could be empty, if so only send back version + } else if (action == "setPartition") { + ok = EMSESP::system_.set_partition(param.c_str()); } else if (action == "export") { if (has_param) { ok = exportData(root, param); diff --git a/test/test_api/api_test.http b/test/test_api/api_test.http index 320779672..1a37372bc 100755 --- a/test/test_api/api_test.http +++ b/test/test_api/api_test.http @@ -4,8 +4,8 @@ # The response will be shown in the right panel # @host = http://ems-esp.local -@host = http://192.168.1.65 -@host_dev = http://192.168.1.223 +@host = http://192.168.1.223 +@host_dev = http://192.168.1.65 @host_standalone = http://localhost:3080 @host_standalone2 = http://localhost:3082 @@ -145,6 +145,30 @@ Authorization: Bearer {{token}} ### +POST {{host_dev}}/api/system/txpause +Content-Type: application/json +Authorization: Bearer {{token}} + +{ + "value" : "on" +} + +### + +POST {{host_dev}}/api/system/txpause +Content-Type: application/json +Authorization: Bearer {{token}} + +{ + "value" : "off" +} + +### + +GET {{host_dev}}/api/system/settings/txMode/value + +### + GET {{host_dev}}/api/system/settings/locale/value ###