尝试针对魅族20系设计新的计算逻辑
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import 'dart:developer' as dev;
|
||||
import '../services/database_service.dart';
|
||||
import '../logic/capacity_extractor.dart';
|
||||
import '../models/saf_permission_state.dart';
|
||||
import '../services/saf_storage_service.dart';
|
||||
|
||||
/// 电池数据服务:扫描日志、更新数据库
|
||||
class BatteryDataService {
|
||||
final SafStorageService _safService = SafStorageService();
|
||||
final DatabaseService _dbService = DatabaseService();
|
||||
|
||||
/// 扫描所有日志文件并更新数据库
|
||||
Future<void> scanAndUpdateDB() async {
|
||||
dev.log('🔵 scanAndUpdateDB 开始', name: 'BatteryHealth');
|
||||
|
||||
final state = await _safService.getPermissionState();
|
||||
if (state != SafPermissionState.authorized) {
|
||||
dev.log('🔵 scanAndUpdateDB: 未授权', name: 'BatteryHealth');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final files = await _safService.listFiles();
|
||||
final filePattern = RegExp(r'mbattery_charger_log_(\d{4}_\d{2}_\d{2})$');
|
||||
|
||||
for (String fileName in files) {
|
||||
final match = filePattern.firstMatch(fileName);
|
||||
if (match == null) continue;
|
||||
|
||||
final dateStr = match.group(1)!.replaceAll('_', '-');
|
||||
dev.log('🔵 处理文件: $fileName, 日期: $dateStr', name: 'BatteryHealth');
|
||||
|
||||
try {
|
||||
final lines = await _safService.readLogFile(fileName);
|
||||
if (lines.isEmpty) continue;
|
||||
|
||||
// 使用 CapacityExtractor 提取容量
|
||||
final cap = CapacityExtractor.extractCapacity(lines);
|
||||
if (cap == null) {
|
||||
dev.log('🔵 文件 $fileName 无容量数据', name: 'BatteryHealth');
|
||||
continue;
|
||||
}
|
||||
|
||||
// 提取电压极值
|
||||
final voltReg = RegExp(r'vbat=(\d+)');
|
||||
double? maxVolt, minVolt;
|
||||
for (String line in lines) {
|
||||
if (!line.contains('tbat=')) continue;
|
||||
final match = voltReg.firstMatch(line);
|
||||
if (match != null) {
|
||||
final v = int.parse(match.group(1)!) / 1000000;
|
||||
if (maxVolt == null || v > maxVolt) maxVolt = v;
|
||||
if (minVolt == null || v < minVolt) minVolt = v;
|
||||
}
|
||||
}
|
||||
if (maxVolt == null || minVolt == null) continue;
|
||||
|
||||
await _dbService.insertOrUpdate(dateStr, cap, maxVolt, minVolt);
|
||||
dev.log('🔵 插入数据库: $dateStr, cap=$cap', name: 'BatteryHealth');
|
||||
} catch (e) {
|
||||
dev.log('🔵 处理文件 $fileName 异常: $e', name: 'BatteryHealth');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
dev.log('🔵 scanAndUpdateDB 异常: $e', name: 'BatteryHealth');
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取趋势数据(最近 N 天)
|
||||
Future<List<Map<String, dynamic>>> getTrendData(int days) async {
|
||||
return await _dbService.queryRecentData(days);
|
||||
}
|
||||
|
||||
/// 获取最近一条数据
|
||||
Future<Map<String, dynamic>?> getLatestData() async {
|
||||
final data = await _dbService.queryRecentData(1);
|
||||
if (data.isNotEmpty) return data.first;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
import 'dart:developer' as dev;
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
import 'package:path/path.dart';
|
||||
|
||||
/// 数据库服务:管理电池数据持久化
|
||||
class DatabaseService {
|
||||
static Database? _database;
|
||||
static const String _tableName = 'battery_data';
|
||||
|
||||
/// 获取数据库实例(单例)
|
||||
Future<Database> get database async {
|
||||
if (_database != null) return _database!;
|
||||
_database = await _initDatabase();
|
||||
return _database!;
|
||||
}
|
||||
|
||||
/// 初始化数据库
|
||||
Future<Database> _initDatabase() async {
|
||||
final dbPath = await getDatabasesPath();
|
||||
final path = join(dbPath, 'battery_health.db');
|
||||
|
||||
return await openDatabase(
|
||||
path,
|
||||
version: 1,
|
||||
onCreate: (db, version) async {
|
||||
await db.execute('''
|
||||
CREATE TABLE $_tableName (
|
||||
date TEXT PRIMARY KEY,
|
||||
capacity INTEGER NOT NULL,
|
||||
volt_max REAL NOT NULL,
|
||||
volt_min REAL NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
)
|
||||
''');
|
||||
await db.execute('''
|
||||
CREATE INDEX idx_date ON $_tableName (date DESC)
|
||||
''');
|
||||
dev.log('✅ 数据库表创建成功', name: 'DatabaseService');
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 插入或更新数据
|
||||
Future<void> insertOrUpdate(
|
||||
String date,
|
||||
int capacity,
|
||||
double voltMax,
|
||||
double voltMin,
|
||||
) async {
|
||||
final db = await database;
|
||||
final now = DateTime.now().toIso8601String();
|
||||
|
||||
await db.insert(_tableName, {
|
||||
'date': date,
|
||||
'capacity': capacity,
|
||||
'volt_max': voltMax,
|
||||
'volt_min': voltMin,
|
||||
'updated_at': now,
|
||||
}, conflictAlgorithm: ConflictAlgorithm.replace);
|
||||
dev.log('📝 数据已保存: $date, cap=$capacity', name: 'DatabaseService');
|
||||
}
|
||||
|
||||
/// 查询最近 N 条数据(按日期倒序)
|
||||
Future<List<Map<String, dynamic>>> queryRecentData(int limit) async {
|
||||
final db = await database;
|
||||
try {
|
||||
final result = await db.query(
|
||||
_tableName,
|
||||
orderBy: 'date DESC',
|
||||
limit: limit,
|
||||
);
|
||||
return result;
|
||||
} catch (e) {
|
||||
dev.log('⚠️ 查询数据失败: $e', name: 'DatabaseService');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/// 查询指定日期数据
|
||||
Future<Map<String, dynamic>?> queryByDate(String date) async {
|
||||
final db = await database;
|
||||
try {
|
||||
final result = await db.query(
|
||||
_tableName,
|
||||
where: 'date = ?',
|
||||
whereArgs: [date],
|
||||
);
|
||||
return result.isNotEmpty ? result.first : null;
|
||||
} catch (e) {
|
||||
dev.log('⚠️ 查询单日数据失败: $e', name: 'DatabaseService');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// 删除指定日期数据
|
||||
Future<void> deleteByDate(String date) async {
|
||||
final db = await database;
|
||||
await db.delete(_tableName, where: 'date = ?', whereArgs: [date]);
|
||||
}
|
||||
|
||||
/// 获取数据库中所有日期列表
|
||||
Future<List<String>> getAllDates() async {
|
||||
final db = await database;
|
||||
try {
|
||||
final result = await db.query(
|
||||
_tableName,
|
||||
columns: ['date'],
|
||||
orderBy: 'date DESC',
|
||||
);
|
||||
return result.map((row) => row['date'] as String).toList();
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/// 清空所有数据
|
||||
Future<void> clearAll() async {
|
||||
final db = await database;
|
||||
await db.delete(_tableName);
|
||||
dev.log('🗑️ 所有数据已清空', name: 'DatabaseService');
|
||||
}
|
||||
|
||||
/// 关闭数据库
|
||||
Future<void> close() async {
|
||||
if (_database != null) {
|
||||
await _database!.close();
|
||||
_database = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user