最近我在为我的微信小程序新增物联网通信功能时,添加了蓝牙通信功能。看了很多资料和教程,我终于写出了一个差不多能实现的微信小程序蓝牙通信功能。
但是,由于我的知识水平有限,我急急忙忙的将小程序提交审核上线后,遇到了iOS设备无法正常连接蓝牙通信的问题。经过两天的调试,我终于解决了这个问题。原来,在iOS上,微信小程序无法通过MAC地址来连接设备,并且一些方法的执行顺序和时间间隔也需要遵循特定的规则。这个问题揭示了许多其他问题,不得不让我重新编写之前的代码。
实际上,对于初学者来说,理解蓝牙通信仍然是一件困难的事情。尤其是在我之前对蓝牙通信领域没有任何了解的情况下,完成一个项目确实需要一定的基础知识,不能急于求成。
废话少说,接下来我将简单说明如何在小程序中实现蓝牙连接并发送数据。
1、关闭蓝牙
可能很多人好奇,为什么第一步是关闭蓝牙呢?其实这个坑还是微信挖的(微信开发者社区:https://developers.weixin.qq.com/community/develop/doc/000a6287404ee8c64f8888fa056800),可以看链接提到的问题,具体不好说清楚,但是在做连接之前,最好还是先关闭一下蓝牙,因为这个操作不会花费太多时间。
wx.closeBluetoothAdapter({ success: function(res) { console.log("断开连接") } })
2、初始化蓝牙适配器
初始化蓝牙适配器,即在使用蓝牙功能之前先进行初始化,判断设备是否支持蓝牙并且蓝牙是否已开启,否则会报错。我们使用wx.openBluetoothAdapter来执行初始化操作。如果成功,则说明蓝牙功能正常;如果失败,则说明蓝牙不可用(可以弹出一个提示框告知用户)。
此处可以设置一个5秒的延迟函数,在5秒后检查是否找到了指定设备。如果未找到,则提示设备未找到,并停止蓝牙扫描。
wx.openBluetoothAdapter({ success: function(res) { //蓝牙正常 ble_isok=1; }, fail(res) { //蓝牙异常 }, complete(res) { //这里是蓝牙开启后要干的事情 if (ble_isok == 1) {//这里判断一下蓝牙正不正常,正常才继续执行 //下一步 } } })
这里,我们可以设定一个5s的延时执行函数,5s后看一下有没有找到我们的设备,如果没有找到,那就报设备没有找到,然后停止蓝牙。
fxble_isfound = 0; //初始化默认没有找到 fxble_startsearch(); //开始搜索周围的蓝牙设备,这里是下一个步骤 setTimeout(function () { if (fxble_isfound == 0) { // 代表搜不到设备 console.log("搜索不到设备"); wx.showToast({ title: "搜索不到设备", icon: "none", duration: 2000, mask: true //是否有透明蒙层,默认为false }); wx.stopBluetoothDevicesDiscovery({ success: function (res) { console.log("停止搜索"); } }); wx.closeBluetoothAdapter({ success: function (res) { console.log("断开连接"); } }); } }, 5000);
这样,我们就比较完美做好了初始化。
3、扫描周围的蓝牙设备,并通过一些方法来获取指定设备的serviceID
需要注意的是,Android和iOS的serviceID是不同的。Android使用MAC地址作为serviceID,而iOS使用UUID作为serviceID。而且这个UUID并不是固定的,不同设备可能不相同。之前我写的代码直接将serviceID写死了,肯定会出现兼容性问题。
这里对应你提到的fxble_startsearch()函数。由于我比较懒,没有修改ESP32上的代码来通过蓝牙广播中的特殊值判断设备,而是直接根据蓝牙设备的名称来判断。虽然这种方式并不完美,但在我的生产环境中已经足够。
wx.startBluetoothDevicesDiscovery({ services: [], success(res) { wx.onBluetoothDeviceFound(res => { var devices = res.devices; for (let i = 0; i < devices.length; i++) { if (devices[i].localName == "你要找的设备名字") { fxble_isfound = 1; // 标记设备找到了 deviceId = devices[i].deviceId; // 我这种方法的话其实这句可有可无的 console.log("find" + deviceId); wx.stopBluetoothDevicesDiscovery({ success: function(res) { console.log("停止搜索"); } }); wx.showToast({ title: '设备搜索成功', icon: 'loading', duration: 2000, mask: true // 是否有透明蒙层,默认为false }); fxble_connect(); // 接着下一个阶段 return 0; } } }); }, fail(res) { console.log(res); return 0; } });
4、连接蓝牙设备
这里我们先使用wx.createBLEConnection来连接到指定的蓝牙设备,然后wx.getBLEDeviceServices获取serviceID,notify_id,write_id,read_id(其实写数据的话,只要write_id就可以了)。
对应fxble_connect()函数。
wx.createBLEConnection({ deviceId: deviceId, // 获取到的 deviceID success(res) { console.log("设备连接成功!"); wx.showToast({ title: '设备连接成功', icon: 'loading', duration: 2000, mask: true // 是否有透明蒙层,默认为false }); wx.getBLEDeviceServices({ deviceId: deviceId, success: function(res) { console.log("设备加载成功"); wx.showToast({ title: '设备加载成功', icon: 'loading', duration: 2000, mask: true // 是否有透明蒙层,默认为false }); for (let i = 0; i < res.services.length; i++) { if (res.services[i].uuid.toUpperCase().indexOf(service_id) != -1) { service_id = res.services[i].uuid; break; } } console.log("Find Services" + service_id); wx.getBLEDeviceCharacteristics({ deviceId: deviceId, serviceId: service_id, success: function(res) { console.log("设备加载成功"); for (let i = 0; i < res.characteristics.length; i++) { let charc = res.characteristics[i]; if (charc.properties.notify) { notify_id = charc.uuid; } if (charc.properties.write) { write_id = charc.uuid; } if (charc.properties.write) { read_id = charc.uuid; } } console.log("Find notify_id" + notify_id + ", write_id" + write_id + ", read_id" + read_id); setTimeout(function() { fxble_write(); // 下一阶段,写数据 }, 1000); }, fail(res) { console.log(res); } }); }, fail(res) { console.log(res); return 0; } }); }, fail(res) { console.log(res); wx.showToast({ title: '设备连接失败', icon: 'none', duration: 2000, mask: true // 是否有透明蒙层,默认为false }); return 0; } });
5、写入数据
其实已经快接近尾声了,这里有个难点就是要把字符串转换一下对应的格式(字符串转byte),然后传入buffer,不能直接发送。
对应上面的fxble_write()。
let order = stringToBytes(writetext); let byteLength = order.byteLength; wx.writeBLECharacteristicValue({ deviceId: deviceId, serviceId: service_id, characteristicId: write_id, value: order.slice(0, 20), success: function(res) { // 成功 fxble_close(); // 下一阶段,关闭连接 }, fail(res) { console.log(res); wx.showToast({ title: '请求发送失败!', icon: 'none', duration: 2000, mask: true // 是否有透明蒙层,默认为false }); } }); // 字符串转byte function stringToBytes(str) { var strArray = new Uint8Array(str.length); for (var i = 0; i < str.length; i++) { strArray[i] = str.charCodeAt(i); } const array = new Uint8Array(strArray.length); strArray.forEach((item, index) => array[index] = item); return array.buffer; }
6、关闭连接
做完所有操作之后,就要关闭连接了,以免资源占用,常规操作了。文章来源:https://www.toymoban.com/article/594.html
wx.closeBLEConnection({ deviceId: deviceId, success(res) { console.log("断开连接成功"); }, fail(res) { console.log(res); console.log("断开连接失败"); } }); wx.closeBluetoothAdapter({ success: function (res) { console.log("断开成功"); } });
补充
连接成功后,我们可以通过task.write方法向蓝牙设备发送数据。需要注意的是,由于蓝牙通信的特性,一次最多只能发送20个字节的数据。如果要发送更大的数据量,需要分包发送。文章来源地址https://www.toymoban.com/article/594.html
task.write({ value: data, // 要发送的数据(最多20个字节) success: function(res) { console.log("数据发送成功"); // 数据发送成功后的操作 }, fail: function(err) { console.log("数据发送失败", err); // 数据发送失败后的处理 } });
到此这篇关于在微信小程序中如何通过蓝牙BLE连接ESP32并发送数据的文章就介绍到这了,更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!