🧭 目录
- Web Serial API 简介
- 浏览器支持情况
- 串口通讯的典型流程
- 实战:发送和接收串口数据(纯前端)
- 示例代码解析
- 常见问题与注意事项
- 参考资料
1️⃣ Web Serial API 简介
Web Serial API 是一种浏览器原生 API,允许网页通过串口与设备进行通信,核心对象包括:
navigator.serial
:访问串口权限SerialPort
:表示一个串口连接ReadableStream
/WritableStream
:读写数据流
⚠️ 需 HTTPS 或 localhost 环境才能使用。
2️⃣ 浏览器支持情况
浏览器 | 是否支持 Web Serial API |
---|---|
✅ Chrome (v89+) | ✔️ 全面支持 |
✅ Edge (v89+) | ✔️ 支持 |
❌ Firefox | ❌ 不支持 |
❌ Safari | ❌ 不支持 |
3️⃣ 串口通讯的典型流程
- 用户点击按钮,浏览器弹出串口选择窗口
- 用户选择设备后建立连接
- 使用串口写入命令、读取设备返回
- 断开连接
4️⃣ 实战:发送和接收串口数据(纯前端)
✅ HTML 页面结构
<button id="connect">连接串口</button>
<button id="send">发送数据</button>
<textarea id="output" rows="10" cols="50" readonly></textarea>
✅ JavaScript 主逻辑
let port;
let reader;
let outputElem = document.getElementById("output");
document.getElementById("connect").addEventListener("click", async () => {
try {
// 选择串口
port = await navigator.serial.requestPort();
await port.open({ baudRate: 9600 }); // 根据设备配置波特率
// 启动读取循环
const decoder = new TextDecoderStream();
port.readable.pipeTo(decoder.writable);
reader = decoder.readable.getReader();
readLoop();
} catch (err) {
console.error("连接串口失败:", err);
}
});
document.getElementById("send").addEventListener("click", async () => {
if (!port || !port.writable) return;
const writer = port.writable.getWriter();
const data = "Hello Device!\n";
const encoder = new TextEncoder();
await writer.write(encoder.encode(data));
writer.releaseLock();
});
async function readLoop() {
while (true) {
const { value, done } = await reader.read();
if (done) {
reader.releaseLock();
break;
}
outputElem.value += value;
}
}
5️⃣ 示例说明
TextDecoderStream
:自动处理流数据为字符串requestPort()
:触发串口设备选择对话框readable / writable
:标准的 JS 流接口
你也可以自定义 baudRate
, dataBits
, stopBits
等配置:
await port.open({
baudRate: 115200,
dataBits: 8,
stopBits: 1,
parity: "none",
flowControl: "none",
});
6️⃣ 常见问题与注意事项
问题 | 说明 |
---|---|
浏览器提示未授权 | 必须用户主动触发 requestPort() (如点击按钮) |
串口返回乱码 | 确保 TextDecoderStream 和波特率与设备一致 |
多次连接导致设备忙或卡死 | 确保使用 port.close() 正确关闭连接 |
网页不是 HTTPS 无法运行 | 必须运行在 HTTPS 或 localhost 上 |
✅ 断开串口连接
if (port && port.readable) {
await reader.cancel();
await port.close();
}
发表回复