Compare commits

...

30 Commits

Author SHA1 Message Date
ba3d721940 refactor(ocp): lots of work for rfid and dyco contorl 2025-03-27 21:12:22 -05:00
27d6b6e884 refactor(ocme): added new error in posting where we know when the pallet is not instock 2025-03-27 21:11:42 -05:00
2c8d1fb710 fix(logger): changes to get the most recent verse aged 2025-03-27 21:10:57 -05:00
b5de6445b3 feat(rfid): work on the readers and there functions 2025-03-27 21:08:05 -05:00
f9f68ce969 refactor(logger): changed log level to be in the env file vs hardcoded 2025-03-27 21:07:15 -05:00
0ced135ec3 feat(updater): added in a delete function for the server side 2025-03-27 21:06:45 -05:00
7b1c6e1361 refactor(ocp): finished the dashboard and move logs and labels to a tab style 2025-03-27 21:06:25 -05:00
e3ba45ae13 fix(ocme): fixed to make sure we can always just update a runnning nunmber 2025-03-27 21:05:49 -05:00
ac7859fda3 chore(release): bump build number to 115 2025-03-27 20:21:24 -05:00
fb31ae79d1 chore(release): bump build number to 114 2025-03-27 18:50:04 -05:00
ff1dfdde68 chore(release): bump build number to 113 2025-03-27 18:44:11 -05:00
f0b9bd599a chore(release): bump build number to 112 2025-03-27 18:42:43 -05:00
f3103d8c1a chore(release): bump build number to 111 2025-03-27 18:22:13 -05:00
d557728fa2 chore(release): bump build number to 110 2025-03-27 17:26:30 -05:00
d58cb5286e chore(release): bump build number to 109 2025-03-27 17:03:39 -05:00
7d4733896e chore(release): bump build number to 108 2025-03-27 16:48:14 -05:00
175c7226ed chore(release): bump build number to 107 2025-03-27 15:00:51 -05:00
c32547ceb8 chore(release): bump build number to 106 2025-03-27 14:47:42 -05:00
a01c0566c2 chore(release): bump build number to 105 2025-03-27 14:46:43 -05:00
ca4106945b chore(release): bump build number to 104 2025-03-27 14:45:41 -05:00
1386e0f00f chore(release): bump build number to 103 2025-03-27 14:44:10 -05:00
290f20b86b chore(release): bump build number to 102 2025-03-27 14:33:34 -05:00
52171c87fc chore(release): bump build number to 101 2025-03-27 14:31:22 -05:00
c474536992 chore(release): bump build number to 100 2025-03-27 14:07:33 -05:00
600a989226 chore(release): bump build number to 99 2025-03-27 11:55:35 -05:00
ea7801fccf chore(release): bump build number to 98 2025-03-27 10:59:53 -05:00
c03b61f48a chore(release): bump build number to 97 2025-03-27 10:33:59 -05:00
ca552d5587 chore(release): bump build number to 96 2025-03-27 10:12:23 -05:00
278c5538bc chore(release): bump build number to 95 2025-03-27 09:21:15 -05:00
f39ae0f590 chore(release): bump build number to 94 2025-03-27 09:10:01 -05:00
46 changed files with 2337 additions and 428 deletions

View File

@@ -0,0 +1,4 @@
ALTER TABLE "prodlabels" ALTER COLUMN "add_date" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "prodlabels" ALTER COLUMN "upd_date" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "prodlabels" ADD COLUMN "add_user" text DEFAULT 'lst';--> statement-breakpoint
CREATE UNIQUE INDEX "ocme_runningNr" ON "ocmeData" USING btree ("runningNr");

File diff suppressed because it is too large Load Diff

View File

@@ -225,6 +225,13 @@
"when": 1742939306614,
"tag": "0031_loud_alex_power",
"breakpoints": true
},
{
"idx": 32,
"version": "7",
"when": 1743124980863,
"tag": "0032_tough_iron_monger",
"breakpoints": true
}
]
}

View File

@@ -1,4 +1,13 @@
import {text, pgTable, numeric, index, timestamp, boolean, uuid, uniqueIndex} from "drizzle-orm/pg-core";
import {
text,
pgTable,
numeric,
index,
timestamp,
boolean,
uuid,
uniqueIndex,
} from "drizzle-orm/pg-core";
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
import { z } from "zod";
@@ -20,6 +29,7 @@ export const ocmeData = pgTable(
(table) => [
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
// uniqueIndex("role_name").on(table.name),
uniqueIndex("ocme_runningNr").on(table.runningNr),
]
);

View File

