Flutter蓝牙接收ESP32数据遇FormatException:输入意外结束
解决Flutter蓝牙接收JSON时的FormatException问题
问题原因
蓝牙通信的输入流是流式传输,并非每次回调都会完整接收一个JSON数组:
- 可能出现分片接收(一次只收到JSON的一部分)
- 可能收到空数据包、换行符或额外空白字符
- 你当前的代码直接将每次收到的字节转成字符串就解析,遇到不完整的JSON片段或空内容时,就会触发
Unexpected end of input错误
解决方案
1. 缓存数据+按分隔符提取完整JSON
在ESP32端给每个JSON数据包末尾添加固定分隔符(比如\n),Flutter端缓存所有接收的数据,每次按分隔符分割出完整的JSON片段再解析。
修改后的Flutter代码:
String _dataBuffer = ''; final String _delimiter = '\n'; // 和ESP32端保持一致 void _startListening() { _connection!.input!.listen((Uint8List data) { String newData = utf8.decode(data); _dataBuffer += newData; // 循环处理所有完整的JSON片段 while (_dataBuffer.contains(_delimiter)) { int delimiterPos = _dataBuffer.indexOf(_delimiter); String completeJson = _dataBuffer.substring(0, delimiterPos).trim(); // 更新缓存,移除已处理的内容 _dataBuffer = _dataBuffer.substring(delimiterPos + 1); if (completeJson.isNotEmpty) { try { List<dynamic> sensorData = json.decode(completeJson); debugPrint('解析结果: $completeJson'); setState(() { _sensorData = sensorData; }); } catch (e) { debugPrint('解析失败: $e'); } } } }); }
2. ESP32端配合修改
确保ESP32发送JSON时末尾添加分隔符,以Arduino为例:
// 生成JSON字符串后,用println发送(自动追加换行符) Serial.println(jsonString);
3. 关键优化点
- 缓存机制:避免分片数据导致的解析失败
- 错误捕获:用
try-catch包裹JSON解析,防止未处理异常崩溃 - 空数据过滤:跳过空字符串,避免解析空内容触发错误
补充说明
你控制台打印的完整JSON格式是正确的,报错是因为某次回调收到了不完整的片段(比如单独的换行符),直接解析就会抛出异常。流式处理是串口/蓝牙通信的标准方案,能保证数据的完整性。
内容的提问来源于stack exchange,提问作者Kavindu Wijesekara
相关产品推荐
相关产品推荐

