微信小程序开发-蓝牙功能开发
Posted wunaozai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微信小程序开发-蓝牙功能开发相关的知识,希望对你有一定的参考价值。
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 wx.stopBluetoothDevicesDiscovery( 114 success: function (res) 115 console.log(‘连接蓝牙成功之后关闭蓝牙搜索‘); 116 117 ) 118 clearInterval(delayTimer) 119 wx.showModal( 120 title: ‘搜索设备超时‘, 121 content: ‘请检查蓝牙设备是否正常工作,Android手机请打开GPS定位.‘, 122 showCancel: false 123 ) 124 util.toastError("搜索设备超时,请打开GPS定位,再搜索") 125 return 126 127 , 15000); 128 , 129 fail: function(res) 130 that.printLog("蓝牙设备服务发现失败: " + res.errMsg); 131 132 ) 133 , 134 discoveryBLE: function() 135 var that = this 136 wx.getBluetoothDevices( 137 success: function(res) 138 var list = res.devices; 139 console.log(list); 140 if(list.length <= 0) 141 return ; 142 143 var devices = []; 144 for (var i = 0; i < list.length; i++) 145 //that.data.inputValue:表示的是需要连接的蓝牙设备ID, 146 //简单点来说就是我想要连接这个蓝牙设备, 147 //所以我去遍历我搜索到的蓝牙设备中是否有这个ID 148 var name = list[i].name || list[i].localName; 149 if(util.isEmpty(name)) 150 continue; 151 152 if(name.indexOf(‘JL‘) >= 0 && list[i].RSSI != 0) 153 console.log(list[i]); 154 devices.push(list[i]); 155 156 157 console.log(‘总共有‘ + devices.length + "个设备需要设置") 158 if (devices.length <= 0) 159 return; 160 161 that.connectBLE(devices); 162 , 163 fail: function() 164 util.toastError(‘搜索蓝牙设备失败‘); 165 166 ) 167 , 168 connectBLE: function(devices) 169 this.printLog(‘总共有‘ + devices.length + "个设备需要设置") 170 var that = this; 171 wx.hideLoading(); 172 isFound = true; 173 clearInterval(delayTimer); 174 wx.stopBluetoothDevicesDiscovery( 175 success: function (res) 176 that.printLog(‘连接蓝牙成功之后关闭蓝牙搜索‘); 177 178 ) 179 //两个的时候需要选择 180 var list = []; 181 for (var i = 0; i < devices.length; i++) 182 var name = devices[i].name || devices[i].localName; 183 list.push(name + "[" + devices[i].deviceId + "]") 184 185 this.setData( 186 deviceArray: list 187 ) 188 //默认选择 189 this.setData( 190 currDeviceID: list[0] 191 ) 192 , 193 194 195 createBLE: function(deviceId) 196 this.printLog("连接: [" + deviceId+"]"); 197 var that = this; 198 this.closeBLE(deviceId, function(res) 199 console.log("预先关闭,再打开"); 200 setTimeout(function() 201 wx.createBLEConnection( 202 deviceId: deviceId, 203 success: function (res) 204 that.printLog("设备连接成功"); 205 that.getBLEServiceId(deviceId); 206 , 207 fail: function (res) 208 that.printLog("设备连接失败" + res.errMsg); 209 210 ) 211 , 2000) 212 ); 213 , 214 //获取服务UUID 215 getBLEServiceId: function(deviceId) 216 this.printLog("获取设备[" + deviceId + "]服务列表") 217 var that = this; 218 wx.getBLEDeviceServices( 219 deviceId: deviceId, 220 success: function(res) 221 console.log(res); 222 var services = res.services; 223 if (services.length <= 0) 224 that.printLog("未找到主服务列表") 225 return; 226 227 that.printLog(‘找到设备服务列表个数: ‘ + services.length); 228 if (services.length == 1) 229 var service = services[0]; 230 that.printLog("服务UUID:["+service.uuid+"] Primary:" + service.isPrimary); 231 that.getBLECharactedId(deviceId, service.uuid); 232 else //多个主服务 233 //TODO 234 235 , 236 fail: function(res) 237 that.printLog("获取设备服务列表失败" + res.errMsg); 238 239 ) 240 , 241 getBLECharactedId: function(deviceId, serviceId) 242 this.printLog("获取设备特征值") 243 var that = this; 244 wx.getBLEDeviceCharacteristics( 245 deviceId: deviceId, 246 serviceId: serviceId, 247 success: function(res) 248 console.log(res); 249 //这里会获取到两个特征值,一个用来写,一个用来读 250 var chars = res.characteristics; 251 if(chars.length <= 0) 252 that.printLog("未找到设备特征值") 253 return ; 254 255 that.printLog("找到设备特征值个数:" + chars.length); 256 if(chars.length == 2) 257 for(var i=0; i<chars.length; i++) 258 var char = chars[i]; 259 that.printLog("特征值[" + char.uuid + "]") 260 var prop = char.properties; 261 if(prop.notify == true) 262 that.printLog("该特征值属性: Notify"); 263 that.recvBLECharacterNotice(deviceId, serviceId, char.uuid); 264 else if(prop.write == true) 265 that.printLog("该特征值属性: Write"); 266 that.sendBLECharacterNotice(deviceId, serviceId, char.uuid); 267 else 268 that.printLog("该特征值属性: 其他"); 269 270 271 else 272 //TODO 273 274 , 275 fail: function(res) 276 that.printLog("获取设备特征值失败") 277 278 ) 279 , 280 recvBLECharacterNotice: function(deviceId, serviceId, charId) 281 //接收设置是否成功 282 this.printLog("注册Notice 回调函数"); 283 var that = this; 284 wx.notifyBLECharacteristicValueChange( 285 deviceId: deviceId, 286 serviceId: serviceId, 287 characteristicId: charId, 288 state: true, //启用Notify功能 289 success: function(res) 290 wx.onBLECharacteristicValueChange(function(res) 291 console.log(res); 292 that.printLog("收到Notify数据: " + that.ab2hex(res.value)); 293 //关闭蓝牙 294 wx.showModal( 295 title: ‘配网成功‘, 296 content: that.ab2hex(res.value), 297 showCancel: false 298 ) 299 ); 300 , 301 fail: function(res) 302 console.log(res); 303 that.printLog("特征值Notice 接收数据失败: " + res.errMsg); 304 305 ) 306 , 307 sendBLECharacterNotice: function (deviceId, serviceId, charId) 308 //发送ssid/pass 309 this.printLog("延时1秒后,发送SSID/PASS"); 310 var that = this; 311 var cell = 312 "ssid": this.data.ssid, 313 "pass": this.data.pass 314 315 var buffer = this.string2buffer(JSON.stringify(cell)); 316 setTimeout(function() 317 wx.writeBLECharacteristicValue( 318 deviceId: deviceId, 319 serviceId: serviceId, 320 characteristicId: charId, 321 value: buffer, 322 success: function(res) 323 that.printLog("发送SSID/PASS 成功"); 324 , 325 fail: function(res) 326 console.log(res); 327 that.printLog("发送失败." + res.errMsg); 328 , 329 complete: function() 330 331 332 ) 333 334 , 1000); 335 , 336 337 closeBLE: function(deviceId, callback) 338 var that = this; 339 wx.closeBLEConnection( 340 deviceId: deviceId, 341 success: function(res) 342 that.printLog("断开设备[" + deviceId + "]成功."); 343 console.log(res) 344 , 345 fail: function(res) 346 that.printLog("断开设备成功."); 347 , 348 complete: callback 349 ) 350 , 351 352 353 354 355 printLog: function(msg) 356 var logs = this.data.logs; 357 logs.push(msg); 358 this.setData( logs: logs ) 359 , 360 /** 361 * 将字符串转换成ArrayBufer 362 */ 363 string2buffer(str) 364 if (!str) return; 365 var val = ""; 366 for (var i = 0; i < str.length; i++) 367 val += str.charCodeAt(i).toString(16); 368 369 console.log(val); 370 str = val; 371 val = ""; 372 let length = str.length; 373 let index = 0; 374 let array = [] 375 while (index < length) 376 array.push(str.substring(index, index + 2)); 377 index = index + 2; 378 379 val = array.join(","); 380 // 将16进制转化为ArrayBuffer 381 return new Uint8Array(val.match(/[\\da-f]2/gi).map(function (h) 382 return parseInt(h, 16) 383 )).buffer 384 , 385 /** 386 * 将ArrayBuffer转换成字符串 387 */ 388 ab2hex(buffer) 389 var hexArr = Array.prototype.map.call( 390 new Uint8Array(buffer), 391 function (bit) 392 return (‘00‘ + bit.toString(16)).slice(-2) 393 394 ) 395 return hexArr.join(‘‘); 396 , 397 inputSSID: function(res) 398 var ssid = res.detail.value; 399 this.setData( 400 ssid: ssid 401 ) 402 , 403 inputPASS: function(res) 404 var pass = res.detail.value; 405 this.setData( 406 pass: pass 407 ) 408 409 410 )
4. 运行时截图
工具下载地址:
https://files.cnblogs.com/files/wunaozai/sscom5.13.1.zip
https://files.cnblogs.com/files/wunaozai/CH341SER_64bit.zip
参考资料:
https://www.cnblogs.com/guhonghao/p/9947144.html
本文地址:
https://www.cnblogs.com/wunaozai/p/11512874.html
以上是关于微信小程序开发-蓝牙功能开发的主要内容,如果未能解决你的问题,请参考以下文章