从蓝牙4.0开始包含了两个标准,传统蓝牙(Classic Buletooth)和低功耗蓝牙(Bluetooth Low Energy)以下简称 BLE。
传统蓝牙支持音频和数据两大类协议,所以更适合音乐等数据量大的应用场景;传统蓝牙有3个功率级别,Class1、Class2、Class3,分别支持100m、10m、1m的传输距离。
BLE 更适用于实时性比较高,数据传输量小的场景,如遥控灯;BLE 无功率级别,一般发送功率在7dBm,一般在空旷距离,达到20m应该是没有问题的。
BLE 的基本概念
1 GATT
说到 BLE 就不得不提一下 GATT (Generic Attribute Profile) 通用属性协议。GATT是一个在蓝牙连接之上的发送和接收很短的数据段的通用规范,GATT 按照层级定义了三个概念:Service、Characteristic 和描述 Descriptor,这些合起来称为一个 Profile。
2 GAP
GAP(Generic Access Profile)通用访问协议,用来控制设备连接和广播。GAP 使你的设备被其他设备可见,并决定了你的设备是否可以或者怎样与合同设备进行交互。
在 GAP 中外围设备通过两种方式向外广播数据: Advertising Data Payload(广播数据)和 Scan Response Data Payload(扫描回复),每种数据最长可以包含 31 byte。这里广播数据是必需的,因为外设必需不停的向外广播,让中心设备知道它的存在。扫描回复是可选的,中心设备可以向外设请求扫描回复,这里包含一些设备额外的信息,例如设备的名字。
3 Service
Characteristic 的集合。比如某个 Service 可能叫“电量管理”,它可能包含多个Characteristics。
4 Characteristic
Characteristic 可以理解为一个数据类型,包含了一个 value 和零至多个对该 value 的描述。
5 Descriptor (可选)
对 Characteristic 的描述,例如范围、计量单位等。
6 UUID
统一识别码,service 和 characteristic 都需要一个唯一的 uuid 来标识, 它是 128bit 的值。
如何在小程序中使用,第一步先开启蓝牙配器。
wx.closeBluetoothAdapter({
complete: function(res) {
console.log(res)
wx.openBluetoothAdapter({
success: function(res) {
console.log(res)
wx.getBluetoothAdapterState({
success: function(res) {
console.log(res)
}
})
第二步 开始搜索附近的蓝牙设备。
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: false,
success: function(res) {
console.log(res)
that.setData({
searching: true,
devicesList: []
})
}
})
第三步 获取附近的蓝牙设备
wx.onBluetoothDeviceFound(function(devices) {
var isnotexist = true
if (devices.devices) {
if (devices.devices[0].advertisData) {
devices.devices[0].advertisData = app.buf2hex(devices.devices[0].advertisData)
} else {
devices.devices[0].advertisData = ''
}
console.log(devices.devices[0])
for (var i = 0; i < that.data.devicesList.length; i++) {
if (devices.devices[0].deviceId == that.data.devicesList[i].deviceId) {
isnotexist = false
}
}
that.data.devicesList.push(devices.devices[0])
}
that.setData({
devicesList: that.data.devicesList
})
})
}
第四步 连接蓝牙
deviceId 是对应蓝牙设备信息的deviceId,系统是根据这个蓝牙的deviceId,去找到这个蓝牙并建立连接。在前面第三步中获取的是所有搜索到蓝牙设备列表,这个是对应的某一蓝牙设备的deviceId,注意: 一个蓝牙有多个服务,一个服务有多个特征值,如果我们想对蓝牙进行写、读操作,那么我们至少需要3个参数。
1、蓝牙的deviceId
2、蓝牙的某一服务的 uuid
3、蓝牙某一服务下的某一特征值的uuid
我们至少需要这3个,才能对蓝牙的某一个功能进行操作。
Connect: function(e) {
var that = this
var advertisData, name
for (var i = 0; i < that.data.devicesList.length; i++) {
if (e.currentTarget.id == that.data.devicesList[i].deviceId) {
name = that.data.devicesList[i].name
advertisData = that.data.devicesList[i].advertisData
}
}
第五步 获取蓝牙的服务
蓝牙的服务是由对应蓝牙设备设定的,这个是属于硬件的设置。一个蓝牙可以开启多个服务,我们根据对应的服务操作相对应的功能。开启主服务isPrimary的值为true,主服务是为了与其他服务区分开来,注意: 我们这里是用对应的服务uuid去区分服务的。
wx.getBLEDeviceServices({
deviceId: that.data.connectedDeviceId,
success: function(res) {
var all_UUID = res.services;
var index_uuid = -1;
var UUID_lenght = all_UUID.length;
/* 遍历服务数组 */
for (var index = 0; index < UUID_lenght; index++) {
var ergodic_UUID = all_UUID[index].uuid; //取出服务里面的UUID
//console.log('接收到ergodic_UUID数据:' + ergodic_UUID)
if (ergodic_UUID == '00001910-0000-1000-8000-00805F9B34FB') {
index_uuid = index;
};
};
第六步 获取蓝牙对应服务的特征值
每一个不同的蓝牙服务,对应的特征值也不同,当该服务的特征值为true时,我们才与之进行对应的操作,一般我们通过判断 read 属性是否为真,便可以知道能不能通过该服务读取到蓝牙的值,当write为真时,我们便可以对蓝牙设备进行写数据操作。
wx.getBLEDeviceCharacteristics({
deviceId: options.connectedDeviceId,
serviceId: res.services[index_uuid].uuid,
success: function(res) {
that.setData({
characteristics: res.characteristics,
})
wx.notifyBLECharacteristicValueChange({
state: true,
deviceId: options.connectedDeviceId,
serviceId: that.data.serviceId,
characteristicId: that.data.characteristics[1].uuid,
success: function(res) {
console.log('启用notify成功')
},
fail(res) {
console.log(res)
}
})
}
})
}
第七步 获取蓝牙的返回数据
我们在与蓝牙进行数据交互时,蓝牙也常常需要对我们传过去的参数进行相对应的回参,也就是对我们传过去的信息进行回复,这样我们才知道写数据操作有没有成功,我们需要启用低功耗蓝牙设备特征值变化时的notify 功能,用来监听数据的返回。
wx.onBLECharacteristicValueChange(function(res) {
console.log('接收到数据:' + app.buf2string(res.value))
var time = that.getNowTime()
that.setData({
receiveText: that.data.receiveText + time + (app.buf2string(res.value))
})
})
},
接下来测试,我们编译w800的蓝牙程序,串口命令打开蓝牙功能,蓝牙服务:
使用微信开发者工具,导入微信小程序源码,导入时选自己的测试号。手机微信扫描进入测试调试。
找到WM开头的,就是我们开发板产生的蓝牙,连接。
连接成功,可以收到W800发送过来的实时数据。
点击发送可以发数据到开发板: