0. 前言
这两天刚好了解了一下微信小程序的蓝牙功能。主要用于配网功能。发现微信的小程序蓝牙API已经封装的很好了。编程起来很方便。什么蓝牙知识都不懂的情况下,不到两天就晚上数据的收发了,剩下的就是数据帧格式的定义,当然这部分就不是本次博客的重点。
1. 准备硬件
这里我准备了CH341SER这个作为USB转串口。用sscom5.13.1 串口工具。由于我不太懂硬件开发。硬件部分都是由公司其他人开发的。我只是负责把环境搭建起来。然后负责我的微信小程序开发。
2. 开发小程序简单讲解
onLoad 这个一方面是用来获取当前连接的WiFi名称,减少用户输入,另一方面也是用来判断当前是否开启GPS功能。对于Android用户,是需要打开GPS蓝牙功能才能搜索到周围的蓝牙设备。
1 onLoad: function(options) { 2 var that = this; 3 wx.startWifi({ 4 success(res) { 5 console.log(res.errMsg) 6 wx.getConnectedWifi({ 7 success: function(res) { 8 console.log(res); 9 that.setData({ 10 ssid: res.wifi.SSID 11 }) 12 }, 13 fail: function(res) { 14 if(res.errCode == 12006){ 15 wx.showModal({ 16 title: \'请打开GPS定位\', 17 content: \'Android手机不打开GPS定位,无法搜索到蓝牙设备.\', 18 showCancel: false 19 }) 20 } 21 console.log(res); 22 } 23 }) 24 } 25 }) 26 },
搜索蓝牙设备相关代码
1 searchBleEvent: function(ret){ 2 var ssid = this.data.ssid; 3 var pass = this.data.pass; 4 console.log(ssid, pass); 5 if (util.isEmpty(ssid) || util.isEmpty(pass)) { 6 util.toastError(\'请输入WiFi名称及密码\'); 7 return; 8 } 9 this.initBLE(); 10 },
初始化蓝牙适配器
1 initBLE: function() { 2 this.printLog("启动蓝牙适配器, 蓝牙初始化") 3 var that = this; 4 wx.openBluetoothAdapter({ 5 success: function(res) { 6 console.log(res); 7 that.findBLE(); 8 }, 9 fail: function(res) { 10 util.toastError(\'请先打开蓝牙\'); 11 } 12 }) 13 },
定义搜索设备任务
1 findBLE: function() { 2 this.printLog("打开蓝牙成功.") 3 var that = this 4 wx.startBluetoothDevicesDiscovery({ 5 allowDuplicatesKey: false, 6 interval: 0, 7 success: function(res) { 8 wx.showLoading({ 9 title: \'正在搜索设备\', 10 }) 11 console.log(res); 12 delayTimer = setInterval(function(){ 13 that.discoveryBLE() //3.0 //这里的discovery需要多次调用 14 }, 1000); 15 setTimeout(function () { 16 if (isFound) { 17 return; 18 } else { 19 wx.hideLoading(); 20 console.log("搜索设备超时"); 21 wx.stopBluetoothDevicesDiscovery({ 22 success: function (res) { 23 console.log(\'连接蓝牙成功之后关闭蓝牙搜索\'); 24 } 25 }) 26 clearInterval(delayTimer) 27 wx.showModal({ 28 title: \'搜索设备超时\', 29 content: \'请检查蓝牙设备是否正常工作,Android手机请打开GPS定位.\', 30 showCancel: false 31 }) 32 util.toastError("搜索设备超时,请打开GPS定位,再搜索") 33 return 34 } 35 }, 15000); 36 }, 37 fail: function(res) { 38 that.printLog("蓝牙设备服务发现失败: " + res.errMsg); 39 } 40 }) 41 },
搜索设备回调
1 discoveryBLE: function() { 2 var that = this 3 wx.getBluetoothDevices({ 4 success: function(res) { 5 var list = res.devices; 6 console.log(list); 7 if(list.length <= 0){ 8 return ; 9 } 10 var devices = []; 11 for (var i = 0; i < list.length; i++) { 12 //that.data.inputValue:表示的是需要连接的蓝牙设备ID, 13 //简单点来说就是我想要连接这个蓝牙设备, 14 //所以我去遍历我搜索到的蓝牙设备中是否有这个ID 15 var name = list[i].name || list[i].localName; 16 if(util.isEmpty(name)){ 17 continue; 18 } 19 if(name.indexOf(\'JL\') >= 0 && list[i].RSSI != 0){ 20 console.log(list[i]); 21 devices.push(list[i]); 22 } 23 } 24 console.log(\'总共有\' + devices.length + "个设备需要设置") 25 if (devices.length <= 0) { 26 return; 27 } 28 that.connectBLE(devices); 29 }, 30 fail: function() { 31 util.toastError(\'搜索蓝牙设备失败\'); 32 } 33 }) 34 },
设置可以进行连接的设备
1 connectBLE: function(devices){ 2 this.printLog(\'总共有\' + devices.length + "个设备需要设置") 3 var that = this; 4 wx.hideLoading(); 5 isFound = true; 6 clearInterval(delayTimer); 7 wx.stopBluetoothDevicesDiscovery({ 8 success: function (res) { 9 that.printLog(\'连接蓝牙成功之后关闭蓝牙搜索\'); 10 } 11 }) 12 //两个的时候需要选择 13 var list = []; 14 for (var i = 0; i < devices.length; i++) { 15 var name = devices[i].name || devices[i].localName; 16 list.push(name + "[" + devices[i].deviceId + "]") 17 } 18 this.setData({ 19 deviceArray: list 20 }) 21 //默认选择 22 this.setData({ 23 currDeviceID: list[0] 24 }) 25 },
选择设备,然后点击对应的配网按钮,创建BLE连接
1 createBLE: function(deviceId){ 2 this.printLog("连接: [" + deviceId+"]"); 3 var that = this; 4 this.closeBLE(deviceId, function(res){ 5 console.log("预先关闭,再打开"); 6 setTimeout(function(){ 7 wx.createBLEConnection({ 8 deviceId: deviceId, 9 success: function (res) { 10 that.printLog("设备连接成功"); 11 that.getBLEServiceId(deviceId); 12 }, 13 fail: function (res) { 14 that.printLog("设备连接失败" + res.errMsg); 15 } 16 }) 17 }, 2000) 18 }); 19 },
获取蓝牙设备提供的服务UUID(本项目由于只会提供一个服务,就默认选择,实际项目,会自定义这个UUID的前缀或者后缀规则,定义多个不同的服务)
1 //获取服务UUID 2 getBLEServiceId: function(deviceId){ 3 this.printLog("获取设备[" + deviceId + "]服务列表") 4 var that = this; 5 wx.getBLEDeviceServices({ 6 deviceId: deviceId, 7 success: function(res) { 8 console.log(res); 9 var services = res.services; 10 if (services.length <= 0){ 11 that.printLog("未找到主服务列表") 12 return; 13 } 14 that.printLog(\'找到设备服务列表个数: \' + services.length); 15 if (services.length == 1){ 16 var service = services[0]; 17 that.printLog("服务UUID:["+service.uuid+"] Primary:" + service.isPrimary); 18 that.getBLECharactedId(deviceId, service.uuid); 19 }else{ //多个主服务 20 //TODO 21 } 22 }, 23 fail: function(res){ 24 that.printLog("获取设备服务列表失败" + res.errMsg); 25 } 26 }) 27 },
获取服务下的特征值(由于这个例子,是包含两个特征值,一个用于读,一个用于写,实际项目,跟上面的服务一样,要定义好特征量UUID的规则)
1 getBLECharactedId: function(deviceId, serviceId){ 2 this.printLog("获取设备特征值") 3 var that = this; 4 wx.getBLEDeviceCharacteristics({ 5 deviceId: deviceId, 6 serviceId: serviceId, 7 success: function(res) { 8 console.log(res); 9 //这里会获取到两个特征值,一个用来写,一个用来读 10 var chars = res.characteristics; 11 if(chars.length <= 0){ 12 that.printLog("未找到设备特征值") 13 return ; 14 } 15 that.printLog("找到设备特征值个数:" + chars.length); 16 if(chars.length == 2){ 17 for(var i=0; i<chars.length; i++){ 18 var char = chars[i]; 19 that.printLog("特征值[" + char.uuid + "]") 20 var prop = char.properties; 21 if(prop.notify == true){ 22 that.printLog("该特征值属性: Notify"); 23 that.recvBLECharacterNotice(deviceId, serviceId, char.uuid); 24 }else if(prop.write == true){ 25 that.printLog("该特征值属性: Write"); 26 that.sendBLECharacterNotice(deviceId, serviceId, char.uuid); 27 }else{ 28 that.printLog("该特征值属性: 其他"); 29 } 30 } 31 }else{ 32 //TODO 33 } 34 }, 35 fail: function(res){ 36 that.printLog("获取设备特征值失败") 37 } 38 }) 39 },
recv 接收设备发送过来数据
1 recvBLECharacterNotice: function(deviceId, serviceId, charId){ 2 //接收设置是否成功 3 this.printLog("注册Notice 回调函数"); 4 var that = this; 5 wx.notifyBLECharacteristicValueChange({ 6 deviceId: deviceId, 7 serviceId: serviceId, 8 characteristicId: charId, 9 state: true, //启用Notify功能 10 success: function(res) { 11 wx.onBLECharacteristicValueChange(function(res){ 12 console.log(res); 13 that.printLog("收到Notify数据: " + that.ab2hex(res.value)); 14 //关闭蓝牙 15 wx.showModal({ 16 title: \'配网成功\', 17 content: that.ab2hex(res.value), 18 showCancel: false 19 }) 20 }); 21 }, 22 fail: function(res){ 23 console.log(res); 24 that.printLog("特征值Notice 接收数据失败: " + res.errMsg); 25 } 26 }) 27 },
send 小程序发送数据到设备
1 sendBLECharacterNotice: function (deviceId, serviceId, charId){ 2 //发送ssid/pass 3 this.printLog("延时1秒后,发送SSID/PASS"); 4 var that = this; 5 var cell = { 6 "ssid": this.data.ssid, 7 "pass": this.data.pass 8 } 9 var buffer = this.string2buffer(JSON.stringify(cell)); 10 setTimeout(function(){ 11 wx.writeBLECharacteristicValue({ 12 deviceId: deviceId, 13 serviceId: serviceId, 14 characteristicId: charId, 15 value: buffer, 16 success: function(res) { 17 that.printLog("发送SSID/PASS 成功"); 18 }, 19 fail: function(res){ 20 console.log(res); 21 that.printLog("发送失败." + res.errMsg); 22 }, 23 complete: function(){ 24 25 } 26 }) 27 28 }, 1000); 29 },
手机端可以同时连接多个蓝牙设备,但是同一个蓝牙设备不能被多次连接,所以需要在每次连接前关闭BLE连接
1 closeBLE: function(deviceId, callback){ 2 var that = this; 3 wx.closeBLEConnection({ 4 deviceId: deviceId, 5 success: function(res) { 6 that.printLog("断开设备[" + deviceId + "]成功."); 7 console.log(res) 8 }, 9 fail: function(res){ 10 that.printLog("断开设备成功."); 11 }, 12 complete: callback 13 }) 14 },
说明:接收数据和发送数据时,注意BLE限制了发送数据包的大小,现在20byte。具体参考微信小程序官方文档: https://developers.weixin.qq.com/miniprogram/dev/api/device/bluetooth-ble/wx.writeBLECharacteristicValue.html
3. 蓝牙相关的所有JS代码
1 // pages/bluetoothconfig/bluetoothconfig.js 2 const util = require(\'../../utils/util.js\') 3 4 var delayTimer; //用来控制是否持续服务发现 5 var isFound = false; 6 7 Page({ 8 /** 9 * 页面的初始数据 10 */ 11 data: { 12 ssid: \'\', 13 pass: \'\', 14 logs: [], 15 deviceArray: [], 16 currDeviceID: \'请选择...\' 17 }, 18 onLoad: function(options) { 19 var that = this; 20 wx.startWifi({ 21 success(res) { 22 console.log(res.errMsg) 23 wx.getConnectedWifi({ 24 success: function(res) { 25 console.log(res); 26 that.setData({ 27 ssid: res.wifi.SSID 28 }) 29 }, 30 fail: function(res) { 31 if(res.errCode == 12006){ 32 wx.showModal({ 33 title: \'请打开GPS定位\', 34 content: \'Android手机不打开GPS定位,无法搜索到蓝牙设备.\', 35 showCancel: false 36 }) 37 } 38 console.log(res); 39 } 40 }) 41 } 42 }) 43 }, 44 bindPickerChange: function(ret){ 45 var array = this.data.deviceArray; 46 console.log(array[ret.detail.value]); 47 this.setData({ 48 currDeviceID: array[ret.detail.value] 49 }) 50 }, 51 searchBleEvent: function(ret){ 52 var ssid = this.data.ssid; 53 var pass = this.data.pass; 54 console.log(ssid, pass); 55 if (util.isEmpty(ssid) || util.isEmpty(pass)) { 56 util.toastError(\'请输入WiFi名称及密码\'); 57 return; 58 } 59 this.initBLE(); 60 }, 61 bleConfigEvent: function (ret) { 62 var deviceID = this.data.currDeviceID; 63 console.log("选中:" + deviceID); 64 if (util.isEmpty(deviceID) || deviceID == "请选择..."){ 65 util.toastError("请先搜索设备"); 66 return ; 67 } 68 var device = deviceID.split(\'[\'); 69 if(device.length <= 1){ 70 util.toastError("请先搜索设备"); 71 return ; 72 } 73 var id = device[device.length - 1].replace("]", ""); 74 console.log(id); 75 util.toastError("连接" + id); 76 this.createBLE(id); 77 }, 78 79 80 initBLE: function() { 81 this.printLog("启动蓝牙适配器, 蓝牙初始化") 82 var that = this; 83 wx.openBluetoothAdapter({ 84 success: function(res) { 85 console.log(res); 86 that.findBLE(); 87 }, 88 fail: function(res) { 89 util.toastError(\'请先打开蓝牙\'); 90 } 91 }) 92 }, 93 findBLE: function() { 94 this.printLog("打开蓝牙成功.") 95 var that = this 96 wx.startBluetoothDevicesDiscovery({ 97 allowDuplicatesKey: false, 98 interval: 0, 99 success: function(res) { 100 wx.showLoading({ 101 title: \'正在搜索设备\', 102 }) 103 console.log(res); 104 delayTimer = setInterval(function(){ 105 that.discoveryBLE() //3.0 //这里的discovery需要多次调用 106 }, 1000); 107 setTimeout(function () { 108 if (isFound) { 109 return; 110 } else { 111 wx.hideLoading(); 112 console.log("搜索设备超时"); 113
请发表评论