mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2026-06-23 13:41:43 +00:00
70 lines
2.3 KiB
TypeScript
70 lines
2.3 KiB
TypeScript
import {platform} from "node:os";
|
|
import type {UnixDgramSocket} from "unix-dgram";
|
|
|
|
import logger from "./logger";
|
|
|
|
/**
|
|
* Handle sd_notify protocol, @see https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html
|
|
* No-op if running on unsupported platforms or without Type=notify
|
|
* Soft-fails if improperly setup (this is not necessary for Zigbee2MQTT to function properly)
|
|
*/
|
|
export async function initSdNotify(): Promise<{notifyStopping: () => void; stop: () => void} | undefined> {
|
|
if (!process.env.NOTIFY_SOCKET) {
|
|
return;
|
|
}
|
|
|
|
let socket: UnixDgramSocket | undefined;
|
|
|
|
try {
|
|
const {createSocket} = await import("unix-dgram");
|
|
socket = createSocket("unix_dgram");
|
|
} catch (error) {
|
|
if (platform() !== "win32" || process.env.WSL_DISTRO_NAME) {
|
|
// not on plain Windows
|
|
logger.error(`Could not init sd_notify: ${(error as Error).message}`);
|
|
// biome-ignore lint/style/noNonNullAssertion: always Error
|
|
logger.debug((error as Error).stack!);
|
|
} else {
|
|
// this should not happen
|
|
logger.warning(`NOTIFY_SOCKET env is set: ${(error as Error).message}`);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
const sendToSystemd = (msg: string): void => {
|
|
const buffer = Buffer.from(msg);
|
|
|
|
// biome-ignore lint/style/noNonNullAssertion: valid from start of function
|
|
socket.send(buffer, 0, buffer.byteLength, process.env.NOTIFY_SOCKET!, (err) => {
|
|
if (err) {
|
|
logger.warning(`Failed to send "${msg}" to systemd: ${err.message}`);
|
|
}
|
|
});
|
|
};
|
|
const notifyStopping = (): void => sendToSystemd("STOPPING=1");
|
|
|
|
sendToSystemd("READY=1");
|
|
|
|
const wdUSec = process.env.WATCHDOG_USEC !== undefined ? Math.max(0, Number.parseInt(process.env.WATCHDOG_USEC, 10)) : -1;
|
|
|
|
if (wdUSec > 0) {
|
|
// Convert us to ms, send twice as frequently as the timeout
|
|
const watchdogInterval = setInterval(() => sendToSystemd("WATCHDOG=1"), wdUSec / 1000 / 2);
|
|
|
|
return {
|
|
notifyStopping,
|
|
stop: (): void => clearInterval(watchdogInterval),
|
|
};
|
|
}
|
|
|
|
if (wdUSec !== -1) {
|
|
logger.warning(`WATCHDOG_USEC invalid: "${process.env.WATCHDOG_USEC}", parsed to "${wdUSec}"`);
|
|
}
|
|
|
|
return {
|
|
notifyStopping,
|
|
stop: (): void => {},
|
|
};
|
|
}
|