Flutter重复写入同一BLE特征报ERROR_GATT_WRITE_REQUEST_BUSY错误排查
蓝牙BLE设备写入特征异常排查(Flutter Blue Plus)
问题现象
- 首次点击
isLinked按钮向目标特征写入命令成功 - 点击
LinkRing按钮向同一特征写入不同命令时触发错误,核心错误提示为ERROR_GATT_WRITE_REQUEST_BUSY和UNKNOWN_GATT_ERROR (133),最终导致连接断开
核心错误日志
E/flutter (9263): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(setNotifyValue, gatt.writeDescriptor() returned 201: ERROR_GATT_WRITE_REQUEST_BUSY, null, null)
完整错误日志:
I/flutter (19243): Write error: FlutterBluePlusException | writeCharacteristic | fbp-code: 1 | Timed out after 15s I/flutter (19243): Write successful[36, 83, 32, 57, 102, 48, 101, 50, 107, 32, 116, 114, 117, 101] I/flutter (19243): [FBP] <writeCharacteristic> args: {remote_id: BC:02:6E:AF:D9:5B, service_uuid: b56c04ea-6cba-4dd4-83b9-7f3056a1bac5, secondary_service_uuid: null, characteristic_uuid: 6ae5deca-d2d0-4e13-a662-ad16e9a78dde, write_type: 0, allow_long_write: 0, value: 24532039663065326b2074727565} D/[FBP-Android](19243): [FBP] onMethodCall: writeCharacteristic I/flutter (19243): Write error: PlatformException(writeCharacteristic, gatt.writeCharacteristic() returned 201 : ERROR_GATT_WRITE_REQUEST_BUSY, null, null) D/BluetoothGatt(19243): onConnectionUpdated() - Device=BC:02:6E:AF:D9:5B interval=48 latency=30 timeout=600 status=0 E/[FBP-Android](19243): [FBP] onCharacteristicWrite: E/[FBP-Android](19243): [FBP] chr: 6ae5deca-d2d0-4e13-a662-ad16e9a78dde E/[FBP-Android](19243): [FBP] status: UNKNOWN_GATT_ERROR (133) (133) D/BluetoothGatt(19243): onClientConnectionState() - status=22 clientIf=13 device=BC:02:6E:AF:D9:5B D/[FBP-Android](19243): [FBP] onConnectionStateChange:disconnected D/[FBP-Android](19243): [FBP] status: CONNECTION_TERMINATED_BY_LOCAL_HOST D/BluetoothGatt(19243): close() D/BluetoothGatt(19243): unregisterApp() - mClientIf=13 I/flutter (19243): [FBP] [[ OnCharacteristicWritten ]] result: {error_string: UNKNOWN_GATT_ERROR (133), service_uuid: b56c04ea-6cba-4dd4-83b9-7f3056a1bac5, success: 0, remote_id: BC:02:6E:AF:D9:5B, error_code: 133, characteristic_uuid: 6ae5deca-d2d0-4e13-a662-ad16e9a78dde, value: 24532039663065326b2074727565} I/flutter (19243): [FBP] [[ OnConnectionStateChanged ]] result: {disconnect_reason_code: 22, disconnect_reason_string: CONNECTION_TERMINATED_BY_LOCAL_HOST, remote_id: BC:02:6E:AF:D9:5B, connection_state: 0}
相关代码
按钮触发代码
ElevatedButton( onPressed: () { print("isWatchLinkedTo"); for (var service in _services) { if (service.uuid == targetSensorServiceUUID) { for (var characteristic in service.characteristics) { if (characteristic.uuid == targetSensorCharacteristicUUID) { sensorcharacteristic = characteristic; String result = "\$S userId false"; sensorcharacteristic!.setNotifyValue(true); startListening(); _writeCharacteristic(sensorcharacteristic!, result); } } break; } } }, child: Text("isLinked")), ElevatedButton( onPressed: () { print("linkRingTo"); for (var service in _services) { if (service.uuid == targetSensorServiceUUID) { for (var characteristic in service.characteristics) { if (characteristic.uuid == targetSensorCharacteristicUUID) { sensorcharacteristic = characteristic; String result = "\$S userId true"; _writeCharacteristic(sensorcharacteristic!, result); } } break; } } }, child: Text("LinkRing")),
写入与队列逻辑代码
Future<void> _writeCharacteristic( BluetoothCharacteristic characteristic, String value) async { _enqueueOperation(() async { if (_isWriting) return; _isWriting = true; print("Write successful${Uint8List.fromList(utf8.encode(value))}"); try { await characteristic.write(Uint8List.fromList(utf8.encode(value))); print("Write successful${Uint8List.fromList(utf8.encode(value))}"); } catch (e) { print("Write error: $e"); } finally { _isWriting = false; } }); } Future<void> startListening() async { subscription = sensorcharacteristic?.onValueReceived.listen((value) { print("PairCheck New : $value"); }); } void _enqueueOperation(Future Function() operation) { _operationQueue.add(operation); _processQueue(); } Future<void> _processQueue() async { if (_isProcessingQueue) return; _isProcessingQueue = true; while (_operationQueue.isNotEmpty) { final operation = _operationQueue.removeAt(0); await operation(); } _isProcessingQueue = false; }
问题分析
- 队列逻辑冗余:
_isWriting标记与队列的串行处理逻辑重复,若标记未正确重置会导致后续任务直接跳过;同时BLE设备未完成前一次写入ACK时,新的写入请求会触发GATT栈繁忙错误。 - 重复设置Notify:
isLinked按钮每次点击都会调用setNotifyValue(true),重复触发CCCD描述符写入操作,与后续特征写入请求冲突,加剧GATT栈负载。 - 设备响应延迟:同一特征连续写入时,设备未及时处理完前一次请求,导致GATT栈拒绝新请求,最终触发未知错误并断开连接。
解决方案
1. 优化队列逻辑,移除冗余标记
利用队列的串行特性保证单任务执行,移除_isWriting标记:
Future<void> _writeCharacteristic( BluetoothCharacteristic characteristic, String value) async { _enqueueOperation(() async { final bytes = Uint8List.fromList(utf8.encode(value)); print("Writing value: $bytes"); try { await characteristic.write(bytes); print("Write successful: $bytes"); } catch (e) { print("Write error: $e"); } }); }
2. 避免重复开启Notify
添加状态标记,仅在未开启通知时执行setNotifyValue:
// 类内添加状态标记 bool _isNotifyEnabled = false; // 修改isLinked按钮逻辑 if (!_isNotifyEnabled) { await sensorcharacteristic!.setNotifyValue(true); _isNotifyEnabled = true; startListening(); }
3. 增加写入间隔(可选)
针对处理速度较慢的设备,在队列任务间添加短暂延迟:
Future<void> _processQueue() async { if (_isProcessingQueue) return; _isProcessingQueue = true; while (_operationQueue.isNotEmpty) { final operation = _operationQueue.removeAt(0); await operation(); await Future.delayed(Duration(milliseconds: 200)); // 根据设备调整延迟时长 } _isProcessingQueue = false; }
4. 调整写入类型(可选)
若设备支持,使用无响应写入类型避免ACK等待阻塞:
await characteristic.write(bytes, writeType: WriteType.withoutResponse);
内容的提问来源于stack exchange,提问作者avinash Yadav
相关产品推荐
相关产品推荐

