Compare commits

..

22 Commits

Author SHA1 Message Date
6a082d9737 feat(rfid): more rfid topics while monitoring the system run 2025-07-10 20:09:35 -05:00
58711becf2 refactor(mm check): added in a check that if we dont need mm we return mm checked 2025-07-10 20:08:45 -05:00
f757085fc2 refactor(ocp page): changes to the layout so it can better be moved for the tiles 2025-07-10 20:07:59 -05:00
8f5e1cb094 refactor(wrapper card): changes to include the rfid and remove the manual trigger as no one used it 2025-07-10 20:07:35 -05:00
7497ee454c feat(rfid): added in manual trigger for rfid reader at the wrapper 2025-07-10 20:07:10 -05:00
c0ede8714c feat(readers): added in good and bad reads to monitor eff 2025-07-10 20:06:31 -05:00
1a6a05112b fix(db): lastRead column was named incorrectly 2025-07-10 20:06:05 -05:00
97c6631eab ci(release): bump build number to 453 2025-07-10 20:04:31 -05:00
1ae506939c ci(release): bump build number to 452 2025-07-10 19:56:21 -05:00
f0294942a7 ci(release): bump build number to 451 2025-07-10 14:42:37 -05:00
e323607b39 ci(release): bump build number to 450 2025-07-10 14:32:25 -05:00
df0851414e ci(release): bump build number to 449 2025-07-10 14:13:05 -05:00
a9b860a34d ci(release): bump build number to 448 2025-07-10 14:06:37 -05:00
ead35b4360 ci(release): bump build number to 447 2025-07-10 13:52:06 -05:00
d6b1a75afa ci(release): bump build number to 446 2025-07-10 12:25:17 -05:00
1b661a6685 ci(release): bump build number to 445 2025-07-10 12:16:58 -05:00
f597142ee3 ci(release): bump build number to 444 2025-07-10 08:04:44 -05:00
18780d872c ci(release): bump build number to 443 2025-07-10 07:25:23 -05:00
ba02ee42c5 ci(release): bump build number to 442 2025-07-10 07:14:56 -05:00
f573f4f721 ci(release): bump build number to 441 2025-07-10 07:13:51 -05:00
1d6bf7215b ci(release): bump build number to 440 2025-07-09 20:15:37 -05:00
e616574fa6 ci(release): bump build number to 439 2025-07-09 18:24:44 -05:00
22 changed files with 4532 additions and 23 deletions

View File

@@ -0,0 +1 @@
ALTER TABLE "rfidTags" RENAME COLUMN "timeStamp" TO "lastRead";

View File

@@ -0,0 +1,2 @@
ALTER TABLE "rfidReaders" ADD COLUMN "goodReads" integer DEFAULT 0;--> statement-breakpoint
ALTER TABLE "rfidReaders" ADD COLUMN "badReads" integer DEFAULT 0;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -477,6 +477,20 @@
"when": 1749744049457,
"tag": "0067_shallow_trish_tilby",
"breakpoints": true
},
{
"idx": 68,
"version": "7",
"when": 1752195741709,
"tag": "0068_last_caretaker",
"breakpoints": true
},
{
"idx": 69,
"version": "7",
"when": 1752195894698,
"tag": "0069_chemical_maximus",
"breakpoints": true
}
]
}

View File

@@ -8,6 +8,7 @@ import {
uuid,
uniqueIndex,
jsonb,
integer,
} from "drizzle-orm/pg-core";
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
import { z } from "zod";
@@ -23,6 +24,8 @@ export const rfidReaders = pgTable(
lastTriggerGood: boolean("lastTiggerGood").default(true),
active: boolean("active").default(true),
lastTagScanned: text("lastTagScanned"),
goodReads: integer("goodReads").default(0),
badReads: integer("badReads").default(0),
},
(table) => [
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),

View File

