uni-app中uni.notifyBLECharacteristicValueChange报错 notifyBLECharacteristicValueChange:fail no descriptor

发布于 1周前 作者 phonegap100 来自 Uni-App

uni-app中uni.notifyBLECharacteristicValueChange报错 notifyBLECharacteristicValueChange:fail no descriptor

类别 信息
产品分类 uniapp/App
PC开发环境 Windows
PC版本号 win11
HBuilderX 正式
HBuilderX版本 4.29
手机系统 Android
手机版本号 Android 10
手机厂商 OnePlus 6
手机机型 ONEPLUSA6000
页面类型 vue
vue版本 vue3
打包方式 离线
项目创建方式 HBuilderX

示例代码:

<script setup>  
import { onLoad } from '@dcloudio/uni-app';  
import { ref } from 'vue';  

let deviceInfo = ref({});  
let result = ref(null);  
let device_service = ref([])  
let device_characteristics = ref([])  
let scanstorage = ref()  
let tmp_predict = ref()  
let NewMultiscan = ref()  
let mresult = ref()  
onLoad((options) => {  
    try {  
        deviceInfo.value = { ...JSON.parse(decodeURIComponent(options.device_info)) };  
        console.log("设备信息:", deviceInfo.value);  
    } catch (error) {  
        console.error("解析设备信息失败:", error);  
    }  
});  
function toScanAndPredict(){  
    console.log('开始扫描并且预测');  
    console.log(deviceInfo.value);  
    const deviceId = deviceInfo.value.deviceId;  
    let connect = false  
    uni.getBLEDeviceServices({  
        deviceId,  
        success(res){  
            console.log(res.services)  
            device_service.value = [...res.services]  
            const serviceId = device_service.value[9].uuid  
            uni.getBLEDeviceCharacteristics({  
                deviceId,  
                serviceId,  
                success(res){  
                    const characteristicIdn = res.characteristics[17].uuid  
                    const characteristicIdw = res.characteristics[16].uuid  
                    console.log(res.characteristics)  
                    device_characteristics.value = res.characteristics  
                    console.log(device_characteristics.value[5])  
                    addEventNotify(deviceId, device_service.value[9].uuid, device_characteristics.value[5])  
                },  
                fail(err){  
                    console.log("获取特征值失败:", err);  
                }  
            })  
        },  
        fail(err){  
            console.log("获取服务失败:", err);  
        }  
    })  
}  
function addEventNotify(deviceId, serviceId, characteristicId){  
    uni.onBLECharacteristicValueChange(res => {  
        if(ab2ten(res.value)[0] == 255){  
            uni.offBLECharacteristicValueChange()  
            let scanIndex = ab2ten(res.value)  
            let buffer = new ArrayBuffer(4)  
            let dataView = new DataView(buffer)  
            dataView.setUint8(0, scanIndex[1])  
            dataView.setUint8(1, scanIndex[2])  
            dataView.setUint8(2, scanIndex[3])  
            dataView.setUint8(3, scanIndex[4])  
            uni.notifyBLECharacteristicValueChange({  
                deviceId: deviceId,  
                serviceId: serviceId,  
                characteristicId: characteristicIdn,  
                state: true,  
                success(res) {  
                    console.log('return data n', res)  
                },  
            })  
            setTimeout(()=>{  
                uni.writeBLECharacteristicValue({  
                    deviceId: deviceId,  
                    serviceId: serviceId,  
                    characteristicId: characteristicIdw,  
                    value: buffer,  
                    success(res) {  
                        console.log('request data w', res)  
                    },  
                })  
            },2000)  
            let d = ref([])  
            uni.onBLECharacteristicValueChange(res => {  
                let a = ab2ten(res.value)  
                console.log(a)  
                if (ab2ten(res.value)[0] != 0) {  
                    a.shift()  
                    Array.prototype.push.apply(d, a);  
                }  
                if (ab2ten(res.value)[0] == 202) {  
                    uni.offBLECharacteristicValueChange()  
                    if (that.data.multiscan) {  
                        if (!scanstorage.value) {  
                            var scanstorage = []  
                        } else {  
                            var scanstorage = scanstorage.value  
                        }  
                        Array.prototype.push.apply(scanstorage, d);  
                        scanstorage.value = scanstorage  
                        tmp_predict.value = scanstorage  
                        NewMultiscan.value = false  
                        mresult.value = '已完成' + String(scanstorage.length / 3822) + '次扫描'  
                    }else{  
                        console.log('d')  
                        //发送数据  
                        tmp_predict.value = d  
                    }  
                }  
            })  
        }  
    });  

    uni.notifyBLECharacteristicValueChange({  
        deviceId: deviceId.toUpperCase(),  
        serviceId: serviceId.toUpperCase(),  
        characteristicId: device_characteristics.value[7].uuid.toUpperCase(),  
        state: true, // 启用 notify 功能  
        success: (res) => {  
            console.log('start scan n', res);  
        },  
        fail: (err)=>{  
            console.log({deviceId, serviceId})  
            console.log(device_characteristics.value[5])  
            console.log('开启扫描失败', err)  
        }  
    })  
}  
// ArrayBuffer转16进度字符串示例  
function ab2hex(buffer) {  
    var hexArr = Array.prototype.map.call(  
        new Uint8Array(buffer),  
        function (bit) {  
            return ('00' + bit.toString(16)).slice(-2)  
        }  
    )  
    return hexArr.join('');  
}  

