Flutter串口通信插件serial_communication的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter串口通信插件serial_communication的使用

简介

serial_communication 是一个用于Android平台的Flutter插件,支持通过可用端口进行数据读写。主要功能包括:

  • 列出设备上可用的串行端口(包括USB到串行适配器)
  • 配置串行端口(波特率、停止位等)
  • 提供标准的输入输出流

支持的平台

  • Android

安装

pubspec.yaml 文件中添加依赖:

dependencies:
  serial_communication: 0.0.2

导入包:

import 'package:serial_communication/serial_communication.dart';

使用方法

初始化

首先调用 startSerial() 方法并订阅 StreamSubscription

获取可用端口

使用 getAvailablePorts() 方法获取设备上的所有可用端口。

打开端口

使用 openPort() 方法打开串行通信,需要指定数据格式、端口号和波特率。

发送命令

使用 sendCommand() 方法发送消息。

关闭端口

使用 closePort() 方法关闭已打开的端口。

清除日志

使用 clearLog()clearRead() 方法分别清除日志通道和读取通道。

销毁资源

dispose 方法中调用 destroy() 方法以释放资源。

示例代码

以下是一个完整的示例应用,演示了如何使用 serial_communication 插件。

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:serial_communication/serial_communication.dart';

void main() {
  DartPluginRegistrant.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Serial Communication',
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  String logData = "";
  String receivedData = "";
  String selectedPort = "Select Port";
  int selectedBaudRate = SerialCommunication().baudRateList.first;
  List<String>? serialList = [];
  DataFormat format = DataFormat.ASCII;
  SerialCommunication serialCommunication = SerialCommunication();

  @override
  void initState() {
    super.initState();
    serialCommunication.startSerial().listen(_updateConnectionStatus);
    getSerialList();
  }

  getSerialList() async {
    serialList = await serialCommunication.getAvailablePorts();
  }

  @override
  void dispose() {
    serialCommunication.destroy();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        resizeToAvoidBottomInset: false,
        appBar: AppBar(
          title: const Text('Serial Communication Example'),
        ),
        body: SingleChildScrollView(
          physics: const NeverScrollableScrollPhysics(),
          child: Padding(
            padding: const EdgeInsets.all(10.0),
            child: Column(
              children: [
                setupButton(context),
                const Divider(),
                operations(),
                const Divider(),
                sendCommand(),
                const Divider(),
                response()
              ],
            ),
          ),
        ),
      ),
    );
  }

  // 其他UI相关函数...

  void _updateConnectionStatus(SerialResponse? result) async {
    setState(() {
      logData = result!.logChannel ?? "";
      receivedData = result.readChannel ?? "";
    });
  }

  // 更多UI相关函数...
}

const mediumStyle = TextStyle(
  fontSize: 20,
  fontWeight: FontWeight.bold,
);

Android 设置

初始化

调用 startSerial() 方法并订阅 StreamSubscription

SerialCommunication serialCommunication = SerialCommunication();

@override
void initState() {
  super.initState();
  serialCommunication.startSerial().listen(_updateConnectionStatus);
  getSerialList();
}

void _updateConnectionStatus(SerialResponse? result) async {
  logData = result!.logChannel ?? "";
  receivedData = result.readChannel ?? "";
}

获取可用端口

serialList = await serialCommunication.getAvailablePorts();

打开端口

serialCommunication.openPort(
  dataFormat: DataFormat.ASCII,
  serialPort: serialList.first,
  baudRate: serialCommunication.baudRateList.first
);

关闭端口

serialCommunication.closePort();

发送命令

serialCommunication.sendCommand(message: "message");

清除日志

serialCommunication.clearLog();
serialCommunication.clearRead();

销毁资源

@override
void dispose() {
  serialCommunication.destroy();
  super.dispose();
}

通过以上步骤,您可以轻松实现Flutter应用中的串口通信功能。希望这些信息对您有所帮助!


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

1 回复

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


当然,以下是一个关于如何在Flutter应用中使用serial_communication插件进行串口通信的代码示例。请确保你已经添加了serial_communication插件到你的pubspec.yaml文件中。

首先,你需要在pubspec.yaml文件中添加依赖项:

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

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

接下来,是一个简单的示例代码,展示如何使用serial_communication插件进行串口通信。

1. 主文件 main.dart

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

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

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

class _MyAppState extends State<MyApp> {
  SerialPort? _serialPort;
  String _dataReceived = '';

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

  Future<void> _initSerialPort() async {
    SerialCommunication serialCommunication = SerialCommunication();
    
    // 请求权限(Android上需要)
    bool hasPermission = await serialCommunication.requestPermission();
    if (!hasPermission) {
      print("Permission denied");
      return;
    }

    // 获取可用的串口列表
    List<String> ports = await serialCommunication.getPortList();
    print("Available Ports: $ports");

    // 打开串口(假设我们使用第一个串口)
    if (ports.isNotEmpty) {
      _serialPort = await serialCommunication.openPort(ports[0], 9600);
      _serialPort!.inputStream!.listen((Uint8List data) {
        setState(() {
          _dataReceived += String.fromCharCodes(data);
        });
      });
    } else {
      print("No ports available");
    }
  }

  Future<void> _sendData(String data) async {
    if (_serialPort != null && _serialPort!.isOpen!) {
      _serialPort!.write(data.codeUnits);
    } else {
      print("Port is not open");
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Serial Communication Demo'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Text('Received Data:', style: TextStyle(fontSize: 18)),
              Text(_dataReceived, style: TextStyle(fontSize: 16)),
              SizedBox(height: 20),
              TextField(
                decoration: InputDecoration(labelText: 'Send Data'),
                onChanged: (value) {
                  // 当用户输入时,可以立即发送数据(这里仅作为示例)
                  // 实际应用中,可能需要一个发送按钮
                  _sendData(value);
                },
              ),
            ],
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _serialPort?.close();
    super.dispose();
  }
}

2. 注意事项

  1. 权限处理:在Android上,你需要处理运行时权限。上述代码已经包含了请求权限的部分,但你可能需要在AndroidManifest.xml中添加一些必要的权限声明,例如:

    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
    

    注意:实际所需权限可能因具体需求而异,MANAGE_EXTERNAL_STORAGE是一个较为宽泛的权限,实际项目中应根据需要申请最小权限集。

  2. 错误处理:为了简化示例,错误处理部分被省略了。在实际应用中,你应该添加适当的错误处理逻辑,例如处理串口打开失败、数据发送失败等情况。

  3. UI交互:上述示例中,TextField的onChanged回调直接调用了_sendData方法,这意味着用户每输入一个字符都会发送数据。在实际应用中,你可能希望用户点击一个按钮来发送数据。

  4. 跨平台兼容性serial_communication插件可能在不同平台上有不同的行为,确保在目标平台上进行充分的测试。

这个示例提供了一个基本的框架,展示了如何在Flutter应用中使用serial_communication插件进行串口通信。根据你的具体需求,你可能需要进一步定制和扩展这个示例。

回到顶部