uni-app蓝牙踩坑小记
之前接了个与硬件建立蓝牙通讯的项目,学到了一些 uni-app 蓝牙操作的知识,也踩了一些坑,特此记录一下防止忘记。
Step1 初始化蓝牙适配器
使用uni.openBluetoothAdapter()函数初始化蓝牙适配器,uni.getBluetoothAdapterState()函数获取蓝牙适配器状态。
// Step1 初始化蓝牙
function initBlue() {
return new Promise((resolve, reject) => {
uni.openBluetoothAdapter({
success(res) {
console.log('初始化蓝牙成功')
uni.getBluetoothAdapterState({
success(r) {
console.log('蓝牙状态', r.available)
if (r.available) {
resolve()
}
else {
uni.showToast({
title: '请开启蓝牙',
icon: 'error',
duration: 2000,
})
reject()
}
},
fail(err) {
uni.showToast({
title: '请开启蓝牙',
icon: 'error',
duration: 2000,
})
reject()
},
})
},
fail(err) {
console.log('初始化蓝牙失败')
console.error(err)
uni.showToast({
title: '请开启蓝牙',
icon: 'error',
duration: 2000,
})
reject()
},
})
})
}Step2 开始搜索附近的蓝牙设备
使用uni.startBluetoothDevicesDiscovery()函数启动搜索附近的蓝牙设备,uni.onBluetoothDeviceFound()函数定义搜索到新设备时的回调函数。
// Step2 开始搜寻附近设备
function discovery() {
return new Promise((resolve, reject) => {
uni.startBluetoothDevicesDiscovery({
success(res) {
uni.showLoading({
title: '正在搜索设备',
icon: 'none',
})
// 开启监听回调
uni.onBluetoothDeviceFound((devices) => {
let obj = devices.devices[0]
console.log(obj.name)
if (obj.name === conf.deviceName) {
// 找到目标设备
// 设置设备ID到同步缓存中
uni.setStorageSync('deviceId', obj.deviceId)
uni.hideLoading()
resolve()
}
})
console.log('搜索蓝牙外围设备完成', res)
},
fail(err) {
console.log(err)
},
})
})
}Step3 连接蓝牙设备
使用uni.createBLEConnection(deviceId)函数连接到目标蓝牙设备。
// Step3 连接设备
function connect() {
return new Promise((resolve, reject) => {
uni.createBLEConnection({
deviceId: uni.getStorageSync('deviceId'), // 设备id
success(res) {
console.log('连接成功')
console.log(res)
uni.showToast({
title: '连接成功',
icon: 'success',
})
// Step4 蓝牙连接成功后关闭蓝牙搜索
stopDiscovery()
resolve()
},
fail(err) {
uni.showToast({
title: '连接失败',
icon: 'error',
})
console.log('蓝牙连接失败')
console.log(err)
reject()
},
})
})
}重要
由于 Setp2 中搜索蓝牙设备的功能比较耗费系统资源,因此在搜索并连接到设备后务必停止搜索。
Step4 停止搜索
使用uni.stopBluetoothDevicesDiscovery()函数停止搜索附近的蓝牙设备。
// Step4 停止搜索
function stopDiscovery() {
uni.stopBluetoothDevicesDiscovery({
success(res) {
console.log('停止成功')
console.log(res)
},
fail(err) {
console.log('停止失败')
console.error(err)
},
})
}Step5 获取蓝牙设备所有服务
使用uni.getBLEDeviceServices(deviceId)函数获取蓝牙设备所有服务。
// Step5 获取蓝牙设备所有服务
function getServices() {
return new Promise((resolve, reject) => {
uni.getBLEDeviceServices({
deviceId: uni.getStorageSync('deviceId'),
success(res) {
console.log(res)
resolve()
},
fail(err) {
console.error(err)
reject()
},
})
})
}Step6 获取蓝牙设备某个服务中所有特征值
使用uni.getBLEDeviceCharacteristics(deviceId, serviceId)函数获取蓝牙设备某个服务中所有特征值。
// Step6 获取蓝牙设备某个服务中所有特征值
function getCharacteristics() {
return new Promise((resolve, reject) => {
uni.getBLEDeviceCharacteristics({
deviceId: uni.getStorageSync('deviceId'),
serviceId: conf.serviceId,
success(res) {
console.log(res)
resolve()
},
fail(err) {
console.error(err)
reject()
},
})
})
}Step7 开启消息监听
使用uni.notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicId, ...)函数开启消息监听。
// Step7 开启消息监听
function notify(handleFunc) {
// 这里传入一个回调函数,用于处理接收到的数据。
uni.notifyBLECharacteristicValueChange({
deviceId: uni.getStorageSync('deviceId'), // 设备id
serviceId: conf.serviceId, // 监听指定的服务
characteristicId: conf.characteristicId, // 监听对应的特征值
state: true,
success(res) {
console.log(res)
listenValueChange(handleFunc) // 开启监听消息变化,并传入回调函数。
},
fail(err) {
console.error(err)
uni.showToast({
title: '监听失败',
icon: 'error',
})
},
})
}Step8 监听消息变化
使用uni.onBLECharacteristicValueChange()函数监听消息变化并根据需求做相应处理。
// Step8 监听消息变化
function listenValueChange(handleFunc) {
// 这里传入一个回调函数,用于处理接收到的数据。
uni.onBLECharacteristicValueChange((res) => {
let resArray = ab2array(res.value) // 拿到数字数组
// Something to do...
})
}
// ArrayBuffer 转数组
function ab2array(buffer) {
return Array.from(new Uint8Array(buffer))
}Step9 发送数据
使用uni.writeBLECharacteristicValue(deviceId, serviceId, characteristicId, value)函数向蓝牙设备发送数据。
// Step9 发送数据
function sendCommand(data) {
uni.writeBLECharacteristicValue({
deviceId: uni.getStorageSync('deviceId'),
serviceId: conf.serviceId,
characteristicId: conf.characteristicId,
// 注意:value 是ArrayBuffer类型,需要进行转换。
value: array2ab(data),
success(res) {
console.log(`写入成功${res.errMsg}`)
},
fail(err) {
console.error(err)
uni.showToast({
title: '指令发送失败',
icon: 'error',
})
},
})
}
// 数组转Arraybuffer
function array2ab(numbers) {
// 创建一个ArrayBuffer,其大小等于数字数组的长度
const buffer = new ArrayBuffer(numbers.length)
// 创建一个Uint8Array视图来操作buffer
const uint8View = new Uint8Array(buffer)
// 将数字填充到Uint8Array中
for (let i = 0; i < numbers.length; i++) {
uint8View[i] = numbers[i]
}
// 返回ArrayBuffer
return buffer
}Step10 断开蓝牙连接
使用uni.closeBLEConnection(deviceId)函数断开蓝牙连接。
// Step10 断开蓝牙连接
function stopConnection() {
return new Promise((resolve, reject) => {
uni.closeBLEConnection({
deviceId: uni.getStorageSync('deviceId'), // 设备id
success(r) {
resolve()
},
fail(r) {
console.log(r)
reject()
},
})
})
}踩过的坑
为什么收到的数据是乱码(不符合预期)?
- 协议文档写错了:可能是文档看错了或者硬件那边把协议改了却没有更新文档。
- 数据类型不对:可能是收到的数据没有进行转换,直接在 ArrayBuffer 上面进行了数据解析操作。
- 硬件波特率设置有问题:可能是硬件那边的波特率设置有问题,导致数据收发不正常。经过
测试踩坑,波特率设置成 9600 时, 数据收发正常。