// ArrayBuffer转10进度字符串示例  
function ab2ten(buffer) {  
    var hexArr = Array.prototype.map.call(  
        new Uint8Array(buffer),  
        function (bit) {  
            return (bit.toString(10))  
        }  
    )  
    return hexArr;  
}  

function ab2int(buffer) {  
    var hexArr = Array.prototype.map.call(  
        new Int16Array(buffer),  
        function (bit) {  
            return (bit.toString(10))  
        }  
    )  
    return hexArr;  
}  
</script>

操作步骤:

uni.notifyBLECharacteristicValueChange({  
    deviceId: deviceId.toUpperCase(),  
    serviceId: serviceId.toUpperCase(),  
    characteristicId: device_characteristics.value[7].uuid.toUpperCase(),  
    state: true, // 启用 notify 功能  
    success: (res) => {  
        console.log('start scan n', res);  
    },  
    fail: (err)=>{  
        console.log({deviceId, serviceId})  
        console.log(device_characteristics.value[5])  
        console.log('开启扫描失败', err)  
    }  
})

预期结果:

console.log('start scan n', res);

实际结果:

console.log({deviceId, serviceId})  
console.log(device_characteristics.value[5])  
console.log('开启扫描失败', err)

bug描述:

报错信息 调用uni.notifyBLECharacteristicValueChange接口报错 “errMsg”: “notifyBLECharacteristicValueChange:fail no descriptor”,“code”: 10008 目前怀疑是uniapp识别不了相同特征值不同权限的蓝牙接口


1 回复

在uni-app中处理蓝牙BLE(Bluetooth Low Energy)设备时,uni.notifyBLECharacteristicValueChange 方法用于启用或禁用特定蓝牙特征值(characteristic)的notify/indicate功能,以便在特征值发生变化时接收通知。如果在使用 uni.notifyBLECharacteristicValueChange 方法时遇到错误提示 “notifyBLECharacteristicValueChange:fail no descriptor”,这通常意味着在尝试启用的特征值上没有找到所需的客户端配置描述符(Client Configuration Descriptor)。

客户端配置描述符是用于控制notify/indicate功能的,它必须存在于特征值中,并且其值需要被正确设置以启用或禁用通知。以下是一个处理BLE通知的基本代码示例,包括错误处理和一些检查步骤,帮助你解决可能的问题:

// 假设已经成功连接到蓝牙设备,并且已经获取了服务(service)和特征值(characteristic)

// 启用notify/indicate功能
function enableNotify(deviceId, serviceId, characteristicId) {
    uni.notifyBLECharacteristicValueChange({
        deviceId: deviceId,
        serviceId: serviceId,
        characteristicId: characteristicId,
        state: true, // 启用notify/indicate
        success: function (res) {
            console.log('Notify enabled successfully', res);
            // 监听特征值变化
            uni.onBLECharacteristicValueChange(function (res) {
                console.log('BLE characteristic value changed:', res);
            });
        },
        fail: function (err) {
            console.error('Failed to enable notify:', err);
            // 检查描述符是否存在
            checkDescriptors(deviceId, serviceId, characteristicId);
        }
    });
}

// 检查特征值描述符
function checkDescriptors(deviceId, serviceId, characteristicId) {
    uni.getBLEDeviceCharacteristics({
        deviceId: deviceId,
        serviceId: serviceId,
        success: function (res) {
            const characteristics = res.characteristics;
            const targetChar = characteristics.find(char => char.uuid === characteristicId);
            if (targetChar && targetChar.descriptors) {
                const descriptors = targetChar.descriptors;
                const clientConfigDesc = descriptors.find(desc => desc.uuid === '00002902-0000-1000-8000-00805f9b34fb'); // 客户端配置描述符的UUID
                if (!clientConfigDesc) {
                    console.error('No client configuration descriptor found');
                } else {
                    console.log('Client configuration descriptor found:', clientConfigDesc);
                }
            } else {
                console.error('No descriptors or target characteristic not found');
            }
        },
        fail: function (err) {
            console.error('Failed to get BLE device characteristics:', err);
        }
    });
}

在上述代码中,我们首先尝试启用notify/indicate功能。如果失败,则调用 checkDescriptors 函数来检查目标特征值是否包含客户端配置描述符。如果描述符不存在,则输出错误信息。注意,客户端配置描述符的UUID是固定的(00002902-0000-1000-8000-00805f9b34fb),这是BLE标准定义的。

回到顶部