async function createPlugin(ctx) { let currentRoute = String(ctx.getSetting("defaultRoute", ctx.env.RFROUTE_DEFAULT || "rx")); const allowed = new Set(["tx", "rx", "on", "off", "draht", "beam", "wrtc"]); return { async execute(action, input) { if (action !== "setRoute") { throw new Error(`Unknown action: ${action}`); } const route = String(input && input.route || "").toLowerCase(); if (!allowed.has(route)) { throw new Error("ungueltige Route"); } const map = { tx: ctx.env.RFROUTE_CMD_TX, rx: ctx.env.RFROUTE_CMD_RX, on: ctx.env.RFROUTE_CMD_ON, off: ctx.env.RFROUTE_CMD_OFF, draht: ctx.env.RFROUTE_CMD_DRAHT, beam: ctx.env.RFROUTE_CMD_BEAM, wrtc: ctx.env.RFROUTE_CMD_WRTC }; const command = String(map[route] || "").trim(); const simulate = typeof ctx.simulateHardware === "boolean" ? ctx.simulateHardware : (process.platform !== "linux" && String(ctx.env.ALLOW_NON_LINUX_CMDS || "false") !== "true"); if (!command && !simulate) { throw new Error(`RFROUTE_CMD_${route.toUpperCase()} fehlt`); } if (command) { if (simulate) { currentRoute = route; return { ok: true, skipped: true, message: `RF Route ${route} simuliert (${ctx.execMode || "dev"})` }; } const result = await ctx.commandRunner(command, { timeoutMs: Number(ctx.getSetting("timeoutMs", ctx.env.RFROUTE_TIMEOUT_MS || 15000)) }); if (!result.ok) { throw new Error(result.stderr || result.error || "rfroute command failed"); } } currentRoute = route; return { ok: true, message: `Route auf ${route} gesetzt` }; }, async getStatus() { return { current: currentRoute, options: ["tx", "rx", "on", "off", "draht", "beam", "wrtc"] }; }, async health() { return { ok: true }; } }; } module.exports = { createPlugin };