最近的项目是做一个通过蓝牙控制开关的小程序,看了很多写的很详细全面的博客,不过自己还是有点混混沌沌的。现在自己总结一下小程序运行代码的大致流程,也能整理一下思路。
一、蓝牙的介绍:
蓝牙的类型
小程序提供的API都是针对“BLE低功耗蓝牙 ”,这种蓝牙有区别与我们手机的蓝牙功能,特点是特点就是耗电极低、传输速度更快,常用在对续航要求较高且只需小数据量传输的各种智能电子产品中。
蓝牙的工作模式
根据低功耗蓝牙协议为设备定义了若干角色,比较重要的角色便是“外围设备”和“中心设备”。
外围设备是用来提供数据,通过不停的向外广播数据,使中心设备在扫描的时候能够发现自己并连接。中心设备扫描到外围设备可以与之建立连接,然后使用外围设备提供的服务(Service),利用外围设备提供的数据进行处理或展示等。而我们用到的小程序接口默认设定手机为中心设备。
通信协议
两个蓝牙设备建立连接后,双方的数据交互式基于一个叫做GTAA(Generic Attribute Profile)的规范,根据该规范可以定义出不同的配置文件(Profile)描述该蓝牙设备提供的服务。
配置文件(Profile)、服务(Service)、特性(ChriCharacteristic)是通信过程中比较重要的三个概念:
Profile是被蓝牙标准预先定义的一些Service的集合,一个蓝牙可以支持多种Profile,当两个蓝牙设备支持相同的Profile,便能兼容。
Service是一个功能的合集,一个设备可以提供多个服务,而每一个service都有一个16bit或128bit的UUID作为唯一识别。蓝牙的UUID共用了一个基本的UUID:0x0000xxxx-0000-1000-8000-00805F9B34FB。所以16 bit 的 UUID 实际上是 128 bit 的缩短版,代替xxxx部分,接收方收到后会补上蓝牙的 UUID 基数,目的是为了提高传输效率。
Characteristic是存在于Service中的独立数据项,由一个 value 和多个描述特性的 Desciptor 组成。同样有一个16bit或128bit的UUID作为标识。而设备之间的交互便是通过对value的读写完成的。我们通过蓝牙发送给数据给外围设备就是往Characteristic的value字段写入数据;外围设备发送数据给手机就是监听这些 Charateristic 中的 Value 字段有没有变化,如果发生了变化,手机的接口就会收到一个监听的回调。
二、搜索设备
检查蓝牙是否打开
首先利用wx.openBluetoothAdapter(OBJECT)初始化蓝牙模块,在用户蓝牙开关未开启或者手机不支持蓝牙功能的情况下,调用wx.openBluetoothAdapter会返回错误,表示手机蓝牙功能不可用;
在数据传输后调用wx.closeBluetoothAdapter(OBJECT)来使关闭蓝牙模块使其处于未初始化的状态,断开所有已经建立的连接并释放系统资源。
可以用wx.onBluetoothAdapterStateChange接口看蓝牙适配器的状态,avavaliable属性是表示蓝牙适配器是否可用,discovering属性是表示蓝牙适配器是否处在搜索状态。
wx.openBluetoothAdapter({ success: function (res) { console.log("初始化蓝牙适配器成功") wx.onBluetoothAdapterStateChange(function (res) { console.log("蓝牙适配器状态变化", res) }) })
开启蓝牙搜索
调用wx.startBluetoothDevicesDiscovery接口开始搜索附近的蓝牙外围设备。
该操作比较耗费系统资源,在搜索并连接设备后应该调用wx.stopBluetoothDevicesDiscovery接口停止搜索。
wx.startBluetoothDevicesDiscovery({ success: function (res) { console.log("开始搜索附近蓝牙设备") console.log(res) } })
wx.onBluetoothDeviceFound(function (res) { var devices = res.devices; console.log(devices) temp = temp.concat(devices) console.log("temp:", temp); that.setData({ devices: temp }) console.log(\'发现新蓝牙设备\') console.log(\'设备id\' + devices[0].deviceId) console.log(\'设备name\' + devices[0].name) })
三、连接设备
调用wx.createBLEConnection接口通过传入deviceId连接设备
wx.createBLEConnection({ deviceId: id, success: function (res) { wx.hideLoading() wx.showToast({ title: \'连接成功\', icon: \'success\', duration: 1000 })
})
四、数据交互
连接后就可以调用wx.getBLEDeviceServices获取设备的服务列表和wx.getBLEDeviceCharacteristics获取特征值
wx.getBLEDeviceServices({ deviceId:id,//传入连接设备的ID success(res) { console.log(\'device services:\', res.services); var services = res.services; for(var i=0;i<services.length;i++){ var service = services[i]; wx.getBLEDeviceCharacteristics({ deviceId: id, serviceId: service.uuid, success: function(res) { console.log(service,res); }, }) } } })
用支持notify的设备特征值调用wx.notifyBLECharacteristicValueChange接口,接收设备推送的notification。
wx.notifyBLECharacteristicValueChanged({ deviceId: that.data.connectedDeviceId, serviceId: serviceId, characteristicId: characteristicId, success: function (res) { console.log("启用notify"); callback(\'open\'); }, fail: (res) =>{ console.log("启用notify失败:",res); } })
用支持write的设备特征值调用wx.writeBLECharacteristicValue接口写入数据。
wx.writeBLECharacteristicValue({ deviceId: id, serviceId: serviceId, characteristicId: characteristicId, value: data,//写入数据 success: function(res) { console.log(res); console.log(\'writeBLECharacteristicValue success\', res.errMsg); }, fail: function(res) { console.log(res); } })