- 添加Ch934xMode和GpioDirection枚举类定义 - 实现GPIO方向控制相关方法(setGpioDir/queryGpioDirFromCache) - 添加GPIO使能控制(enableGpio)和数量/组数查询(getGpiocount/getGpiogroup) - 实现串口参数配置(setSerialParameter)包括波特率/数据位/停止位/校验位/流控 - 添加Break信号控制(setBreak)功能 - 实现当前串口模式查询(getCurrentMode) - 添加设备连接状态查询(isConnected)和已打开设备列表获取(getConnectedDevices) - 更新文档说明GPIO方向控制和串口参数配置用法 - 在示例应用中添加相关功能按钮和操作逻辑
532 lines
19 KiB
Markdown
532 lines
19 KiB
Markdown
# ch934x_serial 插件使用说明
|
|
|
|
`ch934x_serial` 是基于南京沁恒微电子 **CH934X 系列** USB 转多串口芯片
|
|
Android SDK 封装的 Flutter 插件,文档面向其他 Flutter 开发者,介绍
|
|
如何把它集成到自己的应用中并使用全部对外 API。
|
|
|
|
> 全部接口语义与官方 Android 文档 `docs/CH934X_Android_开发说明.md`
|
|
> 保持一致,本说明不再重复其原始描述,而是说明在 Flutter 中如何调用。
|
|
|
|
---
|
|
|
|
## 1. 插件概述
|
|
|
|
- **支持的平台:** Android(已实现,iOS / Web / Desktop 暂不支持)。
|
|
- **主要能力:**
|
|
- CH934X 设备枚举、序列号读取、芯片类型识别
|
|
- 多串口打开 / 关闭 / **同设备内串口切换**
|
|
- 字节级串口读写
|
|
- GPIO 输出 / 输入 / 方向控制 / 使能
|
|
- Modem 控制 (DTR/RTS) 与状态 (CTS/DSR/RI/DCD) 读取
|
|
- **主动申请 USB 权限**
|
|
- **Break 信号控制**
|
|
- **串口参数配置(波特率/数据位/停止位/校验/流控)**
|
|
- **查询设备连接状态与已打开设备列表**
|
|
- **查询 GPIO 数量、组信息**
|
|
- 设备拔出、Modem 错误等异常事件回调
|
|
- **底层依赖:** 沁恒官方 `CH934XLib.jar`(插件随包发布,位于
|
|
`android/libs/CH934XLib.jar`),通过原生 `CH934XManager` 单例直接调用,
|
|
无需在调用方业务代码中额外处理反射。
|
|
- **平台通道名称:** `ch934x_serial`
|
|
- **Dart 包名:** `ch934x_serial`(主类 `Ch934xSerial`)
|
|
- **Android 包名:** `com.xiarui.ch934x_serial`
|
|
|
|
---
|
|
|
|
## 2. 集成步骤
|
|
|
|
### 2.1 在 `pubspec.yaml` 中加入依赖
|
|
|
|
```yaml
|
|
dependencies:
|
|
flutter:
|
|
sdk: flutter
|
|
ch934x_serial: ^1.0.0
|
|
```
|
|
|
|
执行 `flutter pub get` 完成依赖拉取。
|
|
|
|
### 2.2 Android 工程准备
|
|
|
|
1. 确认 `android/app/build.gradle` 中 `minSdk >= 24`,CH934X SDK 不支持
|
|
更低版本。
|
|
2. **无需在 `AndroidManifest.xml` 中声明 USB Host 能力**——插件自带
|
|
`android/src/main/AndroidManifest.xml` 已声明
|
|
`<uses-feature android:name="android.hardware.usb.host" required="true" />`,
|
|
应用侧合并后即可生效。
|
|
3. **USB 权限处理可省略**——`openPort` 在底层若检测到未授权,会自动
|
|
调用 `UsbManager.requestPermission` 弹出系统对话框并等待用户回应;
|
|
也可以在业务侧通过 `requestUsbPermission(deviceId)` 提前主动申请。
|
|
插件内部 `BroadcastReceiver` 会在需要时动态注册/反注册,无需在
|
|
`AndroidManifest.xml` 中额外声明。
|
|
|
|
> 如果你仍想自己接管权限流程(例如在主界面"刷新设备列表"之后
|
|
> 立刻弹一次授权请求),直接调用 `Ch934xSerial.requestUsbPermission`
|
|
> 即可,内部会等待用户的回应并以 `bool` 返回结果。
|
|
|
|
### 2.3 第一次调用
|
|
|
|
```dart
|
|
import 'package:ch934x_serial/ch934x_serial.dart';
|
|
|
|
Future<void> scan() async {
|
|
final plugin = Ch934xSerial();
|
|
final devices = await plugin.getDeviceList();
|
|
for (final d in devices) {
|
|
debugPrint('发现设备: VID=0x${d.vendorId.toRadixString(16)} '
|
|
'SN=${d.serialNumber}');
|
|
}
|
|
}
|
|
```
|
|
|
|
> **注意:** `getSerialPortList` 在设备尚未 `openPort` 时会返回空
|
|
> 列表,因为 SDK 的 `getSerialCount` 必须先 `openDevice` 才能返回
|
|
> 真实值。完整流程是:扫描 → 选设备 → `openPort` →
|
|
> `getSerialPortList` 拿真实串口数,详见 §3.2。
|
|
|
|
---
|
|
|
|
## 3. API 接口说明
|
|
|
|
所有 API 都挂在 `Ch934xSerial` 单例上,命名风格与原 SDK 文档保持一致,
|
|
参数使用 `int` 表示芯片/引脚编号,数据以 `Uint8List` 形式传递。
|
|
|
|
### 3.1 设备查找
|
|
|
|
| Dart 方法 | 原 SDK 接口 | 说明 |
|
|
| --------- | ----------- | ---- |
|
|
| `getDeviceList()` | `CH934XManager.enumDevice` + `getChipType` | 获取全部 CH934X 设备 |
|
|
| `getSerialNumber(deviceId)` | `UsbDevice.getSerialNumber` | 获取指定设备的序列号 |
|
|
| `getDeviceType(deviceId)` | `CH934XManager.getChipType` | 获取设备类型常量 |
|
|
| `getSerialPortList(deviceId, interfaceNumber: n)` | `CH934XManager.getSerialCount` | 获取设备串口列表(需先 `openPort`) |
|
|
|
|
返回类型:
|
|
|
|
- `getDeviceList()` → `List<Ch934xDeviceInfo>`
|
|
- `getSerialPortList(...)` → `List<Ch934xSerialPortInfo>`
|
|
- `Ch934xDeviceInfo` 包含 `deviceId / vendorId / productId / deviceType /
|
|
serialNumber / productName / manufacturerName / interfaceCount /
|
|
serialPorts`,可通过 `isCh934x` 判定是否被识别为 CH934X 设备。
|
|
- **`isCh934x`:** 当 `deviceType` 落在 `ch9344..ch934xOther` 范围内
|
|
时返回 `true`(`unknown = -1` 不算)。
|
|
- `Ch934xSerialPortInfo` 包含 `portIndex / devicePath / driverName`。
|
|
- `deviceType` 取值为 `Ch934xDeviceType` 中的常量(`ch9344`、`ch9344L`、
|
|
`ch9350`、`ch9348Q`、`ch9342`、`ch934xOther`,未识别为 `unknown = -1`)。
|
|
|
|
### 3.2 设备打开、关闭与串口切换
|
|
|
|
```dart
|
|
final target = Ch934xPortTarget(
|
|
deviceId: device.deviceId,
|
|
interfaceNumber: 0, // 多数设备只有 1 个接口
|
|
serialPortIndex: port.portIndex,
|
|
);
|
|
final ok = await plugin.openPort(target);
|
|
if (!ok) {
|
|
debugPrint('打开失败');
|
|
return;
|
|
}
|
|
// ... 进行业务通信
|
|
await plugin.closePort();
|
|
```
|
|
|
|
- `Ch934xPortTarget` 封装了 `deviceId` / `interfaceNumber` /
|
|
`serialPortIndex` 三个参数,可通过 `toMap()` 调试其字段,也可
|
|
通过 `Ch934xPortTarget.fromMap` 从 MethodChannel 回包中还原。
|
|
- **`openPort` 内部会自动处理 USB 权限申请**:若 SDK 抛
|
|
`NoPermissionException`,会主动调起系统对话框并等待用户回应
|
|
(最多 60 秒),授权成功后会自动重试 `openDevice`。
|
|
- **同设备内串口切换(`setActivePort`)**:CH934X 设备一次 `openPort`
|
|
之后所有串口都已连接,后续读写只需切换 `serialPortIndex`,
|
|
无需重新 `open`。`setActivePort(idx)` 仅切换当前活跃串口,
|
|
不重复打开设备:
|
|
|
|
```dart
|
|
// 串口 #0 已打开,切换到 #2
|
|
await plugin.setActivePort(2);
|
|
```
|
|
|
|
- **主动申请 USB 权限**(`requestUsbPermission`):
|
|
|
|
```dart
|
|
final granted = await plugin.requestUsbPermission(device.deviceId);
|
|
if (granted) {
|
|
// 用户已授权,可继续 openPort
|
|
}
|
|
```
|
|
|
|
- 同一会话仅保留最近一次打开的串口对象,与原 SDK 行为一致;打开新
|
|
串口前请先 `closePort()` 或在 `finally` 块中清理。
|
|
|
|
### 3.3 串口读写
|
|
|
|
```dart
|
|
// 写入
|
|
final bytes = Uint8List.fromList([0x01, 0x02, 0x03]);
|
|
final written = await plugin.write(bytes);
|
|
debugPrint('写入字节数: $written');
|
|
|
|
// 读取(单次)
|
|
final recv = await plugin.read(1024);
|
|
if (recv.isEmpty) debugPrint('暂无数据');
|
|
|
|
// 持续接收:使用 dataStream
|
|
final sub = plugin.dataStream(chunkSize: 1024).listen((chunk) {
|
|
debugPrint('收到: $chunk');
|
|
});
|
|
// 取消订阅
|
|
await sub.cancel();
|
|
```
|
|
|
|
- `read(length)` 返回 `Uint8List`,无数据或失败时为空。
|
|
- `length <= 0` 时**不会调用原生层**,直接返回空数组。
|
|
- SDK 的 `readData` 会返回内部缓冲的所有数据,插件按
|
|
`min(data.length, length)` 截断后回传。
|
|
- `write(data)` 返回实际写入字节数,失败时为 0。
|
|
- `dataStream` 默认 `chunkSize = 1024`、`interval = 20ms`,内部
|
|
持续以 [interval] 为周期反复调用 `read`;当底层无数据时返回
|
|
空缓冲区,消费者可据此判定。`chunkSize <= 0` 会抛
|
|
`ArgumentError`。
|
|
- 业务方在 widget dispose 时记得 `cancel` 订阅并 `closePort`。
|
|
- `read`/`write` 都针对**当前活跃串口**;切换串口用 `setActivePort`。
|
|
|
|
### 3.4 GPIO 接口
|
|
|
|
```dart
|
|
// 设置 GPIO 输出电平
|
|
final ok = await plugin.setGpioOutput(gpioNumber: 0, level: 1);
|
|
|
|
// 读取 GPIO 输入电平(负值表示失败)
|
|
final value = await plugin.getGpioInput(0);
|
|
```
|
|
|
|
- `gpioNumber` 与 `level` 与原文档保持一致(0/1)。
|
|
- `getGpioInput` 失败时返回 -1,业务方需要自行处理。
|
|
- GPIO 操作同样作用于**当前活跃串口**。
|
|
|
|
### 3.4.1 GPIO 方向控制
|
|
|
|
```dart
|
|
// 使能 GPIO(需要先获取 chipType,可从 Ch934xDeviceInfo.deviceType 取得)
|
|
await plugin.enableGpio(chipType: device.deviceType, gpioGroup: 0, enable: 1);
|
|
|
|
// 设置 GPIO 方向
|
|
await plugin.setGpioDir(gpioGroup: 0, gpioNumber: 0, dir: GpioDirection.out);
|
|
|
|
// 从缓存查询 GPIO 方向
|
|
final dir = await plugin.queryGpioDirFromCache(gpioGroup: 0, gpioNumber: 0);
|
|
if (dir == GpioDirection.out) { /* 输出 */ }
|
|
|
|
// 查询 GPIO 数量与组数
|
|
final count = await plugin.getGpiocount(device.deviceId);
|
|
final groups = await plugin.getGpiogroup(device.deviceId);
|
|
```
|
|
|
|
- `GpioDirection` 常量: `in_ = 0`(输入)、`out = 1`(输出)。
|
|
- `enableGpio` 的 `enable` 参数: CH9344 传 1/0 控制整组;CH348 使用位掩码。
|
|
- 方向查询返回 -1 表示失败。
|
|
- `getGpiocount`/`getGpiogroup` 失败时返回 -1,需先 `openPort`。
|
|
|
|
### 3.5 Modem 控制接口
|
|
|
|
```dart
|
|
await plugin.setModemControl(dtr: 1, rts: 0);
|
|
final status = await plugin.getModemStatus();
|
|
if (ModemStatus.isSet(status, ModemStatus.cts)) {
|
|
debugPrint('CTS 高电平');
|
|
}
|
|
```
|
|
|
|
- `ModemStatus` 暴露位掩码常量 `cts(0x01) / dsr(0x02) / ri(0x04) /
|
|
dcd(0x08)` 与工具方法 `isSet(status, mask)`,取值与文档表格一致。
|
|
- `getModemStatus()` 返回**最近一次由 SDK 回调推送的位掩码**;
|
|
若 SDK 尚未推送过任何状态,返回 0。业务方注意判空。
|
|
|
|
### 3.6 异常回调
|
|
|
|
```dart
|
|
final sub = await plugin.setExceptionCallback((event) {
|
|
debugPrint('设备异常: ${event.type} ${event.message}');
|
|
// 业务方应主动关闭串口、刷新设备列表或提示用户重新插拔
|
|
});
|
|
|
|
// 主动取消监听
|
|
await sub.cancel();
|
|
```
|
|
|
|
- 异常类型见 `Ch934xExceptionType`:
|
|
- `deviceDetached = 1`:设备被拔出(由 SDK 的 `usbDeviceDetach` 触发)。
|
|
- `ioError = 2`:Modem overrun / parity / frame 等错误。
|
|
- `sdk = 3`:原生 SDK 主动抛出的其他异常(目前未触发,保留语义)。
|
|
- `unknown = 0`:未识别(当前未触发,保留语义)。
|
|
- `Ch934xException` 包含 `type / message / cause`,`toString()` 会把
|
|
`type` 翻译为对应的常量名,方便日志/UI 显示。
|
|
- 返回的 `StreamSubscription` **必须在合适时机 `cancel`**,以便
|
|
释放底层 `StreamController` 与 `MethodCallHandler`。
|
|
|
|
### 3.7 其他接口
|
|
|
|
#### 3.7.1 Break 信号
|
|
|
|
```dart
|
|
final ok = await plugin.setBreak(true); // 设置 Break(低电平有效)
|
|
```
|
|
|
|
- 作用于**当前活跃串口**。
|
|
|
|
#### 3.7.2 获取当前串口模式
|
|
|
|
```dart
|
|
final mode = await plugin.getCurrentMode();
|
|
// mode 取值见 Ch934xMode 常量
|
|
```
|
|
|
|
- `Ch934xMode` 常量: `normal = 0`(普通)、`hardflow = 1`(硬件流控)、`gpio = 2`(GPIO)。
|
|
- **仅对 CH934X 型号有效**,CH348 返回 -1。
|
|
|
|
#### 3.7.3 设备连接状态
|
|
|
|
```dart
|
|
final connected = await plugin.isConnected(device.deviceId);
|
|
final ids = await plugin.getConnectedDevices();
|
|
```
|
|
|
|
- `isConnected`: 查询指定设备是否已被打开。
|
|
- `getConnectedDevices`: 返回当前已打开设备的 `deviceId` 列表。
|
|
|
|
### 3.8 串口参数配置
|
|
|
|
```dart
|
|
// 配置波特率为 9600
|
|
final ok = await plugin.setSerialParameter(
|
|
baud: 9600,
|
|
dataBit: 8,
|
|
stopBit: 1,
|
|
parityBit: 0,
|
|
flow: false,
|
|
);
|
|
```
|
|
|
|
- 作用于**当前活跃串口**。`openPort` 内部默认设为 `115200/8/1/N/无流控`,
|
|
如需修改可在此之后调用。
|
|
- `stopBit`: 0=1 停止位,1=1.5 停止位,2=2 停止位。
|
|
- `parityBit`: 0=无校验,1=奇校验,2=偶校验。
|
|
|
|
---
|
|
|
|
## 4. 完整示例
|
|
|
|
```dart
|
|
final sub = await plugin.setExceptionCallback((event) {
|
|
debugPrint('设备异常: ${event.type} ${event.message}');
|
|
// 业务方应主动关闭串口、刷新设备列表或提示用户重新插拔
|
|
});
|
|
|
|
// 主动取消监听
|
|
await sub.cancel();
|
|
```
|
|
|
|
- 异常类型见 `Ch934xExceptionType`:
|
|
- `deviceDetached = 1`:设备被拔出(由 SDK 的 `usbDeviceDetach` 触发)。
|
|
- `ioError = 2`:Modem overrun / parity / frame 等错误。
|
|
- `sdk = 3`:原生 SDK 主动抛出的其他异常(目前未触发,保留语义)。
|
|
- `unknown = 0`:未识别(当前未触发,保留语义)。
|
|
- `Ch934xException` 包含 `type / message / cause`,`toString()` 会把
|
|
`type` 翻译为对应的常量名,方便日志/UI 显示。
|
|
- 返回的 `StreamSubscription` **必须在合适时机 `cancel`**,以便
|
|
释放底层 `StreamController` 与 `MethodCallHandler`。
|
|
|
|
---
|
|
|
|
## 4. 完整示例
|
|
|
|
下面给出一个最小可运行示例,演示"扫描 → 打开 → 收发 → 关闭"的完整
|
|
流程,完整可交互的 demo 见 `example/lib/main.dart`。
|
|
|
|
```dart
|
|
import 'dart:async';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:ch934x_serial/ch934x_serial.dart';
|
|
|
|
class SerialBridge {
|
|
SerialBridge() : _plugin = Ch934xSerial();
|
|
|
|
final Ch934xSerial _plugin;
|
|
StreamSubscription<Ch934xException>? _exceptionSub;
|
|
StreamSubscription<Uint8List>? _dataSub;
|
|
|
|
Future<void> connect(Ch934xDeviceInfo device, Ch934xSerialPortInfo port) async {
|
|
final opened = await _plugin.openPort(
|
|
Ch934xPortTarget(
|
|
deviceId: device.deviceId,
|
|
interfaceNumber: 0,
|
|
serialPortIndex: port.portIndex,
|
|
),
|
|
);
|
|
if (!opened) throw StateError('串口打开失败');
|
|
|
|
_exceptionSub = await _plugin.setExceptionCallback((e) {
|
|
// 设备拔出时通常会触发 deviceDetached。
|
|
print('异常: $e');
|
|
});
|
|
|
|
_dataSub = _plugin.dataStream().listen((chunk) {
|
|
print('接收: $chunk');
|
|
});
|
|
}
|
|
|
|
Future<void> sendString(String s) async {
|
|
final bytes = Uint8List.fromList(s.codeUnits);
|
|
await _plugin.write(bytes);
|
|
}
|
|
|
|
/// 切换到同一设备的另一个串口,无需重新 open。
|
|
Future<void> switchToPort(int index) async {
|
|
await _plugin.setActivePort(index);
|
|
}
|
|
|
|
Future<void> dispose() async {
|
|
await _dataSub?.cancel();
|
|
await _exceptionSub?.cancel();
|
|
await _plugin.closePort();
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 5. 平台接口与单元测试
|
|
|
|
插件使用 `plugin_platform_interface` 暴露抽象层 `Ch934xSerialPlatform`,
|
|
默认实现是 `MethodChannelCh934xSerial`(绑定到 `ch934x_serial` 通道)。
|
|
注入自定义平台实现即可在宿主测试中验证上层逻辑,无需启动 Android:
|
|
|
|
```dart
|
|
import 'package:ch934x_serial/ch934x_serial.dart';
|
|
import 'package:ch934x_serial/ch934x_serial_method_channel.dart';
|
|
import 'package:ch934x_serial/ch934x_serial_platform_interface.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
|
|
|
class FakePlatform extends Ch934xSerialPlatform with MockPlatformInterfaceMixin {
|
|
@override
|
|
Future<List<Ch934xDeviceInfo>> getDeviceList() async => const [];
|
|
// ... 其它方法按需返回
|
|
}
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
test('替换为 mock 后 Ch934xSerial 委托给 fake', () async {
|
|
Ch934xSerialPlatform.instance = FakePlatform();
|
|
final plugin = Ch934xSerial();
|
|
expect(await plugin.getDeviceList(), isEmpty);
|
|
});
|
|
}
|
|
```
|
|
|
|
也可以直接用 `Ch934xSerial.withPlatform(fake)` 局部注入,避免污染
|
|
`Ch934xSerialPlatform.instance`。完整 mock 示例见
|
|
`test/ch934x_serial_test.dart` 与 `test/ch934x_serial_method_channel_test.dart`。
|
|
|
|
---
|
|
|
|
## 6. 常见问题(FAQ)
|
|
|
|
**Q1. `getDeviceList()` 返回空数组。**
|
|
- 确认 OTG 数据线连接稳固。
|
|
- 部分设备需要先在系统设置中开启"USB 调试"或插入 OTG 后等几秒。
|
|
- 确认 `minSdk >= 24`。
|
|
|
|
**Q2. `openPort()` 返回 false。**
|
|
- 多数情况是 USB 权限未授予:确认 `requestUsbPermission` /
|
|
`openPort` 内部弹出的授权框被用户点击了"允许"。
|
|
- 如果目标设备具有多个接口,请尝试修改 `interfaceNumber`。
|
|
- 确认设备中至少有一个 `Ch934xSerialPortInfo`(`getSerialPortList`
|
|
返回),否则原 SDK 也无法打开。**注意:** 该方法必须先 `openPort`
|
|
才返回真实数据,枚举阶段调用只会得到空列表。
|
|
|
|
**Q3. `read()` 一直返回空数组。**
|
|
- 确认对端设备正在发送数据,且波特率/校验位等参数匹配。可通过
|
|
`setSerialParameter(baud: 9600, dataBit: 8, stopBit: 1, parityBit: 0, flow: false)`
|
|
配置串口参数。
|
|
- 检查线序:RX/TX 是否接反,以及硬件流控是否正确。
|
|
- 确认 `setActivePort` 已切换到正确的串口索引。
|
|
|
|
**Q4. `setExceptionCallback` 没有触发。**
|
|
- 本插件仅在原生层主动推送时才会触发回调,目前沁恒 SDK 在以下
|
|
场景会自动调用:设备热拔插(`usbDeviceDetach`)、USB 权限被
|
|
拒绝(`usbDevicePermission(result=false)`)、Modem overrun /
|
|
parity / frame 错误。其他异常(超时、CRC 错误等)目前不会
|
|
触发,可在原生层 `Ch934xSerialPlugin.java` 中扩展
|
|
`MethodChannel.invokeMethod("onException", payload)` 上报。
|
|
|
|
**Q5. 是否支持 iOS / 桌面 / Web?**
|
|
- 当前仅在 Android 端验证通过;`CH934XLib.jar` 由沁恒官方提供
|
|
Android 端 SDK,其他平台需要厂商另行提供或自行实现。
|
|
|
|
**Q6. 如何做单元测试?**
|
|
- 注入自定义的 `Ch934xSerialPlatform` 即可,详见 §5。
|
|
|
|
**Q7. 同一设备如何在多个串口之间切换?**
|
|
- 使用 `setActivePort(serialPortIndex)`,无需重新 `openPort`。
|
|
`openPort` 之后该设备的所有串口都已连接,后续读写/GPIO/Modem
|
|
都作用于"当前活跃串口"。
|
|
|
|
**Q8. Android 侧需要哪些初始化?**
|
|
- 插件自带 `<uses-feature android:name="android.hardware.usb.host" />`。
|
|
- 业务侧不需要在 `AndroidManifest.xml` 中声明 USB 权限
|
|
`BroadcastReceiver`——插件会在需要时动态注册(`NOT_EXPORTED`)。
|
|
- 若希望应用启动即初始化 SDK,可在 `Application.onCreate` 中
|
|
调用 `CH934XManager.getInstance().init(this)`;不调用也不影响
|
|
插件工作,插件会在 `onAttachedToEngine` 兜底初始化。
|
|
|
|
---
|
|
|
|
## 7. 接口总览
|
|
|
|
下表汇总插件中暴露的全部 API,具体调用示例见上文第 3 节。
|
|
|
|
| Dart 方法 | 文档编号 | 分类 |
|
|
| --------- | -------- | ---- |
|
|
| `getDeviceList` | 4.1.4 | 设备查找 |
|
|
| `getSerialNumber` | 4.1.1 | 设备查找 |
|
|
| `getDeviceType` | 4.1.2 | 设备查找 |
|
|
| `getSerialPortList` | 4.1.3 | 设备查找 |
|
|
| `openPort` | 5.1.1 | 设备打开 |
|
|
| `closePort` | 5.2.1 | 设备关闭 |
|
|
| `setActivePort` | 5.1 增强 | 串口切换(插件新增) |
|
|
| `requestUsbPermission` | 2.2 增强 | 主动授权(插件新增) |
|
|
| `read` | 6.1.1 | 串口读写 |
|
|
| `write` | 6.2.1 | 串口读写 |
|
|
| `setSerialParameter` | setSerialParameter | 串口参数 |
|
|
| `setBreak` | setBreak | 其他 |
|
|
| `getCurrentMode` | getCurrentMode | 其他 |
|
|
| `isConnected` | isConnected | 设备状态 |
|
|
| `getConnectedDevices` | getConnectedDevices | 设备状态 |
|
|
| `setGpioOutput` | setGPIOValue | GPIO |
|
|
| `getGpioInput` | getGPIOValue | GPIO |
|
|
| `setGpioDir` | setGPIODir | GPIO 方向 |
|
|
| `queryGpioDirFromCache` | queryGPIODirFromCache | GPIO 方向 |
|
|
| `enableGpio` | enableGPIO | GPIO |
|
|
| `getGpiocount` | getGPIOCount | GPIO |
|
|
| `getGpiogroup` | getGPIOGroup | GPIO |
|
|
| `setModemControl` | 7.2.1 | Modem |
|
|
| `getModemStatus` | 7.2.2 | Modem |
|
|
| `setExceptionCallback` | 7.3.1 | 异常 |
|
|
| `dataStream` | 6.1 增强 | 串口流(插件新增) |
|
|
| `portDataStream` | 6.1 增强 | 多端口轮询流(插件新增) |
|
|
|
|
---
|
|
|
|
## 8. 反馈与贡献
|
|
|
|
遇到问题请提供:
|
|
|
|
- 复现步骤(设备型号、Android 版本、是否开启 USB 调试)
|
|
- 完整日志(建议使用 `adb logcat` 过滤 `ch934x_serial` 标签)
|
|
- 期望结果 vs 实际结果
|
|
|
|
提交 Issue 时附上以上信息可以大幅加快排查速度。
|