@@ -125,7 +125,10 @@ export default function LabelLog() {
{label.runningNr}
</TableCell>
<TableCell className="font-medium">
{format(label.upd_date, "M/d/yyyy hh:mm")}
{format(
label?.upd_date.replace("Z", ""),
"M/d/yyyy hh:mm"
)}
</TableCell>
<TableCell className="font-medium">
{label.status}

View File

@@ -70,8 +70,6 @@ export default function Lots() {
const { settings } = useSettingStore();
const server = settings.filter((n) => n.name === "server")[0]?.value || "";
console.log(data);
const roles = ["admin", "manager", "operator"];
if (user && roles.includes(user.role)) {
@@ -234,9 +232,7 @@ export default function Lots() {
server === "localhost" ? (
<>
<TableCell className="flex justify-center">
<ManualPrintForm
lot={lot}
/>
<ManualPrintForm />
</TableCell>
</>
) : (

View File

@@ -20,31 +20,31 @@ import {
SelectValue,
} from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import {useSessionStore} from "@/lib/store/sessionStore";
import { useSettingStore } from "@/lib/store/useSettings";
import {LotType} from "@/types/lots";
import axios from "axios";
import { Tag } from "lucide-react";
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { toast } from "sonner";
import {manualPrintLabels} from "./ManualPrintLabel";
const printReason = [
{ key: "printerIssue", label: "Printer Related" },
{ key: "missingRfidTag", label: "Missing or incorrect tag" },
{ key: "strapper", label: "Strapper Error" },
{ key: "manualCheck", label: "20th pallet check" },
{ key: "outOfSync", label: "Labeler Out of Sync" },
];
export default function ManualPrintForm({lot}: {lot: LotType}) {
const {user} = useSessionStore();
export default function ManualPrintForm() {
const token = localStorage.getItem("auth_token");
const { settings } = useSettingStore();
const [open, setOpen] = useState(false);
const server = settings.filter((n) => n.name === "server")[0]?.value;
// const serverPort = settings.filter((n) => n.name === "serverPort")[0]?.value;
// const serverUrl = `http://${server}:${serverPort}`;
// what is the dyco set to? rfid or dyco
const dyco = settings.filter((n) => n.name === "dycoPrint");
const {
register,
handleSubmit,
@@ -54,27 +54,22 @@ export default function ManualPrintForm({lot}: {lot: LotType}) {
control,
} = useForm();
const handlePrintLabel = async (lot: LotType) => {
//console.log(lot);
const labels: any = await manualPrintLabels(lot, user);
if (labels.success) {
toast.success(labels.message);
} else {
toast.error(labels.message);
}
};
const handleManualPrintLog = async (logData: any, lot: LotType) => {
const handleManualPrintLog = async (logData: any) => {
// toast.success(`A new label was sent to printer: ${lot.PrinterName} for line ${lot.MachineDescription} `);
const logdataUrl = `/api/ocp/manualLabelLog`;
const logdataUrl = `/api/ocp/manuallabellog`;
axios
.post(logdataUrl, logData, {headers: {Authorization: `Bearer ${token}`}})
.post(logdataUrl, logData, {
headers: { Authorization: `Bearer ${token}` },
})
.then((d) => {
//console.log(d);
console.log(d);
if (d.data.success) {
toast.success(d.data.message);
handlePrintLabel(lot);
} else {
toast.error(d.data.message);
}
reset();
setOpen(false);
})
.catch((e) => {
if (e.response.status === 500) {
@@ -91,9 +86,14 @@ export default function ManualPrintForm({lot}: {lot: LotType}) {
};
const onSubmit = (data: any) => {
console.log(data);
//console.log(data);
handleManualPrintLog(data, lot);
handleManualPrintLog(data);
};
const closeForm = () => {
reset();
setOpen(false);
};
return (
<Dialog
@@ -117,12 +117,14 @@ export default function ManualPrintForm({lot}: {lot: LotType}) {
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>
Make changes to your profile here. Click save when you're done.
Make changes to your profile here. Click save when
you're done.
</DialogDescription>
</DialogHeader>
<form onSubmit={handleSubmit(onSubmit)}>
<p>
To manually print a label you must complete all the required fields below.
To manually print a label you must complete all the
required fields below.
<br />
If you clicked this in error just click close
</p>
@@ -143,35 +145,46 @@ export default function ManualPrintForm({lot}: {lot: LotType}) {
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Print Reasons</SelectLabel>
{printReason.map((printReason: any) => (
<SelectItem value={printReason.key}>{printReason.label}</SelectItem>
))}
<SelectLabel>
Print Reasons
</SelectLabel>
{printReason.map(
(printReason: any) => (
<SelectItem
value={printReason.key}
>
{printReason.label}
</SelectItem>
)
)}
</SelectGroup>
</SelectContent>
</Select>
)}
/>
) : (
<div>
<div className="m-2">
<Label htmlFor="printRason" className="m-1">
Why are you manually printing?
</Label>
<Input
type="text"
className={errors.printReason ? "border-red-500" : ""}
className={
errors.printReason ? "border-red-500" : ""
}
aria-invalid={!!errors.printReason}
{...register("printReason", {
required: true,
minLength: {
value: 5,
message: "To short of a reason please try again!",
message:
"To short of a reason please try again!",
},
})}
/>
</div>
)}
<div>
<div className="m-2">
<Label htmlFor="line" className="m-1">
"What is the line number you are printing?"
</Label>
@@ -184,7 +197,7 @@ export default function ManualPrintForm({lot}: {lot: LotType}) {
/>
</div>
<div>
<div className="m-2">
<Label htmlFor="initials" className="m-1">
Enter intials
</Label>
@@ -195,20 +208,52 @@ export default function ManualPrintForm({lot}: {lot: LotType}) {
{...register("initials", { required: true })}
/>
</div>
<hr />
{dyco[0].value === "0" && (
<div>
<p>Enter the missing tag number.</p>
<hr />
<Label htmlFor="rfidTag" className="m-1">
Enter the tag number only Example
ALPLA000002541. only enter 2541
</Label>
<Input
type="text"
className={
errors.printReason ? "border-red-500" : ""
}
aria-invalid={!!errors.printReason}
{...register("rfidTag", {
required: true,
minLength: {
value: 1,
message: "Tag number is to short!",
},
})}
/>
</div>
)}
<div className="m-2">
<Textarea
//label="Comments"
placeholder="add more info as needed."
{...register("additionalComments")}
/>
</div>
<DialogFooter>
<Button color="danger" variant="default" onClick={() => setOpen(!open)}>
<div className="mt-3">
<Button
color="danger"
variant="default"
onClick={closeForm}
>
Close
</Button>
<Button color="primary" type="submit">
Print
</Button>
</div>
</DialogFooter>
</form>
</DialogContent>

View File

@@ -3,7 +3,7 @@ import axios from "axios";
export const manualPrintLabels = async (lot: LotType, user: any) => {
//console.log(lot);
const labelUrl = `/ocp/manualPrintAndFollow`;
const labelUrl = `/api/ocp/manualprintandfollow`;
try {
const res = await axios.post(
@@ -19,7 +19,7 @@ export const manualPrintLabels = async (lot: LotType, user: any) => {
};
} else {
return {
success: true,
success: false,
message: `Line ${lot.MachineDescription} encountered an error printing labels: ${res.data.message}`,
};
}

View File

@@ -1,5 +1,154 @@
import { LstCard } from "@/components/extendedUI/LstCard";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { getOcpLogs } from "@/utils/querys/production/ocpLogs";
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
import { format } from "date-fns";
import { Trash } from "lucide-react";
import { toast } from "sonner";
const labelLogs = [
{ key: "message", label: "Error Message" },
{ key: "created_at", label: "ErrorDat" },
{ key: "clear", label: "Clear" },
//{key: "reprint", label: "Reprint"}, // removing the reprint button for now until repritning is working as intended
];
export default function OcpLogs() {
return <LstCard className="m-2 p-2">Ocp Logs</LstCard>;
const { data, isError, isLoading } = useQuery(getOcpLogs("4"));
const clearLog = async (log: any) => {
try {
const res = await axios.patch(`/api/logger/logs/${log.log_id}`);
if (res.data.success) {
toast.success(`Log message: ${log.message}, was just cleared`);
} else {
console.log(res);
toast.error(`There was an error clearing the message.`);
}
} catch (error) {
toast.error(`There was an error trying to clearing the message.`);
}
};
const logData = data ? data : [];
if (isError) {
return (
<div className="m-2 p-2 min-h-2/5">
<LstCard>
<p className="text-center">Labels for the last 2 hours</p>
<Table>
<TableHeader>
<TableRow>
{labelLogs.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{Array(7)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</LstCard>
</div>
);
}
return (
<LstCard className="m-2 p-2 min-h-2/5">
<p className="text-center">Labels for the last 2 hours</p>
<Table>
<TableHeader>
<TableRow>
{labelLogs.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
</TableHeader>
{isLoading ? (
<>
<TableBody>
{Array(7)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</>
) : (
<TableBody>
{logData.map((label: any) => (
<TableRow key={label.log_id}>
<TableCell className="font-medium max-w-5/6">
<p className="text-balance">
{label.message}
</p>
</TableCell>
<TableCell className="font-medium">
{format(
label?.created_at.replace("Z", ""),
"M/d/yyyy hh:mm"
)}
</TableCell>
<TableCell className="font-medium">
<Button
size="icon"
onClick={() => clearLog(label)}
>
<Trash />
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
)}
</Table>
</LstCard>
);
}

View File

@@ -4,6 +4,7 @@ import Lots from "./Lots";
import OcpLogs from "./OcpLogs";
import PrinterStatus from "./PrinterStatus";
import { useSettingStore } from "@/lib/store/useSettings";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
export default function OCPPage() {
const { settings } = useSettingStore();
@@ -17,13 +18,25 @@ export default function OCPPage() {
<Lots />
</div>
<div className="flex flex-row">
<div className="w-1/2">
<LabelLog />
</div>
<div className="w-1/2">
<div className="w-5/6">
<Tabs defaultValue="ocplogs" className="w-full">
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="ocplogs">
OcpLogs
</TabsTrigger>
<TabsTrigger value="labels">Labels</TabsTrigger>
</TabsList>
<TabsContent value="ocplogs">
<div className="w-full">
<OcpLogs />
</div>
</TabsContent>
<TabsContent value="labels">
<div className="w-full">
<LabelLog />
</div>
</TabsContent>
</Tabs>
</div>
</div>
<div className="w-1/6 flex flex-col">

View File

@@ -7,7 +7,7 @@ export function getlabels(hours: string) {
queryFn: () => fetchSettings(hours),
staleTime: 1000,
//refetchInterval: 2500,
refetchInterval: 2 * 2000,
refetchOnWindowFocus: true,
});
}

View File

@@ -7,7 +7,7 @@ export function getlots() {
queryFn: () => fetchSettings(),
staleTime: 10 * 1000,
//refetchInterval: 10 * 1000,
refetchInterval: 10 * 1000,
refetchOnWindowFocus: true,
});
}

View File

@@ -0,0 +1,22 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getOcpLogs(hours: string) {
return queryOptions({
queryKey: ["ocpLogs"],
queryFn: () => fetchSettings(hours),
staleTime: 1000,
refetchInterval: 2 * 1000,
refetchOnWindowFocus: true,
});
}
const fetchSettings = async (hours: string) => {
const { data } = await axios.get(
`/api/logger/logs?service=ocp&service=rfid&level=error&level=warn&hours=${hours}`
);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -21,8 +21,8 @@
"deploy": "standard-version --conventional-commits && npm run prodBuild",
"zipServer": "dotenvx run -f .env -- tsx server/scripts/zipUpBuild.ts \"C:\\Users\\matthes01\\Documents\\lstv2\"",
"v1Build": "cd C:\\Users\\matthes01\\Documents\\logisticsSupportTool && npm run oldBuilder",
"scriptBuild": "powershell -ExecutionPolicy Bypass -File server/scripts/build.ps1 -dir \"C:\\Users\\matthes01\\Documents\\lstv2-dev\"",
"prodBuild": "npm run v1Build && npm run zipServer",
"scriptBuild": "powershell -ExecutionPolicy Bypass -File server/scripts/build.ps1 -dir \"C:\\Users\\matthes01\\Documents\\lstv2\"",
"prodBuild": "npm run v1Build && npm run build && npm run zipServer",
"commit": "cz",
"prodinstall": "npm i --omit=dev && npm run db:migrate",
"checkupdates": "npx npm-check-updates"
@@ -33,7 +33,7 @@
}
},
"admConfig": {
"build": 93,
"build": 115,
"oldBuild": "backend-0.1.3.zip"
},
"devDependencies": {

View File

@@ -86,7 +86,33 @@ $plantFunness = {
$serverFile = "$($localPath)\$buildFile"
$serverPath = "$($localPath)"
Write-Host "In the plant we go!!!!!"
######################################################################################
# Removing the fist and frontend folder to make sure we keep them the same and clean.
######################################################################################
try {
# Delete the directories after extraction
Write-Host "Deleting Dist and Frontend..."
$distPath = "$serverPath\dist\"
$frontendPath = "$serverPath\frontend\"
if (Test-Path $distPath) {
Remove-Item -Path $distPath -Recurse -Force
}
if (Test-Path $frontendPath) {
Remove-Item -Path $frontendPath -Recurse -Force
}
} catch {
Write-Host "Error: $_"
exit 1 # Exit with a non-zero code if there's an error
}
Write-Host "Unzipping the folder..."
$extractedFolderPath = $serverPath

View File

@@ -1,4 +1,4 @@
import {and, eq, inArray, lte, sql} from "drizzle-orm";
import { and, eq, gte, inArray, lte, sql } from "drizzle-orm";
import { db } from "../../../../database/dbclient.js";
import { logs } from "../../../../database/schema/logs.js";
import { createLog } from "../logger.js";
@@ -6,13 +6,17 @@ import {createLog} from "../logger.js";
export const getLogs = async (data: any) => {
try {
// clear all remaining logs ne to info.
const checked = data.checked && data.checked[0] === "true" ? true : false || false;
const checked =
data.checked && data.checked[0] === "true" ? true : false || false;
const logData = await db
.select()
.from(logs)
.where(
and(
lte(logs.created_at, sql.raw(`NOW() - INTERVAL '${data.hours} hours'`)),
gte(
logs.created_at,
sql.raw(`NOW() - INTERVAL '${data.hours ?? "4"} hours'`)
),
inArray(logs.service, data.service),
inArray(logs.level, data.level),
eq(logs.checked, checked)
@@ -22,7 +26,16 @@ export const getLogs = async (data: any) => {
return { success: true, message: "logs returned", data: logData };
} catch (error) {
console.log(error);
createLog("error", "lst", "logger", `There was an error deleteing server logs. ${error}`);
return {success: false, message: "An error occured while trying to get the logs", error};
createLog(
"error",
"lst",
"logger",
`There was an error deleteing server logs. ${error}`
);
return {
success: false,
message: "An error occured while trying to get the logs",
error,
};
}
};

View File

@@ -1,6 +1,6 @@
import { pino, type LogFn, type Logger } from "pino";
export let logLevel = "info";
export let logLevel = process.env.LOGLEVEL || "info";
const transport = pino.transport({
targets: [
@@ -45,6 +45,9 @@ export const createLog = (
if (level in log) {
log[level]({ username, service }, message);
} else {
log.warn({username, service}, `Invalid log level '${level}', falling back to warn: ${message}`);
log.warn(
{ username, service },
`Invalid log level '${level}', falling back to warn: ${message}`
);
}
};

View File

@@ -38,6 +38,13 @@ export const postLabelData = async (data: any) => {
"There was an error getting the labelData"
);
}
if (label.length === 0) {
return {
success: false,
message: "The label you scanned dose not exist in stock.",
};
}
const newPost = {
sscc: newData.sscc ? newData.sscc : await createSSCC(newData.runningNr),
runningNr: newData.runningNr,
@@ -50,6 +57,7 @@ export const postLabelData = async (data: any) => {
const enterNewData = await db
.insert(ocmeData)
.values(newPost)
.onConflictDoUpdate({ target: ocmeData.runningNr, set: newPost })
.returning({
sscc: ocmeData.sscc,
runningNr: ocmeData.runningNr,
@@ -69,8 +77,8 @@ export const postLabelData = async (data: any) => {
//console.log(error);
return {
success: false,
message: "Data was posted to ocme info",
data: [],
message: "Was not posted",
data: [error],
};
}
};

View File

@@ -10,7 +10,9 @@ export const bookInLabel = async (data: any) => {
// update sscc so we can book in
const SSCC = data.SSCC.slice(2);
// api url
const url = await prodEndpointCreation("public/v1.0/Warehousing/BookIn");
const url = await prodEndpointCreation(
"/public/v1.1/Manufacturing/ProductionControlling/BookIn"
);
// create bookin
const newBookin = {
@@ -26,12 +28,12 @@ export const bookInLabel = async (data: any) => {
},
});
if (res.data.Result !== 0) {
if (res.status != 200) {
createLog(
"error",
"labeling",
"ocp",
`${data.printer.name}, Error:${res.data.Message}`
`${data.printer[0].name}, Error:${res.data}`
);
//printerUpdate(data.printer, 7, "Error while booking in.");
@@ -44,7 +46,7 @@ export const bookInLabel = async (data: any) => {
// update the label.
try {
await db
const booked = await db
.update(prodlabels)
.set({
status: "Booked in",
@@ -52,7 +54,22 @@ export const bookInLabel = async (data: any) => {
})
.where(
eq(prodlabels.runningNr, parseInt(data.SSCC.slice(10, -1)))
)
.returning({ runningNr: prodlabels.runningNr });
createLog(
"info",
"labeling",
"ocp",
`${booked[0].runningNr} , was just booked in.`
);
return {
success: true,
message: `${parseInt(
data.SSCC.slice(10, -1)
)}, was just booked in`,
};
} catch (error) {
createLog(
"error",
@@ -61,24 +78,12 @@ export const bookInLabel = async (data: any) => {
`Error creating new runningNumber in the DB.`
);
}
// label was booked in
createLog(
"info",
"labeling",
"ocp",
`${parseInt(data.SSCC.slice(10, -1))}, was just booked in`
);
return {
success: true,
message: `${parseInt(data.SSCC.slice(10, -1))}, was just booked in`,
};
} catch (error) {
createLog(
"error",
"labeling",
"ocp",
`${data.printer.name}, "Error: ${error}`
`${data.printer[0].name}, "Error: ${error}`
);
return {
success: false,

View File

@@ -43,7 +43,7 @@ export const createLabel = async (data: any, userPrinted: any) => {
const plantToken = settingsData.filter((n) => n.name === "plantToken");
const newLabel = {
scannerId: 99,
lotNr: data.LOT,
lotNr: data.lot,
machineId: data.machineID,
printerId: data.printerID,
//layoutId: cartonCustomers.includes(data.CustomerId.toString()) ? data.cartonLabel : data.palletLabel,
@@ -87,14 +87,24 @@ export const createLabel = async (data: any, userPrinted: any) => {
let newlabel = res.data;
try {
await db.insert(prodlabels).values({
const insertLabel = await db
.insert(prodlabels)
.values({
printerID: parseInt(printer[0]?.humanReadableId!, 10),
runningNr: parseInt(newlabel.SSCC.slice(10, -1)),
printerName: printer[0].name.toLowerCase(),
line: data.MachineLocation,
status: "printed",
add_user: userPrinted || "LST_System",
});
})
.returning({ runningNr: prodlabels.runningNr });
createLog(
"info",
"labeling",
"ocp",
`${insertLabel[0]?.runningNr} was just inserted into the db.`
);
} catch (error) {
createLog(
"error",
@@ -119,7 +129,7 @@ export const createLabel = async (data: any, userPrinted: any) => {
};
// check if we can remove labels or not
deleteLabels();
//deleteLabels();
return { sucess: true, message: "Label created", data: returnData }; // returning label data to be able to book in if active
} catch (error) {
createLog(

View File

@@ -1,4 +1,4 @@
import { desc, lte, sql } from "drizzle-orm";
import { desc, gte, lte, sql } from "drizzle-orm";
import { db } from "../../../../../database/dbclient.js";
import { prodlabels } from "../../../../../database/schema/prodLabels.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
@@ -8,7 +8,7 @@ export const getLabels = async (hours: string) => {
.select()
.from(prodlabels)
.where(
lte(
gte(
prodlabels.upd_date,
sql.raw(`NOW() - INTERVAL '${hours} hours'`)
)
@@ -27,6 +27,7 @@ export const getLabels = async (hours: string) => {
return {
success: true,
message: "Current labels order by upd_Date.",
count: labelInfo.length,
data: labelInfo,
};
};

View File

@@ -50,9 +50,10 @@ export const labelingProcess = async ({
// if we got a line passed over we need to get the machine id from this.
if (line) {
const macId = await getMac(line);
// filter out the lot for the line
filteredLot = lots.data.filter((l: any) => l.machineId === macId);
filteredLot = lots.data.filter(
(l: any) => l.MachineID === macId[0].HumanReadableId
);
if (filteredLot.length === 0) {
createLog(
@@ -160,7 +161,10 @@ export const labelingProcess = async ({
`Main material is not prepaired for lot ${filteredLot[0].lot}`
);
return;
return {
success: false,
message: `Main material is not prepaired for lot ${filteredLot[0].lot}`,
};
}
// comment only but will check for color
@@ -198,16 +202,19 @@ export const labelingProcess = async ({
"ocp",
`Prolink does not match for ${filteredLot[0].MachineDescription}`
);
return;
return {
success: false,
message: `Prolink does not match for ${filteredLot[0].MachineDescription}`,
};
}
createLog("info", "labeling", "ocp", `Is prolink good? ${prolink}`);
// create the label
const label = await createLabel(filteredLot[0], userPrinted);
if (!label.success) {
return { sucess: false, message: label.message, data: label.data };
}
// if (!label.success) {
// return { sucess: false, message: label.message, data: label.data };
// }
// send over to be booked in if we can do it.
const bookin = settingData.filter((s) => s.name === "bookin");

View File

@@ -0,0 +1,52 @@
import { db } from "../../../../../database/dbclient.js";
import { manualPrinting } from "../../../../../database/schema/ocpManualPrint.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { manualTag } from "../../../rfid/controller/tags/manualTag.js";
import { labelingProcess } from "./labelProcess.js";
export const manualPrint = async (manualPrint: any) => {
/**
* add the reason we did a manual print.
*/
const manualPrintData = {
line: manualPrint.line,
printReason: manualPrint.printReason,
initials: manualPrint.initials,
additionalComments: manualPrint?.additionalComments,
add_user: "lst",
};
const { data, error } = await tryCatch(
db.insert(manualPrinting).values(manualPrintData).returning({
line: manualPrinting.line,
printReason: manualPrinting.printReason,
initials: manualPrinting.initials,
additionalComments: manualPrinting?.additionalComments,
add_user: manualPrinting.add_user,
})
);
if (error) {
return {
success: false,
message: "There was an error posting the manualPrintData",
data: error,
};
}
let label = await labelingProcess({ line: manualPrint.line });
if (manualPrint.rfidTag) {
manualTag(
manualPrint.rfidTag,
"wrapper1",
parseInt(label.data.SSCC.slice(10, -1))
);
}
return {
success: true,
message: "Log Entered label will be coming soon.",
data,
};
};

View File

@@ -43,8 +43,6 @@ export const prolinkCheck = async (lot: any) => {
// run the query
try {
const prolink = await query(prolinkQuery, "Prolink Checks");
//console.log(lot);
// filter out the lot
const filterdLot = prolink.filter(
(p: any) => p.AlplaLabelOnline === lot

View File

@@ -1,44 +0,0 @@
import { db } from "../../../../database/dbclient.js";
import { manualPrinting } from "../../../../database/schema/ocpManualPrint.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
export const manualPrint = async (manualPrint: any) => {
/**
* add the reason we did a manual print.
*/
const manualPrintData = {
line: manualPrint.line,
printReason: manualPrint.printReason,
initials: manualPrint.initials,
additionalComments: manualPrint?.additionalComments,
add_user: "lst",
};
const { data, error } = await tryCatch(
db
.insert(manualPrinting)
.values(manualPrintData)
.returning({
line: manualPrinting.line,
printReason: manualPrinting.printReason,
initials: manualPrinting.initials,
additionalComments: manualPrinting?.additionalComments,
add_user: manualPrinting.add_user,
})
);
if (error) {
return {
success: false,
message: "There was an error posting the manualPrintData",
data: error,
};
}
return {
success: true,
message: "There was an error posting the manualPrintData",
data,
};
};

View File

@@ -2,13 +2,14 @@ import { Controller, Tag } from "st-ethernet-ip";
import { createLog } from "../../../../logger/logger.js";
import { labelerTagRead } from "./plcTags/labelerTag.js";
import { palletSendTag } from "./plcTags/palletSendTag.js";
import { strapperFaults } from "./plcTags/strapperFault.js";
let PLC = new Controller();
let isDycoRunning = false;
// PLC address
let plcAddress = "10.44.5.4";
let isReading = false;
// Initialize the interval variable outside the function
let plcCycle: any;
let plcInterval = 500;
@@ -31,17 +32,42 @@ export const dycoConnect = async () => {
await PLC.connect(plcAddress, 0).then(async () => {
createLog("info", "dyco", "ocp", `We are connected to the dyco.`);
isDycoRunning = true;
let buffer = "";
plcCycle = setInterval(async () => {
if (isReading) {
createLog(
"warn",
"dyco",
"ocp",
"Skipping cycle: previous read still in progress."
);
return;
}
isReading = true; // Set flag
try {
await PLC.readTag(labelerTag);
await PLC.readTag(palletSend);
await PLC.readTag(strapperError);
// strapper check
strapperFaults(strapperError);
// send the labeler tag data over
labelerTagRead(labelerTag);
// send the end of line check over.
palletSendTag(palletSend);
}, 500);
} catch (error: any) {
createLog(
"error",
"dyco",
"ocp",
`Error reading PLC tag: ${error.message}`
);
} finally {
isReading = false; // Reset flag
}
}, plcInterval);
});
} catch (error) {
createLog(
@@ -50,6 +76,7 @@ export const dycoConnect = async () => {
"ocp",
`There was an error in the dyco: ${error}`
);
await PLC.disconnect();
isDycoRunning = false;
}
};

View File

@@ -4,7 +4,10 @@ import { tryCatch } from "../../../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../../../logger/logger.js";
import { readTags } from "../../../../../rfid/controller/readTags.js";
import { labelingProcess } from "../../../labeling/labelProcess.js";
import { stapperFaulted, strapperFaults } from "./strapperFault.js";
export let cameraPalletCheck = 20;
export let currentPalletCheck = 0;
let lastProcessedTimestamp = 0;
export const labelerTagRead = async (tagData: any) => {
@@ -41,11 +44,48 @@ export const labelerTagRead = async (tagData: any) => {
// Only process if this is a new timestamp within the last 5 seconds
if (tagTime !== lastProcessedTimestamp && Date.now() - tagTime <= 5000) {
lastProcessedTimestamp = tagTime;
//console.log(numericString, tagData.state.timestamp);
/**
* add logic in to see if this is the first time we run this so we return an error to validate we are in sync.
*/
createLog(
"info",
"dyco",
"ocp",
`Current pallet at the wrapper is: ${numericString}`
);
if (dycoPrint[0].value === "1") {
createLog("info", "dyco", "ocp", "Dyco will be printing the label");
// send over to print.
// if (!dycoControlCheck) {
// createLog(
// "error",
// "dyco",
// "ocp",
// `Dyco was switch to be the printer guys. please validate the line is in sync, Current line is ${numericString}`
// );
// dycoControlCheck = true;
// return;
// }
// check the stapper error logic.
if (stapperFaulted) {
createLog("error", "dyco", "ocp", `Strapper is faulted.`);
return;
}
// check if we need to manual check due to 20 pallets.
if (currentPalletCheck <= cameraPalletCheck) {
currentPalletCheck = currentPalletCheck + 1;
labelingProcess({ line: numericString });
} else {
currentPalletCheck = 0;
createLog(
"error",
"dyco",
"ocp",
`You have reached 20 pallets since the last check please validate the labeler is still in sync.`
);
}
}
if (dycoPrint[0].value === "0") {
@@ -56,7 +96,9 @@ export const labelerTagRead = async (tagData: any) => {
"Rfid system is contorlling the printing"
);
// trigger the reader so we can get the label from the tag readers.
setTimeout(async () => {
await readTags("wrapper1");
}, 2 * 1000);
}
}
};

View File

@@ -0,0 +1,72 @@
import { db } from "../../../../../../../database/dbclient.js";
import { settings } from "../../../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../../../logger/logger.js";
// strapper related issues
export let strapperActive = true;
export let stapperFaulted = false;
export let strapperFaultCount = 3; // move to db so we can control it outside the app
export const strapperFaults = async (tagData: any) => {
const { data, error } = await tryCatch(db.select().from(settings));
if (error) {
return { success: false, message: "Failed to get settings." };
}
if (strapperActive) {
// monitor strapper
//console.log(`Strapper fault is ${strapperError.value}`);
if (tagData.value && strapperFaultCount > 0) {
// strapper faulted we want to start the trigger to force the check
if (!stapperFaulted) {
createLog(
"error",
"dyco",
"ocp",
`Strapper errored triggering manual checks will be required for the next ${strapperFaultCount}`
);
}
stapperFaulted = true;
// change move fault count to db....
strapperFaultCount = 3;
}
}
const strapperCheckSetting = data.filter((n) => n.name === "strapperCheck");
if (strapperCheckSetting[0]?.value === "1") {
if (stapperFaulted && strapperFaultCount > 0) {
createLog(
"warn",
"dyco",
"ocp",
`There was a strapper error, remaining pallets to check ${strapperFaultCount}.`
);
strapperFaultCount = strapperFaultCount - 1;
return {
success: false,
message: `There was a strapper error, remaining pallets to check ${strapperFaultCount}.`,
};
} else {
createLog(
"debug",
"dyco",
"ocp",
`Strapper check is active but not faulted, remaining pallets to check ${strapperFaultCount}.`
);
// reset everything
stapperFaulted = false;
strapperFaultCount = 3; // move to db as well
return {
success: true,
message: `Strapper check is active but not faulted, remaining pallets to check ${strapperFaultCount}.`,
};
}
}
};

View File

@@ -1,7 +1,7 @@
import { OpenAPIHono } from "@hono/zod-openapi";
// routes
import manualLabelLog from "./routes/manualPrintLog.js";
import manualLabelLog from "./routes/labeling/manualPrintLog.js";
import getPrinters from "./routes/printers/getPritners.js";
import { db } from "../../../database/dbclient.js";
import { settings } from "../../../database/schema/settings.js";
@@ -12,6 +12,7 @@ import getLabels from "./routes/labeling/getLabels.js";
import { dycoConnect } from "./controller/specialProcesses/dyco/plcConnection.js";
import dycoCon from "./routes/specialProcesses/dyco/connection.js";
import dycoClose from "./routes/specialProcesses/dyco/closeConnection.js";
import manualprint from "./routes/labeling/manualPrint.js";
const app = new OpenAPIHono();
@@ -24,6 +25,7 @@ const routes = [
getLots,
// labeling
getLabels,
manualprint,
//dyco
dycoCon,
dycoClose,

View File

@@ -30,6 +30,7 @@ app.openapi(
return c.json({
success: labelData.success,
message: labelData.message,
count: labelData.count,
data: labelData.data,
});
}

View File

@@ -0,0 +1,50 @@
// an external way to creating logs
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { labelingProcess } from "../../controller/labeling/labelProcess.js";
const app = new OpenAPIHono({ strict: false });
app.openapi(
createRoute({
tags: ["ocp"],
summary: "Manual print a label by line and printer name",
method: "post",
path: "/manualprintandfollow",
responses: responses(),
}),
async (c) => {
//const hours = c.req.query("hours");
const { data: bodyData, error: bodyError } = await tryCatch(
c.req.json()
);
if (bodyError) {
return c.json({
success: false,
message: "You are missing data",
});
}
const { data: createLabel, error: labelError } = await tryCatch(
labelingProcess({ line: bodyData.line })
);
if (labelError) {
return c.json({
success: false,
message: "There was an error creating the label.",
data: labelError,
});
}
const newLabel: any = createLabel;
return c.json({
success: newLabel.success,
message: newLabel.message,
data: newLabel.data,
});
}
);
export default app;

View File

@@ -1,11 +1,12 @@
// an external way to creating logs
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import type { User } from "../../../types/users.js";
import { apiHit } from "../../../../globalUtils/apiHits.js";
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import type { User } from "../../../../types/users.js";
import { verify } from "hono/jwt";
import { manualPrint } from "../controller/manualLabelLog.js";
import { authMiddleware } from "../../auth/middleware/authMiddleware.js";
import { manualPrint } from "../../controller/labeling/manualLabelLog.js";
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
const app = new OpenAPIHono({ strict: false });
const CreateLog = z.object({
@@ -32,7 +33,17 @@ app.openapi(
responses: responses(),
}),
async (c) => {
const body = await c.req.json();
const { data: body, error } = await tryCatch(c.req.json());
if (error) {
return c.json(
{
success: false,
message: "Missing Data.",
},
400
);
}
apiHit(c, { endpoint: `api/logger/logs/id` });
try {
//const data = {...body, add_user: user.username};

View File

@@ -1,52 +0,0 @@
// an external way to creating logs
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
import {apiHit} from "../../../globalUtils/apiHits.js";
import {responses} from "../../../globalUtils/routeDefs/responses.js";
const app = new OpenAPIHono({strict: false});
const CreateLog = z.object({
line: z.string().openapi({example: "info"}),
initials: z.string().openapi({example: "server"}),
printReason: z.string().openapi({example: "This is a new log posted"}),
additionalComments: z.string().optional().openapi({example: "Some reason why we did this."}),
});
app.openapi(
createRoute({
tags: ["ocp"],
summary: "Prints a label.",
method: "post",
path: "/printlabel",
//middleware: authMiddleware,
//description: "This might be a temp soltuin during the transtion between versions",
request: {
body: {content: {"application/json": {schema: CreateLog}}},
},
responses: responses(),
}),
async (c) => {
const body = await c.req.json();
apiHit(c, {endpoint: `api/logger/logs/id`});
// const authHeader = c.req.header("Authorization");
// const token = authHeader?.split("Bearer ")[1] || "";
// let user: User;
// try {
// const payload = await verify(token, process.env.JWT_SECRET!);
// user = payload.user as User;
// } catch (error) {
// console.log(error);
// return c.json({message: "Unauthorized"}, 401);
// }
try {
//const data = {...body, add_user: user.username};
return c.json({success: true, message: "Label was printed.", data: []}, 200);
} catch (error) {
return c.json({success: false, message: "There was an error printing a label.", data: error}, 400);
}
}
);
export default app;

View File

@@ -2,6 +2,13 @@
* For a no read we just want to put up a notification to the rfid dashboard stating this reader did not respond with any tag data.
*/
import { createLog } from "../../logger/logger.js";
export const noRead = async (reader: string) => {
console.log(`${reader} just had a no read please check for a tag and manually trigger a read.`);
createLog(
"error",
"rfid",
"rifd",
`${reader} just had a no read please check for a tag and manually trigger a read.`
);
};

View File

@@ -29,15 +29,18 @@ export const readTags = async (reader: string) => {
// get the auth token
ip = readers.find((r) => r.reader === reader)?.readerIP as string;
// start the read
startRead();
// start the read
};
const getReaderToken = async () => {
try {
const res = await axios.get(`https://${ip}/cloud/localRestLogin`, {
headers: { Authorization: `Basic ${authData}` },
});
token = res.data.message;
// start the read
startRead();
} catch (error: any) {
console.log(error);
createLog(
"error",
"rfid",
@@ -45,11 +48,10 @@ export const readTags = async (reader: string) => {
`There was an error Getting the token the read: ${error.response?.data.message}`
);
}
// start the read
};
const startRead = async () => {
await getReaderToken();
try {
const res = await axios.put(
`https://${ip}/cloud/start`,
@@ -64,12 +66,12 @@ const startRead = async () => {
if (res.status === 200) {
setTimeout(() => {
stopRead();
}, 5 * 1000);
}, 2 * 1000);
}
// stop after 5 seconds
} catch (error: any) {
if (error.response.data.code === 3) {
if (error.response?.data.code === 3) {
stopRead();
setTimeout(() => {
startRead();
@@ -79,11 +81,13 @@ const startRead = async () => {
"error",
"rfid",
"rfid",
`There was an error Starting the read: ${error.response.data.message}`
`There was an error Starting the read: ${error.response?.data.message}`
);
}
};
const stopRead = async () => {
export const stopRead = async () => {
await getReaderToken();
try {
const res = await axios.put(
`https://${ip}/cloud/stop`,
@@ -97,7 +101,7 @@ const stopRead = async () => {
"error",
"rfid",
"rfid",
`There was an error Stopping the read: ${error.response.data.message}`
`There was an error Stopping the read: ${JSON.stringify(error)}`
);
}
};

View File

@@ -17,11 +17,27 @@ export const newHeartBeat = async (reader: string) => {
.update(rfidReaders)
.set({ lastHeartBeat: sql`NOW()` })
.where(eq(rfidReaders.reader, reader));
createLog("info", "rfid", "rfid", `${reader} just updated its heatBeat.`);
return {success: true, message: `${reader} just updated its heatBeat.`};
createLog(
"debug",
"rfid",
"rfid",
`${reader} just updated its heatBeat.`
);
return {
success: true,
message: `${reader} just updated its heatBeat.`,
};
} catch (error) {
createLog("error", "rfid", "rfid", `${reader} encountered an error while updating the heatbeat, ${error}`);
return {success: false, message: `${reader} encountered an error while updating the heatbeat, ${error}`};
createLog(
"error",
"rfid",
"rfid",
`${reader} encountered an error while updating the heatbeat, ${error}`
);
return {
success: false,
message: `${reader} encountered an error while updating the heatbeat, ${error}`,
};
}
};
@@ -34,11 +50,27 @@ export const badRead = async (reader: string) => {
.update(rfidReaders)
.set({ lastTrigger: sql`NOW()`, lastTriggerGood: false })
.where(eq(rfidReaders.reader, reader));
createLog("info", "rfid", "rfid", `${reader} just Triggered a bad read.`);
return {success: true, message: `${reader} just Triggered a bad read.`};
createLog(
"info",
"rfid",
"rfid",
`${reader} just Triggered a bad read.`
);
return {
success: true,
message: `${reader} just Triggered a bad read.`,
};
} catch (error) {
createLog("error", "rfid", "rfid", `${reader} encountered an error while updating the heatbeat, ${error}`);
return {success: false, message: `${reader} encountered an error while updating the heatbeat, ${error}`};
createLog(
"error",
"rfid",
"rfid",
`${reader} encountered an error while updating the heatbeat, ${error}`
);
return {
success: false,
message: `${reader} encountered an error while updating the heatbeat, ${error}`,
};
}
};
@@ -51,10 +83,26 @@ export const goodRead = async (reader: string) => {
.update(rfidReaders)
.set({ lastTrigger: sql`NOW()`, lastTriggerGood: true })
.where(eq(rfidReaders.reader, reader));
createLog("info", "rfid", "rfid", `${reader} just Triggered a good read.`);
return {success: true, message: `${reader} just Triggered a good read.`};
createLog(
"info",
"rfid",
"rfid",
`${reader} just Triggered a good read.`
);
return {
success: true,
message: `${reader} just Triggered a good read.`,
};
} catch (error) {
createLog("error", "rfid", "rfid", `${reader} encountered an error while updating the heatbeat, ${error}`);
return {success: false, message: `${reader} encountered an error while updating the heatbeat, ${error}`};
createLog(
"error",
"rfid",
"rfid",
`${reader} encountered an error while updating the heatbeat, ${error}`
);
return {
success: false,
message: `${reader} encountered an error while updating the heatbeat, ${error}`,
};
}
};

View File

@@ -8,6 +8,12 @@ import type { TagData } from "../tagData.js";
import { tagStuff } from "../tags/crudTag.js";
export const station3Tags = async (tagData: TagData[]) => {
createLog(
"info",
"rfid",
"rfid",
`${tagData[0].reader} has a ${tagData[0].tag} will post it :)`
);
// make sure we only have one tag or dont update
if (tagData.length != 1) {
createLog(

View File

@@ -8,17 +8,46 @@ import { labelingProcess } from "../../../ocp/controller/labeling/labelProcess.j
import type { TagData } from "../tagData.js";
import { tagStuff } from "../tags/crudTag.js";
import { sendEmail } from "../../../notifications/controller/sendMail.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { db } from "../../../../../database/dbclient.js";
import { rfidTags } from "../../../../../database/schema/rfidTags.js";
import { eq } from "drizzle-orm";
export const wrapperStuff = async (tagData: TagData[]) => {
if (tagData[0]?.lastareaIn === "NeedsChecked") {
export const wrapperStuff = async (tagData: any) => {
console.log("WrapperTag", tagData[0].tag);
if (tagData.length != 1) {
createLog(
"error",
"rfid",
"rfid",
`There are ${tagData.length} tags and this ${tagData[0].reader} only allows 1 tag to create a label.`
);
const tag = { ...tagData[0], runningNr: 0 };
//tagStuff([tag]);
monitorChecks();
} else {
if (!tagData) {
createLog("error", "rfid", "rfid", `No tagData was grabbed.`);
monitorChecks();
}
const { data: tagdata, error: tagError } = await tryCatch(
db.select().from(rfidTags).where(eq(rfidTags.tag, tagData[0].tag))
);
if (tagError) {
return {
success: false,
message: `There was an error getting the tag data for ${tagData[0].tag}.`,
};
}
const checkTag: any = tagdata;
if (checkTag[0]?.lastareaIn === "NeedsChecked") {
createLog(
"error",
"rfid",
"rfid",
`The tags on this pallet need to be checked as it was flagged as more than 1 tag number. please validate and looks at both sides.`
);
// just making sure we clear out the running number if one really came over.
for (let i = 0; i < tagData.length; i++) {
const tag = { ...tagData[i], runningNr: 0 };
tagStuff([tag]);
@@ -30,47 +59,20 @@ export const wrapperStuff = async (tagData: TagData[]) => {
"The tags on this pallet need to be checked as it was flagged as more than 1 tag number. please validate and looks at both sides.",
};
}
if (tagData.length != 1) {
createLog(
"error",
"rfid",
"rfid",
`There are ${tagData.length} tags and this ${tagData[0].reader} only allows 1 tag to create a label.`
);
const tag = { ...tagData[0], runningNr: 0 };
tagStuff([tag]);
monitorChecks();
} else {
if (!tagData) {
createLog("error", "rfid", "rfid", `No tagData was grabbed.`);
monitorChecks();
}
const tagdata = await tagStuff(tagData);
/**
* we want to make sure this pallet came from a line as its last spot if not we need to have a manual check.
*/
const lines = tagdata[0]?.lastareaIn.includes("line3");
const lines = checkTag[0]?.lastareaIn.includes("line3");
if (!lines) {
createLog(
"error",
"rfid",
"rfid",
`${tagdata[0].tag}, Did not come from a line please check the pallet and manually print the label.`
`${tagData[0].tag}, Did not come from a line please check the pallet and manually print the label.`
);
monitorChecks();
return {
success: false,
message: `${tagdata[0].tag}, Did not come from a line please check the pallet and manually print the label.`,
message: `${tagData[0].tag}, Did not come from a line please check the pallet and manually print the label.`,
};
// when we manually run again we want to make sure we read from the 3rd antenna this way we do not get the wrong info.
// more testing will need to be done on this.
}
// check if a running number exists
if (lines[0].runningNumber) {
createLog(
"info",
@@ -83,12 +85,10 @@ export const wrapperStuff = async (tagData: TagData[]) => {
"info",
"rfid",
"rfid",
`A new label will be created and linked to this ${tagdata[0].tag} tag`
`A new label will be created and linked to this ${tagData[0].tag} tag`
);
// get the actaul line number from the last area in
const lineNum = parseInt(
tagdata[0]?.lastareaIn.repalceAll("line3", "")
checkTag[0]?.lastareaIn.repalceAll("line3", "")
);
createLog(
"info",
@@ -96,17 +96,16 @@ export const wrapperStuff = async (tagData: TagData[]) => {
"rfid",
`Line to be checked for printing: ${lineNum}`
);
const genlabel = await labelingProcess({
line: lineNum.toString(),
});
if (genlabel?.success) {
// update the tag and add the label into it
const createPrintData = {
...tagData[0],
runnungNr: parseInt(genlabel.data?.SSCC.slice(10, -1)),
};
tagStuff([createPrintData]);
}
}
}

View File

@@ -15,6 +15,9 @@ export const tagData = async (data: TagData[]) => {
* We will always update a tag
*/
if (monitorTagsdata.includes(data[0].tag)) {
}
// dyco wall makes sure we have 10 tags
const station1 = data.some((n) => n.reader.includes("reader1"));
@@ -44,3 +47,21 @@ export const tagData = async (data: TagData[]) => {
wrapperStuff(data);
}
};
const monitorTagsdata: any = [];
const monitorTags = (tag: string) => {
/**
* If we have to check more than 10 tags in an hour send an email to alert everyone.
*/
const now = new Date(Date.now()).getTime();
monitorTagsdata.push({ timestamp: now, tag: tag });
// remove if creater than 1 hour
const removalTiming = now - 2 * 60 * 1000; // 2 min
while (
monitorTagsdata > 0 &&
monitorTagsdata[0].timestamp < removalTiming
) {
monitorTagsdata.shift();
}
};

View File

@@ -2,7 +2,11 @@ import {db} from "../../../../../database/dbclient.js";
import { rfidTags } from "../../../../../database/schema/rfidTags.js";
import { createLog } from "../../../logger/logger.js";
export const manualTag = async (tag: string, area: string) => {
export const manualTag = async (
tag: string,
area: string,
runningNr?: any | null
) => {
/**
* we only allow tags to be manually added from the wrappers
*/
@@ -20,17 +24,33 @@ export const manualTag = async (tag: string, area: string) => {
};
try {
// insert the tag with the onConflict update the tag
const tag = await db.insert(rfidTags).values(newTag).returning({
const tag = await db
.insert(rfidTags)
.values(newTag)
.returning({
tag: rfidTags.tag,
runningNumber: rfidTags.runningNumber,
runningNumber: runningNr ? runningNr : rfidTags.runningNumber,
counts: rfidTags.counts,
lastareaIn: rfidTags.lastareaIn,
});
createLog("info", "rfid", "rfid", `Tags were just added, and label printed.`);
createLog(
"info",
"rfid",
"rfid",
`Tags were just added, and label printed.`
);
// do the label thing here
return {success: true, message: `${tagString} was just added, and label printed.`, data: tag};
return {
success: true,
message: `${tagString} was just added, and label printed.`,
data: tag,
};
} catch (error) {
createLog("error", "rfid", "rfid", `${JSON.stringify(error)}`);
return {success: false, message: `Error creating a new tag`, data: error};
return {
success: false,
message: `Error creating a new tag`,
data: error,
};
}
};

View File

@@ -38,26 +38,42 @@ app.openapi(
if (body.type === "heartbeat") {
const heart = await newHeartBeat(reader);
return c.json({success: heart.success, message: heart.message}, 200);
return c.json(
{ success: heart.success, message: heart.message },
200
);
}
if (body.type === "gpi" && body.data.state === "HIGH") {
const eventTimestamp = new Date(body.timestamp).getTime(); // Convert ISO timestamp to milliseconds
if (eventTimestamp - lastGpiTimestamp > 5 * 1000) {
if (eventTimestamp - lastGpiTimestamp > 30 * 1000) {
// Check if it's been more than 2ms
lastGpiTimestamp = eventTimestamp; // Update last seen timestamp
createLog("info", "rfid", "rfid", `${reader} is reading a tag.`);
createLog(
"info",
"rfid",
"rfid",
`${reader} is reading a tag.`
);
await readTags(reader);
} else {
createLog("info", "rfid", "rfid", `A new trigger from ${reader} was to soon`);
createLog(
"info",
"rfid",
"rfid",
`A new trigger from ${reader} was to soon`
);
lastGpiTimestamp = eventTimestamp;
}
//console.log(body);
}
return c.json({success: true, message: `New info from ${reader}`}, 200);
return c.json(
{ success: true, message: `New info from ${reader}` },
200
);
}
);

View File

@@ -5,6 +5,9 @@ import {tagData} from "../controller/tagData.js";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import { noRead } from "../controller/noRead.js";
import { badRead, goodRead } from "../controller/readerControl.js";
import { createLog } from "../../logger/logger.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { stopRead } from "../controller/readTags.js";
const app = new OpenAPIHono();
@@ -34,14 +37,24 @@ app.openapi(
}),
async (c) => {
const { reader } = c.req.valid("param");
createLog("info", "rfid", "rfid", `${reader} is sending us data.`);
let tagdata: any = [];
const body = await c.req.json();
const { data: body, error: bodyError } = await tryCatch(c.req.json());
if (bodyError) {
return c.json({ success: false, message: "missing data" }, 400);
}
//console.log(`Tag: ${Buffer.from(body.idHex, "hex").toString("utf-8")}, ${body[key].data.idHex}`);
for (let i = 0; i < body.length; i++) {
const tag = Buffer.from(body[i].data.idHex, "hex").toString("utf-8");
const tag = Buffer.from(body[i].data.idHex, "hex").toString(
"utf-8"
);
//console.log("Raw value:", body[i].data.peakRssi, "Parsed:", parseInt(body[i].data.peakRssi));
if (tag.includes("ALPLA") && parseInt(body[i].data.peakRssi) < -50) {
if (
tag.includes("ALPLA") &&
parseInt(body[i].data.peakRssi) < -50
) {
tagdata = [
...tagdata,
{
@@ -59,11 +72,18 @@ app.openapi(
if (tagdata.length === 0) {
noRead(reader);
badRead(reader);
return c.json({success: false, message: `There were no tags scanned.`}, 200);
return c.json(
{ success: false, message: `There were no tags scanned.` },
200
);
} else {
tagData(tagdata);
goodRead(reader);
return c.json({success: true, message: `New info from ${reader}`}, 200);
return c.json(
{ success: true, message: `New info from ${reader}` },
200
);
}
}
);

View File

@@ -168,6 +168,13 @@ const newSettings = [
roles: "admin",
module: "ocp",
},
{
name: "strapperCheck",
value: "1",
description: "Are we monitoring the strapper for faults?",
roles: "admin",
module: "ocp",
},
];
export const areSettingsIn = async () => {
// get the roles

View File

@@ -16,5 +16,6 @@ left join
alplaprod_test1.dbo.T_Maschine as m on
e.IdMaschine = m.IdMaschine
where x.lfdnr = [rn] and x.IdWarenlager not in(6)
where x.lfdnr = [rn]
--and x.IdWarenlager not in(6)
`;

View File

@@ -3,7 +3,7 @@ select IdMaschinen_ProdPlanung as LabelOnlineID,
IdMaschine as machineID,
MaschinenStandort as MachineLocation,
MaschinenBez as MachineDescription,
IdProdPlanung as LOT,
IdProdPlanung as lot,
prolink.lot as ProlinkLot,
IdArtikelvarianten as AV,
ArtikelVariantenBez as Alias,

View File

@@ -14,6 +14,9 @@ let tcpServer: net.Server;
let tcpSockets: Set<net.Socket> = new Set();
let isServerRunning = false;
/**
* add in proper logging
*/
const tcpPort = await db
.select()
.from(settings)
@@ -25,14 +28,19 @@ export const startTCPServer = () => {
return { success: false, message: "Server is already running" };
tcpServer = net.createServer((socket) => {
console.log("Client connected");
createLog("info", "tcp", "tcp", "Client connected");
tcpSockets.add(socket);
socket.on("data", (data: Buffer) => {
console.log("Received:", data.toString());
const parseData = data.toString("utf-8").trimEnd().split(" ");
// hb from the scanners
if (parseData[0] === "HB") {
createLog(
"debug",
"tcp",
"tcp",
`Received:", ${data.toString()}`
);
return;
}
@@ -46,12 +54,12 @@ export const startTCPServer = () => {
});
socket.on("end", () => {
console.log("Client disconnected");
createLog("info", "tcp", "tcp", "Client disconnected");
tcpSockets.delete(socket);
});
socket.on("error", (err: Error) => {
console.error("Socket error:", err);
createLog("info", "tcp", "tcp", `Socket error:", ${err}`);
tcpSockets.delete(socket);
});
});
@@ -78,7 +86,7 @@ export const stopTCPServer = () => {
}
tcpSockets.clear();
tcpServer.close(() => {
console.log("TCP Server stopped");
createLog("info", "tcp", "tcp", "TCP Server stopped");
});
isServerRunning = false;
return { success: true, message: "TCP Server stopped" };