使用 WebUSB 从串行设备读取整个响应

Reading the entire response from a serial device using WebUSB

我一直在尝试通过 WebUSB 使用串行设备。我可以使用 transferIntransferOut 打开设备并 read/write 到它。由于 USB 设备不会一次发送所有数据,我编写了一个函数,发送命令然后通过递归调用 transferIn 读回结果:

/** Send command to a device, and get its response back.
 * @param {string} command
 * @param {USBDevice} device
 * @returns {Promise<string>}
 */
function sendCommand(command, device) {
    return new Promise(function (resolve, reject) {
        var pieces = [];
        device.transferOut(1, new TextEncoder().encode(command + '\n')).then(function readMore() {
            device.transferIn(1, 64).then(function (res) {
                if (res.status !== 'ok')
                    reject(new Error('Failed to read result: ' + res.status));
                else if (res.data.byteLength > 0) {
                    pieces.push(res.data);
                    readMore();
                } else
                    resolve(new TextDecoder().decode(join(pieces))); // join() concatenates an array of arraybuffers
            }).catch(reject);
        }).catch(reject);
    });
}

但是,这不起作用,因为 transferIn 在解析之前等待新数据可用。如何检查 USB 串行设备是否已完成发送响应?

WebUSB 不支持串口设备,但是目前正在为 Chrome 开发 Web Serial API 可以解锁此功能。

串口设备是流式数据源。你如何定义"done"什么时候设备可以随时发送更多数据?

如果您的设备在 "messages" 中发送数据,这是一个高级概念,您必须在串行层之上定义。也许您的设备根据终止字符(例如换行符或空字节)来定义消息。也许它在消息前面加上它的长度。也许它不做这些事情,唯一告诉它完成的方法是在定义的毫秒数内没有接收到新数据。

在 USB 中,一个常见的模式是设备使用正好是端点最大数据包大小的数据包来响应批量传输 IN 请求。如果收到小于该长度的数据包,则表示消息结束。这不适用于 USB 串行设备,因为串行通信没有数据包的概念,并且当接收到传输请求时,批量数据包中填充了 UART 缓冲区中的任何数据。