// src/lib/serial/serial.service.ts // Web Serial API implementation // Requires: @types/w3c-web-serial /** * 内部IO资源 */ let reader: ReadableStreamDefaultReader | null = null; let writer: WritableStreamDefaultWriter | null = null; let isOpen = false; /** * 判断当前环境是否支持Web Serial API */ export function isWebSerialSupported(): boolean { return typeof navigator !== 'undefined' && 'serial' in navigator; } /** * 请求用户选择串口设备 */ export async function requestPort( filters?: SerialPortRequestOptions['filters'] ): Promise { if (!isWebSerialSupported()) { throw new Error('Web Serial API is not supported in this environment.'); } const port = await navigator.serial.requestPort( filters ? { filters } : undefined ); return port ?? null; } /** * 打开串口 */ export async function openPort( port: SerialPort, options: SerialOptions ): Promise { if (isOpen) { // 串口已经打开,直接返回 return; } await port.open(options); isOpen = true; // 初始化reader和writer reader = port.readable?.getReader() ?? null; writer = port.writable?.getWriter() ?? null; } /** * 关闭串口 */ export async function closePort(port: SerialPort) { if (!isOpen) { // 串口未打开,直接返回 return; } await reader?.cancel(); reader?.releaseLock(); await writer?.close(); writer?.releaseLock(); reader = null; writer = null; isOpen = false; await port.close(); } /** * 向串口写入数据 */ export async function write(data: Uint8Array): Promise { if (!writer) { throw new Error('Serial port is not writable.'); } await writer.write(data); } /** * 开始读取串口数据循环 */ export async function startReadLoop( onData: (chunk: Uint8Array) => void, onError?: (err: unknown) => void ): Promise { if (!reader) { throw new Error('Serial port is not readable.'); } try { while (true) { const { value, done } = await reader.read(); if (done) break; if (value) onData(value); } } catch (err) { onError?.(err); } }