uni-app 蓝牙传输

https://www.cnblogs.com/ckfuture/p/16450418.html

https://www.cnblogs.com/yangxiaobai123/p/16021058.html

字符串转base64:https://www.cnblogs.com/sunny3158/p/17312158.html 

将 ArrayBuffer 对象转成 Base64 字符串:基础 - uni.arrayBufferToBase64 - 《uni-app API 文档》 - 书栈网 · BookStack 

ArrayBuffer:https://zhuanlan.zhihu.com/p/655456833 

最近在做一个项目,要求app通过蓝牙连接设备并将报文传输至设备中,在这个过程踩过了几个坑,总结如下:

根据uni-app官网API主要涉及到“蓝牙”和“低功耗蓝牙”两个部分。

主要步骤:

步骤1:初始化蓝牙模块 openBluetoothAdapter

            $openBluetoothAdapter(){uni.openBluetoothAdapter({success: (res) => {//初始化成功,搜索设备console.log('openBluetoothAdapter success', res);uni.showLoading({title: '搜索设备中'});setTimeout(()=>{this.baseList=[];//每次扫码清空设备列表,不然会导致重复this.$startBluetoothDevicesDiscovery();//扫码蓝牙设备},100);//定时关闭搜索设备setTimeout(()=>{this.$stopBluetoothDevicesDiscovery();uni.hideLoading();},10*1000);},fail: (res) => {uni.showToast({title: '请打开蓝牙',duration: 1000});if (res.errCode === 10001) {//监听蓝牙适配器状态变化事件uni.onBluetoothAdapterStateChange(function(res){console.log('onBluetoothAdapterStateChange', res);if (res.available) {//开始扫描this.$startBluetoothDevicesDiscovery()}})}}})},

步骤2:搜索附近的蓝牙外围设备 startBluetoothDevicesDiscovery

            //2.搜索附近的蓝牙外围设备$startBluetoothDevicesDiscovery(){if (this._discoveryStarted) {return;}this._discoveryStarted = true;//开始搜寻附近的蓝牙外围设备uni.startBluetoothDevicesDiscovery({allowDuplicatesKey: true,success: (res) => {console.log('startBluetoothDevicesDiscovery success', res);//监听寻找到新设备的事件this.$onBluetoothDeviceFound()},fail:err=>{console.error("startBluetoothDevicesDiscoveryErr",err);uni.showToast({icon:'none',duration:2000,title:"请检查蓝牙状态",});}})},

步骤3:监听寻找到新设备 onBluetoothDeviceFound

            $onBluetoothDeviceFound(){let that =this;//监听寻找到新设备的事件uni.onBluetoothDeviceFound(function(res){res.devices.forEach(device => {if (!device.name && !device.localName) {return;}//添加蓝牙设备列表let oneBluetooth={deviceId: device.deviceId,name: device.name,RSSI:device.RSSI,localName:device.localName}            //判断是否存在if(that.bluetoothIndex.indexOf(device.deviceId) ==-1){that.baseList.push(oneBluetooth);that.bluetoothIndex.push(device.deviceId);}//如果名字相同连接设备//if(device.name == devicename){//$createBLEConnection(device.deviceId);//}})})},

步骤4:创建连接蓝牙事件  createBLEConnection

            $createBLEConnection(deviceId){let that=this;//1)判断设备是否处于连接状态if(that.Connecting){uni.showToast({icon:'none',duration:2000,title:"设备已连接",});return} //2)创建连接uni.showLoading({title: '设备连接中',mask:true,});uni.createBLEConnection({deviceId:deviceId,success: (res) => {that._deviceId = deviceId;//不延迟造成获取不到服务!!!!,我走过的坑!!!setTimeout(function() {//获取设备的蓝牙服务that.$getBLEDeviceServices(deviceId);//关闭等待提示setTimeout(function () {uni.hideLoading();}, 100);}, 7000);},fail: (err) =>{console.log(err);}});//3)设置MTU,否则传输报文不全,默认是23bytes,但是蓝牙本身是需要3bytes,故而只能传输20bytessetTimeout(()=>{console.log('deviceId>>>',deviceId);uni.setBLEMTU({deviceId:deviceId,mtu:255,success:(res)=>{console.log('设置MTU最大值成功',res);},fail:(res)=>{console.log('设置MTU最大值失败',res);}});},9000);//4)关闭搜索this.$stopBluetoothDevicesDiscovery();},

步骤5:获取蓝牙设备的所有服务 getBLEDeviceServices

            $getBLEDeviceServices(deviceId){//获取蓝牙设备所有服务(service)uni.getBLEDeviceServices({deviceId,success: (res) => {console.log('250res.services>>>',res.services);for (let i = 0; i < res.services.length; i++) {if (res.services[i].isPrimary) {this.$getBLEDeviceCharacteristics(deviceId, res.services[i].uuid);return;}}}});},

步骤6:获取蓝牙设备某个服务中所有特征值(characteristic)getBLEDeviceCharacteristics

            $getBLEDeviceCharacteristics(deviceId,serviceId){let that = this;//获取蓝牙设备某个服务中所有特征值(characteristic)。uni.getBLEDeviceCharacteristics({deviceId,serviceId,success: (res) => {console.log('288getBLEDeviceCharacteristics success', res.characteristics);for (let i = 0; i < res.characteristics.length; i++) {let item = res.characteristics[i]//if (item.properties.read) {//读取低功耗蓝牙设备的特征值的二进制数据值。1uni.readBLECharacteristicValue({deviceId,serviceId,characteristicId: item.uuid,})//}if (item.properties.write) {this._deviceId = deviceId;this._serviceId = serviceId;this._characteristicId = item.uuid;//写入请求数据this.$writeBLECharacteristicValue();                                }//if (item.properties.notify || item.properties.indicate) {//启用低功耗蓝牙设备特征值变化时的 notify 功能,订阅特征值。uni.notifyBLECharacteristicValueChange({deviceId,serviceId,characteristicId: item.uuid,state: true,success(res) {// console.log('notifyBLECharacteristicValueChange success:' + res.errMsg);// console.log(JSON.stringify(res));uni.onBLECharacteristicValueChange(characteristic => {console.log('监听低功耗蓝牙设备的特征值变化事件成功>>');//将字节转换成16进制字符串var data = ab2hex(characteristic.value)//将16进制转成字符串let newdataStr = Buffer.from(data,'hex');//先把数据存在buf里面//that.btvalue=newdataStr.toString("utf-8");//使用toString函数就能转换成字符串//设备返回SNthat.SN=newdataStr.toString("utf-8");console.log('设备返回SN>>>',that.SN);//根据返回的数据处理设备类型和显示的输入区域-----------------that.getEquType(that.SN);});}});//}}},fail(res) {console.error('getBLEDeviceCharacteristics', res)}})},

步骤7:向蓝牙设备发送一个16进制数据

            $writeBLECharacteristicValue(){let buffer = new ArrayBuffer(1)let dataView = new DataView(buffer);dataView.setUint8(0, 0);//0x61 | 0uni.writeBLECharacteristicValue({deviceId: this._deviceId,serviceId: this._serviceId,//"0000FE61-0000-1000-8000-00805F9B34FB",characteristicId: this._characteristicId,value: buffer,success: function(res){console.log('350',res);},fail: function(res){console.log(res);}})},

步骤8:向蓝牙设备发送字符串数据 writeBLECharacteristicValueString

            $writeBLECharacteristicValueString(str){// 发送方式一let buffer = new ArrayBuffer(str.length);let dataView = new DataView(buffer);for (let i in str) {dataView.setUint8(i, str[i].charCodeAt() | 0);    //打印二进制字节//console.log('dataView.getUint8(i)>>',dataView.getUint8(i));}//延迟发送指令setTimeout(()=>{uni.writeBLECharacteristicValue({deviceId: this._deviceId,serviceId: this._serviceId,characteristicId: this._characteristicId,//"0000FE61-0000-1000-8000-00805F9B34FB",//,value: buffer,success: function(res){console.log("命令写入成功",res); },fail: function(res){console.error("命令写入失败",res);}});},2000);},

步骤9:关闭搜索  stopBluetoothDevicesDiscovery

            $stopBluetoothDevicesDiscovery(){//关闭搜索uni.stopBluetoothDevicesDiscovery({success(res) {this._discoveryStarted=false;}})},

步骤10:断开蓝牙设备连接 closeBLEConnect

            $closeBLEConnect(deviceId){uni.closeBLEConnection({deviceId,success:res=>{this.deviceId = "";console.log("断开成功",res);},fail:err=>{console.error("断开错误",err);}})},

需要注意的是:

1)和蓝牙设备通讯不能太频繁。

2)写入数据时候要注意特性值UUID。

3)写入数据超过20bytes时候需要设置MTU。否则传输的内容将被截取,造成传输信息不完整。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IT运维也有自己的节日 724向日葵IT运维节,三大版本如何选?

“724运维节”&#xff0c;是2016年由开放运维联盟发起倡议&#xff0c;广大运维人员共同投票产生的属于运维人自己的节日。 对于运维人最大的印象&#xff0c;那就是工作都需要7x24小时待命&#xff0c;是名副其实的“日不落骑士”&#xff0c;这也是大家选择724这一天作为运…

原理图大结局

一、总结哪些地方是5V供电&#xff1f;哪些地方是4V供电&#xff1f;哪些地方是3.3V供电&#xff1f;为什么会这样&#xff1f;根据什么原则来划分供电区域&#xff1f; 二、 5V 供电为什么有的地方要100uF&#xff0b; 0.1uF 滤波&#xff1f;有的地方只要 10uF 滤波&#xff…

RabbitMQ - 延迟消息 - 死信交换机

目录 1、怎么理解延迟消息&#xff1f; 2、如何实现延迟消息&#xff1f; 2.1、方案一&#xff1a;死信交换机 2.1.1、什么是死信&#xff1a; 2.1.2、什么是死信交换机&#xff1f; 2.2、方案二&#xff1a;延迟消息插件 2.2.1、插件安装&#xff1a; 2.2.2、代码实现 …

AndroidStudio2023.3版本avd manager模拟器无法创建

创建到最后一步的时候提示WARN - #com.android.sdklib.internal.avd.AvdManager - com.android.prefs.AndroidLocationsException: Can’t locate Android SDK installation directory for the AVD .ini file. 前提&#xff1a; 1.sdk路径没问题 2.安装了下图内容 那是什么原因…

提高项目透明度:有效的跟踪软件

国内外主流的10款项目进度跟踪软件对比&#xff1a;PingCode、Worktile、Teambition、Tower、Asana、Trello、Jira、ClickUp、Notion、Liquid Planner。 在项目管理中&#xff0c;确保进度跟踪的准确性与效率是每位项目经理面临的主要挑战之一。选用合适的项目进度跟踪软件不仅…

VUE2用elementUI实现父组件中校验子组件中的表单

需求是VUE2框架用elementUI写复杂表单组件&#xff0c;比如&#xff0c;3个相同功能的表单共用一个提交按钮&#xff0c;把相同功能的表单写成一个子组件&#xff0c;另一个父组件包含子组件的重复调用和一个提交按钮&#xff0c;并且要求提交时校验必填项。 注意&#xff1a; …

【Python进阶】正则表达式、pymysql模块

目录 一、正则表达式的概述 1、基本介绍 2、快速使用re模块 二、正则的常见规则 1、匹配单个字符 2、原始字符串 3、匹配多个字符 4、匹配开头和结尾 5、匹配分组 三、Python与MySQL交互 1、pymysql模块的安装 2、pymysql的操作步骤 3、connection对象 4、cursor…

记录一点mybatis的坑

1. mybatis的分页插件 startPage执行后&#xff0c;紧跟的一个查询语句 会被加上limit对应的参数&#xff0c;然后自动执行clearPage&#xff08;&#xff09;&#xff0c;以免其他语句受到 分页的影响。 但是如果我们没有 执行查询语句&#xff0c;那么&#xff0c;这个分页可…

可重入锁深入学习(有码)

【摘要】 ​今天&#xff0c;梳理下java中的常用锁&#xff0c;但在搞清楚这些锁之前&#xff0c;先理解下 “临界区”。临界区在同步的程序设计中&#xff0c;临界区段活称为关键区块&#xff0c;指的是一个访问共享资源&#xff08;例如&#xff1a;共享设备或是共享存储器&a…

数据湖仓一体(二) 安装kafka

上传安装包到/opt/software目录并解压 [bigdatanode106 software]$ tar -zxvf kafka_2.12-3.5.2.tgz -C /opt/services/ 重命名kafka [bigdatanode106 software]$ mv kafka_2.12-3.5.2 kafka_3.5.2 配置环境变量 [bigdatanode106 ~]$ sudo vim /etc/profile.d/bigdata_…

深度学习调参

此文整理总结github上的一个资料&#xff0c;结尾附上链接。对于工程应用很有现实参考&#xff0c;带入实际工作场景中会有不少的收获。 这份文档旨在帮助工程师和研究人员系统性地优化深度学习模型的性能。它涵盖了从项目启动到模型部署的各个环节&#xff0c;包括&#xff1a…

6、evil box one

低—>中 目标&#xff1a;获取root权限以及2个flag 主机发现 靶机 192.168.1100.40 或者使用fping -gaq 192.168.100.1/24发现主机使用ping的方式。 端口扫描 发现开放了22和80 可以使用-A参数&#xff0c;-A参数会得到更多的扫描细节 访问80端口就是一个apache的基本的…

基于Python/MATLAB长时间序列遥感数据处理及在全球变化、植被物候提取、植被变绿与生态系统固碳分析、生物量估算与趋势分析应用

植被是陆地生态系统中最重要的组分之一&#xff0c;也是对气候变化最敏感的组分&#xff0c;其在全球变化过程中起着重要作用&#xff0c;能够指示自然环境中的大气、水、土壤等成分的变化&#xff0c;其年际和季节性变化可以作为地球气候变化的重要指标。此外&#xff0c;由于…

怎么安装Manim库在Windows环境下的Jupyter Notebook上

Manim 是解释性数学视频的动画引擎。 您可以使用它来制作数学视频&#xff08;或其他字段&#xff09;。也许你们会在有有些平台上会看过特别好看的数学动画&#xff0c;例如 3Blue1Brown等。这些动画特别好看&#xff0c;还特别丝滑&#xff0c;基本找不到太大的毛病。 我当初…

在 WebSocket 连接建立之前进行身份验证

要在 WebSocket 连接建立之前进行身份验证,可以采用以下常见方法: 基于 token 的鉴权:客户端在连接请求中携带 token,服务器端接收后验证 token 的合法性。例如,使用 ws 库时,可以在建立 WebSocket 连接时设置请求头: const socket = new WebSocket(ws://localhost:…

推荐 2 个 硬核的 AI 开源项目

01 AI 助手在你的终端中配对编程 Aider 由 Paul Gauthier 精心打造的开源AI配对编程工具&#xff0c;已经在GitHub上赢得了超过 12.8k 颗星星&#xff0c;人气爆棚&#xff01; 这不仅仅是个工具&#xff0c;它是你在终端中的 AI 编程伙伴&#xff0c;帮你编辑存储在本地 Git 仓…

mavsdk_server安卓平台编译

1.下载好mavsdk并进入mavsdk目录 2.生成docker安卓平台文件 docker run --rm dockcross/android-arm64 >./dockcross-android-arm64 3.生成makefile ./dockcross-android-arm64 cmake -DCMAKE_BUILD_TYPERelease -DBUILD_MAVSDK_SERVERON -DBUILD_SHARED_LIBSOFF -Bbuild/…

JS进阶-异常处理

学习目标&#xff1a; 掌握异常处理 学习内容&#xff1a; throw抛异常try/catch捕获异常debugger throw抛异常&#xff1a; 异常处理是预估代码执行过程中可能发生的错误&#xff0c;然后最大程度的避免错误的发生导致整个程序无法继续运行。 <title>throw抛异常</…

用C在安卓手机上开发

在安卓手机上进行C语言开发需要一些特定的工具和设置。通常&#xff0c;C语言用于编写安卓的底层代码&#xff0c;如性能关键的模块或与硬件直接交互的部分。我们可以使用Android NDK&#xff08;Native Development Kit&#xff09;来开发这些部分。以下是如何在安卓手机上使用…

前端面试题-怎样获取 url 地址栏 ? 后面的查询字符串,并以键值对形式放到对象里面

哈喽小伙伴们大家好!今天继续更新面试题系列文章 以百度为例&#xff1a; 我们以百度搜索掘金&#xff0c;url 为以下格式 https://cn.bing.com/search?q%E7%A8%80%E5%9C%9F%E6%8E%98%E9%87%91&formANNTH1&refig668f422a37c343b6b0f4ac940f65d043&pcEDGENTP&am…