You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 20:35:03