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