如何在Flutter中读取蓝牙设备更新后的Notify值?
问题:写入蓝牙设备后无法读取Notify值更新
向蓝牙设备写入数据后,尝试读取Notify值的更新,但使用Flutter_Blue_Plus包(包括官方示例应用)时,Notify值始终为空。用nRF Connect测试设备时,写入数据后能正常看到Notify值变化。
如何读取更新后的Notify值?
连接设备与发现服务的代码
List<ScanResult> result = []; try { result = await FlutterBluePlus.instance.startScan(timeout: Duration(seconds: 5)) as List<ScanResult>; resultIndex = getResultIndex(result, event.dataTrac.sensor.dtId.getOrCrash()); } catch (ex){ log("Scan failed because another scan was already in progress."); } try { if (resultIndex == -1){ for (int i = 0; i < 5; i++){ result = await FlutterBluePlus.instance.startScan(timeout: Duration(seconds: 5)) as List<ScanResult>; resultIndex = getResultIndex(result, event.dataTrac.sensor.dtId.getOrCrash()); if (resultIndex > -1){ break; } } } } catch (ex){ log("Exception while scanning: $ex"); } if (resultIndex > -1 && result.isNotEmpty){ final ScanResult r = result.elementAt(resultIndex); //Make sure we aren't already connected to the device if (!(await FlutterBluePlus.instance.connectedDevices).contains(r.device)) { //log("Had not connected to device; connecting now"); await r.device.connect(autoConnect: false); await r.device.mtu.first; final int response = await r.device.requestMtu(165); log("New Mtu: $response"); final List<BluetoothService> serviceList = await r.device.discoverServices(); }
与设备交互的代码
for (final s in serviceList) { //log("Service UUID: ${s.uuid}", name: "programming_status_bloc.dart"); if (s.uuid.toString() == "6e400001-b5a3-f393-e0a9-e50e24dcca9e") { serviceFound = true; final actualTxChar = s.characteristics.firstWhere((element) => element.uuid.toString() == txChar); final success = await actualTxChar.setNotifyValue(true); if (success){ log("Set notify value."); } else { log("**Failed to set notify value.**"); } final actualRxChar = s.characteristics.firstWhere((element) => element.uuid.toString() == rxChar); //log("Char UUID: ${char.uuid}"); if (continueWriting) { continueWriting = false; //TODO: change CID for production final List<int> payload = createPayload(event.dataTrac, event.changedValuesMap, 151); //final payload = [12, 12, 12, 12, 12, 0, 70]; add(ProgrammingStatusEvent.updated(true)); await actualRxChar.write(payload); log("Wrote to device."); // final readResult = await actualRxChar.read(); // log("Read result: $readResult"); } //r.device.disconnect(); bool readYet = false; final txCharSubscription = actualTxChar.value.listen((value){ log("Notify value: $value"); }); await Future.delayed(Duration(seconds: 4)); await txCharSubscription.cancel(); await r.device.disconnect(); await FlutterBluePlus.instance.stopScan(); } } if (!serviceFound){ r.device.disconnect(); await FlutterBluePlus.instance.stopScan(); }
解决方案
1. 调整订阅Notify的时机
当前代码先写入数据再订阅Notify流,会错过设备发送的响应。必须先订阅Notify,再执行写入操作,确保不会遗漏设备的反馈。
2. 确认特征UUID对应关系
检查txChar和rxChar的UUID是否正确:
txChar应为设备用于主动推送Notify的特征UUIDrxChar应为设备用于接收写入数据的特征UUID
避免两者搞反导致无法接收数据。
3. 修改交互代码(修复版)
for (final s in serviceList) { if (s.uuid.toString() == "6e400001-b5a3-f393-e0a9-e50e24dcca9e") { serviceFound = true; final actualTxChar = s.characteristics.firstWhere((element) => element.uuid.toString() == txChar); final actualRxChar = s.characteristics.firstWhere((element) => element.uuid.toString() == rxChar); // 先订阅Notify流 bool receivedNotify = false; final txCharSubscription = actualTxChar.value.listen((value) { if (value.isNotEmpty) { log("Notify value: $value"); receivedNotify = true; } }); // 开启Notify final success = await actualTxChar.setNotifyValue(true); if (!success) { log("**开启Notify失败**"); await txCharSubscription.cancel(); await r.device.disconnect(); await FlutterBluePlus.instance.stopScan(); continue; } log("已开启Notify"); if (continueWriting) { continueWriting = false; final List<int> payload = createPayload(event.dataTrac, event.changedValuesMap, 151); add(ProgrammingStatusEvent.updated(true)); // 写入数据 await actualRxChar.write(payload); log("已向设备写入数据"); } // 等待收到Notify或超时(可根据设备调整超时时间) int timeoutCount = 0; await Future.doWhile(() async { await Future.delayed(Duration(milliseconds: 500)); timeoutCount += 500; return !receivedNotify && timeoutCount < 10000; // 10秒超时 }); // 清理资源 await txCharSubscription.cancel(); await r.device.disconnect(); await FlutterBluePlus.instance.stopScan(); } } if (!serviceFound){ await r.device.disconnect(); await FlutterBluePlus.instance.stopScan(); }
4. 额外排查点
- 检查Notify特征是否支持指示(Indication):如果设备使用Indication而非Notification,需调用
actualTxChar.setIndicateValue(true),并监听对应流。 - 确认写入参数:
actualRxChar.write(payload, withoutResponse: false),确保设备收到写入后会返回响应。 - 验证特征属性:打印
actualTxChar.properties,确认notify字段为true,确保该特征支持Notify功能。
内容的提问来源于stack exchange,提问作者TarHalda
相关产品推荐
相关产品推荐

