微信小程序开发-蓝牙功能开发

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 )
View Code

 

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

以上是关于微信小程序开发-蓝牙功能开发的主要内容,如果未能解决你的问题,请参考以下文章

如何开发微信小程序数据库

微信小程序需要啥知识

简单处理下微信开发者工具开发微信小程序网络请求封装

微信小程序开发和HTML5开发,css3开发的区别

开发微信小程序需要注意些啥问题

怎样用php开发微信小程序的后端?