基于Bleno的BLE外设如何在写入请求处理时向发送方回传响应
Bleno 外设端回传逻辑失效的原因与修复方案
现有代码的核心问题
- 对
onWriteRequest回调的作用认知错误:该回调仅用于向BLE协议栈告知写入请求的处理状态,传入的Buffer不会被发送到手机端,将业务回传数据塞在这里完全无法触达发送方。 - 回调调用时机错误:代码在
wifi.scan异步流程外、所有业务逻辑执行前就触发了callback(this.RESULT_SUCCESS),此时协议栈已经关闭了本次写入的会话通道,后续异步流程里的操作都无法完成数据回传。 - 业务判断逻辑错误:通过
forEach遍历网络列表时,只要碰到一个不匹配目标SSID的网络就触发错误回传,实际需要遍历完全部列表,确认所有扫描到的网络都不存在目标SSID时,才能判定为匹配失败。 - 遗漏了Bleno外设主动发数据的正确通道:Bleno里外设给手机端回传业务数据,不能依赖写入请求的回调,必须通过特征自带的通知/指示能力,调用
updateValue方法主动推送。
正确实现步骤
- 校验特征定义:确保当前使用的读写特征,在初始化配置时就开启了
notify(通知)或indicate(指示)属性,没有这个属性就算推送数据,手机端也无法接收。 - 调整回调位置:将
onWriteRequest的协议层回调移动到所有异步业务逻辑执行完成的节点再触发,避免提前关闭写入会话。 - 替换回传通道:所有需要发送给手机的业务状态、错误信息,统一通过特征实例的
updateValue(数据Buffer, false)方法推送。 - 修正SSID匹配逻辑:先遍历完所有扫描到的网络列表,通过布尔标记记录是否存在匹配的目标SSID,遍历完成后再生成对应回传数据。
修正后的参考代码
// 特征初始化时需包含notify属性,示例配置参考: // this.properties = ['read', 'write', 'notify'] WriteReadCharacteristic.prototype.onWriteRequest = function(data, offset, withoutResponse, callback) { const output = Buffer.from(data, 'hex'); let payload = {}; if (hasJsonStructure(String(output))) { payload = JSON.parse(String(output)); } wifi.scan((error, networks) => { if (error) { console.log('WiFi扫描异常', error); // 扫描异常时生成错误包,通过通知推给手机 const errBuffer = Buffer.alloc(4); errBuffer.writeUInt32LE(this.RESULT_SCAN_FAIL); this.updateValue(errBuffer, false); // 给协议栈返回写入处理完成的状态 callback(this.RESULT_SUCCESS); return; } // 遍历所有网络,判断目标SSID是否存在 let ssidMatched = false; networks.forEach(network => { if (payload.ssid === network.ssid) { ssidMatched = true; } }); if (ssidMatched) { console.log("Success, wifi found"); // 匹配成功时推送成功状态给手机 const successBuffer = Buffer.alloc(4); successBuffer.writeUInt32LE(this.RESULT_SUCCESS); this.updateValue(successBuffer, false); } else { console.log("Failed, not found"); // 匹配失败时推送错误状态给手机 const failBuffer = Buffer.alloc(4); failBuffer.writeUInt32LE(this.RESULT_UNLIKELY_ERROR); this.updateValue(failBuffer, false); } // 所有业务逻辑走完,最后触发协议层回调 callback(this.RESULT_SUCCESS); }); };
注意事项:手机端需在nRF Connect中先点击对应特征的订阅按钮,开启通知接收权限,才能收到外设推送的回传数据;代码中原先使用的
new Buffer(31)是Node.js已废弃的API,替换为Buffer.alloc()可避免潜在的内存安全问题。
内容的提问来源于stack exchange,提问作者Dizio Adil
相关产品推荐
相关产品推荐

