diff --git a/src/node_info/files/PveMod_pvemanagerlib.js b/src/node_info/files/PveMod_pvemanagerlib.js
index a08fc71..8a9f47d 100644
--- a/src/node_info/files/PveMod_pvemanagerlib.js
+++ b/src/node_info/files/PveMod_pvemanagerlib.js
@@ -656,7 +656,106 @@ 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 '';
+ }
+ 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) {
+ this.hide();
+ 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..0df7c99 100644
--- a/src/node_info/node_info.configure.sh
+++ b/src/node_info/node_info.configure.sh
@@ -251,6 +251,12 @@ node_info_configure() {
fi
#endregion NVMe
+ #region Other thermals
+ msgb "\n=== Detecting other thermal sensors ==="
+ local otherCount
+
+ #region Other thermals
+
#region Fans
msgb "\n=== Detecting fan speed sensors ==="
local fanCount