mirror of
https://github.com/adrianjagielak/home-assistant-futurehome.git
synced 2025-09-13 07:37:09 +00:00
Format the codebase using prettier
This commit is contained in:
parent
7b4309a596
commit
3c56a30d01
@ -1,6 +1,6 @@
|
||||
# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config
|
||||
name: Futurehome
|
||||
version: "0.0.33"
|
||||
version: "0.0.34"
|
||||
slug: futurehome
|
||||
description: Local Futurehome Smarthub integration
|
||||
url: "https://github.com/adrianjagielak/home-assistant-futurehome"
|
||||
|
@ -1,53 +1,56 @@
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { IMqttClient } from "./mqtt/interface";
|
||||
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"
|
||||
hubAddr = 'pt:j1/mt:cmd/rt:app/rn:zb/ad:1',
|
||||
) {
|
||||
const base = "homeassistant/switch/fh_zb_pairing";
|
||||
const base = 'homeassistant/switch/fh_zb_pairing';
|
||||
const device = {
|
||||
identifiers: ["futurehome_hub"],
|
||||
name: "Futurehome Hub",
|
||||
model: "Smarthub",
|
||||
identifiers: ['futurehome_hub'],
|
||||
name: 'Futurehome Hub',
|
||||
model: 'Smarthub',
|
||||
};
|
||||
|
||||
ha.publish(
|
||||
`${base}/config`,
|
||||
JSON.stringify({
|
||||
name: "Zigbee Pairing",
|
||||
uniq_id: "fh_zb_pairing",
|
||||
name: 'Zigbee Pairing',
|
||||
uniq_id: 'fh_zb_pairing',
|
||||
cmd_t: `${base}/set`,
|
||||
stat_t: `${base}/state`,
|
||||
device,
|
||||
}),
|
||||
{ retain: true, qos: 2 }
|
||||
{ retain: true, qos: 2 },
|
||||
);
|
||||
|
||||
// // keep last known state locally
|
||||
// let pairingOn = false;
|
||||
|
||||
ha.subscribe(`${base}/set`);
|
||||
ha.on("message", (topic, payload) => {
|
||||
ha.on('message', (topic, payload) => {
|
||||
if (topic !== `${base}/set`) return;
|
||||
const turnOn = payload.toString() === "ON";
|
||||
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 });
|
||||
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",
|
||||
type: 'cmd.pairing_mode.set',
|
||||
service: 'zigbee',
|
||||
uid: uuidv4(),
|
||||
val_t: "str",
|
||||
val: turnOn ? "start" : "stop",
|
||||
val_t: 'str',
|
||||
val: turnOn ? 'start' : 'stop',
|
||||
}),
|
||||
{ qos: 1 }
|
||||
{ qos: 1 },
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -1,26 +1,48 @@
|
||||
import { DemoFimpMqttClient } from "./mqtt/demo_client";
|
||||
import { IMqttClient } from "./mqtt/interface";
|
||||
import { RealMqttClient } from "./mqtt/real_client";
|
||||
import { DemoFimpMqttClient } from './mqtt/demo_client';
|
||||
import { IMqttClient } from './mqtt/interface';
|
||||
import { RealMqttClient } from './mqtt/real_client';
|
||||
|
||||
export function connectHub(opts: { hubIp: string; username: string; password: string; demo: boolean; }): Promise<IMqttClient> {
|
||||
export function connectHub(opts: {
|
||||
hubIp: string;
|
||||
username: string;
|
||||
password: string;
|
||||
demo: boolean;
|
||||
}): Promise<IMqttClient> {
|
||||
const url = `mqtt://${opts.hubIp}`;
|
||||
return makeClient(url, 1884, opts.username, opts.password, opts.demo);
|
||||
}
|
||||
|
||||
export async function connectHA(opts: { mqttHost: string; mqttPort: number; mqttUsername: string; mqttPassword: string; }): Promise<{ ha: IMqttClient; retainedMessages: RetainedMessage[] }> {
|
||||
export async function connectHA(opts: {
|
||||
mqttHost: string;
|
||||
mqttPort: number;
|
||||
mqttUsername: string;
|
||||
mqttPassword: string;
|
||||
}): Promise<{ ha: IMqttClient; retainedMessages: RetainedMessage[] }> {
|
||||
const url = `mqtt://${opts.mqttHost}`;
|
||||
const ha = await makeClient(url, opts.mqttPort, opts.mqttUsername, opts.mqttPassword, false);
|
||||
const retainedMessages = await waitForHARetainedMessages(ha)
|
||||
const ha = await makeClient(
|
||||
url,
|
||||
opts.mqttPort,
|
||||
opts.mqttUsername,
|
||||
opts.mqttPassword,
|
||||
false,
|
||||
);
|
||||
const retainedMessages = await waitForHARetainedMessages(ha);
|
||||
|
||||
return { ha, retainedMessages };
|
||||
}
|
||||
|
||||
function makeClient(url: string, port: number, username: string, password: string, demo: boolean): Promise<IMqttClient> {
|
||||
function makeClient(
|
||||
url: string,
|
||||
port: number,
|
||||
username: string,
|
||||
password: string,
|
||||
demo: boolean,
|
||||
): Promise<IMqttClient> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const client = demo ? new DemoFimpMqttClient() : new RealMqttClient();
|
||||
client.connect(url, { port, username, password, protocolVersion: 4 });
|
||||
client.once("connect", () => resolve(client));
|
||||
client.once("error", reject);
|
||||
client.once('connect', () => resolve(client));
|
||||
client.once('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
@ -28,14 +50,18 @@ export type RetainedMessage = { topic: string; message: string };
|
||||
|
||||
async function waitForHARetainedMessages(
|
||||
client: IMqttClient,
|
||||
timeoutMs = 3000
|
||||
timeoutMs = 3000,
|
||||
): Promise<RetainedMessage[]> {
|
||||
const topicPattern = /^homeassistant\/device\/futurehome.*$/;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const retainedMessages: RetainedMessage[] = [];
|
||||
|
||||
const messageHandler = (topic: string, message: Buffer, packet: { retain?: boolean }) => {
|
||||
const messageHandler = (
|
||||
topic: string,
|
||||
message: Buffer,
|
||||
packet: { retain?: boolean },
|
||||
) => {
|
||||
if (packet.retain && topicPattern.test(topic)) {
|
||||
retainedMessages.push({ topic, message: message.toString() });
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { log } from "../logger";
|
||||
import { IMqttClient } from "../mqtt/interface";
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { log } from '../logger';
|
||||
import { IMqttClient } from '../mqtt/interface';
|
||||
|
||||
let fimp: IMqttClient | undefined = undefined;
|
||||
|
||||
@ -21,7 +21,21 @@ export type FimpResponse = {
|
||||
ver?: any;
|
||||
};
|
||||
|
||||
type FimpValueType = 'string' | 'int' | 'float' | 'bool' | 'null' | 'str_array' | 'int_array' | 'float_array' | 'str_map' | 'int_map' | 'float_map' | 'bool_map' | 'object' | 'bin';
|
||||
type FimpValueType =
|
||||
| 'string'
|
||||
| 'int'
|
||||
| 'float'
|
||||
| 'bool'
|
||||
| 'null'
|
||||
| 'str_array'
|
||||
| 'int_array'
|
||||
| 'float_array'
|
||||
| 'str_map'
|
||||
| 'int_map'
|
||||
| 'float_map'
|
||||
| 'bool_map'
|
||||
| 'object'
|
||||
| 'bin';
|
||||
|
||||
export async function sendFimpMsg({
|
||||
address,
|
||||
@ -40,27 +54,27 @@ export async function sendFimpMsg({
|
||||
}): Promise<FimpResponse> {
|
||||
const uid = uuidv4();
|
||||
const topic = `pt:j1/mt:cmd${address}`;
|
||||
const message = JSON.stringify(
|
||||
{
|
||||
corid: null,
|
||||
ctime: new Date().toISOString(),
|
||||
props: {},
|
||||
resp_to: 'pt:j1/mt:rsp/rt:app/rn:ha-futurehome/ad:addon',
|
||||
serv: service,
|
||||
src: 'ha-futurehome',
|
||||
tags: [],
|
||||
'type': cmd,
|
||||
uid: uid,
|
||||
val: val,
|
||||
val_t: val_t,
|
||||
ver: '1',
|
||||
},
|
||||
);
|
||||
const message = JSON.stringify({
|
||||
corid: null,
|
||||
ctime: new Date().toISOString(),
|
||||
props: {},
|
||||
resp_to: 'pt:j1/mt:rsp/rt:app/rn:ha-futurehome/ad:addon',
|
||||
serv: service,
|
||||
src: 'ha-futurehome',
|
||||
tags: [],
|
||||
type: cmd,
|
||||
uid: uid,
|
||||
val: val,
|
||||
val_t: val_t,
|
||||
ver: '1',
|
||||
});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
fimp?.removeListener('message', onResponse);
|
||||
const error = new Error(`Timeout waiting for FIMP response (uid: ${uid}, service: ${service}, cmd: ${cmd})`);
|
||||
const error = new Error(
|
||||
`Timeout waiting for FIMP response (uid: ${uid}, service: ${service}, cmd: ${cmd})`,
|
||||
);
|
||||
log.warn(error.message, error.stack);
|
||||
reject(error);
|
||||
}, timeoutMs);
|
||||
@ -72,13 +86,17 @@ export async function sendFimpMsg({
|
||||
if (msg.type === 'evt.error.report') {
|
||||
fimp?.removeListener('message', onResponse);
|
||||
|
||||
const error = new Error(`Received FIMP response for message ${uid}: error (evt.error.report) (matched using uid)`);
|
||||
const error = new Error(
|
||||
`Received FIMP response for message ${uid}: error (evt.error.report) (matched using uid)`,
|
||||
);
|
||||
log.warn(error.message, error.stack);
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug(`Received FIMP response for message ${uid} (matched using uid).`);
|
||||
log.debug(
|
||||
`Received FIMP response for message ${uid} (matched using uid).`,
|
||||
);
|
||||
|
||||
clearTimeout(timeout);
|
||||
fimp?.removeListener('message', onResponse);
|
||||
@ -90,13 +108,17 @@ export async function sendFimpMsg({
|
||||
if (msg.type === 'evt.error.report') {
|
||||
fimp?.removeListener('message', onResponse);
|
||||
|
||||
const error = new Error(`Received FIMP response for message ${uid}: error (evt.error.report) (matched using topic)`);
|
||||
const error = new Error(
|
||||
`Received FIMP response for message ${uid}: error (evt.error.report) (matched using topic)`,
|
||||
);
|
||||
log.warn(error.message, error.stack);
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug(`Received FIMP response for message ${uid} (matched using topic).`);
|
||||
log.debug(
|
||||
`Received FIMP response for message ${uid} (matched using topic).`,
|
||||
);
|
||||
|
||||
clearTimeout(timeout);
|
||||
fimp?.removeListener('message', onResponse);
|
||||
@ -107,13 +129,23 @@ export async function sendFimpMsg({
|
||||
const hasValidType = msg.type != null && msg.type.startsWith('evt.');
|
||||
const reqCmdParts = cmd.split('.');
|
||||
const resCmdParts = msg.type?.split('.') ?? [];
|
||||
const hasThreeParts = resCmdParts.length === 3 && reqCmdParts.length === 3;
|
||||
const hasThreeParts =
|
||||
resCmdParts.length === 3 && reqCmdParts.length === 3;
|
||||
const middlePartMatches = resCmdParts[1] === reqCmdParts[1];
|
||||
const endsWithLastPart = cmd.endsWith(resCmdParts.at(-1)!);
|
||||
const reqEndsWithSetAndResEndsWithReport = reqCmdParts[2] === 'set' && resCmdParts[2] === 'report'
|
||||
const reqEndsWithSetAndResEndsWithReport =
|
||||
reqCmdParts[2] === 'set' && resCmdParts[2] === 'report';
|
||||
const sameService = msg.serv === service;
|
||||
if (hasValidType && hasThreeParts && middlePartMatches && (endsWithLastPart || reqEndsWithSetAndResEndsWithReport) && sameService) {
|
||||
log.debug(`Received FIMP response for message ${uid} (matched using event name).`);
|
||||
if (
|
||||
hasValidType &&
|
||||
hasThreeParts &&
|
||||
middlePartMatches &&
|
||||
(endsWithLastPart || reqEndsWithSetAndResEndsWithReport) &&
|
||||
sameService
|
||||
) {
|
||||
log.debug(
|
||||
`Received FIMP response for message ${uid} (matched using event name).`,
|
||||
);
|
||||
|
||||
clearTimeout(timeout);
|
||||
fimp?.removeListener('message', onResponse);
|
||||
@ -136,4 +168,4 @@ val_t: "${val_t}"
|
||||
|
||||
fimp?.publish(topic, message, { qos: 1 });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
/// Returns the adapter address of the device associated with the given service address.
|
||||
/// The service address may belong to any service on the device.
|
||||
export function adapterAddressFromServiceAddress(serviceAddress: string): string {
|
||||
export function adapterAddressFromServiceAddress(
|
||||
serviceAddress: string,
|
||||
): string {
|
||||
const parts = serviceAddress.split('/');
|
||||
|
||||
if (parts.length < 4) {
|
||||
throw new Error("Invalid address format");
|
||||
throw new Error('Invalid address format');
|
||||
}
|
||||
|
||||
const adapterPart = parts[2]; // e.g., "rn:zigbee"
|
||||
@ -16,11 +18,13 @@ export function adapterAddressFromServiceAddress(serviceAddress: string): string
|
||||
|
||||
/// Returns the adapter service name of the device associated with the given service address.
|
||||
/// The service address may belong to any service on the device.
|
||||
export function adapterServiceFromServiceAddress(serviceAddress: string): string {
|
||||
export function adapterServiceFromServiceAddress(
|
||||
serviceAddress: string,
|
||||
): string {
|
||||
const parts = serviceAddress.split('/');
|
||||
|
||||
if (parts.length < 3) {
|
||||
throw new Error("Invalid address format");
|
||||
throw new Error('Invalid address format');
|
||||
}
|
||||
|
||||
const adapterPart = parts[2]; // e.g., "rn:zigbee"
|
||||
@ -31,5 +35,4 @@ export function adapterServiceFromServiceAddress(serviceAddress: string): string
|
||||
}
|
||||
|
||||
return adapterName;
|
||||
|
||||
}
|
||||
|
@ -1,27 +1,31 @@
|
||||
import { log } from "../logger";
|
||||
import { sendFimpMsg } from "./fimp";
|
||||
import { log } from '../logger';
|
||||
import { sendFimpMsg } from './fimp';
|
||||
|
||||
export type InclusionReport = {
|
||||
address?: string | null; // Household device ID
|
||||
product_name?: string | null; // e.g. "SWITCH-ZR03-1"
|
||||
product_hash?: string | null; // e.g. "zb - eWeLink - SWITCH-ZR03-1"
|
||||
product_id?: string | null; // e.g. "SWITCH-ZR03-1"
|
||||
manufacturer_id?: string | null; // e.g. "eWeLink"
|
||||
device_id?: string | null; // e.g. "b4:0e:cf:d1:bc:2a:00:00"
|
||||
hw_ver?: string | null; // e.g. "0"
|
||||
sw_ver?: string | null; // e.g. "0x0"
|
||||
comm_tech?: string | null; // e.g. "zigbee"
|
||||
power_source?: string | null; // e.g. "battery"
|
||||
product_hash?: string | null; // e.g. "zb - eWeLink - SWITCH-ZR03-1"
|
||||
product_id?: string | null; // e.g. "SWITCH-ZR03-1"
|
||||
manufacturer_id?: string | null; // e.g. "eWeLink"
|
||||
device_id?: string | null; // e.g. "b4:0e:cf:d1:bc:2a:00:00"
|
||||
hw_ver?: string | null; // e.g. "0"
|
||||
sw_ver?: string | null; // e.g. "0x0"
|
||||
comm_tech?: string | null; // e.g. "zigbee"
|
||||
power_source?: string | null; // e.g. "battery"
|
||||
services?: InclusionReportService[] | null;
|
||||
};
|
||||
|
||||
export type InclusionReportService = {
|
||||
name?: string | null;
|
||||
address?: string | null;
|
||||
props?: { [key: string]: any } | null
|
||||
props?: { [key: string]: any } | null;
|
||||
};
|
||||
|
||||
export async function getInclusionReport(parameters: { adapterAddress: string; adapterService: string; deviceId: string }): Promise<InclusionReport | undefined> {
|
||||
export async function getInclusionReport(parameters: {
|
||||
adapterAddress: string;
|
||||
adapterService: string;
|
||||
deviceId: string;
|
||||
}): Promise<InclusionReport | undefined> {
|
||||
try {
|
||||
const inclusionReport = await sendFimpMsg({
|
||||
address: parameters.adapterAddress,
|
||||
@ -33,6 +37,9 @@ export async function getInclusionReport(parameters: { adapterAddress: string; a
|
||||
|
||||
return inclusionReport.val;
|
||||
} catch (e) {
|
||||
log.error(`Failed getting inclusion report for adapterAddress: ${parameters.adapterAddress}, adapterService: ${parameters.adapterService}, deviceId: ${parameters.deviceId}`, e)
|
||||
log.error(
|
||||
`Failed getting inclusion report for adapterAddress: ${parameters.adapterAddress}, adapterService: ${parameters.adapterService}, deviceId: ${parameters.deviceId}`,
|
||||
e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,34 @@
|
||||
export type DeviceState = {
|
||||
id?: number | null;
|
||||
services?: DeviceStateService[] | null
|
||||
services?: DeviceStateService[] | null;
|
||||
};
|
||||
|
||||
export type DeviceStateService = {
|
||||
addr?: string;
|
||||
attributes?: Attribute[];
|
||||
name?: string;
|
||||
}
|
||||
};
|
||||
|
||||
export type Attribute = {
|
||||
name: string;
|
||||
values: AttributeValue[];
|
||||
}
|
||||
};
|
||||
|
||||
export type AttributeValue = StringValue | IntValue | FloatValue | BoolValue | NullValue | StrArrayValue | IntArrayValue | FloatArrayValue | StrMapValue | IntMapValue | FloatMapValue | BoolMapValue | ObjectValue | BinValue;
|
||||
export type AttributeValue =
|
||||
| StringValue
|
||||
| IntValue
|
||||
| FloatValue
|
||||
| BoolValue
|
||||
| NullValue
|
||||
| StrArrayValue
|
||||
| IntArrayValue
|
||||
| FloatArrayValue
|
||||
| StrMapValue
|
||||
| IntMapValue
|
||||
| FloatMapValue
|
||||
| BoolMapValue
|
||||
| ObjectValue
|
||||
| BinValue;
|
||||
|
||||
export type Timestamp = string;
|
||||
|
||||
@ -22,49 +36,49 @@ export type StringValue = {
|
||||
ts: Timestamp;
|
||||
val: string;
|
||||
val_t: 'string';
|
||||
}
|
||||
};
|
||||
|
||||
export type IntValue = {
|
||||
ts: Timestamp;
|
||||
val: number;
|
||||
val_t: 'int';
|
||||
}
|
||||
};
|
||||
|
||||
export type FloatValue = {
|
||||
ts: Timestamp;
|
||||
val: number;
|
||||
val_t: 'float';
|
||||
}
|
||||
};
|
||||
|
||||
export type BoolValue = {
|
||||
ts: Timestamp;
|
||||
val: boolean;
|
||||
val_t: 'bool';
|
||||
}
|
||||
};
|
||||
|
||||
export type NullValue = {
|
||||
ts: Timestamp;
|
||||
val?: null;
|
||||
val_t: 'null';
|
||||
}
|
||||
};
|
||||
|
||||
export type StrArrayValue = {
|
||||
ts: Timestamp;
|
||||
val: string[];
|
||||
val_t: 'str_array';
|
||||
}
|
||||
};
|
||||
|
||||
export type IntArrayValue = {
|
||||
ts: Timestamp;
|
||||
val: number[];
|
||||
val_t: 'int_array';
|
||||
}
|
||||
};
|
||||
|
||||
export type FloatArrayValue = {
|
||||
ts: Timestamp;
|
||||
val: number[];
|
||||
val_t: 'float_array';
|
||||
}
|
||||
};
|
||||
|
||||
export type StrMapValue = {
|
||||
ts: Timestamp;
|
||||
@ -72,7 +86,7 @@ export type StrMapValue = {
|
||||
[key: string]: string;
|
||||
};
|
||||
val_t: 'str_map';
|
||||
}
|
||||
};
|
||||
|
||||
export type IntMapValue = {
|
||||
ts: Timestamp;
|
||||
@ -80,7 +94,7 @@ export type IntMapValue = {
|
||||
[key: string]: number;
|
||||
};
|
||||
val_t: 'int_map';
|
||||
}
|
||||
};
|
||||
|
||||
export type FloatMapValue = {
|
||||
ts: Timestamp;
|
||||
@ -88,7 +102,7 @@ export type FloatMapValue = {
|
||||
[key: string]: number;
|
||||
};
|
||||
val_t: 'float_map';
|
||||
}
|
||||
};
|
||||
|
||||
export type BoolMapValue = {
|
||||
ts: Timestamp;
|
||||
@ -96,7 +110,7 @@ export type BoolMapValue = {
|
||||
[key: string]: boolean;
|
||||
};
|
||||
val_t: 'bool_map';
|
||||
}
|
||||
};
|
||||
|
||||
export type ObjectValue = {
|
||||
ts: Timestamp;
|
||||
@ -104,10 +118,10 @@ export type ObjectValue = {
|
||||
[key: string]: any;
|
||||
};
|
||||
val_t: 'object';
|
||||
}
|
||||
};
|
||||
|
||||
export type BinValue = {
|
||||
ts: Timestamp;
|
||||
val: string;
|
||||
val_t: 'bin';
|
||||
}
|
||||
};
|
||||
|
@ -8,7 +8,20 @@ export type VinculumPd7Device = {
|
||||
model?: string | null;
|
||||
// "Model alias", e.g. "TS0202"
|
||||
modelAlias?: string | null;
|
||||
functionality?: 'appliance' | 'climate' | 'energy' | 'ev_charger' | 'lighting' | 'media' | 'other' | 'power' | 'safety' | 'security' | 'shading' | string | null;
|
||||
functionality?:
|
||||
| 'appliance'
|
||||
| 'climate'
|
||||
| 'energy'
|
||||
| 'ev_charger'
|
||||
| 'lighting'
|
||||
| 'media'
|
||||
| 'other'
|
||||
| 'power'
|
||||
| 'safety'
|
||||
| 'security'
|
||||
| 'shading'
|
||||
| string
|
||||
| null;
|
||||
services?: Record<string, VinculumPd7Service> | null;
|
||||
type?: {
|
||||
// User-defined device type (e.g. "sensor", "chargepoint", or "light")
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { IMqttClient } from "../mqtt/interface";
|
||||
import { CommandHandlers } from "./publish_device";
|
||||
import { IMqttClient } from '../mqtt/interface';
|
||||
import { CommandHandlers } from './publish_device';
|
||||
|
||||
export let ha: IMqttClient | undefined = undefined;
|
||||
|
||||
|
@ -274,7 +274,8 @@ export function haPublishDevice(parameters: {
|
||||
},
|
||||
origin: {
|
||||
name: 'futurehome',
|
||||
support_url: 'https://github.com/adrianjagielak/home-assistant-futurehome',
|
||||
support_url:
|
||||
'https://github.com/adrianjagielak/home-assistant-futurehome',
|
||||
},
|
||||
components: components,
|
||||
state_topic: stateTopic,
|
||||
@ -283,7 +284,10 @@ export function haPublishDevice(parameters: {
|
||||
};
|
||||
|
||||
log.debug(`Publishing HA device "${configTopic}"`);
|
||||
ha?.publish(configTopic, JSON.stringify(abbreviateHaMqttKeys(config)), { retain: true, qos: 2 });
|
||||
ha?.publish(configTopic, JSON.stringify(abbreviateHaMqttKeys(config)), {
|
||||
retain: true,
|
||||
qos: 2,
|
||||
});
|
||||
|
||||
return { commandHandlers: handlers };
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { log } from "../logger";
|
||||
import { ha } from "./globals";
|
||||
import { log } from '../logger';
|
||||
import { ha } from './globals';
|
||||
|
||||
/**
|
||||
* Example raw FIMP availaility (from evt.network.all_nodes_report) input:
|
||||
@ -20,11 +20,15 @@ topic: homeassistant/device/futurehome_123456_1/availability
|
||||
online
|
||||
```
|
||||
*/
|
||||
export function haUpdateAvailability(parameters: { hubId: string, deviceAvailability: any }) {
|
||||
const availabilityTopic = `homeassistant/device/futurehome_${parameters.hubId}_${parameters.deviceAvailability.address?.toString()}/availability`
|
||||
export function haUpdateAvailability(parameters: {
|
||||
hubId: string;
|
||||
deviceAvailability: any;
|
||||
}) {
|
||||
const availabilityTopic = `homeassistant/device/futurehome_${parameters.hubId}_${parameters.deviceAvailability.address?.toString()}/availability`;
|
||||
|
||||
const availability = parameters.deviceAvailability?.status === "UP" ? "online" : "offline";
|
||||
const availability =
|
||||
parameters.deviceAvailability?.status === 'UP' ? 'online' : 'offline';
|
||||
|
||||
log.debug(`Publishing HA availability "${availabilityTopic}"`)
|
||||
log.debug(`Publishing HA availability "${availabilityTopic}"`);
|
||||
ha?.publish(availabilityTopic, availability, { retain: true, qos: 2 });
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { DeviceState } from "../fimp/state";
|
||||
import { log } from "../logger";
|
||||
import { ha } from "./globals";
|
||||
import { DeviceState } from '../fimp/state';
|
||||
import { log } from '../logger';
|
||||
import { ha } from './globals';
|
||||
|
||||
/**
|
||||
* Example raw FIMP state input:
|
||||
@ -77,8 +77,8 @@ topic: homeassistant/device/futurehome_123456_1/state
|
||||
*/
|
||||
|
||||
const haStateCache: Record<
|
||||
string, // state topic
|
||||
Record<string, Record<string, any>> // payload (addr → { attr → value })
|
||||
string, // state topic
|
||||
Record<string, Record<string, any>> // payload (addr → { attr → value })
|
||||
> = {};
|
||||
|
||||
/**
|
||||
@ -88,7 +88,10 @@ const haStateCache: Record<
|
||||
* Example MQTT topic produced for hub 123456 and device id 1:
|
||||
* homeassistant/device/futurehome_123456_1/state
|
||||
*/
|
||||
export function haUpdateState(parameters: { hubId: string; deviceState: DeviceState }) {
|
||||
export function haUpdateState(parameters: {
|
||||
hubId: string;
|
||||
deviceState: DeviceState;
|
||||
}) {
|
||||
const stateTopic = `homeassistant/device/futurehome_${parameters.hubId}_${parameters.deviceState.id?.toString()}/state`;
|
||||
|
||||
const haState: Record<string, Record<string, any>> = {};
|
||||
@ -126,9 +129,13 @@ export function haUpdateState(parameters: { hubId: string; deviceState: DeviceSt
|
||||
* The prefix "pt:j1/mt:evt" is removed before matching so that the remainder
|
||||
* exactly matches the address keys stored in the cached HA payloads.
|
||||
*/
|
||||
export function haUpdateStateSensorReport(parameters: { topic: string; value: any, attrName: string }) {
|
||||
export function haUpdateStateSensorReport(parameters: {
|
||||
topic: string;
|
||||
value: any;
|
||||
attrName: string;
|
||||
}) {
|
||||
// Strip the FIMP envelope so we end up with "/rt:dev/…/ad:x_y"
|
||||
const sensorAddr = parameters.topic.replace(/^pt:j1\/mt:evt/, "");
|
||||
const sensorAddr = parameters.topic.replace(/^pt:j1\/mt:evt/, '');
|
||||
|
||||
for (const [stateTopic, payload] of Object.entries(haStateCache)) {
|
||||
if (!payload[sensorAddr]) continue;
|
||||
@ -136,7 +143,9 @@ export function haUpdateStateSensorReport(parameters: { topic: string; value: an
|
||||
// Update the reading in‑place
|
||||
payload[sensorAddr][parameters.attrName] = parameters.value;
|
||||
|
||||
log.debug(`Publishing updated sensor value for "${sensorAddr}" to "${stateTopic}"`);
|
||||
log.debug(
|
||||
`Publishing updated sensor value for "${sensorAddr}" to "${stateTopic}"`,
|
||||
);
|
||||
ha?.publish(stateTopic, JSON.stringify(payload), { retain: true, qos: 2 });
|
||||
|
||||
haStateCache[stateTopic] = payload;
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { connectHub, connectHA, RetainedMessage } from "./client";
|
||||
import { log } from "./logger";
|
||||
import { FimpResponse, sendFimpMsg, setFimp } from "./fimp/fimp";
|
||||
import { haCommandHandlers, setHa, setHaCommandHandlers } from "./ha/globals";
|
||||
import { CommandHandlers, haPublishDevice } from "./ha/publish_device";
|
||||
import { haUpdateState, haUpdateStateSensorReport } from "./ha/update_state";
|
||||
import { VinculumPd7Device } from "./fimp/vinculum_pd7_device";
|
||||
import { haUpdateAvailability } from "./ha/update_availability";
|
||||
import { delay } from "./utils";
|
||||
import { connectHub, connectHA, RetainedMessage } from './client';
|
||||
import { log } from './logger';
|
||||
import { FimpResponse, sendFimpMsg, setFimp } from './fimp/fimp';
|
||||
import { haCommandHandlers, setHa, setHaCommandHandlers } from './ha/globals';
|
||||
import { CommandHandlers, haPublishDevice } from './ha/publish_device';
|
||||
import { haUpdateState, haUpdateStateSensorReport } from './ha/update_state';
|
||||
import { VinculumPd7Device } from './fimp/vinculum_pd7_device';
|
||||
import { haUpdateAvailability } from './ha/update_availability';
|
||||
import { delay } from './utils';
|
||||
|
||||
(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 hubPassword = process.env.FH_PASSWORD || '';
|
||||
const demoMode = (process.env.DEMO_MODE || '').toLowerCase().includes('true');
|
||||
@ -20,13 +20,20 @@ import { delay } from "./utils";
|
||||
const mqttPassword = process.env.MQTT_PWD || '';
|
||||
|
||||
// 1) Connect to HA broker (for discovery + state + availability + commands)
|
||||
log.info("Connecting to HA broker...");
|
||||
const { ha, retainedMessages } = await connectHA({ mqttHost, mqttPort, mqttUsername, mqttPassword, });
|
||||
log.info('Connecting to HA broker...');
|
||||
const { ha, retainedMessages } = await connectHA({
|
||||
mqttHost,
|
||||
mqttPort,
|
||||
mqttUsername,
|
||||
mqttPassword,
|
||||
});
|
||||
setHa(ha);
|
||||
log.info("Connected to HA broker");
|
||||
log.info('Connected to HA broker');
|
||||
|
||||
if (!demoMode && (!hubUsername || !hubPassword)) {
|
||||
log.info("Empty username or password in non-demo mode. Removing all Futurehome devices from Home Assistant...");
|
||||
log.info(
|
||||
'Empty username or password in non-demo mode. Removing all Futurehome devices from Home Assistant...',
|
||||
);
|
||||
|
||||
const publishWithDelay = (messages: RetainedMessage[], index = 0) => {
|
||||
if (index >= messages.length) return;
|
||||
@ -42,17 +49,22 @@ import { delay } from "./utils";
|
||||
}
|
||||
|
||||
// 2) Connect to Futurehome hub (FIMP traffic)
|
||||
log.info("Connecting to Futurehome hub...");
|
||||
const fimp = await connectHub({ hubIp, username: hubUsername, password: hubPassword, demo: demoMode });
|
||||
fimp.subscribe("#");
|
||||
log.info('Connecting to Futurehome hub...');
|
||||
const fimp = await connectHub({
|
||||
hubIp,
|
||||
username: hubUsername,
|
||||
password: hubPassword,
|
||||
demo: demoMode,
|
||||
});
|
||||
fimp.subscribe('#');
|
||||
setFimp(fimp);
|
||||
log.info("Connected to Futurehome hub");
|
||||
log.info('Connected to Futurehome hub');
|
||||
|
||||
const house = await sendFimpMsg({
|
||||
address: '/rt:app/rn:vinculum/ad:1',
|
||||
service: 'vinculum',
|
||||
cmd: 'cmd.pd7.request',
|
||||
val: { cmd: "get", component: null, param: { components: ['house'] } },
|
||||
val: { cmd: 'get', component: null, param: { components: ['house'] } },
|
||||
val_t: 'object',
|
||||
timeoutMs: 30000,
|
||||
});
|
||||
@ -62,16 +74,20 @@ import { delay } from "./utils";
|
||||
address: '/rt:app/rn:vinculum/ad:1',
|
||||
service: 'vinculum',
|
||||
cmd: 'cmd.pd7.request',
|
||||
val: { cmd: "get", component: null, param: { components: ['device'] } },
|
||||
val: { cmd: 'get', component: null, param: { components: ['device'] } },
|
||||
val_t: 'object',
|
||||
timeoutMs: 30000,
|
||||
});
|
||||
|
||||
const haConfig = retainedMessages.filter(msg => msg.topic.endsWith("/config"));
|
||||
const haConfig = retainedMessages.filter((msg) =>
|
||||
msg.topic.endsWith('/config'),
|
||||
);
|
||||
|
||||
const regex = new RegExp(`^homeassistant/device/futurehome_${hubId}_([a-zA-Z0-9]+)/config$`);
|
||||
const regex = new RegExp(
|
||||
`^homeassistant/device/futurehome_${hubId}_([a-zA-Z0-9]+)/config$`,
|
||||
);
|
||||
for (const haDevice of haConfig) {
|
||||
log.debug('Found existing HA device', haDevice.topic)
|
||||
log.debug('Found existing HA device', haDevice.topic);
|
||||
|
||||
const match = haDevice.topic.match(regex);
|
||||
|
||||
@ -80,15 +96,18 @@ import { delay } from "./utils";
|
||||
const idNumber = Number(deviceId);
|
||||
|
||||
if (!isNaN(idNumber)) {
|
||||
const basicDeviceData: { services?: { [key: string]: any } } = devices.val.param.device.find((d: any) => d?.id === idNumber);
|
||||
const firstServiceAddr = basicDeviceData?.services ? Object.values(basicDeviceData.services)[0]?.addr : undefined;;
|
||||
const basicDeviceData: { services?: { [key: string]: any } } =
|
||||
devices.val.param.device.find((d: any) => d?.id === idNumber);
|
||||
const firstServiceAddr = basicDeviceData?.services
|
||||
? Object.values(basicDeviceData.services)[0]?.addr
|
||||
: undefined;
|
||||
|
||||
if (!basicDeviceData || !firstServiceAddr) {
|
||||
log.debug('Device was removed, removing from HA.');
|
||||
ha?.publish(haDevice.topic, '', { retain: true, qos: 2 });
|
||||
await delay(50);
|
||||
}
|
||||
} else if (deviceId.toLowerCase() === "hub") {
|
||||
} else if (deviceId.toLowerCase() === 'hub') {
|
||||
// Hub admin tools, ignore
|
||||
} else {
|
||||
log.debug('Invalid format, removing.');
|
||||
@ -106,11 +125,15 @@ import { delay } from "./utils";
|
||||
const commandHandlers: CommandHandlers = {};
|
||||
for (const device of devices.val.param.device) {
|
||||
try {
|
||||
const vinculumDeviceData: VinculumPd7Device = device
|
||||
const deviceId = vinculumDeviceData.id.toString()
|
||||
const firstServiceAddr = vinculumDeviceData.services ? Object.values(vinculumDeviceData.services)[0]?.addr : undefined;;
|
||||
const vinculumDeviceData: VinculumPd7Device = device;
|
||||
const deviceId = vinculumDeviceData.id.toString();
|
||||
const firstServiceAddr = vinculumDeviceData.services
|
||||
? Object.values(vinculumDeviceData.services)[0]?.addr
|
||||
: undefined;
|
||||
|
||||
if (!firstServiceAddr) { continue; }
|
||||
if (!firstServiceAddr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// This is problematic when the adapter doesn't respond, so we are not getting the inclusion report for now. I'm leaving it here since we might want it in the future.
|
||||
// // Get additional metadata like manufacutrer or sw/hw version directly from the adapter
|
||||
@ -119,14 +142,27 @@ import { delay } from "./utils";
|
||||
// const deviceInclusionReport = await getInclusionReport({ adapterAddress, adapterService, deviceId });
|
||||
const deviceInclusionReport = undefined;
|
||||
|
||||
const result = haPublishDevice({ hubId, vinculumDeviceData, deviceInclusionReport });
|
||||
const result = haPublishDevice({
|
||||
hubId,
|
||||
vinculumDeviceData,
|
||||
deviceInclusionReport,
|
||||
});
|
||||
await delay(50);
|
||||
|
||||
Object.assign(commandHandlers, result.commandHandlers);
|
||||
|
||||
if (!retainedMessages.some(msg => msg.topic === `homeassistant/device/futurehome_${hubId}_${deviceId}/availability`)) {
|
||||
if (
|
||||
!retainedMessages.some(
|
||||
(msg) =>
|
||||
msg.topic ===
|
||||
`homeassistant/device/futurehome_${hubId}_${deviceId}/availability`,
|
||||
)
|
||||
) {
|
||||
// Set initial availability
|
||||
haUpdateAvailability({ hubId, deviceAvailability: { address: deviceId, status: 'UP' } });
|
||||
haUpdateAvailability({
|
||||
hubId,
|
||||
deviceAvailability: { address: deviceId, status: 'UP' },
|
||||
});
|
||||
await delay(50);
|
||||
}
|
||||
} catch (e) {
|
||||
@ -142,10 +178,12 @@ import { delay } from "./utils";
|
||||
// todo
|
||||
// exposeSmarthubTools();
|
||||
|
||||
fimp.on("message", async (topic, buf) => {
|
||||
fimp.on('message', async (topic, buf) => {
|
||||
try {
|
||||
const msg: FimpResponse = JSON.parse(buf.toString());
|
||||
log.debug(`Received FIMP message on topic "${topic}":\n${JSON.stringify(msg, null, 0)}`);
|
||||
log.debug(
|
||||
`Received FIMP message on topic "${topic}":\n${JSON.stringify(msg, null, 0)}`,
|
||||
);
|
||||
|
||||
switch (msg.type) {
|
||||
case 'evt.pd7.response': {
|
||||
@ -163,8 +201,12 @@ import { delay } from "./utils";
|
||||
if (devices) {
|
||||
const newDeviceIds = new Set(devices.map((d: any) => d?.id));
|
||||
|
||||
const addedDeviceIds = [...newDeviceIds].filter(id => !knownDeviceIds.has(id));
|
||||
const removedDeviceIds = [...knownDeviceIds].filter(id => !newDeviceIds.has(id));
|
||||
const addedDeviceIds = [...newDeviceIds].filter(
|
||||
(id) => !knownDeviceIds.has(id),
|
||||
);
|
||||
const removedDeviceIds = [...knownDeviceIds].filter(
|
||||
(id) => !newDeviceIds.has(id),
|
||||
);
|
||||
|
||||
log.info(`Added devices: ${addedDeviceIds}`);
|
||||
log.info(`Removed devices: ${removedDeviceIds}`);
|
||||
@ -190,14 +232,19 @@ import { delay } from "./utils";
|
||||
case 'evt.open.report':
|
||||
case 'evt.lvl.report':
|
||||
case 'evt.alarm.report':
|
||||
case 'evt.binary.report':
|
||||
{
|
||||
haUpdateStateSensorReport({ topic, value: msg.val, attrName: msg.type.split('.')[1] })
|
||||
break;
|
||||
}
|
||||
case 'evt.binary.report': {
|
||||
haUpdateStateSensorReport({
|
||||
topic,
|
||||
value: msg.val,
|
||||
attrName: msg.type.split('.')[1],
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'evt.network.all_nodes_report': {
|
||||
const devicesAvailability = msg.val;
|
||||
if (!devicesAvailability) { return; }
|
||||
if (!devicesAvailability) {
|
||||
return;
|
||||
}
|
||||
for (const deviceAvailability of devicesAvailability) {
|
||||
haUpdateAvailability({ hubId, deviceAvailability });
|
||||
await delay(50);
|
||||
@ -206,50 +253,59 @@ import { delay } from "./utils";
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
log.warn("Bad FIMP JSON", e, topic, buf);
|
||||
log.warn('Bad FIMP JSON', e, topic, buf);
|
||||
}
|
||||
});
|
||||
|
||||
const pollState = () => {
|
||||
log.debug("Refreshing Vinculum state after 30 seconds...");
|
||||
log.debug('Refreshing Vinculum state after 30 seconds...');
|
||||
|
||||
sendFimpMsg({
|
||||
address: '/rt:app/rn:vinculum/ad:1',
|
||||
service: 'vinculum',
|
||||
cmd: 'cmd.pd7.request',
|
||||
val: { cmd: "get", component: null, param: { components: ['state'] } },
|
||||
val: { cmd: 'get', component: null, param: { components: ['state'] } },
|
||||
val_t: 'object',
|
||||
timeoutMs: 30000,
|
||||
}).catch(e => log.warn("Failed to request state", e));
|
||||
}).catch((e) => log.warn('Failed to request state', e));
|
||||
};
|
||||
// Request initial state
|
||||
pollState();
|
||||
// Then poll every 30 seconds
|
||||
if (!demoMode) { setInterval(pollState, 30 * 1000); }
|
||||
if (!demoMode) {
|
||||
setInterval(pollState, 30 * 1000);
|
||||
}
|
||||
|
||||
const pollDevices = () => {
|
||||
log.debug("Refreshing Vinculum devices after 30 minutes...");
|
||||
log.debug('Refreshing Vinculum devices after 30 minutes...');
|
||||
|
||||
sendFimpMsg({
|
||||
address: '/rt:app/rn:vinculum/ad:1',
|
||||
service: 'vinculum',
|
||||
cmd: 'cmd.pd7.request',
|
||||
val: { cmd: "get", component: null, param: { components: ['device'] } },
|
||||
val: { cmd: 'get', component: null, param: { components: ['device'] } },
|
||||
val_t: 'object',
|
||||
timeoutMs: 30000,
|
||||
}).catch(e => log.warn("Failed to request state", e));
|
||||
}).catch((e) => log.warn('Failed to request state', e));
|
||||
};
|
||||
// Poll devices every 30 minutes (1800000 ms)
|
||||
if (!demoMode) { setInterval(pollDevices, 30 * 60 * 1000); }
|
||||
if (!demoMode) {
|
||||
setInterval(pollDevices, 30 * 60 * 1000);
|
||||
}
|
||||
|
||||
ha.on('message', (topic, buf) => {
|
||||
// Handle Home Assistant command messages
|
||||
const handler = haCommandHandlers?.[topic];
|
||||
if (handler) {
|
||||
log.debug(`Handling Home Assistant command topic: ${topic}, payload: ${buf.toString()}`);
|
||||
log.debug(
|
||||
`Handling Home Assistant command topic: ${topic}, payload: ${buf.toString()}`,
|
||||
);
|
||||
handler(buf.toString()).catch((e) => {
|
||||
log.warn(`Failed executing handler for topic: ${topic}, payload: ${buf.toString()}`, e);
|
||||
log.warn(
|
||||
`Failed executing handler for topic: ${topic}, payload: ${buf.toString()}`,
|
||||
e,
|
||||
);
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
})();
|
||||
|
@ -31,4 +31,4 @@ export const log = {
|
||||
warn: (...args: unknown[]) => _log('warn', ...args),
|
||||
error: (...args: unknown[]) => _log('error', ...args),
|
||||
fatal: (...args: unknown[]) => _log('fatal', ...args),
|
||||
};
|
||||
};
|
||||
|
@ -11,26 +11,37 @@ export class DemoFimpMqttClient implements IMqttClient {
|
||||
private onceConnectHandlers: (() => void)[] = [];
|
||||
private onceErrorHandlers: OnErrorCallback[] = [];
|
||||
|
||||
connect(_url: string, _options: {
|
||||
port: number;
|
||||
username: string;
|
||||
password: string;
|
||||
protocolVersion: 4;
|
||||
}): void {
|
||||
connect(
|
||||
_url: string,
|
||||
_options: {
|
||||
port: number;
|
||||
username: string;
|
||||
password: string;
|
||||
protocolVersion: 4;
|
||||
},
|
||||
): void {
|
||||
setTimeout(() => {
|
||||
this.onceConnectHandlers.forEach((h) => h());
|
||||
}, 100);
|
||||
}
|
||||
|
||||
subscribe(topicObject: string, opts?: { qos: 0 | 1 | 2 }, callback?: (err: Error | null) => void): void;
|
||||
subscribe(_topic: string, _opts?: any, _callback?: any): void { }
|
||||
subscribe(
|
||||
topicObject: string,
|
||||
opts?: { qos: 0 | 1 | 2 },
|
||||
callback?: (err: Error | null) => void,
|
||||
): void;
|
||||
subscribe(_topic: string, _opts?: any, _callback?: any): void {}
|
||||
|
||||
publish(topic: string, value: string, _options: {
|
||||
retain?: boolean;
|
||||
qos: 0 | 1 | 2;
|
||||
}): void {
|
||||
publish(
|
||||
topic: string,
|
||||
value: string,
|
||||
_options: {
|
||||
retain?: boolean;
|
||||
qos: 0 | 1 | 2;
|
||||
},
|
||||
): void {
|
||||
setTimeout(() => {
|
||||
const msg = JSON.parse(value)
|
||||
const msg = JSON.parse(value);
|
||||
|
||||
const sendResponse = (response: FimpResponse) => {
|
||||
response.corid = response.corid ?? msg.uid;
|
||||
@ -38,14 +49,35 @@ export class DemoFimpMqttClient implements IMqttClient {
|
||||
for (const handler of this.messageHandlers) {
|
||||
handler(topic, buffer, { retain: false } as any);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (msg.serv == 'vinculum' && msg.type == 'cmd.pd7.request' && msg.val?.param?.components?.includes('house')) {
|
||||
sendResponse({ type: 'evt.pd7.response', val: { param: { house: { hubId: '000000004c38b232' } } } })
|
||||
} else if (msg.serv == 'vinculum' && msg.type == 'cmd.pd7.request' && msg.val?.param?.components?.includes('device')) {
|
||||
sendResponse({ type: 'evt.pd7.response', val: { param: { device: demo_data__device } } });
|
||||
} else if (msg.serv == 'vinculum' && msg.type == 'cmd.pd7.request' && msg.val?.param?.components?.includes('state')) {
|
||||
sendResponse({ type: 'evt.pd7.response', val: { param: { state: { devices: demo_data__state } } } })
|
||||
if (
|
||||
msg.serv == 'vinculum' &&
|
||||
msg.type == 'cmd.pd7.request' &&
|
||||
msg.val?.param?.components?.includes('house')
|
||||
) {
|
||||
sendResponse({
|
||||
type: 'evt.pd7.response',
|
||||
val: { param: { house: { hubId: '000000004c38b232' } } },
|
||||
});
|
||||
} else if (
|
||||
msg.serv == 'vinculum' &&
|
||||
msg.type == 'cmd.pd7.request' &&
|
||||
msg.val?.param?.components?.includes('device')
|
||||
) {
|
||||
sendResponse({
|
||||
type: 'evt.pd7.response',
|
||||
val: { param: { device: demo_data__device } },
|
||||
});
|
||||
} else if (
|
||||
msg.serv == 'vinculum' &&
|
||||
msg.type == 'cmd.pd7.request' &&
|
||||
msg.val?.param?.components?.includes('state')
|
||||
) {
|
||||
sendResponse({
|
||||
type: 'evt.pd7.response',
|
||||
val: { param: { state: { devices: demo_data__state } } },
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
@ -92,4 +124,4 @@ export class DemoFimpMqttClient implements IMqttClient {
|
||||
this.onceErrorHandlers.forEach((h) => h(err));
|
||||
this.onceErrorHandlers = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -474,9 +474,7 @@
|
||||
{
|
||||
"ts": "2022-02-19 16:19:10 +0100",
|
||||
"val": {
|
||||
"members": [
|
||||
"3_1"
|
||||
]
|
||||
"members": ["3_1"]
|
||||
},
|
||||
"val_t": "object"
|
||||
}
|
||||
@ -972,9 +970,7 @@
|
||||
{
|
||||
"ts": "2023-01-05 00:31:29 +0100",
|
||||
"val": {
|
||||
"members": [
|
||||
"3_1"
|
||||
]
|
||||
"members": ["3_1"]
|
||||
},
|
||||
"val_t": "object"
|
||||
}
|
||||
|
@ -1,20 +1,31 @@
|
||||
import { IPublishPacket, OnErrorCallback, OnMessageCallback } from "mqtt/*";
|
||||
import { IPublishPacket, OnErrorCallback, OnMessageCallback } from 'mqtt/*';
|
||||
|
||||
export interface IMqttClient {
|
||||
connect(url: string, options: {
|
||||
port: number;
|
||||
username: string;
|
||||
password: string;
|
||||
protocolVersion: 4;
|
||||
}): void;
|
||||
connect(
|
||||
url: string,
|
||||
options: {
|
||||
port: number;
|
||||
username: string;
|
||||
password: string;
|
||||
protocolVersion: 4;
|
||||
},
|
||||
): void;
|
||||
|
||||
subscribe(topic: string): void;
|
||||
subscribe(topicObject: string, opts?: { qos: 0 | 1 | 2 }, callback?: (err: Error | null) => void): void;
|
||||
subscribe(
|
||||
topicObject: string,
|
||||
opts?: { qos: 0 | 1 | 2 },
|
||||
callback?: (err: Error | null) => void,
|
||||
): void;
|
||||
|
||||
publish(topic: string, value: string, options: {
|
||||
retain?: boolean;
|
||||
qos: 0 | 1 | 2;
|
||||
}): void;
|
||||
publish(
|
||||
topic: string,
|
||||
value: string,
|
||||
options: {
|
||||
retain?: boolean;
|
||||
qos: 0 | 1 | 2;
|
||||
},
|
||||
): void;
|
||||
|
||||
on(event: 'message', handler: OnMessageCallback): void;
|
||||
on(event: 'error', handler: OnErrorCallback): void;
|
||||
@ -22,8 +33,11 @@ export interface IMqttClient {
|
||||
off(event: 'message', handler: OnMessageCallback): void;
|
||||
off(event: 'error', handler: OnErrorCallback): void;
|
||||
|
||||
removeListener(event: 'message', handler: (topic: string, payload: Buffer, packet: IPublishPacket) => void): void;
|
||||
removeListener(
|
||||
event: 'message',
|
||||
handler: (topic: string, payload: Buffer, packet: IPublishPacket) => void,
|
||||
): void;
|
||||
|
||||
once(event: 'connect', handler: () => void): void;
|
||||
once(event: 'error', handler: OnErrorCallback): void;
|
||||
}
|
||||
}
|
||||
|
@ -8,16 +8,23 @@ export class RealMqttClient implements IMqttClient {
|
||||
this.client = {} as MqttClient; // gets initialized in connect()
|
||||
}
|
||||
|
||||
connect(url: string, options: {
|
||||
port: number;
|
||||
username: string;
|
||||
password: string;
|
||||
protocolVersion: 4;
|
||||
}): void {
|
||||
connect(
|
||||
url: string,
|
||||
options: {
|
||||
port: number;
|
||||
username: string;
|
||||
password: string;
|
||||
protocolVersion: 4;
|
||||
},
|
||||
): void {
|
||||
this.client = connect(url, options);
|
||||
}
|
||||
|
||||
subscribe(topicObject: string, opts?: { qos: 0 | 1 | 2 }, callback?: (err: Error | null) => void): void;
|
||||
subscribe(
|
||||
topicObject: string,
|
||||
opts?: { qos: 0 | 1 | 2 },
|
||||
callback?: (err: Error | null) => void,
|
||||
): void;
|
||||
subscribe(topic: string, opts?: any, callback?: any): void {
|
||||
if (opts) {
|
||||
this.client.subscribe(topic, opts, callback);
|
||||
@ -26,10 +33,14 @@ export class RealMqttClient implements IMqttClient {
|
||||
}
|
||||
}
|
||||
|
||||
publish(topic: string, value: string, options: {
|
||||
retain?: boolean;
|
||||
qos: 0 | 1 | 2;
|
||||
}): void {
|
||||
publish(
|
||||
topic: string,
|
||||
value: string,
|
||||
options: {
|
||||
retain?: boolean;
|
||||
qos: 0 | 1 | 2;
|
||||
},
|
||||
): void {
|
||||
this.client.publish(topic, value, options);
|
||||
}
|
||||
|
||||
|
@ -7,14 +7,17 @@
|
||||
// command_topic → cmd.lvl.set
|
||||
// ───────────────────────────────────────────────────────────────
|
||||
|
||||
import { sendFimpMsg } from "../fimp/fimp";
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import { sendFimpMsg } from '../fimp/fimp';
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function basic__components(
|
||||
topicPrefix: string,
|
||||
_device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
// MQTT topic that HA will publish commands to
|
||||
const cmdTopic = `${topicPrefix}${svc.addr}/command`;
|
||||
@ -45,9 +48,9 @@ export function basic__components(
|
||||
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: "basic",
|
||||
cmd: "cmd.lvl.set",
|
||||
val_t: "int",
|
||||
service: 'basic',
|
||||
cmd: 'cmd.lvl.set',
|
||||
val_t: 'int',
|
||||
val: lvl,
|
||||
});
|
||||
},
|
||||
|
@ -1,11 +1,14 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { HaMqttComponent } from "../ha/mqtt_components/_component";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { HaMqttComponent } from '../ha/mqtt_components/_component';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function battery__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const components: Record<string, HaMqttComponent> = {};
|
||||
|
||||
|
@ -1,12 +1,18 @@
|
||||
import { sendFimpMsg } from "../fimp/fimp";
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { LightComponent } from "../ha/mqtt_components/light";
|
||||
import { ServiceComponentsCreationResult, CommandHandlers } from "../ha/publish_device";
|
||||
import { sendFimpMsg } from '../fimp/fimp';
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { LightComponent } from '../ha/mqtt_components/light';
|
||||
import {
|
||||
ServiceComponentsCreationResult,
|
||||
CommandHandlers,
|
||||
} from '../ha/publish_device';
|
||||
|
||||
export function color_ctrl__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const supComponents: string[] = svc.props?.sup_components ?? [];
|
||||
|
||||
@ -15,7 +21,10 @@ export function color_ctrl__components(
|
||||
}
|
||||
|
||||
// Check if we have RGB support (minimum requirement for a useful light)
|
||||
const hasRgb = supComponents.includes('red') && supComponents.includes('green') && supComponents.includes('blue');
|
||||
const hasRgb =
|
||||
supComponents.includes('red') &&
|
||||
supComponents.includes('green') &&
|
||||
supComponents.includes('blue');
|
||||
if (!hasRgb) {
|
||||
return undefined; // No RGB support, skip this service
|
||||
}
|
||||
@ -76,7 +85,10 @@ export function color_ctrl__components(
|
||||
lightComponent.color_temp_value_template = `{{ (1000000 / value_json['${svc.addr}'].temp) | round(0) }}`; // Convert Kelvin to mireds
|
||||
lightComponent.min_mireds = 153; // ~6500K
|
||||
lightComponent.max_mireds = 370; // ~2700K
|
||||
} else if (supComponents.includes('warm_w') && supComponents.includes('cold_w')) {
|
||||
} else if (
|
||||
supComponents.includes('warm_w') &&
|
||||
supComponents.includes('cold_w')
|
||||
) {
|
||||
// Z-Wave style - warm/cold white mix
|
||||
lightComponent.color_temp_command_topic = colorTempCommandTopic;
|
||||
lightComponent.color_temp_state_topic = stateTopic;
|
||||
@ -101,23 +113,23 @@ export function color_ctrl__components(
|
||||
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: "color_ctrl",
|
||||
cmd: "cmd.color.set",
|
||||
val_t: "int_map",
|
||||
service: 'color_ctrl',
|
||||
cmd: 'cmd.color.set',
|
||||
val_t: 'int_map',
|
||||
val: colorMap,
|
||||
});
|
||||
} else if (payload === 'OFF') {
|
||||
// Turn off (all components to 0)
|
||||
const colorMap: Record<string, number> = {};
|
||||
supComponents.forEach(component => {
|
||||
supComponents.forEach((component) => {
|
||||
colorMap[component] = 0;
|
||||
});
|
||||
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: "color_ctrl",
|
||||
cmd: "cmd.color.set",
|
||||
val_t: "int_map",
|
||||
service: 'color_ctrl',
|
||||
cmd: 'cmd.color.set',
|
||||
val_t: 'int_map',
|
||||
val: colorMap,
|
||||
});
|
||||
}
|
||||
@ -132,8 +144,17 @@ export function color_ctrl__components(
|
||||
const green = parseInt(parts[1], 10);
|
||||
const blue = parseInt(parts[2], 10);
|
||||
|
||||
if (Number.isNaN(red) || Number.isNaN(green) || Number.isNaN(blue)) return;
|
||||
if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) return;
|
||||
if (Number.isNaN(red) || Number.isNaN(green) || Number.isNaN(blue))
|
||||
return;
|
||||
if (
|
||||
red < 0 ||
|
||||
red > 255 ||
|
||||
green < 0 ||
|
||||
green > 255 ||
|
||||
blue < 0 ||
|
||||
blue > 255
|
||||
)
|
||||
return;
|
||||
|
||||
const colorMap: Record<string, number> = {
|
||||
red,
|
||||
@ -143,9 +164,9 @@ export function color_ctrl__components(
|
||||
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: "color_ctrl",
|
||||
cmd: "cmd.color.set",
|
||||
val_t: "int_map",
|
||||
service: 'color_ctrl',
|
||||
cmd: 'cmd.color.set',
|
||||
val_t: 'int_map',
|
||||
val: colorMap,
|
||||
});
|
||||
},
|
||||
@ -167,12 +188,15 @@ export function color_ctrl__components(
|
||||
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: "color_ctrl",
|
||||
cmd: "cmd.color.set",
|
||||
val_t: "int_map",
|
||||
service: 'color_ctrl',
|
||||
cmd: 'cmd.color.set',
|
||||
val_t: 'int_map',
|
||||
val: colorMap,
|
||||
});
|
||||
} else if (supComponents.includes('warm_w') && supComponents.includes('cold_w')) {
|
||||
} else if (
|
||||
supComponents.includes('warm_w') &&
|
||||
supComponents.includes('cold_w')
|
||||
) {
|
||||
// Z-Wave style - convert mireds to warm/cold white mix
|
||||
// Linear interpolation between cold (153 mireds) and warm (370 mireds)
|
||||
const warmRatio = (mireds - 153) / (370 - 153);
|
||||
@ -189,9 +213,9 @@ export function color_ctrl__components(
|
||||
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: "color_ctrl",
|
||||
cmd: "cmd.color.set",
|
||||
val_t: "int_map",
|
||||
service: 'color_ctrl',
|
||||
cmd: 'cmd.color.set',
|
||||
val_t: 'int_map',
|
||||
val: colorMap,
|
||||
});
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
import { sendFimpMsg } from "../fimp/fimp";
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import { sendFimpMsg } from '../fimp/fimp';
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function fan_ctrl__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const supModes: string[] = svc.props?.sup_modes ?? [];
|
||||
|
||||
@ -38,10 +41,10 @@ export function fan_ctrl__components(
|
||||
if (supModes.includes(mode) || mode === 'off') {
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: "fan_ctrl",
|
||||
cmd: "cmd.mode.set",
|
||||
service: 'fan_ctrl',
|
||||
cmd: 'cmd.mode.set',
|
||||
val: mode,
|
||||
val_t: "string",
|
||||
val_t: 'string',
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@ -49,10 +52,10 @@ export function fan_ctrl__components(
|
||||
if (supModes.includes(payload)) {
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: "fan_ctrl",
|
||||
cmd: "cmd.mode.set",
|
||||
service: 'fan_ctrl',
|
||||
cmd: 'cmd.mode.set',
|
||||
val: payload,
|
||||
val_t: "string",
|
||||
val_t: 'string',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
import { sendFimpMsg } from "../fimp/fimp";
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import { sendFimpMsg } from '../fimp/fimp';
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function out_bin_switch__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const commandTopic = `${topicPrefix}${svc.addr}/command`;
|
||||
|
||||
@ -29,6 +32,6 @@ export function out_bin_switch__components(
|
||||
val_t: 'bool',
|
||||
});
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
import { sendFimpMsg } from "../fimp/fimp";
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import { sendFimpMsg } from '../fimp/fimp';
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function out_lvl_switch__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const commandTopic = `${topicPrefix}${svc.addr}/command`;
|
||||
|
||||
@ -35,10 +38,10 @@ export function out_lvl_switch__components(
|
||||
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: "out_lvl_switch",
|
||||
cmd: "cmd.lvl.set",
|
||||
service: 'out_lvl_switch',
|
||||
cmd: 'cmd.lvl.set',
|
||||
val: lvl,
|
||||
val_t: "int",
|
||||
val_t: 'int',
|
||||
});
|
||||
},
|
||||
},
|
||||
|
@ -8,13 +8,16 @@
|
||||
// <topicPrefix><addr>/scene/command → cmd.scene.set
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
import { sendFimpMsg } from "../fimp/fimp";
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { HaMqttComponent } from "../ha/mqtt_components/_component";
|
||||
import { sendFimpMsg } from '../fimp/fimp';
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { HaMqttComponent } from '../ha/mqtt_components/_component';
|
||||
import {
|
||||
CommandHandlers,
|
||||
ServiceComponentsCreationResult,
|
||||
} from "../ha/publish_device";
|
||||
} from '../ha/publish_device';
|
||||
|
||||
/**
|
||||
* Creates MQTT components for a single *scene_ctrl* service.
|
||||
@ -22,33 +25,33 @@ import {
|
||||
export function scene_ctrl__components(
|
||||
topicPrefix: string,
|
||||
_device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const components: Record<string, HaMqttComponent> = {};
|
||||
const handlers: CommandHandlers = {};
|
||||
|
||||
// ───────────── read-only entities ─────────────
|
||||
if (svc.intf?.includes("evt.scene.report")) {
|
||||
if (svc.intf?.includes('evt.scene.report')) {
|
||||
components[`${svc.addr}_scene`] = {
|
||||
unique_id: `${svc.addr}_scene`,
|
||||
platform: 'sensor',
|
||||
unit_of_measurement: "",
|
||||
unit_of_measurement: '',
|
||||
value_template: `{{ value_json['${svc.addr}'].scene }}`,
|
||||
};
|
||||
}
|
||||
|
||||
if (svc.intf?.includes("evt.lvl.report")) {
|
||||
if (svc.intf?.includes('evt.lvl.report')) {
|
||||
components[`${svc.addr}_lvl`] = {
|
||||
unique_id: `${svc.addr}_lvl`,
|
||||
platform: 'sensor',
|
||||
unit_of_measurement: "",
|
||||
unit_of_measurement: '',
|
||||
value_template: `{{ value_json['${svc.addr}'].lvl }}`,
|
||||
};
|
||||
}
|
||||
|
||||
// ───────────── writeable “select” (scene activator) ─────────────
|
||||
const supScenes: string[] = svc.props?.sup_scenes ?? [];
|
||||
if (svc.intf?.includes("cmd.scene.set") && supScenes.length) {
|
||||
if (svc.intf?.includes('cmd.scene.set') && supScenes.length) {
|
||||
const commandTopic = `${topicPrefix}${svc.addr}/scene/command`;
|
||||
|
||||
components[`${svc.addr}_select`] = {
|
||||
@ -65,9 +68,9 @@ export function scene_ctrl__components(
|
||||
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: "scene_ctrl",
|
||||
cmd: "cmd.scene.set",
|
||||
val_t: "string",
|
||||
service: 'scene_ctrl',
|
||||
cmd: 'cmd.scene.set',
|
||||
val_t: 'string',
|
||||
val: payload,
|
||||
});
|
||||
};
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_accelx__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'm/s2';
|
||||
@ -18,6 +21,6 @@ export function sensor_accelx__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_accely__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'm/s2';
|
||||
@ -18,6 +21,6 @@ export function sensor_accely__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_accelz__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'm/s2';
|
||||
@ -18,6 +21,6 @@ export function sensor_accelz__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_airflow__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'm3/h';
|
||||
@ -18,6 +21,6 @@ export function sensor_airflow__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_airq__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'aqi';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'pm25';
|
||||
@ -18,6 +21,6 @@ export function sensor_airq__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_anglepos__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
const unit = svc.props?.sup_units?.[0] ?? '%';
|
||||
@ -18,6 +21,6 @@ export function sensor_anglepos__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_atmo__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'atmospheric_pressure';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'kPa';
|
||||
@ -18,6 +21,6 @@ export function sensor_atmo__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_baro__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'atmospheric_pressure';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'kPa';
|
||||
@ -18,6 +21,6 @@ export function sensor_baro__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_co__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'carbon_monoxide';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'mol/m3';
|
||||
@ -18,6 +21,6 @@ export function sensor_co__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_co2__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'carbon_dioxide';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'ppm';
|
||||
@ -18,6 +21,6 @@ export function sensor_co2__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_contact__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'opening'
|
||||
const device_class = 'opening';
|
||||
|
||||
return {
|
||||
components: {
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_current__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'current';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'A';
|
||||
@ -18,6 +21,6 @@ export function sensor_current__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,13 +1,16 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_dew__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'temperature'
|
||||
let unit = svc.props?.sup_units?.[0] ?? "°C";
|
||||
const device_class = 'temperature';
|
||||
let unit = svc.props?.sup_units?.[0] ?? '°C';
|
||||
if (unit === 'C') unit = '°C';
|
||||
if (unit === 'F') unit = '°F';
|
||||
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_direct__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'wind_direction';
|
||||
const unit = svc.props?.sup_units?.[0] ?? '°';
|
||||
@ -18,6 +21,6 @@ export function sensor_direct__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_distance__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'distance';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'm';
|
||||
@ -18,6 +21,6 @@ export function sensor_distance__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_elresist__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'ohm/m';
|
||||
@ -18,6 +21,6 @@ export function sensor_elresist__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_freq__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'frequency';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'Hz';
|
||||
@ -18,6 +21,6 @@ export function sensor_freq__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_gp__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
const unit = svc.props?.sup_units?.[0] ?? '%';
|
||||
@ -18,6 +21,6 @@ export function sensor_gp__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,14 +1,17 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_gust__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
let unit = svc.props?.sup_units?.[0] ?? 'km/h';
|
||||
if (unit === 'kph') unit = 'km/h'
|
||||
if (unit === 'kph') unit = 'km/h';
|
||||
|
||||
return {
|
||||
components: {
|
||||
@ -19,6 +22,6 @@ export function sensor_gust__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_humid__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'humidity';
|
||||
const unit = svc.props?.sup_units?.[0] ?? '%';
|
||||
@ -18,6 +21,6 @@ export function sensor_humid__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_lumin__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'illuminance';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'Lux';
|
||||
@ -18,6 +21,6 @@ export function sensor_lumin__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_moist__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'moisture';
|
||||
const unit = svc.props?.sup_units?.[0] ?? '%';
|
||||
@ -18,6 +21,6 @@ export function sensor_moist__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_noise__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'sound_pressure';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'dB';
|
||||
@ -18,6 +21,6 @@ export function sensor_noise__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_power__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'power';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'W';
|
||||
@ -18,6 +21,6 @@ export function sensor_power__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_presence__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'occupancy'
|
||||
const device_class = 'occupancy';
|
||||
|
||||
return {
|
||||
components: {
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_rain__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'precipitation_intensity';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'mm/h';
|
||||
@ -18,6 +21,6 @@ export function sensor_rain__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_rotation__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'rpm';
|
||||
@ -18,6 +21,6 @@ export function sensor_rotation__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_seismicint__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'EMCRO';
|
||||
@ -18,6 +21,6 @@ export function sensor_seismicint__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_seismicmag__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'MB';
|
||||
@ -18,6 +21,6 @@ export function sensor_seismicmag__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_solarrad__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'W/m2';
|
||||
@ -18,6 +21,6 @@ export function sensor_solarrad__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_tank__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'volume_storage';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'l';
|
||||
@ -18,6 +21,6 @@ export function sensor_tank__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,13 +1,16 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_temp__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'temperature'
|
||||
let unit = svc.props?.sup_units?.[0] ?? "°C";
|
||||
const device_class = 'temperature';
|
||||
let unit = svc.props?.sup_units?.[0] ?? '°C';
|
||||
if (unit === 'C') unit = '°C';
|
||||
if (unit === 'F') unit = '°F';
|
||||
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_tidelvl__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'm';
|
||||
@ -18,6 +21,6 @@ export function sensor_tidelvl__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_uv__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'index';
|
||||
@ -18,6 +21,6 @@ export function sensor_uv__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_veloc__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = undefined;
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'm/2';
|
||||
@ -18,6 +21,6 @@ export function sensor_veloc__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_voltage__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'voltage';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'V';
|
||||
@ -18,6 +21,6 @@ export function sensor_voltage__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_watflow__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'volume_flow_rate';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'l/h';
|
||||
@ -18,6 +21,6 @@ export function sensor_watflow__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_watpressure__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'pressure';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'kPa';
|
||||
@ -18,6 +21,6 @@ export function sensor_watpressure__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,13 +1,16 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_wattemp__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'temperature';
|
||||
let unit = svc.props?.sup_units?.[0] ?? "°C";
|
||||
let unit = svc.props?.sup_units?.[0] ?? '°C';
|
||||
if (unit === 'C') unit = '°C';
|
||||
if (unit === 'F') unit = '°F';
|
||||
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_weight__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'weight';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'kg';
|
||||
@ -18,6 +21,6 @@ export function sensor_weight__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ServiceComponentsCreationResult } from "../ha/publish_device";
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
||||
|
||||
export function sensor_wind__components(
|
||||
topicPrefix: string,
|
||||
device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const device_class = 'wind_speed';
|
||||
const unit = svc.props?.sup_units?.[0] ?? 'km/h';
|
||||
@ -18,6 +21,6 @@ export function sensor_wind__components(
|
||||
unit_of_measurement: unit,
|
||||
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -9,26 +9,29 @@
|
||||
// temperature_command_topic → cmd.setpoint.set
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
import { sendFimpMsg } from "../fimp/fimp";
|
||||
import { VinculumPd7Device, VinculumPd7Service } from "../fimp/vinculum_pd7_device";
|
||||
import { ClimateComponent } from "../ha/mqtt_components/climate";
|
||||
import { sendFimpMsg } from '../fimp/fimp';
|
||||
import {
|
||||
VinculumPd7Device,
|
||||
VinculumPd7Service,
|
||||
} from '../fimp/vinculum_pd7_device';
|
||||
import { ClimateComponent } from '../ha/mqtt_components/climate';
|
||||
import {
|
||||
CommandHandlers,
|
||||
ServiceComponentsCreationResult,
|
||||
} from "../ha/publish_device";
|
||||
import { haGetCachedState } from "../ha/update_state";
|
||||
} from '../ha/publish_device';
|
||||
import { haGetCachedState } from '../ha/update_state';
|
||||
|
||||
export function thermostat__components(
|
||||
topicPrefix: string,
|
||||
_device: VinculumPd7Device,
|
||||
svc: VinculumPd7Service
|
||||
svc: VinculumPd7Service,
|
||||
): ServiceComponentsCreationResult | undefined {
|
||||
const supModes: string[] = svc.props?.sup_modes ?? [];
|
||||
const supSetpoints: string[] = svc.props?.sup_setpoints ?? [];
|
||||
|
||||
if (!supModes.length) return undefined; // nothing useful to expose
|
||||
|
||||
const defaultSpType = supSetpoints[0] ?? "heat";
|
||||
const defaultSpType = supSetpoints[0] ?? 'heat';
|
||||
|
||||
const ranges: Record<string, { min?: number; max?: number }> =
|
||||
svc.props?.sup_temperatures ?? {};
|
||||
@ -82,9 +85,9 @@ export function thermostat__components(
|
||||
if (!supModes.includes(payload)) return;
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: "thermostat",
|
||||
cmd: "cmd.mode.set",
|
||||
val_t: "string",
|
||||
service: 'thermostat',
|
||||
cmd: 'cmd.mode.set',
|
||||
val_t: 'string',
|
||||
val: payload,
|
||||
});
|
||||
},
|
||||
@ -95,13 +98,15 @@ export function thermostat__components(
|
||||
|
||||
await sendFimpMsg({
|
||||
address: svc.addr!,
|
||||
service: "thermostat",
|
||||
cmd: "cmd.setpoint.set",
|
||||
val_t: "str_map",
|
||||
service: 'thermostat',
|
||||
cmd: 'cmd.setpoint.set',
|
||||
val_t: 'str_map',
|
||||
val: {
|
||||
type: haGetCachedState({ topic: `${topicPrefix}/state` })?.[svc.addr]?.mode ?? defaultSpType,
|
||||
type:
|
||||
haGetCachedState({ topic: `${topicPrefix}/state` })?.[svc.addr]
|
||||
?.mode ?? defaultSpType,
|
||||
temp: payload,
|
||||
unit: "C",
|
||||
unit: 'C',
|
||||
},
|
||||
});
|
||||
},
|
||||
|
@ -1,3 +1,3 @@
|
||||
export function delay(ms: number) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user