Fix preload bridge crash and bump version to 0.2.0
This commit is contained in:
+73
-8
@@ -4,10 +4,30 @@ const dgram = require("node:dgram");
|
||||
const fs = require("node:fs/promises");
|
||||
const os = require("node:os");
|
||||
const { pathToFileURL } = require("node:url");
|
||||
const mqtt = require("mqtt");
|
||||
const { SerialPort } = require("serialport");
|
||||
const ModbusRTU = require("modbus-serial");
|
||||
const knx = require("knx");
|
||||
function loadOptionalDependency(packageName) {
|
||||
try {
|
||||
return {
|
||||
module: require(packageName),
|
||||
error: null
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`[time4midi] Optional dependency "${packageName}" failed to load:`, error);
|
||||
return {
|
||||
module: null,
|
||||
error
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const mqttDependency = loadOptionalDependency("mqtt");
|
||||
const serialportDependency = loadOptionalDependency("serialport");
|
||||
const modbusDependency = loadOptionalDependency("modbus-serial");
|
||||
const knxDependency = loadOptionalDependency("knx");
|
||||
|
||||
const mqtt = mqttDependency.module;
|
||||
const SerialPort = serialportDependency.module?.SerialPort || null;
|
||||
const ModbusRTU = modbusDependency.module || null;
|
||||
const knx = knxDependency.module || null;
|
||||
|
||||
const ARTNET_PORT = 6454;
|
||||
const SACN_PORT = 5568;
|
||||
@@ -34,6 +54,11 @@ function emitStatus(target, message) {
|
||||
}
|
||||
}
|
||||
|
||||
function dependencyError(label, dependency) {
|
||||
const detail = dependency.error?.message || "Modul nicht verfuegbar";
|
||||
return new Error(`${label} Modul nicht verfuegbar: ${detail}`);
|
||||
}
|
||||
|
||||
function addStatusApi(target, handler) {
|
||||
target.statusListeners.add(handler);
|
||||
handler({
|
||||
@@ -120,7 +145,7 @@ const serialState = {
|
||||
|
||||
const modbusTcpState = {
|
||||
...createStatusEmitter(),
|
||||
client: new ModbusRTU(),
|
||||
client: null,
|
||||
connected: false,
|
||||
signature: "",
|
||||
config: {
|
||||
@@ -134,7 +159,7 @@ const modbusTcpState = {
|
||||
|
||||
const modbusRtuState = {
|
||||
...createStatusEmitter(),
|
||||
client: new ModbusRTU(),
|
||||
client: null,
|
||||
connected: false,
|
||||
signature: "",
|
||||
config: {
|
||||
@@ -635,6 +660,11 @@ function configureMqtt(nextConfig) {
|
||||
return mqttState.config;
|
||||
}
|
||||
|
||||
if (!mqtt) {
|
||||
emitStatus(mqttState, dependencyError("MQTT", mqttDependency).message);
|
||||
return mqttState.config;
|
||||
}
|
||||
|
||||
const options = { reconnectPeriod: 1000 };
|
||||
if (mqttState.config.clientId) options.clientId = mqttState.config.clientId;
|
||||
if (mqttState.config.username) options.username = mqttState.config.username;
|
||||
@@ -705,11 +735,18 @@ function closeSerialPort() {
|
||||
async function configureSerial(nextConfig) {
|
||||
serialState.config = normalizeSerialConfig(nextConfig);
|
||||
await closeSerialPort();
|
||||
if (serialState.config.enabled && !SerialPort) {
|
||||
emitStatus(serialState, dependencyError("Serial", serialportDependency).message);
|
||||
return serialState.config;
|
||||
}
|
||||
emitStatus(serialState, "");
|
||||
return serialState.config;
|
||||
}
|
||||
|
||||
async function ensureSerialPortOpen() {
|
||||
if (!SerialPort) {
|
||||
throw dependencyError("Serial", serialportDependency);
|
||||
}
|
||||
if (!serialState.config.enabled) {
|
||||
throw new Error("Serial deaktiviert");
|
||||
}
|
||||
@@ -768,6 +805,9 @@ async function sendSerial(payload) {
|
||||
}
|
||||
|
||||
async function listSerialPorts() {
|
||||
if (!SerialPort) {
|
||||
throw dependencyError("Serial", serialportDependency);
|
||||
}
|
||||
const ports = await SerialPort.list();
|
||||
return ports.map((port) => ({
|
||||
path: port.path,
|
||||
@@ -799,9 +839,11 @@ async function listNetworkInterfaces() {
|
||||
}
|
||||
|
||||
async function disconnectModbusClient(state) {
|
||||
if (state.client?.isOpen) {
|
||||
const client = state.client;
|
||||
state.client = null;
|
||||
if (client?.isOpen) {
|
||||
try {
|
||||
await state.client.close();
|
||||
await client.close();
|
||||
} catch (_error) {
|
||||
// Best effort close.
|
||||
}
|
||||
@@ -813,6 +855,10 @@ async function disconnectModbusClient(state) {
|
||||
async function configureModbusTcp(nextConfig) {
|
||||
modbusTcpState.config = normalizeModbusTcpConfig(nextConfig);
|
||||
await disconnectModbusClient(modbusTcpState);
|
||||
if (modbusTcpState.config.enabled && !ModbusRTU) {
|
||||
emitStatus(modbusTcpState, dependencyError("Modbus TCP", modbusDependency).message);
|
||||
return modbusTcpState.config;
|
||||
}
|
||||
emitStatus(modbusTcpState, "");
|
||||
return modbusTcpState.config;
|
||||
}
|
||||
@@ -820,11 +866,18 @@ async function configureModbusTcp(nextConfig) {
|
||||
async function configureModbusRtu(nextConfig) {
|
||||
modbusRtuState.config = normalizeModbusRtuConfig(nextConfig);
|
||||
await disconnectModbusClient(modbusRtuState);
|
||||
if (modbusRtuState.config.enabled && !ModbusRTU) {
|
||||
emitStatus(modbusRtuState, dependencyError("Modbus RTU", modbusDependency).message);
|
||||
return modbusRtuState.config;
|
||||
}
|
||||
emitStatus(modbusRtuState, "");
|
||||
return modbusRtuState.config;
|
||||
}
|
||||
|
||||
async function ensureModbusTcpConnected() {
|
||||
if (!ModbusRTU) {
|
||||
throw dependencyError("Modbus TCP", modbusDependency);
|
||||
}
|
||||
if (!modbusTcpState.config.enabled) {
|
||||
throw new Error("Modbus TCP deaktiviert");
|
||||
}
|
||||
@@ -833,6 +886,7 @@ async function ensureModbusTcpConnected() {
|
||||
return modbusTcpState.client;
|
||||
}
|
||||
await disconnectModbusClient(modbusTcpState);
|
||||
modbusTcpState.client = new ModbusRTU();
|
||||
await modbusTcpState.client.connectTCP(modbusTcpState.config.host, {
|
||||
port: modbusTcpState.config.port,
|
||||
timeout: modbusTcpState.config.timeout,
|
||||
@@ -846,6 +900,9 @@ async function ensureModbusTcpConnected() {
|
||||
}
|
||||
|
||||
async function ensureModbusRtuConnected() {
|
||||
if (!ModbusRTU) {
|
||||
throw dependencyError("Modbus RTU", modbusDependency);
|
||||
}
|
||||
if (!modbusRtuState.config.enabled) {
|
||||
throw new Error("Modbus RTU deaktiviert");
|
||||
}
|
||||
@@ -857,6 +914,7 @@ async function ensureModbusRtuConnected() {
|
||||
return modbusRtuState.client;
|
||||
}
|
||||
await disconnectModbusClient(modbusRtuState);
|
||||
modbusRtuState.client = new ModbusRTU();
|
||||
await modbusRtuState.client.connectRTUBuffered(modbusRtuState.config.path, {
|
||||
baudRate: modbusRtuState.config.baudRate,
|
||||
parity: modbusRtuState.config.parity,
|
||||
@@ -929,11 +987,18 @@ function disconnectKnx() {
|
||||
async function configureKnx(nextConfig) {
|
||||
knxState.config = normalizeKnxConfig(nextConfig);
|
||||
await disconnectKnx();
|
||||
if (knxState.config.enabled && !knx) {
|
||||
emitStatus(knxState, dependencyError("KNX", knxDependency).message);
|
||||
return knxState.config;
|
||||
}
|
||||
emitStatus(knxState, "");
|
||||
return knxState.config;
|
||||
}
|
||||
|
||||
async function ensureKnxConnection() {
|
||||
if (!knx) {
|
||||
throw dependencyError("KNX", knxDependency);
|
||||
}
|
||||
if (!knxState.config.enabled) {
|
||||
throw new Error("KNX deaktiviert");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user