Flutter串口通信插件serial_communication的使用

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插件进行串口通信。根据你的具体需求,你可能需要进一步定制和扩展这个示例。

回到顶部