使用蓝牙相关api之前需要让用户授权蓝牙的隐私协议,代码如下:
uni.authorize({
scope: 'scope.bluetooth',
success:(res=>{
console.log('蓝牙授权成功,开始使用蓝牙相关api功能')
}),
fail:(res=>{
console.log('用户拒绝授权蓝牙功能,返回')
})
})
所有蓝牙相关API调用必须要在uni.openBluetoothAdapter之后使用,接口调用成功会进入到success里,表示蓝牙模块初始化完成,代码如下:
uni.openBluetoothAdapter({
success(res) {
console.log(res,'初始化蓝牙成功,准备搜索附近蓝牙设备')
},
fail(err) {
console.log(err,'err初始化蓝牙fail')
}
})
在蓝牙初始化成功后调用uni.startBluetoothDevicesDiscovery开启蓝牙搜索功能,搜索成功后需要调用uni.onBluetoothDeviceFound方法去寻找你想要找的设备,uni.onBluetoothDeviceFound方法调用成功后,按照我贴的代码获取蓝牙设备返回的数据段,与你们后端返回的数据进行比较,匹配成功,就调用uni.stopBluetoothDevicesDiscovery方法关闭蓝牙搜索,减少资源消耗。
uni.startBluetoothDevicesDiscovery({
allowDuplicatesKey: false,
success(res) {
console.log('开启蓝牙搜索成功,准备查找目的设备')
},
fail(err) {
log.info(err,'开启蓝牙搜索失败')
}
})
uni.onBluetoothDeviceFound(function (devices) {
//ArrayBuffer转16进度字符串示例
const deviceId= Array.prototype.map.call(
new Uint8Array(devices[0].advertisData),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
let deviceData = xxx //这是你们公司返回的该设备的数据
//接下来看你们公司定义的数据,一般是hexArr 等于deviceData时代表搜索到目标设备
if(deviceId==deviceData ){
//因为搜索的过程比较耗费资源,所以找到目标设备后需要调用 uni.stopBluetoothDevicesDiscovery停止搜索
uni.stopBluetoothDevicesDiscovery({
success: (res) => {
console.log('停止搜寻附近的蓝牙外围设备成功res', res);
},
fail: (err) => {
console.log('停止搜寻附近的蓝牙外围设备失败err', err);
log.info('停止搜寻附近的蓝牙外围设备失败err', err);
}
})
}
})
经过以上步骤找到想要的设备之后,拿到上一步骤匹配到的deviceId进行连接
uni.createBLEConnection({
deviceId: deviceId,
timeout: 5000,
success: (res) => {
console.log('通过deviceId连接蓝牙设备成功res,开始获取蓝牙所有服务', res);
},
fail: (err) => {
console.log('通过deviceId连接蓝牙设备失败err', err);
}
});
获取服务成功后,遍历返回的所有设备服务列表,UUID_SERVICE这个是你们后端提供的uuid,当设备服务列表里的uuid与你们自己的uuid一致时,开始下一步获取特征值
uni.getBLEDeviceServices({
deviceId: phone,
success(res) {
console.log('第五步获取蓝牙设备所有服务成功res', res);
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].uuid.toLowerCase() == UUID_SERVICE) {
// 获取特征值,这里把res.services[i].uuid赋值给seviceId留给下个步骤用
let seviceId = res.services[i].uuid
}
}
},
fail(err) {
console.log('第五步获取蓝牙设备所有服务失败err', err);
}
})
获取到上个步骤具体的服务后,调用uni.getBLEDeviceCharacteristics方法获取特征值,调用成功后遍历获取到的res.characteristics数据,判断里面的properties是否支持notify操作,支持就调用uni.notifyBLECharacteristicValueChange方法启用 notify 功能,订阅特征值。启动成功后就到了下一个步骤,发送蓝牙指令,也就是最重要的步骤啦
uni.getBLEDeviceCharacteristics({
deviceId: deviceId,//蓝牙设备id
serviceId: serviceId,
success: (res) => {
console.log('第六步获取蓝牙设备某个服务中所有特征值成功res', res);
for (let i = 0; i < res.characteristics.length; i++) {
let item = res.characteristics[i]
// item.properties.notify:该特征值是否支持 notify 操作
if (item.properties.notify) {
that._characteristicsId=item.uuid
// 启用低功耗蓝牙设备特征值变化时的 notify 功能,订阅特征值成功res
uni.notifyBLECharacteristicValueChange({
deviceId: deviceId,//蓝牙设备id
serviceId: serviceId,
characteristicId: item.uuid,
state: true,
type: 'notification',
success(res) {
console.log('启用低功耗蓝牙设备特征值变化时的 notify 功能 success', res.errMsg);
//开始监听蓝牙变化
},
fail(res) {
console.log('启用低功耗蓝牙设备特征值变化时的 notify 功能 fail', res.errMsg);
},
})
}
}
},
fail(res) {
log.error("获取蓝牙服务的特征值失败:", res.errMsg);
}
})
在这里就是业务需求了,比如做智能门窗,可以向蓝牙发送门开指令,如果是单车可以发送锁开的指令,但前提是必须要向蓝牙传送二进制数据才行,下面是一个向蓝牙设备发送一个0x00的16进制的小demo,具体写入数据需要根据业务不同进行调整
const buffer = new ArrayBuffer(1)
const dataView = new DataView(buffer)
dataView.setUint8(0, 0)
uni.writeBLECharacteristicValue({
// 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId,
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
characteristicId,
// 这里的value是ArrayBuffer类型
value: buffer,
success(res) {
console.log('writeBLECharacteristicValue success', res.errMsg)
}
})
上个步骤向蓝牙传输数据之后,调用uni.onBLECharacteristicValueChange方法去监听蓝牙变化,获取蓝牙传送来的数据,这块也需要根据业务不同进行不同场景的处理,比如向蓝牙发送开锁指令后蓝牙执行了锁开的操作,并向你返回蓝牙数据,告诉你锁开成功,你就可以在这处理啦,这里依然贴一下官方给的demo,详细需求可以在这基础上进行扩写
// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('')
}
uni.onBLECharacteristicValueChange(function (res) {
var value = ab2Str(res.value)
})
以上就完成啦