flutter_libserialport数据流接入COBS decodeCOBSStream异常排查
问题:COBS解码流处理串口数据时中断并抛出ArgumentError
我正在尝试用COBS 0.2.0的decodeCOBSStream函数处理串口数据:通过禁用CR/LF的Hercules终端发送HEX数据,经PC蓝牙传给HC-05模块,模块通过FTDI线连到USB端口。flutter_libserialport能正常读取原始数据并打印到调试控制台,但把数据流传入decodeCOBSStream后,第一条消息能正常打印,有时第二条也可以,之后就停止输出,最终flutter_libserialport的read方法抛出ArgumentError(参数无效:长度需在[0, 4611686018427387903]范围内)。
涉及的flutter_libserialport函数
static Uint8List read(int bytes, UtilFunc<ffi.Uint8> readFunc) { return ffi.using((arena) { final ptr = arena<ffi.Uint8>(bytes); final len = call(() => readFunc(ptr)); return Uint8List.fromList(ptr.asTypedList(len)); }); }
问题定位与完整代码
直接监听upcomingData的Uint8List数据并传给接收Uint8List的onDataReceived时一切正常,问题显然出在decodeCOBSStream的接入方式上——flutter_libserialport用Uint8List,而decodeCOBSStream用ByteData。我试过多种数据传递方式,包括在upcomingData里转成ByteData、用流转换器等,部分尝试代码已注释。完整代码如下:
import 'dart:typed_data'; import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_libserialport/flutter_libserialport.dart'; import 'package:cobs2/cobs2.dart'; const kDebugMode = true; void main() { runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { @override Widget build(BuildContext context) { List<String> availablePort = SerialPort.availablePorts; SerialPort port = SerialPort('COM4'); SerialPortReader reader = SerialPortReader(port); final controller = StreamController<ByteData>(); debugPrint('Available Ports: $availablePort'); /* Stream<ByteData> upcomingData = reader.stream.map((data) { ByteData byteData = data.buffer.asByteData(); return byteData; }); */ // Received the serial data from the SerialPortReader 'reader' Stream<Uint8List> upcomingData = reader.stream.map((data) { return data; }); controller.addStream(decodeCOBSStream(upcomingData.byteData)); // When data is received void onDataReceived(ByteData data) { var decodeUint8 = data.buffer.asUint8List(); var decodedPrt = getHexString(decodeUint8, offset: 0, length: decodeUint8.length); debugPrint('Decoded: $decodedPrt'); } /* // When data is received void onDataReceived(Uint8List data) { var decodedPrt = getHexString(data, offset: 0, length: data.length); debugPrint('Decoded: $decodedPrt'); } */ try { port.openReadWrite(); initSerial(port); // Send data to serial port serialSend(port, 'Ready for data!'); // Creates a listener to receive the decoded data //controller.stream.listen((data) => onDataReceived(data)); controller.stream.listen(onDataReceived).onDone(() {}); //upcomingData.listen(onDataReceived).onDone(() {}); } on SerialPortError catch (err, _) { debugPrint('${SerialPort.lastError}'); port.close(); } return Container(); } } extension on Stream<Uint8List> { Stream<ByteData> get byteData => transform(Uint8ListToByteData()); } // Stream transformer that converts Uint8List data to ByteData. class Uint8ListToByteData extends StreamTransformerBase<Uint8List, ByteData> { @override Stream<ByteData> bind(Stream<Uint8List> stream) { return stream.map((data) => data.buffer.asByteData()); } } Uint8List _stringToUint8List(String data) { List<int> codeUnits = data.codeUnits; Uint8List uint8list = Uint8List.fromList(codeUnits); return uint8list; } // Converts a String of multiple integers into HEX String getHexString( List<int> list, { required int offset, required int length, }) { var sublist = list.getRange(offset, offset + length); return [ for (var byte in sublist) byte.toRadixString(16).padLeft(2, '0').toUpperCase() ].join(); } void initSerial(SerialPort port) { var config = port.config; config.baudRate = 9600; config.bits = 8; config.stopBits = 1; config.parity = 0; port.config = config; debugPrint('BaudRate = 9600'); } void serialSend(SerialPort port, String data) { debugPrint('Written Bytes: ${port.write(_stringToUint8List(data))}'); }
内容的提问来源于stack exchange,提问作者kdesroch1
相关产品推荐
相关产品推荐

