70 lines
2.3 KiB
TypeScript
Raw Normal View History

2025-07-23 20:25:01 +02:00
import { DemoFimpMqttClient } from "./mqtt/demo_client";
import { IMqttClient } from "./mqtt/interface";
import { RealMqttClient } from "./mqtt/real_client";
2025-07-21 22:28:31 +02:00
2025-07-23 20:38:17 +02:00
export function connectHub(opts: { hubIp: string; username: string; password: string; demo: boolean; }): Promise<IMqttClient> {
const url = `mqtt://${opts.hubIp}`;
2025-07-23 20:25:01 +02:00
return makeClient(url, 1884, opts.username, opts.password, opts.demo);
2025-07-21 22:28:31 +02:00
}
2025-07-23 20:25:01 +02:00
export async function connectHA(opts: { mqttHost: string; mqttPort: number; mqttUsername: string; mqttPassword: string; }): Promise<{ ha: IMqttClient; retainedMessages: RetainedMessage[] }> {
2025-07-21 23:04:44 +02:00
const url = `mqtt://${opts.mqttHost}`;
2025-07-23 20:38:17 +02:00
const ha = await makeClient(url, opts.mqttPort, opts.mqttUsername, opts.mqttPassword, false);
const retainedMessages = await waitForHARetainedMessages(ha)
return { ha, retainedMessages };
2025-07-21 22:28:31 +02:00
}
2025-07-23 20:25:01 +02:00
function makeClient(url: string, port: number, username: string, password: string, demo: boolean): Promise<IMqttClient> {
2025-07-21 22:28:31 +02:00
return new Promise((resolve, reject) => {
2025-07-23 20:25:01 +02:00
const client = demo ? new DemoFimpMqttClient() : new RealMqttClient();
client.connect(url, { port, username, password, protocolVersion: 4 });
2025-07-21 22:28:31 +02:00
client.once("connect", () => resolve(client));
client.once("error", reject);
});
}
2025-07-23 22:32:23 +02:00
export type RetainedMessage = { topic: string; message: string };
async function waitForHARetainedMessages(
2025-07-23 20:25:01 +02:00
client: IMqttClient,
timeoutMs = 3000
): Promise<RetainedMessage[]> {
const topicPattern = /^homeassistant\/device\/futurehome.*$/;
return new Promise((resolve, reject) => {
const retainedMessages: RetainedMessage[] = [];
2025-07-23 20:25:01 +02:00
const messageHandler = (topic: string, message: Buffer, packet: { retain?: boolean }) => {
if (packet.retain && topicPattern.test(topic)) {
retainedMessages.push({ topic, message: message.toString() });
}
};
const errorHandler = (err: Error) => {
cleanup();
reject(err);
};
const cleanup = () => {
client.off('message', messageHandler);
client.off('error', errorHandler);
};
client.on('message', messageHandler);
client.on('error', errorHandler);
client.subscribe('#', { qos: 1 }, (err) => {
if (err) {
cleanup();
reject(err);
}
});
setTimeout(() => {
cleanup();
resolve(retainedMessages);
}, timeoutMs);
});
}