mirror of
https://github.com/adrianjagielak/home-assistant-futurehome.git
synced 2025-09-13 15:47:08 +00:00
Add support for pairing new devices
This commit is contained in:
parent
15c65850bf
commit
b034197a93
15
README.md
15
README.md
@ -12,15 +12,19 @@ This add-on:
|
|||||||
* Fetches all device metadata from the Futurehome hub and maps them to Home Assistant devices/entities.
|
* Fetches all device metadata from the Futurehome hub and maps them to Home Assistant devices/entities.
|
||||||
* Fetches and updates device states and availability in real time.
|
* Fetches and updates device states and availability in real time.
|
||||||
* Supports interaction with devices comparable to the official Futurehome app.
|
* Supports interaction with devices comparable to the official Futurehome app.
|
||||||
|
* Supports pairing and unpairing of devices.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
todo: rewrite the installation instructions
|
||||||
|
|
||||||
1. In the Futurehome app, go to Settings > My household > Smarthub and enable Local API.
|
1. In the Futurehome app, go to Settings > My household > Smarthub and enable Local API.
|
||||||
2. (Optional but highly recommended) Block the hub’s internet (WAN) access in your router settings to prevent future firmware updates.
|
2. (Optional) In the Futurehome app go to Settings > ??? > ??? and install Thingsplex integration (Needed for support of pairing new devices).
|
||||||
3. In Home Assistant, enable the **MQTT** integration.
|
3. (Optional but highly recommended) Block the hub’s internet (WAN) access in your router settings to prevent future firmware updates.
|
||||||
4. [Add this add-on repository to Home Assistant](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Fadrianjagielak%2Fhome-assistant-futurehome) and refresh the page.
|
4. In Home Assistant, enable the **MQTT** integration.
|
||||||
5. Open the **Add-on Store** and search for "Futurehome".
|
5. [Add this add-on repository to Home Assistant](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Fadrianjagielak%2Fhome-assistant-futurehome) and refresh the page.
|
||||||
6. Install, configure, and start the Futurehome add-on.
|
6. Open the **Add-on Store** and search for "Futurehome".
|
||||||
|
7. Install, configure, and start the Futurehome add-on.
|
||||||
|
|
||||||
# Futurehome Device Services Compatibility Chart
|
# Futurehome Device Services Compatibility Chart
|
||||||
|
|
||||||
@ -31,7 +35,6 @@ Devices commonly consist of multiple services: for example, a presence sensor mi
|
|||||||
Some services are more common than others; some are deprecated entirely.
|
Some services are more common than others; some are deprecated entirely.
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
todo: pairing
|
|
||||||
todo add info about factory reset hub to restore 30 day trial
|
todo add info about factory reset hub to restore 30 day trial
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
## 0.1.8 (28.07.2025)
|
## 0.1.8 (28.07.2025)
|
||||||
|
|
||||||
- Added logo.
|
- Added logo.
|
||||||
|
- Added support for pairing new devices.
|
||||||
|
|
||||||
## 0.1.7 (26.07.2025)
|
## 0.1.7 (26.07.2025)
|
||||||
|
|
||||||
|
@ -11,15 +11,19 @@ This add-on:
|
|||||||
* Fetches all device metadata from the Futurehome hub and maps them to Home Assistant devices/entities.
|
* Fetches all device metadata from the Futurehome hub and maps them to Home Assistant devices/entities.
|
||||||
* Fetches and updates device states and availability in real time.
|
* Fetches and updates device states and availability in real time.
|
||||||
* Supports interaction with devices comparable to the official Futurehome app.
|
* Supports interaction with devices comparable to the official Futurehome app.
|
||||||
|
* Supports pairing and unpairing of devices.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
todo: rewrite the installation instructions
|
||||||
|
|
||||||
1. In the Futurehome app, go to Settings > My household > Smarthub and enable Local API.
|
1. In the Futurehome app, go to Settings > My household > Smarthub and enable Local API.
|
||||||
2. (Optional but highly recommended) Block the hub’s internet (WAN) access in your router settings to prevent future firmware updates.
|
2. (Optional) In the Futurehome app go to Settings > ??? > ??? and install Thingsplex integration (Needed for support of pairing new devices).
|
||||||
3. In Home Assistant, enable the **MQTT** integration.
|
3. (Optional but highly recommended) Block the hub’s internet (WAN) access in your router settings to prevent future firmware updates.
|
||||||
4. [Add this add-on repository to Home Assistant](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Fadrianjagielak%2Fhome-assistant-futurehome) and refresh the page.
|
4. In Home Assistant, enable the **MQTT** integration.
|
||||||
5. Open the **Add-on Store** and search for "Futurehome".
|
5. [Add this add-on repository to Home Assistant](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Fadrianjagielak%2Fhome-assistant-futurehome) and refresh the page.
|
||||||
6. Install, configure, and start the Futurehome add-on.
|
6. Open the **Add-on Store** and search for "Futurehome".
|
||||||
|
7. Install, configure, and start the Futurehome add-on.
|
||||||
|
|
||||||
# Futurehome Device Services Compatibility Chart
|
# Futurehome Device Services Compatibility Chart
|
||||||
|
|
||||||
@ -30,7 +34,6 @@ Devices commonly consist of multiple services: for example, a presence sensor mi
|
|||||||
Some services are more common than others; some are deprecated entirely.
|
Some services are more common than others; some are deprecated entirely.
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
todo: pairing
|
|
||||||
todo add info about factory reset hub to restore 30 day trial
|
todo add info about factory reset hub to restore 30 day trial
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config
|
# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config
|
||||||
name: Futurehome
|
name: Futurehome
|
||||||
version: "0.1.8"
|
version: '0.1.8'
|
||||||
slug: futurehome
|
slug: futurehome
|
||||||
description: Local Futurehome Smarthub integration
|
description: Local Futurehome Smarthub integration
|
||||||
url: "https://github.com/adrianjagielak/home-assistant-futurehome"
|
url: 'https://github.com/adrianjagielak/home-assistant-futurehome'
|
||||||
arch:
|
arch:
|
||||||
- armhf
|
- armhf
|
||||||
- armv7
|
- armv7
|
||||||
@ -13,20 +13,24 @@ arch:
|
|||||||
init: false
|
init: false
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- "mqtt:need"
|
- 'mqtt:need'
|
||||||
|
|
||||||
options:
|
options:
|
||||||
hub_ip: ""
|
hub_ip: ''
|
||||||
username: ""
|
fh_username: ''
|
||||||
password: ""
|
fh_password: ''
|
||||||
|
tp_username: ''
|
||||||
|
tp_password: ''
|
||||||
demo_mode: false
|
demo_mode: false
|
||||||
show_debug_log: false
|
show_debug_log: false
|
||||||
|
|
||||||
schema:
|
schema:
|
||||||
hub_ip: "str?"
|
hub_ip: 'str?'
|
||||||
username: "str?"
|
fh_username: 'str?'
|
||||||
password: "str?"
|
fh_password: 'str?'
|
||||||
demo_mode: "bool?"
|
tp_username: 'str?'
|
||||||
show_debug_log: "bool?"
|
tp_password: 'str?'
|
||||||
|
demo_mode: 'bool?'
|
||||||
|
show_debug_log: 'bool?'
|
||||||
|
|
||||||
image: "ghcr.io/adrianjagielak/{arch}-home-assistant-futurehome"
|
image: 'ghcr.io/adrianjagielak/{arch}-home-assistant-futurehome'
|
||||||
|
284
futurehome/package-lock.json
generated
284
futurehome/package-lock.json
generated
@ -9,12 +9,15 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"axios": "^1.11.0",
|
||||||
"mqtt": "^5.13.3",
|
"mqtt": "^5.13.3",
|
||||||
"uuid": "^11.1.0"
|
"uuid": "^11.1.0",
|
||||||
|
"ws": "^8.18.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.31.0",
|
"@eslint/js": "^9.31.0",
|
||||||
"@types/node": "^24.0.15",
|
"@types/node": "^24.0.15",
|
||||||
|
"@types/ws": "^8.18.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
||||||
"@typescript-eslint/parser": "^8.38.0",
|
"@typescript-eslint/parser": "^8.38.0",
|
||||||
"eslint": "^9.31.0",
|
"eslint": "^9.31.0",
|
||||||
@ -742,6 +745,23 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Python-2.0"
|
"license": "Python-2.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/axios": {
|
||||||
|
"version": "1.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz",
|
||||||
|
"integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"follow-redirects": "^1.15.6",
|
||||||
|
"form-data": "^4.0.4",
|
||||||
|
"proxy-from-env": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
@ -835,6 +855,19 @@
|
|||||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/call-bind-apply-helpers": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/callsites": {
|
"node_modules/callsites": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||||
@ -898,6 +931,18 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/commist": {
|
"node_modules/commist": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz",
|
||||||
@ -979,6 +1024,29 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/dunder-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.1",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"gopd": "^1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eastasianwidth": {
|
"node_modules/eastasianwidth": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||||
@ -993,6 +1061,51 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/es-define-property": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-errors": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-object-atoms": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-set-tostringtag": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"get-intrinsic": "^1.2.6",
|
||||||
|
"has-tostringtag": "^1.0.2",
|
||||||
|
"hasown": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/escape-string-regexp": {
|
"node_modules/escape-string-regexp": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||||
@ -1330,6 +1443,26 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/follow-redirects": {
|
||||||
|
"version": "1.15.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||||
|
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"debug": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/foreground-child": {
|
"node_modules/foreground-child": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
|
||||||
@ -1347,6 +1480,68 @@
|
|||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/form-data": {
|
||||||
|
"version": "4.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||||
|
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"es-set-tostringtag": "^2.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/function-bind": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-intrinsic": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.2",
|
||||||
|
"es-define-property": "^1.0.1",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"es-object-atoms": "^1.1.1",
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"get-proto": "^1.0.1",
|
||||||
|
"gopd": "^1.2.0",
|
||||||
|
"has-symbols": "^1.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"math-intrinsics": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"dunder-proto": "^1.0.1",
|
||||||
|
"es-object-atoms": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/glob": {
|
"node_modules/glob": {
|
||||||
"version": "11.0.3",
|
"version": "11.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz",
|
||||||
@ -1397,6 +1592,18 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/gopd": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/graphemer": {
|
"node_modules/graphemer": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||||
@ -1414,6 +1621,45 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/has-symbols": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-tostringtag": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-symbols": "^1.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hasown": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/help-me": {
|
"node_modules/help-me": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz",
|
||||||
@ -1665,6 +1911,15 @@
|
|||||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/math-intrinsics": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/merge2": {
|
"node_modules/merge2": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||||
@ -1689,6 +1944,27 @@
|
|||||||
"node": ">=8.6"
|
"node": ">=8.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mime-db": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-types": {
|
||||||
|
"version": "2.1.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": "1.52.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "10.0.3",
|
"version": "10.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz",
|
||||||
@ -1945,6 +2221,12 @@
|
|||||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/proxy-from-env": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/punycode": {
|
"node_modules/punycode": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
|
@ -9,12 +9,15 @@
|
|||||||
"start": "node dist/index.js"
|
"start": "node dist/index.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"axios": "^1.11.0",
|
||||||
"mqtt": "^5.13.3",
|
"mqtt": "^5.13.3",
|
||||||
"uuid": "^11.1.0"
|
"uuid": "^11.1.0",
|
||||||
|
"ws": "^8.18.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.31.0",
|
"@eslint/js": "^9.31.0",
|
||||||
"@types/node": "^24.0.15",
|
"@types/node": "^24.0.15",
|
||||||
|
"@types/ws": "^8.18.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
||||||
"@typescript-eslint/parser": "^8.38.0",
|
"@typescript-eslint/parser": "^8.38.0",
|
||||||
"eslint": "^9.31.0",
|
"eslint": "^9.31.0",
|
||||||
|
@ -6,8 +6,10 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
export FH_HUB_IP=$(bashio::config 'hub_ip')
|
export FH_HUB_IP=$(bashio::config 'hub_ip')
|
||||||
export FH_USERNAME=$(bashio::config 'username')
|
export FH_USERNAME=$(bashio::config 'fh_username')
|
||||||
export FH_PASSWORD=$(bashio::config 'password')
|
export FH_PASSWORD=$(bashio::config 'fh_password')
|
||||||
|
export TP_USERNAME=$(bashio::config 'tp_username')
|
||||||
|
export TP_PASSWORD=$(bashio::config 'tp_password')
|
||||||
export DEMO_MODE=$(bashio::config 'demo_mode')
|
export DEMO_MODE=$(bashio::config 'demo_mode')
|
||||||
export SHOW_DEBUG_LOG=$(bashio::config 'show_debug_log')
|
export SHOW_DEBUG_LOG=$(bashio::config 'show_debug_log')
|
||||||
|
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
import { v4 as uuidv4 } from 'uuid';
|
|
||||||
import { IMqttClient } from './mqtt/interface';
|
|
||||||
|
|
||||||
export function exposeSmarthubTools(
|
|
||||||
ha: IMqttClient,
|
|
||||||
fimp: IMqttClient,
|
|
||||||
hubAddr = 'pt:j1/mt:cmd/rt:app/rn:zb/ad:1',
|
|
||||||
) {
|
|
||||||
const base = 'homeassistant/switch/fh_zb_pairing';
|
|
||||||
const device = {
|
|
||||||
identifiers: ['futurehome_hub'],
|
|
||||||
name: 'Futurehome Hub',
|
|
||||||
model: 'Smarthub',
|
|
||||||
};
|
|
||||||
|
|
||||||
ha.publish(
|
|
||||||
`${base}/config`,
|
|
||||||
JSON.stringify({
|
|
||||||
name: 'Zigbee Pairing',
|
|
||||||
uniq_id: 'fh_zb_pairing',
|
|
||||||
cmd_t: `${base}/set`,
|
|
||||||
stat_t: `${base}/state`,
|
|
||||||
device,
|
|
||||||
}),
|
|
||||||
{ retain: true, qos: 2 },
|
|
||||||
);
|
|
||||||
|
|
||||||
// // keep last known state locally
|
|
||||||
// let pairingOn = false;
|
|
||||||
|
|
||||||
ha.subscribe(`${base}/set`);
|
|
||||||
ha.on('message', (topic, payload) => {
|
|
||||||
if (topic !== `${base}/set`) return;
|
|
||||||
const turnOn = payload.toString() === 'ON';
|
|
||||||
|
|
||||||
// // optimistic update so the UI flips instantly
|
|
||||||
// pairingOn = turnOn;
|
|
||||||
ha.publish(`${base}/state`, turnOn ? 'ON' : 'OFF', {
|
|
||||||
retain: true,
|
|
||||||
qos: 2,
|
|
||||||
});
|
|
||||||
|
|
||||||
// placeholder FIMP message – adjust to real API if different
|
|
||||||
fimp.publish(
|
|
||||||
hubAddr,
|
|
||||||
JSON.stringify({
|
|
||||||
type: 'cmd.pairing_mode.set',
|
|
||||||
service: 'zigbee',
|
|
||||||
uid: uuidv4(),
|
|
||||||
val_t: 'str',
|
|
||||||
val: turnOn ? 'start' : 'stop',
|
|
||||||
}),
|
|
||||||
{ qos: 1 },
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// (optional) listen for hub-side confirmation and correct state here
|
|
||||||
}
|
|
@ -21,7 +21,7 @@ export type FimpResponse = {
|
|||||||
ver?: any;
|
ver?: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
type FimpValueType =
|
export type FimpValueType =
|
||||||
| 'string'
|
| 'string'
|
||||||
| 'int'
|
| 'int'
|
||||||
| 'float'
|
| 'float'
|
||||||
@ -51,7 +51,7 @@ export async function sendFimpMsg({
|
|||||||
cmd: string;
|
cmd: string;
|
||||||
val: unknown;
|
val: unknown;
|
||||||
val_t: FimpValueType;
|
val_t: FimpValueType;
|
||||||
props?: any;
|
props?: Record<string, any>;
|
||||||
timeoutMs?: number;
|
timeoutMs?: number;
|
||||||
}): Promise<FimpResponse> {
|
}): Promise<FimpResponse> {
|
||||||
const uid = uuidv4();
|
const uid = uuidv4();
|
||||||
@ -60,9 +60,9 @@ export async function sendFimpMsg({
|
|||||||
corid: null,
|
corid: null,
|
||||||
ctime: new Date().toISOString(),
|
ctime: new Date().toISOString(),
|
||||||
props: props,
|
props: props,
|
||||||
resp_to: 'pt:j1/mt:rsp/rt:app/rn:ha-futurehome/ad:addon',
|
resp_to: 'pt:j1/mt:rsp/rt:cloud/rn:remote-client/ad:smarthome-app',
|
||||||
serv: service,
|
serv: service,
|
||||||
src: 'ha-futurehome',
|
src: 'smarthome-app',
|
||||||
tags: [],
|
tags: [],
|
||||||
type: cmd,
|
type: cmd,
|
||||||
uid: uid,
|
uid: uid,
|
||||||
@ -165,7 +165,7 @@ service: "${service}",
|
|||||||
uid: "${uid}",
|
uid: "${uid}",
|
||||||
cmd: "${cmd}",
|
cmd: "${cmd}",
|
||||||
val: ${JSON.stringify(val)},
|
val: ${JSON.stringify(val)},
|
||||||
val_t: "${val_t}"
|
val_t: "${val_t}"${Object.entries(props).length > 0 ? `\nprops: ${JSON.stringify(props)}` : ''}${timeoutMs != 10000 ? `\ntimeoutMs: ${timeoutMs}` : ''}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
fimp?.publish(topic, message, { qos: 1 });
|
fimp?.publish(topic, message, { qos: 1 });
|
||||||
|
14
futurehome/src/fimp/vinculum.ts
Normal file
14
futurehome/src/fimp/vinculum.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { FimpResponse, sendFimpMsg } from './fimp';
|
||||||
|
|
||||||
|
export async function pollVinculum(
|
||||||
|
component: 'device' | 'house' | 'state',
|
||||||
|
): Promise<FimpResponse> {
|
||||||
|
return await sendFimpMsg({
|
||||||
|
address: '/rt:app/rn:vinculum/ad:1',
|
||||||
|
service: 'vinculum',
|
||||||
|
cmd: 'cmd.pd7.request',
|
||||||
|
val: { cmd: 'get', component: null, param: { components: [component] } },
|
||||||
|
val_t: 'object',
|
||||||
|
timeoutMs: 30000,
|
||||||
|
});
|
||||||
|
}
|
276
futurehome/src/ha/admin.ts
Normal file
276
futurehome/src/ha/admin.ts
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import { IMqttClient } from '../mqtt/interface';
|
||||||
|
import { CommandHandlers } from './publish_device';
|
||||||
|
import { HaDeviceConfig } from './ha_device_config';
|
||||||
|
import { ha } from './globals';
|
||||||
|
import { log } from '../logger';
|
||||||
|
import { abbreviateHaMqttKeys } from './abbreviate_ha_mqtt_keys';
|
||||||
|
import { FimpResponse } from '../fimp/fimp';
|
||||||
|
import {
|
||||||
|
connectThingsplexWebSocketAndSend,
|
||||||
|
loginToThingsplex,
|
||||||
|
} from '../thingsplex/thingsplex';
|
||||||
|
import { delay } from '../utils';
|
||||||
|
import { pollVinculum } from '../fimp/vinculum';
|
||||||
|
|
||||||
|
let initializedState = false;
|
||||||
|
|
||||||
|
export function exposeSmarthubTools(parameters: {
|
||||||
|
hubId: string;
|
||||||
|
demoMode: boolean;
|
||||||
|
hubIp: string;
|
||||||
|
thingsplexUsername: string;
|
||||||
|
thingsplexPassword: string;
|
||||||
|
}): {
|
||||||
|
commandHandlers: CommandHandlers;
|
||||||
|
} {
|
||||||
|
// e.g. "homeassistant/device/futurehome_123456_hub"
|
||||||
|
const topicPrefix = `homeassistant/device/futurehome_${parameters.hubId}_hub`;
|
||||||
|
|
||||||
|
if (!initializedState) {
|
||||||
|
ha?.publish(
|
||||||
|
`${topicPrefix}/inclusion_status/state`,
|
||||||
|
'Ready to start inclusion',
|
||||||
|
{
|
||||||
|
retain: true,
|
||||||
|
qos: 2,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
initializedState = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const configTopic = `${topicPrefix}/config`;
|
||||||
|
|
||||||
|
const deviceId = `futurehome_${parameters.hubId}_hub`;
|
||||||
|
|
||||||
|
const config: HaDeviceConfig = {
|
||||||
|
device: {
|
||||||
|
identifiers: deviceId,
|
||||||
|
name: 'Futurehome Smarthub',
|
||||||
|
manufacturer: 'Futurehome',
|
||||||
|
model: 'Smarthub',
|
||||||
|
serial_number: parameters.hubId,
|
||||||
|
},
|
||||||
|
origin: {
|
||||||
|
name: 'futurehome',
|
||||||
|
support_url:
|
||||||
|
'https://github.com/adrianjagielak/home-assistant-futurehome',
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
[`${deviceId}_zwave_startInclusion`]: {
|
||||||
|
unique_id: `${deviceId}_zwave_startInclusion`,
|
||||||
|
platform: 'button',
|
||||||
|
entity_category: 'diagnostic',
|
||||||
|
name: 'Start Z-Wave inclusion',
|
||||||
|
icon: 'mdi:z-wave',
|
||||||
|
command_topic: `${topicPrefix}/start_inclusion/command`,
|
||||||
|
payload_press: 'zwave',
|
||||||
|
availability_topic: `${topicPrefix}/inclusion_status/state`,
|
||||||
|
availability_template: `{% if value == "Done" or value == "Ready to start inclusion" or value == "Failed trying to start inclusion." or value == "Operation failed. The device can't be included." or value == "Device added successfully!" or value == "" %}online{% else %}offline{% endif %}`,
|
||||||
|
} as any,
|
||||||
|
[`${deviceId}_zigbee_startInclusion`]: {
|
||||||
|
unique_id: `${deviceId}_zigbee_startInclusion`,
|
||||||
|
platform: 'button',
|
||||||
|
entity_category: 'diagnostic',
|
||||||
|
name: 'Start ZigBee inclusion',
|
||||||
|
icon: 'mdi:zigbee',
|
||||||
|
command_topic: `${topicPrefix}/start_inclusion/command`,
|
||||||
|
payload_press: 'zigbee',
|
||||||
|
availability_topic: `${topicPrefix}/inclusion_status/state`,
|
||||||
|
availability_template: `{% if value == "Done" or value == "Ready to start inclusion" or value == "Failed trying to start inclusion." or value == "Operation failed. The device can't be included." or value == "Device added successfully!" or value == "" %}online{% else %}offline{% endif %}`,
|
||||||
|
} as any,
|
||||||
|
[`${deviceId}_stopInclusion`]: {
|
||||||
|
unique_id: `${deviceId}_stopInclusion`,
|
||||||
|
platform: 'button',
|
||||||
|
entity_category: 'diagnostic',
|
||||||
|
name: 'Stop inclusion',
|
||||||
|
icon: 'mdi:cancel',
|
||||||
|
command_topic: `${topicPrefix}/stop_inclusion/command`,
|
||||||
|
availability_topic: `${topicPrefix}/inclusion_status/state`,
|
||||||
|
availability_template: `{% if value == "Done" or value == "Ready to start inclusion" or value == "Failed trying to start inclusion." or value == "Operation failed. The device can't be included." or value == "Device added successfully!" or value == "Starting" or value == "Stopping" or value == "" %}offline{% else %}online{% endif %}`,
|
||||||
|
} as any,
|
||||||
|
[`${deviceId}_inclusion_status`]: {
|
||||||
|
unique_id: `${deviceId}_inclusion_status`,
|
||||||
|
platform: 'sensor',
|
||||||
|
entity_category: 'diagnostic',
|
||||||
|
device_class: 'enum',
|
||||||
|
name: 'Inclusion status',
|
||||||
|
state_topic: `${topicPrefix}/inclusion_status/state`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
qos: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
log.debug('Publishing Smarthub tools');
|
||||||
|
ha?.publish(configTopic, JSON.stringify(abbreviateHaMqttKeys(config)), {
|
||||||
|
retain: true,
|
||||||
|
qos: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handlers: CommandHandlers = {
|
||||||
|
[`${topicPrefix}/start_inclusion/command`]: async (payload) => {
|
||||||
|
if (parameters.demoMode) {
|
||||||
|
ha?.publish(`${topicPrefix}/inclusion_status/state`, 'Starting', {
|
||||||
|
retain: true,
|
||||||
|
qos: 2,
|
||||||
|
});
|
||||||
|
await delay(2000);
|
||||||
|
ha?.publish(
|
||||||
|
`${topicPrefix}/inclusion_status/state`,
|
||||||
|
'Looking for device',
|
||||||
|
{
|
||||||
|
retain: true,
|
||||||
|
qos: 2,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
await delay(2000);
|
||||||
|
ha?.publish(
|
||||||
|
`${topicPrefix}/inclusion_status/state`,
|
||||||
|
'Demo mode, inclusion not supported',
|
||||||
|
{
|
||||||
|
retain: true,
|
||||||
|
qos: 2,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
await delay(2000);
|
||||||
|
ha?.publish(`${topicPrefix}/inclusion_status/state`, 'Done', {
|
||||||
|
retain: true,
|
||||||
|
qos: 2,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha?.publish(`${topicPrefix}/inclusion_status/state`, 'Starting', {
|
||||||
|
retain: true,
|
||||||
|
qos: 2,
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
const token = await loginToThingsplex({
|
||||||
|
host: parameters.hubIp,
|
||||||
|
username: parameters.thingsplexUsername,
|
||||||
|
password: parameters.thingsplexPassword,
|
||||||
|
});
|
||||||
|
await connectThingsplexWebSocketAndSend(
|
||||||
|
{
|
||||||
|
host: parameters.hubIp,
|
||||||
|
token: token,
|
||||||
|
},
|
||||||
|
[
|
||||||
|
{
|
||||||
|
address:
|
||||||
|
payload == 'zwave'
|
||||||
|
? 'pt:j1/mt:cmd/rt:ad/rn:zw/ad:1'
|
||||||
|
: 'pt:j1/mt:cmd/rt:ad/rn:zigbee/ad:1',
|
||||||
|
service: payload == 'zwave' ? 'zwave-ad' : 'zigbee',
|
||||||
|
cmd: 'cmd.thing.inclusion',
|
||||||
|
val: true,
|
||||||
|
val_t: 'bool',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
ha?.publish(
|
||||||
|
`${topicPrefix}/inclusion_status/state`,
|
||||||
|
'Failed trying to start inclusion.',
|
||||||
|
{
|
||||||
|
retain: true,
|
||||||
|
qos: 2,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[`${topicPrefix}/stop_inclusion/command`]: async (_payload) => {
|
||||||
|
ha?.publish(`${topicPrefix}/inclusion_status/state`, 'Stopping', {
|
||||||
|
retain: true,
|
||||||
|
qos: 2,
|
||||||
|
});
|
||||||
|
if (parameters.demoMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = await loginToThingsplex({
|
||||||
|
host: parameters.hubIp,
|
||||||
|
username: parameters.thingsplexUsername,
|
||||||
|
password: parameters.thingsplexPassword,
|
||||||
|
});
|
||||||
|
await connectThingsplexWebSocketAndSend(
|
||||||
|
{
|
||||||
|
host: parameters.hubIp,
|
||||||
|
token: token,
|
||||||
|
},
|
||||||
|
[
|
||||||
|
{
|
||||||
|
address: 'pt:j1/mt:cmd/rt:ad/rn:zigbee/ad:1',
|
||||||
|
service: 'zigbee',
|
||||||
|
cmd: 'cmd.thing.inclusion',
|
||||||
|
val: false,
|
||||||
|
val_t: 'bool',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: 'pt:j1/mt:cmd/rt:ad/rn:zw/ad:1',
|
||||||
|
service: 'zwave-ad',
|
||||||
|
cmd: 'cmd.thing.inclusion',
|
||||||
|
val: false,
|
||||||
|
val_t: 'bool',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
);
|
||||||
|
ha?.publish(`${topicPrefix}/inclusion_status/state`, 'Done', {
|
||||||
|
retain: true,
|
||||||
|
qos: 2,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
ha?.publish(
|
||||||
|
`${topicPrefix}/inclusion_status/state`,
|
||||||
|
'Failed trying to stop inclusion.',
|
||||||
|
{
|
||||||
|
retain: true,
|
||||||
|
qos: 2,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return { commandHandlers: handlers };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleInclusionStatusReport(hubId: string, msg: FimpResponse) {
|
||||||
|
const topicPrefix = `homeassistant/device/futurehome_${hubId}_hub`;
|
||||||
|
|
||||||
|
let localizedStatus: string;
|
||||||
|
switch (msg.val) {
|
||||||
|
case 'ADD_NODE_STARTING':
|
||||||
|
case 'ADD_NODE_STARTED':
|
||||||
|
localizedStatus = 'Looking for device';
|
||||||
|
break;
|
||||||
|
case 'ADD_NODE_ADDED':
|
||||||
|
case 'ADD_NODE_GET_NODE_INFO':
|
||||||
|
case 'ADD_NODE_PROTOCOL_DONE':
|
||||||
|
localizedStatus = 'Device added successfully!';
|
||||||
|
pollVinculum('device').catch((e) => log.warn('Failed to request devices', e));
|
||||||
|
pollVinculum('state').catch((e) => log.warn('Failed to request state', e));
|
||||||
|
break;
|
||||||
|
case 'ADD_NODE_DONE':
|
||||||
|
localizedStatus = 'Done';
|
||||||
|
pollVinculum('device').catch((e) => log.warn('Failed to request devices', e));
|
||||||
|
pollVinculum('state').catch((e) => log.warn('Failed to request state', e));
|
||||||
|
break;
|
||||||
|
case 'NET_NODE_INCL_CTRL_OP_FAILED':
|
||||||
|
localizedStatus = "Operation failed. The device can't be included.";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
localizedStatus = msg.val;
|
||||||
|
log.warn(`Unknown inclusion status: ${msg.val}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha?.publish(`${topicPrefix}/inclusion_status/state`, localizedStatus, {
|
||||||
|
retain: true,
|
||||||
|
qos: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo exclusion?
|
||||||
|
// NET_NODE_REMOVE_FAILED", "Device can't be deleted
|
86
futurehome/src/ha/ha_device_config.ts
Normal file
86
futurehome/src/ha/ha_device_config.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import { HaMqttComponent } from './mqtt_components/_component';
|
||||||
|
|
||||||
|
export type HaDeviceConfig = {
|
||||||
|
/**
|
||||||
|
* Information about the device this sensor is a part of to tie it into the [device registry](https://developers.home-assistant.io/docs/device_registry_index/).
|
||||||
|
* Only works when [`unique_id`](#unique_id) is set.
|
||||||
|
* At least one of identifiers or connections must be present to identify the device.
|
||||||
|
*/
|
||||||
|
device?: {
|
||||||
|
/**
|
||||||
|
* A link to the webpage that can manage the configuration of this device.
|
||||||
|
* Can be either an `http://`, `https://` or an internal `homeassistant://` URL.
|
||||||
|
*/
|
||||||
|
configuration_url?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of connections of the device to the outside world as a list of tuples `[connection_type, connection_identifier]`.
|
||||||
|
* For example the MAC address of a network interface:
|
||||||
|
* `"connections": [["mac", "02:5b:26:a8:dc:12"]]`.
|
||||||
|
*/
|
||||||
|
connections?: Array<[string, string]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hardware version of the device.
|
||||||
|
*/
|
||||||
|
hw_version?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of IDs that uniquely identify the device.
|
||||||
|
* For example a serial number.
|
||||||
|
*/
|
||||||
|
identifiers?: string | string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The manufacturer of the device.
|
||||||
|
*/
|
||||||
|
manufacturer?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model of the device.
|
||||||
|
*/
|
||||||
|
model?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model identifier of the device.
|
||||||
|
*/
|
||||||
|
model_id?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the device.
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The serial number of the device.
|
||||||
|
*/
|
||||||
|
serial_number?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suggest an area if the device isn’t in one yet.
|
||||||
|
*/
|
||||||
|
suggested_area?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The firmware version of the device.
|
||||||
|
*/
|
||||||
|
sw_version?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifier of a device that routes messages between this device and Home Assistant.
|
||||||
|
* Examples of such devices are hubs, or parent devices of a sub-device.
|
||||||
|
* This is used to show device topology in Home Assistant.
|
||||||
|
*/
|
||||||
|
via_device?: string;
|
||||||
|
};
|
||||||
|
origin: {
|
||||||
|
name: 'futurehome';
|
||||||
|
support_url: 'https://github.com/adrianjagielak/home-assistant-futurehome';
|
||||||
|
};
|
||||||
|
components: {
|
||||||
|
[key: string]: HaMqttComponent;
|
||||||
|
};
|
||||||
|
state_topic?: string;
|
||||||
|
availability_topic?: string;
|
||||||
|
qos: number;
|
||||||
|
};
|
@ -114,24 +114,12 @@ export interface AlarmControlPanelComponent extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
payload_arm_custom_bypass?: string;
|
payload_arm_custom_bypass?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The payload to disarm your Alarm Panel.
|
* The payload to disarm your Alarm Panel.
|
||||||
* Default: "DISARM"
|
* Default: "DISARM"
|
||||||
*/
|
*/
|
||||||
payload_disarm?: string;
|
payload_disarm?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The payload to trigger the alarm on your Alarm Panel.
|
* The payload to trigger the alarm on your Alarm Panel.
|
||||||
* Default: "TRIGGER"
|
* Default: "TRIGGER"
|
||||||
|
@ -86,12 +86,6 @@ export interface BinarySensorComponent extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
off_delay?: number;
|
off_delay?: number;
|
||||||
|
|
||||||
/**
|
|
||||||
* The string that represents the `online` state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The string that represents the `offline` state.
|
* The string that represents the `offline` state.
|
||||||
* Default: "offline"
|
* Default: "offline"
|
||||||
|
@ -51,16 +51,4 @@ export interface ButtonComponent extends BaseComponent {
|
|||||||
* Usage example can be found in [MQTT sensor](https://www.home-assistant.io/integrations/sensor.mqtt/#json-attributes-topic-configuration) documentation.
|
* Usage example can be found in [MQTT sensor](https://www.home-assistant.io/integrations/sensor.mqtt/#json-attributes-topic-configuration) documentation.
|
||||||
*/
|
*/
|
||||||
json_attributes_topic?: string;
|
json_attributes_topic?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
}
|
}
|
||||||
|
@ -157,18 +157,6 @@ export interface ClimateComponent extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
optimistic?: boolean;
|
optimistic?: boolean;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The payload sent to turn off the device.
|
* The payload sent to turn off the device.
|
||||||
* Default: "OFF"
|
* Default: "OFF"
|
||||||
|
@ -47,12 +47,6 @@ export interface CoverComponent extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
optimistic?: boolean;
|
optimistic?: boolean;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the online state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The command payload that closes the cover.
|
* The command payload that closes the cover.
|
||||||
* Set to `null` to disable the close command.
|
* Set to `null` to disable the close command.
|
||||||
|
@ -83,16 +83,4 @@ export interface DeviceTrackerComponent extends BaseComponent {
|
|||||||
* Default: '"None"'
|
* Default: '"None"'
|
||||||
*/
|
*/
|
||||||
payload_reset?: string;
|
payload_reset?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
}
|
}
|
||||||
|
@ -56,18 +56,6 @@ export interface EventComponent extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
name?: string;
|
name?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a [template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt)
|
* Defines a [template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt)
|
||||||
* to extract the value and render it to a valid JSON event payload.
|
* to extract the value and render it to a valid JSON event payload.
|
||||||
|
@ -154,18 +154,6 @@ export interface FanComponent extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
json_attributes_topic?: string;
|
json_attributes_topic?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The payload that represents the stop state.
|
* The payload that represents the stop state.
|
||||||
* Default: "OFF"
|
* Default: "OFF"
|
||||||
|
@ -342,18 +342,6 @@ export interface LightComponent extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
min_mireds?: number;
|
min_mireds?: number;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The payload that represents the off state.
|
* The payload that represents the off state.
|
||||||
* Default: "OFF"
|
* Default: "OFF"
|
||||||
|
@ -61,24 +61,12 @@ export interface LockComponent extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
optimistic?: boolean;
|
optimistic?: boolean;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The payload sent to the lock to lock it.
|
* The payload sent to the lock to lock it.
|
||||||
* Default: "LOCK"
|
* Default: "LOCK"
|
||||||
*/
|
*/
|
||||||
payload_lock?: string;
|
payload_lock?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The payload sent to the lock to unlock it.
|
* The payload sent to the lock to unlock it.
|
||||||
* Default: "UNLOCK"
|
* Default: "UNLOCK"
|
||||||
|
@ -40,16 +40,4 @@ export interface NotifyComponent extends BaseComponent {
|
|||||||
* Usage example can be found in [MQTT sensor](https://www.home-assistant.io/integrations/sensor.mqtt/#json-attributes-topic-configuration) documentation.
|
* Usage example can be found in [MQTT sensor](https://www.home-assistant.io/integrations/sensor.mqtt/#json-attributes-topic-configuration) documentation.
|
||||||
*/
|
*/
|
||||||
json_attributes_topic?: string;
|
json_attributes_topic?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
}
|
}
|
||||||
|
@ -25,18 +25,6 @@ export interface SceneComponent extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
payload_on?: string;
|
payload_on?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a [template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt)
|
* Defines a [template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt)
|
||||||
* to extract the JSON dictionary from messages received on the `json_attributes_topic`.
|
* to extract the JSON dictionary from messages received on the `json_attributes_topic`.
|
||||||
|
@ -103,16 +103,4 @@ export interface SensorComponent extends BaseComponent {
|
|||||||
* Available variables: `entity_id`. The `entity_id` can be used to reference the entity's attributes.
|
* Available variables: `entity_id`. The `entity_id` can be used to reference the entity's attributes.
|
||||||
*/
|
*/
|
||||||
last_reset_value_template?: string;
|
last_reset_value_template?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
}
|
}
|
||||||
|
@ -50,18 +50,6 @@ export interface SirenComponent extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
optimistic?: boolean;
|
optimistic?: boolean;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The payload that represents `off` state. If specified, will be used for both comparing to the value in the `state_topic` (see `value_template` and `state_off` for details) and sending as `off` command to the `command_topic`.
|
* The payload that represents `off` state. If specified, will be used for both comparing to the value in the `state_topic` (see `value_template` and `state_off` for details) and sending as `off` command to the `command_topic`.
|
||||||
* Default: "OFF"
|
* Default: "OFF"
|
||||||
|
@ -52,18 +52,6 @@ export interface SwitchComponent extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
optimistic?: boolean;
|
optimistic?: boolean;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The payload that represents `off` state.
|
* The payload that represents `off` state.
|
||||||
* If specified, will be used for both comparing to the value in the `state_topic` (see `value_template` and `state_off` for details)
|
* If specified, will be used for both comparing to the value in the `state_topic` (see `value_template` and `state_off` for details)
|
||||||
|
@ -39,12 +39,6 @@ export interface VacuumComponent extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
json_attributes_topic?: string;
|
json_attributes_topic?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The payload to send to the `command_topic` to begin a spot cleaning cycle.
|
* The payload to send to the `command_topic` to begin a spot cleaning cycle.
|
||||||
* Default: "clean_spot"
|
* Default: "clean_spot"
|
||||||
@ -57,12 +51,6 @@ export interface VacuumComponent extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
payload_locate?: string;
|
payload_locate?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The payload to send to the `command_topic` to pause the vacuum.
|
* The payload to send to the `command_topic` to pause the vacuum.
|
||||||
* Default: "pause"
|
* Default: "pause"
|
||||||
|
@ -15,18 +15,6 @@ export interface WaterHeaterComponent extends BaseComponent {
|
|||||||
*/
|
*/
|
||||||
platform: 'water_heater';
|
platform: 'water_heater';
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the available state.
|
|
||||||
* Default: "online"
|
|
||||||
*/
|
|
||||||
payload_available?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The payload that represents the unavailable state.
|
|
||||||
* Default: "offline"
|
|
||||||
*/
|
|
||||||
payload_not_available?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The MQTT topic to publish commands to change the water heater operation mode.
|
* The MQTT topic to publish commands to change the water heater operation mode.
|
||||||
*/
|
*/
|
||||||
|
@ -32,93 +32,9 @@ import { user_code__components } from '../services/user_code';
|
|||||||
import { water_heater__components } from '../services/water_heater';
|
import { water_heater__components } from '../services/water_heater';
|
||||||
import { abbreviateHaMqttKeys } from './abbreviate_ha_mqtt_keys';
|
import { abbreviateHaMqttKeys } from './abbreviate_ha_mqtt_keys';
|
||||||
import { ha } from './globals';
|
import { ha } from './globals';
|
||||||
|
import { HaDeviceConfig } from './ha_device_config';
|
||||||
import { HaMqttComponent } from './mqtt_components/_component';
|
import { HaMqttComponent } from './mqtt_components/_component';
|
||||||
|
|
||||||
type HaDeviceConfig = {
|
|
||||||
/**
|
|
||||||
* Information about the device this sensor is a part of to tie it into the [device registry](https://developers.home-assistant.io/docs/device_registry_index/).
|
|
||||||
* Only works when [`unique_id`](#unique_id) is set.
|
|
||||||
* At least one of identifiers or connections must be present to identify the device.
|
|
||||||
*/
|
|
||||||
device?: {
|
|
||||||
/**
|
|
||||||
* A link to the webpage that can manage the configuration of this device.
|
|
||||||
* Can be either an `http://`, `https://` or an internal `homeassistant://` URL.
|
|
||||||
*/
|
|
||||||
configuration_url?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A list of connections of the device to the outside world as a list of tuples `[connection_type, connection_identifier]`.
|
|
||||||
* For example the MAC address of a network interface:
|
|
||||||
* `"connections": [["mac", "02:5b:26:a8:dc:12"]]`.
|
|
||||||
*/
|
|
||||||
connections?: Array<[string, string]>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The hardware version of the device.
|
|
||||||
*/
|
|
||||||
hw_version?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A list of IDs that uniquely identify the device.
|
|
||||||
* For example a serial number.
|
|
||||||
*/
|
|
||||||
identifiers?: string | string[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The manufacturer of the device.
|
|
||||||
*/
|
|
||||||
manufacturer?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The model of the device.
|
|
||||||
*/
|
|
||||||
model?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The model identifier of the device.
|
|
||||||
*/
|
|
||||||
model_id?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the device.
|
|
||||||
*/
|
|
||||||
name?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The serial number of the device.
|
|
||||||
*/
|
|
||||||
serial_number?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Suggest an area if the device isn’t in one yet.
|
|
||||||
*/
|
|
||||||
suggested_area?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The firmware version of the device.
|
|
||||||
*/
|
|
||||||
sw_version?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Identifier of a device that routes messages between this device and Home Assistant.
|
|
||||||
* Examples of such devices are hubs, or parent devices of a sub-device.
|
|
||||||
* This is used to show device topology in Home Assistant.
|
|
||||||
*/
|
|
||||||
via_device?: string;
|
|
||||||
};
|
|
||||||
origin: {
|
|
||||||
name: 'futurehome';
|
|
||||||
support_url: 'https://github.com/adrianjagielak/home-assistant-futurehome';
|
|
||||||
};
|
|
||||||
components: {
|
|
||||||
[key: string]: HaMqttComponent;
|
|
||||||
};
|
|
||||||
state_topic: string;
|
|
||||||
availability_topic: string;
|
|
||||||
qos: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ServiceComponentsCreationResult = {
|
export type ServiceComponentsCreationResult = {
|
||||||
components: { [key: string]: HaMqttComponent };
|
components: { [key: string]: HaMqttComponent };
|
||||||
commandHandlers?: CommandHandlers;
|
commandHandlers?: CommandHandlers;
|
||||||
@ -348,7 +264,7 @@ export function haPublishDevice(parameters: {
|
|||||||
const availabilityTopic = `${topicPrefix}/availability`;
|
const availabilityTopic = `${topicPrefix}/availability`;
|
||||||
const config: HaDeviceConfig = {
|
const config: HaDeviceConfig = {
|
||||||
device: {
|
device: {
|
||||||
identifiers: parameters.vinculumDeviceData.id.toString(),
|
identifiers: `futurehome_${parameters.hubId}_${parameters.vinculumDeviceData.id}`,
|
||||||
name:
|
name:
|
||||||
parameters.vinculumDeviceData?.client?.name ??
|
parameters.vinculumDeviceData?.client?.name ??
|
||||||
parameters.vinculumDeviceData?.modelAlias ??
|
parameters.vinculumDeviceData?.modelAlias ??
|
||||||
@ -366,7 +282,7 @@ export function haPublishDevice(parameters: {
|
|||||||
serial_number:
|
serial_number:
|
||||||
parameters.deviceInclusionReport?.product_hash ?? undefined,
|
parameters.deviceInclusionReport?.product_hash ?? undefined,
|
||||||
hw_version: parameters.deviceInclusionReport?.hw_ver ?? undefined,
|
hw_version: parameters.deviceInclusionReport?.hw_ver ?? undefined,
|
||||||
via_device: 'todo_hub_id',
|
via_device: `futurehome_${parameters.hubId}_hub`,
|
||||||
},
|
},
|
||||||
origin: {
|
origin: {
|
||||||
name: 'futurehome',
|
name: 'futurehome',
|
||||||
|
@ -7,11 +7,15 @@ import { haUpdateState, haUpdateStateValueReport } from './ha/update_state';
|
|||||||
import { VinculumPd7Device } from './fimp/vinculum_pd7_device';
|
import { VinculumPd7Device } from './fimp/vinculum_pd7_device';
|
||||||
import { haUpdateAvailability } from './ha/update_availability';
|
import { haUpdateAvailability } from './ha/update_availability';
|
||||||
import { delay } from './utils';
|
import { delay } from './utils';
|
||||||
|
import { exposeSmarthubTools, handleInclusionStatusReport } from './ha/admin';
|
||||||
|
import { pollVinculum } from './fimp/vinculum';
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
const hubIp = process.env.FH_HUB_IP || 'futurehome-smarthub.local';
|
const hubIp = process.env.FH_HUB_IP || 'futurehome-smarthub.local';
|
||||||
const hubUsername = process.env.FH_USERNAME || '';
|
const localApiUsername = process.env.FH_USERNAME || '';
|
||||||
const hubPassword = process.env.FH_PASSWORD || '';
|
const localApiPassword = process.env.FH_PASSWORD || '';
|
||||||
|
const thingsplexUsername = process.env.TP_USERNAME || '';
|
||||||
|
const thingsplexPassword = process.env.TP_PASSWORD || '';
|
||||||
const demoMode = (process.env.DEMO_MODE || '').toLowerCase().includes('true');
|
const demoMode = (process.env.DEMO_MODE || '').toLowerCase().includes('true');
|
||||||
const showDebugLog = (process.env.SHOW_DEBUG_LOG || '')
|
const showDebugLog = (process.env.SHOW_DEBUG_LOG || '')
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
@ -35,7 +39,7 @@ import { delay } from './utils';
|
|||||||
setHa(ha);
|
setHa(ha);
|
||||||
log.info('Connected to HA broker');
|
log.info('Connected to HA broker');
|
||||||
|
|
||||||
if (!demoMode && (!hubUsername || !hubPassword)) {
|
if (!demoMode && (!localApiUsername || !localApiPassword)) {
|
||||||
log.info(
|
log.info(
|
||||||
'Empty username or password in non-demo mode. Removing all Futurehome devices from Home Assistant...',
|
'Empty username or password in non-demo mode. Removing all Futurehome devices from Home Assistant...',
|
||||||
);
|
);
|
||||||
@ -57,32 +61,18 @@ import { delay } from './utils';
|
|||||||
log.info('Connecting to Futurehome hub...');
|
log.info('Connecting to Futurehome hub...');
|
||||||
const fimp = await connectHub({
|
const fimp = await connectHub({
|
||||||
hubIp,
|
hubIp,
|
||||||
username: hubUsername,
|
username: localApiUsername,
|
||||||
password: hubPassword,
|
password: localApiPassword,
|
||||||
demo: demoMode,
|
demo: demoMode,
|
||||||
});
|
});
|
||||||
fimp.subscribe('#');
|
fimp.subscribe('#');
|
||||||
setFimp(fimp);
|
setFimp(fimp);
|
||||||
log.info('Connected to Futurehome hub');
|
log.info('Connected to Futurehome hub');
|
||||||
|
|
||||||
const house = await sendFimpMsg({
|
const house = await pollVinculum('house');
|
||||||
address: '/rt:app/rn:vinculum/ad:1',
|
|
||||||
service: 'vinculum',
|
|
||||||
cmd: 'cmd.pd7.request',
|
|
||||||
val: { cmd: 'get', component: null, param: { components: ['house'] } },
|
|
||||||
val_t: 'object',
|
|
||||||
timeoutMs: 30000,
|
|
||||||
});
|
|
||||||
const hubId = house.val.param.house.hubId;
|
const hubId = house.val.param.house.hubId;
|
||||||
|
|
||||||
const devices = await sendFimpMsg({
|
const devices = await pollVinculum('device');
|
||||||
address: '/rt:app/rn:vinculum/ad:1',
|
|
||||||
service: 'vinculum',
|
|
||||||
cmd: 'cmd.pd7.request',
|
|
||||||
val: { cmd: 'get', component: null, param: { components: ['device'] } },
|
|
||||||
val_t: 'object',
|
|
||||||
timeoutMs: 30000,
|
|
||||||
});
|
|
||||||
|
|
||||||
const haConfig = retainedMessages.filter((msg) =>
|
const haConfig = retainedMessages.filter((msg) =>
|
||||||
msg.topic.endsWith('/config'),
|
msg.topic.endsWith('/config'),
|
||||||
@ -181,15 +171,24 @@ import { delay } from './utils';
|
|||||||
log.error('Failed publishing device', device, e);
|
log.error('Failed publishing device', device, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (demoMode || (thingsplexUsername && thingsplexPassword)) {
|
||||||
|
Object.assign(
|
||||||
|
commandHandlers,
|
||||||
|
exposeSmarthubTools({
|
||||||
|
hubId,
|
||||||
|
demoMode,
|
||||||
|
hubIp,
|
||||||
|
thingsplexUsername,
|
||||||
|
thingsplexPassword,
|
||||||
|
}).commandHandlers,
|
||||||
|
);
|
||||||
|
}
|
||||||
setHaCommandHandlers(commandHandlers);
|
setHaCommandHandlers(commandHandlers);
|
||||||
};
|
};
|
||||||
vinculumDevicesToHa(devices);
|
vinculumDevicesToHa(devices);
|
||||||
|
|
||||||
let knownDeviceIds = new Set(devices.val.param.device.map((d: any) => d?.id));
|
let knownDeviceIds = new Set(devices.val.param.device.map((d: any) => d?.id));
|
||||||
|
|
||||||
// todo
|
|
||||||
// exposeSmarthubTools();
|
|
||||||
|
|
||||||
fimp.on('message', async (topic, buf) => {
|
fimp.on('message', async (topic, buf) => {
|
||||||
try {
|
try {
|
||||||
const msg: FimpResponse = JSON.parse(buf.toString());
|
const msg: FimpResponse = JSON.parse(buf.toString());
|
||||||
@ -252,6 +251,11 @@ import { delay } from './utils';
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'evt.thing.inclusion_status_report': {
|
||||||
|
handleInclusionStatusReport(hubId, msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
// Handle any event that matches the pattern: evt.<something>.report
|
// Handle any event that matches the pattern: evt.<something>.report
|
||||||
if (/^evt\..+\.report$/.test(msg.type ?? '')) {
|
if (/^evt\..+\.report$/.test(msg.type ?? '')) {
|
||||||
@ -271,14 +275,7 @@ import { delay } from './utils';
|
|||||||
const pollState = () => {
|
const pollState = () => {
|
||||||
log.debug('Refreshing Vinculum state after 30 seconds...');
|
log.debug('Refreshing Vinculum state after 30 seconds...');
|
||||||
|
|
||||||
sendFimpMsg({
|
pollVinculum('state').catch((e) => log.warn('Failed to request state', e));
|
||||||
address: '/rt:app/rn:vinculum/ad:1',
|
|
||||||
service: 'vinculum',
|
|
||||||
cmd: 'cmd.pd7.request',
|
|
||||||
val: { cmd: 'get', component: null, param: { components: ['state'] } },
|
|
||||||
val_t: 'object',
|
|
||||||
timeoutMs: 30000,
|
|
||||||
}).catch((e) => log.warn('Failed to request state', e));
|
|
||||||
};
|
};
|
||||||
// Request initial state
|
// Request initial state
|
||||||
pollState();
|
pollState();
|
||||||
@ -290,14 +287,9 @@ import { delay } from './utils';
|
|||||||
const pollDevices = () => {
|
const pollDevices = () => {
|
||||||
log.debug('Refreshing Vinculum devices after 30 minutes...');
|
log.debug('Refreshing Vinculum devices after 30 minutes...');
|
||||||
|
|
||||||
sendFimpMsg({
|
pollVinculum('device').catch((e) =>
|
||||||
address: '/rt:app/rn:vinculum/ad:1',
|
log.warn('Failed to request devices', e),
|
||||||
service: 'vinculum',
|
);
|
||||||
cmd: 'cmd.pd7.request',
|
|
||||||
val: { cmd: 'get', component: null, param: { components: ['device'] } },
|
|
||||||
val_t: 'object',
|
|
||||||
timeoutMs: 30000,
|
|
||||||
}).catch((e) => log.warn('Failed to request state', e));
|
|
||||||
};
|
};
|
||||||
// Poll devices every 30 minutes (1800000 ms)
|
// Poll devices every 30 minutes (1800000 ms)
|
||||||
if (!demoMode) {
|
if (!demoMode) {
|
||||||
|
104
futurehome/src/thingsplex/thingsplex.ts
Normal file
104
futurehome/src/thingsplex/thingsplex.ts
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
// src/futurehomeClient.ts
|
||||||
|
import axios from 'axios';
|
||||||
|
import { WebSocket } from 'ws';
|
||||||
|
import { URLSearchParams } from 'url';
|
||||||
|
import { FimpValueType } from '../fimp/fimp';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs in to the Thingsplex and extracts the tplex token.
|
||||||
|
* @param username - The login username
|
||||||
|
* @param password - The login password
|
||||||
|
* @returns The tplex token if login is successful
|
||||||
|
*/
|
||||||
|
export async function loginToThingsplex(parameters: {
|
||||||
|
host: string;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}): Promise<string> {
|
||||||
|
const url = `http://${parameters.host}:8081/fimp/login`;
|
||||||
|
const payload = new URLSearchParams({
|
||||||
|
username: parameters.username,
|
||||||
|
password: parameters.password,
|
||||||
|
}).toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios.post(url, payload, {
|
||||||
|
maxRedirects: 0,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
validateStatus: (status) => status === 301,
|
||||||
|
});
|
||||||
|
|
||||||
|
const setCookie = response.headers['set-cookie'];
|
||||||
|
if (!setCookie || setCookie.length === 0) {
|
||||||
|
throw new Error('Set-Cookie header missing in login response');
|
||||||
|
}
|
||||||
|
|
||||||
|
const cookie = setCookie.find((c) => c.startsWith('tplex='));
|
||||||
|
if (!cookie) {
|
||||||
|
throw new Error('tplex cookie not found in Set-Cookie header');
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = cookie.match(/tplex=([^;]+)/);
|
||||||
|
if (!match) {
|
||||||
|
throw new Error('Unable to extract tplex token from cookie');
|
||||||
|
}
|
||||||
|
|
||||||
|
return match[1];
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`Login failed: ${(err as Error).message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connects to the Thingsplex websocket with the tplex token and sends the messages.
|
||||||
|
* @param token - The tplex token from login
|
||||||
|
*/
|
||||||
|
export function connectThingsplexWebSocketAndSend(
|
||||||
|
parameters: {
|
||||||
|
host: string;
|
||||||
|
token: string;
|
||||||
|
},
|
||||||
|
messages: {
|
||||||
|
address: string;
|
||||||
|
service: string;
|
||||||
|
cmd: string;
|
||||||
|
val: unknown;
|
||||||
|
val_t: FimpValueType;
|
||||||
|
props?: any;
|
||||||
|
}[],
|
||||||
|
): Promise<void> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const ws = new WebSocket(`ws://${parameters.host}:8081/ws-bridge`, {
|
||||||
|
headers: {
|
||||||
|
Cookie: `tplex=${parameters.token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.on('open', () => {
|
||||||
|
for (const msg of messages) {
|
||||||
|
const message = {
|
||||||
|
serv: msg.service,
|
||||||
|
type: msg.cmd,
|
||||||
|
val_t: msg.val_t,
|
||||||
|
val: msg.val,
|
||||||
|
props: msg.props,
|
||||||
|
tags: null,
|
||||||
|
resp_to: 'pt:j1/mt:rsp/rt:app/rn:tplex-ui/ad:1',
|
||||||
|
src: 'tplex-ui',
|
||||||
|
ver: '1',
|
||||||
|
uid: uuidv4(),
|
||||||
|
topic: msg.address,
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.send(JSON.stringify(message));
|
||||||
|
}
|
||||||
|
ws.close(); // Close immediately after sending
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.on('close', () => resolve());
|
||||||
|
ws.on('error', (err) => reject(err));
|
||||||
|
});
|
||||||
|
}
|
21
futurehome/translations/be.yaml
Normal file
21
futurehome/translations/be.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
configuration:
|
||||||
|
hub_ip:
|
||||||
|
name: IP хаба (неабавязкова)
|
||||||
|
description: Пакіньце пустым для аўтаматычнага выяўлення.
|
||||||
|
fh_username:
|
||||||
|
name: Лагін лакальнага API
|
||||||
|
description: Ваш лагін для лакальнага API/MQTT у Smarthub.
|
||||||
|
fh_password:
|
||||||
|
name: Пароль лакальнага API
|
||||||
|
description: Ваш пароль для лакальнага API/MQTT у Smarthub.
|
||||||
|
tp_username:
|
||||||
|
name: Лагін Thingsplex (неабавязкова)
|
||||||
|
description: Ваш лагін для Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Пароль Thingsplex (неабавязкова)
|
||||||
|
description: Ваш пароль для Thingsplex.
|
||||||
|
demo_mode:
|
||||||
|
name: Дэманстрацыйны рэжым
|
||||||
|
description: Выкарыстоўвайце запісаны стан з рэальнага Futurehome Smarthub для мадэлявання прылад.
|
||||||
|
show_debug_log:
|
||||||
|
name: Паказваць журнал адладкі
|
21
futurehome/translations/by.yaml
Normal file
21
futurehome/translations/by.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
configuration:
|
||||||
|
hub_ip:
|
||||||
|
name: IP хаба (неабавязкова)
|
||||||
|
description: Пакіньце пустым для аўтаматычнага выяўлення.
|
||||||
|
fh_username:
|
||||||
|
name: Лагін лакальнага API
|
||||||
|
description: Ваш лагін для лакальнага API/MQTT у Smarthub.
|
||||||
|
fh_password:
|
||||||
|
name: Пароль лакальнага API
|
||||||
|
description: Ваш пароль для лакальнага API/MQTT у Smarthub.
|
||||||
|
tp_username:
|
||||||
|
name: Лагін Thingsplex (неабавязкова)
|
||||||
|
description: Ваш лагін для Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Пароль Thingsplex (неабавязкова)
|
||||||
|
description: Ваш пароль для Thingsplex.
|
||||||
|
demo_mode:
|
||||||
|
name: Дэманстрацыйны рэжым
|
||||||
|
description: Выкарыстоўвайце запісаны стан з рэальнага Futurehome Smarthub для мадэлявання прылад.
|
||||||
|
show_debug_log:
|
||||||
|
name: Паказваць журнал адладкі
|
21
futurehome/translations/cs.yaml
Normal file
21
futurehome/translations/cs.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
configuration:
|
||||||
|
hub_ip:
|
||||||
|
name: IP adresa hubu (volitelné)
|
||||||
|
description: Nechte prázdné pro automatické vyhledání.
|
||||||
|
fh_username:
|
||||||
|
name: Uživatelské jméno pro lokální API
|
||||||
|
description: Vaše uživatelské jméno pro lokální API/MQTT Smarthubu.
|
||||||
|
fh_password:
|
||||||
|
name: Heslo pro lokální API
|
||||||
|
description: Vaše heslo pro lokální API/MQTT Smarthubu.
|
||||||
|
tp_username:
|
||||||
|
name: Uživatelské jméno Thingsplex (volitelné)
|
||||||
|
description: Vaše uživatelské jméno pro Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Heslo Thingsplex (volitelné)
|
||||||
|
description: Vaše heslo pro Thingsplex.
|
||||||
|
demo_mode:
|
||||||
|
name: Demo režim
|
||||||
|
description: Použijte uložený stav ze skutečného Futurehome Smarthubu pro simulaci zařízení.
|
||||||
|
show_debug_log:
|
||||||
|
name: Zobrazit ladicí protokol
|
21
futurehome/translations/cz.yaml
Normal file
21
futurehome/translations/cz.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
configuration:
|
||||||
|
hub_ip:
|
||||||
|
name: IP adresa hubu (volitelné)
|
||||||
|
description: Nechte prázdné pro automatické vyhledání.
|
||||||
|
fh_username:
|
||||||
|
name: Uživatelské jméno pro lokální API
|
||||||
|
description: Vaše uživatelské jméno pro lokální API/MQTT Smarthubu.
|
||||||
|
fh_password:
|
||||||
|
name: Heslo pro lokální API
|
||||||
|
description: Vaše heslo pro lokální API/MQTT Smarthubu.
|
||||||
|
tp_username:
|
||||||
|
name: Uživatelské jméno Thingsplex (volitelné)
|
||||||
|
description: Vaše uživatelské jméno pro Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Heslo Thingsplex (volitelné)
|
||||||
|
description: Vaše heslo pro Thingsplex.
|
||||||
|
demo_mode:
|
||||||
|
name: Demo režim
|
||||||
|
description: Použijte uložený stav ze skutečného Futurehome Smarthubu pro simulaci zařízení.
|
||||||
|
show_debug_log:
|
||||||
|
name: Zobrazit ladicí protokol
|
@ -1,15 +1,21 @@
|
|||||||
configuration:
|
configuration:
|
||||||
hub_ip:
|
hub_ip:
|
||||||
name: Hub IP (valgfrit)
|
name: Hub IP (valgfri)
|
||||||
description: Lad stå tom for automatisk opdagelse.
|
description: Lad feltet være tomt for automatisk opdagelse.
|
||||||
username:
|
fh_username:
|
||||||
name: Brugernavn
|
name: Lokal API-brugernavn
|
||||||
description: Dit brugernavn til lokal API/MQTT-adgang til Smarthub.
|
description: Dit Smarthub lokale API/MQTT-brugernavn.
|
||||||
password:
|
fh_password:
|
||||||
name: Adgangskode
|
name: Lokal API-adgangskode
|
||||||
description: Din adgangskode til lokal API/MQTT-adgang til Smarthub.
|
description: Din Smarthub lokale API/MQTT-adgangskode.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplex-brugernavn (valgfri)
|
||||||
|
description: Dit Thingsplex-brugernavn.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplex-adgangskode (valgfri)
|
||||||
|
description: Din Thingsplex-adgangskode.
|
||||||
demo_mode:
|
demo_mode:
|
||||||
name: Demotilstand
|
name: Demotilstand
|
||||||
description: Brug en optaget tilstand fra en ægte Futurehome Smarthub til at simulere enheder.
|
description: Brug en optaget prøvetilstand fra en rigtig Futurehome Smarthub til at simulere enheder.
|
||||||
show_debug_log:
|
show_debug_log:
|
||||||
name: Vis fejllog
|
name: Vis fejllog
|
||||||
|
@ -2,14 +2,20 @@ configuration:
|
|||||||
hub_ip:
|
hub_ip:
|
||||||
name: Hub-IP (optional)
|
name: Hub-IP (optional)
|
||||||
description: Leer lassen für automatische Erkennung.
|
description: Leer lassen für automatische Erkennung.
|
||||||
username:
|
fh_username:
|
||||||
name: Benutzername
|
name: Lokaler API-Benutzername
|
||||||
description: Dein Benutzername für den lokalen API/MQTT-Zugang zum Smarthub.
|
description: Dein Smarthub lokaler API-/MQTT-Benutzername.
|
||||||
password:
|
fh_password:
|
||||||
name: Passwort
|
name: Lokales API-Passwort
|
||||||
description: Dein Passwort für den lokalen API/MQTT-Zugang zum Smarthub.
|
description: Dein Smarthub lokales API-/MQTT-Passwort.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplex-Benutzername (optional)
|
||||||
|
description: Dein Thingsplex-Benutzername.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplex-Passwort (optional)
|
||||||
|
description: Dein Thingsplex-Passwort.
|
||||||
demo_mode:
|
demo_mode:
|
||||||
name: Demomodus
|
name: Demo-Modus
|
||||||
description: Verwende einen aufgezeichneten Zustand von einem echten Futurehome Smarthub, um Geräte zu simulieren.
|
description: Verwende einen aufgezeichneten Beispielzustand eines echten Futurehome Smarthubs, um Geräte zu simulieren.
|
||||||
show_debug_log:
|
show_debug_log:
|
||||||
name: Debug-Log anzeigen
|
name: Debug-Log anzeigen
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
configuration:
|
configuration:
|
||||||
hub_ip:
|
hub_ip:
|
||||||
name: Hub IP (valgfrit)
|
name: Hub IP (valgfri)
|
||||||
description: Lad stå tom for automatisk opdagelse.
|
description: Lad feltet være tomt for automatisk opdagelse.
|
||||||
username:
|
fh_username:
|
||||||
name: Brugernavn
|
name: Lokal API-brugernavn
|
||||||
description: Dit brugernavn til lokal API/MQTT-adgang til Smarthub.
|
description: Dit Smarthub lokale API/MQTT-brugernavn.
|
||||||
password:
|
fh_password:
|
||||||
name: Adgangskode
|
name: Lokal API-adgangskode
|
||||||
description: Din adgangskode til lokal API/MQTT-adgang til Smarthub.
|
description: Din Smarthub lokale API/MQTT-adgangskode.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplex-brugernavn (valgfri)
|
||||||
|
description: Dit Thingsplex-brugernavn.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplex-adgangskode (valgfri)
|
||||||
|
description: Din Thingsplex-adgangskode.
|
||||||
demo_mode:
|
demo_mode:
|
||||||
name: Demotilstand
|
name: Demotilstand
|
||||||
description: Brug en optaget tilstand fra en ægte Futurehome Smarthub til at simulere enheder.
|
description: Brug en optaget prøvetilstand fra en rigtig Futurehome Smarthub til at simulere enheder.
|
||||||
show_debug_log:
|
show_debug_log:
|
||||||
name: Vis fejllog
|
name: Vis fejllog
|
||||||
|
21
futurehome/translations/ee.yaml
Normal file
21
futurehome/translations/ee.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
configuration:
|
||||||
|
hub_ip:
|
||||||
|
name: Hubi IP (valikuline)
|
||||||
|
description: Jäta tühjaks automaatseks tuvastamiseks.
|
||||||
|
fh_username:
|
||||||
|
name: Kohaliku API kasutajanimi
|
||||||
|
description: Sinu Smarthubi kohaliku API/MQTT kasutajanimi.
|
||||||
|
fh_password:
|
||||||
|
name: Kohaliku API parool
|
||||||
|
description: Sinu Smarthubi kohaliku API/MQTT parool.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplexi kasutajanimi (valikuline)
|
||||||
|
description: Sinu Thingsplexi kasutajanimi.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplexi parool (valikuline)
|
||||||
|
description: Sinu Thingsplexi parool.
|
||||||
|
demo_mode:
|
||||||
|
name: Demorežiim
|
||||||
|
description: Kasuta päris Futurehome Smarthubist salvestatud näidisseisu seadmete simuleerimiseks.
|
||||||
|
show_debug_log:
|
||||||
|
name: Näita silumislogi
|
@ -2,12 +2,18 @@ configuration:
|
|||||||
hub_ip:
|
hub_ip:
|
||||||
name: Hub IP (Optional)
|
name: Hub IP (Optional)
|
||||||
description: Leave blank for automatic discovery.
|
description: Leave blank for automatic discovery.
|
||||||
username:
|
fh_username:
|
||||||
name: Username
|
name: Local API Username
|
||||||
description: Your Smarthub local API/MQTT username.
|
description: Your Smarthub local API/MQTT username.
|
||||||
password:
|
fh_password:
|
||||||
name: Password
|
name: Local API Password
|
||||||
description: Your Smarthub local API/MQTT password.
|
description: Your Smarthub local API/MQTT password.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplex Username (Optional)
|
||||||
|
description: Your Thingsplex username.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplex Password (Optional)
|
||||||
|
description: Your Thingsplex password.
|
||||||
demo_mode:
|
demo_mode:
|
||||||
name: Demo Mode
|
name: Demo Mode
|
||||||
description: Use a sample recorded state from a real Futurehome Smarthub to simulate devices.
|
description: Use a sample recorded state from a real Futurehome Smarthub to simulate devices.
|
||||||
|
21
futurehome/translations/et.yaml
Normal file
21
futurehome/translations/et.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
configuration:
|
||||||
|
hub_ip:
|
||||||
|
name: Hubi IP (valikuline)
|
||||||
|
description: Jäta tühjaks automaatseks tuvastamiseks.
|
||||||
|
fh_username:
|
||||||
|
name: Kohaliku API kasutajanimi
|
||||||
|
description: Sinu Smarthubi kohaliku API/MQTT kasutajanimi.
|
||||||
|
fh_password:
|
||||||
|
name: Kohaliku API parool
|
||||||
|
description: Sinu Smarthubi kohaliku API/MQTT parool.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplexi kasutajanimi (valikuline)
|
||||||
|
description: Sinu Thingsplexi kasutajanimi.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplexi parool (valikuline)
|
||||||
|
description: Sinu Thingsplexi parool.
|
||||||
|
demo_mode:
|
||||||
|
name: Demorežiim
|
||||||
|
description: Kasuta päris Futurehome Smarthubist salvestatud näidisseisu seadmete simuleerimiseks.
|
||||||
|
show_debug_log:
|
||||||
|
name: Näita silumislogi
|
@ -1,15 +1,21 @@
|
|||||||
configuration:
|
configuration:
|
||||||
hub_ip:
|
hub_ip:
|
||||||
name: Keskittimen IP (valinnainen)
|
name: Hubin IP-osoite (valinnainen)
|
||||||
description: Jätä tyhjäksi automaattista tunnistusta varten.
|
description: Jätä tyhjäksi automaattista etsintää varten.
|
||||||
username:
|
fh_username:
|
||||||
name: Käyttäjätunnus
|
name: Paikallinen API-käyttäjätunnus
|
||||||
description: Paikallisen Smarthub API/MQTT -yhteyden käyttäjätunnus.
|
description: Smarthubin paikallinen API/MQTT-käyttäjätunnuksesi.
|
||||||
password:
|
fh_password:
|
||||||
name: Salasana
|
name: Paikallinen API-salasana
|
||||||
description: Paikallisen Smarthub API/MQTT -yhteyden salasana.
|
description: Smarthubin paikallinen API/MQTT-salasanasi.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplex-käyttäjätunnus (valinnainen)
|
||||||
|
description: Thingsplex-käyttäjätunnuksesi.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplex-salasana (valinnainen)
|
||||||
|
description: Thingsplex-salasanasi.
|
||||||
demo_mode:
|
demo_mode:
|
||||||
name: Demotila
|
name: Demotila
|
||||||
description: Käytä tallennettua esimerkkitilaa oikeasta Futurehome Smarthubista laitteiden simuloimiseen.
|
description: Käytä tallennettua tilanäytettä oikeasta Futurehome Smarthubista laitteiden simuloimiseen.
|
||||||
show_debug_log:
|
show_debug_log:
|
||||||
name: Näytä vianmääritysloki
|
name: Näytä virheloki
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
configuration:
|
configuration:
|
||||||
hub_ip:
|
hub_ip:
|
||||||
name: Miðlari IP (valkvæmt)
|
name: IP-tala miðlara (valkvætt)
|
||||||
description: Láttu autt til að uppgötva sjálfkrafa.
|
description: Skildu eftir autt til að uppgötva sjálfkrafa.
|
||||||
username:
|
fh_username:
|
||||||
name: Notandanafn
|
name: Notandanafn fyrir staðbundið API
|
||||||
description: Notandanafn þitt fyrir staðbundið API/MQTT aðgang að Smarthub.
|
description: Notandanafn fyrir staðbundið API/MQTT í Smarthub.
|
||||||
password:
|
fh_password:
|
||||||
name: Lykilorð
|
name: Lykilorð fyrir staðbundið API
|
||||||
description: Lykilorðið þitt fyrir staðbundið API/MQTT aðgang að Smarthub.
|
description: Lykilorð fyrir staðbundið API/MQTT í Smarthub.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplex notandanafn (valkvætt)
|
||||||
|
description: Notandanafn þitt fyrir Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplex lykilorð (valkvætt)
|
||||||
|
description: Lykilorðið þitt fyrir Thingsplex.
|
||||||
demo_mode:
|
demo_mode:
|
||||||
name: Sýnishamur
|
name: Sýnishamur
|
||||||
description: Notaðu skráða stöðu úr raunverulegum Futurehome Smarthub til að líkja eftir tækjum.
|
description: Notaðu upptaka af raunverulegu ástandi úr Futurehome Smarthub til að herma eftir tækjum.
|
||||||
show_debug_log:
|
show_debug_log:
|
||||||
name: Sýna aflúsunarskrá
|
name: Sýna villuskýrslu
|
||||||
|
21
futurehome/translations/lt.yaml
Normal file
21
futurehome/translations/lt.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
configuration:
|
||||||
|
hub_ip:
|
||||||
|
name: Hub IP (pasirinktinai)
|
||||||
|
description: Palikite tuščią automatiniam aptikimui.
|
||||||
|
fh_username:
|
||||||
|
name: Vietinio API naudotojo vardas
|
||||||
|
description: Jūsų Smarthub vietinio API/MQTT naudotojo vardas.
|
||||||
|
fh_password:
|
||||||
|
name: Vietinio API slaptažodis
|
||||||
|
description: Jūsų Smarthub vietinio API/MQTT slaptažodis.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplex naudotojo vardas (pasirinktinai)
|
||||||
|
description: Jūsų Thingsplex naudotojo vardas.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplex slaptažodis (pasirinktinai)
|
||||||
|
description: Jūsų Thingsplex slaptažodis.
|
||||||
|
demo_mode:
|
||||||
|
name: Demonstracinis režimas
|
||||||
|
description: Naudokite įrašytą būsena iš tikro Futurehome Smarthub, kad imituotumėte įrenginius.
|
||||||
|
show_debug_log:
|
||||||
|
name: Rodyti derinimo žurnalą
|
21
futurehome/translations/lv.yaml
Normal file
21
futurehome/translations/lv.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
configuration:
|
||||||
|
hub_ip:
|
||||||
|
name: Hub IP (pēc izvēles)
|
||||||
|
description: Atstāj tukšu automātiskai noteikšanai.
|
||||||
|
fh_username:
|
||||||
|
name: Vietējā API lietotājvārds
|
||||||
|
description: Tavs Smarthub vietējais API/MQTT lietotājvārds.
|
||||||
|
fh_password:
|
||||||
|
name: Vietējā API parole
|
||||||
|
description: Tava Smarthub vietējā API/MQTT parole.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplex lietotājvārds (pēc izvēles)
|
||||||
|
description: Tavs Thingsplex lietotājvārds.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplex parole (pēc izvēles)
|
||||||
|
description: Tava Thingsplex parole.
|
||||||
|
demo_mode:
|
||||||
|
name: Demonstrācijas režīms
|
||||||
|
description: Izmanto ierakstītu stāvokli no īsta Futurehome Smarthub, lai simulētu ierīces.
|
||||||
|
show_debug_log:
|
||||||
|
name: Rādīt atkļūdošanas žurnālu
|
@ -1,15 +1,21 @@
|
|||||||
configuration:
|
configuration:
|
||||||
hub_ip:
|
hub_ip:
|
||||||
name: Hub IP (valgfritt)
|
name: Hub-IP (valgfritt)
|
||||||
description: La stå tomt for automatisk oppdagelse.
|
description: La stå tomt for automatisk oppdagelse.
|
||||||
username:
|
fh_username:
|
||||||
name: Brukernavn
|
name: Lokalt API-brukernavn
|
||||||
description: Ditt brukernavn for lokal API/MQTT-tilgang til Smarthub.
|
description: Ditt lokale API-/MQTT-brukernavn for Smarthub.
|
||||||
password:
|
fh_password:
|
||||||
name: Passord
|
name: Lokalt API-passord
|
||||||
description: Ditt passord for lokal API/MQTT-tilgang til Smarthub.
|
description: Ditt lokale API-/MQTT-passord for Smarthub.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplex-brukernavn (valgfritt)
|
||||||
|
description: Ditt brukernavn for Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplex-passord (valgfritt)
|
||||||
|
description: Ditt passord for Thingsplex.
|
||||||
demo_mode:
|
demo_mode:
|
||||||
name: Demomodus
|
name: Demomodus
|
||||||
description: Bruk et forhåndsopptatt eksempel fra en ekte Futurehome Smarthub for å simulere enheter.
|
description: Bruk en forhåndsopptatt tilstand fra en ekte Futurehome Smarthub for å simulere enheter.
|
||||||
show_debug_log:
|
show_debug_log:
|
||||||
name: Vis feillogg
|
name: Vis feilsøkingslogg
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
configuration:
|
configuration:
|
||||||
hub_ip:
|
hub_ip:
|
||||||
name: Hub IP (valfritt)
|
name: Hub-IP (valfritt)
|
||||||
description: La stå tomt for automatisk oppdaging.
|
description: La stå tomt for automatisk oppdaging.
|
||||||
username:
|
fh_username:
|
||||||
name: Brukarnamn
|
name: Lokalt API-brukarnamn
|
||||||
description: Brukarnamnet ditt for lokal API/MQTT-tilgang til Smarthub.
|
description: Ditt lokale API-/MQTT-brukarnamn for Smarthub.
|
||||||
password:
|
fh_password:
|
||||||
name: Passord
|
name: Lokalt API-passord
|
||||||
description: Passordet ditt for lokal API/MQTT-tilgang til Smarthub.
|
description: Ditt lokale API-/MQTT-passord for Smarthub.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplex-brukarnamn (valfritt)
|
||||||
|
description: Ditt brukarnamn for Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplex-passord (valfritt)
|
||||||
|
description: Ditt passord for Thingsplex.
|
||||||
demo_mode:
|
demo_mode:
|
||||||
name: Demomodus
|
name: Demomodus
|
||||||
description: Bruk eit førehandsopptak frå ein ekte Futurehome Smarthub for å simulere einingar.
|
description: Bruk ein førehandsopptak frå ein ekte Futurehome Smarthub for å simulere einingar.
|
||||||
show_debug_log:
|
show_debug_log:
|
||||||
name: Vis feillogg
|
name: Vis feilsøkingslogg
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
configuration:
|
configuration:
|
||||||
hub_ip:
|
hub_ip:
|
||||||
name: Hub IP (valgfritt)
|
name: Hub-IP (valgfritt)
|
||||||
description: La stå tomt for automatisk oppdagelse.
|
description: La stå tomt for automatisk oppdagelse.
|
||||||
username:
|
fh_username:
|
||||||
name: Brukernavn
|
name: Lokalt API-brukernavn
|
||||||
description: Ditt brukernavn for lokal API/MQTT-tilgang til Smarthub.
|
description: Ditt lokale API-/MQTT-brukernavn for Smarthub.
|
||||||
password:
|
fh_password:
|
||||||
name: Passord
|
name: Lokalt API-passord
|
||||||
description: Ditt passord for lokal API/MQTT-tilgang til Smarthub.
|
description: Ditt lokale API-/MQTT-passord for Smarthub.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplex-brukernavn (valgfritt)
|
||||||
|
description: Ditt brukernavn for Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplex-passord (valgfritt)
|
||||||
|
description: Ditt passord for Thingsplex.
|
||||||
demo_mode:
|
demo_mode:
|
||||||
name: Demomodus
|
name: Demomodus
|
||||||
description: Bruk et forhåndsopptatt eksempel fra en ekte Futurehome Smarthub for å simulere enheter.
|
description: Bruk en forhåndsopptatt tilstand fra en ekte Futurehome Smarthub for å simulere enheter.
|
||||||
show_debug_log:
|
show_debug_log:
|
||||||
name: Vis feillogg
|
name: Vis feilsøkingslogg
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
configuration:
|
configuration:
|
||||||
hub_ip:
|
hub_ip:
|
||||||
name: IP huba (opcjonalne)
|
name: IP centralki (opcjonalne)
|
||||||
description: Pozostaw puste, aby wykryć automatycznie.
|
description: Pozostaw puste, aby włączyć automatyczne wykrywanie.
|
||||||
username:
|
fh_username:
|
||||||
name: Nazwa użytkownika
|
name: Nazwa użytkownika lokalnego API
|
||||||
description: Twoja nazwa użytkownika do lokalnego API/MQTT Smarthuba.
|
description: Twoja nazwa użytkownika lokalnego API/MQTT Smarthub.
|
||||||
password:
|
fh_password:
|
||||||
name: Hasło
|
name: Hasło do lokalnego API
|
||||||
description: Twoje hasło do lokalnego API/MQTT Smarthuba.
|
description: Twoje hasło do lokalnego API/MQTT Smarthub.
|
||||||
|
tp_username:
|
||||||
|
name: Nazwa użytkownika Thingsplex (opcjonalne)
|
||||||
|
description: Twoja nazwa użytkownika Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Hasło do Thingsplex (opcjonalne)
|
||||||
|
description: Twoje hasło do Thingsplex.
|
||||||
demo_mode:
|
demo_mode:
|
||||||
name: Tryb demo
|
name: Tryb demonstracyjny
|
||||||
description: Użyj przykładowego zapisanego stanu z prawdziwego Futurehome Smarthub, aby symulować urządzenia.
|
description: Użyj zapisanego stanu z prawdziwego Futurehome Smarthub, aby symulować urządzenia.
|
||||||
show_debug_log:
|
show_debug_log:
|
||||||
name: Pokaż dziennik debugowania
|
name: Pokaż dziennik debugowania
|
||||||
|
21
futurehome/translations/ru.yaml
Normal file
21
futurehome/translations/ru.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
configuration:
|
||||||
|
hub_ip:
|
||||||
|
name: IP хаба (необязательно)
|
||||||
|
description: Оставьте пустым для автоматического обнаружения.
|
||||||
|
fh_username:
|
||||||
|
name: Имя пользователя локального API
|
||||||
|
description: Ваше имя пользователя локального API/MQTT для Smarthub.
|
||||||
|
fh_password:
|
||||||
|
name: Пароль локального API
|
||||||
|
description: Ваш пароль локального API/MQTT для Smarthub.
|
||||||
|
tp_username:
|
||||||
|
name: Имя пользователя Thingsplex (необязательно)
|
||||||
|
description: Ваше имя пользователя Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Пароль Thingsplex (необязательно)
|
||||||
|
description: Ваш пароль Thingsplex.
|
||||||
|
demo_mode:
|
||||||
|
name: Демонстрационный режим
|
||||||
|
description: Используйте сохранённое состояние от настоящего Futurehome Smarthub для имитации устройств.
|
||||||
|
show_debug_log:
|
||||||
|
name: Показать отладочный журнал
|
@ -1,15 +1,21 @@
|
|||||||
configuration:
|
configuration:
|
||||||
hub_ip:
|
hub_ip:
|
||||||
name: Hub IP (valfritt)
|
name: Hubbens IP (valfritt)
|
||||||
description: Lämna tomt för automatisk upptäckt.
|
description: Lämna tomt för automatisk upptäckt.
|
||||||
username:
|
fh_username:
|
||||||
name: Användarnamn
|
name: Lokalt API-användarnamn
|
||||||
description: Ditt användarnamn för lokal API/MQTT-åtkomst till Smarthub.
|
description: Ditt lokala API-/MQTT-användarnamn för Smarthub.
|
||||||
password:
|
fh_password:
|
||||||
name: Lösenord
|
name: Lösenord för lokalt API
|
||||||
description: Ditt lösenord för lokal API/MQTT-åtkomst till Smarthub.
|
description: Ditt lokala API-/MQTT-lösenord för Smarthub.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplex-användarnamn (valfritt)
|
||||||
|
description: Ditt användarnamn för Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplex-lösenord (valfritt)
|
||||||
|
description: Ditt lösenord för Thingsplex.
|
||||||
demo_mode:
|
demo_mode:
|
||||||
name: Demoläge
|
name: Demoläge
|
||||||
description: Använd ett inspelat exempel från en riktig Futurehome Smarthub för att simulera enheter.
|
description: Använd ett inspelat exempel från en riktig Futurehome Smarthub för att simulera enheter.
|
||||||
show_debug_log:
|
show_debug_log:
|
||||||
name: Čájet divrrodagaslogu
|
name: Visa felsökningslogg
|
||||||
|
21
futurehome/translations/sk.yaml
Normal file
21
futurehome/translations/sk.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
configuration:
|
||||||
|
hub_ip:
|
||||||
|
name: IP adresa hubu (voliteľné)
|
||||||
|
description: Nechajte prázdne pre automatické vyhľadanie.
|
||||||
|
fh_username:
|
||||||
|
name: Používateľské meno lokálneho API
|
||||||
|
description: Vaše používateľské meno pre lokálne API/MQTT Smarthubu.
|
||||||
|
fh_password:
|
||||||
|
name: Heslo lokálneho API
|
||||||
|
description: Vaše heslo pre lokálne API/MQTT Smarthubu.
|
||||||
|
tp_username:
|
||||||
|
name: Používateľské meno Thingsplex (voliteľné)
|
||||||
|
description: Vaše používateľské meno pre Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Heslo Thingsplex (voliteľné)
|
||||||
|
description: Vaše heslo pre Thingsplex.
|
||||||
|
demo_mode:
|
||||||
|
name: Demo režim
|
||||||
|
description: Použite uložený stav zo skutočného Futurehome Smarthubu na simuláciu zariadení.
|
||||||
|
show_debug_log:
|
||||||
|
name: Zobraziť ladicí protokol
|
@ -1,13 +1,19 @@
|
|||||||
configuration:
|
configuration:
|
||||||
hub_ip:
|
hub_ip:
|
||||||
name: Hub IP (valfritt)
|
name: Hubbens IP (valfritt)
|
||||||
description: Lämna tomt för automatisk upptäckt.
|
description: Lämna tomt för automatisk upptäckt.
|
||||||
username:
|
fh_username:
|
||||||
name: Användarnamn
|
name: Lokalt API-användarnamn
|
||||||
description: Ditt användarnamn för lokal API/MQTT-åtkomst till Smarthub.
|
description: Ditt lokala API-/MQTT-användarnamn för Smarthub.
|
||||||
password:
|
fh_password:
|
||||||
name: Lösenord
|
name: Lösenord för lokalt API
|
||||||
description: Ditt lösenord för lokal API/MQTT-åtkomst till Smarthub.
|
description: Ditt lokala API-/MQTT-lösenord för Smarthub.
|
||||||
|
tp_username:
|
||||||
|
name: Thingsplex-användarnamn (valfritt)
|
||||||
|
description: Ditt användarnamn för Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Thingsplex-lösenord (valfritt)
|
||||||
|
description: Ditt lösenord för Thingsplex.
|
||||||
demo_mode:
|
demo_mode:
|
||||||
name: Demoläge
|
name: Demoläge
|
||||||
description: Använd ett inspelat exempel från en riktig Futurehome Smarthub för att simulera enheter.
|
description: Använd ett inspelat exempel från en riktig Futurehome Smarthub för att simulera enheter.
|
||||||
|
21
futurehome/translations/ua.yaml
Normal file
21
futurehome/translations/ua.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
configuration:
|
||||||
|
hub_ip:
|
||||||
|
name: IP хабу (необов’язково)
|
||||||
|
description: Залиште порожнім для автоматичного виявлення.
|
||||||
|
fh_username:
|
||||||
|
name: Ім’я користувача локального API
|
||||||
|
description: Ваше ім’я користувача локального API/MQTT для Smarthub.
|
||||||
|
fh_password:
|
||||||
|
name: Пароль локального API
|
||||||
|
description: Ваш пароль локального API/MQTT для Smarthub.
|
||||||
|
tp_username:
|
||||||
|
name: Ім’я користувача Thingsplex (необов’язково)
|
||||||
|
description: Ваше ім’я користувача для Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Пароль Thingsplex (необов’язково)
|
||||||
|
description: Ваш пароль для Thingsplex.
|
||||||
|
demo_mode:
|
||||||
|
name: Демонстраційний режим
|
||||||
|
description: Використовуйте записаний стан із реального Futurehome Smarthub для імітації пристроїв.
|
||||||
|
show_debug_log:
|
||||||
|
name: Показувати журнал налагодження
|
21
futurehome/translations/uk.yaml
Normal file
21
futurehome/translations/uk.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
configuration:
|
||||||
|
hub_ip:
|
||||||
|
name: IP хабу (необов’язково)
|
||||||
|
description: Залиште порожнім для автоматичного виявлення.
|
||||||
|
fh_username:
|
||||||
|
name: Ім’я користувача локального API
|
||||||
|
description: Ваше ім’я користувача локального API/MQTT для Smarthub.
|
||||||
|
fh_password:
|
||||||
|
name: Пароль локального API
|
||||||
|
description: Ваш пароль локального API/MQTT для Smarthub.
|
||||||
|
tp_username:
|
||||||
|
name: Ім’я користувача Thingsplex (необов’язково)
|
||||||
|
description: Ваше ім’я користувача для Thingsplex.
|
||||||
|
tp_password:
|
||||||
|
name: Пароль Thingsplex (необов’язково)
|
||||||
|
description: Ваш пароль для Thingsplex.
|
||||||
|
demo_mode:
|
||||||
|
name: Демонстраційний режим
|
||||||
|
description: Використовуйте записаний стан із реального Futurehome Smarthub для імітації пристроїв.
|
||||||
|
show_debug_log:
|
||||||
|
name: Показувати журнал налагодження
|
Loading…
x
Reference in New Issue
Block a user