diff --git a/README.md b/README.md index f90bbad..b33ff76 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # ch934x_serial Flutter 插件:封装南京沁恒微电子 **CH934X 系列** USB 转多串口芯片的 -Android SDK,提供设备查找、串口读写、GPIO 与 Modem 控制等能力。 +Android SDK,提供设备枚举、串口读写、GPIO/Modem 控制、Break 信号、 +串口参数配置、设备状态查询等完整能力。 ## 文档 @@ -26,5 +27,5 @@ final devices = await plugin.getDeviceList(); ## 平台支持 -- ✅ Android(基于 `CH934XLib.jar` 反射桥接) +- ✅ Android(基于 `CH934XLib.jar`) - ❌ iOS / Web / Desktop(暂未实现) diff --git a/android/src/main/java/com/xiarui/ch934x_serial/Ch934xSerialPlugin.java b/android/src/main/java/com/xiarui/ch934x_serial/Ch934xSerialPlugin.java index 306ba32..439024f 100644 --- a/android/src/main/java/com/xiarui/ch934x_serial/Ch934xSerialPlugin.java +++ b/android/src/main/java/com/xiarui/ch934x_serial/Ch934xSerialPlugin.java @@ -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 handleGetConnectedDevices() { + List ids = new ArrayList<>(); + try { + ArrayList 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> buildSerialPortList(int count) { List> ports = new ArrayList<>(); for (int i = 0; i < Math.max(count, 0); i++) { diff --git a/docs/CH934X_Plugin_使用说明.md b/docs/CH934X_Plugin_使用说明.md index 077f996..f360c29 100644 --- a/docs/CH934X_Plugin_使用说明.md +++ b/docs/CH934X_Plugin_使用说明.md @@ -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 增强 | 多端口轮询流(插件新增) | --- diff --git a/example/lib/main.dart b/example/lib/main.dart index f101456..8f6dff3 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -378,6 +378,148 @@ class _Ch934xSerialExamplePageState extends State { 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), diff --git a/lib/ch934x_serial.dart b/lib/ch934x_serial.dart index 421d882..65cf7f7 100644 --- a/lib/ch934x_serial.dart +++ b/lib/ch934x_serial.dart @@ -168,4 +168,80 @@ class Ch934xSerial { await _platform.setExceptionCallback(controller.add); return subscription; } + + // --------------------------------------------------------------------------- + // 新增接口(文档补充的完整 SDK API) + // --------------------------------------------------------------------------- + + /// 设置 Break 信号。 + Future setBreak(bool valid) => _platform.setBreak(valid); + + /// 获取当前串口模式。 + Future getCurrentMode() => _platform.getCurrentMode(); + + /// 获取 GPIO 数量。 + Future getGpiocount(int deviceId) => + _platform.getGpiocount(deviceId); + + /// 获取 GPIO 组数。 + Future getGpiogroup(int deviceId) => + _platform.getGpiogroup(deviceId); + + /// 使能 GPIO。 + Future enableGpio({ + required int chipType, + required int gpioGroup, + required int enable, + }) => + _platform.enableGpio( + chipType: chipType, + gpioGroup: gpioGroup, + enable: enable, + ); + + /// 设置 GPIO 方向。 + Future setGpioDir({ + required int gpioGroup, + required int gpioNumber, + required int dir, + }) => + _platform.setGpioDir( + gpioGroup: gpioGroup, + gpioNumber: gpioNumber, + dir: dir, + ); + + /// 从缓存查询 GPIO 方向。 + Future queryGpioDirFromCache({ + required int gpioGroup, + required int gpioNumber, + }) => + _platform.queryGpioDirFromCache( + gpioGroup: gpioGroup, + gpioNumber: gpioNumber, + ); + + /// 查询设备是否已打开。 + Future isConnected(int deviceId) => + _platform.isConnected(deviceId); + + /// 获取当前已打开的设备 ID 列表。 + Future> getConnectedDevices() => + _platform.getConnectedDevices(); + + /// 配置当前活跃串口的参数。 + Future 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, + ); } diff --git a/lib/ch934x_serial_method_channel.dart b/lib/ch934x_serial_method_channel.dart index 2de2715..b963bbf 100644 --- a/lib/ch934x_serial_method_channel.dart +++ b/lib/ch934x_serial_method_channel.dart @@ -215,6 +215,117 @@ class MethodChannelCh934xSerial extends Ch934xSerialPlatform { ); } + @override + Future setBreak(bool valid) { + return methodChannel.invokeMethod( + 'setBreak', + {'valid': valid}, + ).then((v) => v ?? false); + } + + @override + Future getCurrentMode() { + return methodChannel.invokeMethod('getCurrentMode') + .then((v) => v ?? -1); + } + + @override + Future getGpiocount(int deviceId) { + return methodChannel.invokeMethod( + 'getGPIOCount', + {'deviceId': deviceId}, + ).then((v) => v ?? -1); + } + + @override + Future getGpiogroup(int deviceId) { + return methodChannel.invokeMethod( + 'getGPIOGroup', + {'deviceId': deviceId}, + ).then((v) => v ?? -1); + } + + @override + Future enableGpio({ + required int chipType, + required int gpioGroup, + required int enable, + }) { + return methodChannel.invokeMethod( + 'enableGPIO', + { + 'chipType': chipType, + 'gpioGroup': gpioGroup, + 'enable': enable, + }, + ).then((v) => v ?? false); + } + + @override + Future setGpioDir({ + required int gpioGroup, + required int gpioNumber, + required int dir, + }) { + return methodChannel.invokeMethod( + 'setGPIODir', + { + 'gpioGroup': gpioGroup, + 'gpioNumber': gpioNumber, + 'dir': dir, + }, + ).then((v) => v ?? false); + } + + @override + Future queryGpioDirFromCache({ + required int gpioGroup, + required int gpioNumber, + }) { + return methodChannel.invokeMethod( + 'queryGPIODirFromCache', + { + 'gpioGroup': gpioGroup, + 'gpioNumber': gpioNumber, + }, + ).then((v) => v ?? -1); + } + + @override + Future isConnected(int deviceId) { + return methodChannel.invokeMethod( + 'isConnected', + {'deviceId': deviceId}, + ).then((v) => v ?? false); + } + + @override + Future> getConnectedDevices() async { + final raw = await methodChannel.invokeMethod>('getConnectedDevices'); + if (raw == null) return const []; + return raw.whereType().toList(growable: false); + } + + @override + Future setSerialParameter({ + required int baud, + int dataBit = 8, + int stopBit = 1, + int parityBit = 0, + bool flow = false, + }) { + return methodChannel.invokeMethod( + 'setSerialParameter', + { + 'baud': baud, + 'dataBit': dataBit, + 'stopBit': stopBit, + 'parityBit': parityBit, + 'flow': flow, + }, + ).then((v) => v ?? false); + } + /// 释放内部资源,通常仅在测试或热重载场景下使用。 @visibleForTesting void dispose() { diff --git a/lib/ch934x_serial_platform_interface.dart b/lib/ch934x_serial_platform_interface.dart index 949bf2a..ba0715d 100644 --- a/lib/ch934x_serial_platform_interface.dart +++ b/lib/ch934x_serial_platform_interface.dart @@ -112,4 +112,60 @@ abstract class Ch934xSerialPlatform extends PlatformInterface { Future setExceptionCallback( void Function(Ch934xException exception) onException, ); + + // --------------------------------------------------------------------------- + // 新增接口(文档补充的完整 SDK API) + // --------------------------------------------------------------------------- + + /// 设置 Break 信号(对应 `CH934XManager.setBreak`)。 + Future setBreak(bool valid); + + /// 获取当前串口模式(对应 `CH934XManager.getCurrentMode`)。 + /// 返回值见 [Ch934xMode];仅 CH934X 有效,CH348 返回 -1。 + Future getCurrentMode(); + + /// 获取 GPIO 数量(对应 `CH934XManager.getGPIOCount`)。 + Future getGpiocount(int deviceId); + + /// 获取 GPIO 组数(对应 `CH934XManager.getGPIOGroup`)。 + Future getGpiogroup(int deviceId); + + /// 使能 GPIO(对应 `CH934XManager.enableGPIO`)。 + /// [chipType] 由 [Ch934xDeviceType] 常量标识,[gpioGroup] 为组号, + /// [enable] 含义见文档: CH9344 传 1/0 控制整组;CH348 使用位掩码。 + Future enableGpio({ + required int chipType, + required int gpioGroup, + required int enable, + }); + + /// 设置 GPIO 方向(对应 `CH934XManager.setGPIODir`)。 + /// [dir] 取值见 [GpioDirection]。 + Future setGpioDir({ + required int gpioGroup, + required int gpioNumber, + required int dir, + }); + + /// 从缓存查询 GPIO 方向(对应 `CH934XManager.queryGPIODirFromCache`)。 + /// 返回值见 [GpioDirection];-1 表示查询失败。 + Future queryGpioDirFromCache({ + required int gpioGroup, + required int gpioNumber, + }); + + /// 查询设备是否已打开(对应 `CH934XManager.isConnected`)。 + Future isConnected(int deviceId); + + /// 获取当前已打开的设备 ID 列表(对应 `CH934XManager.getConnectedDevices`)。 + Future> getConnectedDevices(); + + /// 配置当前活跃串口的参数(对应 `CH934XManager.setSerialParameter`)。 + Future setSerialParameter({ + required int baud, + int dataBit = 8, + int stopBit = 1, + int parityBit = 0, + bool flow = false, + }); } diff --git a/lib/src/models/ch934x_device_type.dart b/lib/src/models/ch934x_device_type.dart index b5de334..ab30204 100644 --- a/lib/src/models/ch934x_device_type.dart +++ b/lib/src/models/ch934x_device_type.dart @@ -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; +}