mirror of
https://github.com/adrianjagielak/home-assistant-futurehome.git
synced 2026-06-18 05:40:14 +00:00
Compare commits
7 Commits
729c6c839f
...
claude/fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87dded2e4a | ||
|
|
ce36669587 | ||
|
|
dac16b0fd4 | ||
|
|
45182a6416 | ||
|
|
9f2feea8c1 | ||
|
|
a38e441c9b | ||
|
|
afbfd1d1c7 |
@@ -1,5 +1,17 @@
|
|||||||
<!-- https://developers.home-assistant.io/docs/add-ons/presentation#keeping-a-changelog -->
|
<!-- 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)
|
## 1.4.0 (13.10.2025)
|
||||||
|
|
||||||
- Added ability to specify a custom MQTT broker.
|
- Added ability to specify a custom MQTT broker.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# 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: '1.4.0'
|
version: '1.6.1'
|
||||||
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'
|
||||||
@@ -22,6 +22,7 @@ options:
|
|||||||
tp_username: ''
|
tp_username: ''
|
||||||
tp_password: ''
|
tp_password: ''
|
||||||
tp_allow_empty: false
|
tp_allow_empty: false
|
||||||
|
ignore_availability_reports: false
|
||||||
demo_mode: false
|
demo_mode: false
|
||||||
show_debug_log: false
|
show_debug_log: false
|
||||||
|
|
||||||
@@ -32,10 +33,7 @@ schema:
|
|||||||
tp_username: 'str?'
|
tp_username: 'str?'
|
||||||
tp_password: 'password?'
|
tp_password: 'password?'
|
||||||
tp_allow_empty: 'bool?'
|
tp_allow_empty: 'bool?'
|
||||||
custom_mqtt_host: 'str?'
|
ignore_availability_reports: 'bool?'
|
||||||
custom_mqtt_port: 'int?'
|
|
||||||
custom_mqtt_user: 'str?'
|
|
||||||
custom_mqtt_pwd: 'password?'
|
|
||||||
demo_mode: 'bool?'
|
demo_mode: 'bool?'
|
||||||
show_debug_log: 'bool?'
|
show_debug_log: 'bool?'
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,7 @@ export FH_PASSWORD=$(bashio::config 'fh_password')
|
|||||||
export TP_USERNAME=$(bashio::config 'tp_username')
|
export TP_USERNAME=$(bashio::config 'tp_username')
|
||||||
export TP_PASSWORD=$(bashio::config 'tp_password')
|
export TP_PASSWORD=$(bashio::config 'tp_password')
|
||||||
export TP_ALLOW_EMPTY=$(bashio::config 'tp_allow_empty')
|
export TP_ALLOW_EMPTY=$(bashio::config 'tp_allow_empty')
|
||||||
export CUSTOM_MQTT_HOST=$(bashio::config 'custom_mqtt_host')
|
export IGNORE_AVAILABILITY_REPORTS=$(bashio::config 'ignore_availability_reports')
|
||||||
export CUSTOM_MQTT_PORT=$(bashio::config 'custom_mqtt_port')
|
|
||||||
export CUSTOM_MQTT_USER=$(bashio::config 'custom_mqtt_user')
|
|
||||||
export CUSTOM_MQTT_PWD=$(bashio::config 'custom_mqtt_pwd')
|
|
||||||
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')
|
||||||
|
|
||||||
|
|||||||
@@ -25,19 +25,20 @@ import { pollVinculum } from './fimp/vinculum';
|
|||||||
const thingsplexAllowEmpty = (process.env.TP_ALLOW_EMPTY || '')
|
const thingsplexAllowEmpty = (process.env.TP_ALLOW_EMPTY || '')
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes('true');
|
.includes('true');
|
||||||
|
const ignoreAvailabilityReports = (
|
||||||
|
process.env.IGNORE_AVAILABILITY_REPORTS || ''
|
||||||
|
)
|
||||||
|
.toLowerCase()
|
||||||
|
.includes('true');
|
||||||
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()
|
||||||
.includes('true');
|
.includes('true');
|
||||||
|
|
||||||
const mqttHost = process.env.CUSTOM_MQTT_HOST || process.env.MQTT_HOST || '';
|
const mqttHost = process.env.MQTT_HOST || '';
|
||||||
const mqttPort = Number(
|
const mqttPort = Number(process.env.MQTT_PORT || '1883');
|
||||||
process.env.CUSTOM_MQTT_PORT || process.env.MQTT_PORT || '1883',
|
const mqttUsername = process.env.MQTT_USER || '';
|
||||||
);
|
const mqttPassword = process.env.MQTT_PWD || '';
|
||||||
const mqttUsername =
|
|
||||||
process.env.CUSTOM_MQTT_USER || process.env.MQTT_USER || '';
|
|
||||||
const mqttPassword =
|
|
||||||
process.env.CUSTOM_MQTT_PWD || process.env.MQTT_PWD || '';
|
|
||||||
|
|
||||||
setupLogger({ showDebugLog });
|
setupLogger({ showDebugLog });
|
||||||
|
|
||||||
@@ -273,6 +274,9 @@ import { pollVinculum } from './fimp/vinculum';
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const deviceAvailability of devicesAvailability) {
|
for (const deviceAvailability of devicesAvailability) {
|
||||||
|
if (ignoreAvailabilityReports) {
|
||||||
|
deviceAvailability.status = 'UP';
|
||||||
|
}
|
||||||
haUpdateAvailability({ hubId, deviceAvailability });
|
haUpdateAvailability({ hubId, deviceAvailability });
|
||||||
await delay(50);
|
await delay(50);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -370,16 +370,25 @@ export function _meter__components(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Map FIMP unit names to HA-compatible unit_of_measurement values
|
||||||
|
const haUnit =
|
||||||
|
unit === 'power_factor' ? '' :
|
||||||
|
unit === 'VAr' ? 'var' :
|
||||||
|
unit === 'kVArh' ? 'kvarh' : unit;
|
||||||
|
|
||||||
const component: SensorComponent = {
|
const component: SensorComponent = {
|
||||||
unique_id: componentId,
|
unique_id: componentId,
|
||||||
platform: 'sensor',
|
platform: 'sensor',
|
||||||
entity_category: 'diagnostic',
|
entity_category: 'diagnostic',
|
||||||
name: friendlyName,
|
name: friendlyName,
|
||||||
unit_of_measurement: unit,
|
|
||||||
state_class: stateClass,
|
state_class: stateClass,
|
||||||
value_template: `{{ value_json['${svc.addr}'].meter.${unit}.val | default(0) }}`,
|
value_template: `{{ value_json['${svc.addr}'].meter.${unit}.val | default(0) }}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (haUnit) {
|
||||||
|
component.unit_of_measurement = haUnit;
|
||||||
|
}
|
||||||
|
|
||||||
if (deviceClass) {
|
if (deviceClass) {
|
||||||
component.device_class = deviceClass;
|
component.device_class = deviceClass;
|
||||||
}
|
}
|
||||||
@@ -460,16 +469,24 @@ export function _meter__components(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Map FIMP unit names to HA-compatible unit_of_measurement values
|
||||||
|
const haUnit =
|
||||||
|
unit === 'VAr' ? 'var' :
|
||||||
|
unit === 'kVArh' ? 'kvarh' : unit;
|
||||||
|
|
||||||
const component: SensorComponent = {
|
const component: SensorComponent = {
|
||||||
unique_id: componentId,
|
unique_id: componentId,
|
||||||
platform: 'sensor',
|
platform: 'sensor',
|
||||||
entity_category: 'diagnostic',
|
entity_category: 'diagnostic',
|
||||||
name: friendlyName,
|
name: friendlyName,
|
||||||
unit_of_measurement: unit,
|
|
||||||
state_class: stateClass,
|
state_class: stateClass,
|
||||||
value_template: `{{ value_json['${svc.addr}'].meter_export.${unit}.val | default(0) }}`,
|
value_template: `{{ value_json['${svc.addr}'].meter_export.${unit}.val | default(0) }}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (haUnit) {
|
||||||
|
component.unit_of_measurement = haUnit;
|
||||||
|
}
|
||||||
|
|
||||||
if (deviceClass) {
|
if (deviceClass) {
|
||||||
component.device_class = deviceClass;
|
component.device_class = deviceClass;
|
||||||
}
|
}
|
||||||
@@ -510,14 +527,25 @@ export function _meter__components(
|
|||||||
|
|
||||||
// Determine unit based on value name
|
// Determine unit based on value name
|
||||||
let unit = '';
|
let unit = '';
|
||||||
if (
|
const isPhasePower =
|
||||||
valueName.startsWith('p_') ||
|
valueName.startsWith('p_') ||
|
||||||
valueName.startsWith('p1') ||
|
valueName.startsWith('p1') ||
|
||||||
valueName.startsWith('p2') ||
|
valueName.startsWith('p2') ||
|
||||||
valueName.startsWith('p3') ||
|
valueName.startsWith('p3');
|
||||||
valueName === 'dc_p'
|
if (isPhasePower && valueName.includes('_react')) {
|
||||||
) {
|
unit = 'var';
|
||||||
|
} else if (isPhasePower && valueName.includes('_apparent')) {
|
||||||
|
unit = 'VA';
|
||||||
|
} else if (isPhasePower || valueName === 'dc_p') {
|
||||||
unit = 'W';
|
unit = 'W';
|
||||||
|
} else if (
|
||||||
|
(valueName.startsWith('e_') ||
|
||||||
|
valueName.startsWith('e1') ||
|
||||||
|
valueName.startsWith('e2') ||
|
||||||
|
valueName.startsWith('e3')) &&
|
||||||
|
valueName.includes('_react')
|
||||||
|
) {
|
||||||
|
unit = 'kvarh';
|
||||||
} else if (
|
} else if (
|
||||||
valueName.startsWith('e_') ||
|
valueName.startsWith('e_') ||
|
||||||
valueName.startsWith('e1') ||
|
valueName.startsWith('e1') ||
|
||||||
@@ -565,9 +593,9 @@ export function _meter__components(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set suggested display precision
|
// Set suggested display precision
|
||||||
if (unit === 'kWh') {
|
if (unit === 'kWh' || unit === 'kvarh') {
|
||||||
component.suggested_display_precision = 3;
|
component.suggested_display_precision = 3;
|
||||||
} else if (unit === 'W' || unit === 'V' || unit === 'A') {
|
} else if (unit === 'W' || unit === 'V' || unit === 'A' || unit === 'var' || unit === 'VA') {
|
||||||
component.suggested_display_precision = 1;
|
component.suggested_display_precision = 1;
|
||||||
} else if (unit === 'Hz') {
|
} else if (unit === 'Hz') {
|
||||||
component.suggested_display_precision = 2;
|
component.suggested_display_precision = 2;
|
||||||
|
|||||||
@@ -72,12 +72,15 @@ export function _sensor_numeric__components(
|
|||||||
|
|
||||||
if (!data) return undefined;
|
if (!data) return undefined;
|
||||||
|
|
||||||
const device_class = data[0];
|
let device_class = data[0];
|
||||||
const name = data[1];
|
const name = data[1];
|
||||||
let unit = svc.props?.sup_units?.[0] ?? data[2];
|
let unit = svc.props?.sup_units?.[0] ?? data[2];
|
||||||
if (unit === 'C') unit = '°C';
|
if (unit === 'C') unit = '°C';
|
||||||
if (unit === 'F') unit = '°F';
|
if (unit === 'F') unit = '°F';
|
||||||
if (unit === 'kph') unit = 'km/h';
|
if (unit === 'kph') unit = 'km/h';
|
||||||
|
if (unit === 'Lux') unit = 'lx';
|
||||||
|
// HA rejects illuminance + %; drop device_class for percentage-reporting sensors
|
||||||
|
if (device_class === 'illuminance' && unit === '%') device_class = undefined;
|
||||||
const state_class = data[3];
|
const state_class = data[3];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -17,18 +17,9 @@ configuration:
|
|||||||
tp_allow_empty:
|
tp_allow_empty:
|
||||||
name: Allow Empty Thingsplex Credentials
|
name: Allow Empty Thingsplex Credentials
|
||||||
description: Allow empty Thingsplex username and/or password.
|
description: Allow empty Thingsplex username and/or password.
|
||||||
custom_mqtt_host:
|
ignore_availability_reports:
|
||||||
name: Custom MQTT Host (Optional)
|
name: Ignore Availability Reports
|
||||||
description: Your custom MQTT broker host.
|
description: Sometimes the hub incorrectly reports some devices as down. This setting forces all devices to always be treated as up.
|
||||||
custom_mqtt_port:
|
|
||||||
name: Custom MQTT Port (Optional)
|
|
||||||
description: Your custom MQTT broker port.
|
|
||||||
custom_mqtt_user:
|
|
||||||
name: Custom MQTT Username (Optional)
|
|
||||||
description: Your custom MQTT broker username.
|
|
||||||
custom_mqtt_pwd:
|
|
||||||
name: Custom MQTT Password (Optional)
|
|
||||||
description: Your custom MQTT broker 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.
|
||||||
|
|||||||
Reference in New Issue
Block a user