微信小程序蓝牙开发
2017-09-01 17:37
501 查看
微信小程序蓝牙开发
1、蓝牙模块(小程序蓝牙模块每一个操作都是通过封装好的API函数来 调用该功能,从成功回调函数里面得到需要的数据)蓝牙连接过程:
1)初始化蓝牙适配器,执行初始化操作
// 打开蓝牙 openBluetooth:function () { var that = this; // 初始化蓝牙适配器 wx.openBluetoothAdapter({ success:function (res) { console.log(res.errMsg); wx.showToast({ title:"初始化成功", duration:1000 }); }, fail:function (res) { wx.showToast({ title:"请打开手机蓝牙", duration:2000 }); } }) // 获取本机蓝牙适配器状态 wx.getBluetoothAdapterState({ success:function(res) { console.log("适配器状态:",res.errMsg) } }) wx.onBluetoothAdapterStateChange(function(res) { console.log(`adapterState changed, now is`, res) }) },
同时,调用wx.getBluetoothAdapterState(OBJECT),获取本机蓝牙适配器状态;调用wx.onBluetoothAdapterStateChange(CALLBACK)监听蓝牙适配器状态变化事件。
2)开始搜索设备
wx.onBluetoothAdapterStateChange(CALLBACK)
开始搜寻附近的蓝牙外围设备。注意,该操作比较耗费系统资源,请在搜索并连接到设备后调用 stop 方法停止搜索。
// 以我自己蓝牙设备为例,主服务的 UUID 是 FEE9。传入这个参数,只搜索主服务 UUID 为 FEE9 的设备,该参数也可以不设置
wx.getBluetoothDevices(OBJECT)获取所有已发现的蓝牙设备,包括已经和本机 处于连接状态的设备
已发现的设备在回调函数中,res.devices数组中。然后将数组保存在data中,通过渲染数据将发现的设备显示在页面上。
wx.startBluetoothDevicesDiscovery({ services: ['FEE9'], success: function (res) { console.log(res) setTimeout(function () { wx.getBluetoothDevices({ success: func 4000 tion (res) { console.log(res.devices) } }) },3000) } })
3)连接设备
wx.createBLEConnection(OBJECT) 根据deviceID连接低功耗蓝牙设备
e为当前元素(需要连接的设备)属性,通过其携带的deviceId参数执行连接
connectTo: function (e) { var that = this; // console.log(e); wx.createBLEConnection({ deviceId: e.currentTarget.id, success: function (res) { console.log("连接成功"); //将连接的deviceID暴露出来,以供后面使用 that.setData({ connectedDeviceId: e.currentTarget.id, }) //将已连接设备的deviceID作为携带参数,进入test页面 wx.navigateTo({ Url: ‘../test?deviceId=’+that.data.connectedDeviceId, Complete:function (rew){ Console.log(res) } }) //连接成功后执行停止搜索方法(性能优化) wx.stopBluetoothDevicesDiscovery({ sucess:function (res) { Console.log(res) } }) } }) }
//连接成功后同时写一个监听函数
监听低功耗蓝牙连接的错误事件,包括设备丢失,连接异常断开等等。
wx.onBLEConnectionStateChange(function(res) { // 该方法回调中可以用于处理连接意外断开等异常情况 console.log(`device ${res.deviceId} state has changed, connected: ${res.connected}`) })
4)页面间数据传递
页面间传递数据的坑:
我这里蓝牙数据量非常大并且需要实时传递。
开始是在蓝牙设备配对页面完成所有蓝牙操作,在该页面接收数据。问题出现在,蓝牙设备配对页面中接收到的数据无法实时传递到第二页面。
小程序中每个页面下都是独立的js文件,不互通,可以通过定义全局变量接收参数并传递。但是由于蓝牙设备 数据传输量巨大,并且需要达到实时传递的效果,通过定义全局变量方法,无法实现实时实时传递目的。
解决方案:设备连接上后,将deviceID作为携带参数,直接跳转到第二页面,在第二页面上完成后续的获取serviceID和特征值,完成蓝牙后续左右操作。
通过wx.navigateTo()方法携带的参数只能在onLoad函数中获取;
wx.getBLEDeviceServices(OBJECT)获取蓝牙设备所有service(服务)
wx.getBLEDeviceCharacteristics(OBJECT)获取蓝牙设备所有 characteristic(特征值)
通过deviceID获得serviceID。(安卓和iOS不同,安卓为小写。后续API更新将统一为大写),下一步,通过一个延迟函数,等获取serviceID后再获取Characteristics(特征值),根据需求分别获取读取通道和写入通道特征值,将以上获取的值赋值给data中的变量。
注意:serviceId和特征值uuid 都是事先知道的,然后在获取的值中匹配。很多小伙伴都在这里遇到问题,如果你不知道serviceID 和 uuid的话,我只能说你去找硬件要了。。。
getBLEDeviceServices:function () { var that = this; // 获取蓝牙设备所有service(服务) wx.getBLEDeviceServices({ deviceId:that.data.connectedDeviceId, success:function (res) { for (var i = 0; i < res.services.length; i++) { // 安卓和iOS不同,安卓为小写。后续API更新将统一为大写 //判断是否为需要的UUID if (res.services[i].uuid.indexOf("fee9") > 0 || res.services[i].uuid.indexOf("FEE9") > 0) { that.setData({ serviceId : res.services[i].uuid }) } } } }) // 获取蓝牙设备所有characteristic(特征值) setTimeout(function (){ wx.getBLEDeviceCharacteristics({ deviceId:that.data.connectedDeviceId, serviceId: that.data.serviceId, success:function (res) { for (var i = 0; i < res.characteristics.length; i++) { if(res.characteristics[i].uuid.indexOf('129601') > 0 ) { that.setData({ readCharacteristic:res.characteristics[i].uuid }) } if (res.characteristics[i].uuid.indexOf('129600') > 0) { that.setData({ writeCharacteristic : res.characteristics[i].uuid }) } } } }) },500) }
到此,蓝牙设备连接完毕。下面进行读写命令操作
5)读写监听数据
首先,wx.notifyBLECharacteristicValueChange(OBJECT)启用低功耗蓝牙设备特征值变化时的 notify 功能。注意:必须设备的特征值支持notify才可以成功调用,具体参照 characteristic 的 properties 属性
另外,必须先启用notify才能监听到设备 characteristicValueChange 事件。characteristieValueChange事件只调用一次即可,切忌像小程序API中每个写入函数都调用characteristieValueChange事件(此处为坑)
蓝牙API中提供了wx.readBLECharacteristicValue(OBJECT)方法和wx.writeBLEChatracteristicValue(OBJECT)方法。但是,经过讨论和实践,read方法没有作用,读取到的数据都在characteristieValueChange函数中获取。
// 开启notify通道 notifyBLECharacteristicValueChange:function () { var that = this; wx.notifyBLECharacteristicValueChange({ state: true, // 启用 notify 功能 // 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取 deviceId: that.data.connectedDeviceId, // 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取 serviceId: that.data.serviceId, // 这里的 characteristicId 需要在上面的 getBLEDeviceCharacteristics 接口中获取 characteristicId: that.data.readCharacteristic, success: function (res) { // 安卓bug,加个延迟 setTimeout(function () { that.onWrite(); },500); // IOS // that.onWrite(); } }) wx.onBLECharacteristicValueChange(function(res) { //此处为坑,vConsole 无法打印出 ArrayBuffer 类型数据。需要将监听到的数据转换成字符串,才能被后面使用。 let hex = Array.prototype.map.call(new Uint8Array(res.value), x => ('00' + x.toString(16)).slice(-2)).join(''); that.setData({ returnValue:hex }) }) }
写入方法:
onWrite:function () { var that = this; // wirte里面不要写监听函数 // 向蓝牙设备发送一个0x00的16进制数据 let buffer = new ArrayBuffer(5); let dataView = new DataView(buffer); dataView.setUint8(0,0x0f) dataView.setUint8(1,0x0f) dataView.setUint8(2,0x57) dataView.setUint8(3,0x46) dataView.setUint8(4,0x78) //可以通过getUint8(0)的方法取到setUint8()的值 // console.log(dataView.getUint8(0)) wx.writeBLECharacteristicValue({ // 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取 deviceId: that.data.connectedDeviceId, // 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取 serviceId: that.data.serviceId, // 这里的 characteristicId 需要在上面的 getBLEDeviceCharacteristics 接口中获取 characteristicId: that.data.writeCharacteristic, // 这里的value是ArrayBuffer类型 value: buffer, success: function (res) { console.log(res); }, fail: function (res) { console.log(res); } }) }
写入方法的坑:
// 向蓝牙设备发送一个0x00的16进制数据
let buffer = new ArrayBuffer(1)
let dataView = new DataView(buffer)
dataView.setUint8(0, 0)
此处用到的是JavaScript中ArratBuffer类型化数组 数据类型。
首先将写入命令转换成0x00类型的16进制数据;
Buffer = new ArrayBuffer(1)中,1为开辟的内存空间的数量,根据命令的个数填入所需要的内存空间。
dataView.setUint8(0,0);第一个参数为下标从0开始,第二个参数为命令。循环命令的长度,将所有命令setUint8写入。可以通过dataView.getUint8()
下图为其中一条创建新key命令,如果将命令赋值给变量的时候,此时数据类型就会改变,因此只能对每个写入命令单独写一个函数调用write方法。
安卓手机连接蓝牙的坑:
安卓手机在连接上,notify函数中会报一个10008(其余所有系统上报的异常)的错误码,此处可以理解为小程序蓝牙自身的bug。
解决方法:在notify的成功回调函数里面调用写入方法的时候,给写入方法加一个延迟函数,调用,就正常了。
还有一种情况,可以在notify的失败回调函数里继续执行下一步操作,也可能会正常操作。
该问题有可能在后续API更新后得以解决。
欢迎大家指导,交流!
相关文章推荐
- 微信小程序--蓝牙连接开发总结
- 微信小程序蓝牙功能开发
- FE - 微信小程序 - 蓝牙 BLE 开发调研与使用
- 微信小程序蓝牙通讯开发
- 微信小程序蓝牙功能开发
- 微信小程序蓝牙功能开发
- 微信小程序---蓝牙连接开发总结
- FE - 微信小程序 - 蓝牙 BLE 开发调研与使用
- 微信小程序蓝牙功能开发流程详解和思维导图--shewei
- 微信小程序--蓝牙连接开发总结
- 微信小程序支付功能 C# .NET开发
- 微信小程序开发之大坑记之post请求
- 微信小程序开发之大转盘 仿天猫超市抽奖
- 微信小程序自定义tabBar组件开发
- 哪些领域适合开发微信小程序
- 微信小程序开发之吐司toast(消息提示框)
- 微信小程序开发(3) 热门电影
- 微信小程序开发实例
- 详解微信小程序开发
- 微信小程序 开发之快递查询功能的实现