重庆铭贝科技
重庆铭贝科技
  • 发布:2020-06-29 16:40
  • 更新:2025-10-17 15:52
  • 阅读:2670

低功耗蓝牙 onBLECharacteristicValueChange 多次回调

分类:uni-app

在使用低功耗蓝牙的时候发现一个问题 ,不知道是自己的写法问题还是BUG,请各位指教。

蓝牙连接成功后 开启特征值订阅 (notifyBLECharacteristicValueChange),然后断开当前连接的蓝牙设备连接另一个,且订阅特征值,这个时候


收到了是两包相同的数据,回调被执行了两次。

2020-06-29 16:40 负责人:无 分享
已邀请:
小马蹄

小马蹄

我也遇到了,现在发现保证uni.onBLECharacteristicValueChange只执行一次就好,这个函数不需要放在uni.notifyBLECharacteristicValueChange回调成功后调用,在uni.notifyBLECharacteristicValueChange前面调用也可以的。具体的调用时机我没一个个测过,不确定是否要等初始化蓝牙模块后调用

  • 小马蹄

    文档里只是说 必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification ,而不是说先启用notifyBLECharacteristicValueChange 再启用 onBLECharacteristicValueChange

    2024-09-04 09:10

热热子向前冲

热热子向前冲 -

遇到了一样的问题,请问你解决了吗

  • 了了_

    同样的问题,我暂时通过判断包号,过滤掉同样的数据,但是终究不是终极办法

    2020-10-10 12:12

  • 热热子向前冲

    回复 了了_: 嗯嗯,我看到HbuilderX alpha最新版解决了这个bug,使用了一下,没有重复的数据

    2020-10-11 15:43

d***@yundasys.com

d***@yundasys.com

遇到了一样的问题,请问你解决了吗

侠客请接刀s

侠客请接刀s

还是有问题 同问

7***@qq.com

7***@qq.com

ios,安卓 app中 notify回调只有一次,,但是onBLEConnectionStateChange和 onBLECharacteristicValueChange 回调会和connect(设置回调)的次数有关,close connection也没法避免. 有大佬解决了吗

2***@qq.com

2***@qq.com

还是有问题,有大佬有解决方案吗?

杨夕

杨夕 - lottie动画设计师

25年了,我的还是有问题,我都怀疑是我写的问题了。

  • 水月

    uni.onBLECharacteristicValueChange()方法放到APP.vue的onLunch()就行了

    2025-10-17 15:47

水月

水月

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('用户点击取消');  
                        }  
                      }  
                    });               
                }  
            });  
        }  
    }  

}

要回复问题请先登录注册