mirror of
https://github.com/adrianjagielak/home-assistant-futurehome.git
synced 2025-11-18 17:19:02 +00:00
Compare commits
29 Commits
0bb82f6d95
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce36669587 | ||
|
|
dac16b0fd4 | ||
|
|
45182a6416 | ||
|
|
9f2feea8c1 | ||
|
|
a38e441c9b | ||
|
|
afbfd1d1c7 | ||
|
|
729c6c839f | ||
|
|
b937f90340 | ||
|
|
4a3eb07464 | ||
|
|
5732c70d4e | ||
|
|
16a4fb3181 | ||
|
|
fdc65a0bd5 | ||
|
|
91c33b33cd | ||
|
|
6ca05e95b9 | ||
|
|
7e3d56cec1 | ||
|
|
a8c61c4658 | ||
|
|
653df93807 | ||
|
|
50500e97be | ||
|
|
f216f4b719 | ||
|
|
e7cab97142 | ||
|
|
e39bfbcde8 | ||
|
|
060ae593f8 | ||
|
|
383980d5f8 | ||
|
|
41cd550225 | ||
|
|
060947e06b | ||
|
|
a05e96bae0 | ||
|
|
000537585d | ||
|
|
351274f56e | ||
|
|
a8e5b00275 |
8
.github/workflows/builder.yaml
vendored
8
.github/workflows/builder.yaml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
changed: ${{ steps.changed_addons.outputs.changed }}
|
||||
steps:
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v5.0.0
|
||||
|
||||
- name: Get changed files
|
||||
id: changed_files
|
||||
@@ -71,7 +71,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v5.0.0
|
||||
|
||||
- name: Get information
|
||||
id: info
|
||||
@@ -98,7 +98,7 @@ jobs:
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: env.BUILD_ARGS != '--test'
|
||||
uses: docker/login-action@v3.4.0
|
||||
uses: docker/login-action@v3.5.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
@@ -106,7 +106,7 @@ jobs:
|
||||
|
||||
- name: Build ${{ matrix.addon }} add-on
|
||||
if: steps.check.outputs.build_arch == 'true'
|
||||
uses: home-assistant/builder@2025.03.0
|
||||
uses: home-assistant/builder@2025.09.0
|
||||
with:
|
||||
args: |
|
||||
${{ env.BUILD_ARGS }} \
|
||||
|
||||
4
.github/workflows/lint.yaml
vendored
4
.github/workflows/lint.yaml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
addons: ${{ steps.addons.outputs.addons_list }}
|
||||
steps:
|
||||
- name: ⤵️ Check out code from GitHub
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v5.0.0
|
||||
|
||||
- name: 🔍 Find add-on directories
|
||||
id: addons
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
path: ${{ fromJson(needs.find.outputs.addons) }}
|
||||
steps:
|
||||
- name: ⤵️ Check out code from GitHub
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v5.0.0
|
||||
|
||||
- name: 🚀 Run Home Assistant Add-on Lint
|
||||
uses: frenck/action-addon-linter@v2.18
|
||||
|
||||
@@ -7,6 +7,8 @@ Futurehome add-on for Home Assistant. Designed to be a complete drop-in replacem
|
||||
|
||||

