mirror of
https://github.com/adrianjagielak/home-assistant-futurehome.git
synced 2025-09-13 15:47:08 +00:00
139 lines
4.0 KiB
TypeScript
139 lines
4.0 KiB
TypeScript
import { v4 as uuidv4 } from "uuid";
|
|
import { log } from "../logger";
|
|
import { IMqttClient } from "../mqtt/interface";
|
|
|
|
let fimp: IMqttClient | undefined = undefined;
|
|
|
|
export function setFimp(client: IMqttClient) {
|
|
fimp = client;
|
|
}
|
|
|
|
export type FimpResponse = {
|
|
corid?: any;
|
|
ctime?: any;
|
|
props?: any;
|
|
serv?: any;
|
|
tags?: any;
|
|
type?: string | null;
|
|
uid?: any;
|
|
val?: any;
|
|
val_t?: FimpValueType;
|
|
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';
|
|
|
|
export async function sendFimpMsg({
|
|
address,
|
|
service,
|
|
cmd,
|
|
val,
|
|
val_t,
|
|
timeoutMs = 10000,
|
|
}: {
|
|
address: string;
|
|
service: string;
|
|
cmd: string;
|
|
val: unknown;
|
|
val_t: FimpValueType;
|
|
timeoutMs?: number;
|
|
}): Promise<FimpResponse> {
|
|
const uid = uuidv4();
|
|
const topic = `pt:j1/mt:cmd${address}`;
|
|
const message = JSON.stringify(
|
|
{
|
|
corid: null,
|
|
ctime: new Date().toISOString(),
|
|
props: {},
|
|
resp_to: 'pt:j1/mt:rsp/rt:app/rn:ha-futurehome/ad:addon',
|
|
serv: service,
|
|
src: 'ha-futurehome',
|
|
tags: [],
|
|
'type': cmd,
|
|
uid: uid,
|
|
val: val,
|
|
val_t: val_t,
|
|
ver: '1',
|
|
},
|
|
);
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const timeout = setTimeout(() => {
|
|
fimp?.removeListener('message', onResponse);
|
|
const error = new Error(`Timeout waiting for FIMP response (uid: ${uid}, service: ${service}, cmd: ${cmd})`);
|
|
log.warn(error.message, error.stack);
|
|
reject(error);
|
|
}, timeoutMs);
|
|
|
|
const onResponse = (topic: string, buffer: any) => {
|
|
const msg = JSON.parse(buffer.toString());
|
|
|
|
if (msg.corid === uid) {
|
|
if (msg.type === 'evt.error.report') {
|
|
fimp?.removeListener('message', onResponse);
|
|
|
|
const error = new Error(`Received FIMP response for message ${uid}: error (evt.error.report) (matched using uid)`);
|
|
log.warn(error.message, error.stack);
|
|
reject(error);
|
|
return;
|
|
}
|
|
|
|
log.debug(`Received FIMP response for message ${uid} (matched using uid).`);
|
|
|
|
clearTimeout(timeout);
|
|
fimp?.removeListener('message', onResponse);
|
|
resolve(msg);
|
|
return;
|
|
}
|
|
|
|
if (msg.topic === `pt:j1/mt:evt${address}`) {
|
|
if (msg.type === 'evt.error.report') {
|
|
fimp?.removeListener('message', onResponse);
|
|
|
|
const error = new Error(`Received FIMP response for message ${uid}: error (evt.error.report) (matched using topic)`);
|
|
log.warn(error.message, error.stack);
|
|
reject(error);
|
|
return;
|
|
}
|
|
|
|
log.debug(`Received FIMP response for message ${uid} (matched using topic).`);
|
|
|
|
clearTimeout(timeout);
|
|
fimp?.removeListener('message', onResponse);
|
|
resolve(msg);
|
|
return;
|
|
}
|
|
|
|
const hasValidType = msg.type != null && msg.type.startsWith('evt.');
|
|
const reqCmdParts = cmd.split('.');
|
|
const resCmdParts = msg.type?.split('.') ?? [];
|
|
const hasThreeParts = resCmdParts.length === 3 && reqCmdParts.length === 3;
|
|
const middlePartMatches = resCmdParts[1] === reqCmdParts[1];
|
|
const endsWithLastPart = cmd.endsWith(resCmdParts.at(-1)!);
|
|
const reqEndsWithSetAndResEndsWithReport = reqCmdParts[2] === 'set' && resCmdParts[2] === 'report'
|
|
const sameService = msg.serv === service;
|
|
if (hasValidType && hasThreeParts && middlePartMatches && (endsWithLastPart || reqEndsWithSetAndResEndsWithReport) && sameService) {
|
|
log.debug(`Received FIMP response for message ${uid} (matched using event name).`);
|
|
|
|
clearTimeout(timeout);
|
|
fimp?.removeListener('message', onResponse);
|
|
resolve(msg);
|
|
return;
|
|
}
|
|
};
|
|
|
|
fimp?.on('message', onResponse);
|
|
|
|
log.debug(`
|
|
Sending FIMP message:
|
|
address: "${address}",
|
|
service: "${service}",
|
|
uid: "${uid}",
|
|
cmd: "${cmd}",
|
|
val: "${JSON.stringify(val)}",
|
|
val_t: "${val_t}"
|
|
`);
|
|
|
|
fimp?.publish(topic, message, { qos: 1 });
|
|
});
|
|
} |