微信小程序连接蓝牙血压仪
### 小程序连接血压仪是通过蓝牙进行通信
### 此款血压仪是通过indicate服务进行数据通信
##### 小程序通过监听蓝牙设备特征值的变化进行读取数据
具体操作直接上代码:
-
微信小程序需要首先打开蓝牙适配器 wx.openBluetoothAdapter
wx.openBluetoothAdapter({
success: function (res) {
console.log(res)
},
fail: function (res) {
wx.showModal({
content: '请开启手机蓝牙后再试'
})
}
})
此方法可以检测中心设备是否支持蓝牙功能,是否打开蓝牙开关,如不符合上述条件,返回失败建wx.openBluetoothAdapter(OBJECT)和wx.closeBluetoothAdapter(OBJECT)成对使用wx.closeBluetoothAdapter:关闭蓝牙模块,使其进入未初始化状态。调用该方法将断开所有已建立的链接并释放系统资源;
2.搜索指定设备
wx.startBluetoothDevicesDiscovery(OBJECT)开始搜寻附近的蓝牙外围设备
wx.getBluetoothDevices(OBJECT)获取在小程序蓝牙模块生效期间所有已发现的蓝牙设备
wx.onBluetoothDeviceFound(CALLBACK) 监听寻找到新设备的事件
注意: 搜索蓝牙wx.startBluetoothDevicesDiscovery(OBJECT)操作比较耗费系统资源,在搜索并连接到设备后调用 wx.stopBluetoothDevicesDiscovery(OBJECT) 方法停止搜索。
startBluetoothDevicesDiscovery() {
if (this._discoveryStarted) {
return
}
this._discoveryStarted = true
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
success: (res) => {
console.log('startBluetoothDevicesDiscovery success', res)
this.onBluetoothDeviceFound()
},
})
},
stopBluetoothDevicesDiscovery() {
wx.stopBluetoothDevicesDiscovery()
},
onBluetoothDeviceFound() {
wx.onBluetoothDeviceFound((res) => {
res.devices.forEach(device => {
if (!device.name && !device.localName) {
return
}
const foundDevices = this.data.devices
const idx = inArray(foundDevices, 'deviceId', device.deviceId)
const data = {}
if (idx === -1) {
data[`devices[${foundDevices.length}]`] = device
} else {
data[`devices[${idx}]`] = device
}
this.setData(data)
})
})
},
createBLEConnection(e) {
const ds = e.currentTarget.dataset
const deviceId = ds.deviceId
const name = ds.name
wx.createBLEConnection({
deviceId,
success: (res) => {
this.setData({
connected: true,
name,
deviceId,
})
wx.setStorageSync('deviceId',deviceId);
// this.getBLEDeviceServices(deviceId)
}
})
this.stopBluetoothDevicesDiscovery()
},
- wx.setStorageSync('deviceId',deviceId); 将页面的选择的服务的UUID放入缓存中,此时我将跳转下一个页面进行定时扫描蓝牙的广播
- 开发者工具和 Android 上获取到的deviceId为设备 MAC 地址,iOS 上则为设备 uuid。因此deviceId不能硬编码到代码中,如何连接蓝牙搜索我们可以拿到了设备的deviceId,通过deviceId去连接蓝牙Android 上获取到的deviceId为设备 MAC 地址,iOS 上获取到的deviceId则为设备 uuid,因此deviceId不能硬编码到代码中,那么可能就有机智的小伙伴说了,设置两个变量,一个为设备MAC,一个为设备uuid,在连接设备的之前判断下机型,ios设备deviceId取:设备uuid,android设备deviceId:MAC地址!!!
我原本也是这样想的,因为我们做的这个小程序是扫码连接指定设备(就好像共享单车一样),所以本来是想在二维码中直接放入mac和uuid然后连接的时候去根据机型去取对应值
但是!!!但是!!!但是!!!
在实现过程中发现,ios不同手机搜索到的设备deviceId还是不同的.所以还是乖乖通过设备name(广播名),去获取deviceId去连接
正确的流程是
初始化蓝牙wx.openBluetoothAdapter(OBJECT)
↓
开始搜索蓝牙 wx.startBluetoothDevicesDiscovery(OBJECT)
↓
所有已发现的蓝牙设备wx.getBluetoothDevices(OBJECT)
↓
监听寻找到新设备的事件wx.onBluetoothDeviceFound(CALLBACK)
↓
连接低功耗蓝牙设备wx.createBLEConnection(OBJECT)
↓
获取蓝牙设备所有 service(服务) wx.getBLEDeviceServices(OBJECT)
↓
获取蓝牙设备某个服务中的所有 characteristic(特征值)wx.getBLEDeviceCharacteristics(OBJECT)
↓
启用低功耗蓝牙设备特征值变化时的 notify 功能wx.notifyBLECharacteristicValueChange(OBJECT)
↓
写入wx.writeBLECharacteristicValue(OBJECT)
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
var that=this;
that.setData({
//动态压力值
pressure: "",
//收缩压
SYS: "",
//舒张压
DIA: "",
//脉搏
PUL: ""
})
},
pickUpOnce:function(){
let that=this;
let deviceId=wx.getStorageSync('deviceId');
console.log("deviceId的值"+deviceId);
that.data.inter=setInterval(function() {
console.log('doSomething')
wx.createBLEConnection({
deviceId,
success: (res) => {
that.getBLEDeviceServices(deviceId)
}
})
}, 5000);
},
endInter:function(){
var that =this;
clearInterval(that.data.inter);
},
getBLEDeviceServices(deviceId) {
wx.getBLEDeviceServices({
deviceId,
success: (res) => {
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].isPrimary) {
this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
return
}
}
}
})
},
getBLEDeviceCharacteristics(deviceId, serviceId) {
let self = this;
console.log(deviceId,serviceId)
wx.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: (res) => {
console.log('getBLEDeviceCharacteristics success', res.characteristics)
console.log('获取服务的信息包括特征值', res)
for (let i = 0; i < res.characteristics.length; i++) {
let item = res.characteristics[i]
if (item.properties.notify || item.properties.indicate) {
console.log(item.uuid)
wx.notifyBLECharacteristicValueChange({
deviceId: deviceId,
serviceId: serviceId ,
characteristicId: item.uuid,
state: true,
success: (res) => {
wx.onBLECharacteristicValueChange(function(res) {
console.log("ab2hex方法执行之前的value="+res.value);
var value = ab2hex(res.value);
console.log("ab2hex方法执行之后的value="+value);
// if (value.length === 14){
// let result = parseInt(value.slice(10, 12), 16);
// console.log("动态压力值:" + result);
// // this.measureResult[0].pressure = result;
// }
if (value.length === 36){
let sys = parseInt(value.slice(2, 4), 16);
let dia = parseInt(value.slice(5, 8), 16);
let pul = parseInt(value.slice(28, 30), 16);
console.log("高压值 SYS:" + sys);
console.log("低压值 DIA:" + dia);
console.log("脉搏值 PUL:" + pul);
if(value.substring(2,4)==="ff"){
self.setData({
//收缩压
SYS: 'ERR',
//舒张压
DIA: 'ERR',
//脉搏
PUL: 'ERR'
})
}else{
self.setData({
//收缩压
SYS: sys,
//舒张压
DIA: dia,
//脉搏
PUL: pul
})
}
}
console.log("----------------------------------------------");
});
}
})
}
}
},
// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
var hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('');
}