Web Serial API串口通信,实现web和electron扫码枪读取数据

文章目录

  • 前言
  • 一、Serial API是什么?
  • 二、API使用步骤
    • 1.navigator.serial.requestPort()
    • 2.port.open(options)
    • 3.reader.read()
    • 4.port.close()
    • 其他常见API:
    • 完整代码
  • 三、electron使用


前言

本文将讲述Web Serial API简单应用,以扫码枪为示例,通过代码实现web端读取扫码枪扫码内容。


一、Serial API是什么?

Serial API为浏览器提供的一些接口函数,能实现与USB串行端口的硬件设备进行通信。诸如扫码枪或者打印机等

二、API使用步骤

以扫码枪为例子实现读取扫码数据

1.navigator.serial.requestPort()

作用:弹窗让用户选择一个串行端口设备,类似授权

if ('serial' in navigator) {try {const port = (await navigator.serial.requestPort()) || null;console.log('选择串口设备成功');} catch (e) {console.log('选择串口设备失败');}} else {console.log('浏览器不支持serial API');}

在这里插入图片描述

2.port.open(options)

作用:打开并连接到指定串行端口

 await port.value.open({ baudRate: 9600 })

参数option属性:
baudRate:波特率,9600
dataBits:数据位,7或8
stopBits:停止位,1或2
parity:奇偶校验模式,默认none
flowControl:流控制类型,none或hardware

3.reader.read()

作用:读取流数据

返回2个字段value和done,value为读取的数据,类型为Uint8Array,需要通过其他方式转换为字符串
done为true表示没有正在接收数据或者串口已关闭,通过如下循环获取数据:

