feat(ocp): printer sync and logging logic added
This commit is contained in:
@@ -2,6 +2,7 @@ NODE_ENV=development
|
||||
# Server
|
||||
PORT=3000
|
||||
URL=http://localhost:3000
|
||||
SERVER_IP=10.75.2.38
|
||||
TIMEZONE=America/New_York
|
||||
TCP_PORT=2222
|
||||
|
||||
@@ -22,7 +23,7 @@ DEFAULT_DOCK=
|
||||
DEFAULT_LOAD_TYPE=
|
||||
DEFAULT_CARRIER=
|
||||
|
||||
# prodServer when runing on an actual prod server use localhost this way we dont go out and back in.
|
||||
# prodServer when ruining on an actual prod server use localhost this way we don't go out and back in.
|
||||
PROD_SERVER=
|
||||
PROD_PLANT_TOKEN=
|
||||
PROD_USER=
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { integer, pgTable, text } from "drizzle-orm/pg-core";
|
||||
import { integer, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
||||
|
||||
export const opendockApt = pgTable("printer_log", {
|
||||
export const printerLog = pgTable("printer_log", {
|
||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||
name: text("name").notNull(),
|
||||
name: text("name"),
|
||||
ip: text("ip"),
|
||||
printerSN: text("printer_sn"),
|
||||
condition: text("condition").notNull(),
|
||||
message: text("message"),
|
||||
createdAt: timestamp("created_at").defaultNow(),
|
||||
});
|
||||
|
||||
@@ -14,20 +14,82 @@
|
||||
*/
|
||||
|
||||
import { Router } from "express";
|
||||
import multer from "multer";
|
||||
import { db } from "../db/db.controller.js";
|
||||
import { printerLog } from "../db/schema/printerLogs.schema.js";
|
||||
import { apiReturn } from "../utils/returnHelper.utils.js";
|
||||
import { tryCatch } from "../utils/trycatch.utils.js";
|
||||
|
||||
type PrinterEvent = {
|
||||
name: string;
|
||||
condition: string;
|
||||
message: string;
|
||||
};
|
||||
const r = Router();
|
||||
const upload = multer();
|
||||
|
||||
r.post("/printer/listener/:printer", async (req, res) => {
|
||||
const parseZebraAlert = (body: any): PrinterEvent => {
|
||||
const name = body.uniqueId || "unknown";
|
||||
const decoded = decodeURIComponent(body.alertMsg || "");
|
||||
|
||||
const [conditionRaw, ...rest] = decoded.split(":");
|
||||
const condition = conditionRaw?.toLowerCase()?.trim() || "unknown";
|
||||
const message = rest.join(":").trim();
|
||||
|
||||
return {
|
||||
name,
|
||||
condition,
|
||||
message,
|
||||
};
|
||||
};
|
||||
|
||||
r.post("/printer/listener/:printer", upload.any(), async (req, res) => {
|
||||
const { printer: printerName } = req.params;
|
||||
console.log(req.body);
|
||||
const event: PrinterEvent = parseZebraAlert(req.body);
|
||||
|
||||
const rawIp =
|
||||
req.headers["x-forwarded-for"]?.toString().split(",")[0]?.trim() ||
|
||||
req.socket.remoteAddress ||
|
||||
req.ip;
|
||||
|
||||
const ip = rawIp?.replace("::ffff:", "");
|
||||
|
||||
// post the new message
|
||||
const { data, error } = await tryCatch(
|
||||
db
|
||||
.insert(printerLog)
|
||||
.values({
|
||||
ip: ip?.replace("::ffff:", ""),
|
||||
name: printerName,
|
||||
printerSN: event.name,
|
||||
condition: event.condition,
|
||||
message: event.message,
|
||||
})
|
||||
.returning(),
|
||||
);
|
||||
|
||||
if (error) {
|
||||
return apiReturn(res, {
|
||||
success: false,
|
||||
level: "info",
|
||||
module: "ocp",
|
||||
subModule: "printing",
|
||||
message: `${printerName} encountered an error posting the log`,
|
||||
data: error as any,
|
||||
status: 400,
|
||||
});
|
||||
}
|
||||
|
||||
if (data) {
|
||||
// TODO: send message over to the controller to decide what to do next with it
|
||||
}
|
||||
|
||||
return apiReturn(res, {
|
||||
success: true,
|
||||
level: "info",
|
||||
module: "ocp",
|
||||
subModule: "printing",
|
||||
message: `${printerName} just passed over a message`,
|
||||
message: `${printerName} just sent a message`,
|
||||
data: req.body ?? [],
|
||||
status: 200,
|
||||
});
|
||||
|
||||
@@ -10,10 +10,323 @@
|
||||
* printer status will live here this will be how we manage all the levels of status like 3 paused, 1 printing, 8 error, 10 power up, etc...
|
||||
*/
|
||||
|
||||
import { eq } from "drizzle-orm";
|
||||
import net from "net";
|
||||
import { db } from "../db/db.controller.js";
|
||||
import { printerData } from "../db/schema/printers.schema.js";
|
||||
import { createLogger } from "../logger/logger.controller.js";
|
||||
import { delay } from "../utils/delay.utils.js";
|
||||
import { runProdApi } from "../utils/prodEndpoint.utils.js";
|
||||
import { returnFunc } from "../utils/returnHelper.utils.js";
|
||||
|
||||
type Printer = {
|
||||
name: string;
|
||||
humanReadableId: string;
|
||||
type: number;
|
||||
ipAddress: string;
|
||||
port: number;
|
||||
default: boolean;
|
||||
labelInstanceIpAddress: string;
|
||||
labelInstancePort: number;
|
||||
active: boolean;
|
||||
remark: string;
|
||||
processes: number[];
|
||||
};
|
||||
|
||||
const log = createLogger({ module: "ocp", subModule: "printers" });
|
||||
|
||||
export const printerManager = async () => {};
|
||||
|
||||
export const printerHeartBeat = async () => {
|
||||
// heat heats will be defaulted to 60 seconds no reason to allow anything else
|
||||
// heat heats will be defaulted to 60 seconds no reason to allow anything else, and heart beats will only go to assigned printers no need to be monitoring non labeling printers
|
||||
};
|
||||
|
||||
//export const printerStatus = async (statusNr: number, printerId: number) => {};
|
||||
export const printerSync = async () => {
|
||||
// pull the printers from alpla prod and update them in lst
|
||||
|
||||
const printers = await runProdApi({
|
||||
method: "get",
|
||||
endpoint: "/public/v1.0/Administration/Printers",
|
||||
});
|
||||
|
||||
if (!printers?.success) {
|
||||
return returnFunc({
|
||||
success: false,
|
||||
level: "error",
|
||||
module: "ocp",
|
||||
subModule: "printer",
|
||||
message: printers?.message ?? "",
|
||||
data: printers?.data ?? [],
|
||||
notify: false,
|
||||
});
|
||||
}
|
||||
|
||||
if (printers?.success) {
|
||||
const ignorePrinters = ["pdf24", "standard"];
|
||||
|
||||
const validPrinters =
|
||||
printers.data.filter(
|
||||
(n: any) =>
|
||||
!ignorePrinters.includes(n.name.toLowerCase()) && n.ipAddress,
|
||||
) ?? [];
|
||||
if (validPrinters.length) {
|
||||
for (const printer of validPrinters as Printer[]) {
|
||||
// run an update for each printer, do on conflicts based on the printer id
|
||||
log.debug({}, `Add/Updating ${printer.name}`);
|
||||
|
||||
if (printer.active) {
|
||||
await db
|
||||
.insert(printerData)
|
||||
.values({
|
||||
name: printer.name,
|
||||
humanReadableId: printer.humanReadableId,
|
||||
ipAddress: printer.ipAddress,
|
||||
port: printer.port,
|
||||
remark: printer.remark,
|
||||
processes: printer.processes,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: printerData.humanReadableId,
|
||||
set: {
|
||||
name: printer.name,
|
||||
humanReadableId: printer.humanReadableId,
|
||||
ipAddress: printer.ipAddress,
|
||||
port: printer.port,
|
||||
remark: printer.remark,
|
||||
processes: printer.processes,
|
||||
},
|
||||
})
|
||||
.returning();
|
||||
await tcpPrinter(printer);
|
||||
}
|
||||
|
||||
if (!printer.active) {
|
||||
log.warn({}, `${printer.name} is not active so removing from lst.`);
|
||||
await db
|
||||
.delete(printerData)
|
||||
.where(eq(printerData.humanReadableId, printer.humanReadableId));
|
||||
}
|
||||
}
|
||||
return returnFunc({
|
||||
success: true,
|
||||
level: "info",
|
||||
module: "ocp",
|
||||
subModule: "printer",
|
||||
message: `${printers.data.length} printers were just synced, this includes new and old printers`,
|
||||
data: [],
|
||||
notify: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return returnFunc({
|
||||
success: true,
|
||||
level: "info",
|
||||
module: "ocp",
|
||||
subModule: "printer",
|
||||
message: `No printers to update`,
|
||||
data: [],
|
||||
notify: false,
|
||||
});
|
||||
};
|
||||
|
||||
const tcpPrinter = (printer: Printer) => {
|
||||
return new Promise<void>((resolve) => {
|
||||
const socket = new net.Socket();
|
||||
const timeoutMs = 15 * 1000;
|
||||
|
||||
const commands = [
|
||||
{
|
||||
key: "clearAlerts",
|
||||
command: '! U1 setvar "alerts.configured" ""\r\n',
|
||||
},
|
||||
{
|
||||
key: "addAlert",
|
||||
command: `! U1 setvar "alerts.add" "ALL MESSAGES,HTTP-POST,Y,Y,http://${process.env.SERVER_IP}:${process.env.PORT}/lst/api/ocp/printer/listener/${printer.name},0,N,printer"\r\n`,
|
||||
},
|
||||
{
|
||||
key: "setFriendlyName",
|
||||
command: `! U1 setvar "device.friendly_name" "${printer.name}"\r\n`,
|
||||
},
|
||||
{
|
||||
key: "getUniqueId",
|
||||
command: '! U1 getvar "device.unique_id"\r\n',
|
||||
},
|
||||
] as const;
|
||||
|
||||
let currentCommandIndex = 0;
|
||||
let awaitingSerial = false;
|
||||
let settled = false;
|
||||
|
||||
const cleanup = () => {
|
||||
socket.removeAllListeners();
|
||||
socket.destroy();
|
||||
};
|
||||
|
||||
const finish = (err?: unknown) => {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
clearTimeout(timeout);
|
||||
cleanup();
|
||||
|
||||
if (err) {
|
||||
log.error(
|
||||
{ err, printer: printer.name },
|
||||
`Printer update failed for ${printer.name}: doing the name and alert add directly on the printer.`,
|
||||
);
|
||||
}
|
||||
|
||||
resolve();
|
||||
};
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
finish(`${printer.name} timed out while updating printer config`);
|
||||
}, timeoutMs);
|
||||
|
||||
const sendNext = async () => {
|
||||
if (currentCommandIndex >= commands.length) {
|
||||
socket.end();
|
||||
return;
|
||||
}
|
||||
|
||||
const current = commands[currentCommandIndex];
|
||||
|
||||
if (!current) {
|
||||
socket.end();
|
||||
return;
|
||||
}
|
||||
|
||||
awaitingSerial = current.key === "getUniqueId";
|
||||
|
||||
log.info(
|
||||
{ printer: printer.name, command: current.key },
|
||||
`Sending command to ${printer.name}`,
|
||||
);
|
||||
|
||||
socket.write(current.command);
|
||||
|
||||
currentCommandIndex++;
|
||||
|
||||
// Small pause between commands so the printer has breathing room
|
||||
if (currentCommandIndex < commands.length) {
|
||||
await delay(1500);
|
||||
await sendNext();
|
||||
} else {
|
||||
// last command was sent, now wait for final data/close
|
||||
await delay(1500);
|
||||
socket.end();
|
||||
}
|
||||
};
|
||||
|
||||
socket.connect(printer.port, printer.ipAddress, async () => {
|
||||
log.info({}, `Connected to ${printer.name}`);
|
||||
|
||||
try {
|
||||
await sendNext();
|
||||
} catch (error) {
|
||||
finish(
|
||||
error instanceof Error
|
||||
? error
|
||||
: new Error(
|
||||
`Unknown error while sending commands to ${printer.name}`,
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("data", async (data) => {
|
||||
const response = data.toString().trim().replaceAll('"', "");
|
||||
|
||||
log.info(
|
||||
{ printer: printer.name, response },
|
||||
`Received printer response from ${printer.name}`,
|
||||
);
|
||||
|
||||
if (!awaitingSerial) return;
|
||||
|
||||
awaitingSerial = false;
|
||||
|
||||
try {
|
||||
await db
|
||||
.update(printerData)
|
||||
.set({ printerSN: response })
|
||||
.where(eq(printerData.humanReadableId, printer.humanReadableId));
|
||||
} catch (error) {
|
||||
finish(
|
||||
error instanceof Error
|
||||
? error
|
||||
: new Error(`Failed to update printer SN for ${printer.name}`),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("close", () => {
|
||||
log.info({}, `Closed connection to ${printer.name}`);
|
||||
finish();
|
||||
});
|
||||
|
||||
socket.on("error", (err) => {
|
||||
finish(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// const tcpPrinter = async (printer: Printer) => {
|
||||
// const p = new net.Socket();
|
||||
// const commands = [
|
||||
// '! U1 setvar "alerts.configured" ""\r\n', // clean install just remove all alerts
|
||||
// `! U1 setvar "alerts.add" "ALL MESSAGES,HTTP-POST,Y,Y,http://${process.env.SERVER_IP}:${process.env.PORT}/lst/api/ocp/printer/listener/${printer.name},0,N,printer"\r\n`, // add in the all alert
|
||||
// `! U1 setvar "device.friendly_name" "${printer.name}"\r\n`, // change the name to match the alplaprod name
|
||||
// `! U1 getvar "device.unique_id"\r\n`, // this will get mapped into the printer as this is the one we will link to in the db.
|
||||
// //'! U1 getvar "alerts.configured" ""\r\n',
|
||||
// ];
|
||||
|
||||
// let index = 0;
|
||||
// const sendNext = async () => {
|
||||
// if (index >= commands.length) {
|
||||
// p.end();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// const cmd = commands[index] as string;
|
||||
// p.write(cmd);
|
||||
// return;
|
||||
// };
|
||||
|
||||
// p.connect(printer.port, printer.ipAddress, async () => {
|
||||
// log.info({}, `Connected to ${printer.name}`);
|
||||
// while (index < commands.length) {
|
||||
// await sendNext();
|
||||
// await delay(2000);
|
||||
// index++;
|
||||
// }
|
||||
// });
|
||||
|
||||
// p.on("data", async (data) => {
|
||||
// // this is just the sn that comes over so we will update this printer.
|
||||
// await db
|
||||
// .update(printerData)
|
||||
// .set({ printerSN: data.toString().trim().replaceAll('"', "") })
|
||||
// .where(eq(printerData.humanReadableId, printer.humanReadableId));
|
||||
|
||||
// // get the name
|
||||
// // p.write('! U1 getvar "device.friendly_name"\r\n');
|
||||
// // p.write('! U1 getvar "device.unique_id"\r\n');
|
||||
// // p.write('! U1 getvar "alerts.configured"\r\n');
|
||||
// });
|
||||
|
||||
// p.on("close", () => {
|
||||
// log.info({}, `Closed connection to ${printer.name}`);
|
||||
// p.destroy();
|
||||
// return;
|
||||
// });
|
||||
|
||||
// p.on("error", (err) => {
|
||||
// log.info(
|
||||
// { stack: err },
|
||||
// `${printer.name} encountered an error while trying to update`,
|
||||
// );
|
||||
// return;
|
||||
// });
|
||||
// };
|
||||
|
||||
38
backend/ocp/ocp.printer.update.ts
Normal file
38
backend/ocp/ocp.printer.update.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* the route that listens for the printers post.
|
||||
*
|
||||
* and http-post alert should be setup on each printer pointing to at min you will want to make the alert for
|
||||
* pause printer, you can have all on here as it will also monitor and do things on all messages
|
||||
*
|
||||
* http://{serverIP}:2222/lst/api/ocp/printer/listener/{printerName}
|
||||
*
|
||||
* the messages will be sent over to the db for logging as well as specific ones will do something
|
||||
*
|
||||
* pause will validate if can print
|
||||
* close head will repause the printer so it wont print a label
|
||||
* power up will just repause the printer so it wont print a label
|
||||
*/
|
||||
|
||||
import { Router } from "express";
|
||||
|
||||
import { apiReturn } from "../utils/returnHelper.utils.js";
|
||||
//import { tryCatch } from "../utils/trycatch.utils.js";
|
||||
import { printerSync } from "./ocp.printer.manage.js";
|
||||
|
||||
const r = Router();
|
||||
|
||||
r.post("/printer/update", async (_, res) => {
|
||||
printerSync();
|
||||
return apiReturn(res, {
|
||||
success: true,
|
||||
level: "info",
|
||||
module: "ocp",
|
||||
subModule: "printing",
|
||||
message:
|
||||
"Printer update has been triggered to monitor progress please head to the logs.",
|
||||
data: [],
|
||||
status: 200,
|
||||
});
|
||||
});
|
||||
|
||||
export default r;
|
||||
@@ -2,6 +2,7 @@ import { type Express, Router } from "express";
|
||||
import { requireAuth } from "../middleware/auth.middleware.js";
|
||||
import { featureCheck } from "../middleware/featureActive.middleware.js";
|
||||
import listener from "./ocp.printer.listener.js";
|
||||
import update from "./ocp.printer.update.js";
|
||||
|
||||
export const setupOCPRoutes = (baseUrl: string, app: Express) => {
|
||||
//setup all the routes
|
||||
@@ -16,6 +17,7 @@ export const setupOCPRoutes = (baseUrl: string, app: Express) => {
|
||||
// auth routes below here
|
||||
router.use(requireAuth);
|
||||
|
||||
router.use(update);
|
||||
//router.use("");
|
||||
|
||||
app.use(`${baseUrl}/api/ocp`, router);
|
||||
|
||||
@@ -8,12 +8,14 @@ import { connectGPSql } from "./gpSql/gpSqlConnection.controller.js";
|
||||
import { createLogger } from "./logger/logger.controller.js";
|
||||
import { startNotifications } from "./notification/notification.controller.js";
|
||||
import { createNotifications } from "./notification/notifications.master.js";
|
||||
import { printerSync } from "./ocp/ocp.printer.manage.js";
|
||||
import { monitorReleaseChanges } from "./opendock/openDockRreleaseMonitor.utils.js";
|
||||
import { opendockSocketMonitor } from "./opendock/opendockSocketMonitor.utils.js";
|
||||
import { connectProdSql } from "./prodSql/prodSqlConnection.controller.js";
|
||||
import { monitorAlplaPurchase } from "./purchase/purchase.controller.js";
|
||||
import { setupSocketIORoutes } from "./socket.io/serverSetup.js";
|
||||
import { baseSettingValidationCheck } from "./system/settingsBase.controller.js";
|
||||
import { startTCPServer } from "./tcpServer/tcp.server.js";
|
||||
import { createCronJob } from "./utils/croner.utils.js";
|
||||
import { sendEmail } from "./utils/sendEmail.utils.js";
|
||||
|
||||
@@ -29,6 +31,7 @@ const start = async () => {
|
||||
const log = createLogger({ module: "system", subModule: "main start" });
|
||||
|
||||
// triggering long lived processes
|
||||
startTCPServer();
|
||||
connectProdSql();
|
||||
connectGPSql();
|
||||
|
||||
@@ -52,6 +55,10 @@ const start = async () => {
|
||||
monitorAlplaPurchase();
|
||||
}
|
||||
|
||||
if (systemSettings.filter((n) => n.name === "ocp")[0]?.active) {
|
||||
printerSync();
|
||||
}
|
||||
|
||||
// these jobs below are system jobs and should run no matter what.
|
||||
createCronJob("JobAuditLogCleanUp", "0 0 5 * * *", () =>
|
||||
dbCleanup("jobs", 30),
|
||||
|
||||
51
backend/tcpServer/tcp.printerListener.ts
Normal file
51
backend/tcpServer/tcp.printerListener.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { db } from "../db/db.controller.js";
|
||||
import { printerLog } from "../db/schema/printerLogs.schema.js";
|
||||
import { createLogger } from "../logger/logger.controller.js";
|
||||
import { returnFunc } from "../utils/returnHelper.utils.js";
|
||||
import { tryCatch } from "../utils/trycatch.utils.js";
|
||||
|
||||
export type PrinterData = {
|
||||
ip: string;
|
||||
name: string;
|
||||
condition: string;
|
||||
message: string;
|
||||
date?: string;
|
||||
printerSN: string;
|
||||
};
|
||||
|
||||
const log = createLogger({ module: "tcp", submodule: "create_server" });
|
||||
|
||||
export const printerListen = async (tcpData: PrinterData) => {
|
||||
const ip = tcpData.ip?.replace("::ffff:", "");
|
||||
|
||||
// post the new message
|
||||
const { data, error } = await tryCatch(
|
||||
db
|
||||
.insert(printerLog)
|
||||
.values({
|
||||
ip,
|
||||
name: tcpData.name,
|
||||
condition: tcpData.condition,
|
||||
message: tcpData.message,
|
||||
printerSN: tcpData.printerSN,
|
||||
})
|
||||
.returning(),
|
||||
);
|
||||
|
||||
if (error) {
|
||||
return returnFunc({
|
||||
success: false,
|
||||
level: "error",
|
||||
module: "tcp",
|
||||
subModule: "post",
|
||||
message: "Failed to post tcp printer data.",
|
||||
data: [],
|
||||
notify: false,
|
||||
});
|
||||
}
|
||||
|
||||
if (data) {
|
||||
log.info({}, `${tcpData.name} sent a message over`);
|
||||
// TODO: send message over to the controller to decide what to do next with it
|
||||
}
|
||||
};
|
||||
117
backend/tcpServer/tcp.server.ts
Normal file
117
backend/tcpServer/tcp.server.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import net from "node:net";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../db/db.controller.js";
|
||||
import { printerData } from "../db/schema/printers.schema.js";
|
||||
import { createLogger } from "../logger/logger.controller.js";
|
||||
import { returnFunc } from "../utils/returnHelper.utils.js";
|
||||
import { tryCatch } from "../utils/trycatch.utils.js";
|
||||
import { type PrinterData, printerListen } from "./tcp.printerListener.js";
|
||||
|
||||
let tcpServer: net.Server;
|
||||
const tcpSockets: Set<net.Socket> = new Set();
|
||||
//let isServerRunning = false;
|
||||
|
||||
const port = parseInt(process.env.TCP_PORT ?? "2222", 10);
|
||||
|
||||
const parseTcpAlert = (input: string) => {
|
||||
// guard
|
||||
const colonIndex = input.indexOf(":");
|
||||
if (colonIndex === -1) return null;
|
||||
|
||||
const condition = input.slice(0, colonIndex).trim();
|
||||
const rest = input.slice(colonIndex + 1).trim();
|
||||
|
||||
// extract all [ ... ] blocks from rest
|
||||
const matches = [...rest.matchAll(/\[(.*?)\]/g)];
|
||||
|
||||
const date = matches[0]?.[1] ?? "";
|
||||
const name = matches[1]?.[1] ?? "";
|
||||
|
||||
// message = everything before first "["
|
||||
const bracketIndex = rest.indexOf("[");
|
||||
const message =
|
||||
bracketIndex !== -1 ? rest.slice(0, bracketIndex).trim() : rest;
|
||||
|
||||
return {
|
||||
condition,
|
||||
message,
|
||||
date,
|
||||
name,
|
||||
};
|
||||
};
|
||||
|
||||
export const startTCPServer = () => {
|
||||
const log = createLogger({ module: "tcp", submodule: "create_server" });
|
||||
tcpServer = net.createServer(async (socket) => {
|
||||
tcpSockets.add(socket);
|
||||
socket.on("data", async (data: Buffer) => {
|
||||
const parseData = data.toString("utf-8").trimEnd();
|
||||
|
||||
// check where the data came from then we do something.
|
||||
|
||||
const ip = socket.remoteAddress ?? "127.0.0.1";
|
||||
const { data: printer, error: pError } = await tryCatch(
|
||||
db
|
||||
.select()
|
||||
.from(printerData)
|
||||
.where(eq(printerData.ipAddress, ip.replace("::ffff:", ""))),
|
||||
);
|
||||
if (pError) {
|
||||
log.error(
|
||||
{ stack: pError },
|
||||
"There was an error getting printer data for tcp check",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (printer?.length) {
|
||||
const printerData = {
|
||||
...parseTcpAlert(parseData),
|
||||
ip,
|
||||
printerSN: printer[0]?.printerSN,
|
||||
name: printer[0]?.name,
|
||||
};
|
||||
|
||||
printerListen(printerData as PrinterData);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("end", () => {
|
||||
log.debug({}, "Client disconnected");
|
||||
// just in case we dont fully disconnect
|
||||
setTimeout(() => {
|
||||
if (!socket.destroyed) {
|
||||
socket.destroy();
|
||||
}
|
||||
}, 1000);
|
||||
tcpSockets.delete(socket);
|
||||
});
|
||||
|
||||
socket.on("error", (err: Error) => {
|
||||
log.error({ stack: err }, `Socket error:", ${err}`);
|
||||
// just in case we dont fully disconnect
|
||||
setTimeout(() => {
|
||||
if (!socket.destroyed) {
|
||||
socket.destroy();
|
||||
}
|
||||
}, 1000);
|
||||
tcpSockets.delete(socket);
|
||||
});
|
||||
});
|
||||
|
||||
tcpServer.listen(port, () => {
|
||||
log.info({}, `TCP Server listening on port ${port}`);
|
||||
});
|
||||
|
||||
//isServerRunning = true;
|
||||
return returnFunc({
|
||||
success: true,
|
||||
level: "info",
|
||||
module: "tcp",
|
||||
subModule: "create_server",
|
||||
message: "TCP server started.",
|
||||
data: [],
|
||||
notify: false,
|
||||
room: "",
|
||||
});
|
||||
};
|
||||
@@ -12,7 +12,8 @@ interface Data<T = unknown[]> {
|
||||
| "opendock"
|
||||
| "notification"
|
||||
| "email"
|
||||
| "purchase";
|
||||
| "purchase"
|
||||
| "tcp";
|
||||
subModule:
|
||||
| "db"
|
||||
| "labeling"
|
||||
@@ -34,7 +35,9 @@ interface Data<T = unknown[]> {
|
||||
| "printing"
|
||||
| "gpSql"
|
||||
| "email"
|
||||
| "gpChecks";
|
||||
| "gpChecks"
|
||||
| "prodEndpoint"
|
||||
| "create_server";
|
||||
level: "info" | "error" | "debug" | "fatal";
|
||||
message: string;
|
||||
room?: string;
|
||||
|
||||
24
migrations/0027_free_green_goblin.sql
Normal file
24
migrations/0027_free_green_goblin.sql
Normal file
@@ -0,0 +1,24 @@
|
||||
CREATE TABLE "printer_data" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"humanReadable_id" text NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"ipAddress" text,
|
||||
"port" numeric,
|
||||
"status" text,
|
||||
"statusText" text,
|
||||
"last_time_printed" timestamp DEFAULT now() NOT NULL,
|
||||
"assigned" boolean DEFAULT false,
|
||||
"remark" text,
|
||||
"printDelay" numeric DEFAULT '90',
|
||||
"processes" jsonb DEFAULT '[]'::jsonb,
|
||||
"print_delay_override" boolean DEFAULT false,
|
||||
"add_Date" timestamp DEFAULT now(),
|
||||
"upd_date" timestamp DEFAULT now(),
|
||||
CONSTRAINT "printer_data_humanReadable_id_unique" UNIQUE("humanReadable_id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "printer_log" RENAME COLUMN "name" TO "ip";--> statement-breakpoint
|
||||
ALTER TABLE "printer_log" ADD COLUMN "printer_sn" text;--> statement-breakpoint
|
||||
ALTER TABLE "printer_log" ADD COLUMN "condition" text NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "printer_log" ADD COLUMN "message" text;--> statement-breakpoint
|
||||
CREATE UNIQUE INDEX "printer_id" ON "printer_data" USING btree ("humanReadable_id");
|
||||
1
migrations/0028_keen_the_fallen.sql
Normal file
1
migrations/0028_keen_the_fallen.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "printer_log" ADD COLUMN "name" text;
|
||||
1
migrations/0029_gigantic_thunderbolt_ross.sql
Normal file
1
migrations/0029_gigantic_thunderbolt_ross.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "printer_data" ADD COLUMN "printer_sn" text;
|
||||
3
migrations/0030_high_invisible_woman.sql
Normal file
3
migrations/0030_high_invisible_woman.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE "printer_data" ALTER COLUMN "port" SET DATA TYPE integer;--> statement-breakpoint
|
||||
ALTER TABLE "printer_data" ALTER COLUMN "printDelay" SET DATA TYPE integer;--> statement-breakpoint
|
||||
ALTER TABLE "printer_data" ALTER COLUMN "printDelay" SET DEFAULT 90;
|
||||
1
migrations/0031_numerous_the_phantom.sql
Normal file
1
migrations/0031_numerous_the_phantom.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "printer_log" ADD COLUMN "created_at" timestamp DEFAULT now();
|
||||
1627
migrations/meta/0027_snapshot.json
Normal file
1627
migrations/meta/0027_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1633
migrations/meta/0028_snapshot.json
Normal file
1633
migrations/meta/0028_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1639
migrations/meta/0029_snapshot.json
Normal file
1639
migrations/meta/0029_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1639
migrations/meta/0030_snapshot.json
Normal file
1639
migrations/meta/0030_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1646
migrations/meta/0031_snapshot.json
Normal file
1646
migrations/meta/0031_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -190,6 +190,41 @@
|
||||
"when": 1775786221817,
|
||||
"tag": "0026_vengeful_wiccan",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 27,
|
||||
"version": "7",
|
||||
"when": 1776085181774,
|
||||
"tag": "0027_free_green_goblin",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 28,
|
||||
"version": "7",
|
||||
"when": 1776085921073,
|
||||
"tag": "0028_keen_the_fallen",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 29,
|
||||
"version": "7",
|
||||
"when": 1776087535705,
|
||||
"tag": "0029_gigantic_thunderbolt_ross",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 30,
|
||||
"version": "7",
|
||||
"when": 1776087914328,
|
||||
"tag": "0030_high_invisible_woman",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 31,
|
||||
"version": "7",
|
||||
"when": 1776098377074,
|
||||
"tag": "0031_numerous_the_phantom",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user