前言
书接前文,上篇文章我们主要介绍了初始化蓝牙、以及搜索附近蓝牙设备以及展示搜索到的蓝牙设备,但是我们在真实的业务场景中,肯定是需要将搜到的设备“用”起来的,所以本文我们就介绍一下如何使用小程序连接蓝牙设备以及后续的操作。
进行蓝牙连接
连接蓝牙设备主要使用wx.createBLEConnection
方法,若小程序在之前已有搜索过某个蓝牙设备,并成功建立连接,可直接传入之前搜索获取的 deviceId 直接尝试连接该设备,无需再次进行搜索操作。
实现代码如下:
//通过蓝牙设备的id进行蓝牙连接
const createBLEConnection = () => {
wx.createBLEConnection({
deviceId: ConnectedDeviceRelated.deviceId,
success: function (res) {
wx.stopBluetoothDevicesDiscovery({
success: function (res) {
console.log('连接成功,关闭蓝牙搜索')
ConnectedDeviceRelated.isSearchBluetooth_detectionBoard = false
}
})
getBLEDeviceServices()
},
fail: function (res) {
//连接失败后重连
if (that.data.isconnect == 'false') {
createBLEConnection()
}
}
})
}
其中,deviceId
就是我们搜索到的蓝牙设备的id
。
注意:
- 请尽量成对的调用
wx.createBLEConnection
和wx.closeBLEConnection
接口,安卓如果重复调用wx.createBLEConnection
创建连接,有可能导致系统对同一设备持有多个连接实例,会导致调用closeBLEConnection
的时候并不能真正的断开与设备的连接。 - 蓝牙连接随时有可能断开,可以调用
wx.onBLEConnectionStateChange
来监听设备断开,当设备断开时根据连接需求进行重连操作。
到这里蓝牙设备就连接上了(因为安卓和iOS的区别,iOS连接上蓝牙后,可以在通知栏看到蓝牙图标显示或者在控制中心看到蓝牙设备连接的名称来判断是否已经连接;安卓只能通过小程序提供的API回调参数来判断),如果想要获取蓝牙设备的数据或向蓝牙设备写入指令,就需要下面的步骤:
获取蓝牙设备的UUID
我们需要使用wx.getBLEDeviceServices
来获取蓝牙设备的UUID
。
获取蓝牙低功耗设备所有服务 (service
),代码如下:
//获取蓝牙设备的uuid
const getBLEDeviceServices = () => {
wx.getBLEDeviceServices({
deviceId: ConnectedDeviceRelated.deviceId,
success: function (res) {
for (var i = 0; i < res.services.length; i++) {
if (res.services[i].uuid.includes('xxxxx')) {
ios_uuid.push({
'notify': res.services[i].uuid
})
} else if (res.services[i].uuid.includes('xxxx')) {
ios_uuid.push({
'write': res.services[i].uuid
})
}
}
getBLEDeviceCharacteristics()
}
})
}
其中deviceId
为搜索蓝牙设备时获取的设备id
;这里按照蓝牙设备的不同,会获取到一个或多个服务id
这个时候只需获取最关键的两个服务id
:notify
和write
,怎么判断呢?一般对接这些设备都会给你协议文档,里面会提及用到的服务id
,以及他们的作用,那如果没有文档或者文档里面没有说呢?那你就要一个一个去试了.......
获取UUID中的特征值
我们需要通过wx.getCLEDeviceCharacteristics
方法来获取UUID
的特征值。
代码如下:
//获取蓝牙设备uuid的notify特征值
const getBLEDeviceCharacteristics = () => {
var notify = null;
for (var i = 0; i < ios_uuid.length; i++) {
if (ios_uuid[i].hasOwnProperty('notify')) {
notify = ios_uuid[i].notify
}
}
wx.getBLEDeviceCharacteristics({
deviceId: ConnectedDeviceRelated.deviceId,
serviceId: notify,
success: function (res) {
ios_uuidEigenvalues.push(res.characteristics[0].uuid)
setTimeout(() => (
startNotice(notify)
), 800)
},
fail: function (res) {
console.log('获取uuid的notify特征值失败', res)
}
})
}
其中deviceId
为前面搜索到的蓝牙设备的id
,serviceId
为获取的支持开启notify
的uuid
。
上图为获取服务中特征值成功的回调参数,其中在properties
属性中就可以判断获取的uuid
的作用,图示的是 只支持开启notify
的uuid
。部分蓝牙设备只会包含一个uuid
,但会有同时开启notify
和write
的能力。
开启notify
开启notify
需要调用wx.notifyBLECharacteristicValueChange
方法,启用蓝牙低功耗设备特征值变化时的 notify
功能,订阅特征。注意:必须设备的特征支持 notify
或者 indicate
才可以成功调用。
代码如下:
const startNotice = notify => {
wx.notifyBLECharacteristicValueChange({
state: true,
deviceId: ConnectedDeviceRelated.deviceId,
serviceId: notify,
characteristicId: ios_uuidEigenvalues[0],
success: function (res) {
console.log("开启notify成功")
//获取蓝牙设备uuid的write特征值
getBLEDeviceCharacteristics_write()
},
fail: function (res) {
console.log("notity失败", res)
}
})
}
其中,state为
是否启用notify
、deviceId
为步骤3中获取的设备id
、serviceId
为获取的uuid
、characteristicId
为uuid
特征值.
还是因为设备的不同,有的设备不需要主机(你的设备)主动触发从机(蓝牙设备)的功能,所以直接在开启notify
的方法中 监听蓝牙设备返回的数据就可以了
代码如下:
wx.onBLECharacteristicValueChange(function (characteristic) {
isOk = true
if (that.ab2hex(characteristic.value).substring(0, 4) == 'xxxxx') {
that.judgingElectricity(that.ab2hex(characteristic.value))
} else if (that.ab2hex(characteristic.value) == ConnectedDeviceRelated.turnSuccess_notify) {
sendMy(ConnectedDeviceRelated.approve)
} else if (that.ab2hex(characteristic.value) == 'xxxx') {
console.log('认证成功')
ConnectedDeviceRelated.disconnect = true
app.globalData.isturn = 'true'
app.globalData.isconnect = 'true'
that.setData({
isturn: 'true',
isconnect: 'true',
BluetoothNotConnected_icon: that.data.BluetoothIsConnected_icon,
electricityNotConnected_icon: that.data.electricityIsConnected_icon
})
that.isDeviceUnique(0)
}
})
注意:
这里蓝牙设备返回的数据格式是arraybuffer
需要再转一下字符串,代码如下:
// arraybuffer转字符串
ab2hex: function (buffer) {
var hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('');
},
如果你对接的蓝牙设备需要被动的触发功能(比如主机发送对应的功能指令),就要通过步骤中获取支持write
的uuid
,通过上面的方法获取UUID
特征值,然后向蓝牙设备写入`,写入成功,触发了成功的回调后,接着调用
wx.onBLECharacteristicValueChange`监听蓝牙设备返回的数据:
代码如下:
wx.writeBLECharacteristicValue({
deviceId: ConnectedDeviceRelated.deviceId,
serviceId: ConnectedDeviceRelated.services_write,
characteristicId: ConnectedDeviceRelated.write,
value: arrayBuffer,
success: function (res) {
wx.showToast({
title: '正在连接中...',
icon: 'none',
duration: 2000
})
//检测板子自己关闭 再打开后自动连接 如果写入后没反应,就再写入
setTimeout(function (params) {
if (isOk == false) {
sendMy('notify')
}
}, 1500)
//监听设备返回的值
wx.onBLECharacteristicValueChange(function (characteristic) {
isOk = true
if (that.ab2hex(characteristic.value).substring(0, 4) == 'fdf4') {
that.judgingElectricity(that.ab2hex(characteristic.value))
} else if (that.ab2hex(characteristic.value) == ConnectedDeviceRelated.turnSuccess_notify) {
sendMy(ConnectedDeviceRelated.approve)
} else if (that.ab2hex(characteristic.value) == 'xxxx') {
console.log('认证成功')
ConnectedDeviceRelated.disconnect = true
app.globalData.isturn = 'true'
app.globalData.isconnect = 'true'
that.setData({
isturn: 'true',
isconnect: 'true',
BluetoothNotConnected_icon: that.data.BluetoothIsConnected_icon,
electricityNotConnected_icon: that.data.electricityIsConnected_icon
})
that.isDeviceUnique(0)
}
})
//监听连接断开
that.disconnect()
},
fail: function (res) {
console.log('写入失败', res)
},
})
注意:
这里的value
需要的是arraybuffer
格式的数据指令,所以需要把字符转成arraybuffer
关闭蓝牙
断开与蓝牙低功耗设备的连接,代码如下:
wx.showModal({
title: '提示',
content: '要关闭蓝牙吗?',
success: function (res) {
if (res.confirm) {
if (app.globalData.bluetooth == 'W8') {
deviceId = ConnectedDeviceRelated.deviceId_sphygmomanometer
} else if (app.globalData.bluetooth == 'Yuwell BP-YE8900A') {
deviceId = ConnectedDeviceRelated.deviceId_YYSphygmomanometer
}
wx.closeBLEConnection({
deviceId: deviceId,
success(res) {
console.log("关闭蓝牙成功")
ConnectedDeviceRelated.disconnect = false
app.globalData.isconnect_bloodPressure = false
that.setData({
isconnect_bloodPressure: false,
SphygmomanometerBluetoothNotConnected_icon: config.ImageAddr_url + 'applets/images/jiance/YRSphygmomanometerBluetoothNotConnected.png',
})
}
})
}
}
})