uni-app蓝牙踩坑小记
之前接了个与硬件建立蓝牙通讯的项目,学到了一些uni-app蓝牙操作的知识,也踩了一些坑,特此记录一下防止忘记。
Step1 初始化蓝牙适配器
使用uni.openBluetoothAdapter()
函数初始化蓝牙适配器,uni.getBluetoothAdapterState()
函数获取蓝牙适配器状态。
// Step1 初始化蓝牙
const 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 开始搜寻附近设备
const discovery = () => {
return new Promise((resolve, reject) => {
uni.startBluetoothDevicesDiscovery({
success(res) {
uni.showLoading({
title: "正在搜索设备",
icon: "none",
});
// 开启监听回调
uni.onBluetoothDeviceFound(function(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 连接设备
const 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 停止搜索
const stopDiscovery = () => {
uni.stopBluetoothDevicesDiscovery({
success(res) {
console.log('停止成功');
console.log(res);
},
fail(err) {
console.log('停止失败');
console.error(err);
}
});
};
Step5 获取蓝牙设备所有服务
使用uni.getBLEDeviceServices(deviceId)
函数获取蓝牙设备所有服务。
// Step5 获取蓝牙设备所有服务
const 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 获取蓝牙设备某个服务中所有特征值
const 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 开启消息监听
const 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 监听消息变化
const listenValueChange = (handleFunc) => { // 这里传入一个回调函数,用于处理接收到的数据。
uni.onBLECharacteristicValueChange(res => {
let resArray = ab2array(res.value); // 拿到数字数组
// Something to do...
})
};
// ArrayBuffer 转数组
const ab2array = (buffer) => {
return Array.from(new Uint8Array(buffer));
};
Step9 发送数据
使用uni.writeBLECharacteristicValue(deviceId, serviceId, characteristicId, value)
函数向蓝牙设备发送数据。
// Step9 发送数据
const 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
const 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 断开蓝牙连接
const stopConnection = () => {
return new Promise((resolve, reject) => {
uni.closeBLEConnection({
deviceId: uni.getStorageSync('deviceId'), // 设备id
success(r) {
resolve();
},
fail(r) {
console.log(r);
reject();
}
});
});
};
踩过的坑
为什么收到的数据是乱码(不符合预期)?
- 协议文档写错了:可能是文档看错了或者硬件那边把协议改了却没有更新文档。
- 数据类型不对:可能是收到的数据没有进行转换,直接在ArrayBuffer上面进行了数据解析操作。
- 硬件波特率设置有问题:可能是硬件那边的波特率设置有问题,导致数据收发不正常。经过
测试踩坑,波特率设置成9600时, 数据收发正常。