diff --git a/lib/logic/capacity_extractor.dart b/lib/logic/capacity_extractor.dart index c53dcfe..971b322 100644 --- a/lib/logic/capacity_extractor.dart +++ b/lib/logic/capacity_extractor.dart @@ -2,24 +2,33 @@ /// 支持两种日志格式: /// 1. learned_cap(21 系列):单位 µAh,除以 1000 得到 mAh /// 2. remaining_cap(20 系列):单位 mAh,直接使用(但 21 系列的 remaining_cap 也是 µAh,需判断) +/// +/// 🟢 1.4.5 优化:仅从 status=Full 的行中提取容量(充满状态下 BMS 最准确) class CapacityExtractor { static int? extractCapacity(List lines) { - final validLines = lines.where((line) => line.contains('tbat=')).toList(); - if (validLines.isEmpty) return null; + // 🟢 只保留包含 tbat= 且 status=Full 的行 + final fullLines = lines.where((line) { + return line.contains('tbat=') && line.contains('status=Full'); + }).toList(); + + if (fullLines.isEmpty) { + // 今天没有充满电的记录,返回 null 表示无有效数据 + return null; + } // 模式一:learned_cap(21 系列) final learnedReg = RegExp(r'learned_cap=(\d+)'); - for (String line in validLines.reversed) { + for (String line in fullLines.reversed) { final match = learnedReg.firstMatch(line); if (match != null) { return int.parse(match.group(1)!) ~/ 1000; } } - // 模式二:remaining_cap 最大值 + // 模式二:remaining_cap 最大值(20 系列,或 21 系列回退) final remainingReg = RegExp(r'remaining_cap=(\d+)'); int? maxRemaining; - for (String line in validLines) { + for (String line in fullLines) { final match = remainingReg.firstMatch(line); if (match != null) { final value = int.parse(match.group(1)!); @@ -31,7 +40,6 @@ class CapacityExtractor { if (maxRemaining == null) return null; // 🟢 判断单位:如果数值大于 100000(约 100 mAh),则认为是 µAh,需除以 1000 - // 否则认为是 mAh,直接使用 if (maxRemaining > 100000) { return maxRemaining ~/ 1000; } else { diff --git a/lib/services/battery_data_service.dart b/lib/services/battery_data_service.dart index 972b85e..8c8747a 100644 --- a/lib/services/battery_data_service.dart +++ b/lib/services/battery_data_service.dart @@ -34,14 +34,41 @@ class BatteryDataService { final lines = await _safService.readLogFile(fileName); if (lines.isEmpty) continue; - // 使用 CapacityExtractor 提取容量 - final cap = CapacityExtractor.extractCapacity(lines); + // 🟢 1.4.5 改进:使用 CapacityExtractor 提取容量(仅从 Full 状态提取) + int? cap = CapacityExtractor.extractCapacity(lines); + + // 🟢 如果今天没有充满电(cap == null),尝试从昨天复制数据 if (cap == null) { - dev.log('🔵 文件 $fileName 无容量数据', name: 'BatteryHealth'); - continue; + dev.log('🔵 日期 $dateStr 无充满记录,尝试复制前一天数据', name: 'BatteryHealth'); + + // 查询最近一条已有数据 + final recentData = await _dbService.queryRecentData(1); + if (recentData.isNotEmpty) { + final yesterdayCap = recentData.first['capacity'] as int; + final yesterdayMaxVolt = + recentData.first['volt_max'] as double? ?? 0.0; + final yesterdayMinVolt = + recentData.first['volt_min'] as double? ?? 0.0; + + dev.log( + '🔵 复制前一天数据: cap=$yesterdayCap, date=$dateStr', + name: 'BatteryHealth', + ); + + // 🟢 复制昨天的容量和电压极值到今天 + await _dbService.insertOrUpdate( + dateStr, + yesterdayCap, + yesterdayMaxVolt, + yesterdayMinVolt, + ); + } else { + dev.log('🔵 无历史数据可复制,跳过日期 $dateStr', name: 'BatteryHealth'); + } + continue; // 已处理,跳过后续电压提取逻辑 } - // 提取电压极值 + // 提取电压极值(从所有有效行提取,不限于 Full) final voltReg = RegExp(r'vbat=(\d+)'); double? maxVolt, minVolt; for (String line in lines) { diff --git a/lib/services/database_service.dart b/lib/services/database_service.dart index 016422b..5e548f7 100644 --- a/lib/services/database_service.dart +++ b/lib/services/database_service.dart @@ -76,7 +76,7 @@ class DatabaseService { } } - /// 查询指定日期数据 + /// 🟢 1.4.5 新增:查询指定日期数据 Future?> queryByDate(String date) async { final db = await database; try { diff --git a/lib/widgets/charge_entry.dart b/lib/widgets/charge_entry.dart index 1901174..263b58e 100644 --- a/lib/widgets/charge_entry.dart +++ b/lib/widgets/charge_entry.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +/// 充电入口行(显示充电状态 + 点击进入详情) class ChargeEntry extends StatelessWidget { final String summary; final bool isCharging;