You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Web Serial API无法稳定读取全部数据,请求技术解决方案

Web Serial API 数据读取异常问题

使用Web Serial API时遇到数据读取异常:有时能完整读取数据,有时会中途停止,无法获取全部数据。希望实现releaseLock后总能读取全部数据,以下是读写代码:

async function writeSerial_BMSA() {
    try {
        writer = port.writable.getWriter();
        let commandframe = new Uint8Array([
            0x42,
            0x4D,
            0x53,
            0x41,
        ]);
        commandframe = NACTRAU_Send(commandframe);
        await writer.write(commandframe);
        log.innerHTML = commandframe;
        writer.releaseLock();
        write_times++;
    } catch (error) {
        log.innerHTML = error;
    }
}
async function readSerial_BMSA() {
    try {
        reader = port.readable.getReader();
        try {
            while (true) {
                const { value, done } = await reader.read();
                if (done) {
                    reader.releaseLock();
                    break;
                }
                if (value.length > 1) {
                    let FWV = "";
                    let U_len = value[2] - 4;
                    for (let i = 0; i < U_len; i++) {
                        value[i] = value[i + 6];
                        FWV += String.fromCharCode(value[i]);
                    }
                    read_times++;
                    break;
                }
            }
        } catch (error) {
            console.error(error);
            log.innerHTML = error;
        } finally {
            console.log(port.readable);
            reader.releaseLock();
        }
    } catch (error) {
        log.innerHTML = error;
    }
}

已尝试将处理代码放入if (done){}中,但未解决问题。

预期正确读取结果:

new Uint8Array([49, 48, 45, 48, 55, 45, 66, 44, 65, 117, 103, 32, 50, 55, 32, 50, 48, 50, 49, 32, 49, 56, 58, 52, 56, 58, 50, 53, 32, 44, 48, 50, 48, 55, 44, 56, 48, 50, 48, 44, 49, 48, 44, 48, 50, 44, 49, 48, 44, 48, 50, 74, 226])

错误读取结果示例:

new Uint8Array([49, 48, 45, 48, 55, 45, 66, 44, 65, 117, 103, 32, 50, 55, 32, 50, 48, 50, 49, 32, 49, 0, 0, 0, 0, 0, 0])

问题分析与修复方案

你的读取逻辑有两个核心问题:

  1. 单次读取后直接中断循环:Web Serial API的read()是分批返回数据的,设备不会一次性发送所有内容,当前代码读取到第一块数据就break,自然拿不到完整内容。
  2. 未按协议拼接完整数据:依赖单次读取的value[2]计算长度,若第一块数据不包含完整长度字段或后续数据未接收完,会导致长度计算错误,读取到无效的0填充数据。

修复后的代码会先拼接所有接收的数据,直到满足协议规定的完整条件再处理:

async function readSerial_BMSA() {
    try {
        const reader = port.readable.getReader();
        let receivedData = new Uint8Array();
        
        try {
            while (true) {
                const { value, done } = await reader.read();
                
                if (done) {
                    break;
                }
                
                // 拼接新接收的数据
                const temp = new Uint8Array(receivedData.length + value.length);
                temp.set(receivedData);
                temp.set(value, receivedData.length);
                receivedData = temp;
                
                // 根据协议判断是否接收完整:第3个字节(索引2)为总长度
                if (receivedData.length >= 3) {
                    const totalLength = receivedData[2];
                    if (receivedData.length >= totalLength) {
                        // 处理完整数据
                        let FWV = "";
                        const U_len = totalLength - 4;
                        for (let i = 0; i < U_len; i++) {
                            FWV += String.fromCharCode(receivedData[i + 6]);
                        }
                        read_times++;
                        break;
                    }
                }
            }
        } catch (error) {
            console.error(error);
            log.innerHTML = error;
        } finally {
            reader.releaseLock();
        }
    } catch (error) {
        log.innerHTML = error;
    }
}

额外优化建议

  • 改用局部变量:避免全局的reader/writer引发锁冲突,修复代码中已改为函数内局部变量。
  • 添加超时机制:防止设备无响应导致读取逻辑挂起,可在循环中加入超时判断,超时后终止读取并释放锁。
  • 数据完整性校验:根据设备协议添加CRC等校验逻辑,确保接收的数据未出错。

内容的提问来源于stack exchange,提问作者Vince

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 12:35:30