这个模块作了2周,找了不少资料文档,看示例看别人的demo,最后发现其实仍是得靠本身,不吐槽了,开正文。我实现的小程序模块自动链接(根据须要,可改手动),是在小程序初始化完成时开始自动调用执行。php
大体流程:小程序
一、 开启蓝牙适配
二、 获取蓝牙适配器状态,判断设备蓝牙是否可用。
三、 判断蓝牙适配器可用时开启扫描蓝牙设备和开启获取已链接的蓝牙设备
四、 若是开启扫描蓝牙设备失败5s后自动再次开启扫描
五、 开启扫描蓝牙设备成功后开启监听已扫描的设备
六、 若是已扫描到的新设备含FeiZhi名(我的产品须要)的设备则开始链接该设备
七、 开启获取已链接蓝牙设备开启获取设备成功后判断以获取的设备名包含FeiZhi(我的产品须要)字符串的设备则开始链接该设备
八、 开始获取已链接蓝牙设备没有成功获取到已链接的蓝牙设备5s后自动从新开启获取。
九、 开始链接某设备时中止扫描设备,中止循环获取已链接设备。
十、链接成功后中止扫描设备,中止循环获取已链接设备。微信小程序
点击查看:蓝牙模块链接流程图数组
一、app.js的onLaunch() 方法里中调用开启链接 this.startConnect();弹出提示框,开启适配,若是失败提示设备蓝牙不可用,同时开启蓝牙适配器状态监听微信
startConnect: function () { var that = this; wx.showLoading({ title: '开启蓝牙适配' }); wx.openBluetoothAdapter({ success: function (res) { console.log("初始化蓝牙适配器"); console.log(res); that.getBluetoothAdapterState(); }, fail: function (err) { console.log(err); wx.showToast({ title: '蓝牙初始化失败', icon: 'success', duration: 2000 }) setTimeout(function () { wx.hideToast() }, 2000) } }); wx.onBluetoothAdapterStateChange(function (res) { var available = res.available; if (available) { that.getBluetoothAdapterState(); } }) }
二、初始化蓝牙适配器成功,调用this.getBluetoothAdapterState() 获取本机蓝牙适配器状态,判断是否可用,available为false则由于用户没有开启系统蓝牙。同时判断程序尚未开始搜索蓝牙设备,调用this.startBluetoothDevicesDiscovery();开始扫描附近的蓝牙设备,同时调用this.getConnectedBluetoothDevices() 开启获取本机已配对的蓝牙设备。app
getBluetoothAdapterState: function () { var that = this; wx.getBluetoothAdapterState({ success: function (res) { var available = res.available, discovering = res.discovering; if (!available) { wx.showToast({ title: '设备没法开启蓝牙链接', icon: 'success', duration: 2000 }) setTimeout(function () { wx.hideToast() }, 2000) } else { if (!discovering) { that.startBluetoothDevicesDiscovery(); that.getConnectedBluetoothDevices(); } } } }) }
三、开始搜索蓝牙设备startBluetoothDevicesDiscovery() , 提示蓝牙搜索。ide
startBluetoothDevicesDiscovery: function () { var that = this; wx.showLoading({ title: '蓝牙搜索' }); wx.startBluetoothDevicesDiscovery({ services: [], allowDuplicatesKey: false, success: function (res) { if (!res.isDiscovering) { that.getBluetoothAdapterState(); } else { that.onBluetoothDeviceFound(); } }, fail: function (err) { console.log(err); } }); }
四、获取已配对的蓝牙设备。此方法特别说明参数services(Array)是必填的,可是官方示例中以及各类坑爹demo里从没见过有谁填写,可是不填写这个属性此方法没法获取到任何已配对设备。若是要调用此方法则是须要链接特定设备,而且知道该设备的一个主服务serviceId。若是未知能够先手动链接一次想要链接的设备,而后获取service列表,记录属性primary为true的值至少一个。oop
getConnectedBluetoothDevices: function () { var that = this; wx.getConnectedBluetoothDevices({ services: [that.serviceId], success: function (res) { console.log("获取处于链接状态的设备", res); var devices = res['devices'], flag = false, index = 0, conDevList = []; devices.forEach(function (value, index, array) { if (value['name'].indexOf('FeiZhi') != -1) { // 若是存在包含FeiZhi字段的设备 flag = true; index += 1; conDevList.push(value['deviceId']); that.deviceId = value['deviceId']; return; } }); if (flag) { this.connectDeviceIndex = 0; that.loopConnect(conDevList); } else { if (!this.getConnectedTimer) { that.getConnectedTimer = setTimeout(function () { that.getConnectedBluetoothDevices(); }, 5000); } } }, fail: function (err) { if (!this.getConnectedTimer) { that.getConnectedTimer = setTimeout(function () { that.getConnectedBluetoothDevices(); }, 5000); } } }); }
五、开启蓝牙搜索功能失败,则回到第2步从新检查蓝牙是适配器是否可用,开启蓝牙搜索功能成功后开启发现附近蓝牙设备事件监听。this.onBluetoothDeviceFound()学习
onBluetoothDeviceFound: function () { var that = this; console.log('onBluetoothDeviceFound'); wx.onBluetoothDeviceFound(function (res) { console.log('new device list has founded') console.log(res); if (res.devices[0]) { var name = res.devices[0]['name']; if (name != '') { if (name.indexOf('FeiZhi') != -1) { var deviceId = res.devices[0]['deviceId']; that.deviceId = deviceId; console.log(that.deviceId); that.startConnectDevices(); } } } }) }
此方法可自定义过滤一些无效的蓝牙设备好比name为空的,我的产品开发中须要过滤devices name 不含有FeiZhi字符串的设备。this
六、在第5步中发现了某个想配对的设备,则获取到该设备的deviceId,而后开始配对该设备 this.startConnectDevices()。
startConnectDevices: function (ltype, array) { var that = this; clearTimeout(that.getConnectedTimer); that.getConnectedTimer = null; clearTimeout(that.discoveryDevicesTimer); that.stopBluetoothDevicesDiscovery(); this.isConnectting = true; wx.createBLEConnection({ deviceId: that.deviceId, success: function (res) { if (res.errCode == 0) { setTimeout(function () { that.getService(that.deviceId); }, 5000) } }, fail: function (err) { console.log('链接失败:', err); if (ltype == 'loop') { that.connectDeviceIndex += 1; that.loopConnect(array); } else { that.startBluetoothDevicesDiscovery(); that.getConnectedBluetoothDevices(); } }, complete: function () { console.log('complete connect devices'); this.isConnectting = false; } }); }
开启链接后为了不出现冲突,一旦开启链接则终止扫描附近蓝牙设备,终止读取本机已配对设备。
getService: function (deviceId) { var that = this; // 监听蓝牙链接 wx.onBLEConnectionStateChange(function (res) { console.log(res); }); // 获取蓝牙设备service值 wx.getBLEDeviceServices({ deviceId: deviceId, success: function (res) { that.getCharacter(deviceId, res.services); } }) }
八、读取服务的特征值。
getCharacter: function (deviceId, services) { var that = this; services.forEach(function (value, index, array) { if (value == that.serviceId) { that.serviceId = array[index]; } }); wx.getBLEDeviceCharacteristics({ deviceId: deviceId, serviceId: that.serviceId, success: function (res) { that.writeBLECharacteristicValue(deviceId, that.serviceId, that.characterId_write); that.openNotifyService(deviceId, that.serviceId, that.characterId_read); }, fail: function (err) { console.log(err); }, complete: function () { console.log('complete'); } }) }
九、若是扫描到的设备中没有想要链接的设备,能够尝试使用系统蓝牙手动配对,而后再小程序中调用getConnectedBluetoothDevices() 获取本机已配对的蓝牙设备,而后过滤设备(可能获取多个已配对的蓝牙设备)。将以获取的蓝牙设备deviceId放入到一个数组中调用自定义方法this.loopConnect(); 思路:经过递归调用获取已配对蓝牙设备的deviceId,若是获取到了就去链接,devicesId[x] 为空说明上传调用getConnectedBluetoothDevices()时获取到的已配对设备所有链接失败了。则开启从新获取已配对蓝牙设备,并开启扫描附近蓝牙设备。
loopConnect: function (devicesId) { var that = this; var listLen = devicesId.length; if (devicesId[this.connectDeviceIndex]) { this.deviceId = devicesId[this.connectDeviceIndex]; this.startConnectDevices('loop', devicesId); } else { console.log('已配对的设备小程序蓝牙链接失败'); that.startBluetoothDevicesDiscovery(); that.getConnectedBluetoothDevices(); } }
十、**startConnectDevices('loop', array)方法,是当获取已配对蓝牙设备进行链接时这样调用。其中的处理逻辑上文已经贴出,意思就是在链接失败后fail方法里累加一个全局变量,而后回调loopConnect(array)方法。
**十一、手动链接,上文介绍的方法是为了直接自动链接,若是不须要自动链接,可在使用方法getBluetoothDevices() 将会获取到已扫描到的蓝牙设备的列表,能够作个页面显示出设备名,点击该设备开始链接。
一、that.serviceId 是在初始化时设置的,因为对须要链接设备的主服务serivceId和各类特征值都是已知的所以能够这样作。若是不可知能够作一个扫描方法本身检查特征值的用途。
二、 链接成功后的writeBLECharacteristicValue和openNotifyService操做须要注意,若是同时开启这两项操做要先调用wirte再开启notify(缘由未知,我的心得)。
三、经人提醒还能够再完善一下在onBlueToothAdapterStateChange()**能够监听蓝牙适配器状态,以此判断链接过程当中或链接后用户开关了设备蓝牙,若是判断到关了蓝牙提示请开启,若是监听到开启了,就从新回到第1步。
最后本文属于我的开发者的一点总结,欢迎留言指导讨论,也能够加入微信小程序联盟群一块儿探讨学习。