import { ControllerManager } from "st-ethernet-ip"; import { createLog } from "../../../../logger/logger.js"; import { getMac } from "../../../utils/getMachineId.js"; import { labelingProcess } from "../../labeling/labelProcess.js"; export const createPlcMonitor = (config: any) => { let cm: any; let controllers: any = {}; let stats: any = {}; let isRunning = false; const nowISO = () => { return new Date().toISOString(); }; const start = () => { if (isRunning) return; cm = new ControllerManager(); config.controllers.forEach((cfg: any) => { const plc: any = cm.addController( cfg.ip, cfg.slot, cfg.rpi, true, cfg.retrySP || 3000, ); plc.connect(); controllers[cfg.id] = plc; // initialize stats stats[cfg.id] = { id: cfg.id, ip: cfg.ip, slot: cfg.slot, scanRate: cfg.rpi, connected: false, lastConnectedAt: null, lastDisconnectedAt: null, reconnectCount: 0, }; // Add tags cfg.tags.forEach((tag: any) => plc.addTag(tag)); // Events plc.on("Connected", () => { const s = stats[cfg.id]; s.connected = true; s.lastConnectedAt = nowISO(); if (s.lastDisconnectedAt) { s.reconnectCount++; } createLog( "info", "zechette", "ocp", `[${cfg.id}] Connected @ ${cfg.ip}:${cfg.slot}`, ); }); plc.on("Disconnected", () => { const s = stats[cfg.id]; s.connected = false; s.lastDisconnectedAt = nowISO(); createLog("info", "zechette", "ocp", `[${cfg.id}] Disconnected`); }); plc.on("error", (err: any) => { createLog( "error", "zechette", "ocp", `[${cfg.id}] Error: ${JSON.stringify(err.message)}`, ); }); plc.on("TagChanged", async (tag: any, prevVal: any) => { if (tag.value !== 0) { const time = nowISO(); if (tag.value === 0) return; setTimeout(async () => { if (tag.value === 0) return; const macId = await getMac(tag.value); // temp work around until we can get the zechetti 2 to play nice with lst if (cfg.id === "Zecchetti_2") return; // const { data, error } = (await tryCatch( // query( // getCurrentLabel // .replace( // "[macId]", // macId[0]?.HumanReadableId // ) // .replace( // "[time]", // format(time, "yyyy-MM-dd HH:mm") // ), // "Current label data" // ) // )) as any; // createLog( // "info", // "zechettii", // "zechettii", // `${format(time, "yyyy-MM-dd HH:mm")} [${cfg.id}] ${ // tag.name // }: ${prevVal} -> ${ // tag.value // }, the running number is ${ // error ? null : data.data[0]?.LfdNr // }}` // ); const zechette = { line: tag.value.toString(), printer: cfg.printerId, // this is the id of the zechetti 2 to print we should move this to the db printerName: cfg.id, }; createLog( "info", "zechette", "ocp", `Date being sent to labeler: ${JSON.stringify(zechette)}`, ); labelingProcess({ zechette: zechette }); }, 150); } }); }); isRunning = true; }; const stop = () => { if (!isRunning) return; Object.values(controllers).forEach((plc: any) => { try { plc.disconnect(); } catch {} }); controllers = {}; cm = null; isRunning = false; console.log("Monitor stopped"); }; const restart = () => { console.log("Restarting the plc(s)"); stop(); new Promise((resolve) => setTimeout(resolve, 1500)); start(); }; const status = () => { const result: any = {}; for (const [id, s] of Object.entries(stats)) { let s: any; let uptimeMs = null, downtimeMs = null; if (s.connected && s.lastConnectedAt) { uptimeMs = Date.now() - new Date(s.lastConnectedAt).getTime(); } else if (!s.connected && s.lastDisconnectedAt) { downtimeMs = Date.now() - new Date(s.lastDisconnectedAt).getTime(); } result[id] = { ...s, uptimeMs, downtimeMs }; } return result; }; return { start, stop, restart, status }; };