diff --git a/src/node_info/files/Collector/LmSensors.pm b/src/node_info/files/Collector/LmSensors.pm
index 9fc952d..9d3ca5d 100644
--- a/src/node_info/files/Collector/LmSensors.pm
+++ b/src/node_info/files/Collector/LmSensors.pm
@@ -92,11 +92,12 @@ sub _get_temperature_sensors {
}
$data = JSON->new->pretty->encode({
- cpu => $config{lm_sensors}{enable_cpu} ? \1 : \0,
- nvme => $config{lm_sensors}{enable_nvme_temp} ? \1 : \0,
- fans => $config{lm_sensors}{enable_fan_speed} ? \1 : \0,
- hdd => $config{lm_sensors}{enable_hdd_temp} ? \1 : \0,
- data => { 'PVE MOD lm-sensors Enhanced' => $sensors_json },
+ cpu => $config{lm_sensors}{enable_cpu} ? \1 : \0,
+ nvme => $config{lm_sensors}{enable_nvme_temp} ? \1 : \0,
+ fans => $config{lm_sensors}{enable_fan_speed} ? \1 : \0,
+ hdd => $config{lm_sensors}{enable_hdd_temp} ? \1 : \0,
+ other => $config{lm_sensors}{enable_other_temp} ? \1 : \0,
+ data => { 'PVE MOD lm-sensors Enhanced' => $sensors_json },
});
return $data;
diff --git a/src/node_info/files/Config.pm b/src/node_info/files/Config.pm
index 2ccadc2..5d31db2 100644
--- a/src/node_info/files/Config.pm
+++ b/src/node_info/files/Config.pm
@@ -69,6 +69,7 @@ our %config = (
enable_ram_temp => 0,
enable_hdd_temp => 0,
enable_nvme_temp => 0,
+ enable_other_temp => 0,
enable_fan_speed => 0,
display_zero_speed_fans => 0,
temp_unit => 'C',
diff --git a/src/node_info/files/PveMod_pvemanagerlib.js b/src/node_info/files/PveMod_pvemanagerlib.js
index a08fc71..2f03726 100644
--- a/src/node_info/files/PveMod_pvemanagerlib.js
+++ b/src/node_info/files/PveMod_pvemanagerlib.js
@@ -656,7 +656,108 @@ Ext.define('PVE.node.StatusView', {
return '
' + html + '
';
}
},
-
+ {
+ itemId: 'otherThermals',
+ colspan: 2,
+ printBar: false,
+ title: gettext('Other Temperatures'),
+ iconCls: 'fa fa-fw fa-thermometer-half',
+ textField: 'PveMod_JsonSensorInfo',
+ renderer: function(value) {
+ // Prefixes belonging to other known categories (excluded from this view)
+ const excludePrefixes = [
+ 'nvme-pci-',
+ 'coretemp-isa-',
+ 'k10temp-pci-',
+ 'cpu_thermal-virtual-',
+ 'drivetemp-',
+ 'spd5118-',
+ ];
+ const tempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: PVE.mod.TempHelper.CELSIUS});
+ // ---
+ let objValue;
+ try {
+ const parsed = value || {};
+ if (parsed.disabled === true) {
+ this.hide();
+ return '';
+ } else if (parsed.other !== true) {
+ this.hide();
+ return '';
+ }
+ objValue = (parsed.data && parsed.data[Object.keys(parsed.data)[0]]) || {};
+ } catch(e) {
+ objValue = {};
+ }
+
+ // Keep only keys that do not belong to known categories
+ const otherKeys = Object.keys(objValue).filter(key =>
+ !excludePrefixes.some(prefix => String(key).startsWith(prefix))
+ ).sort();
+
+ let rows = [];
+
+ otherKeys.forEach(sensorKey => {
+ try {
+ const sensorObj = objValue[sensorKey];
+ if (!sensorObj || typeof sensorObj !== 'object') { return; }
+
+ // Collect all nested temp* sub-objects
+ const tempKeys = Object.keys(sensorObj).filter(k => String(k).startsWith('temp')).sort();
+ if (tempKeys.length === 0) { return; }
+
+ let tempParts = [];
+ tempKeys.forEach(tempKey => {
+ try {
+ const tempData = sensorObj[tempKey];
+ if (!tempData || typeof tempData !== 'object') { return; }
+
+ let tempVal = NaN, tempMax = NaN, tempCrit = NaN;
+ Object.keys(tempData).forEach(subKey => {
+ if (subKey.endsWith('_input')) {
+ tempVal = tempHelper.getTemp(parseFloat(tempData[subKey]));
+ } else if (subKey.endsWith('_max')) {
+ tempMax = tempHelper.getTemp(parseFloat(tempData[subKey]));
+ } else if (subKey.endsWith('_crit')) {
+ tempCrit = tempHelper.getTemp(parseFloat(tempData[subKey]));
+ }
+ });
+
+ if (!isNaN(tempVal)) {
+ let tempStyle = '';
+ if (!isNaN(tempMax) && tempVal >= tempMax) {
+ tempStyle = 'color: #FFC300; font-weight: bold;';
+ }
+ if (!isNaN(tempCrit) && tempVal >= tempCrit) {
+ tempStyle = 'color: red; font-weight: bold;';
+ }
+ tempParts.push(`${tempKey}: ${Ext.util.Format.number(tempVal, '0.0')}${tempHelper.getUnit()}`);
+ }
+ } catch(e) { /*_*/ }
+ });
+
+ if (tempParts.length > 0) {
+ rows.push({ label: sensorKey, temps: tempParts.join(' | ') });
+ }
+ } catch(e) { /*_*/ }
+ });
+
+ if (rows.length === 0) {
+ return '';
+ }
+
+ let html = '';
+ rows.forEach(row => {
+ html += '';
+ html += `| ${row.label} | `;
+ html += `${row.temps} | `;
+ html += '
';
+ });
+ html += '
';
+ return '' + html + '
';
+ }
+ },
+
// ========== TERTIARY DIAGNOSTICS (Tier 3) ==========
{
xtype: 'box',
diff --git a/src/node_info/node_info.configure.sh b/src/node_info/node_info.configure.sh
index feef1a8..3362cd8 100644
--- a/src/node_info/node_info.configure.sh
+++ b/src/node_info/node_info.configure.sh
@@ -64,7 +64,7 @@ _check_nvidia_tool() {
node_info_defaults() {
LM_SENSORS_ENABLED=0
ENABLE_CPU=0; CPU_TEMP_TARGET="Core"
- ENABLE_RAM_TEMP=0; ENABLE_HDD_TEMP=0; ENABLE_NVME_TEMP=0
+ ENABLE_RAM_TEMP=0; ENABLE_HDD_TEMP=0; ENABLE_NVME_TEMP=0; ENABLE_OTHER_TEMP=0
ENABLE_FAN_SPEED=0; DISPLAY_ZERO_SPEED_FANS=0; TEMP_UNIT="C"
ENABLE_INTEL_GPU_INFO=0; ENABLE_NVIDIA_GPU_INFO=0; ENABLE_AMD_GPU_INFO=0
ENABLE_GPU_HISTORY=0
@@ -101,6 +101,7 @@ node_info_load_conf() {
lm_sensors.enable_ram_temp) ENABLE_RAM_TEMP="$val" ;;
lm_sensors.enable_hdd_temp) ENABLE_HDD_TEMP="$val" ;;
lm_sensors.enable_nvme_temp) ENABLE_NVME_TEMP="$val" ;;
+ lm_sensors.enable_other_temp) ENABLE_OTHER_TEMP="$val" ;;
lm_sensors.enable_fan_speed) ENABLE_FAN_SPEED="$val" ;;
lm_sensors.display_zero_speed_fans) DISPLAY_ZERO_SPEED_FANS="$val" ;;
lm_sensors.temp_unit) TEMP_UNIT="$val" ;;
@@ -131,7 +132,7 @@ node_info_configure() {
# Initialize all variables to off
LM_SENSORS_ENABLED=0
ENABLE_CPU=0; CPU_TEMP_TARGET="Core"
- ENABLE_RAM_TEMP=0; ENABLE_HDD_TEMP=0; ENABLE_NVME_TEMP=0
+ ENABLE_RAM_TEMP=0; ENABLE_HDD_TEMP=0; ENABLE_NVME_TEMP=0; ENABLE_OTHER_TEMP=0
ENABLE_FAN_SPEED=0; DISPLAY_ZERO_SPEED_FANS=0; TEMP_UNIT="C"
ENABLE_INTEL_GPU_INFO=0; ENABLE_NVIDIA_GPU_INFO=0; ENABLE_AMD_GPU_INFO=0
ENABLE_GPU_HISTORY=0
@@ -251,6 +252,21 @@ node_info_configure() {
fi
#endregion NVMe
+ #region Other thermals
+ msgb "\n=== Detecting other thermal sensors ==="
+ local otherTempCount
+ otherTempCount=$(echo "$sanitisedSensorsOutput" \
+ | grep -Ev '"(coretemp|k10temp-pci|cpu_thermal-virtual|nvme|drivetemp-scsi|SODIMM|spd5118)[^"]*"' \
+ | grep -c '"temp[0-9]*_input"' || true)
+
+ if [[ "$otherTempCount" -gt 0 ]]; then
+ info "Detected $otherTempCount other temperature reading(s)."
+ ENABLE_OTHER_TEMP=1; sensors_detected=true
+ else
+ warn "No other temperature sensors found."
+ fi
+ #region Other thermals
+
#region Fans
msgb "\n=== Detecting fan speed sensors ==="
local fanCount
@@ -459,6 +475,7 @@ cpu_temp_target=${CPU_TEMP_TARGET}
enable_ram_temp=${ENABLE_RAM_TEMP}
enable_hdd_temp=${ENABLE_HDD_TEMP}
enable_nvme_temp=${ENABLE_NVME_TEMP}
+enable_other_temp=${ENABLE_OTHER_TEMP}
enable_fan_speed=${ENABLE_FAN_SPEED}
display_zero_speed_fans=${DISPLAY_ZERO_SPEED_FANS}
temp_unit=${TEMP_UNIT}
diff --git a/src/node_info/readme.md b/src/node_info/readme.md
index ed49996..c102355 100644
--- a/src/node_info/readme.md
+++ b/src/node_info/readme.md
@@ -6,7 +6,7 @@ Extends the Proxmox VE node status view with live hardware sensor data. A backgr
### Temperature Sensors (lm-sensors)
-Reads hardware sensor data via `lm-sensors` and enriches each chip/adapter entry with context.
+Reads hardware sensor data via `lm-sensors` and enriches each chip/adapter entry with context. CPU, RAM, HDD/SSD, NVME are directly supported and other temperature sensors can be bundled and displayed together.
### NVIDIA GPU