Flutter串口通信插件linux_serial的使用

Flutter串口通信插件linux_serial的使用

Dart包用于在Linux上通过dart:ffi访问串口。

示例用法

/// 获取可用的串口列表
final ports = SerialPorts.ports;
print(ports);

/// 查找名为 `ttyS0` 的串口
final port = ports.singleWhere((p) => p.name == 'ttyS0');

/// 打开串口,以便我们可以读写数据
final handle = port.open(baudrate: Baudrate.b9600);

/// 设置用于将写入的字符串转换为字节以及相反操作的编码
handle.encoding = AsciiCodec();

/// 获取一个新的串口读取器。
/// 这个顺序读取器会缓存所有传入的数据,直到我们从中读取。我们也可以获取另一个顺序读取器,如果这样做,两个构造的顺序读取器可能会发出相同的字符串。
final reader = handle.getNewSequentialReader();

/// 向串口写入 'ATWS' 并跟随一个回车符。这是一个与ELM327通信的例子。ATWS基本上重新启动了ELM。
await handle.write('ATWS\r');

/// 当命令(在这个例子中是重启)完成时,我们会从ELM读取一个回车符和一个 '>'。
/// 我们读取的响应不包括 '\r>'。
var response = await reader.readln('\r>');

await handle.write('ATE0\r');
response = await reader.readln('\r>');

await handle.write('ATL0\r');
response = await reader.readln('\r>');

await handle.write("ATS0");
response = await reader.readln('\r>');

await handle.write('ATI\r');
response = await reader.readln('\r>');
response = response.replaceAll('\r', '');
print('ATI: $response');

await handle.write('01001');
response = await reader.readln('\r>');
response = response.replaceAll('\r', '');
print('01001: $response');

await reader.close();
await handle.close();
print("finished");

完整示例代码

import 'dart:convert';

import 'package:linux_serial/linux_serial.dart';

void main() async {
  // 打印可用的串口列表
  print("ports: ${SerialPorts.ports}");

  // 查找名为 "ttyS0" 的串口
  final port = SerialPorts.ports.singleWhere((element) => element.name == "ttyS0");

  // 打开串口并设置波特率为9600
  final handle = port.open(baudrate: Baudrate.b9600);

  // 设置编码
  handle.encoding = AsciiCodec();

  // 创建一个异步函数来持续读取串口数据
  (() async {
    final reader = handle.getNewSequentialReader();
    while (true) {
      try {
        // 读取一个字节的数据
        final char = await reader.read(numBytes: 1);
        final rune = char.runes.single;

        // 如果字符是可打印的,打印它;否则,打印其十六进制表示
        if (rune >= 0x1f && rune != 0x7F) {
          print('$char');
        } else {
          print('0x${rune.toRadixString(16).toUpperCase()}');
        }
      } on StateError {
        // 如果发生StateError,则关闭读取器并退出循环
        reader.close();
        break;
      }
    }
  })();

  // 获取一个新的顺序读取器
  final reader = handle.getNewSequentialReader();

  // 发送指令并读取响应
  await handle.write('ATWS\r');
  var response = await reader.readln('\r>');

  await handle.write('ATE0\r');
  response = await reader.readln('\r>');

  await handle.write('ATL0\r');
  response = await reader.readln('\r>');

  await handle.write("ATS0");
  response = await reader.readln('\r>');

  await handle.write('ATI\r');
  response = await reader.readln('\r>');
  response = response.replaceAll('\r', '');
  print('ATI: $response');

  await handle.write('01001');
  response = await reader.readln('\r>');
  response = response.replaceAll('\r', '');
  print('01001: $response');

  // 关闭读取器和句柄
  await reader.close();
  await handle.close();
  print("finished");
}

更多关于Flutter串口通信插件linux_serial的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter串口通信插件linux_serial的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中实现串口通信,特别是在Linux平台上,可以使用linux_serial插件。下面是一个使用linux_serial插件进行串口通信的代码示例。

首先,确保你的Flutter项目中已经添加了linux_serial依赖。在你的pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  linux_serial: ^x.y.z  # 替换为最新版本号

然后运行flutter pub get来安装依赖。

接下来,编写Flutter代码来使用linux_serial插件。以下是一个简单的示例,展示了如何打开串口、写入数据以及读取数据。

import 'package:flutter/material.dart';
import 'package:linux_serial/linux_serial.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  SerialPort? _serialPort;
  String _output = "";

  @override
  void initState() {
    super.initState();
    _initSerialPort();
  }

  @override
  void dispose() {
    _closeSerialPort();
    super.dispose();
  }

  Future<void> _initSerialPort() async {
    try {
      // 打开串口,假设串口设备路径为'/dev/ttyUSB0',波特率为9600
      _serialPort = await SerialPort.open('/dev/ttyUSB0', 9600);
      
      // 设置数据读取监听器
      _serialPort!.inputStream.listen((Uint8List data) {
        setState(() {
          _output += String.fromCharCodes(data);
        });
      });
      
      print('Serial port opened successfully');
    } catch (e) {
      print('Failed to open serial port: $e');
    }
  }

  Future<void> _closeSerialPort() async {
    if (_serialPort != null && _serialPort!.isOpen) {
      await _serialPort!.close();
      print('Serial port closed');
    }
  }

  Future<void> _sendData(String data) async {
    if (_serialPort != null && _serialPort!.isOpen) {
      _serialPort!.write(data.codeUnits);
      print('Data sent: $data');
    } else {
      print('Serial port is not open');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Serial Communication'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              TextField(
                decoration: InputDecoration(labelText: 'Enter data to send'),
                onEditingComplete: () {
                  _sendData(TextField.currentTextSelection!.textInside(TextField.currentTextEditingValue!.text)!);
                },
              ),
              SizedBox(height: 16),
              Text('Received Data:', style: TextStyle(fontWeight: FontWeight.bold)),
              Text(_output, style: TextStyle(fontFamily: 'monospace')),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            _closeSerialPort();
            _initSerialPort(); // 重新打开串口(仅示例,实际应用中可能需要更精细的控制)
          },
          tooltip: 'Restart Serial',
          child: Icon(Icons.refresh),
        ),
      ),
    );
  }
}

在这个示例中:

  1. 初始化串口:在initState方法中调用_initSerialPort函数打开串口,并设置数据读取监听器。
  2. 发送数据:在文本字段的onEditingComplete回调中调用_sendData函数发送数据。
  3. 关闭串口:在dispose方法中调用_closeSerialPort函数关闭串口。
  4. UI显示:使用Text组件显示接收到的数据。

请注意,这个示例假设你已经在Linux上设置了串口设备,并且具有访问权限。你可能需要使用sudo chmod命令来设置串口的权限,或者将用户添加到dialout组(或其他适当的组)。

此外,实际应用中可能需要处理更多的错误情况,例如串口打开失败、写入失败等。这个示例仅用于演示基本的串口通信功能。

回到顶部