import 'dart:developer' as dev; import '../utils/time_utils.dart'; /// 充电日志解析器 class ChargeParser { /// 解析充电数据,返回解析结果 static ParseResult parse(List lines, DateTime? chargingStartTime) { dev.log('[ChargeParser] 开始解析,共 ${lines.length} 行', name: 'BatteryHealth'); final validLines = _collectValidLines(lines, chargingStartTime); if (validLines.isEmpty) { dev.log('[ChargeParser] 无有效时间窗口内的数据行', name: 'BatteryHealth'); return ParseResult.empty(); } // 按时间戳从新到旧排序 validLines.sort((a, b) => b['timestamp'].compareTo(a['timestamp'])); final latest = validLines.first; final latestLine = latest['line'] as String; final latestType = latest['type'] as String; dev.log( '[ChargeParser] 最新有效数据: $latestType, 时间: ${latest['timestamp']}', name: 'BatteryHealth', ); if (latestType == 'wls') { return _parseWireless(latestLine); } else { return _parseWired(latestLine); } } static List> _collectValidLines( List lines, DateTime? chargingStartTime, ) { final result = >[]; for (String line in lines) { final timestamp = TimeUtils.parseLogTimestamp(line); if (!TimeUtils.isLogTimestampValid(timestamp, chargingStartTime)) { continue; } final isUsb = line.contains('chg_usb') && (line.contains('ibus=') || line.contains('real_type=')); final isWls = line.contains('chg_wls') && line.contains('wls_online=1'); if (isUsb || isWls) { result.add({ 'line': line, 'timestamp': timestamp, 'type': isWls ? 'wls' : 'usb', }); } } return result; } static ParseResult _parseWireless(String line) { final typeReg = RegExp(r'wls_type=(\w+)'); final voltReg = RegExp(r'wls_volt=(\d+)'); final currReg = RegExp(r'wls_curr=(\d+)'); final wlsType = typeReg.firstMatch(line)?.group(1); final volt = int.parse(voltReg.firstMatch(line)?.group(1) ?? '0'); final curr = int.parse(currReg.firstMatch(line)?.group(1) ?? '0'); return ParseResult( isWireless: true, chargeType: wlsType ?? '无线', power: (volt * curr) / 1000000.0, volt: volt / 1000.0, curr: curr / 1000.0, wiredLevel: null, ); } static ParseResult _parseWired(String line) { final ibusReg = RegExp(r'ibus=(\d+)'); final vbusReg = RegExp(r'vbus=(\d+)'); final levelReg = RegExp(r'wired_level=(\d+)'); final typeReg = RegExp(r'real_type=(\w+)'); final ibus = int.parse(ibusReg.firstMatch(line)?.group(1) ?? '0'); final vbus = int.parse(vbusReg.firstMatch(line)?.group(1) ?? '0'); final realType = typeReg.firstMatch(line)?.group(1); final level = int.parse(levelReg.firstMatch(line)?.group(1) ?? '0'); String chargeType; if (realType == 'PPS') { chargeType = 'PPS'; } else if (realType == 'SDP' || realType == 'FLOAT') { chargeType = 'SDP'; } else if (level >= 3) { chargeType = 'PPS'; } else { chargeType = 'SDP'; } return ParseResult( isWireless: false, chargeType: chargeType, power: (vbus * ibus) / 1000000000.0, volt: vbus / 1000000.0, curr: ibus / 1000000.0, wiredLevel: chargeType == 'PPS' ? level : null, ); } } class ParseResult { final bool isWireless; final String chargeType; final double power; final double volt; final double curr; final int? wiredLevel; ParseResult({ required this.isWireless, required this.chargeType, required this.power, required this.volt, required this.curr, this.wiredLevel, }); factory ParseResult.empty() { return ParseResult( isWireless: false, chargeType: '', power: 0.0, volt: 0.0, curr: 0.0, wiredLevel: null, ); } }