Files
RFID/services/rfidService.ts
2026-01-23 11:41:59 +09:00

73 lines
3.1 KiB
TypeScript

import { ReaderCommand } from '../types';
import { calculateCRC16, getCRCBytes } from '../utils/crc16';
export class RfidProtocol {
/**
* Constructs a command frame: [Len, Adr, Cmd, Data..., CRC_LSB, CRC_MSB]
*/
static buildCommand(address: number, cmd: ReaderCommand, data: number[] = []): Uint8Array {
const len = data.length + 4; // Len byte itself is not included in length value logic usually, but manual says: "Len equals length of Data[] plus 4"
// Frame except CRC
const frameHeader = [len, address, cmd, ...data];
// Calculate CRC on [Len, Adr, Cmd, Data...]
const crc = calculateCRC16(new Uint8Array(frameHeader));
const [lsb, msb] = getCRCBytes(crc);
return new Uint8Array([...frameHeader, lsb, msb]);
}
/**
* Helper to interpret status codes from the reader
*/
static getStatusDescription(status: number): string {
switch (status) {
case 0x00: return "Success";
case 0x01: return "Return before Inventory finished";
case 0x02: return "Inventory Timeout";
case 0x03: return "More data follows";
case 0x04: return "Reader memory full";
case 0x05: return "Access Password Error";
case 0x09: return "Kill Tag Error";
case 0x0A: return "Kill Password cannot be zero";
case 0x0B: return "Tag does not support command";
case 0x0C: return "Access Password cannot be zero (Locked)";
case 0x0D: return "Tag is protected, cannot set again";
case 0x0E: return "Tag is unprotected, no need to reset";
case 0x10: return "Locked bytes, write fail";
case 0x11: return "Cannot lock tag";
case 0x12: return "Already locked, cannot lock again";
case 0x13: return "Save Parameter Failed";
case 0x14: return "Cannot adjust power";
case 0x15: return "Return before Inventory finished (6B)";
case 0x16: return "Inventory Timeout (6B)";
case 0x17: return "More data follows (6B)";
case 0x18: return "Reader memory full (6B)";
case 0x19: return "Not Support Command or Access Password Error";
case 0xF9: return "Command Execution Error";
case 0xFA: return "Poor Communication / Tag Inoperable";
case 0xFB: return "No Tag Operable";
case 0xFC: return "Tag Returned Error Code"; // Check data for specific code
case 0xFD: return "Command Length Wrong";
case 0xFE: return "Illegal Command / CRC Error";
case 0xFF: return "Parameter Error";
case 0x30: return "Communication Error";
default: return `Unknown Status (0x${status.toString(16).toUpperCase().padStart(2, '0')})`;
}
}
/**
* Helper to interpret EPC C1G2 Tag specific error codes (Status 0xFC)
*/
static getTagErrorDescription(errorCode: number): string {
switch (errorCode) {
case 0x00: return "Other error";
case 0x03: return "Memory overrun or EPC length not supported";
case 0x04: return "Memory locked";
case 0x0B: return "Insufficient power";
case 0x0F: return "Non-specific error";
default: return `Unknown Tag Error (0x${errorCode.toString(16).toUpperCase().padStart(2, '0')})`;
}
}
}