zhyj
zhyj
  • 发布:2020-02-13 15:07
  • 更新:2023-11-09 10:46
  • 阅读:2514

【报Bug】在indicate模式下APP使用onBLECharacteristicValueChange 无法侦听到设备发送的数据,编译到小程序端可以侦听到。

分类:uni-app

详细问题描述

(DCloud产品不会有明显的bug,所以你遇到的问题大都是在特定环境下才能重现的问题,请仔细描述你的环境和重现方式,否则DCloud很难排查解决你的问题)

[内容]
使用uniappBLE接口,安卓流程,搜索设备 -》连接设备 -》 读取service -》读取characteristic -》 notifyBLECharacteristicValueChange -》onBLECharacteristicValueChange 。结果在onBLECharacteristicValueChange 内,没有侦听到任何东西。
我们是使用现有小程序的设备和代码进行移植测试,想要将原生小程序的设备功能移植到uniapp的app中。设备已经在小程序验证过。
代码如下:

                       async startScan() { // 主要流程  
                await this.closeBleAdpt()  
                await this.openBleAdpt()  

                await this.scanDevice()  
                let device = await this.findDevice()  
                this.stopSacn()  
                await this.connectDevice(device)  
                await this.delay(1500)  

                let suuid = await this.getService(device)  
                let characteristicId = await this.getCharacteristics(device.deviceId, suuid)  

                await this.notifyCharacteristicChange(device.deviceId, suuid, characteristicId)  
                this.listenCharacteristicChange(device.deviceId, suuid, characteristicId)  

            },  

            openBleAdpt() { // 打开蓝牙适配器,所有蓝牙操作均要在此操作之后  
                let _this = this  
                return new Promise((resolve, reject) => {  
                    uni.openBluetoothAdapter({  
                        success(res) {  
                            console.log(res)  
                            _this.listenConnectState()  
                            resolve()  
                        },  
                        fail: (res) => {  
                            console.log('open adapter fail', res)  
                            reject()  
                        }  
                    })  
                })  
            },  

            closeBleAdpt() {  
                return new Promise((resolve, reject) => {  
                    uni.closeBluetoothAdapter({  
                        complete: res => {  
                            console.log('关闭adpt', res)  
                            resolve(res)  
                        }  
                    })  
                })  
            },  

            listenConnectState() {  
                // return new Promise((resolve, reject) => {  
                uni.onBLEConnectionStateChange(function(res) {  
                    // 该方法回调中可以用于处理连接意外断开等异常情况  
                    console.log(`device ${res.deviceId} state has changed, connected: ${res.connected}`)  
                })  
                // })  

            },  

            delay(time) {  
                return new Promise((resolve) => {  
                    setTimeout(() => {  
                        resolve()  
                    }, time)  
                })  
            },  

            scanDevice() {  
                console.log('scanDevice')  
                return new Promise((resolve, reject) => {  
                    uni.startBluetoothDevicesDiscovery({  
                        services: ['FEE7', '0000FEE7-0000-1000-8000-00805F9B34FB'],  
                        success(res) {  
                            console.log('开启搜索设备', res)  
                            resolve(res)  
                        }  
                    })  
                })  

            },  

            ab2hex(buffer) {  
                const hexArr = Array.prototype.map.call(  
                    new Uint8Array(buffer),  
                    function(bit) {  
                        return ('00' + bit.toString(16)).slice(-2)  
                    }  
                )  
                return hexArr.join('')  
            },  

            findDevice() {  
                let _this = this  
                return new Promise((resolve, reject) => {  
                    uni.onBluetoothDeviceFound(function(res) {  
                        console.log('new device list has founded', res)  
                        // console.dir(devices)  
                        // console.log(_this.ab2hex(devices[0].advertisData))  
                        for (let device of res.devices) {  
                            if (device.name.toString().toUpperCase().indexOf('ETC') != -1) {  
                                resolve(device)  
                                return  
                            }  
                        }  

                    })  
                })  
            },  

            stopSacn() {  
                uni.stopBluetoothDevicesDiscovery({  
                    success(res) {  
                        console.log(res)  
                    }  
                })  
            },  

            connectDevice(device) {  
                console.log('connectDevice', device)  
                return new Promise((resolve, reject) => {  
                uni.createBLEConnection({  
                // plus.bluetooth.createBLEConnection({ // 5+  
                    timeout: 30000,  
                    // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接  
                    deviceId: device.deviceId,  
                    complete: (res) => {  
                        console.log('调用createBLEConnection完成', res)  
                        if (res.code == '0') {  
                            console.log('createBLEConnection success', res)  
                            resolve()  
                        } else {  
                            console.log('createBLEConnection fail', res)  
                            reject()  
                        }  
                    }  
                })  
                })  
            },  

            getService(device) {  
                let _this = this  
                return new Promise((resolve, reject) => {  
                    uni.getBLEDeviceServices({  
                        // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接  
                        deviceId: device.deviceId,  
                        success(res) {  
                            console.log('device services:', res)  
                            for (let service of res.services) {  
                                if ('0000FEE7-0000-1000-8000-00805F9B34FB' == service.uuid) {  
                                    resolve(service.uuid)  
                                    return  
                                }  
                            }  
                            reject('没找到对应服务')  
                        },  
                        fail: res => {  
                            reject(res)  
                        }  
                    })  
                })  
            },  

            getCharacteristics(deviceId, serviceId) {  
                return new Promise((resolve, reject) => {  
                    uni.getBLEDeviceCharacteristics({  
                        // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接  
                        deviceId,  
                        // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取  
                        serviceId,  
                        success(res) {  
                            console.log('device getBLEDeviceCharacteristics:', res)  
                            for (let characteristic of res.characteristics) {  
                                if ('0000FEC8-0000-1000-8000-00805F9B34FB' == characteristic.uuid) {  
                                    resolve(characteristic.uuid)  
                                    return  
                                }  
                            }  
                            reject('未找到对应特征值')  
                        },  
                        fail: res => {  
                            reject(res)  
                        }  
                    })  
                })  
            },  

            notifyCharacteristicChange(deviceId, serviceId, characteristicId) {  
                return new Promise((resolve, reject) => {  
                    uni.notifyBLECharacteristicValueChange({  
                    // plus.bluetooth.notifyBLECharacteristicValueChange({  
                        state: true, // 启用 notify 功能  
                        // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接  
                        deviceId,  
                        // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取  
                        serviceId,  
                        // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取  
                        characteristicId,  
                        success: (res) => {  
                            console.log('notifyBLECharacteristicValueChange success', res)  
                            resolve()  
                        },  
                        fail: res => {  
                            reject(res)  
                        }  
                    })  
                })  
            },  

            listenCharacteristicChange(deviceId, serviceId, characteristicId) {  
                let _this = this  
                console.log('开始侦听 listenCharacteristicChange')  
                uni.onBLECharacteristicValueChange(function(res) {  
                    console.log('收到侦听数据变化')  
                    console.log('onBLECharacteristicValueChange', res)  
                    console.log(`characteristic ${res.characteristicId} has changed, now is ${res.value}`)  
                    console.log(_this.ab2hex(res.value))  
                })  

            }