@@ -16,7 +16,7 @@ export const rfidTags = pgTable(
rfidTag_id: uuid("rfidTag_id").defaultRandom().primaryKey(),
tagHex: text("tagHex"),
tag: text("tag"),
lastRead: timestamp("timeStamp").defaultNow(),
lastRead: timestamp("lastRead").defaultNow(), // cahnge this and hope we dont loose the data.
counts: jsonb("counts").default([]), // example [{area: Line3.2, count: 1}, {area: line3.1, count: 6}]
lastareaIn: text("lastareaIn").notNull(),
runningNumber: integer("runningNumber"),

View File

@@ -0,0 +1,31 @@
import { Button } from "@/components/ui/button";
import axios from "axios";
import { toast } from "sonner";
export default function ManualTrigger() {
const rfidReaderTrigger = async () => {
try {
const res = await axios.post("/api/rfid/manualtrigger/wrapper1");
if (res.data.success) {
toast.success(res.data.message);
return;
}
if (!res.data.success) {
toast.error(res.data.message);
}
} catch (error) {
console.log(error);
//stoast.success(error.data.message);
}
};
return (
<div>
<Button onClick={rfidReaderTrigger}>Wrapper 1 RFID</Button>
</div>
);
}

View File

@@ -16,8 +16,7 @@ import { getOcmeInfo } from "@/utils/querys/production/getOcmeInfo";
import { useQuery } from "@tanstack/react-query";
import { format } from "date-fns";
import { Trash } from "lucide-react";
import ManuallyEnterRn from "./ManuallyEnterRn";
import { Separator } from "../ui/separator";
import ManualTrigger from "../logistics/rfid/ManualTrigger";
const currentPallets = [
{ key: "line", label: "Line" },
@@ -160,11 +159,12 @@ export default function WrapperManualTrigger() {
<div>
<hr />
<p className="text-center mb-3">Manual Trigger</p>
{/* <p className="text-center mb-3">Manual Trigger</p>
<ManuallyEnterRn />
<Separator className="m-1" />
<div className="flex flex-row justify-between">
<Separator className="m-1" /> */}
<div className="flex flex-row justify-between m-2">
<Button onClick={cameraTrigger}>Camera</Button>
<ManualTrigger />
</div>
</div>
</LstCard>

View File

@@ -64,18 +64,32 @@ export default function OCPPage() {
</ResizablePanelGroup>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={25}>
<ResizablePanel className="min-h-[200px] min-w-[200px] max-w-[450px]">
<ResizablePanelGroup
direction="vertical"
autoSaveId="ocpPage"
autoSaveId="ocpPage_vert"
>
{server[0].value === "usday1vms006" && (
<ResizablePanel className="max-h-[300px]">
<ResizablePanel
style={{
overflow: "auto",
scrollbarWidth: "none",
}}
defaultSize={50}
className="min-h-[200px]"
>
<WrapperManualTrigger />
</ResizablePanel>
)}
{server[0]?.value === "localhost" && (
<ResizablePanel className="max-h-[300px]">
<ResizablePanel
className="min-h-[200px]"
style={{
overflow: "auto",
scrollbarWidth: "none",
}}
defaultSize={50}
>
<WrapperManualTrigger />
</ResizablePanel>
)}

View File

@@ -36,7 +36,7 @@
}
},
"admConfig": {
"build": 438,
"build": 453,
"oldBuild": "backend-0.1.3.zip"
},
"devDependencies": {

View File

@@ -1,11 +1,34 @@
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../logger/logger.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import { machineCheck } from "../../../sqlServer/querys/ocp/machineId.js";
import { mmQuery } from "../../../sqlServer/querys/ocp/mainMaterial.js";
export const isMainMatStaged = async (lot: any) => {
// make staged false by deefault and error logged if theres an issue
let isStaged = false;
const { data, error } = (await tryCatch(
query(
machineCheck.replace("where Active = 1 and [Location] = [loc]", ""),
"check machine needs mm"
)
)) as any;
const machine = data.data.filter(
(m: any) => m.HumanReadableId === lot.machineID
);
// we have a check on ksc side to ignore the tetra machine for now as its not updating in 2.0
if (!machine.StagingMainMaterialMandatory) {
createLog(
"info",
"mainMaterial",
"ocp",
`The machine dose not require mm to print and book in.`
);
return true;
}
// strangly the lot is not always sending over in slc so adding this in for now to see what line is cauing this issue
if (!lot) {
return isStaged;

View File

@@ -107,7 +107,7 @@ export const labelerTagRead = async (tagData: any) => {
// trigger the reader so we can get the label from the tag readers.
setTimeout(async () => {
await readTags("wrapper1");
}, 2 * 1000);
}, 500); // half second delay on this guy
}
}
};

View File

@@ -49,6 +49,8 @@ export const palletSendTag = async (tagData: any) => {
Date.now() - tagTime <= 5000 &&
!tagData.value
) {
await pickedup({ runningNr: 1234, all: true, areaFrom: "wrapper_1" });
setTimeout(() => {
pickedup({ runningNr: 1234, all: true, areaFrom: "wrapper_1" });
}, 5000);
}
};

View File

@@ -8,7 +8,22 @@ export const noRead = async (reader: string) => {
createLog(
"error",
"rfid",
"rifd",
"rfid",
`${reader} just had a no read please check for a tag and manually trigger a read.`
);
};
// noReadTimer.js
let timeout: any = null;
export const startNoReadTimer = (onTimeout: any, ms = 10000) => {
clearNoReadTimer(); // Always clear any previous timer
timeout = setTimeout(onTimeout, ms);
};
export const clearNoReadTimer = () => {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
};

View File