|
||||
|
||||
[Watch the official add-on demo video](https://www.youtube.com/watch?v=dmEy6R49CC0)
|
||||
|
||||
## Features
|
||||
|
||||
This add-on:
|
||||
@@ -40,7 +42,7 @@ Some services are more common than others; some are deprecated entirely.
|
||||
| Media player | [media_player](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/media_player.ts) | | ✅ | [Select](https://www.home-assistant.io/integrations/select/), [Number](https://www.home-assistant.io/integrations/number/), [Switch](https://www.home-assistant.io/integrations/switch/), [Image](https://www.home-assistant.io/integrations/image/), [Sensor](https://www.home-assistant.io/integrations/sensor/) |
|
||||
| Meter | [meter_elec](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/_meter.ts), [meter_gas](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/_meter.ts), [meter_water](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/_meter.ts), [meter_heating](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/_meter.ts), [meter_cooling](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/_meter.ts) | [HAN-Sensor](https://www.futurehome.io/en/shop/han-sensor) | ✅ | [Sensor](https://www.home-assistant.io/integrations/sensor/), [Button](https://www.home-assistant.io/integrations/button/) |
|
||||
| Binary switch | [out_bin_switch](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/out_bin_switch.ts) | [16A Puck Relé](https://www.futurehome.io/en_no/shop/puck-relay-16a) | ✅ | [Switch](https://www.home-assistant.io/integrations/switch/) |
|
||||
| Level switch | [out_lvl_switch](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/out_lvl_switch.ts) | [Smart LED Dimmer](https://www.futurehome.io/en_no/shop/smart-led-dimmer-polar-white) | ✅ | [Number](https://www.home-assistant.io/integrations/number/) |
|
||||
| Level switch | [out_lvl_switch](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/out_lvl_switch.ts) | [Smart LED Dimmer](https://www.futurehome.io/en_no/shop/smart-led-dimmer-polar-white) | ✅ | [Light](https://www.home-assistant.io/integrations/light/), [Number](https://www.home-assistant.io/integrations/number/) |
|
||||
| Button | [scene_ctrl](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/scene_ctrl.ts) | [Modusbryter](https://www.futurehome.io/en_no/shop/modeswitch-white) | ✅ | [Sensor](https://www.home-assistant.io/integrations/sensor/), [Select](https://www.home-assistant.io/integrations/select/) |
|
||||
| Schedule entry | [schedule_entry](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/schedule_entry.ts) | | ✅ | [Number](https://www.home-assistant.io/integrations/number/), [Button](https://www.home-assistant.io/integrations/button/), [Binary sensor](https://www.home-assistant.io/integrations/binary_sensor/), [Sensor](https://www.home-assistant.io/integrations/sensor/) |
|
||||
| Binary sensor | [sensor_contact](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/_sensor_binary.ts), [sensor_presence](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/_sensor_binary.ts) | | ✅ | [Binary sensor](https://www.home-assistant.io/integrations/binary_sensor/) |
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
4. **Enable MQTT Integration**
|
||||
|
||||
In Home Assistant, go to **Settings > Devices & Services > Integrations** and enable **MQTT**.
|
||||
Add the MQTT integration by going to **Settings → Devices & Services → Integrations → Add integration**, search for and select **MQTT → MQTT**, then choose **"Use the official Mosquitto MQTT Broker add-on"**.
|
||||
|
||||
5. **Install the Futurehome Add-on**
|
||||
|
||||
|
||||
@@ -1,5 +1,53 @@
|
||||
<!-- https://developers.home-assistant.io/docs/add-ons/presentation#keeping-a-changelog -->
|
||||
|
||||
## 1.6.1 (16.10.2025)
|
||||
|
||||
- Tweaked 'Ignore Availability Reports' setting.
|
||||
|
||||
## 1.6.0 (16.10.2025)
|
||||
|
||||
- Added setting to always treat all devices as up.
|
||||
|
||||
## 1.5.0 (16.10.2025)
|
||||
|
||||
- Reverted: Add ability to specify a custom MQTT broker.
|
||||
|
||||
## 1.4.0 (13.10.2025)
|
||||
|
||||
- Added ability to specify a custom MQTT broker.
|
||||
|
||||
## 1.3.1 (28.09.2025)
|
||||
|
||||
- Revert upgrading dependencies.
|
||||
|
||||
## 1.3.0 (28.09.2025)
|
||||
|
||||
- Upgrade dependencies.
|
||||
- Use proper `light` entity for out_lvl_switch if the device type is "light", instead of generic `number` level switch (thanks @Andbli for help!).
|
||||
|
||||
## 1.2.1 (26.09.2025)
|
||||
|
||||
- Revert 'Use `light` entity for out_lvl_switch if the device type is "light"'.
|
||||
|
||||
## 1.2.0 (26.09.2025)
|
||||
|
||||
- Use `light` entity for out_lvl_switch if the device type is "light".
|
||||
|
||||
## 1.1.2 (24.09.2025)
|
||||
|
||||
- Bumped dependencies (#1, #2, #6).
|
||||
|
||||
## 1.1.1 (24.09.2025)
|
||||
|
||||
- Added error handling for invalid FIMP messages.
|
||||
- Updated installation.md - clarified that users must select the MQTT Integration instead of the hub’s MQTT server, with step-by-step guidance provided (@Andbli).
|
||||
|
||||
## 1.1.0 (24.09.2025)
|
||||
|
||||
- Stop inclusion/exclusion after the first device is added/removed, just like in the official app.
|
||||
- Add configuration checkbox for allowing empty Thingsplex credentials (#3).
|
||||
- Improved GUI security by hiding passwords by default (#4, #5) (thanks @Andbli !).
|
||||
|
||||
## 1.0.2 (16.09.2025)
|
||||
|
||||
- Added logging the initial devices response.
|
||||
|
||||
@@ -6,6 +6,8 @@ Futurehome add-on for Home Assistant. Designed to be a complete drop-in replacem
|
||||
|
||||

|
||||
|
||||
[Watch the official add-on demo video](https://www.youtube.com/watch?v=dmEy6R49CC0)
|
||||
|
||||
## Features
|
||||
|
||||
This add-on:
|
||||
@@ -39,7 +41,7 @@ Some services are more common than others; some are deprecated entirely.
|
||||
| Media player | [media_player](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/media_player.ts) | | ✅ | [Select](https://www.home-assistant.io/integrations/select/), [Number](https://www.home-assistant.io/integrations/number/), [Switch](https://www.home-assistant.io/integrations/switch/), [Image](https://www.home-assistant.io/integrations/image/), [Sensor](https://www.home-assistant.io/integrations/sensor/) |
|
||||
| Meter | [meter_elec](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/_meter.ts), [meter_gas](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/_meter.ts), [meter_water](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/_meter.ts), [meter_heating](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/_meter.ts), [meter_cooling](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/_meter.ts) | [HAN-Sensor](https://www.futurehome.io/en/shop/han-sensor) | ✅ | [Sensor](https://www.home-assistant.io/integrations/sensor/), [Button](https://www.home-assistant.io/integrations/button/) |
|
||||
| Binary switch | [out_bin_switch](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/out_bin_switch.ts) | [16A Puck Relé](https://www.futurehome.io/en_no/shop/puck-relay-16a) | ✅ | [Switch](https://www.home-assistant.io/integrations/switch/) |
|
||||
| Level switch | [out_lvl_switch](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/out_lvl_switch.ts) | [Smart LED Dimmer](https://www.futurehome.io/en_no/shop/smart-led-dimmer-polar-white) | ✅ | [Number](https://www.home-assistant.io/integrations/number/) |
|
||||
| Level switch | [out_lvl_switch](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/out_lvl_switch.ts) | [Smart LED Dimmer](https://www.futurehome.io/en_no/shop/smart-led-dimmer-polar-white) | ✅ | [Light](https://www.home-assistant.io/integrations/light/), [Number](https://www.home-assistant.io/integrations/number/) |
|
||||
| Button | [scene_ctrl](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/scene_ctrl.ts) | [Modusbryter](https://www.futurehome.io/en_no/shop/modeswitch-white) | ✅ | [Sensor](https://www.home-assistant.io/integrations/sensor/), [Select](https://www.home-assistant.io/integrations/select/) |
|
||||
| Schedule entry | [schedule_entry](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/schedule_entry.ts) | | ✅ | [Number](https://www.home-assistant.io/integrations/number/), [Button](https://www.home-assistant.io/integrations/button/), [Binary sensor](https://www.home-assistant.io/integrations/binary_sensor/), [Sensor](https://www.home-assistant.io/integrations/sensor/) |
|
||||
| Binary sensor | [sensor_contact](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/_sensor_binary.ts), [sensor_presence](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/_sensor_binary.ts) | | ✅ | [Binary sensor](https://www.home-assistant.io/integrations/binary_sensor/) |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config
|
||||
name: Futurehome
|
||||
version: '1.0.2'
|
||||
version: '1.6.1'
|
||||
slug: futurehome
|
||||
description: Local Futurehome Smarthub integration
|
||||
url: 'https://github.com/adrianjagielak/home-assistant-futurehome'
|
||||
@@ -21,15 +21,19 @@ options:
|
||||
fh_password: ''
|
||||
tp_username: ''
|
||||
tp_password: ''
|
||||
tp_allow_empty: false
|
||||
ignore_availability_reports: false
|
||||
demo_mode: false
|
||||
show_debug_log: false
|
||||
|
||||
schema:
|
||||
hub_ip: 'str?'
|
||||
fh_username: 'str?'
|
||||
fh_password: 'str?'
|
||||
fh_password: 'password?'
|
||||
tp_username: 'str?'
|
||||
tp_password: 'str?'
|
||||
tp_password: 'password?'
|
||||
tp_allow_empty: 'bool?'
|
||||
ignore_availability_reports: 'bool?'
|
||||
demo_mode: 'bool?'
|
||||
show_debug_log: 'bool?'
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ export FH_USERNAME=$(bashio::config 'fh_username')
|
||||
export FH_PASSWORD=$(bashio::config 'fh_password')
|
||||
export TP_USERNAME=$(bashio::config 'tp_username')
|
||||
export TP_PASSWORD=$(bashio::config 'tp_password')
|
||||
export TP_ALLOW_EMPTY=$(bashio::config 'tp_allow_empty')
|
||||
export IGNORE_AVAILABILITY_REPORTS=$(bashio::config 'ignore_availability_reports')
|
||||
export DEMO_MODE=$(bashio::config 'demo_mode')
|
||||
export SHOW_DEBUG_LOG=$(bashio::config 'show_debug_log')
|
||||
|
||||
|
||||
@@ -82,7 +82,24 @@ export async function sendFimpMsg({
|
||||
}, timeoutMs);
|
||||
|
||||
const onResponse = (topic: string, buffer: any) => {
|
||||
const msg = JSON.parse(buffer.toString());
|
||||
let bufferToString;
|
||||
try {
|
||||
bufferToString = buffer.toString();
|
||||
} catch (e) {
|
||||
log.warn('Invalid message received from hub MQTT broker', e);
|
||||
return;
|
||||
}
|
||||
|
||||
let msg;
|
||||
try {
|
||||
msg = JSON.parse(bufferToString);
|
||||
} catch (e) {
|
||||
log.warn(
|
||||
`Invalid FIMP message received from hub MQTT broker\nMessage: ${bufferToString}`,
|
||||
e,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.corid === uid) {
|
||||
if (msg.type === 'evt.error.report') {
|
||||
|
||||
@@ -400,12 +400,150 @@ export function handleExclusionStatusReport(hubId: string, msg: FimpResponse) {
|
||||
);
|
||||
}
|
||||
|
||||
export function handleInclusionReport() {
|
||||
export async function handleInclusionReport(parameters: {
|
||||
hubId: string;
|
||||
demoMode: boolean;
|
||||
hubIp: string;
|
||||
thingsplexUsername: string;
|
||||
thingsplexPassword: string;
|
||||
thingsplexAllowEmpty: boolean;
|
||||
}) {
|
||||
const topicPrefix = `homeassistant/device/futurehome_${parameters.hubId}_hub`;
|
||||
|
||||
pollVinculum('device').catch((e) => log.warn('Failed to request devices', e));
|
||||
pollVinculum('state').catch((e) => log.warn('Failed to request state', e));
|
||||
|
||||
if (parameters.demoMode) {
|
||||
ha?.publish(`${topicPrefix}/inclusion_exclusion_status/state`, 'Done', {
|
||||
retain: true,
|
||||
qos: 2,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
export function handleExclusionReport() {
|
||||
if (
|
||||
!parameters.thingsplexAllowEmpty &&
|
||||
!parameters.thingsplexUsername &&
|
||||
!parameters.thingsplexPassword
|
||||
) {
|
||||
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_exclusion_status/state`, 'Done', {
|
||||
retain: true,
|
||||
qos: 2,
|
||||
});
|
||||
} catch (e) {
|
||||
log.error('Failed trying to stop inclusion/exclusion', e);
|
||||
ha?.publish(
|
||||
`${topicPrefix}/inclusion_exclusion_status/state`,
|
||||
'Failed trying to stop inclusion/exclusion.',
|
||||
{
|
||||
retain: true,
|
||||
qos: 2,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleExclusionReport(parameters: {
|
||||
hubId: string;
|
||||
demoMode: boolean;
|
||||
hubIp: string;
|
||||
thingsplexUsername: string;
|
||||
thingsplexPassword: string;
|
||||
thingsplexAllowEmpty: boolean;
|
||||
}) {
|
||||
const topicPrefix = `homeassistant/device/futurehome_${parameters.hubId}_hub`;
|
||||
|
||||
pollVinculum('device').catch((e) => log.warn('Failed to request devices', e));
|
||||
pollVinculum('state').catch((e) => log.warn('Failed to request state', e));
|
||||
|
||||
if (parameters.demoMode) {
|
||||
ha?.publish(`${topicPrefix}/inclusion_exclusion_status/state`, 'Done', {
|
||||
retain: true,
|
||||
qos: 2,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!parameters.thingsplexAllowEmpty &&
|
||||
!parameters.thingsplexUsername &&
|
||||
!parameters.thingsplexPassword
|
||||
) {
|
||||
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.exclusion',
|
||||
val: false,
|
||||
val_t: 'bool',
|
||||
},
|
||||
{
|
||||
address: 'pt:j1/mt:cmd/rt:ad/rn:zw/ad:1',
|
||||
service: 'zwave-ad',
|
||||
cmd: 'cmd.thing.exclusion',
|
||||
val: false,
|
||||
val_t: 'bool',
|
||||
},
|
||||
],
|
||||
);
|
||||
ha?.publish(`${topicPrefix}/inclusion_exclusion_status/state`, 'Done', {
|
||||
retain: true,
|
||||
qos: 2,
|
||||
});
|
||||
} catch (e) {
|
||||
log.error('Failed trying to stop inclusion/exclusion', e);
|
||||
ha?.publish(
|
||||
`${topicPrefix}/inclusion_exclusion_status/state`,
|
||||
'Failed trying to stop inclusion/exclusion.',
|
||||
{
|
||||
retain: true,
|
||||
qos: 2,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,6 +208,7 @@ export function haPublishDevice(parameters: {
|
||||
deviceInclusionReport: InclusionReport | undefined;
|
||||
thingsplexUsername: string;
|
||||
thingsplexPassword: string;
|
||||
thingsplexAllowEmpty: boolean;
|
||||
}): { commandHandlers: CommandHandlers } {
|
||||
const components: { [key: string]: HaMqttComponent } = {};
|
||||
const handlers: CommandHandlers = {};
|
||||
@@ -261,8 +262,8 @@ export function haPublishDevice(parameters: {
|
||||
}
|
||||
|
||||
if (
|
||||
parameters.thingsplexUsername &&
|
||||
parameters.thingsplexPassword &&
|
||||
(parameters.thingsplexAllowEmpty ||
|
||||
(parameters.thingsplexUsername && parameters.thingsplexPassword)) &&
|
||||
parameters.vinculumDeviceData.fimp?.address &&
|
||||
parameters.vinculumDeviceData.fimp?.adapter
|
||||
) {
|
||||
|
||||
@@ -22,6 +22,14 @@ import { pollVinculum } from './fimp/vinculum';
|
||||
const localApiPassword = process.env.FH_PASSWORD || '';
|
||||
const thingsplexUsername = process.env.TP_USERNAME || '';
|
||||
const thingsplexPassword = process.env.TP_PASSWORD || '';
|
||||
const thingsplexAllowEmpty = (process.env.TP_ALLOW_EMPTY || '')
|
||||
.toLowerCase()
|
||||
.includes('true');
|
||||
const ignoreAvailabilityReports = (
|
||||
process.env.IGNORE_AVAILABILITY_REPORTS || ''
|
||||
)
|
||||
.toLowerCase()
|
||||
.includes('true');
|
||||
const demoMode = (process.env.DEMO_MODE || '').toLowerCase().includes('true');
|
||||
const showDebugLog = (process.env.SHOW_DEBUG_LOG || '')
|
||||
.toLowerCase()
|
||||
@@ -79,9 +87,7 @@ import { pollVinculum } from './fimp/vinculum';
|
||||
const hubId = house.val.param.house.hubId;
|
||||
|
||||
const devices = await pollVinculum('device');
|
||||
log.debug(
|
||||
`FIMP devices:\n${JSON.stringify(devices, null, 0)}`,
|
||||
);
|
||||
log.debug(`FIMP devices:\n${JSON.stringify(devices, null, 0)}`);
|
||||
|
||||
const haConfig = retainedMessages.filter((msg) =>
|
||||
msg.topic.endsWith('/config'),
|
||||
@@ -166,6 +172,7 @@ import { pollVinculum } from './fimp/vinculum';
|
||||
deviceInclusionReport,
|
||||
thingsplexUsername,
|
||||
thingsplexPassword,
|
||||
thingsplexAllowEmpty,
|
||||
});
|
||||
await delay(50);
|
||||
|
||||
@@ -189,7 +196,11 @@ import { pollVinculum } from './fimp/vinculum';
|
||||
log.error('Failed publishing device', device, e);
|
||||
}
|
||||
}
|
||||
if (demoMode || (thingsplexUsername && thingsplexPassword)) {
|
||||
if (
|
||||
demoMode ||
|
||||
thingsplexAllowEmpty ||
|
||||
(thingsplexUsername && thingsplexPassword)
|
||||
) {
|
||||
Object.assign(
|
||||
commandHandlers,
|
||||
exposeSmarthubTools({
|
||||
@@ -263,6 +274,9 @@ import { pollVinculum } from './fimp/vinculum';
|
||||
return;
|
||||
}
|
||||
for (const deviceAvailability of devicesAvailability) {
|
||||
if (ignoreAvailabilityReports) {
|
||||
deviceAvailability.status = 'UP';
|
||||
}
|
||||
haUpdateAvailability({ hubId, deviceAvailability });
|
||||
await delay(50);
|
||||
}
|
||||
@@ -280,12 +294,26 @@ import { pollVinculum } from './fimp/vinculum';
|
||||
}
|
||||
|
||||
case 'evt.thing.inclusion_report': {
|
||||
handleInclusionReport();
|
||||
handleInclusionReport({
|
||||
hubId,
|
||||
demoMode,
|
||||
hubIp,
|
||||
thingsplexUsername,
|
||||
thingsplexPassword,
|
||||
thingsplexAllowEmpty,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case 'evt.thing.exclusion_report': {
|
||||
handleExclusionReport();
|
||||
handleExclusionReport({
|
||||
hubId,
|
||||
demoMode,
|
||||
hubIp,
|
||||
thingsplexUsername,
|
||||
thingsplexPassword,
|
||||
thingsplexAllowEmpty,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -2518,5 +2518,128 @@
|
||||
"props": { "sup_units": ["km/h"] }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client": { "name": "Spisestue" },
|
||||
"fimp": { "adapter": "zwave-ad", "address": "6", "group": "ch_0" },
|
||||
"functionality": "lighting",
|
||||
"id": 1011,
|
||||
"lrn": true,
|
||||
"model": "zw_411_4_8705",
|
||||
"param": {
|
||||
"dimValue": 3,
|
||||
"energy": 49.6100006103516,
|
||||
"power": "off",
|
||||
"timestamp": "2025-09-26 18:32:21 +0200",
|
||||
"wattage": 0,
|
||||
"zwaveConfigParameters": []
|
||||
},
|
||||
"problem": false,
|
||||
"room": 1,
|
||||
"services": {
|
||||
"dev_sys": {
|
||||
"addr": "/rt:dev/rn:zw/ad:1/sv:dev_sys/ad:1011_0",
|
||||
"enabled": true,
|
||||
"intf": [
|
||||
"cmd.config.get_report",
|
||||
"cmd.config.set",
|
||||
"cmd.group.add_members",
|
||||
"cmd.group.delete_members",
|
||||
"cmd.group.get_members",
|
||||
"cmd.ping.send",
|
||||
"evt.config.report",
|
||||
"evt.group.members_report",
|
||||
"evt.ping.report"
|
||||
],
|
||||
"props": { "is_secure": false, "is_unsecure": true }
|
||||
},
|
||||
"indicator_ctrl": {
|
||||
"addr": "/rt:dev/rn:zw/ad:1/sv:indicator_ctrl/ad:1011_0",
|
||||
"enabled": true,
|
||||
"intf": [
|
||||
"cmd.indicator.identify",
|
||||
"cmd.indicator.set_visual_element"
|
||||
],
|
||||
"props": { "is_secure": false, "is_unsecure": true }
|
||||
},
|
||||
"meter_elec": {
|
||||
"addr": "/rt:dev/rn:zw/ad:1/sv:meter_elec/ad:1011_0",
|
||||
"enabled": true,
|
||||
"intf": [
|
||||
"cmd.meter.get_report",
|
||||
"cmd.meter.reset",
|
||||
"evt.meter.report"
|
||||
],
|
||||
"props": {
|
||||
"is_secure": false,
|
||||
"is_unsecure": true,
|
||||
"sup_export_units": [],
|
||||
"sup_units": ["kWh", "W"]
|
||||
}
|
||||
},
|
||||
"out_lvl_switch": {
|
||||
"addr": "/rt:dev/rn:zw/ad:1/sv:out_lvl_switch/ad:1011_0",
|
||||
"enabled": true,
|
||||
"intf": [
|
||||
"cmd.binary.set",
|
||||
"cmd.lvl.get_report",
|
||||
"cmd.lvl.set",
|
||||
"cmd.lvl.start",
|
||||
"cmd.lvl.stop",
|
||||
"evt.binary.report",
|
||||
"evt.lvl.report"
|
||||
],
|
||||
"props": {
|
||||
"is_secure": false,
|
||||
"is_unsecure": true,
|
||||
"max_lvl": 100,
|
||||
"min_lvl": 0
|
||||
}
|
||||
},
|
||||
"scene_ctrl": {
|
||||
"addr": "/rt:dev/rn:zw/ad:1/sv:scene_ctrl/ad:1011_0",
|
||||
"enabled": true,
|
||||
"intf": ["evt.scene.report"],
|
||||
"props": {
|
||||
"is_secure": false,
|
||||
"is_unsecure": true,
|
||||
"sup_scenes": [
|
||||
"1.key_pressed_1_time",
|
||||
"1.key_released",
|
||||
"1.key_held_down",
|
||||
"1.key_pressed_2_times",
|
||||
"1.key_pressed_3_times",
|
||||
"1.key_pressed_4_times",
|
||||
"1.key_pressed_5_times",
|
||||
"2.key_pressed_1_time",
|
||||
"2.key_released",
|
||||
"2.key_held_down",
|
||||
"2.key_pressed_2_times",
|
||||
"2.key_pressed_3_times",
|
||||
"2.key_pressed_4_times",
|
||||
"2.key_pressed_5_times"
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
"addr": "/rt:dev/rn:zw/ad:1/sv:version/ad:1011_0",
|
||||
"enabled": true,
|
||||
"intf": ["cmd.version.get_report", "evt.version.report"],
|
||||
"props": { "is_secure": false, "is_unsecure": true }
|
||||
}
|
||||
},
|
||||
"supports": ["clear", "poll"],
|
||||
"thing": 1,
|
||||
"type": {
|
||||
"subtype": null,
|
||||
"supported": {
|
||||
"appliance": [],
|
||||
"blinds": [],
|
||||
"fan": [],
|
||||
"heater": [],
|
||||
"light": []
|
||||
},
|
||||
"type": "light"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -2380,5 +2380,79 @@
|
||||
"name": "sensor_wind"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 1011,
|
||||
"services": [
|
||||
{
|
||||
"addr": "/rt:dev/rn:zw/ad:1/sv:out_lvl_switch/ad:1011_0",
|
||||
"attributes": [
|
||||
{
|
||||
"name": "lvl",
|
||||
"values": [
|
||||
{
|
||||
"ts": "2025-09-26 12:39:19 +0200",
|
||||
"val": 22,
|
||||
"val_t": "int"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "binary",
|
||||
"values": [
|
||||
{
|
||||
"ts": "2025-09-26 12:39:19 +0200",
|
||||
"val": true,
|
||||
"val_t": "bool"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"name": "out_lvl_switch"
|
||||
},
|
||||
{
|
||||
"addr": "/rt:dev/rn:zw/ad:1/sv:dev_sys/ad:1011_0",
|
||||
"attributes": [
|
||||
{
|
||||
"name": "state",
|
||||
"values": [
|
||||
{
|
||||
"ts": "2025-09-08 21:06:32 +0200",
|
||||
"val": "UP",
|
||||
"val_t": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"name": "dev_sys"
|
||||
},
|
||||
{
|
||||
"addr": "/rt:dev/rn:zw/ad:1/sv:meter_elec/ad:1011_0",
|
||||
"attributes": [
|
||||
{
|
||||
"name": "meter",
|
||||
"values": [
|
||||
{
|
||||
"props": {
|
||||
"delta_t": "774",
|
||||
"prv_data": "31.290001",
|
||||
"unit": "kWh"
|
||||
},
|
||||
"ts": "2025-09-26 18:32:21 +0200",
|
||||
"val": 49.6100006103516,
|
||||
"val_t": "float"
|
||||
},
|
||||
{
|
||||
"props": { "unit": "W" },
|
||||
"ts": "2025-09-26 18:32:21 +0200",
|
||||
"val": 0,
|
||||
"val_t": "float"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"name": "meter_elec"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
import { haGetCachedState } from '../ha/update_state';
|
||||
|
||||
export function out_lvl_switch__components(
|
||||
topicPrefix: string,
|
||||
@@ -11,11 +12,92 @@ export function out_lvl_switch__components(
|
||||
svc: VinculumPd7Service,
|
||||
_svcName: string,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const commandTopic = `${topicPrefix}${svc.addr}/command`;
|
||||
const lvlCommandTopic = `${topicPrefix}${svc.addr}/command`;
|
||||
const binaryCommandTopic = `${topicPrefix}${svc.addr}/binary/command`;
|
||||
const stateTopic = `${topicPrefix}/state`;
|
||||
|
||||
const minLvl = svc.props?.min_lvl ?? 0;
|
||||
const maxLvl = svc.props?.max_lvl ?? 100;
|
||||
|
||||
const isLightDevice = device.type?.type === 'light';
|
||||
|
||||
if (isLightDevice) {
|
||||
// Use light component for light devices
|
||||
return {
|
||||
components: {
|
||||
[`${svc.addr}_light`]: {
|
||||
unique_id: `${svc.addr}_light`,
|
||||
platform: 'light',
|
||||
name: 'Light',
|
||||
brightness: true,
|
||||
brightness_scale: maxLvl,
|
||||
command_topic: binaryCommandTopic,
|
||||
brightness_command_topic: lvlCommandTopic,
|
||||
optimistic: false,
|
||||
state_topic: stateTopic,
|
||||
state_value_template: `{{ (value_json['${svc.addr}'].lvl > 0) | iif('ON', 'OFF') }}`,
|
||||
brightness_state_topic: stateTopic,
|
||||
brightness_value_template: `{{ value_json['${svc.addr}'].lvl }}`,
|
||||
},
|
||||
},
|
||||
commandHandlers: {
|
||||
[lvlCommandTopic]: async (payload: string) => {
|
||||
const lvl = parseInt(payload, 10);
|
||||
if (Number.isNaN(lvl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: 'out_lvl_switch',
|
||||
cmd: 'cmd.lvl.set',
|
||||
val: lvl,
|
||||
val_t: 'int',
|
||||
});
|
||||
},
|
||||
[binaryCommandTopic]: async (payload: string) => {
|
||||
if (payload === 'ON') {
|
||||
// Skip setting to max brightness if the device is already on, because Home Assistant also sends "ON" when only changing brightness.
|
||||
const currentState = haGetCachedState({
|
||||
topic: `${topicPrefix}/state`,
|
||||
})?.[svc.addr];
|
||||
if (currentState.lvl > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (svc.intf?.includes('cmd.binary.set')) {
|
||||
// Set level to the last known non-zero value (not supported in add-on demo mode)
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: 'out_lvl_switch',
|
||||
cmd: 'cmd.binary.set',
|
||||
val: payload === 'ON',
|
||||
val_t: 'bool',
|
||||
});
|
||||
} else {
|
||||
// Set level to max brightness
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: 'out_lvl_switch',
|
||||
cmd: 'cmd.lvl.set',
|
||||
val: maxLvl,
|
||||
val_t: 'int',
|
||||
});
|
||||
}
|
||||
} else {
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: 'out_lvl_switch',
|
||||
cmd: 'cmd.lvl.set',
|
||||
val: minLvl,
|
||||
val_t: 'int',
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
} else {
|
||||
// Use number component for non-light devices
|
||||
return {
|
||||
components: {
|
||||
[svc.addr]: {
|
||||
@@ -25,14 +107,14 @@ export function out_lvl_switch__components(
|
||||
min: minLvl,
|
||||
max: maxLvl,
|
||||
step: 1,
|
||||
command_topic: commandTopic,
|
||||
command_topic: lvlCommandTopic,
|
||||
optimistic: false,
|
||||
value_template: `{{ value_json['${svc.addr}'].lvl }}`,
|
||||
},
|
||||
},
|
||||
|
||||
commandHandlers: {
|
||||
[commandTopic]: async (payload: string) => {
|
||||
[lvlCommandTopic]: async (payload: string) => {
|
||||
const lvl = parseInt(payload, 10);
|
||||
if (Number.isNaN(lvl)) {
|
||||
return;
|
||||
@@ -49,3 +131,4 @@ export function out_lvl_switch__components(
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export function parameters__components(
|
||||
const commandHandlers: CommandHandlers = {};
|
||||
const stateTopic = `${topicPrefix}/state`;
|
||||
|
||||
// Fetch cached state for this service to discover known parameters :contentReference[oaicite:2]{index=2}
|
||||
// Fetch cached state for this service to discover known parameters
|
||||
const currentState = haGetCachedState({ topic: stateTopic })?.[svc.addr];
|
||||
const paramMap = currentState?.param;
|
||||
if (!paramMap) {
|
||||
@@ -31,7 +31,7 @@ export function parameters__components(
|
||||
// Single MQTT topic for setting any parameter
|
||||
const setParamTopic = `${topicPrefix}${svc.addr}/set_param/command`;
|
||||
|
||||
// Iterate over each parameter in the cached state :contentReference[oaicite:3]{index=3}
|
||||
// Iterate over each parameter in the cached state
|
||||
for (const [paramId, param] of Object.entries(paramMap)) {
|
||||
const valueType = (param as any).value_type as string;
|
||||
const uniqueId = `${svc.addr}_${paramId}`;
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Пароль Thingsplex (неабавязкова)
|
||||
description: Ваш пароль для Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Дазволіць пустыя ўліковыя дадзеныя Thingsplex
|
||||
description: Дазволіць пустое імя карыстальніка і/або пароль Thingsplex.
|
||||
demo_mode:
|
||||
name: Дэманстрацыйны рэжым
|
||||
description: Выкарыстоўвайце запісаны стан з рэальнага Futurehome Smarthub для мадэлявання прылад.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Пароль Thingsplex (неабавязкова)
|
||||
description: Ваш пароль для Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Дазволіць пустыя ўліковыя дадзеныя Thingsplex
|
||||
description: Дазволіць пустое імя карыстальніка і/або пароль Thingsplex.
|
||||
demo_mode:
|
||||
name: Дэманстрацыйны рэжым
|
||||
description: Выкарыстоўвайце запісаны стан з рэальнага Futurehome Smarthub для мадэлявання прылад.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Heslo Thingsplex (volitelné)
|
||||
description: Vaše heslo pro Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Povolit prázdné přihlašovací údaje Thingsplex
|
||||
description: Povolit prázdné uživatelské jméno a/nebo heslo Thingsplex.
|
||||
demo_mode:
|
||||
name: Demo režim
|
||||
description: Použijte uložený stav ze skutečného Futurehome Smarthubu pro simulaci zařízení.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Heslo Thingsplex (volitelné)
|
||||
description: Vaše heslo pro Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Povolit prázdné přihlašovací údaje Thingsplex
|
||||
description: Povolit prázdné uživatelské jméno a/nebo heslo Thingsplex.
|
||||
demo_mode:
|
||||
name: Demo režim
|
||||
description: Použijte uložený stav ze skutečného Futurehome Smarthubu pro simulaci zařízení.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplex-adgangskode (valgfri)
|
||||
description: Din Thingsplex-adgangskode.
|
||||
tp_allow_empty:
|
||||
name: Tillad tomme Thingsplex-legitimationsoplysninger
|
||||
description: Tillad tomt Thingsplex-brugernavn og/eller adgangskode.
|
||||
demo_mode:
|
||||
name: Demotilstand
|
||||
description: Brug en optaget prøvetilstand fra en rigtig Futurehome Smarthub til at simulere enheder.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplex-Passwort (optional)
|
||||
description: Dein Thingsplex-Passwort.
|
||||
tp_allow_empty:
|
||||
name: Leere Thingsplex-Anmeldedaten zulassen
|
||||
description: Leeren Thingsplex-Benutzernamen und/oder Passwort zulassen.
|
||||
demo_mode:
|
||||
name: Demo-Modus
|
||||
description: Verwende einen aufgezeichneten Beispielzustand eines echten Futurehome Smarthubs, um Geräte zu simulieren.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplex-adgangskode (valgfri)
|
||||
description: Din Thingsplex-adgangskode.
|
||||
tp_allow_empty:
|
||||
name: Tillad tomme Thingsplex-legitimationsoplysninger
|
||||
description: Tillad tomt Thingsplex-brugernavn og/eller adgangskode.
|
||||
demo_mode:
|
||||
name: Demotilstand
|
||||
description: Brug en optaget prøvetilstand fra en rigtig Futurehome Smarthub til at simulere enheder.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplexi parool (valikuline)
|
||||
description: Sinu Thingsplexi parool.
|
||||
tp_allow_empty:
|
||||
name: Luba tühjad Thingsplexi mandaadid
|
||||
description: Luba tühi Thingsplexi kasutajanimi ja/või parool.
|
||||
demo_mode:
|
||||
name: Demorežiim
|
||||
description: Kasuta päris Futurehome Smarthubist salvestatud näidisseisu seadmete simuleerimiseks.
|
||||
|
||||
@@ -14,6 +14,12 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplex Password (Optional)
|
||||
description: Your Thingsplex password.
|
||||
tp_allow_empty:
|
||||
name: Allow Empty Thingsplex Credentials
|
||||
description: Allow empty Thingsplex username and/or password.
|
||||
ignore_availability_reports:
|
||||
name: Ignore Availability Reports
|
||||
description: Sometimes the hub incorrectly reports some devices as down. This setting forces all devices to always be treated as up.
|
||||
demo_mode:
|
||||
name: Demo Mode
|
||||
description: Use a sample recorded state from a real Futurehome Smarthub to simulate devices.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplexi parool (valikuline)
|
||||
description: Sinu Thingsplexi parool.
|
||||
tp_allow_empty:
|
||||
name: Luba tühjad Thingsplexi mandaadid
|
||||
description: Luba tühi Thingsplexi kasutajanimi ja/või parool.
|
||||
demo_mode:
|
||||
name: Demorežiim
|
||||
description: Kasuta päris Futurehome Smarthubist salvestatud näidisseisu seadmete simuleerimiseks.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplex-salasana (valinnainen)
|
||||
description: Thingsplex-salasanasi.
|
||||
tp_allow_empty:
|
||||
name: Salli tyhjät Thingsplex-tunnistetiedot
|
||||
description: Salli tyhjä Thingsplex-käyttäjätunnus ja/tai salasana.
|
||||
demo_mode:
|
||||
name: Demotila
|
||||
description: Käytä tallennettua tilanäytettä oikeasta Futurehome Smarthubista laitteiden simuloimiseen.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplex lykilorð (valkvætt)
|
||||
description: Lykilorðið þitt fyrir Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Leyfa tómar Thingsplex-auðkenningar
|
||||
description: Leyfa tómt Thingsplex-notandanafn og/eða lykilorð.
|
||||
demo_mode:
|
||||
name: Sýnishamur
|
||||
description: Notaðu upptaka af raunverulegu ástandi úr Futurehome Smarthub til að herma eftir tækjum.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplex slaptažodis (pasirinktinai)
|
||||
description: Jūsų Thingsplex slaptažodis.
|
||||
tp_allow_empty:
|
||||
name: Leisti tuščius „Thingsplex“ prisijungimo duomenis
|
||||
description: Leisti tuščią „Thingsplex“ vartotojo vardą ir (arba) slaptažodį.
|
||||
demo_mode:
|
||||
name: Demonstracinis režimas
|
||||
description: Naudokite įrašytą būsena iš tikro Futurehome Smarthub, kad imituotumėte įrenginius.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplex parole (pēc izvēles)
|
||||
description: Tava Thingsplex parole.
|
||||
tp_allow_empty:
|
||||
name: Atļaut tukšus Thingsplex akreditācijas datus
|
||||
description: Atļaut tukšu Thingsplex lietotājvārdu un/vai paroli.
|
||||
demo_mode:
|
||||
name: Demonstrācijas režīms
|
||||
description: Izmanto ierakstītu stāvokli no īsta Futurehome Smarthub, lai simulētu ierīces.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplex-passord (valgfritt)
|
||||
description: Ditt passord for Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Tillat tomme Thingsplex-legitimasjoner
|
||||
description: Tillat tomt Thingsplex-brukernavn og/eller passord.
|
||||
demo_mode:
|
||||
name: Demomodus
|
||||
description: Bruk en forhåndsopptatt tilstand fra en ekte Futurehome Smarthub for å simulere enheter.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplex-passord (valfritt)
|
||||
description: Ditt passord for Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Tillat tomme Thingsplex-legitimasjonar
|
||||
description: Tillat tomt Thingsplex-brukarnamn og/eller passord.
|
||||
demo_mode:
|
||||
name: Demomodus
|
||||
description: Bruk ein førehandsopptak frå ein ekte Futurehome Smarthub for å simulere einingar.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplex-passord (valgfritt)
|
||||
description: Ditt passord for Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Tillat tomme Thingsplex-legitimasjoner
|
||||
description: Tillat tomt Thingsplex-brukernavn og/eller passord.
|
||||
demo_mode:
|
||||
name: Demomodus
|
||||
description: Bruk en forhåndsopptatt tilstand fra en ekte Futurehome Smarthub for å simulere enheter.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Hasło do Thingsplex (opcjonalne)
|
||||
description: Twoje hasło do Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Zezwól na puste dane logowania Thingsplex
|
||||
description: Zezwól na puste nazwy użytkownika i/lub hasła Thingsplex.
|
||||
demo_mode:
|
||||
name: Tryb demonstracyjny
|
||||
description: Użyj zapisanego stanu z prawdziwego Futurehome Smarthub, aby symulować urządzenia.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Пароль Thingsplex (необязательно)
|
||||
description: Ваш пароль Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Разрешить пустые учетные данные Thingsplex
|
||||
description: Разрешить пустое имя пользователя и/или пароль Thingsplex.
|
||||
demo_mode:
|
||||
name: Демонстрационный режим
|
||||
description: Используйте сохранённое состояние от настоящего Futurehome Smarthub для имитации устройств.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplex-lösenord (valfritt)
|
||||
description: Ditt lösenord för Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Tillåt tomma Thingsplex-uppgifter
|
||||
description: Tillåt tomt Thingsplex-användarnamn och/eller lösenord.
|
||||
demo_mode:
|
||||
name: Demoläge
|
||||
description: Använd ett inspelat exempel från en riktig Futurehome Smarthub för att simulera enheter.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Heslo Thingsplex (voliteľné)
|
||||
description: Vaše heslo pre Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Povoliť prázdne prihlasovacie údaje Thingsplex
|
||||
description: Povoliť prázdne používateľské meno a/alebo heslo Thingsplex.
|
||||
demo_mode:
|
||||
name: Demo režim
|
||||
description: Použite uložený stav zo skutočného Futurehome Smarthubu na simuláciu zariadení.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Thingsplex-lösenord (valfritt)
|
||||
description: Ditt lösenord för Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Tillåt tomma Thingsplex-uppgifter
|
||||
description: Tillåt tomt Thingsplex-användarnamn och/eller lösenord.
|
||||
demo_mode:
|
||||
name: Demoläge
|
||||
description: Använd ett inspelat exempel från en riktig Futurehome Smarthub för att simulera enheter.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Пароль Thingsplex (необов’язково)
|
||||
description: Ваш пароль для Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Дозволити порожні облікові дані Thingsplex
|
||||
description: Дозволити порожнє ім’я користувача та/або пароль Thingsplex.
|
||||
demo_mode:
|
||||
name: Демонстраційний режим
|
||||
description: Використовуйте записаний стан із реального Futurehome Smarthub для імітації пристроїв.
|
||||
|
||||
@@ -14,6 +14,9 @@ configuration:
|
||||
tp_password:
|
||||
name: Пароль Thingsplex (необов’язково)
|
||||
description: Ваш пароль для Thingsplex.
|
||||
tp_allow_empty:
|
||||
name: Дозволити порожні облікові дані Thingsplex
|
||||
description: Дозволити порожнє ім’я користувача та/або пароль Thingsplex.
|
||||
demo_mode:
|
||||
name: Демонстраційний режим
|
||||
description: Використовуйте записаний стан із реального Futurehome Smarthub для імітації пристроїв.
|
||||
|
||||
Reference in New Issue
Block a user