mirror of
https://github.com/adrianjagielak/home-assistant-futurehome.git
synced 2025-09-13 15:47:08 +00:00
Add support for 'parameters' service
This commit is contained in:
parent
9aac6c489f
commit
b882cbab91
@ -65,8 +65,9 @@ todo add info about factory reset hub to restore 30 day trial
|
|||||||
|
|
||||||
| Name | Service | Implementation status | Home Assistant entity |
|
| Name | Service | Implementation status | Home Assistant entity |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| Identify device | [indicator_ctrl](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/indicator_ctrl.ts) | | ✅ | [Button](https://www.home-assistant.io/integrations/button/) |
|
|
||||||
| Reboot device | [dev_sys](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/dev_sys.ts) | | ✅ | [Button](https://www.home-assistant.io/integrations/button/) |
|
| Reboot device | [dev_sys](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/dev_sys.ts) | | ✅ | [Button](https://www.home-assistant.io/integrations/button/) |
|
||||||
|
| Identify device | [indicator_ctrl](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/indicator_ctrl.ts) | | ✅ | [Button](https://www.home-assistant.io/integrations/button/) |
|
||||||
|
| Advanced configuration of a device | [parameters](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/parameters.ts) | | ✅ | [Button](https://www.home-assistant.io/integrations/button/), [Sensor](https://www.home-assistant.io/integrations/sensor/), [Number](https://www.home-assistant.io/integrations/number/), [Select](https://www.home-assistant.io/integrations/select/), [Text](https://www.home-assistant.io/integrations/text/) |
|
||||||
|
|
||||||
## Other system, meta, unused, or not essential services
|
## Other system, meta, unused, or not essential services
|
||||||
|
|
||||||
@ -80,10 +81,9 @@ todo add info about factory reset hub to restore 30 day trial
|
|||||||
| inverter_grid_conn | No devices or hub support this stub service. |
|
| inverter_grid_conn | No devices or hub support this stub service. |
|
||||||
| inverter_solar_conn | No devices or hub support this stub service. |
|
| inverter_solar_conn | No devices or hub support this stub service. |
|
||||||
| ota | Managing OTA updates of devices |
|
| ota | Managing OTA updates of devices |
|
||||||
| parameters | |
|
| power_regulator | Automation. Easily reproducible using Home Assistant's built-in configuration. |
|
||||||
| Power regulator | [power_regulator](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/power_regulator.ts) | [16A Puck Relé](https://www.futurehome.io/en_no/shop/puck-relay-16a) | | |
|
|
||||||
| schedule | No devices or hub support this stub service. |
|
| schedule | No devices or hub support this stub service. |
|
||||||
| technology_specific | |
|
| technology_specific | Should be covered by other services |
|
||||||
| time | Z-wave service for setting and reading time |
|
| time | Z-wave service for setting and reading time |
|
||||||
| time_parameters | Z-wave service for setting and reading time |
|
| time_parameters | Z-wave service for setting and reading time |
|
||||||
| version | Device hardware and software versions. Exposed through other means. |
|
| version | Device hardware and software versions. Exposed through other means. |
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
- Added support for 'doorman' service (Yale door locks).
|
- Added support for 'doorman' service (Yale door locks).
|
||||||
- Added support for 'complex_alarm_system' service (part of alarm sirens control).
|
- Added support for 'complex_alarm_system' service (part of alarm sirens control).
|
||||||
- Added support for 'dev_sys' service (reboot device).
|
- Added support for 'dev_sys' service (reboot device).
|
||||||
|
- Added support for 'parameters' service (advanced configuration of a device).
|
||||||
|
|
||||||
## 0.1.5 (25.07.2025)
|
## 0.1.5 (25.07.2025)
|
||||||
|
|
||||||
|
@ -64,8 +64,9 @@ todo add info about factory reset hub to restore 30 day trial
|
|||||||
|
|
||||||
| Name | Service | Implementation status | Home Assistant entity |
|
| Name | Service | Implementation status | Home Assistant entity |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| Identify device | [indicator_ctrl](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/indicator_ctrl.ts) | | ✅ | [Button](https://www.home-assistant.io/integrations/button/) |
|
|
||||||
| Reboot device | [dev_sys](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/dev_sys.ts) | | ✅ | [Button](https://www.home-assistant.io/integrations/button/) |
|
| Reboot device | [dev_sys](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/dev_sys.ts) | | ✅ | [Button](https://www.home-assistant.io/integrations/button/) |
|
||||||
|
| Identify device | [indicator_ctrl](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/indicator_ctrl.ts) | | ✅ | [Button](https://www.home-assistant.io/integrations/button/) |
|
||||||
|
| Advanced configuration of a device | [parameters](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/parameters.ts) | | ✅ | [Button](https://www.home-assistant.io/integrations/button/), [Sensor](https://www.home-assistant.io/integrations/sensor/), [Number](https://www.home-assistant.io/integrations/number/), [Select](https://www.home-assistant.io/integrations/select/), [Text](https://www.home-assistant.io/integrations/text/) |
|
||||||
|
|
||||||
## Other system, meta, unused, or not essential services
|
## Other system, meta, unused, or not essential services
|
||||||
|
|
||||||
@ -79,10 +80,9 @@ todo add info about factory reset hub to restore 30 day trial
|
|||||||
| inverter_grid_conn | No devices or hub support this stub service. |
|
| inverter_grid_conn | No devices or hub support this stub service. |
|
||||||
| inverter_solar_conn | No devices or hub support this stub service. |
|
| inverter_solar_conn | No devices or hub support this stub service. |
|
||||||
| ota | Managing OTA updates of devices |
|
| ota | Managing OTA updates of devices |
|
||||||
| parameters | |
|
| power_regulator | Automation. Easily reproducible using Home Assistant's built-in configuration. |
|
||||||
| Power regulator | [power_regulator](https://github.com/adrianjagielak/home-assistant-futurehome/blob/master/futurehome/src/services/power_regulator.ts) | [16A Puck Relé](https://www.futurehome.io/en_no/shop/puck-relay-16a) | | |
|
|
||||||
| schedule | No devices or hub support this stub service. |
|
| schedule | No devices or hub support this stub service. |
|
||||||
| technology_specific | |
|
| technology_specific | Should be covered by other services |
|
||||||
| time | Z-wave service for setting and reading time |
|
| time | Z-wave service for setting and reading time |
|
||||||
| time_parameters | Z-wave service for setting and reading time |
|
| time_parameters | Z-wave service for setting and reading time |
|
||||||
| version | Device hardware and software versions. Exposed through other means. |
|
| version | Device hardware and software versions. Exposed through other means. |
|
||||||
|
@ -22,6 +22,7 @@ import { indicator_ctrl__components } from '../services/indicator_ctrl';
|
|||||||
import { media_player__components } from '../services/media_player';
|
import { media_player__components } from '../services/media_player';
|
||||||
import { out_bin_switch__components } from '../services/out_bin_switch';
|
import { out_bin_switch__components } from '../services/out_bin_switch';
|
||||||
import { out_lvl_switch__components } from '../services/out_lvl_switch';
|
import { out_lvl_switch__components } from '../services/out_lvl_switch';
|
||||||
|
import { parameters__components } from '../services/parameters';
|
||||||
import { scene_ctrl__components } from '../services/scene_ctrl';
|
import { scene_ctrl__components } from '../services/scene_ctrl';
|
||||||
import { schedule_entry__components } from '../services/schedule_entry';
|
import { schedule_entry__components } from '../services/schedule_entry';
|
||||||
import { siren_ctrl__components } from '../services/siren_ctrl';
|
import { siren_ctrl__components } from '../services/siren_ctrl';
|
||||||
@ -169,6 +170,7 @@ const serviceHandlers: {
|
|||||||
meter_cooling: _meter__components,
|
meter_cooling: _meter__components,
|
||||||
out_bin_switch: out_bin_switch__components,
|
out_bin_switch: out_bin_switch__components,
|
||||||
out_lvl_switch: out_lvl_switch__components,
|
out_lvl_switch: out_lvl_switch__components,
|
||||||
|
parameters: parameters__components,
|
||||||
scene_ctrl: scene_ctrl__components,
|
scene_ctrl: scene_ctrl__components,
|
||||||
schedule_entry: schedule_entry__components,
|
schedule_entry: schedule_entry__components,
|
||||||
sensor_accelx: _sensor_numeric__components,
|
sensor_accelx: _sensor_numeric__components,
|
||||||
@ -301,9 +303,6 @@ export function haPublishDevice(parameters: {
|
|||||||
svcName,
|
svcName,
|
||||||
);
|
);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
log.error(
|
|
||||||
`Invalid service data prevented component creation: ${parameters.vinculumDeviceData} ${svc}`,
|
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,6 +179,7 @@ const attributeTypeKeyMap: Record<string, string> = {
|
|||||||
alarm: 'event',
|
alarm: 'event',
|
||||||
meter: 'props.unit',
|
meter: 'props.unit',
|
||||||
meter_export: 'props.unit',
|
meter_export: 'props.unit',
|
||||||
|
param: 'parameter_id',
|
||||||
};
|
};
|
||||||
|
|
||||||
function getNestedValue(obj: any, path: string): any {
|
function getNestedValue(obj: any, path: string): any {
|
||||||
@ -211,10 +212,21 @@ function processAttributeValues(values: any[], attrName?: string): any {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort by timestamp to get the latest values first
|
// Special handling for "param" attributes
|
||||||
|
if (attrName === 'param') {
|
||||||
|
const paramMap: Record<string, any> = {};
|
||||||
|
for (const entry of values) {
|
||||||
|
if (entry.parameter_id) {
|
||||||
|
paramMap[entry.parameter_id] = { ...entry };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paramMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by timestamp to get the latest values first (only if ts exists)
|
||||||
const sortedValues = [...values].sort((a, b) => {
|
const sortedValues = [...values].sort((a, b) => {
|
||||||
const tsA = new Date(a.ts).getTime();
|
const tsA = a.ts ? new Date(a.ts).getTime() : 0;
|
||||||
const tsB = new Date(b.ts).getTime();
|
const tsB = b.ts ? new Date(b.ts).getTime() : 0;
|
||||||
return tsB - tsA; // Latest first
|
return tsB - tsA; // Latest first
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2303,9 +2303,9 @@
|
|||||||
"type": "meter"
|
"type": "meter"
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"meter_heat": {
|
"meter_heating": {
|
||||||
"name": "meter_heat",
|
"name": "meter_heating",
|
||||||
"addr": "/rt:dev/rn:hoiax/ad:1/sv:meter_heat/ad:298",
|
"addr": "/rt:dev/rn:hoiax/ad:1/sv:meter_heating/ad:298",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"props": {
|
"props": {
|
||||||
"sup_units": ["kWh", "W"]
|
"sup_units": ["kWh", "W"]
|
||||||
|
@ -1091,6 +1091,26 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"name": "meter_elec"
|
"name": "meter_elec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"addr": "/rt:dev/rn:cloud_adapter/ad:1/sv:parameters/ad:3_1",
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"name": "param",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"parameter_id": "cable_always_locked",
|
||||||
|
"value_type": "bool",
|
||||||
|
"value": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameter_id": "free_charging",
|
||||||
|
"value_type": "bool",
|
||||||
|
"value": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -1668,7 +1688,7 @@
|
|||||||
"id": 298,
|
"id": 298,
|
||||||
"services": [
|
"services": [
|
||||||
{
|
{
|
||||||
"addr": "/rt:dev/rn:hoiax/ad:1/sv:meter_heat/ad:298",
|
"addr": "/rt:dev/rn:hoiax/ad:1/sv:meter_heating/ad:298",
|
||||||
"attributes": [
|
"attributes": [
|
||||||
{
|
{
|
||||||
"name": "meter",
|
"name": "meter",
|
||||||
@ -1692,7 +1712,7 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"name": "meter_heat"
|
"name": "meter_heating"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
100
futurehome/src/services/parameters.ts
Normal file
100
futurehome/src/services/parameters.ts
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import { sendFimpMsg } from '../fimp/fimp';
|
||||||
|
import {
|
||||||
|
VinculumPd7Device,
|
||||||
|
VinculumPd7Service,
|
||||||
|
} from '../fimp/vinculum_pd7_device';
|
||||||
|
import { haGetCachedState } from '../ha/update_state';
|
||||||
|
import {
|
||||||
|
ServiceComponentsCreationResult,
|
||||||
|
CommandHandlers,
|
||||||
|
} from '../ha/publish_device';
|
||||||
|
import { HaMqttComponent } from '../ha/mqtt_components/_component';
|
||||||
|
|
||||||
|
export function parameters__components(
|
||||||
|
topicPrefix: string,
|
||||||
|
device: VinculumPd7Device,
|
||||||
|
svc: VinculumPd7Service,
|
||||||
|
_svcName: string,
|
||||||
|
): ServiceComponentsCreationResult | undefined {
|
||||||
|
const components: Record<string, HaMqttComponent> = {};
|
||||||
|
const commandHandlers: CommandHandlers = {};
|
||||||
|
const stateTopic = `${topicPrefix}/state`;
|
||||||
|
|
||||||
|
// Fetch cached state for this service to discover known parameters :contentReference[oaicite:2]{index=2}
|
||||||
|
const currentState = haGetCachedState({ topic: stateTopic })?.[svc.addr];
|
||||||
|
const paramMap = currentState?.param;
|
||||||
|
if (!paramMap) {
|
||||||
|
// No parameters known → nothing to expose
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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}
|
||||||
|
for (const [paramId, param] of Object.entries(paramMap)) {
|
||||||
|
const valueType = (param as any).value_type as string;
|
||||||
|
const uniqueId = `${svc.addr}_${paramId}`;
|
||||||
|
const name = paramId.replace(/_/g, ' ');
|
||||||
|
const valueTemplate = `{{ value_json['${svc.addr}'].param.${paramId}.value }}`;
|
||||||
|
|
||||||
|
if (valueType === 'bool') {
|
||||||
|
components[uniqueId] = {
|
||||||
|
unique_id: uniqueId,
|
||||||
|
platform: 'switch',
|
||||||
|
name,
|
||||||
|
state_topic: stateTopic,
|
||||||
|
value_template: valueTemplate,
|
||||||
|
command_topic: setParamTopic,
|
||||||
|
payload_on: `{"parameter_id":"${paramId}","value_type":"${valueType}","value":true}`,
|
||||||
|
payload_off: `{"parameter_id":"${paramId}","value_type":"${valueType}","value":false}`,
|
||||||
|
};
|
||||||
|
} else if (
|
||||||
|
['int', 'float', 'double', 'uint8', 'uint16', 'uint32'].includes(
|
||||||
|
valueType,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
components[uniqueId] = {
|
||||||
|
unique_id: uniqueId,
|
||||||
|
platform: 'number',
|
||||||
|
name,
|
||||||
|
state_topic: stateTopic,
|
||||||
|
value_template: valueTemplate,
|
||||||
|
command_topic: setParamTopic,
|
||||||
|
command_template: `{"parameter_id":"${paramId}","value_type":"${valueType}","value":{{ value }}}`,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
components[uniqueId] = {
|
||||||
|
unique_id: uniqueId,
|
||||||
|
platform: 'text',
|
||||||
|
name,
|
||||||
|
state_topic: stateTopic,
|
||||||
|
value_template: valueTemplate,
|
||||||
|
command_topic: setParamTopic,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single handler for all set_param commands
|
||||||
|
commandHandlers[setParamTopic] = async (payload: string) => {
|
||||||
|
let valObj: any;
|
||||||
|
try {
|
||||||
|
valObj = JSON.parse(payload);
|
||||||
|
} catch {
|
||||||
|
// Invalid JSON: ignore
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await sendFimpMsg({
|
||||||
|
address: svc.addr!,
|
||||||
|
service: 'parameters',
|
||||||
|
cmd: 'cmd.param.set',
|
||||||
|
val: valObj,
|
||||||
|
val_t: 'object',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
components,
|
||||||
|
commandHandlers,
|
||||||
|
};
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user