@@ -3,6 +3,8 @@ import { createLog } from "../../logger/logger.js";
import { db } from "../../../../database/dbclient.js";
import { rfidReaders } from "../../../../database/schema/rfidReaders.js";
import { eq } from "drizzle-orm";
import { noRead, startNoReadTimer } from "./noRead.js";
import { badRead } from "./readerControl.js";
const authData = btoa("admin:Zebra123!");
let token: string;
@@ -63,6 +65,11 @@ const startRead = async (reader: string, ip: string) => {
//console.log(res.data);
if (res.status === 200) {
// start the no read timer
startNoReadTimer(() => {
noRead(reader);
badRead(reader);
});
setTimeout(() => {
stopRead(reader, ip);
}, 5 * 1000);

View File

@@ -48,7 +48,11 @@ export const badRead = async (reader: string) => {
try {
const badRead = await db
.update(rfidReaders)
.set({ lastTrigger: sql`NOW()`, lastTriggerGood: false })
.set({
lastTrigger: sql`NOW()`,
lastTriggerGood: false,
lastTagScanned: null,
})
.where(eq(rfidReaders.reader, reader));
createLog(
"info",

View File

@@ -11,12 +11,15 @@ 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";
import { and, eq, gte, ne, sql } from "drizzle-orm";
import { rfidReaders } from "../../../../../database/schema/rfidReaders.js";
import { shouldSkipByCooldown } from "../../utils/rateLimit.js";
export const wrapperStuff = async (tagData: any) => {
console.log("WrapperTag", tagData[0].tag);
if (shouldSkipByCooldown("wrapperDouble Scan", 10)) return;
// update the reader with the last tag read.
const { error } = await tryCatch(
db
.update(rfidReaders)
@@ -53,8 +56,21 @@ export const wrapperStuff = async (tagData: any) => {
monitorChecks();
}
const { data: tagdata, error: tagError } = await tryCatch(
db.select().from(rfidTags).where(eq(rfidTags.tag, tagData[0].tag))
db
.select()
.from(rfidTags)
.where(
and(
eq(rfidTags.tag, tagData[0].tag),
gte(
rfidTags.lastRead,
sql.raw(`NOW() - INTERVAL '6 hours'`)
),
ne(rfidTags.lastareaIn, "wrapper1")
)
)
);
console.log("DB Data:", tagdata);
if (tagError) {
return {
success: false,
@@ -136,10 +152,12 @@ export const wrapperStuff = async (tagData: any) => {
const genlabel = await labelingProcess({
line: lineNum.toString(),
});
console.log(genlabel);
if (genlabel?.success) {
const createPrintData = {
...tagData[0],
runnungNr: parseInt(genlabel.data?.SSCC.slice(10, -1)),
runnungNumber: parseInt(genlabel.data?.SSCC.slice(10, -1)),
};
tagStuff([createPrintData]);

View File

@@ -9,6 +9,7 @@ export type TagData = {
antenna: number;
tagStrength: number;
lastareaIn?: string;
runningNumber?: number;
};
export const tagData = async (data: TagData[]) => {
/**

View File

@@ -26,6 +26,9 @@ export const tagStuff = async (tagData: TagData[]): Promise<any> => {
lastareaIn: tagData[i].reader,
antenna: tagData[i].antenna,
tagStrength: tagData[i].tagStrength,
runningNumber: tagData[i].runningNumber
? tagData[i].runningNumber
: null,
};
try {
// insert the tag with the onConflict update the tag

View File

@@ -3,7 +3,7 @@ import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
import { ConsoleLogWriter } from "drizzle-orm";
import { tagData } from "../controller/tagData.js";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import { noRead } from "../controller/noRead.js";
import { clearNoReadTimer, noRead } from "../controller/noRead.js";
import { badRead, goodRead } from "../controller/readerControl.js";
import { createLog } from "../../logger/logger.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
@@ -51,10 +51,15 @@ app.openapi(
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));
// console.log(
// "Raw value:",
// body[i].data.peakRssi,
// "Parsed:",
// parseInt(body[i].data.peakRssi)
// );
if (
tag.includes("ALPLA") &&
parseInt(body[i].data.peakRssi) < -40
parseInt(body[i].data.peakRssi) < -30
) {
tagdata = [
...tagdata,
@@ -71,8 +76,8 @@ app.openapi(
}
if (tagdata.length === 0) {
noRead(reader);
badRead(reader);
// noRead(reader);
// badRead(reader);
return c.json(
{ success: false, message: `There were no tags scanned.` },
200
@@ -80,6 +85,7 @@ app.openapi(
} else {
tagData(tagdata);
goodRead(reader);
clearNoReadTimer();
return c.json(
{ success: true, message: `New info from ${reader}` },

View File

@@ -0,0 +1,19 @@
const lastRunMap = new Map();
/**
* Returns true if the function with a given key was called within the last `seconds`.
* @param {string} key - Unique key to track cooldown per function/context.
* @param {number} seconds - Cooldown in seconds.
* @returns {boolean} - true if should skip (still in cooldown), false if allowed.
*/
export function shouldSkipByCooldown(key: any, seconds: any) {
const now = Date.now();
const cooldown = seconds * 1000;
if (lastRunMap.has(key) && now - lastRunMap.get(key) < cooldown) {
return true;
}
lastRunMap.set(key, now);
return false;
}