From 15870b4ac47af333e754463e95f4e03a24632081 Mon Sep 17 00:00:00 2001 From: lxh2875931338 Date: Fri, 3 Jul 2026 22:36:18 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=8D=8F=E8=AE=AE=E8=AF=86?= =?UTF-8?q?=E5=88=AB=E9=80=BB=E8=BE=91=E3=80=81=E8=B0=83=E6=95=B4=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E8=AF=BB=E5=8F=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/battery_health_page.dart | 109 +++++++++++++++++++++------- lib/widgets/charge_detail_page.dart | 4 +- pubspec.yaml | 2 +- 3 files changed, 86 insertions(+), 29 deletions(-) diff --git a/lib/pages/battery_health_page.dart b/lib/pages/battery_health_page.dart index d51247d..aba3007 100644 --- a/lib/pages/battery_health_page.dart +++ b/lib/pages/battery_health_page.dart @@ -47,13 +47,16 @@ class _BatteryHealthPageState extends State // ---------- 充电状态 ---------- bool _isCharging = false; - String _chargeType = ''; // "EPP", "PPS", "SDP", "无线" 等 + String _chargeType = ''; // "EPP", "PPS", "SDP", "无线", "MZ_EPP" 等 double _chargePower = 0.0; double _chargeVolt = 0.0; double _chargeCurr = 0.0; int? _wiredLevel; bool _isWireless = false; + // 🟢 1.3.0-dev.3: 充电开始时间(UTC),用于时间窗口判断 + DateTime? _chargingStartTime; + // 动画控制 late AnimationController _chargeAnimationController; late Animation _bottomSlide; @@ -195,15 +198,17 @@ class _BatteryHealthPageState extends State } } + // ---------- 1.3.0-dev.1: 使用 UTC 生成文件名 ---------- String getTodayFileName() { - DateTime now = DateTime.now(); - String year = now.year.toString(); - String month = now.month.toString().padLeft(2, '0'); - String day = now.day.toString().padLeft(2, '0'); + DateTime nowUtc = DateTime.now().toUtc(); + String year = nowUtc.year.toString(); + String month = nowUtc.month.toString().padLeft(2, '0'); + String day = nowUtc.day.toString().padLeft(2, '0'); return 'mbattery_charger_log_${year}_${month}_$day'; } // ---------- 时间戳工具方法 ---------- + /// 解析日志行中的时间戳,强制解析为 UTC DateTime? _parseLogTimestamp(String line) { RegExp reg = RegExp(r'\[(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})\]'); Match? match = reg.firstMatch(line); @@ -226,18 +231,24 @@ class _BatteryHealthPageState extends State } } + /// 🟢 1.3.0-dev.3: 时间窗口以插入时刻为基准,只向前看 bool _isLogTimestampValid(DateTime? logTime) { if (logTime == null) return false; - DateTime nowUtc = DateTime.now().toUtc(); - Duration diff = nowUtc.difference(logTime); - bool isValid = diff.abs().inMinutes <= 3; - return isValid; + if (_chargingStartTime == null) { + // 边缘情况:回退到当前时间 ±3 分钟 + DateTime nowUtc = DateTime.now().toUtc(); + Duration diff = nowUtc.difference(logTime); + return diff.abs().inMinutes <= 3; + } + // 日志时间必须在 [充电开始时间, 充电开始时间 + 3 分钟] 范围内 + DateTime endTime = _chargingStartTime!.add(const Duration(minutes: 3)); + return logTime.isAfter(_chargingStartTime!) && logTime.isBefore(endTime); } - // ---------- 🟢 核心:系统API只触发充电状态,不设类型 ---------- + // ---------- 核心:系统API定调 ---------- void _applySystemChargeState(bool isCharging, String systemChargeType) { dev.log( - '[_applySystemChargeState] isCharging: $isCharging, systemChargeType: $systemChargeType (忽略,只用来触发状态)', + '[_applySystemChargeState] isCharging: $isCharging, systemChargeType: $systemChargeType', name: 'BatteryHealth', ); @@ -252,16 +263,48 @@ class _BatteryHealthPageState extends State _chargeVolt = 0.0; _chargeCurr = 0.0; _wiredLevel = null; + _chargingStartTime = null; // 🟢 清空开始时间 _updateChargeState(); return; } - // 🟢 不再根据 systemChargeType 设定类型,统一显示"识别中..." - // 类型完全由日志解析决定 - if (_chargeType.isEmpty) { - _chargeType = ''; // 保持空,让日志解析来填充 + // 🟢 1.3.0-dev.3: 记录充电开始时刻(仅当从断开状态变为充电状态时) + if (_chargingStartTime == null) { + _chargingStartTime = DateTime.now().toUtc(); + dev.log( + '[_applySystemChargeState] 充电开始时间: $_chargingStartTime', + name: 'BatteryHealth', + ); + } + + if (systemChargeType == "WIRELESS") { + dev.log('[_applySystemChargeState] 无线充电模式', name: 'BatteryHealth'); + _isWireless = true; + _chargeType = "无线"; + _wiredLevel = null; + } else if (systemChargeType == "AC") { + dev.log( + '[_applySystemChargeState] 有线快充模式 (AC/PPS)', + name: 'BatteryHealth', + ); + _isWireless = false; + _chargeType = "PPS"; + } else if (systemChargeType == "USB") { + dev.log( + '[_applySystemChargeState] 有线慢充模式 (USB/SDP)', + name: 'BatteryHealth', + ); + _isWireless = false; + _chargeType = "SDP"; + } else { + // UNKNOWN 时清空旧类型,等待日志修正 + dev.log( + '[_applySystemChargeState] ⚠️ 未知类型: $systemChargeType,清空类型等待日志', + name: 'BatteryHealth', + ); + _isWireless = false; + _chargeType = ''; } - _isWireless = false; // 重置无线标志,等待日志确认 _chargePower = 0.0; _chargeVolt = 0.0; @@ -269,13 +312,12 @@ class _BatteryHealthPageState extends State _updateChargeState(); }); - // 🟢 插入充电器后立即读取日志 if (_isCharging) { _fetchChargeDataFromLog(); } } - // ---------- 🟢 日志解析:唯一的数据源 ---------- + // ---------- 日志解析 ---------- void _parseChargeDataFromLog(List lines) { dev.log( '[_parseChargeDataFromLog] 开始解析,共 ${lines.length} 行', @@ -367,15 +409,16 @@ class _BatteryHealthPageState extends State _chargeVolt = vbus / 1000000.0; _chargeCurr = ibus / 1000000.0; - // 有线模式 _isWireless = false; + // 🟢 1.3.0-dev.2: real_type 优先级最高 if (realType != null && realType == "PPS") { _chargeType = "PPS"; - } else if (level >= 3) { - _chargeType = "PPS"; - } else if (realType != null && realType == "SDP") { + } else if (realType != null && + (realType == "SDP" || realType == "FLOAT")) { _chargeType = "SDP"; + } else if (level >= 3 && _chargeType != "PPS") { + _chargeType = "PPS"; } else if (_chargeType.isEmpty) { _chargeType = "SDP"; } @@ -385,8 +428,9 @@ class _BatteryHealthPageState extends State } else { _wiredLevel = null; } + dev.log( - '[_parseChargeDataFromLog] 有线更新: $_chargeType, ${_chargePower.toStringAsFixed(2)}W', + '[_parseChargeDataFromLog] 有线更新: $_chargeType, ${_chargePower.toStringAsFixed(2)}W, level: $level', name: 'BatteryHealth', ); }); @@ -394,11 +438,25 @@ class _BatteryHealthPageState extends State } } + // 🟢 1.3.0-dev.3: 增加超时保护 Future _fetchChargeDataFromLog() async { if (!_isCharging) { dev.log('[_fetchChargeDataFromLog] 未充电,跳过读取', name: 'BatteryHealth'); return; } + + // 超时检查:如果插入超过 5 分钟还没读到数据,不再频繁报错 + if (_chargingStartTime != null) { + Duration elapsed = DateTime.now().toUtc().difference(_chargingStartTime!); + if (elapsed.inMinutes > 5) { + dev.log( + '[_fetchChargeDataFromLog] 充电开始已超过 5 分钟,跳过本次轮询', + name: 'BatteryHealth', + ); + return; + } + } + String fullPath = _filePath + getTodayFileName(); dev.log('[_fetchChargeDataFromLog] 尝试读取: $fullPath', name: 'BatteryHealth'); @@ -636,7 +694,6 @@ class _BatteryHealthPageState extends State _applySystemChargeState(isCharging, systemType); }); - // 🟢 轮询间隔缩短为 15 秒 _pollTimer = Timer.periodic(const Duration(seconds: 15), (timer) { if (_isCharging) { _fetchChargeDataFromLog(); @@ -980,9 +1037,9 @@ class _BatteryHealthPageState extends State double value = percents[index]; Color barColor; if (value > 0) { - if (value >= 80) { + if (value >= 80) barColor = kHealthGreen; - } else if (value >= 60) + else if (value >= 60) barColor = kHealthYellow; else barColor = kHealthOrange; diff --git a/lib/widgets/charge_detail_page.dart b/lib/widgets/charge_detail_page.dart index 4260ba9..734f7fa 100644 --- a/lib/widgets/charge_detail_page.dart +++ b/lib/widgets/charge_detail_page.dart @@ -11,14 +11,14 @@ class ChargeDetailPage extends StatelessWidget { final int? wiredLevel; const ChargeDetailPage({ - Key? key, + super.key, required this.chargeType, required this.isWireless, required this.power, required this.volt, required this.curr, this.wiredLevel, - }) : super(key: key); + }); String _getDisplayPower() { if (isWireless) { diff --git a/pubspec.yaml b/pubspec.yaml index 6c7e690..91656f7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.2.0 +version: 1.2.0-dev.3 environment: sdk: ^3.9.2