feat: Windows compatibility (#836)

* feat: win compatibility

* fix

* fix: uptime parse

* opt.: linux uptime accuracy

* fix: windows temperature fetching

* opt.

* opt.: powershell exec

* refactor: address PR review feedback and improve code quality

### Major Improvements:
- **Refactored Windows status parsing**: Broke down large `_getWindowsStatus` method into 13 smaller, focused helper methods for better maintainability and readability
- **Extracted system detection logic**: Created dedicated `SystemDetector` helper class to separate OS detection concerns from ServerProvider
- **Improved concurrency handling**: Implemented proper synchronization for server updates using Future-based locks to prevent race conditions

### Bug Fixes:
- **Fixed CPU percentage parsing**: Removed incorrect '*100' multiplication in BSD CPU parsing (values were already percentages)
- **Enhanced memory parsing**: Added validation and error handling to BSD memory fallback parsing with proper logging
- **Improved uptime parsing**: Added support for multiple Windows date formats and robust error handling with validation
- **Fixed division by zero**: Added safety checks in Swap.usedPercent getter

### Code Quality Enhancements:
- **Added comprehensive documentation**: Documented Windows CPU counter limitations and approach
- **Strengthened error handling**: Added detailed logging and validation throughout parsing methods
- **Improved robustness**: Enhanced BSD CPU parsing with percentage validation and warnings
- **Better separation of concerns**: Each parsing method now has single responsibility

### Files Changed:
- `lib/data/helper/system_detector.dart` (new): System detection helper
- `lib/data/model/server/cpu.dart`: Fixed percentage parsing and added validation
- `lib/data/model/server/memory.dart`: Enhanced fallback parsing and division-by-zero protection
- `lib/data/model/server/server_status_update_req.dart`: Refactored into 13 focused parsing methods
- `lib/data/provider/server.dart`: Improved synchronization and extracted system detection

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor: parse & shell fn struct

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
lollipopkit🏳️‍⚧️
2025-08-08 16:56:36 +08:00
committed by GitHub
parent 46a12bc844
commit 3a615449e3
103 changed files with 9591 additions and 1906 deletions

View File

@@ -32,7 +32,7 @@ class AmdSmi {
try {
final jsonData = json.decode(raw);
if (jsonData is! List) return [];
return jsonData
.map((gpu) => _parseGpuItem(gpu))
.where((item) => item != null)
@@ -47,28 +47,28 @@ class AmdSmi {
try {
final name = gpu['name'] ?? gpu['card_model'] ?? gpu['device_name'] ?? 'Unknown AMD GPU';
final deviceId = gpu['device_id']?.toString() ?? gpu['gpu_id']?.toString() ?? '0';
// Temperature parsing
final tempRaw = gpu['temperature'] ?? gpu['temp'] ?? gpu['gpu_temp'];
final temp = _parseIntValue(tempRaw);
// Power parsing
final powerDraw = gpu['power_draw'] ?? gpu['current_power'];
final powerCap = gpu['power_cap'] ?? gpu['power_limit'] ?? gpu['max_power'];
final power = _formatPower(powerDraw, powerCap);
// Memory parsing
final memory = _parseMemory(gpu['memory'] ?? gpu['vram'] ?? {});
// Utilization parsing
final utilization = _parseIntValue(gpu['utilization'] ?? gpu['gpu_util'] ?? gpu['activity']);
// Fan speed parsing
final fanSpeed = _parseIntValue(gpu['fan_speed'] ?? gpu['fan_rpm']);
// Clock speed parsing
final clockSpeed = _parseIntValue(gpu['clock_speed'] ?? gpu['gpu_clock'] ?? gpu['sclk']);
return AmdSmiItem(
deviceId: deviceId,
name: name,
@@ -98,7 +98,7 @@ class AmdSmi {
static String _formatPower(dynamic draw, dynamic cap) {
final drawValue = _parseIntValue(draw);
final capValue = _parseIntValue(cap);
if (drawValue == 0 && capValue == 0) return 'N/A';
if (capValue == 0) return '${drawValue}W';
return '${drawValue}W / ${capValue}W';
@@ -108,7 +108,7 @@ class AmdSmi {
final total = _parseIntValue(memData['total'] ?? memData['total_memory']);
final used = _parseIntValue(memData['used'] ?? memData['used_memory']);
final unit = memData['unit']?.toString() ?? 'MB';
final processes = <AmdSmiMemProcess>[];
final processesData = memData['processes'];
if (processesData is List) {
@@ -119,7 +119,7 @@ class AmdSmi {
}
}
}
return AmdSmiMem(total, used, unit, processes);
}
@@ -127,7 +127,7 @@ class AmdSmi {
final pid = _parseIntValue(procData['pid']);
final name = procData['name']?.toString() ?? procData['process_name']?.toString() ?? 'Unknown';
final memory = _parseIntValue(procData['memory'] ?? procData['used_memory']);
if (pid == 0) return null;
return AmdSmiMemProcess(pid, name, memory);
}
@@ -185,4 +185,4 @@ class AmdSmiMemProcess {
String toString() {
return 'AmdSmiMemProcess{pid: $pid, name: $name, memory: $memory}';
}
}
}