Update AppImage

This commit is contained in:
MacRimi
2025-11-26 18:44:37 +01:00
parent 0b8f5d3b22
commit 9aed659f17
2 changed files with 126 additions and 6 deletions

View File

@@ -2618,6 +2618,53 @@ def identify_temperature_sensor(sensor_name, adapter):
return sensor_name
def identify_fan(sensor_name, adapter):
"""Identify what a fan sensor corresponds to, using hardware_monitor for GPU detection"""
sensor_lower = sensor_name.lower()
adapter_lower = adapter.lower() if adapter else ""
# GPU fans - Use hardware_monitor to get real GPU names
if "pci adapter" in adapter_lower or any(gpu_driver in adapter_lower for gpu_driver in ["nouveau", "amdgpu", "radeon", "i915"]):
# Extract PCI address from adapter string
# Example: "nouveau-pci-0200" -> "02:00.0"
pci_match = re.search(r'pci-([0-9a-f]{4})', adapter_lower)
if pci_match:
pci_code = pci_match.group(1)
pci_address = f"{pci_code[0:2]}:{pci_code[2:4]}.0"
# Get GPU mapping from hardware_monitor
try:
gpu_map = hardware_monitor.get_pci_gpu_map()
if pci_address in gpu_map:
gpu_info = gpu_map[pci_address]
return f"GPU {gpu_info['vendor']} {gpu_info['name']}"
except Exception:
pass
# Fallback: generic GPU label
if "nouveau" in adapter_lower:
return "GPU NVIDIA"
elif "amdgpu" in adapter_lower or "radeon" in adapter_lower:
return "GPU AMD"
elif "i915" in adapter_lower:
return "GPU Intel"
else:
return "GPU"
# CPU/System fans - keep original name
if any(cpu_fan in sensor_lower for cpu_fan in ["cpu_fan", "cpufan", "sys_fan", "sysfan"]):
return sensor_name
# Chassis fans - keep original name
if "chassis" in sensor_lower or "case" in sensor_lower:
return sensor_name
# Default: return original name
return sensor_name
def get_temperature_info():
"""Get detailed temperature information from sensors command"""
temperatures = []
@@ -4514,7 +4561,7 @@ def get_hardware_info():
# Placeholder for identify_fan - needs implementation
# identified_name = identify_fan(sensor_name, current_adapter)
identified_name = sensor_name # Use original name for now
identified_name = identify_fan(sensor_name, current_adapter)
fans.append({
'name': identified_name,

View File

@@ -1,22 +1,95 @@
#!/usr/bin/env python3
"""
Hardware Monitor - RAPL Power Monitoring
Hardware Monitor - RAPL Power Monitoring and GPU Identification
This module provides CPU power consumption monitoring using Intel RAPL
(Running Average Power Limit) interface when IPMI is not available.
This module provides:
1. CPU power consumption monitoring using Intel RAPL (Running Average Power Limit)
2. PCI GPU identification for better fan labeling
Only contains get_power_info() - all other hardware monitoring is handled
by flask_server.py to avoid code duplication.
Only contains these specialized functions - all other hardware monitoring
is handled by flask_server.py to avoid code duplication.
"""
import os
import time
import subprocess
import re
from typing import Dict, Any, Optional
# Global variable to store previous energy reading for power calculation
_last_energy_reading = {'energy_uj': None, 'timestamp': None}
def get_pci_gpu_map() -> Dict[str, Dict[str, str]]:
"""
Get a mapping of PCI addresses to GPU names from lspci.
This function parses lspci output to identify GPU models by their PCI addresses,
which allows us to provide meaningful names for GPU fans in sensors output.
Returns:
dict: Mapping of PCI addresses (e.g., '02:00.0') to GPU info
Example: {
'02:00.0': {
'vendor': 'NVIDIA',
'name': 'GeForce GTX 1080',
'full_name': 'NVIDIA Corporation GP104 [GeForce GTX 1080]'
}
}
"""
gpu_map = {}
try:
# Run lspci to get VGA/3D/Display controllers
result = subprocess.run(
['lspci', '-nn'],
capture_output=True,
text=True,
timeout=5
)
if result.returncode == 0:
for line in result.stdout.split('\n'):
if 'VGA compatible controller' in line or '3D controller' in line or 'Display controller' in line:
# Example line: "02:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP104 [GeForce GTX 1080] [10de:1b80]"
match = re.match(r'^([0-9a-f]{2}:[0-9a-f]{2}\.[0-9a-f])\s+.*:\s+(.+?)\s+\[([0-9a-f]{4}):([0-9a-f]{4})\]', line)
if match:
pci_address = match.group(1)
device_name = match.group(2).strip()
# Extract vendor
vendor = None
if 'NVIDIA' in device_name.upper() or 'GEFORCE' in device_name.upper() or 'QUADRO' in device_name.upper():
vendor = 'NVIDIA'
elif 'AMD' in device_name.upper() or 'RADEON' in device_name.upper():
vendor = 'AMD'
elif 'INTEL' in device_name.upper() or 'ARC' in device_name.upper():
vendor = 'Intel'
# Extract model name (text between brackets is usually the commercial name)
bracket_match = re.search(r'\[([^\]]+)\]', device_name)
if bracket_match:
model_name = bracket_match.group(1)
else:
# Fallback: use everything after the vendor name
if vendor:
model_name = device_name.split(vendor)[-1].strip()
else:
model_name = device_name
gpu_map[pci_address] = {
'vendor': vendor if vendor else 'Unknown',
'name': model_name,
'full_name': device_name
}
except Exception:
pass
return gpu_map
def get_power_info() -> Optional[Dict[str, Any]]:
"""
Get CPU power consumption using Intel RAPL interface.