const reader = port.readable.getReader();
while (true) {const { value, done } = await reader.read();if (done) {// 允许稍后关闭串口reader.releaseLock();break;}//处理数据console.log(value);//数据Uint8Array类型
}

2.也可以利用 port.readable.pipeTo和TextDecoderStream实现数据解析为字符串

const textDecoder = new TextDecoderStream();
const readableStreamClosed = port.readable.pipeTo(textDecoder.writable);
const reader = textDecoder.readable.getReader();while (true) { const { value, done } = await reader.read(); if (done) { // 允许稍后关闭串口reader.releaseLock();break; } // 处理数据console.log(value);//数据String类型} } 

while循环读取数据不是一次性读取的,有可能是多次,需要拼接和判断是否读取结束,一般以"\n"结尾来判断。

二维码数据为{name:“张三”,age:20}通过测试三次获取到value数据如下:

console.log(value.includes('\r'),'value',value)

在这里插入图片描述
通过测试发现有时候一次性读完有时候分2次读完,不确定,但是读取完毕都是以"\r"结尾,所以我们可以以此为判断依据改进如下:

const textDecoder = new TextDecoderStream();
const readableStreamClosed = port.readable.pipeTo(textDecoder.writable);
const reader = textDecoder.readable.getReader();
let data= ''; //扫码数据while (true) { const { value, done } = await reader.read(); if (done) { // 允许稍后关闭串口reader.releaseLock();break; } // 处理数据data=`${data}${value}`if(value.includes('\r')){//读取结束console.log(`二维码数据:${data}`)}} } 

4.port.close()

作用:关闭串口

   port.close();

其他常见API:

port.write(data):数据写入串口
reader.cancel():取消读取流数据
navigator.serial.getPorts():获取用户之前授权过的所有端口,返回port数组

完整代码

<template><button v-if="!port" @click="chooseSerial">选择扫码枪串口</button>
</template><script setup>
import { ref } from 'vue';
const port = ref(null);
//选择串口设备
const chooseSerial = async () => {if ('serial' in navigator) {try {port.value = (await navigator.serial.requestPort()) || null;console.log('选择串口成功');port.value && openSerial();} catch (e) {console.log('选择串口失败');}} else {console.log('浏览器不支持serial API');}
};//打开串口读取数据
const openSerial = async () => {await port.value.open({ baudRate: 9600 });try {const textDecoder = new TextDecoderStream();port.value.readable.pipeTo(textDecoder.writable);const reader = textDecoder.readable.getReader();let data = ''; //扫码数据while (true) {const { value, done } = await reader.read();if (done) {reader.releaseLock();break;}data=`${data}${value}`if(value.includes('\r')){//读取结束let codeData=data;data="";//清空下次读取不会叠加console.log(`二维码数据:${codeData}`)//处理拿到数据逻辑}}} catch (error) {console.error(error);port.value = null;} finally {reader.releaseLock();console.log('关闭串口');await port.value.close();port.value = null;}
};</script>

运行:
在这里插入图片描述在这里插入图片描述
说明:只要点击按钮选择一次串口设备,选择完隐藏按钮,后续就能一直扫码获取数据,如果中途扫码枪拔出来port属性将变成null,按钮重新显示,再次插入扫码枪需要在点击按钮选择一次串口设备。

三、electron使用

electron支持Web Serial API使用,但是有点区别,在于无法弹窗让用户选择串口设备,此时需要在主进程里面授权并获取设备串口ID(portId)返给渲染进程

主进程main/index.js

function createWindow() {// Create the browser window.const mainWindow = new BrowserWindow({width: 900,height: 670,show: false,backgroundColor :'#ffffff',autoHideMenuBar: true,...(process.platform === 'linux' ? { icon } : {}),webPreferences: {preload: join(__dirname, '../preload/index.js'),sandbox: false}})//处理serialApiserialApiHandle(mainWindow)}function serialApiHandle(mainWindow){mainWindow.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => {// Add listeners to handle ports being added or removed before the callback for `select-serial-port`// is called.mainWindow.webContents.session.on('serial-port-added', (event, port) => {console.log('serial-port-added FIRED WITH', port)// Optionally update portList to add the new port})mainWindow.webContents.session.on('serial-port-removed', (event, port) => {console.log('serial-port-removed FIRED WITH', port)// Optionally update portList to remove the port})event.preventDefault();console.log(portList,'portList')if (portList && portList.length > 0) {//默认返回第一个串口idcallback(portList[0].portId)} else {// eslint-disable-next-line n/no-callback-literalcallback('') // Could not find any matching devices}})
//授权mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {if (permission === 'serial') {return true}return false})
//授权mainWindow.webContents.session.setDevicePermissionHandler((details) => {if (details.deviceType === 'serial') {return true}return false})
}

渲染进程写法跟web端一样
ps:默认返回第一个串口id

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2803288.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

idea查找所有未使用的代码

1.背景 最近在做无用代码下线的时候发现一个方法里会引用很多个方法&#xff0c;一旦该方法删除以后&#xff0c;里面被引用的方法应该也一同下线&#xff0c;但是一个一个的找过去比较耗费精力&#xff0c;下面给大家推荐一个idea自带的代码分析工具 2.代码分析工具 Code-&…

【无标题】旋转链表与力扣报错:member access within null pointer of type ‘struct ListNode‘

项目场景&#xff1a; 做单链表反转题目&#xff0c;报错&#xff1a;member access within null pointer of type ‘struct ListNode’ 题目链接:LINK 问题描述 我明明在初始化指针时候&#xff0c;已经处理了n2->next情况却依然报错 这个报错提示含义是&#xff1a;大概就…

创新性3D数据合成模型,微软推出EgoGen

随着AR、VR等设备的广泛应用,第一人称的应用开始增多。但在研发方面面临不同的挑战,例如&#xff0c;图像模糊、视觉混乱、遮挡更严重等&#xff0c;给视觉模型的训练带来重大挑战。 一方面,人工标注真实第一视角数据集&#xff0c;来培训深度学习模型的成本和难度都很高。另一…

第八章 shell编程之sed

目录 1.1. 概念 1.1.1. 工作原理&#xff1a; 1.2. 基本语法 1.2.1. 格式 1.2.2. 参数 1.2.3. 定址符 1.2.4. 操作 1.3. 输出文本 1.3.1. 范例文件&#xff1a; 1.3.2. 示例 1.4. 文本替换 1.4.1. 范例文件 1.4.2. 格式&#xff1a; 1.4.3. 示例 1.5. 删除文本 …

提升生产能力的必备工具——MES系统自动排产

在现代制造业中&#xff0c;生产能力的提升对企业发展至关重要。随着市场竞争的日益激烈&#xff0c;企业不仅需要提高产品质量&#xff0c;还需要提高生产效率。而MES系统自动排产作为一种先进的生产管理工具&#xff0c;可以帮助企业高效地安排生产&#xff0c;实现生产能力的…

江科大stm32学习笔记——【3-2】GPIO输出:LED闪烁LED流水灯蜂鸣器

&#xff08;一&#xff09; 硬件连接 1.LED闪烁 LED灯正极连接面包板电源正极&#xff0c;LED负极连接单片机A0口 (也可以LED负极连面包板负极&#xff0c;LED正极连接单片机A0口) 跳线连接单片机3.3和面包板正极&#xff0c;连接单片机GND和面包板负极 2.LED流水灯 3.蜂鸣…

你并不了解 JavaScript:入门 - 第二版 - 第二章:JS 概观

第二章&#xff1a;JS 概观 学习 JS 的最好方法就是开始写 JS。 要做到这一点&#xff0c;你需要知道这门语言是如何工作的&#xff0c;而这正是我们在这里要重点讨论的。即使你以前用过其他语言编程&#xff0c;也要慢慢适应 JS&#xff0c;并确保练习每一块。 这一章并不是…

自学黑客的这些坑千万别踩,不然就是在做无用功!

一、自学网络安全学习的误区和陷阱 1.不要试图先成为一名程序员&#xff08;以编程为基础的学习&#xff09;再开始学习 一般来说&#xff0c;学习编程不但学习周期长&#xff0c;而且实际向安全过渡后可用到的关键知识并不多 一般人如果想要把编程学好再开始学习网络安全往…

并发编程(3)JMM

5 共享模型之内存 本章内容 上一章讲解的 Monitor 主要关注的是访问共享变量时&#xff0c;保证临界区代码的原子性. 这一章我们进一步深入学习共享变量在多线程间的【可见性】问题与多条指令执行时的【有序性】问题 5.1 Java 内存模型 JMM 即 Java Memory Model&#xff…

SQL库操作

1、创建数据库 概念 创建数据库&#xff1a;根据项目需求创建一个存储数据的仓库 使用create database 数据库名字创建 数据库层面可以指定字符集:charset/character set 数据库层面可以指定校对集:collate 创建数据库会在磁盘指定存放处产生一个文件夹 创建语法 create …

六.生成makefile文件 并基于makefile文件编译opencv

1.点击【Generate】 生成makefile文件 2.进入目录下编译opencv源码&#xff0c;mingw32-make -j 8 3..编译出现报错 4.取消[WITH_OPENCL_D3D11_NV]选项&#xff0c;再次【configure】【generate】 然后再次编译&#xff1a;mingw32-make -j 8

【springblade】springblade(bladeX) 数据权限失效原因分析

文章目录 数据权限接口权限 前言&#xff1a;最近博主在按照bladeX官方文档 配置数据权限 结果发现失效了&#xff0c;网上搜了一下没找到合适的答案&#xff0c;本着求人不如求己的精神&#xff0c;自己调试了一下发现了问题所在&#xff0c;也大致看了一下bladeX的权限逻辑。…

这份攻略帮助你分分钟构建出“幻兽帕鲁游戏”极致体验【下】

在上一篇文章这份攻略帮助你分分钟构建出“幻兽帕鲁游戏”极致体验【上】中写了&#xff0c;极狐GitLab 将 terraform state 文件管理了起来。这篇文章将演示如何将所有的 terraform 文件存储到极狐GitLab 中&#xff0c;并且使用 CI/CD 自动实现 terraform 命令的执行。 在 D…

最简单方式把jar打包成Windows服务

废话 &#x1f622; 将JAR文件转化为Windows服务是一种高效且常见的Java应用部署策略。这种转变赋予了Java应用程序在Windows操作系统上以无界面后台服务模式运行的能力&#xff0c;从而实现了持续、稳定且可靠的功能提供。这种部署方式不仅提升了应用的可用性&#xff0c…

re-迷宫题学习

re中的迷宫问题有以下特点: 在内存中布置一张 "地图"将用户输入限制在少数几个字符范围内.一般只有一个迷宫入口和一个迷宫出口 布置的地图可以由可显字符 (比如#和*)组合而成 (这非常明显, 查看字符串基本就知道这是个迷宫题了.), 也可以单纯用不可显的十六进制值进…

【鸿蒙 HarmonyOS 4.0】UIAbility、页面及组件的生命周期

一、背景 主要梳理下鸿蒙系统开发中常用的生命周期 二、UIAbility组件 UIAbility组件是一种包含UI界面的应用组件&#xff0c;主要用于和用户交互。 UIAbility组件是系统调度的基本单元&#xff0c;为应用提供绘制界面的窗口&#xff1b;一个UIAbility组件中可以通过多个页…

【大厂AI课学习笔记NO.50】2.3深度学习开发任务实例(3)任务背景与目标

我们经常在做项目的时候&#xff0c;觉得分析背景和目标是浪费时间&#xff0c;觉得不过如此。 其实目标梳理特别重要&#xff0c;直接决定你数据的需求分析&#xff0c;模型的选择&#xff0c;决定你交付的质量。 人工智能项目也和其他项目一样&#xff0c;不要想当然&#…

7-liunx服务器规范

目录 概况liunx日志liunx系统日志syslog函数openlog 可以改变syslog默认输出方式 &#xff0c;进一步结构化 用户信息进程间的关系会话ps命令查看进程关系 系统资源限制改变工作目录和根目录服务器程序后台话 概况 liunx服务器上有很多细节需要注意 &#xff0c;这些细节很重要…

Redis进阶篇

Redis线程模型 redis是基于内存运行的高性能k-v数据库&#xff0c;6.x之前是单线程, 对外提供的键值存储服务的主要流程 是单线程&#xff0c;也就是网络 IO 和数据读写是由单个线程来完成&#xff0c;6.x之后引入多线程而键值对读写命 令仍然是单线程处理的&#xff0c;所以 …

智能未来之路:《NIST AI RMF 1.0》与负责任的AI发展

引言 在当今快速发展的人工智能领域&#xff0c;美国国家标准与技术研究院&#xff08;NIST&#xff09;发布的《NIST AI RMF 1.0》框架是一个标志性的里程碑。这一框架不仅为AI技术的负责任和可信赖使用提供了重要指导&#xff0c;而且对于推动可持续的AI发展具有深远影响。本…