在使用低功耗蓝牙的时候发现一个问题 ,不知道是自己的写法问题还是BUG,请各位指教。
蓝牙连接成功后 开启特征值订阅 (notifyBLECharacteristicValueChange),然后断开当前连接的蓝牙设备连接另一个,且订阅特征值,这个时候
收到了是两包相同的数据,回调被执行了两次。
我也遇到了,现在发现保证uni.onBLECharacteristicValueChange只执行一次就好,这个函数不需要放在uni.notifyBLECharacteristicValueChange回调成功后调用,在uni.notifyBLECharacteristicValueChange前面调用也可以的。具体的调用时机我没一个个测过,不确定是否要等初始化蓝牙模块后调用
ios,安卓 app中 notify回调只有一次,,但是onBLEConnectionStateChange和 onBLECharacteristicValueChange 回调会和connect(设置回调)的次数有关,close connection也没法避免. 有大佬解决了吗
APP.vue
export default {
onLaunch: function() {
uni.clearStorageSync();
console.log('App Launch');
uni.onBLECharacteristicValueChange(res => {
let buf = String.fromCharCode.apply(null, new Uint8Array(res.value));
console.log('收到数据:'+buf);
if(buf == '#ok#'){
console.log("数据接收完成");
}else if(buf == '#error#'){
uni.showModal({
title: '提示[4001]',
content: '设备接收数据异常,请重试',
showCancel:false,
success: function(res) {
if(res.confirm) {
console.log('用户点击确定');
} else if(res.cancel) {
console.log('用户点击取消');
}
}
});
}else
this.mergePackage(buf);
});
//蓝牙连接成功,开启接受消息
uni.$on('bluetoothSuccess', (data) => {
console.log('bluetoothSuccess........');
uni.notifyBLECharacteristicValueChange({
state: true,
deviceId: uni.getStorageSync('deviceId'),
serviceId: uni.getStorageSync('serviceId'),
characteristicId: uni.getStorageSync('notifyCharId'),
success: () => {
console.log('通知已开启');
},fail: (res) => {
uni.showModal({
title: '提示[4002]',
content: '操作失败,蓝牙断开或设备异常',
showCancel:false,
success: function(res) {
if(res.confirm) {
console.log('用户点击确定');
} else if(res.cancel) {
console.log('用户点击取消');
}
}
});
}
});
});
/**
* 蓝牙连接成功,向蓝牙设备发送消息
* orderType 1读取 2写入(写入字符串过长时需要拆包)
*/
uni.$on('sendToDevice', (res) => {
if(res.data.indexOf("#")>-1){
uni.showToast({
title:"非法字符#",
icon:'error'
})
return;
}
let _this = this;
if(res.orderType == 2){
uni.showLoading({
title:'数据发送中...'
})
let packageArr = this.splitPackage(res.data);
for (let i = 0; i < packageArr.length; i++) {
setTimeout(function(){
if(i==packageArr.length-1)
_this.sendItemData(res.title,packageArr[i],1);
else
_this.sendItemData(res.title,packageArr[i],0);
},500*i);
}
}else{
uni.showLoading({
title:'指令发送中...'
})
this.sendItemData(res.title,"#01/01#"+res.data);
}
});
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
},
data() {
return {
receiveData:[],
}
},
methods:{
/**
* 拆包
* @param {Object} data
*/
splitPackage(data){
let result = [];
let total = 1;
if(data.length>150){
//不能被整除
if(data.length%150>0){
total = data.length/150+1;
}else
total = data.length/150;
total = Math.floor(total);
}
if(total<10)
total = '0'+ total;
let index = 1;
for (let i = 0; i < data.length; i += 150) {
if(index<10)
result.push("#0"+index+"/"+total+"#"+data.substring(i, i + 150));
else
result.push("#"+index+"/"+total+"#"+data.substring(i, i + 150));
index++;
}
return result;
},
/**
* 合包
* @param {Object} data
* #01/10# str....
* #02/10# str....
*/
mergePackage(data){
let head = data.substring(1,6);
let arr = head.split("/");// 01/10
let index = arr[0]*1;
let count = arr[1]*1;
let obj = new Object();
obj.i = index;
obj.data = data.substring(7,data.length);
if(index == 1)//第一包时清空缓存数据
this.receiveData = [];
this.receiveData.push(obj);
console.log(this.receiveData);
if(count == this.receiveData.length){
this.receiveData = this.receiveData.sort((a, b) => a.i - b.i);
let datas = '';
for (var i = 0; i < this.receiveData.length; i++) {
let d = this.receiveData[i].data;
datas += d;
}
this.receiveData = [];
let jsonObject = JSON.parse(datas);
console.log(jsonObject.cmd+"合包",datas)
uni.setStorageSync(jsonObject.cmd,jsonObject);
}
},
sendItemData(title,msg,doneFlag){
console.log('发送内容:',msg)
const buffer = new ArrayBuffer(msg.length);
const dataView = new DataView(buffer)
for (let i = 0; i < msg.length; i++) {
dataView.setUint8(i, msg.charAt(i).charCodeAt())
}
uni.writeBLECharacteristicValue({
deviceId: uni.getStorageSync('deviceId'),
serviceId: uni.getStorageSync('serviceId'),
characteristicId: uni.getStorageSync('writeCharId'),
value: buffer,
success: () => {
if(doneFlag == 1){
uni.hideLoading();
if(title)
uni.showToast({title:title})
else
uni.showToast({title:'数据发送成功'})
}
},
fail:function(res){
uni.showModal({
title: '提示[4003]',
content: '数据发送失败,请重新连接蓝牙',
showCancel:false,
success: function(res) {
if(res.confirm) {
console.log('用户点击确定');
} else if(res.cancel) {
console.log('用户点击取消');
}
}
});
}
});
}
}
}
小马蹄
文档里只是说
必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification
,而不是说先启用notifyBLECharacteristicValueChange 再启用 onBLECharacteristicValueChange2024-09-04 09:10