串口是非常常用的一种电脑与设备交互的接口。目前在浏览器上直接使用电脑上的串口设备了,这篇文章将介绍相关内容。
Web Serial API 相关内容参考如下:
https://developer.mozilla.org/en-US/docs/Web/API/Serial
https://developer.mozilla.org/en-US/docs/Web/API/SerialPort
https://wicg.github.io/serial/
这个API目前还处于实验性质,只有电脑上的Chrome、Edge、Opera等浏览器支持:
另外还需要注意的是从网页操作设备是比较容易产生安全风险的,所以这个API只支持本地调用或者是HTTPS方式调用。
对于这个API谷歌有提供示例工程:
在线使用:https://googlechromelabs.github.io/serial-terminal/
项目地址:https://github.com/GoogleChromeLabs/serial-terminal
下面这个项目做的挺不错的,直接拿来用也很好:
在线使用:https://itldg.github.io/web-serial-debug/
项目地址:https://gitee.com/itldg/web-serial-debug or https://github.com/itldg/web-serial-debug

使用下面方法可以侦测电脑上串口设备插入与拔出:
// 全局串口设备插入事件 navigator.serial.onconnect = (event) => { console.log("Serial connected: ", event.target); }; // 全局串口设备拔出事件 navigator.serial.ondisconnect = (event) => { console.log("Serial disconnected: ", event.target); }; // 也可以对单个的串口设备设置插入与拔出事件 使用下面方法可以显示电脑上的串口设备选择授权,或者显示已授权的串口设备列表:
// requestPort方法将显示一个包含已连接设备列表的对话框,用户选择可以并授予其中一个设备访问权限 // 对于USB虚拟串口而言该方法还可以传入一个过滤器,指定PID&VID的串口 const port = await navigator.serial.requestPort(); // port.forget(); // 取消授权 // port.getInfo() // 获取PID&VID (对于蓝牙串口好像是显示服务号) // getDevices方法可以返回已连接的授权过的设备列表 const ports = await navigator.serial.getPorts(); 使用 open 方法打开选中的串口设备后就可以进行数据交互了:
// open时可以传入串口参数 await port.open({ baudRate: 115200, // bufferSize: 255, // 读写缓存,默认255 // dataBits: 8, // 数据位,默认8 // flowControl: none, // 流控制,默认无 // parity: none, // 校验,默认无 // stopBits: 1, // 停止位,默认1 }); 打开后就可以发送数据了:
const encoder = new TextEncoder(); // const data= new Uint8Array(length); const writer = port.writable.getWriter(); await writer.write(encoder.encode("PING")); // await writer.write(data); writer.releaseLock(); 同样可以设置数据接收:
while (port.readable) { const reader = port.readable.getReader(); try { while (true) { const { value, done } = await reader.read(); if (done) { // |reader| has been canceled. break; } // Do something with |value|… } } catch (error) { // Handle |error|… } finally { reader.releaseLock(); } } 数据接收本身很简单,但需要注意的是在关闭串口前需要释放 reader 对象。
下面是关闭串口操作:
// 使用 await port.close(); 即可关闭串口,如果正在读写数据,需要先释放相关资源 let keepReading = true; let reader; async function readUntilClosed() { while (port.readable && keepReading) { reader = port.readable.getReader(); try { while (true) { const { value, done } = await reader.read(); if (done) { // |reader| has been canceled. break; } // Do something with |value|... } } catch (error) { // Handle |error|... } finally { reader.releaseLock(); } } await port.close(); } const closed = readUntilClosed(); // Sometime later... keepReading = false; reader.cancel(); await closed; 除了上面内容外还可以使用 setSignals 和 getSignals 来设置和获取流控制情况。
Web Serial API Test
下面测试时我将串口的TX/RT短接在一起,发送什么数据就会收到什么数据:
使用 Web Serial API 访问串口非常方便,目前来说唯一的问题是这还是实验性质的功能,可能之后接口还会变动,需要根据实际情况进行调整。