feat/fix(node_info): expose temp_unit in graphics API response & fix temperature conversion (#295)

Co-authored-by: Meliox <na>
This commit is contained in:
Meliox 2026-08-14 20:32:10 +02:00 committed by GitHub
parent 8ebc2b4753
commit cee8d04e36
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 23 additions and 12 deletions

View File

@ -68,9 +68,10 @@ sub _merge_graphics_files {
my $merged = { my $merged = {
Graphics => { Graphics => {
Intel => {}, Intel => {},
NVIDIA => {}, NVIDIA => {},
AMD => {}, AMD => {},
temp_unit => $config{lm_sensors}{temp_unit},
} }
}; };
@ -134,7 +135,7 @@ sub _load_graphics_data {
\@filepaths, \@filepaths,
$graphics_cache, $graphics_cache,
\&_merge_graphics_files, \&_merge_graphics_files,
{ Graphics => { Intel => {}, NVIDIA => {}, AMD => {} } } { Graphics => { Intel => {}, NVIDIA => {}, AMD => {}, temp_unit => $config{lm_sensors}{temp_unit} } }
); );
my $intel_count = scalar(keys %{$data->{Graphics}{Intel} // {}}); my $intel_count = scalar(keys %{$data->{Graphics}{Intel} // {}});

View File

@ -224,8 +224,7 @@ Ext.define('PVE.node.StatusView', {
objValue = {}; objValue = {};
} }
// sensors configuration // sensors configuration
const cpuTempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: objValue.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS}); const cpuTempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: value.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS});
const cpuKeysI = Object.keys(objValue).filter(item => String(item).startsWith('coretemp-isa-')).sort(); const cpuKeysI = Object.keys(objValue).filter(item => String(item).startsWith('coretemp-isa-')).sort();
const cpuKeysA = Object.keys(objValue).filter(item => String(item).startsWith('k10temp-pci-')).sort(); const cpuKeysA = Object.keys(objValue).filter(item => String(item).startsWith('k10temp-pci-')).sort();
const cpuKeysRpi = Object.keys(objValue).filter(item => String(item).startsWith('cpu_thermal-virtual-')).sort(); const cpuKeysRpi = Object.keys(objValue).filter(item => String(item).startsWith('cpu_thermal-virtual-')).sort();
@ -395,6 +394,12 @@ Ext.define('PVE.node.StatusView', {
return ''; return '';
} }
// Create temperature helper for GPU temperature conversion
const gpuTempHelper = Ext.create('PVE.mod.TempHelper', {
srcUnit: PVE.mod.TempHelper.CELSIUS,
dstUnit: gpuStats.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS
});
let html = '<table style="width: 100%; border-collapse: collapse; table-layout: fixed;">'; let html = '<table style="width: 100%; border-collapse: collapse; table-layout: fixed;">';
// Intel GPUs - Secondary details // Intel GPUs - Secondary details
@ -476,13 +481,18 @@ Ext.define('PVE.node.StatusView', {
// Temperature // Temperature
if (stats.temperature) { if (stats.temperature) {
const gpuTemp = gpuTempHelper.getTemp(parseFloat(stats.temperature.gpu));
const tempUnit = gpuTempHelper.getUnit();
// Convert thresholds to target unit for comparison
const tempHigh = gpuTempHelper.getTemp(80);
const tempWarn = gpuTempHelper.getTemp(70);
let tempStyle = ''; let tempStyle = '';
if (stats.temperature.gpu >= 80) { if (gpuTemp >= tempHigh) {
tempStyle = 'color: red; font-weight: bold;'; tempStyle = 'color: red; font-weight: bold;';
} else if (stats.temperature.gpu >= 70) { } else if (gpuTemp >= tempWarn) {
tempStyle = 'color: #FFC300; font-weight: bold;'; tempStyle = 'color: #FFC300; font-weight: bold;';
} }
details.push(`Temp: <span style="${tempStyle}">${stats.temperature.gpu}${stats.temperature.unit}</span>`); details.push(`Temp: <span style="${tempStyle}">${Ext.util.Format.number(gpuTemp, '0')}${tempUnit}</span>`);
} }
// Power // Power
@ -529,7 +539,7 @@ Ext.define('PVE.node.StatusView', {
} catch(e) { } catch(e) {
objValue = {}; objValue = {};
} }
const tempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: objValue.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS}); const tempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: value.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS});
const drvKeys = Object.keys(objValue).filter(item => String(item).startsWith(addressPrefix)).sort((a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' })); const drvKeys = Object.keys(objValue).filter(item => String(item).startsWith(addressPrefix)).sort((a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }));
let drvData = []; let drvData = [];
drvKeys.forEach((drvKey) => { drvKeys.forEach((drvKey) => {
@ -609,7 +619,7 @@ Ext.define('PVE.node.StatusView', {
} catch(e) { } catch(e) {
objValue = {}; objValue = {};
} }
const tempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: objValue.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS}); const tempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: value.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS});
const nvmeKeys = Object.keys(objValue).filter(item => String(item).startsWith(addressPrefix)).sort(); const nvmeKeys = Object.keys(objValue).filter(item => String(item).startsWith(addressPrefix)).sort();
let nvmeData = []; let nvmeData = [];
nvmeKeys.forEach((nvmeKey, index) => { nvmeKeys.forEach((nvmeKey, index) => {
@ -697,7 +707,7 @@ Ext.define('PVE.node.StatusView', {
} catch(e) { } catch(e) {
objValue = {}; objValue = {};
} }
const tempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: objValue.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS}); const tempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: value.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS});
// Keep only keys that do not belong to known categories // Keep only keys that do not belong to known categories
const otherKeys = Object.keys(objValue).filter(key => const otherKeys = Object.keys(objValue).filter(key =>