具体的log如下

因为我们设备是生产设备,专门针对小程序的,在小程序端正常运行,但是我们移植到APP端就发现了这个问题。下面是小程序端的日志:

小程序端的代码用的是wx.XXX,直接移植过来移植成uni.xxx,代码都一样。但是小程序上面可以侦听到,而安卓真机的时候,始终无法侦听到数据。 特征值是 ‘0000FEC8-0000-1000-8000-00805F9B34FB’,我们特征值


,只有indicate,其他均为false。这个在小程序端是可以notify到数据的,看uniapp文档上也写着只要notify 或 indicate。

重现步骤

[步骤] 因为没有设备,所以很难重现

[如果语言难以表述清晰,拍一个视频或截图,有图有真相]

IDE运行环境说明

HBuilderX。

[IDE版本号] 2.5.1

[windows版本号] win7 64位

uni-app运行环境说明

[运行端是h5或app或某个小程序?] HbuilderX2.5.1的真机调试下,手机是安卓机

App运行环境说明

[Android版本号] MIUI 11.0.3 安卓9

[手机型号] MI 8 SE

附件

[IDE问题请提供HBuilderX运行日志。菜单帮助-查看运行日志,点右键打开文件所在目录,将log文件压缩成zip包上传]

[QQ]
846599646

2020-02-13 15:07 负责人:无 分享
已邀请:
C***@live.cn

C***@live.cn

我测试直接转成JSON字符串会显示不出来value中的值 ,直接走一遍buffer2hex之后就能展示出来具体的值

3***@qq.com

3***@qq.com

我也遇到了一样的问题。

监听到返回的数据,value属性一致是空的。如下:

{  
    "deviceId": "C5:61:52:CC:E2:51",  
    "serviceId": "6E40FFF0-B5A3-F393-E0A9-E50E24DCCA9E",  
    "characteristicId": "6E400003-B5A3-F393-E0A9-E50E24DCCA9E",  
    "value": {}  
}
  • 1***@qq.com

    一样,value是空

    2022-12-21 14:52

  • b***@163.com

    我也找了一会,原来是这样的,可以参考这个文章:https://blog.csdn.net/u012577474/article/details/103831798

    2023-11-09 10:42

技术部一哥

技术部一哥 - 一个热爱前端开发的小菜鸟

我也是遇到上面的问题了 value为空

1***@qq.com

1***@qq.com

同问,求解

b***@163.com

b***@163.com

// 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) {  
    console.log('uni.onBLECharacteristicValueChange');  
    console.log("特征值改变:"+JSON.stringify(res));  
    console.log(`characteristic ${res.characteristicId} has changed, now is ${JSON.stringify(res.value)}`)  
    var value = ab2hex(res.value);  
        console.log("ArrayBuffer转16进度字符串完成:"+value)  

});

要回复问题请先登录注册