135 lines
4.0 KiB
TypeScript

import { sendFimpMsg } from '../fimp/fimp';
import {
VinculumPd7Device,
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,
device: VinculumPd7Device,
svc: VinculumPd7Service,
_svcName: string,
): ServiceComponentsCreationResult | undefined {
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]: {
unique_id: svc.addr,
platform: 'number',
name: 'Level Switch',
min: minLvl,
max: maxLvl,
step: 1,
command_topic: lvlCommandTopic,
optimistic: false,
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',
});
},
},
};
}
}