// serial.js const HEADER1 = 0xAA; const HEADER2 = 0x55; const BAUD_RATE = 1000000; const CMD_ID_REQUEST = 0x01; const CMD_FILE_LIST = 0x02; const CMD_LOAD_FILE = 0x03; const CMD_DELETE_FILE = 0x04; export class SerialManager { constructor() { this.port = null; this.writer = null; this.reader = null; } async connect() { this.port = await navigator.serial.requestPort(); await this.port.open({ baudRate: BAUD_RATE }); this.writer = this.port.writable.getWriter(); this.reader = this.port.readable.getReader(); } async send(commandCode, payload = []) { const length = payload.length; const lengthHigh = (length >> 8) & 0xFF; const lengthLow = length & 0xFF; let checksum = commandCode ^ lengthHigh ^ lengthLow; for (let byte of payload) { checksum ^= byte; } const message = [HEADER1, HEADER2, commandCode, lengthHigh, lengthLow, ...payload, checksum]; console.log(new Uint8Array(message)); await this.writer.write(new Uint8Array(message)); } async requestIDPacket() { console.log("Requesting ID packet"); await this.send(CMD_ID_REQUEST); } async requestFileList() { console.log("Requesting File List"); await this.send(CMD_FILE_LIST); } async requestFile(filename) { const encoder = new TextEncoder(); const payload = Array.from(encoder.encode(filename)); await this.send(CMD_LOAD_FILE, payload); // CMD_LOAD_FILE } startReading(onPacket) { const decoder = new TextDecoder(); let buffer = []; const processBuffer = () => { while (buffer.length >= 5) { if (buffer[0] !== HEADER1 || buffer[1] !== HEADER2) { buffer.shift(); // discard until headers align continue; } const command = buffer[2]; const length = (buffer[3] << 8) | buffer[4]; if (buffer.length < 5 + length) return; // wait for full payload const payload = buffer.slice(5, 5 + length); onPacket(command, payload); buffer = buffer.slice(5 + length); // remove processed packet } }; const loop = async () => { while (this.port.readable) { try { const { value, done } = await this.reader.read(); if (done) break; if (value) { buffer.push(...value); processBuffer(); } } catch (err) { console.error("Read error:", err); break; } } }; loop(); } async receive(timeoutMs = 1000) { const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Timeout waiting for response")), timeoutMs) ); const readPromise = this.reader.read(); try { const { value } = await Promise.race([readPromise, timeoutPromise]); return value; } catch (err) { console.error("Receive error:", err.message); return null; } } disconnect() { this.reader.releaseLock(); this.writer.releaseLock(); this.port.close(); } }