心相随

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

chromium内核89版本以上的浏览才支持

域名或IP访问时需要HTTPS,localhost没有限制

什么是web串行API

Web 串口 API 为网站提供了一种阅读和写入带有 JavaScript 的串行设备的方法。串行设备通过用户系统上的串行端口或仿效串行端口的可移动 USB 和蓝牙设备连接。

换句话说,Web 串行 API 允许网站与串行设备(如微控制器和 3D 打印机)通信,从而将 Web 和物理世界连接在一起。

使用网络串行 API

功能检测

检查客户端浏览器是否支持 Web 串行 API

if ("serial" in navigator) {
  // The Web Serial API is supported.
}
打开串行端口

网络串行 API 按设计是异步的,这可以防止Web UI 在等待输入时造成阻塞。

// 提示用户选择一个串口
const port = await navigator.serial.requestPort();
// 获取用户之前授予网站访问权限的所有串口.
const ports = await navigator.serial.getPorts();
// 通过硬件设备的Arduino Uno USB Vendor/Product IDs等参数筛选串口
const filters = [
  { usbVendorId: 0x2341, usbProductId: 0x0043 },
  { usbVendorId: 0x2341, usbProductId: 0x0001 }
];

// Prompt user to select an Arduino Uno device.
const port = await navigator.serial.requestPort({ filters });
打开串口
// Wait for the serial port to open.
await port.open({ baudRate: 9600 });

在打开串行端口时,您还可以指定以下任何选项。这些选项是可选的,具有方便的默认值。

baudRate:波特率

dataBits:数据位(7 或 8)

stopBits:停止位(1 或 2)

parity:校验位"none"、"even"、"odd"

bufferSize:读写缓冲区大小(必须小于 16MB)

flowControl:流量控制模式(或)。"none"、"hardware"

读取串口数据
let port, reader, inputDone;
// 文本简析流
const decoder = new TextDecoderStream();
// 添加管道
inputDone = port.readable.pipeTo(decoder.writable);
// 添加转换器
reader = decoder.readable.pipeThrough(new TransformStream(new LineBreakTransformer())).getReader();

while (true) {
    const { value, done } = await reader.read();
    if (value) {
        // do somethings
    }
    
    if (done) {//串口关闭
        reader.releaseLock();
        break;
    }
}

lineBreakTransformer.js

// 将原本可能截断成多个字符串的内容按顺序合并一个字符串
class LineBreakTransformer {
    constructor() {
        // 保存流数据直到新行出现的容器
        this.container = "";
    }

    transform(chunk, controller) {
        // 将新块追加到现有块。
        this.container += chunk;
        // 对于每一行分段,将解析后的行发送出去。
        const lines = this.container.split("\r");
        this.container = lines.pop();
        lines.forEach((line) => controller.enqueue(line));
    }

    flush(controller) {
        // 当流关闭时,清除所有剩余的块。
        controller.enqueue(this.container);
    }
}
关闭串口
if (reader && port && inputDone) {
    await reader.cancel();
    await inputDone.catch(() => { });
    reader = null;
    inputDone = null;
    await port.close();
    port = null;
}

实际应用(由于没有设备,以下代码未经测试)

封装

//serial-reader.js
export default class SerialReader {
    port;//串口
    reader;//读取
    inputDone;

    constructor() {
        if (!("serial" in navigator)) {
            console.error('当前浏览器不支持串口');
            return;
        }
        this.filtersSweep = [{ usbVendorId: 0x1A86, usbProductId: 0x7523 }];///串口识别码-扫码机
    }

    //初始化扫码机
    initSweepPrinter = async () => {
        let requestOptions = { filters: this.filtersSweep };
        this.port = await navigator.serial.requestPort(requestOptions);
        await this.port.open({
            baudRate: 115200
        });
        const decoder = new TextDecoderStream();
	this.inputDone = this.port.readable.pipeTo(decoder.writable);
	this.reader = decoder.readable.pipeThrough(new TransformStream(new LineBreakTransformer())).getReader();
	//alert('连接扫码机成功');
        return new Promise(async (resolve, reject) => {            
            while (true) {
                const { value, done } = await this.reader.read();
                if (value) {
                    //console.log('扫码机数据 = ', value);
                    resolve(value);
                }
                if (done) {
                    this.reader.releaseLock();
                    break;
                }
            }
        });
    }

    //断开扫码机
    disconnect = async () => {
        return new Promise(async (resolve, reject) => {
            if (this.reader && this.port && this.inputDone) {
                await this.reader.cancel();
                await this.inputDone.catch(() => { });
                this.reader = null;
                this.inputDone = null;
                await this.port.close();
                this.port = null;
                resolve();
            }
        })
    }
}

调用

import SerialReader from '../serial-reader.js';
let serialReader = new SerialReader ();
//初始化扫码机
const initSweep = async () => {
    try {
        await serialReader.initSweepPrinter().then(value=>{console.log(value)});			
    } catch (e) {
        console.error('扫码机读取失败', e);
    }
}

//断开
function(){
    serialReader.disconnect().then(() => {
        alert(`断开读卡器成功`);
    });
}						

参考

https://web.dev/serial/
https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API

posted on 2022-11-17 06:28  心相随  阅读(2499)  评论(0编辑  收藏  举报