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 (Translated to Korean) */ static getStatusDescription(status: number): string { switch (status) { case 0x00: return "성공"; case 0x01: return "인벤토리 완료 전 반환됨"; case 0x02: return "인벤토리 시간 초과"; case 0x03: return "추가 데이터 있음"; case 0x04: return "리더 메모리 가득 참"; case 0x05: return "액세스 비밀번호 오류"; case 0x09: return "태그 킬(Kill) 오류"; case 0x0A: return "킬(Kill) 비밀번호는 0일 수 없음"; case 0x0B: return "태그가 명령을 지원하지 않음"; case 0x0C: return "액세스 비밀번호는 0일 수 없음 (잠김)"; case 0x0D: return "태그가 보호되어 있어 다시 설정 불가"; case 0x0E: return "태그가 보호되지 않아 재설정 필요 없음"; case 0x10: return "잠긴 바이트 존재, 쓰기 실패"; case 0x11: return "태그를 잠글 수 없음"; case 0x12: return "이미 잠겨 있어 다시 잠글 수 없음"; case 0x13: return "파라미터 저장 실패"; case 0x14: return "전력을 조절할 수 없음"; case 0x15: return "인벤토리 완료 전 반환됨 (6B)"; case 0x16: return "인벤토리 시간 초과 (6B)"; case 0x17: return "추가 데이터 있음 (6B)"; case 0x18: return "리더 메모리 가득 참 (6B)"; case 0x19: return "명령 미지원 또는 액세스 비밀번호 오류"; case 0xF9: return "명령 실행 오류"; case 0xFA: return "통신 불량 / 태그 작동 불가"; case 0xFB: return "태그 없음 (감지 불가)"; case 0xFC: return "태그 오류 코드 반환"; // Check data for specific code case 0xFD: return "명령 길이 오류"; case 0xFE: return "잘못된 명령 / CRC 오류"; case 0xFF: return "파라미터 오류"; case 0x30: return "통신 오류"; default: return `알 수 없는 상태 (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 "기타 오류"; case 0x03: return "메모리 초과 또는 EPC 길이 미지원"; case 0x04: return "메모리 잠김"; case 0x0B: return "전력 부족"; case 0x0F: return "불특정 오류"; default: return `알 수 없는 태그 오류 (0x${errorCode.toString(16).toUpperCase().padStart(2, '0')})`; } } }