feat(android): 添加 CH934X USB 转串口芯片支持
- 在 AndroidManifest.xml 中添加 USB Host 权限声明 - 集成 CH934X Android SDK 并通过反射调用原生功能 - 实现设备查找、串口读写、GPIO 和 Modem 控制功能 - 添加异常回调机制处理设备拔出等情况 - 提供 Stream 数据流支持实时串口数据监听 - 完善单元测试覆盖所有核心功能模块
This commit is contained in:
+127
-2
@@ -1,8 +1,133 @@
|
||||
export 'src/models/models.dart';
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'ch934x_serial_method_channel.dart';
|
||||
import 'ch934x_serial_platform_interface.dart';
|
||||
import 'src/models/models.dart';
|
||||
|
||||
/// CH934X 插件的对外门面类。
|
||||
///
|
||||
/// 内部委托 [Ch934xSerialPlatform] 真正执行平台调用,
|
||||
/// 在 Android 上默认走 [MethodChannelCh934xSerial]。
|
||||
///
|
||||
/// 命名/语义与官方 Android SDK 文档保持一致;若希望
|
||||
/// 监听串口数据流,可使用 [dataStream] 配合 [read]。
|
||||
class Ch934xSerial {
|
||||
Future<String?> getPlatformVersion() {
|
||||
return Ch934xSerialPlatform.instance.getPlatformVersion();
|
||||
/// 使用默认平台实现构造。
|
||||
Ch934xSerial() : _platform = Ch934xSerialPlatform.instance;
|
||||
|
||||
/// 注入自定义平台实现,常用于单元测试。
|
||||
Ch934xSerial.withPlatform(Ch934xSerialPlatform platform)
|
||||
: _platform = platform;
|
||||
|
||||
final Ch934xSerialPlatform _platform;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 设备查找
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// 获取所有已连接的 CH934X 设备信息。
|
||||
Future<List<Ch934xDeviceInfo>> getDeviceList() =>
|
||||
_platform.getDeviceList();
|
||||
|
||||
/// 获取指定设备序列号;非 CH934X 设备时返回 null。
|
||||
Future<String?> getSerialNumber(int deviceId) =>
|
||||
_platform.getSerialNumber(deviceId);
|
||||
|
||||
/// 获取指定设备类型,取值见 [Ch934xDeviceType]。
|
||||
Future<int> getDeviceType(int deviceId) =>
|
||||
_platform.getDeviceType(deviceId);
|
||||
|
||||
/// 获取指定设备的串口列表。
|
||||
Future<List<Ch934xSerialPortInfo>> getSerialPortList(
|
||||
int deviceId, {
|
||||
required int interfaceNumber,
|
||||
}) =>
|
||||
_platform.getSerialPortList(
|
||||
deviceId,
|
||||
interfaceNumber: interfaceNumber,
|
||||
);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 设备打开 / 关闭
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// 打开指定串口。
|
||||
Future<bool> openPort(Ch934xPortTarget target) => _platform.openPort(target);
|
||||
|
||||
/// 关闭当前会话最近一次打开的串口。
|
||||
Future<bool> closePort() => _platform.closePort();
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 串口读写
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// 阻塞式读取,直到拿到 [length] 字节或缓冲区被填满。
|
||||
///
|
||||
/// 返回值为实际读到的字节;若底层无数据或读取失败,返回空。
|
||||
Future<Uint8List> read(int length) => _platform.read(length);
|
||||
|
||||
/// 写入数据,返回实际写入的字节数。
|
||||
Future<int> write(Uint8List data) => _platform.write(data);
|
||||
|
||||
/// 构造一个持续从串口拉取数据的 `Stream<Uint8List>`。
|
||||
///
|
||||
/// 内部以 [interval] 为周期反复调用 [read];当底层无数据
|
||||
/// 时返回空缓冲区,消费者可据此判定是否需要结束订阅。
|
||||
Stream<Uint8List> dataStream({
|
||||
int chunkSize = 1024,
|
||||
Duration interval = const Duration(milliseconds: 20),
|
||||
}) async* {
|
||||
if (chunkSize <= 0) {
|
||||
throw ArgumentError.value(chunkSize, 'chunkSize', '必须大于 0');
|
||||
}
|
||||
while (true) {
|
||||
final chunk = await _platform.read(chunkSize);
|
||||
if (chunk.isNotEmpty) {
|
||||
yield chunk;
|
||||
}
|
||||
await Future<void>.delayed(interval);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// GPIO
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// 设置 GPIO 输出电平(0 或 1)。
|
||||
Future<bool> setGpioOutput({required int gpioNumber, required int level}) =>
|
||||
_platform.setGpioOutput(gpioNumber: gpioNumber, level: level);
|
||||
|
||||
/// 读取 GPIO 输入电平;负值表示读取失败。
|
||||
Future<int> getGpioInput(int gpioNumber) =>
|
||||
_platform.getGpioInput(gpioNumber);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Modem
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// 设置 DTR / RTS 信号。
|
||||
Future<bool> setModemControl({required int dtr, required int rts}) =>
|
||||
_platform.setModemControl(dtr: dtr, rts: rts);
|
||||
|
||||
/// 获取 Modem 状态位,可通过 [ModemStatus] 工具类解析。
|
||||
Future<int> getModemStatus() => _platform.getModemStatus();
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 异常回调
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// 注册异常回调(例如设备拔出)。
|
||||
///
|
||||
/// 返回一个 [StreamSubscription],可在外层 dispose 时取消。
|
||||
Future<StreamSubscription<Ch934xException>> setExceptionCallback(
|
||||
void Function(Ch934xException exception) onException,
|
||||
) async {
|
||||
final controller = StreamController<Ch934xException>();
|
||||
final subscription = controller.stream.listen(onException);
|
||||
await _platform.setExceptionCallback(controller.add);
|
||||
return subscription;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user