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

embedded/2024/9/25 0:32:53/

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

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.ppmy.cn/embedded/12945.html

相关文章

光纤、以太网电缆和 DSL 的比较:技术指南

了解光纤、以太网电缆和 DSL 之间的差异对于做出有关互联网连接的明智决策至关重要。本技术指南对这些技术进行了全面比较&#xff0c;讨论了它们的独特功能、性能指标和应用。它旨在为您提供必要的知识&#xff0c;以选择最适合您的特定需求的选项。 光纤、以太网电缆和 DSL …

深入理解高级加密标准(Advanced Encryption Standard)

title: 深入理解高级加密标准&#xff08;Advanced Encryption Standard&#xff09; date: 2024/4/23 20:04:36 updated: 2024/4/23 20:04:36 tags: AES概述加密原理优势特点算法详解安全性应用实践案例分析 第一章&#xff1a;AES概述 AES的历史和背景 历史&#xff1a; 高…

力扣-1844.将所有数字用字符替换

思路&#xff1a; 1. class Solution:&#xff1a;定义了一个名为 Solution 的类&#xff0c;用于包装解决问题的方法。 2. def replaceDigits(self, s: str) -> str:&#xff1a;定义了一个名为 replaceDigits 的方法&#xff0c;该方法接受一个字符串 s 作为参数&#x…

Maven基础篇2

1.依赖范围 只要是jar默认情况下可以在任何地方使用&#xff0c;可以通过scope标签进行设定其范围 scope的不同参数以及指定范围 关于servlet-api不参与打包&#xff0c;原因服务器上tomcat也有servlet-api如果版本不同会起冲突&#xff1b;因此需要使用scope写provided来进…

线上线下交友社区系统 可打包小程序 支持二开 源码交付!

社交网络的普及&#xff0c;人们交友的方式发生了巨大的变化。过去&#xff0c;我们主要通过线下的方式来结识新朋友&#xff0c;比如在学校、工作场所、社交活动或者兴趣小组中。然而&#xff0c;随着移动端软件的发展&#xff0c;线上交友也逐渐变得流行。 方便性&#xff1a…

QT客户端的开发框架

针对QT客户端开发&#xff0c;目前存在多种框架&#xff0c;各有优缺点&#xff0c;具体选择哪种框架取决于您的具体需求和项目特点。以下是一些流行的QT客户端开发框架。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1. Qt框架 Qt…

ELK日志系统的搭建

文章目录 简介软件准备安装JDK下载Elasticsearch软件修改配置信息创建ElasticSearch运行用户、启动服务添加防火墙策略ElasticSearch-Head插件安装 安装Kibana下载软件包修改配置启动服务 安装Logstash安装包下载安装服务配置修改配置pipeline流水线服务配置文件 启动服务 全流…

算法第42天动态规划4

416 分割等和子集 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等 def canPartition(nums:List[int])->bool:total_sumsum(nums)if total_sum%2!0:return Falsetarget_sumtotal_sum//2dp[[Fal…