feat(ocp): added zechettis stuff in
This commit is contained in:
@@ -78,6 +78,7 @@ export const labelingProcess = async ({
|
|||||||
|
|
||||||
// if we are running the zechettii
|
// if we are running the zechettii
|
||||||
if (zechette) {
|
if (zechette) {
|
||||||
|
if (zechette.line === "0") return;
|
||||||
const macId = await getMac(zechette.line);
|
const macId = await getMac(zechette.line);
|
||||||
// filter out the lot for the line
|
// filter out the lot for the line
|
||||||
filteredLot = lots.data.filter(
|
filteredLot = lots.data.filter(
|
||||||
@@ -163,7 +164,11 @@ export const labelingProcess = async ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if there are more than 2 lots it might be an auto labeler, autolabeler will be defined by its id for now only dayton
|
// if there are more than 2 lots it might be an auto labeler, autolabeler will be defined by its id for now only dayton
|
||||||
if (filteredLot?.length > 2 && plantToken[0].value !== "usday1") {
|
const plantsCanHaveMultiLots = ["usday1", "usmcd1"];
|
||||||
|
if (
|
||||||
|
filteredLot?.length > 2 &&
|
||||||
|
!plantsCanHaveMultiLots.includes(plantToken[0].value)
|
||||||
|
) {
|
||||||
createLog(
|
createLog(
|
||||||
"error",
|
"error",
|
||||||
"labeling",
|
"labeling",
|
||||||
@@ -205,59 +210,65 @@ export const labelingProcess = async ({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the material... mm,color (auto and manual combined), pkg
|
// as we want to allow zechetti to print no matter what if we zechettii is true skip all this and just print the label
|
||||||
const mmStaged = await isMainMatStaged(filteredLot[0]);
|
if (!zechette) {
|
||||||
|
// check the material... mm,color (auto and manual combined), pkg
|
||||||
|
const mmStaged = await isMainMatStaged(filteredLot[0]);
|
||||||
|
|
||||||
if (!mmStaged.success) {
|
if (!mmStaged.success) {
|
||||||
createLog("error", "labeling", "ocp", mmStaged.message);
|
createLog("error", "labeling", "ocp", mmStaged.message);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: mmStaged.message,
|
message: mmStaged.message,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// comment only but will check for color
|
// comment only but will check for color
|
||||||
createLog(
|
|
||||||
"info",
|
|
||||||
"labeling",
|
|
||||||
"ocp",
|
|
||||||
`Remaining pallets for: ${filteredLot[0].MachineDescription} is ${filteredLot[0].Remaining}`
|
|
||||||
);
|
|
||||||
|
|
||||||
// do we want to over run
|
|
||||||
if (filteredLot[0].overPrinting === "no" && filteredLot[0].Remaining <= 0) {
|
|
||||||
createLog(
|
createLog(
|
||||||
"error",
|
"info",
|
||||||
"labeling",
|
"labeling",
|
||||||
"ocp",
|
"ocp",
|
||||||
`Over Printing on ${filteredLot[0].MachineDescription} is not allowed please change the lot`
|
`Remaining pallets for: ${filteredLot[0].MachineDescription} is ${filteredLot[0].Remaining}`
|
||||||
);
|
);
|
||||||
// for slc we want to run the first label for henkel
|
|
||||||
firstLotLabel(filteredLot[0]);
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: `Over Printing on ${filteredLot[0].MachineDescription} is not allowed please change the lot`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// prolink check by lot
|
// do we want to over run
|
||||||
const prolink = await prolinkCheck(filteredLot[0].lot);
|
if (
|
||||||
|
filteredLot[0].overPrinting === "no" &&
|
||||||
|
filteredLot[0].Remaining <= 0
|
||||||
|
) {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"labeling",
|
||||||
|
"ocp",
|
||||||
|
`Over Printing on ${filteredLot[0].MachineDescription} is not allowed please change the lot`
|
||||||
|
);
|
||||||
|
// for slc we want to run the first label for henkel
|
||||||
|
firstLotLabel(filteredLot[0]);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `Over Printing on ${filteredLot[0].MachineDescription} is not allowed please change the lot`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (!prolink) {
|
// prolink check by lot
|
||||||
//console.error(`Prolink does not match for ${filteredLot[0].MachineDescription}`);
|
const prolink = await prolinkCheck(filteredLot[0].lot);
|
||||||
createLog(
|
|
||||||
"error",
|
if (!prolink) {
|
||||||
"labeling",
|
//console.error(`Prolink does not match for ${filteredLot[0].MachineDescription}`);
|
||||||
"ocp",
|
createLog(
|
||||||
`Prolink does not match for ${filteredLot[0].MachineDescription}`
|
"error",
|
||||||
);
|
"labeling",
|
||||||
return {
|
"ocp",
|
||||||
success: false,
|
`Prolink does not match for ${filteredLot[0].MachineDescription}`
|
||||||
message: `Prolink does not match for ${filteredLot[0].MachineDescription}`,
|
);
|
||||||
};
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `Prolink does not match for ${filteredLot[0].MachineDescription}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
createLog("info", "labeling", "ocp", `Is prolink good? ${prolink}`);
|
||||||
}
|
}
|
||||||
createLog("info", "labeling", "ocp", `Is prolink good? ${prolink}`);
|
|
||||||
|
|
||||||
// create the label
|
// create the label
|
||||||
const label = await createLabel(filteredLot[0], userPrinted);
|
const label = await createLabel(filteredLot[0], userPrinted);
|
||||||
@@ -273,9 +284,12 @@ export const labelingProcess = async ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send over to be booked in if we can do it.
|
// send over to be booked in if we can do it.
|
||||||
|
|
||||||
|
// same here if we are passing zechettii dont try to book in
|
||||||
|
|
||||||
const bookin = settingData.filter((s) => s.name === "bookin");
|
const bookin = settingData.filter((s) => s.name === "bookin");
|
||||||
let book: any = [];
|
let book: any = [];
|
||||||
if (bookin[0].value === "1") {
|
if (bookin[0].value === "1" && !zechette) {
|
||||||
book = await bookInLabel(label.data);
|
book = await bookInLabel(label.data);
|
||||||
|
|
||||||
if (!book.success) {
|
if (!book.success) {
|
||||||
|
|||||||
@@ -1,177 +0,0 @@
|
|||||||
import { Controller, Tag } from "st-ethernet-ip";
|
|
||||||
import { labelingProcess } from "../../labeling/labelProcess.js";
|
|
||||||
import { createLog } from "../../../../logger/logger.js";
|
|
||||||
|
|
||||||
let plcAddress = "192.168.193.97"; // zechetti 2
|
|
||||||
let lastProcessedTimestamp = 0;
|
|
||||||
let PLC = new Controller() as any;
|
|
||||||
const labelerTag = new Tag("N7[0]"); // change the car to a or b depending on what zechetti.
|
|
||||||
//const t = new Tag("CONV_M01_SHTL_UNLD_IN_FROM_PREV_CONV_TRACK_CODE.PAL_ORIGIN_LINE_N") // this is for the new zechette to reach the pallet form
|
|
||||||
|
|
||||||
let pollingInterval: any = null;
|
|
||||||
let heartbeatInterval: any = null;
|
|
||||||
let reconnecting = false;
|
|
||||||
let lastTag = 0;
|
|
||||||
// Track last successful read
|
|
||||||
let lastHeartbeat: number = Date.now();
|
|
||||||
|
|
||||||
export async function zechitti1Connect() {
|
|
||||||
try {
|
|
||||||
createLog(
|
|
||||||
"info",
|
|
||||||
"zechitti1",
|
|
||||||
"ocp",
|
|
||||||
`Connecting to PLC at ${plcAddress}...`
|
|
||||||
);
|
|
||||||
await PLC.connect(plcAddress, 0);
|
|
||||||
createLog("info", "zechitti1", "ocp", "Zechetti 2 connected.");
|
|
||||||
|
|
||||||
// Start polling tags
|
|
||||||
startPolling();
|
|
||||||
|
|
||||||
// Start heartbeat
|
|
||||||
// startHeartbeat();
|
|
||||||
|
|
||||||
// Handle disconnects/errors
|
|
||||||
PLC.on("close", () => {
|
|
||||||
console.warn("PLC connection closed.");
|
|
||||||
handleReconnect();
|
|
||||||
});
|
|
||||||
|
|
||||||
PLC.on("error", (err: any) => {
|
|
||||||
createLog("error", "zechitti1", "ocp", `PLC error: ${err.message}`);
|
|
||||||
handleReconnect();
|
|
||||||
});
|
|
||||||
} catch (err: any) {
|
|
||||||
createLog(
|
|
||||||
"error",
|
|
||||||
"zechitti1",
|
|
||||||
"ocp",
|
|
||||||
`Initial connection failed: ${err.message}`
|
|
||||||
);
|
|
||||||
handleReconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function startPolling() {
|
|
||||||
if (pollingInterval) clearInterval(pollingInterval);
|
|
||||||
|
|
||||||
pollingInterval = setInterval(async () => {
|
|
||||||
try {
|
|
||||||
await PLC.readTag(labelerTag);
|
|
||||||
//lastHeartbeat = Date.now();
|
|
||||||
|
|
||||||
const tagTime: any = new Date(labelerTag.timestamp);
|
|
||||||
|
|
||||||
// so we make sure we are not missing a pallet remove it from the lastTag so we can get this next label correctly
|
|
||||||
if (
|
|
||||||
labelerTag.value == 0 &&
|
|
||||||
Date.now() - lastProcessedTimestamp >= 45000
|
|
||||||
) {
|
|
||||||
lastTag = labelerTag.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the tag is not zero and its been longer than 30 seconds and the last tag is not equal to the current tag we can print
|
|
||||||
if (
|
|
||||||
labelerTag.value !== 0 &&
|
|
||||||
lastTag !== labelerTag.value &&
|
|
||||||
tagTime !== lastProcessedTimestamp &&
|
|
||||||
Date.now() - lastProcessedTimestamp >= 30000
|
|
||||||
) {
|
|
||||||
lastProcessedTimestamp = tagTime;
|
|
||||||
lastTag = labelerTag.value;
|
|
||||||
console.log(
|
|
||||||
`Time since last check: ${
|
|
||||||
Date.now() - tagTime
|
|
||||||
}, greater than 30000, ${
|
|
||||||
Date.now() - lastProcessedTimestamp >= 30000
|
|
||||||
}, the line to be printed is ${labelerTag.value}`
|
|
||||||
);
|
|
||||||
//console.log(labelerTag);
|
|
||||||
const zechette = {
|
|
||||||
line: labelerTag.value.toString(),
|
|
||||||
printer: 22, // this is the id of the zechetti 2 to print we should move this to the db
|
|
||||||
printerName: "Zechetti1",
|
|
||||||
};
|
|
||||||
labelingProcess({ zechette: zechette });
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
|
||||||
createLog(
|
|
||||||
"error",
|
|
||||||
"zechitti1",
|
|
||||||
"ocp",
|
|
||||||
`Polling error: ${err.message}`
|
|
||||||
);
|
|
||||||
handleReconnect();
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// function startHeartbeat() {
|
|
||||||
// if (heartbeatInterval) clearInterval(heartbeatInterval);
|
|
||||||
|
|
||||||
// heartbeatInterval = setInterval(() => {
|
|
||||||
// const diff = Date.now() - lastHeartbeat;
|
|
||||||
// if (diff > 60000) {
|
|
||||||
// // 1 minute
|
|
||||||
// console.warn(`⚠️ Heartbeat timeout: no data for ${diff / 1000}s`);
|
|
||||||
// handleReconnect();
|
|
||||||
// }
|
|
||||||
// }, 10000); // check every 10s
|
|
||||||
// }
|
|
||||||
|
|
||||||
async function handleReconnect() {
|
|
||||||
if (reconnecting) return;
|
|
||||||
reconnecting = true;
|
|
||||||
|
|
||||||
if (pollingInterval) {
|
|
||||||
clearInterval(pollingInterval);
|
|
||||||
pollingInterval = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let delay = 2000; // start at 2s
|
|
||||||
let attempts = 0;
|
|
||||||
const maxAttempts = 10; // or limit by time, e.g. 2 min total
|
|
||||||
|
|
||||||
while (!PLC.connected && attempts < maxAttempts) {
|
|
||||||
attempts++;
|
|
||||||
createLog(
|
|
||||||
"info",
|
|
||||||
"zechitti1",
|
|
||||||
"ocp",
|
|
||||||
`Reconnect attempt ${attempts}/${maxAttempts} in ${
|
|
||||||
delay / 1000
|
|
||||||
}s...`
|
|
||||||
);
|
|
||||||
await new Promise((res) => setTimeout(res, delay));
|
|
||||||
|
|
||||||
try {
|
|
||||||
PLC = new Controller(); // fresh instance
|
|
||||||
await PLC.connect(plcAddress, 0);
|
|
||||||
createLog("info", "zechitti1", "ocp", "Reconnected to PLC!");
|
|
||||||
reconnecting = false;
|
|
||||||
startPolling();
|
|
||||||
return;
|
|
||||||
} catch (err: any) {
|
|
||||||
createLog(
|
|
||||||
"error",
|
|
||||||
"zechitti1",
|
|
||||||
"ocp",
|
|
||||||
`Reconnect attempt failed: ${err.message}`
|
|
||||||
);
|
|
||||||
delay = Math.min(delay * 2, 30000); // exponential backoff up to 30s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!PLC.connected) {
|
|
||||||
createLog(
|
|
||||||
"error",
|
|
||||||
"zechitti1",
|
|
||||||
"ocp",
|
|
||||||
"Max reconnect attempts reached. Stopping retries."
|
|
||||||
);
|
|
||||||
reconnecting = false;
|
|
||||||
// optional: exit process or alert someone here
|
|
||||||
// process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { createPlcMonitor } from "../../../utils/plcController.js";
|
||||||
|
|
||||||
|
export const zechettiConnect = () => {
|
||||||
|
const config: any = {
|
||||||
|
controllers: [
|
||||||
|
{
|
||||||
|
id: "Z1",
|
||||||
|
ip: "192.168.193.97",
|
||||||
|
slot: 0,
|
||||||
|
rpi: 250,
|
||||||
|
tags: ["N7[0]"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "Z2",
|
||||||
|
ip: "192.168.193.111",
|
||||||
|
slot: 0,
|
||||||
|
rpi: 100,
|
||||||
|
tags: ["N8[0]"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const monitor = createPlcMonitor(config);
|
||||||
|
|
||||||
|
// Start
|
||||||
|
monitor.start();
|
||||||
|
};
|
||||||
@@ -17,7 +17,6 @@ import { assignedPrinters } from "./utils/checkAssignments.js";
|
|||||||
import { printerCycle } from "./controller/printers/printerCycle.js";
|
import { printerCycle } from "./controller/printers/printerCycle.js";
|
||||||
import stopPrinterCycle from "./routes/printers/stopCycle.js";
|
import stopPrinterCycle from "./routes/printers/stopCycle.js";
|
||||||
import startPrinterCycle from "./routes/printers/startCycle.js";
|
import startPrinterCycle from "./routes/printers/startCycle.js";
|
||||||
import { printerCycleAutoLabelers } from "./controller/printers/printerCycleAutoLabelers.js";
|
|
||||||
import AutostartPrinterCycle from "./routes/printers/autoLabelerStart.js";
|
import AutostartPrinterCycle from "./routes/printers/autoLabelerStart.js";
|
||||||
import AutostopPrinterCycle from "./routes/printers/autoLabelerStop.js";
|
import AutostopPrinterCycle from "./routes/printers/autoLabelerStop.js";
|
||||||
import { deleteLabels } from "../../globalUtils/dbCleanUp/labelCleanUp.js";
|
import { deleteLabels } from "../../globalUtils/dbCleanUp/labelCleanUp.js";
|
||||||
@@ -26,7 +25,8 @@ import labelRatio from "./routes/labeling/getLabelRatio.js";
|
|||||||
import resetRatio from "./routes/labeling/resetLabelRatio.js";
|
import resetRatio from "./routes/labeling/resetLabelRatio.js";
|
||||||
import materialTransferLot from "./routes/materials/lotTransfer.js";
|
import materialTransferLot from "./routes/materials/lotTransfer.js";
|
||||||
import pendingTransfers from "./routes/materials/currentPending.js";
|
import pendingTransfers from "./routes/materials/currentPending.js";
|
||||||
import { zechitti1Connect } from "./controller/specialProcesses/zechettis/zechetti1.js";
|
import { createPlcMonitor } from "./utils/plcController.js";
|
||||||
|
import { zechettiConnect } from "./controller/specialProcesses/zechettis/zechettiConnect.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ setTimeout(() => {
|
|||||||
// if zechetti plc is wanted we will connect
|
// if zechetti plc is wanted we will connect
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (zechetti[0]?.value === "1") {
|
if (zechetti[0]?.value === "1") {
|
||||||
zechitti1Connect();
|
zechettiConnect();
|
||||||
}
|
}
|
||||||
}, 3 * 1000);
|
}, 3 * 1000);
|
||||||
|
|
||||||
|
|||||||
155
lstV2/server/services/ocp/utils/plcController.ts
Normal file
155
lstV2/server/services/ocp/utils/plcController.ts
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
import { ControllerManager } from "st-ethernet-ip";
|
||||||
|
import { getMac } from "./getMachineId.js";
|
||||||
|
import { format } from "date-fns-tz";
|
||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
|
||||||
|
import { getCurrentLabel } from "../../sqlServer/querys/ocp/getLabel.js";
|
||||||
|
import { query } from "../../sqlServer/prodSqlServer.js";
|
||||||
|
import { createLog } from "../../logger/logger.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++;
|
||||||
|
}
|
||||||
|
console.log(`[${cfg.id}] Connected @ ${cfg.ip}:${cfg.slot}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
plc.on("Disconnected", () => {
|
||||||
|
const s = stats[cfg.id];
|
||||||
|
s.connected = false;
|
||||||
|
s.lastDisconnectedAt = nowISO();
|
||||||
|
console.log(`[${cfg.id}] Disconnected`);
|
||||||
|
});
|
||||||
|
|
||||||
|
plc.on("error", (err: any) => {
|
||||||
|
console.error(`[${cfg.id}] Error:`, 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);
|
||||||
|
console.log(macId);
|
||||||
|
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
|
||||||
|
}}`
|
||||||
|
);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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 };
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user