feat(ch934x): 添加GPIO方向控制和串口参数配置功能

- 添加Ch934xMode和GpioDirection枚举类定义
- 实现GPIO方向控制相关方法(setGpioDir/queryGpioDirFromCache)
- 添加GPIO使能控制(enableGpio)和数量/组数查询(getGpiocount/getGpiogroup)
- 实现串口参数配置(setSerialParameter)包括波特率/数据位/停止位/校验位/流控
- 添加Break信号控制(setBreak)功能
- 实现当前串口模式查询(getCurrentMode)
- 添加设备连接状态查询(isConnected)和已打开设备列表获取(getConnectedDevices)
- 更新文档说明GPIO方向控制和串口参数配置用法
- 在示例应用中添加相关功能按钮和操作逻辑
This commit is contained in:
Developer
2026-07-07 16:15:11 +08:00
parent 4813e79c80
commit 020904bd2a
8 changed files with 765 additions and 9 deletions
+3 -2
View File
@@ -1,7 +1,8 @@
# ch934x_serial
Flutter 插件:封装南京沁恒微电子 **CH934X 系列** USB 转多串口芯片的
Android SDK,提供设备查找、串口读写、GPIOModem 控制等能力。
Android SDK,提供设备枚举、串口读写、GPIO/Modem 控制、Break 信号、
串口参数配置、设备状态查询等完整能力。
## 文档
@@ -26,5 +27,5 @@ final devices = await plugin.getDeviceList();
## 平台支持
- ✅ Android(基于 `CH934XLib.jar` 反射桥接)
- ✅ Android(基于 `CH934XLib.jar`)
- ❌ iOS / Web / Desktop(暂未实现)
@@ -229,6 +229,36 @@ public class Ch934xSerialPlugin implements FlutterPlugin, MethodCallHandler, Act
exceptionCallbackEnabled = true;
result.success(null);
break;
case "setBreak":
result.success(handleSetBreak(call));
break;
case "getCurrentMode":
result.success(handleGetCurrentMode(call));
break;
case "getGPIOCount":
result.success(handleGetGPIOCount(call));
break;
case "getGPIOGroup":
result.success(handleGetGPIOGroup(call));
break;
case "enableGPIO":
result.success(handleEnableGPIO(call));
break;
case "setGPIODir":
result.success(handleSetGPIODir(call));
break;
case "queryGPIODirFromCache":
result.success(handleQueryGPIODirFromCache(call));
break;
case "isConnected":
result.success(handleIsConnected(call));
break;
case "getConnectedDevices":
result.success(handleGetConnectedDevices());
break;
case "setSerialParameter":
result.success(handleSetSerialParameter(call));
break;
default:
result.notImplemented();
}
@@ -637,6 +667,187 @@ public class Ch934xSerialPlugin implements FlutterPlugin, MethodCallHandler, Act
return modemStatusCache;
}
// ------------------------------------------------------------------------
// 新增接口(对应文档 setBreak / querySerialErrorCount / getCurrentMode / …)
// ------------------------------------------------------------------------
/** 文档 setBreak。 */
private boolean handleSetBreak(@NonNull MethodCall call) {
if (activeDevice == null || activeSerialNumber < 0) {
return false;
}
Boolean valid = call.argument("valid");
if (valid == null) {
return false;
}
try {
return CH934XManager.getInstance().setBreak(
activeDevice, activeSerialNumber, valid);
} catch (Throwable t) {
return false;
}
}
/** 文档 getCurrentMode。 */
private int handleGetCurrentMode(@NonNull MethodCall call) {
if (activeDevice == null || activeSerialNumber < 0) {
return -1;
}
try {
Mode mode = CH934XManager.getInstance().getCurrentMode(
activeDevice, activeSerialNumber);
if (mode == null) return -1;
String name = mode.name();
if ("NORMAL".equals(name)) return 0;
if ("HARDFLOW".equals(name)) return 1;
if ("GPIO".equals(name)) return 2;
return -1;
} catch (Throwable t) {
return -1;
}
}
/** 文档 getGPIOCount。 */
private int handleGetGPIOCount(@NonNull MethodCall call) {
UsbDevice device = resolveDevice(call);
if (device == null) {
return -1;
}
try {
return CH934XManager.getInstance().getGPIOCount(device);
} catch (Throwable t) {
return -1;
}
}
/** 文档 getGPIOGroup。 */
private int handleGetGPIOGroup(@NonNull MethodCall call) {
UsbDevice device = resolveDevice(call);
if (device == null) {
return -1;
}
try {
return CH934XManager.getInstance().getGPIOGroup(device);
} catch (Throwable t) {
return -1;
}
}
/** 文档 enableGPIO。需要 ChipType 参数,由 Dart 侧传入 int 映射值。 */
private boolean handleEnableGPIO(@NonNull MethodCall call) {
UsbDevice device = resolveDevice(call);
if (device == null) {
return false;
}
Integer chipTypeVal = call.argument("chipType");
Integer gpioGroup = call.argument("gpioGroup");
Integer enable = call.argument("enable");
if (chipTypeVal == null || gpioGroup == null || enable == null) {
return false;
}
ChipType chipType = parseChipType(chipTypeVal);
if (chipType == null) {
return false;
}
try {
return CH934XManager.getInstance().enableGPIO(
device, chipType, gpioGroup, enable);
} catch (Throwable t) {
return false;
}
}
/** 文档 setGPIODir。 */
private boolean handleSetGPIODir(@NonNull MethodCall call) {
if (activeDevice == null) {
return false;
}
Integer gpioGroup = call.argument("gpioGroup");
Integer gpioNumber = call.argument("gpioNumber");
Integer dir = call.argument("dir");
if (gpioGroup == null || gpioNumber == null || dir == null) {
return false;
}
GPIO_DIR gpioDir = dir == 0 ? GPIO_DIR.IN : GPIO_DIR.OUT;
try {
return CH934XManager.getInstance().setGPIODir(
activeDevice, gpioGroup, gpioNumber, gpioDir);
} catch (Throwable t) {
return false;
}
}
/** 文档 queryGPIODirFromCache。返回 0=IN,1=OUT,负值=失败。 */
private int handleQueryGPIODirFromCache(@NonNull MethodCall call) {
if (activeDevice == null) {
return -1;
}
Integer gpioGroup = call.argument("gpioGroup");
Integer gpioNumber = call.argument("gpioNumber");
if (gpioGroup == null || gpioNumber == null) {
return -1;
}
try {
GPIO_DIR dir = CH934XManager.getInstance().queryGPIODirFromCache(
activeDevice, gpioGroup, gpioNumber);
if (dir == null) return -1;
return dir == GPIO_DIR.OUT ? 1 : 0;
} catch (Throwable t) {
return -1;
}
}
/** 文档 isConnected。 */
private boolean handleIsConnected(@NonNull MethodCall call) {
UsbDevice device = resolveDevice(call);
if (device == null) {
return false;
}
try {
return CH934XManager.getInstance().isConnected(device);
} catch (Throwable t) {
return false;
}
}
/** 文档 getConnectedDevices。返回已打开设备的 deviceId 列表。 */
private List<Integer> handleGetConnectedDevices() {
List<Integer> ids = new ArrayList<>();
try {
ArrayList<UsbDevice> devices = CH934XManager.getInstance().getConnectedDevices();
if (devices != null) {
for (UsbDevice d : devices) {
ids.add(d.getDeviceId());
}
}
} catch (Throwable ignored) {
}
return ids;
}
/** 文档 setSerialParameter。配置当前活跃串口的参数。 */
private boolean handleSetSerialParameter(@NonNull MethodCall call) {
if (activeDevice == null || activeSerialNumber < 0) {
return false;
}
Integer baud = call.argument("baud");
Integer dataBit = call.argument("dataBit");
Integer stopBit = call.argument("stopBit");
Integer parityBit = call.argument("parityBit");
Boolean flow = call.argument("flow");
if (baud == null || dataBit == null || stopBit == null
|| parityBit == null || flow == null) {
return false;
}
try {
return CH934XManager.getInstance().setSerialParameter(
activeDevice, activeSerialNumber,
baud, dataBit, stopBit, parityBit, flow);
} catch (Throwable t) {
return false;
}
}
// ------------------------------------------------------------------------
// 内部辅助
// ------------------------------------------------------------------------
@@ -680,6 +891,25 @@ public class Ch934xSerialPlugin implements FlutterPlugin, MethodCallHandler, Act
return 5;
}
/** 将 Dart 侧传入的 int 还原为 SDK ChipType。null 表示未知类型。 */
@Nullable
private ChipType parseChipType(int value) {
String name;
switch (value) {
case 0: name = "CH9344"; break;
case 1: name = "CH9344L"; break;
case 2: name = "CH9350"; break;
case 3: name = "CH9348Q"; break;
case 4: name = "CH9342"; break;
default: return null;
}
try {
return ChipType.valueOf(name);
} catch (IllegalArgumentException e) {
return null;
}
}
private List<Map<String, Object>> buildSerialPortList(int count) {
List<Map<String, Object>> ports = new ArrayList<>();
for (int i = 0; i < Math.max(count, 0); i++) {
+120 -7
View File
@@ -16,9 +16,13 @@ Android SDK 封装的 Flutter 插件,文档面向其他 Flutter 开发者,介绍
- CH934X 设备枚举、序列号读取、芯片类型识别
- 多串口打开 / 关闭 / **同设备内串口切换**
- 字节级串口读写
- GPIO 输出 / 输入
- GPIO 输出 / 输入 / 方向控制 / 使能
- Modem 控制 (DTR/RTS) 与状态 (CTS/DSR/RI/DCD) 读取
- **主动申请 USB 权限**
- **Break 信号控制**
- **串口参数配置(波特率/数据位/停止位/校验/流控)**
- **查询设备连接状态与已打开设备列表**
- **查询 GPIO 数量、组信息**
- 设备拔出、Modem 错误等异常事件回调
- **底层依赖:** 沁恒官方 `CH934XLib.jar`(插件随包发布,位于
`android/libs/CH934XLib.jar`),通过原生 `CH934XManager` 单例直接调用,
@@ -189,14 +193,40 @@ await sub.cancel();
### 3.4 GPIO 接口
```dart
// 设置 GPIO 输出电平
final ok = await plugin.setGpioOutput(gpioNumber: 0, level: 1);
final value = await plugin.getGpioInput(0); // 负值表示失败
// 读取 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
@@ -224,6 +254,78 @@ final sub = await plugin.setExceptionCallback((event) {
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 等错误。
@@ -346,9 +448,9 @@ void main() {
才返回真实数据,枚举阶段调用只会得到空列表。
**Q3. `read()` 一直返回空数组。**
- 确认对端设备正在发送数据,且波特率/校验位等参数与原 SDK 默认值
一致(`CH934XLib` 提供独立的 `setConfig` 接口,本插件当前未做
封装,需要时可扩展原 SDK 直接调用)
- 确认对端设备正在发送数据,且波特率/校验位等参数匹配。可通过
`setSerialParameter(baud: 9600, dataBit: 8, stopBit: 1, parityBit: 0, flow: false)`
配置串口参数
- 检查线序:RX/TX 是否接反,以及硬件流控是否正确。
- 确认 `setActivePort` 已切换到正确的串口索引。
@@ -398,12 +500,23 @@ void main() {
| `requestUsbPermission` | 2.2 增强 | 主动授权(插件新增) |
| `read` | 6.1.1 | 串口读写 |
| `write` | 6.2.1 | 串口读写 |
| `setGpioOutput` | 7.1.1 | GPIO |
| `getGpioInput` | 7.1.2 | GPIO |
| `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 增强 | 多端口轮询流(插件新增) |
---
+142
View File
@@ -378,6 +378,148 @@ class _Ch934xSerialExamplePageState extends State<Ch934xSerialExamplePage> {
icon: const Icon(Icons.input),
label: const Text('读取 GPIO0'),
),
OutlinedButton.icon(
onPressed: () async {
if (!_portOpened) return;
final ok = await _plugin.setBreak(true);
if (!mounted) return;
setState(() => _status = ok ? 'Break 已设置' : 'Break 失败');
},
icon: const Icon(Icons.pause),
label: const Text('SetBreak'),
),
OutlinedButton.icon(
onPressed: () async {
if (!_portOpened) return;
final mode = await _plugin.getCurrentMode();
if (!mounted) return;
final label = switch (mode) {
Ch934xMode.normal => '普通',
Ch934xMode.hardflow => '硬件流控',
Ch934xMode.gpio => 'GPIO',
_ => '未知($mode)',
};
setState(() => _status = '当前模式: $label');
},
icon: const Icon(Icons.settings),
label: const Text('当前模式'),
),
OutlinedButton.icon(
onPressed: () async {
final device = _selectedDevice;
if (device == null) {
setState(() => _status = '请先选择设备');
return;
}
final cnt = await _plugin.getGpiocount(device.deviceId);
final grp = await _plugin.getGpiogroup(device.deviceId);
if (!mounted) return;
setState(() => _status = 'GPIO 数量=$cnt, 组数=$grp');
},
icon: const Icon(Icons.developer_board),
label: const Text('GPIO 信息'),
),
OutlinedButton.icon(
onPressed: () async {
final device = _selectedDevice;
if (device == null) {
setState(() => _status = '请先选择设备');
return;
}
if (!_portOpened) {
setState(() => _status = '请先打开串口');
return;
}
final ok = await _plugin.enableGpio(
chipType: device.deviceType,
gpioGroup: 0,
enable: 1,
);
if (!mounted) return;
setState(() => _status = ok ? 'GPIO 已使能' : '使能 GPIO 失败');
},
icon: const Icon(Icons.toggle_on),
label: const Text('使能GPIO'),
),
OutlinedButton.icon(
onPressed: () async {
if (!_portOpened) return;
final ok = await _plugin.setGpioDir(
gpioGroup: 0,
gpioNumber: 0,
dir: GpioDirection.out,
);
if (!mounted) return;
setState(() => _status = ok ? 'GPIO0 方向设为输出' : '设置方向失败');
},
icon: const Icon(Icons.swap_vert),
label: const Text('GPIO方向'),
),
OutlinedButton.icon(
onPressed: () async {
if (!_portOpened) return;
final dir = await _plugin.queryGpioDirFromCache(
gpioGroup: 0,
gpioNumber: 0,
);
if (!mounted) return;
final label = switch (dir) {
GpioDirection.in_ => '输入',
GpioDirection.out => '输出',
_ => '未知($dir)',
};
setState(() => _status = 'GPIO0 方向缓存: $label');
},
icon: const Icon(Icons.visibility),
label: const Text('查方向缓存'),
),
OutlinedButton.icon(
onPressed: () async {
final device = _selectedDevice;
if (device == null) {
setState(() => _status = '请先选择设备');
return;
}
final connected = await _plugin.isConnected(device.deviceId);
if (!mounted) return;
setState(() => _status = connected ? '设备已连接' : '设备未连接');
},
icon: const Icon(Icons.link),
label: const Text('是否已连'),
),
OutlinedButton.icon(
onPressed: () async {
final ids = await _plugin.getConnectedDevices();
if (!mounted) return;
setState(() => _status = '已打开设备: ${ids.isEmpty ? "" : ids.join(", ")}');
},
icon: const Icon(Icons.list),
label: const Text('已开设备'),
),
OutlinedButton.icon(
onPressed: () async {
if (!_portOpened) return;
final ok = await _plugin.setSerialParameter(
baud: 9600, dataBit: 8, stopBit: 1, parityBit: 0, flow: false,
);
if (!mounted) return;
setState(() => _status = ok ? '已设为 9600/8/1/N' : '设参失败');
},
icon: const Icon(Icons.tune),
label: const Text('波特率9600'),
),
OutlinedButton.icon(
onPressed: () async {
if (!_portOpened) return;
final ok = await _plugin.setSerialParameter(
baud: 115200, dataBit: 8, stopBit: 1, parityBit: 0, flow: false,
);
if (!mounted) return;
setState(() => _status = ok ? '已设为 115200/8/1/N' : '设参失败');
},
icon: const Icon(Icons.tune),
label: const Text('波特率115200'),
),
],
),
const SizedBox(height: 16),
+76
View File
@@ -168,4 +168,80 @@ class Ch934xSerial {
await _platform.setExceptionCallback(controller.add);
return subscription;
}
// ---------------------------------------------------------------------------
// 新增接口(文档补充的完整 SDK API)
// ---------------------------------------------------------------------------
/// 设置 Break 信号。
Future<bool> setBreak(bool valid) => _platform.setBreak(valid);
/// 获取当前串口模式。
Future<int> getCurrentMode() => _platform.getCurrentMode();
/// 获取 GPIO 数量。
Future<int> getGpiocount(int deviceId) =>
_platform.getGpiocount(deviceId);
/// 获取 GPIO 组数。
Future<int> getGpiogroup(int deviceId) =>
_platform.getGpiogroup(deviceId);
/// 使能 GPIO。
Future<bool> enableGpio({
required int chipType,
required int gpioGroup,
required int enable,
}) =>
_platform.enableGpio(
chipType: chipType,
gpioGroup: gpioGroup,
enable: enable,
);
/// 设置 GPIO 方向。
Future<bool> setGpioDir({
required int gpioGroup,
required int gpioNumber,
required int dir,
}) =>
_platform.setGpioDir(
gpioGroup: gpioGroup,
gpioNumber: gpioNumber,
dir: dir,
);
/// 从缓存查询 GPIO 方向。
Future<int> queryGpioDirFromCache({
required int gpioGroup,
required int gpioNumber,
}) =>
_platform.queryGpioDirFromCache(
gpioGroup: gpioGroup,
gpioNumber: gpioNumber,
);
/// 查询设备是否已打开。
Future<bool> isConnected(int deviceId) =>
_platform.isConnected(deviceId);
/// 获取当前已打开的设备 ID 列表。
Future<List<int>> getConnectedDevices() =>
_platform.getConnectedDevices();
/// 配置当前活跃串口的参数。
Future<bool> setSerialParameter({
required int baud,
int dataBit = 8,
int stopBit = 1,
int parityBit = 0,
bool flow = false,
}) =>
_platform.setSerialParameter(
baud: baud,
dataBit: dataBit,
stopBit: stopBit,
parityBit: parityBit,
flow: flow,
);
}
+111
View File
@@ -215,6 +215,117 @@ class MethodChannelCh934xSerial extends Ch934xSerialPlatform {
);
}
@override
Future<bool> setBreak(bool valid) {
return methodChannel.invokeMethod<bool>(
'setBreak',
<String, Object>{'valid': valid},
).then((v) => v ?? false);
}
@override
Future<int> getCurrentMode() {
return methodChannel.invokeMethod<int>('getCurrentMode')
.then((v) => v ?? -1);
}
@override
Future<int> getGpiocount(int deviceId) {
return methodChannel.invokeMethod<int>(
'getGPIOCount',
<String, Object>{'deviceId': deviceId},
).then((v) => v ?? -1);
}
@override
Future<int> getGpiogroup(int deviceId) {
return methodChannel.invokeMethod<int>(
'getGPIOGroup',
<String, Object>{'deviceId': deviceId},
).then((v) => v ?? -1);
}
@override
Future<bool> enableGpio({
required int chipType,
required int gpioGroup,
required int enable,
}) {
return methodChannel.invokeMethod<bool>(
'enableGPIO',
<String, Object>{
'chipType': chipType,
'gpioGroup': gpioGroup,
'enable': enable,
},
).then((v) => v ?? false);
}
@override
Future<bool> setGpioDir({
required int gpioGroup,
required int gpioNumber,
required int dir,
}) {
return methodChannel.invokeMethod<bool>(
'setGPIODir',
<String, Object>{
'gpioGroup': gpioGroup,
'gpioNumber': gpioNumber,
'dir': dir,
},
).then((v) => v ?? false);
}
@override
Future<int> queryGpioDirFromCache({
required int gpioGroup,
required int gpioNumber,
}) {
return methodChannel.invokeMethod<int>(
'queryGPIODirFromCache',
<String, Object>{
'gpioGroup': gpioGroup,
'gpioNumber': gpioNumber,
},
).then((v) => v ?? -1);
}
@override
Future<bool> isConnected(int deviceId) {
return methodChannel.invokeMethod<bool>(
'isConnected',
<String, Object>{'deviceId': deviceId},
).then((v) => v ?? false);
}
@override
Future<List<int>> getConnectedDevices() async {
final raw = await methodChannel.invokeMethod<List<dynamic>>('getConnectedDevices');
if (raw == null) return const <int>[];
return raw.whereType<int>().toList(growable: false);
}
@override
Future<bool> setSerialParameter({
required int baud,
int dataBit = 8,
int stopBit = 1,
int parityBit = 0,
bool flow = false,
}) {
return methodChannel.invokeMethod<bool>(
'setSerialParameter',
<String, Object>{
'baud': baud,
'dataBit': dataBit,
'stopBit': stopBit,
'parityBit': parityBit,
'flow': flow,
},
).then((v) => v ?? false);
}
/// 释放内部资源,通常仅在测试或热重载场景下使用。
@visibleForTesting
void dispose() {
+56
View File
@@ -112,4 +112,60 @@ abstract class Ch934xSerialPlatform extends PlatformInterface {
Future<void> setExceptionCallback(
void Function(Ch934xException exception) onException,
);
// ---------------------------------------------------------------------------
// 新增接口(文档补充的完整 SDK API)
// ---------------------------------------------------------------------------
/// 设置 Break 信号(对应 `CH934XManager.setBreak`)。
Future<bool> setBreak(bool valid);
/// 获取当前串口模式(对应 `CH934XManager.getCurrentMode`)。
/// 返回值见 [Ch934xMode];仅 CH934X 有效,CH348 返回 -1。
Future<int> getCurrentMode();
/// 获取 GPIO 数量(对应 `CH934XManager.getGPIOCount`)。
Future<int> getGpiocount(int deviceId);
/// 获取 GPIO 组数(对应 `CH934XManager.getGPIOGroup`)。
Future<int> getGpiogroup(int deviceId);
/// 使能 GPIO(对应 `CH934XManager.enableGPIO`)。
/// [chipType] 由 [Ch934xDeviceType] 常量标识,[gpioGroup] 为组号,
/// [enable] 含义见文档: CH9344 传 1/0 控制整组;CH348 使用位掩码。
Future<bool> enableGpio({
required int chipType,
required int gpioGroup,
required int enable,
});
/// 设置 GPIO 方向(对应 `CH934XManager.setGPIODir`)。
/// [dir] 取值见 [GpioDirection]。
Future<bool> setGpioDir({
required int gpioGroup,
required int gpioNumber,
required int dir,
});
/// 从缓存查询 GPIO 方向(对应 `CH934XManager.queryGPIODirFromCache`)。
/// 返回值见 [GpioDirection];-1 表示查询失败。
Future<int> queryGpioDirFromCache({
required int gpioGroup,
required int gpioNumber,
});
/// 查询设备是否已打开(对应 `CH934XManager.isConnected`)。
Future<bool> isConnected(int deviceId);
/// 获取当前已打开的设备 ID 列表(对应 `CH934XManager.getConnectedDevices`)。
Future<List<int>> getConnectedDevices();
/// 配置当前活跃串口的参数(对应 `CH934XManager.setSerialParameter`)。
Future<bool> setSerialParameter({
required int baud,
int dataBit = 8,
int stopBit = 1,
int parityBit = 0,
bool flow = false,
});
}
+27
View File
@@ -26,3 +26,30 @@ class Ch934xDeviceType {
/// 未知或非 CH934X 设备。
static const int unknown = -1;
}
/// 串口当前模式,对应 SDK [Mode] 枚举。
///
/// 仅对 CH934X 型号有效(CH348 调用 [Ch934xSerial.getCurrentMode] 无意义)。
class Ch934xMode {
const Ch934xMode._();
/// 普通模式。
static const int normal = 0;
/// 硬件流控模式。
static const int hardflow = 1;
/// GPIO 模式。
static const int gpio = 2;
}
/// GPIO 方向,对应 SDK [GPIO_DIR] 枚举。
class GpioDirection {
const GpioDirection._();
/// 输入方向。
static const int in_ = 0;
/// 输出方向。
static const int out = 1;
}