调整协议识别逻辑、调整时间读取逻辑

This commit is contained in:
2026-07-03 22:36:18 +08:00
parent feede517dc
commit 15870b4ac4
3 changed files with 86 additions and 29 deletions
+81 -24
View File
@@ -47,13 +47,16 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
// ---------- 充电状态 ---------- // ---------- 充电状态 ----------
bool _isCharging = false; bool _isCharging = false;
String _chargeType = ''; // "EPP", "PPS", "SDP", "无线" 等 String _chargeType = ''; // "EPP", "PPS", "SDP", "无线", "MZ_EPP"
double _chargePower = 0.0; double _chargePower = 0.0;
double _chargeVolt = 0.0; double _chargeVolt = 0.0;
double _chargeCurr = 0.0; double _chargeCurr = 0.0;
int? _wiredLevel; int? _wiredLevel;
bool _isWireless = false; bool _isWireless = false;
// 🟢 1.3.0-dev.3: 充电开始时间(UTC),用于时间窗口判断
DateTime? _chargingStartTime;
// 动画控制 // 动画控制
late AnimationController _chargeAnimationController; late AnimationController _chargeAnimationController;
late Animation<double> _bottomSlide; late Animation<double> _bottomSlide;
@@ -195,15 +198,17 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
} }
} }
// ---------- 1.3.0-dev.1: 使用 UTC 生成文件名 ----------
String getTodayFileName() { String getTodayFileName() {
DateTime now = DateTime.now(); DateTime nowUtc = DateTime.now().toUtc();
String year = now.year.toString(); String year = nowUtc.year.toString();
String month = now.month.toString().padLeft(2, '0'); String month = nowUtc.month.toString().padLeft(2, '0');
String day = now.day.toString().padLeft(2, '0'); String day = nowUtc.day.toString().padLeft(2, '0');
return 'mbattery_charger_log_${year}_${month}_$day'; return 'mbattery_charger_log_${year}_${month}_$day';
} }
// ---------- 时间戳工具方法 ---------- // ---------- 时间戳工具方法 ----------
/// 解析日志行中的时间戳,强制解析为 UTC
DateTime? _parseLogTimestamp(String line) { DateTime? _parseLogTimestamp(String line) {
RegExp reg = RegExp(r'\[(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})\]'); RegExp reg = RegExp(r'\[(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})\]');
Match? match = reg.firstMatch(line); Match? match = reg.firstMatch(line);
@@ -226,18 +231,24 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
} }
} }
/// 🟢 1.3.0-dev.3: 时间窗口以插入时刻为基准,只向前看
bool _isLogTimestampValid(DateTime? logTime) { bool _isLogTimestampValid(DateTime? logTime) {
if (logTime == null) return false; if (logTime == null) return false;
if (_chargingStartTime == null) {
// 边缘情况:回退到当前时间 ±3 分钟
DateTime nowUtc = DateTime.now().toUtc(); DateTime nowUtc = DateTime.now().toUtc();
Duration diff = nowUtc.difference(logTime); Duration diff = nowUtc.difference(logTime);
bool isValid = diff.abs().inMinutes <= 3; return diff.abs().inMinutes <= 3;
return isValid; }
// 日志时间必须在 [充电开始时间, 充电开始时间 + 3 分钟] 范围内
DateTime endTime = _chargingStartTime!.add(const Duration(minutes: 3));
return logTime.isAfter(_chargingStartTime!) && logTime.isBefore(endTime);
} }
// ---------- 🟢 核心:系统API只触发充电状态,不设类型 ---------- // ---------- 核心:系统API定调 ----------
void _applySystemChargeState(bool isCharging, String systemChargeType) { void _applySystemChargeState(bool isCharging, String systemChargeType) {
dev.log( dev.log(
'[_applySystemChargeState] isCharging: $isCharging, systemChargeType: $systemChargeType (忽略,只用来触发状态)', '[_applySystemChargeState] isCharging: $isCharging, systemChargeType: $systemChargeType',
name: 'BatteryHealth', name: 'BatteryHealth',
); );
@@ -252,16 +263,48 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
_chargeVolt = 0.0; _chargeVolt = 0.0;
_chargeCurr = 0.0; _chargeCurr = 0.0;
_wiredLevel = null; _wiredLevel = null;
_chargingStartTime = null; // 🟢 清空开始时间
_updateChargeState(); _updateChargeState();
return; return;
} }
// 🟢 不再根据 systemChargeType 设定类型,统一显示"识别中..." // 🟢 1.3.0-dev.3: 记录充电开始时刻(仅当从断开状态变为充电状态时)
// 类型完全由日志解析决定 if (_chargingStartTime == null) {
if (_chargeType.isEmpty) { _chargingStartTime = DateTime.now().toUtc();
_chargeType = ''; // 保持空,让日志解析来填充 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; _chargePower = 0.0;
_chargeVolt = 0.0; _chargeVolt = 0.0;
@@ -269,13 +312,12 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
_updateChargeState(); _updateChargeState();
}); });
// 🟢 插入充电器后立即读取日志
if (_isCharging) { if (_isCharging) {
_fetchChargeDataFromLog(); _fetchChargeDataFromLog();
} }
} }
// ---------- 🟢 日志解析:唯一的数据源 ---------- // ---------- 日志解析 ----------
void _parseChargeDataFromLog(List<String> lines) { void _parseChargeDataFromLog(List<String> lines) {
dev.log( dev.log(
'[_parseChargeDataFromLog] 开始解析,共 ${lines.length}', '[_parseChargeDataFromLog] 开始解析,共 ${lines.length}',
@@ -367,15 +409,16 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
_chargeVolt = vbus / 1000000.0; _chargeVolt = vbus / 1000000.0;
_chargeCurr = ibus / 1000000.0; _chargeCurr = ibus / 1000000.0;
// 有线模式
_isWireless = false; _isWireless = false;
// 🟢 1.3.0-dev.2: real_type 优先级最高
if (realType != null && realType == "PPS") { if (realType != null && realType == "PPS") {
_chargeType = "PPS"; _chargeType = "PPS";
} else if (level >= 3) { } else if (realType != null &&
_chargeType = "PPS"; (realType == "SDP" || realType == "FLOAT")) {
} else if (realType != null && realType == "SDP") {
_chargeType = "SDP"; _chargeType = "SDP";
} else if (level >= 3 && _chargeType != "PPS") {
_chargeType = "PPS";
} else if (_chargeType.isEmpty) { } else if (_chargeType.isEmpty) {
_chargeType = "SDP"; _chargeType = "SDP";
} }
@@ -385,8 +428,9 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
} else { } else {
_wiredLevel = null; _wiredLevel = null;
} }
dev.log( dev.log(
'[_parseChargeDataFromLog] 有线更新: $_chargeType, ${_chargePower.toStringAsFixed(2)}W', '[_parseChargeDataFromLog] 有线更新: $_chargeType, ${_chargePower.toStringAsFixed(2)}W, level: $level',
name: 'BatteryHealth', name: 'BatteryHealth',
); );
}); });
@@ -394,11 +438,25 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
} }
} }
// 🟢 1.3.0-dev.3: 增加超时保护
Future<void> _fetchChargeDataFromLog() async { Future<void> _fetchChargeDataFromLog() async {
if (!_isCharging) { if (!_isCharging) {
dev.log('[_fetchChargeDataFromLog] 未充电,跳过读取', name: 'BatteryHealth'); dev.log('[_fetchChargeDataFromLog] 未充电,跳过读取', name: 'BatteryHealth');
return; 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(); String fullPath = _filePath + getTodayFileName();
dev.log('[_fetchChargeDataFromLog] 尝试读取: $fullPath', name: 'BatteryHealth'); dev.log('[_fetchChargeDataFromLog] 尝试读取: $fullPath', name: 'BatteryHealth');
@@ -636,7 +694,6 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
_applySystemChargeState(isCharging, systemType); _applySystemChargeState(isCharging, systemType);
}); });
// 🟢 轮询间隔缩短为 15 秒
_pollTimer = Timer.periodic(const Duration(seconds: 15), (timer) { _pollTimer = Timer.periodic(const Duration(seconds: 15), (timer) {
if (_isCharging) { if (_isCharging) {
_fetchChargeDataFromLog(); _fetchChargeDataFromLog();
@@ -980,9 +1037,9 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
double value = percents[index]; double value = percents[index];
Color barColor; Color barColor;
if (value > 0) { if (value > 0) {
if (value >= 80) { if (value >= 80)
barColor = kHealthGreen; barColor = kHealthGreen;
} else if (value >= 60) else if (value >= 60)
barColor = kHealthYellow; barColor = kHealthYellow;
else else
barColor = kHealthOrange; barColor = kHealthOrange;
+2 -2
View File
@@ -11,14 +11,14 @@ class ChargeDetailPage extends StatelessWidget {
final int? wiredLevel; final int? wiredLevel;
const ChargeDetailPage({ const ChargeDetailPage({
Key? key, super.key,
required this.chargeType, required this.chargeType,
required this.isWireless, required this.isWireless,
required this.power, required this.power,
required this.volt, required this.volt,
required this.curr, required this.curr,
this.wiredLevel, this.wiredLevel,
}) : super(key: key); });
String _getDisplayPower() { String _getDisplayPower() {
if (isWireless) { if (isWireless) {
+1 -1
View File
@@ -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 # 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 # 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. # 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: environment:
sdk: ^3.9.2 sdk: ^3.9.2