微信小程序实现蓝牙连接通讯

由于最近的项目在做小程序蓝牙通讯这块的内容,所以将实现的过程在这简单的记录下。

1、首先要初始化蓝牙-检查蓝牙适配器是否打开

 async initBluetooth(): Promise<void> {return new Promise((resolve: any, reject: any) => {const _this = thisif (BluetoothController.adapterOpend) {console.log("蓝牙适配器已打开")resolve(true)return}wx.openBluetoothAdapter({success(res) {BluetoothController.adapterOpend = trueconsole.log("=====*****蓝牙适配器已打开")resolve(true)},fail(error) { //用来判断蓝牙是否已打开reject(error)BluetoothController.adapterOpend = falseconsole.log("=====*****蓝牙适初始化失败", error)}})})}//使用案例
initBluetooth().then()

2、开始搜寻附近的蓝牙外围设备

 /*** @param options * options.keywords  蓝牙名称筛选关键字* options.deviceid  可选参数,蓝牙设备id,连接用*/async searchAroundBLE(options: any): Promise<void> {return new Promise((resolve: any, reject: any) => {const _this = thisif (_this.startDiscovery) {console.log("已开启蓝牙扫描,勿重复开启")resolve(true)return}_this.startDiscovery = truewx.startBluetoothDevicesDiscovery({allowDuplicatesKey: true,services: options.services,success(res) {console.log('搜索成功', res);resolve(true)},fail(error) {reject(error)_this.startDiscovery = false},})})}//使用案例searchAroundBLE({ 'keywords': [''], services: [] }).then()

3、监听搜索到的设备

 /*** @param options * options.keywords  蓝牙名称筛选关键字* options.deviceid  可选参数,蓝牙设备id,连接用*/async onBluetoothDeviceFound(options: any): Promise<void> {return new Promise((resolve: any, reject: any) => {let _this = thislet { keywords } = options// 超时自动结束_this.findTimer = setTimeout(() => {clearTimeout(_this.findTimer)if (!_this.connectStatus) {reject({ success: false})console.log('蓝牙扫描超时,自动关闭任务')}}, 3000); //时间根据自己的需求定let arr: any = []wx.onBluetoothDeviceFound(res => {let devices = res.devices;devices.forEach((device) => {if (!device.name && !device.localName) {return}// 获取设备MAC地址,并根据关键字过滤let systemInfo = wx.getSystemInfoSync()let iosDevice = systemInfo.system.toLowerCase().indexOf("ios") > -1;let deviceMac = iosDevice ? uuid2Mac(device.advertisData) : device.deviceId// keywordsif (keywords && keywords.length > 0) {let key = keywords[0]if (device.name.indexOf(key) >= 0) {arr.push({...device,deviceMac})}if (arr.length) {let foundDevices = arr_this.deviceList = foundDevicesresolve({data: arr,success: true})}}})})})}/*** 统一安卓与IOS端deviceId展示* @param advertisData * 在安卓设备中,获取到的 deviceId 为设备 MAC 地址,iOS 上则为设备 uuid,* 因此为了展示一致需要将ios的展示进行输入(当然IOS的连接还是得用获取到的uuid)*/
function uuid2Mac(advertisData: any) {if (advertisData) {let mac = Array.prototype.map.call(new Uint8Array(bf), (x) => ("00" + x.toString(16)).slice(-2)).join(":");mac = mac.toUpperCase();return mac;}
}使用案例: onBluetoothDeviceFound({ 'keywords': [''] }).then()  //keywords根据自己的需求去定,

4、处理蓝牙连接(搜索到设备开始蓝牙链接)

/*** @param {string} options.deviceId 蓝牙设备id,连接用*/async createBLEConnection(options: any): Promise<void> {return new Promise((resolve: any, reject: any) => {let { deviceId } = options,_this = this_this.deviceId = deviceIdif (_this.connectStatus) {wx.closeBLEConnection({deviceId})}let timeout = 3000 //根据自己需求去定console.log('开始连接蓝牙--', deviceId)_this.stopBLEDevicesTask()wx.createBLEConnection({deviceId,timeout,success(res) {console.log('蓝牙连接成功-----', deviceId)_this.connectStatus = trueresolve(true)},fail() {_this.connectStatus = falsereject(false)}})})}使用案例: createBLEConnection({ deviceId: tmp[0].deviceId }).then()

5、连接成功后,要获取蓝牙的所有服务 进而根据项目需求的服务 去获取对应的特征 来进行读写操作

 /*** @param deviceId  蓝牙设备Id,来自createBLEConnection调用*/async getBLEDeviceServices(deviceId: any): Promise<void> {return new Promise((resolve: any, reject: any) => {let _this = thiswx.getBLEDeviceServices({deviceId,success(res) {/*** 16 位 UUID 从对接文档中获取(注意都是0000开头,接着的4位数字为16进制的uuid,所有服务只有4位uuid不一样)注意有多个服务,不同服务的操作不一样,单个服务只能执行单个操作,所以这里需要建立多个连接*/for (let i = 0; i < res.services.length; i++) {// 注意uuid的大小写if (res.services[i].isPrimary &&res.services[i].uuid == "0000D0FF-0000-1000-8000-008cbhschs" //设备id,根据自己的项目去走) {// _this.getBLEDeviceCharacteristics(res.services[i].uuid);resolve({data: res.services[i].uuid,sucess: true})return;}}},fail: (res) => {reject({sucess: false,data: res.errMsg})console.log("服务获取失败------------->", res.errMsg);},});})}async getBLEDeviceCharacteristics(serviceId: any): Promise<void> {return new Promise((resolve: any, reject: any) => {let _this = thiswx.getBLEDeviceCharacteristics({deviceId: _this.deviceId,  //设备id根据自己项目的去赋值serviceId,  //服务idsuccess: (res) => {// 设备特征列表let characteristics = res.characteristics;for (let i = 0; i < characteristics.length; i++) {let item = characteristics[i];if (item.properties.write) {this.serviceId = serviceIdthis.characteristicId = item.uuid}if (item.properties.read) {wx.readBLECharacteristicValue({deviceId: _this.deviceId,serviceId,characteristicId: item.uuid});}if (item.properties.write) {// resolve({//     data: 1,//     sucess: true// })}if (item.properties.notify || item.properties.indicate) {/* 启用蓝牙低功耗设备特征值变化时的 notify 功能,订阅特征。注                        意:必须设备的特征支持 notify 或者 indicate 才可以成功调用。
另外,必须先启用 wx.notifyBLECharacteristicValueChange 才能监听到设备 characteristicValueChange 事件*/wx.notifyBLECharacteristicValueChange({deviceId: _this.deviceId,serviceId,characteristicId: item.uuid,state: true,});resolve({data: item.properties,sucess: true})}}},fail(error: any) {reject({sucess: false,data: error})}});})}使用案例: let { data } = await getBLEDeviceServices(tmp[0].deviceId)  //data就是所有服务内容if (data) {// 2、获取蓝牙低功耗设备某个服务中所有特征 (characteristic)let ble_chart = await getBLEDeviceCharacteristics(data)if (ble_chart.sucess) {let item = ble_chart.data// 该特征是否支持 write 操作if (item.write) {// resolve(true)this.handleWriteSucess();  //处理写操作}// 该特征是否支持 notify ,indicate操作 ,开启监听订阅特征消息if (item.notify || item.indicate) {this.watchBleData()//监听蓝牙数据}}
}

6、读写成功后开始根据蓝牙协议进行操作(蓝牙协议有设备方提供)

handleWriteSucess()  //写成功后的操作
watchBleData() {wx.onBLECharacteristicValueChange(async (res) => { //监听蓝牙数据变化let resHex = ab2hex(res.value).toLocaleUpperCase() //包数据, 根据蓝牙协议去进行处理let { data } = writeBLECharacteristicValue('对应指令', '脚电极')})
}/*** ArrayBuffer转16进度字符串* @param buffer */
// ArrayBuffer转16进度字符串
ab2hex(buffer: any) {var hexArr = Array.prototype.map.call(new Uint8Array(buffer), function (bit) {return ("00" + bit.toString(16)).slice(-2);});return hexArr.join("");
}

 7、处理蓝牙写指令

 /*** 4. 发送蓝牙指令。蓝牙指令超出20字符时需要截断多次发送* @param {string} cmdStr 蓝牙指令* @param {string} cmdName 蓝牙指令名称——可选用于打印调试*/async writeBLECharacteristicValue(cmdStr: any, cmdName: string): Promise<void> {// // console.log("发送蓝牙指令------------》", cmdStr, cmdName);return new Promise((resolve: any, reject: any) => {let _this = thislet data = cmdStr.split(',')let buffer = new ArrayBuffer(data.length);let dataViewLast = new DataView(buffer);for (let i = 0; i < data.length; i++) {dataViewLast.setUint8(i, data[i]);}let param: any = {deviceId: _this.deviceId,serviceId: _this.serviceId,characteristicId: _this.characteristicId,  //在获取特性那有value: dataViewLast.buffer,};console.log("param", param)wx.writeBLECharacteristicValue({...param,success: function () {console.log("发送指令成功", cmdName);resolve({data: {cmdName,sucess: true}})},fail: function (error: any) {reject({data: {data: error,sucess: true}})},})})}

注意点:

在判断蓝牙是否打开之前,还要先判断下手机上位置是否打开

let locationEnabled = wx.getSystemInfoSync().locationEnabled

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

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

相关文章

美森快船和以星快船有什么区别?美线海运都有哪些快船?

在繁忙的国际海运市场中&#xff0c;快船服务以其高效、快捷的特点受到广大货主的青睐。其中&#xff0c;美森快船和以星快船作为知名的海运服务提供商&#xff0c;凭借着卓越的服务品质&#xff0c;在航运界树立了良好的口碑。那么&#xff0c;美森快船和以星快船究竟有何不同…

利用ollama和open-webui本地部署通义千问Qwen1.5-7B-Chat模型

目录 1 安装ollama 2 安装open-webui 2.1 镜像下载 3 配置ollama的模型转换工具环境 3.1 下载ollama源码 3.2 下载ollama子模块 3.3 创建ollama虚拟环境 3.4 安装依赖 3.5 编译量化工具 7 创建ollama模型 8 运行模型 参考文献&#xff1a; 1 安装ollama curl -fsSL …

【CCF推荐-C类】计算机学术会议截稿信息2条

中国计算机学会推荐国际学术会议和期刊目录自2010年8月首次发布以来&#xff0c;已历经五版&#xff0c;得到了计算机领域科研工作者的广泛关注。 目录共包含十个领域&#xff0c;分为ABC三类&#xff1a;A类是国际上极少数顶会与顶刊&#xff1b;B类代表领域内高水平的会议与…

2-2 任务:闰年判断

本次课&#xff0c;我们讨论了闰年的判断方法、关系运算符与关系表达式、逻辑运算符与逻辑表达式&#xff0c;以及流程控制结构中的选择结构。 闰年判断 闰年是为了使日历年与地球绕太阳公转的时间保持一致而设定的&#xff0c;具有366天。闰年的判断规则如下&#xff1a; 普…

16V/2A高集成功率MOS同步降压转换器SOT23-6封装

概述&#xff1a; PCD8020 是一款内部集成两个功率 MOS 的高效率 2A 同步整流降压转换器。 该器件提供PWM 与 PFM 两种控制模式&#xff0c; 能够在很宽的负载范围内实现高效率。PCD8020 采用小巧的 SOT23-6 封装&#xff0c; 外围器件少&#xff0c; 从而实现小尺寸的系统电源…

【算法】约瑟夫环

文章目录 题目一1.数组模拟1.1出圈顺序递归求出圈顺序 1.2最后出圈人 2.环形链表【DEMO】3.递推求最后出圈人3.13.2 题目二1.数组模拟2.递推求最后出圈人2.12.2 题目一 1-n编号 s开始1-m报数 报到m出圈 求出圈顺序or最后人 1.数组模拟 1.1出圈顺序 递归求出圈顺序 // AC输入…

python 如何判断两个字典是否相等

Python 字典的 cmp() 函数用于比较两个字典元素。 语法 cmp()方法语法&#xff1a; cmp(dict1, dict2)参数 dict1 -- 比较的字典。 dict2 -- 比较的字典。 返回值 如果两个字典的元素相同返回0&#xff0c;如果字典dict1大于字典dict2返回1&#xff0c;如果字典dict1小于…

为AI电脑生态注入强悍动力,安耐美PlatiGemini 1200W高性能电源

在DIY攒机的过程中&#xff0c;电源是非常重要的一环&#xff0c;现在高性能的硬件功耗往往很高&#xff0c;因此一款优秀的电源整个系统稳定运行的基石。最近&#xff0c;我发现一款由安耐美&#xff08;Enermax&#xff09;推出的PlatiGemini 1200W电源&#xff0c;它不仅满足…

ShardingSphere-JDBC快速入门

ShardingSphere-JDBC读写分离快速入门 一、ShardingSphere-JDBC 读写分离1.创建springboot程序1.1 添加依赖1.2 java代码1.3 配置 2.测试 二、ShardingSphere-JDBC垂直分片1.创建springboot程序1.1 导入依赖1.2 java代码1.3 配置 2.测试 三、ShardingSphere-JDBC水平分片1.创建…

代码随想录算法Day34(2)||LeetCode134.加油站

学习内容参考卡哥代码随想录,有文字学习资料(代码随想录网站)和视频讲解(b站) 2.134加油站 题目 力扣题目链接(opens new window) 在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需…

flutter笔记-万物皆是widget

文章目录 helloFlluter自定义Widget优化 这篇文章后就不见写了&#xff0c;学flutter主要是为了更好的使用 flutter-webrtc&#xff0c;所以到这里基本就了解了大部分的知识&#xff0c;后续边用边查&#xff1b; 在flutter中所有的view都叫widget&#xff0c;类似文本组件Tex…

Vue3页面的执行过程

在 Vue 3 中&#xff0c;一个普通的页面的执行过程可以分为以下几个环节&#xff1a; 创建 Vue 应用程序实例&#xff08;createApp&#xff09;&#xff1a; 使用 createApp 函数创建一个 Vue 根实例。配置根实例--该函数接收一个配置对象作为参数&#xff0c;其中的配置项可包…

DICOM图像像素值的位数分类、DICOM图像内存申请如何计算?

DICOM图像像素值的位数分类 用于表示像素值的位数会根据图像类型有所不同&#xff1a; 灰度图像&#xff1a; 灰度图像&#xff08;如CT、MR等医学影像&#xff09;&#xff0c;每个像素通常只包含一个灰度值&#xff0c;用来表示该位置的组织密度或信号强度。 根据您提供的…

对象与JSON字符串互转

1、JSON字符串转化成JSON对象 JSONObject jsonobject JSON.parseObject(str); 或者 JSONObject jsonobject JSONObject.parseObject(str); 功能上是一样的&#xff0c;都是将JSON字符串&#xff08;str&#xff09;转换成JSON对象 jsonobject 。注意str一定得是以键值对存在…

C语言进阶 数据的存储(上)

一、 数据类型详细介绍 我们前面已经学习了基本的内置类型 char 字符数据类型 short 短整型 int 整型 long 长整型 long long 更长的整型 float 单精度浮点型 double 双精度浮点形 类型有什么意义呢&#xff1f; 1 使用这个类型开辟内存空间的大小 比如说 int 4个字节 short 两…

Python | Leetcode Python题解之第41题缺失的第一个正数

题目&#xff1a; 题解&#xff1a; class Solution:def firstMissingPositive(self, nums: List[int]) -> int:n len(nums)for i in range(n):while 1 < nums[i] < n and nums[nums[i] - 1] ! nums[i]:nums[nums[i] - 1], nums[i] nums[i], nums[nums[i] - 1]for …

算法刷题day46

目录 引言一、树的重心二、毕业旅行问题三、高精度乘法 引言 今天复习了一下高精度的所有模板&#xff0c;包括加法、减法、乘法、除法&#xff0c;因为自己当时在蓝桥杯的时候没有看出来那个题使用高精度&#xff0c;因为对于一个数的大小和一个数的长度&#xff0c;自己有时…

通过Bedrock Access Gateway解决方案快速访问Amazon Bedrock的多种大语言模型

Bedrock Access Gateway&#xff08;BAG&#xff09;解决方案提供了开箱即用、兼容 OpenAI 的代理功能&#xff0c;帮助用户轻松无缝地从 OpenAI 迁移到 Amazon Bedrock。 1. 概述 亚马逊云科技的 Amazon Bedrock 服务支持一系列领先的基础模型&#xff0c;为客户提供多种选择…

基于卷积神经网络的垃圾图像分类系统研究与实现

1.摘要 垃圾分类作为资源回收利用的重要环节之一, 可以有效地提高资源回收利用效率, 进一步减轻环境污染带来的危害. 随着现代工业逐步智能化, 传统的图像分类算法已经不能满足垃圾分拣设备的要求. 本文提出一种基于卷积神经网络的垃圾图像分类模型 (Garbage Classification Ne…

索引的最左匹配原则

索引的最左匹配原则 我们先创建一张测试表&#xff0c;表的两个字段用来创建联合索引 CREATE TABLE test(id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,col1 INT,col2 INT,col3 INT );CREATE INDEX idx_c1c2 ON test(col1, col2);现在我们就可以分析查询sql脚本了 1.使用联合索…