Compare commits
22 Commits
08109f500f
...
6a082d9737
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a082d9737 | |||
| 58711becf2 | |||
| f757085fc2 | |||
| 8f5e1cb094 | |||
| 7497ee454c | |||
| c0ede8714c | |||
| 1a6a05112b | |||
| 97c6631eab | |||
| 1ae506939c | |||
| f0294942a7 | |||
| e323607b39 | |||
| df0851414e | |||
| a9b860a34d | |||
| ead35b4360 | |||
| d6b1a75afa | |||
| 1b661a6685 | |||
| f597142ee3 | |||
| 18780d872c | |||
| ba02ee42c5 | |||
| f573f4f721 | |||
| 1d6bf7215b | |||
| e616574fa6 |
1
database/migrations/0068_last_caretaker.sql
Normal file
1
database/migrations/0068_last_caretaker.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "rfidTags" RENAME COLUMN "timeStamp" TO "lastRead";
|
||||||
2
database/migrations/0069_chemical_maximus.sql
Normal file
2
database/migrations/0069_chemical_maximus.sql
Normal 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;
|
||||||
2166
database/migrations/meta/0068_snapshot.json
Normal file
2166
database/migrations/meta/0068_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
2180
database/migrations/meta/0069_snapshot.json
Normal file
2180
database/migrations/meta/0069_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -477,6 +477,20 @@
|
|||||||
"when": 1749744049457,
|
"when": 1749744049457,
|
||||||
"tag": "0067_shallow_trish_tilby",
|
"tag": "0067_shallow_trish_tilby",
|
||||||
"breakpoints": true
|
"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
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
uuid,
|
uuid,
|
||||||
uniqueIndex,
|
uniqueIndex,
|
||||||
jsonb,
|
jsonb,
|
||||||
|
integer,
|
||||||
} from "drizzle-orm/pg-core";
|
} from "drizzle-orm/pg-core";
|
||||||
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
@@ -23,6 +24,8 @@ export const rfidReaders = pgTable(
|
|||||||
lastTriggerGood: boolean("lastTiggerGood").default(true),
|
lastTriggerGood: boolean("lastTiggerGood").default(true),
|
||||||
active: boolean("active").default(true),
|
active: boolean("active").default(true),
|
||||||
lastTagScanned: text("lastTagScanned"),
|
lastTagScanned: text("lastTagScanned"),
|
||||||
|
goodReads: integer("goodReads").default(0),
|
||||||
|
badReads: integer("badReads").default(0),
|
||||||
},
|
},
|
||||||
(table) => [
|
(table) => [
|
||||||
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
|
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const rfidTags = pgTable(
|
|||||||
rfidTag_id: uuid("rfidTag_id").defaultRandom().primaryKey(),
|
rfidTag_id: uuid("rfidTag_id").defaultRandom().primaryKey(),
|
||||||
tagHex: text("tagHex"),
|
tagHex: text("tagHex"),
|
||||||
tag: text("tag"),
|
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}]
|
counts: jsonb("counts").default([]), // example [{area: Line3.2, count: 1}, {area: line3.1, count: 6}]
|
||||||
lastareaIn: text("lastareaIn").notNull(),
|
lastareaIn: text("lastareaIn").notNull(),
|
||||||
runningNumber: integer("runningNumber"),
|
runningNumber: integer("runningNumber"),
|
||||||
|
|||||||
31
frontend/src/components/logistics/rfid/ManualTrigger.tsx
Normal file
31
frontend/src/components/logistics/rfid/ManualTrigger.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -16,8 +16,7 @@ import { getOcmeInfo } from "@/utils/querys/production/getOcmeInfo";
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import { Trash } from "lucide-react";
|
import { Trash } from "lucide-react";
|
||||||
import ManuallyEnterRn from "./ManuallyEnterRn";
|
import ManualTrigger from "../logistics/rfid/ManualTrigger";
|
||||||
import { Separator } from "../ui/separator";
|
|
||||||
|
|
||||||
const currentPallets = [
|
const currentPallets = [
|
||||||
{ key: "line", label: "Line" },
|
{ key: "line", label: "Line" },
|
||||||
@@ -160,11 +159,12 @@ export default function WrapperManualTrigger() {
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<hr />
|
<hr />
|
||||||
<p className="text-center mb-3">Manual Trigger</p>
|
{/* <p className="text-center mb-3">Manual Trigger</p>
|
||||||
<ManuallyEnterRn />
|
<ManuallyEnterRn />
|
||||||
<Separator className="m-1" />
|
<Separator className="m-1" /> */}
|
||||||
<div className="flex flex-row justify-between">
|
<div className="flex flex-row justify-between m-2">
|
||||||
<Button onClick={cameraTrigger}>Camera</Button>
|
<Button onClick={cameraTrigger}>Camera</Button>
|
||||||
|
<ManualTrigger />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</LstCard>
|
</LstCard>
|
||||||
|
|||||||
@@ -64,18 +64,32 @@ export default function OCPPage() {
|
|||||||
</ResizablePanelGroup>
|
</ResizablePanelGroup>
|
||||||
</ResizablePanel>
|
</ResizablePanel>
|
||||||
<ResizableHandle />
|
<ResizableHandle />
|
||||||
<ResizablePanel defaultSize={25}>
|
<ResizablePanel className="min-h-[200px] min-w-[200px] max-w-[450px]">
|
||||||
<ResizablePanelGroup
|
<ResizablePanelGroup
|
||||||
direction="vertical"
|
direction="vertical"
|
||||||
autoSaveId="ocpPage"
|
autoSaveId="ocpPage_vert"
|
||||||
>
|
>
|
||||||
{server[0].value === "usday1vms006" && (
|
{server[0].value === "usday1vms006" && (
|
||||||
<ResizablePanel className="max-h-[300px]">
|
<ResizablePanel
|
||||||
|
style={{
|
||||||
|
overflow: "auto",
|
||||||
|
scrollbarWidth: "none",
|
||||||
|
}}
|
||||||
|
defaultSize={50}
|
||||||
|
className="min-h-[200px]"
|
||||||
|
>
|
||||||
<WrapperManualTrigger />
|
<WrapperManualTrigger />
|
||||||
</ResizablePanel>
|
</ResizablePanel>
|
||||||
)}
|
)}
|
||||||
{server[0]?.value === "localhost" && (
|
{server[0]?.value === "localhost" && (
|
||||||
<ResizablePanel className="max-h-[300px]">
|
<ResizablePanel
|
||||||
|
className="min-h-[200px]"
|
||||||
|
style={{
|
||||||
|
overflow: "auto",
|
||||||
|
scrollbarWidth: "none",
|
||||||
|
}}
|
||||||
|
defaultSize={50}
|
||||||
|
>
|
||||||
<WrapperManualTrigger />
|
<WrapperManualTrigger />
|
||||||
</ResizablePanel>
|
</ResizablePanel>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"admConfig": {
|
"admConfig": {
|
||||||
"build": 438,
|
"build": 453,
|
||||||
"oldBuild": "backend-0.1.3.zip"
|
"oldBuild": "backend-0.1.3.zip"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,11 +1,34 @@
|
|||||||
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
import { createLog } from "../../../logger/logger.js";
|
import { createLog } from "../../../logger/logger.js";
|
||||||
import { query } from "../../../sqlServer/prodSqlServer.js";
|
import { query } from "../../../sqlServer/prodSqlServer.js";
|
||||||
|
import { machineCheck } from "../../../sqlServer/querys/ocp/machineId.js";
|
||||||
import { mmQuery } from "../../../sqlServer/querys/ocp/mainMaterial.js";
|
import { mmQuery } from "../../../sqlServer/querys/ocp/mainMaterial.js";
|
||||||
|
|
||||||
export const isMainMatStaged = async (lot: any) => {
|
export const isMainMatStaged = async (lot: any) => {
|
||||||
// make staged false by deefault and error logged if theres an issue
|
// make staged false by deefault and error logged if theres an issue
|
||||||
let isStaged = false;
|
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
|
// 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) {
|
if (!lot) {
|
||||||
return isStaged;
|
return isStaged;
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ export const labelerTagRead = async (tagData: any) => {
|
|||||||
// trigger the reader so we can get the label from the tag readers.
|
// trigger the reader so we can get the label from the tag readers.
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
await readTags("wrapper1");
|
await readTags("wrapper1");
|
||||||
}, 2 * 1000);
|
}, 500); // half second delay on this guy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ export const palletSendTag = async (tagData: any) => {
|
|||||||
Date.now() - tagTime <= 5000 &&
|
Date.now() - tagTime <= 5000 &&
|
||||||
!tagData.value
|
!tagData.value
|
||||||
) {
|
) {
|
||||||
await pickedup({ runningNr: 1234, all: true, areaFrom: "wrapper_1" });
|
setTimeout(() => {
|
||||||
|
pickedup({ runningNr: 1234, all: true, areaFrom: "wrapper_1" });
|
||||||
|
}, 5000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,7 +8,22 @@ export const noRead = async (reader: string) => {
|
|||||||
createLog(
|
createLog(
|
||||||
"error",
|
"error",
|
||||||
"rfid",
|
"rfid",
|
||||||
"rifd",
|
"rfid",
|
||||||
`${reader} just had a no read please check for a tag and manually trigger a read.`
|
`${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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import { createLog } from "../../logger/logger.js";
|
|||||||
import { db } from "../../../../database/dbclient.js";
|
import { db } from "../../../../database/dbclient.js";
|
||||||
import { rfidReaders } from "../../../../database/schema/rfidReaders.js";
|
import { rfidReaders } from "../../../../database/schema/rfidReaders.js";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
|
import { noRead, startNoReadTimer } from "./noRead.js";
|
||||||
|
import { badRead } from "./readerControl.js";
|
||||||
|
|
||||||
const authData = btoa("admin:Zebra123!");
|
const authData = btoa("admin:Zebra123!");
|
||||||
let token: string;
|
let token: string;
|
||||||
@@ -63,6 +65,11 @@ const startRead = async (reader: string, ip: string) => {
|
|||||||
//console.log(res.data);
|
//console.log(res.data);
|
||||||
|
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
|
// start the no read timer
|
||||||
|
startNoReadTimer(() => {
|
||||||
|
noRead(reader);
|
||||||
|
badRead(reader);
|
||||||
|
});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
stopRead(reader, ip);
|
stopRead(reader, ip);
|
||||||
}, 5 * 1000);
|
}, 5 * 1000);
|
||||||
|
|||||||
@@ -48,7 +48,11 @@ export const badRead = async (reader: string) => {
|
|||||||
try {
|
try {
|
||||||
const badRead = await db
|
const badRead = await db
|
||||||
.update(rfidReaders)
|
.update(rfidReaders)
|
||||||
.set({ lastTrigger: sql`NOW()`, lastTriggerGood: false })
|
.set({
|
||||||
|
lastTrigger: sql`NOW()`,
|
||||||
|
lastTriggerGood: false,
|
||||||
|
lastTagScanned: null,
|
||||||
|
})
|
||||||
.where(eq(rfidReaders.reader, reader));
|
.where(eq(rfidReaders.reader, reader));
|
||||||
createLog(
|
createLog(
|
||||||
"info",
|
"info",
|
||||||
|
|||||||
@@ -11,12 +11,15 @@ import { sendEmail } from "../../../notifications/controller/sendMail.js";
|
|||||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
import { db } from "../../../../../database/dbclient.js";
|
import { db } from "../../../../../database/dbclient.js";
|
||||||
import { rfidTags } from "../../../../../database/schema/rfidTags.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 { rfidReaders } from "../../../../../database/schema/rfidReaders.js";
|
||||||
|
import { shouldSkipByCooldown } from "../../utils/rateLimit.js";
|
||||||
|
|
||||||
export const wrapperStuff = async (tagData: any) => {
|
export const wrapperStuff = async (tagData: any) => {
|
||||||
console.log("WrapperTag", tagData[0].tag);
|
console.log("WrapperTag", tagData[0].tag);
|
||||||
|
if (shouldSkipByCooldown("wrapperDouble Scan", 10)) return;
|
||||||
|
|
||||||
|
// update the reader with the last tag read.
|
||||||
const { error } = await tryCatch(
|
const { error } = await tryCatch(
|
||||||
db
|
db
|
||||||
.update(rfidReaders)
|
.update(rfidReaders)
|
||||||
@@ -53,8 +56,21 @@ export const wrapperStuff = async (tagData: any) => {
|
|||||||
monitorChecks();
|
monitorChecks();
|
||||||
}
|
}
|
||||||
const { data: tagdata, error: tagError } = await tryCatch(
|
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) {
|
if (tagError) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
@@ -136,10 +152,12 @@ export const wrapperStuff = async (tagData: any) => {
|
|||||||
const genlabel = await labelingProcess({
|
const genlabel = await labelingProcess({
|
||||||
line: lineNum.toString(),
|
line: lineNum.toString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(genlabel);
|
||||||
if (genlabel?.success) {
|
if (genlabel?.success) {
|
||||||
const createPrintData = {
|
const createPrintData = {
|
||||||
...tagData[0],
|
...tagData[0],
|
||||||
runnungNr: parseInt(genlabel.data?.SSCC.slice(10, -1)),
|
runnungNumber: parseInt(genlabel.data?.SSCC.slice(10, -1)),
|
||||||
};
|
};
|
||||||
|
|
||||||
tagStuff([createPrintData]);
|
tagStuff([createPrintData]);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export type TagData = {
|
|||||||
antenna: number;
|
antenna: number;
|
||||||
tagStrength: number;
|
tagStrength: number;
|
||||||
lastareaIn?: string;
|
lastareaIn?: string;
|
||||||
|
runningNumber?: number;
|
||||||
};
|
};
|
||||||
export const tagData = async (data: TagData[]) => {
|
export const tagData = async (data: TagData[]) => {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ export const tagStuff = async (tagData: TagData[]): Promise<any> => {
|
|||||||
lastareaIn: tagData[i].reader,
|
lastareaIn: tagData[i].reader,
|
||||||
antenna: tagData[i].antenna,
|
antenna: tagData[i].antenna,
|
||||||
tagStrength: tagData[i].tagStrength,
|
tagStrength: tagData[i].tagStrength,
|
||||||
|
runningNumber: tagData[i].runningNumber
|
||||||
|
? tagData[i].runningNumber
|
||||||
|
: null,
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
// insert the tag with the onConflict update the tag
|
// insert the tag with the onConflict update the tag
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
|||||||
import { ConsoleLogWriter } from "drizzle-orm";
|
import { ConsoleLogWriter } from "drizzle-orm";
|
||||||
import { tagData } from "../controller/tagData.js";
|
import { tagData } from "../controller/tagData.js";
|
||||||
import { responses } from "../../../globalUtils/routeDefs/responses.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 { badRead, goodRead } from "../controller/readerControl.js";
|
||||||
import { createLog } from "../../logger/logger.js";
|
import { createLog } from "../../logger/logger.js";
|
||||||
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
@@ -51,10 +51,15 @@ app.openapi(
|
|||||||
const tag = Buffer.from(body[i].data.idHex, "hex").toString(
|
const tag = Buffer.from(body[i].data.idHex, "hex").toString(
|
||||||
"utf-8"
|
"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 (
|
if (
|
||||||
tag.includes("ALPLA") &&
|
tag.includes("ALPLA") &&
|
||||||
parseInt(body[i].data.peakRssi) < -40
|
parseInt(body[i].data.peakRssi) < -30
|
||||||
) {
|
) {
|
||||||
tagdata = [
|
tagdata = [
|
||||||
...tagdata,
|
...tagdata,
|
||||||
@@ -71,8 +76,8 @@ app.openapi(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tagdata.length === 0) {
|
if (tagdata.length === 0) {
|
||||||
noRead(reader);
|
// noRead(reader);
|
||||||
badRead(reader);
|
// badRead(reader);
|
||||||
return c.json(
|
return c.json(
|
||||||
{ success: false, message: `There were no tags scanned.` },
|
{ success: false, message: `There were no tags scanned.` },
|
||||||
200
|
200
|
||||||
@@ -80,6 +85,7 @@ app.openapi(
|
|||||||
} else {
|
} else {
|
||||||
tagData(tagdata);
|
tagData(tagdata);
|
||||||
goodRead(reader);
|
goodRead(reader);
|
||||||
|
clearNoReadTimer();
|
||||||
|
|
||||||
return c.json(
|
return c.json(
|
||||||
{ success: true, message: `New info from ${reader}` },
|
{ success: true, message: `New info from ${reader}` },
|
||||||
|
|||||||
19
server/services/rfid/utils/rateLimit.ts
Normal file
19
server/services/rfid/utils/rateLimit.ts
Normal 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user