import 'dart:convert'; /// 串口奇偶校验 enum SerialParity { none, odd, even, mark, space } /// 串口流控 enum SerialFlowControl { none, rtsCts, xonXoff, dtrDsr } /// 串口配置 /// /// 持久化到 settings 表的 `serial_config` key 中; /// 打开串口时根据此配置构造底层 `UsbConfig`。 class SerialConfig { /// 设备 Vendor ID(十六进制) final int vendorId; /// 设备 Product ID(十六进制),0 表示不指定 final int productId; /// 波特率 final int baudRate; /// 数据位 (5/6/7/8) final int dataBits; /// 停止位 (1/2) final int stopBits; /// 校验位 final SerialParity parity; /// 流控 final SerialFlowControl flowControl; /// 读超时(毫秒) final int readTimeoutMs; /// 写超时(毫秒) final int writeTimeoutMs; const SerialConfig({ this.vendorId = 0x1A86, this.productId = 0x7523, this.baudRate = 9600, this.dataBits = 8, this.stopBits = 1, this.parity = SerialParity.none, this.flowControl = SerialFlowControl.none, this.readTimeoutMs = 2000, this.writeTimeoutMs = 2000, }); /// 默认配置 static const SerialConfig defaults = SerialConfig(); /// 常用波特率 static const List commonBaudRates = [ 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, ]; SerialConfig copyWith({ int? vendorId, int? productId, int? baudRate, int? dataBits, int? stopBits, SerialParity? parity, SerialFlowControl? flowControl, int? readTimeoutMs, int? writeTimeoutMs, }) { return SerialConfig( vendorId: vendorId ?? this.vendorId, productId: productId ?? this.productId, baudRate: baudRate ?? this.baudRate, dataBits: dataBits ?? this.dataBits, stopBits: stopBits ?? this.stopBits, parity: parity ?? this.parity, flowControl: flowControl ?? this.flowControl, readTimeoutMs: readTimeoutMs ?? this.readTimeoutMs, writeTimeoutMs: writeTimeoutMs ?? this.writeTimeoutMs, ); } /// 编码为 JSON 字符串(用于持久化) String toJsonString() => jsonEncode({ 'vendorId': vendorId, 'productId': productId, 'baudRate': baudRate, 'dataBits': dataBits, 'stopBits': stopBits, 'parity': parity.name, 'flowControl': flowControl.name, 'readTimeoutMs': readTimeoutMs, 'writeTimeoutMs': writeTimeoutMs, }); /// 从 JSON 字符串解码;解析失败时返回默认值 factory SerialConfig.fromJsonString(String? raw) { if (raw == null || raw.isEmpty) return defaults; try { final map = jsonDecode(raw) as Map; return SerialConfig( vendorId: (map['vendorId'] as num?)?.toInt() ?? defaults.vendorId, productId: (map['productId'] as num?)?.toInt() ?? defaults.productId, baudRate: (map['baudRate'] as num?)?.toInt() ?? defaults.baudRate, dataBits: (map['dataBits'] as num?)?.toInt() ?? defaults.dataBits, stopBits: (map['stopBits'] as num?)?.toInt() ?? defaults.stopBits, parity: SerialParity.values.firstWhere( (e) => e.name == map['parity'], orElse: () => defaults.parity, ), flowControl: SerialFlowControl.values.firstWhere( (e) => e.name == map['flowControl'], orElse: () => defaults.flowControl, ), readTimeoutMs: (map['readTimeoutMs'] as num?)?.toInt() ?? defaults.readTimeoutMs, writeTimeoutMs: (map['writeTimeoutMs'] as num?)?.toInt() ?? defaults.writeTimeoutMs, ); } catch (_) { return defaults; } } }