React Native BLE Plx中如何判断monitorCharacteristic监听完成?
问题原因分析
monitorCharacteristicForService是回调式的异步API,本身不会返回Promise,调用后会立刻返回订阅实例,不会等待特征值推送完成,所以你函数里后续的同步代码肯定会比回调里的日志先执行。- 你之前把
console.log('DONE')放在return语句之后,函数执行到return就会终止,后面的代码永远不会被执行;而monitorCharacteristicForService返回的是订阅对象不是Promise,所以直接调用.then会报错。 - BLE协议本身没有规定多包传输的结束标志,结束判断逻辑需要和你的设备端通信协议对齐,常见的判断规则有两类:
- 协议约定了结束标记,比如所有数据传输完成后设备会推送一帧带特殊标识(比如
\r\n、0x0D0A这类约定值)的包 - 首帧数据里包含了数据总长度,你累加收到的字节数达到总长度时即为传输完成
- 协议约定了结束标记,比如所有数据传输完成后设备会推送一帧带特殊标识(比如
解决方案
你可以把监听逻辑封装成Promise,在判断传输完成的时候resolve,同时统一处理错误和订阅销毁:
const scanMyDevice = async (device) => { const serviceUUID = '569a1-****' const writeUUID = '569a2-****' const readUUID = '569a2-****' await device.discoverAllServicesAndCharacteristics() await device.characteristicsForService(serviceUUID) await device.writeCharacteristicWithResponseForService(serviceUUID, writeUUID, 'IzEwCg==') // 封装Promise等待传输完成 return new Promise((resolve, reject) => { let tempTrame = '' const subscription = device.monitorCharacteristicForService( serviceUUID, readUUID, (error, characteristic) => { if (error) { subscription.remove() // 出错先销毁订阅 reject(error) return } const curValue = base64.decode(characteristic.value) tempTrame += curValue setTrameResult(tempTrame) console.log('// INSIDE ///', tempTrame) // 这里替换成你和设备约定的结束判断逻辑 // 举个例子:如果约定结束标记是'##END##' if (tempTrame.endsWith('##END##')) { // 或者如果首帧有总长度:if (tempTrame.length >= 约定的总长度) subscription.remove() // 传输完成销毁订阅 console.log('DONE') resolve(tempTrame) // 把完整数据返回出去 } }, 'idMonitor' ) }) }
调用方式
因为现在scanMyDevice返回的是Promise,你可以用await或者then获取结果:
// 调用示例 try { const fullData = await scanMyDevice(yourDevice) // 这里可以处理完整的返回数据 } catch (err) { console.log('BLE监听出错', err) }
内容的提问来源于stack exchange,提问作者Boonty
相关产品推荐
相关产品推荐

