@@ -94,7 +94,7 @@ foreach ($devs as $disk) {
9494}
9595
9696$array_percent = number_format(100*$array_used/($array_size ?: 1),1,$dot,'');
97- exec('cat /sys/devices/system/cpu/*/topology/thread_siblings_list|sort -nu', $cpus);
97+ $cpus=get_cpu_packages( );
9898$wg_up = $wireguard ? exec("wg show interfaces") : '';
9999$wg_up = $wg_up ? explode(' ',$wg_up) : [];
100100$up = count($wg_up);
@@ -351,8 +351,13 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout
351351 <td>
352352 <span class='flex flex-row flex-wrap items-center gap-4'>
353353 <span class="head_info">
354- <span id='cpu-temp'> </span>
354+ <span id='cpu-total-power'><i class='fa fa-fw fa-plug'></i>_(Total)_ _(Power)_: N/A </span>
355355 </span>
356+ <?if (count($cpus)<2):?>
357+ <span class="head_info">
358+ <i class="fa fa-thermometer"></i> _(Temperature)_: <span id='cpu-temp0'>N/A</span>
359+ </span>
360+ <?endif;?>
356361 <span class="switch">
357362 _(Load)_:<span class="head_bar">
358363 <span class='cpu_ load'>0%</span>
@@ -398,22 +403,29 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout
398403 </span>
399404 </td>
400405 </tr>
401-
406+ <tr>
402407 <?
403- foreach ($cpus as $pair) {
404- [$cpu1, $cpu2] = my_preg_split('/[,-]/',$pair);
405- echo "<tr class='cpu_open'>";
406- if ($is_intel_cpu && count($core_types) > 0)
407- $core_type = "({$core_types[$cpu1]})";
408- else
409- $core_type = "";
410-
411- if ($cpu2)
412- echo "<td><span class='w26'>CPU $cpu1 $core_type - HT $cpu2 </span><span class='dashboard w36'><span class='cpu$cpu1 load resize'>0%</span><div class='usage-disk sys'><span id='cpu$cpu1'></span><span></span></div></span><span class='dashboard w36'><span class='cpu$cpu2 load resize'>0%</span><div class='usage-disk sys'><span id='cpu$cpu2'></span><span></span></div></span></td>";
413- else
414- echo "<td><span class='w26'>CPU $cpu1 $core_type</span><span class='w72'><span class='cpu$cpu1 load resize'>0%</span><div class='usage-disk sys'><span id='cpu$cpu1'></span><span></span></div></span></td>";
415- echo "</tr>";
416- }
408+ foreach ($cpus as $cpu_index=>$package) {
409+ if (count($cpus) > 1) {
410+ echo "<td><span class='cpu_open w72'><i class='fa fa-plug'></i> "._("Physical")." CPU $cpu_index "._("Power").": <span id='cpu-power$cpu_index'>N/A </span> ";
411+ if (count($cpus)>1) echo "<i class='fa fa-thermometer'></i> "._("Temperature").": <span id='cpu-temp$cpu_index'>N/A</span>";
412+ echo "</td></span></tr>";
413+ }
414+ foreach ($package as $pair) {
415+ [$cpu1, $cpu2] = my_preg_split('/[,-]/',$pair);
416+ echo "<tr class='cpu_open'>";
417+ if ($is_intel_cpu && count($core_types) > 0)
418+ $core_type = "({$core_types[$cpu1]})";
419+ else
420+ $core_type = "";
421+
422+ if ($cpu2)
423+ echo "<td><span class='w26'>CPU $cpu1 $core_type - HT $cpu2 </span><span class='dashboard w36'><span class='cpu$cpu1 load resize'>0%</span><div class='usage-disk sys'><span id='cpu$cpu1'></span><span></span></div></span><span class='dashboard w36'><span class='cpu$cpu2 load resize'>0%</span><div class='usage-disk sys'><span id='cpu$cpu2'></span><span></span></div></span></td>";
424+ else
425+ echo "<td><span class='w26'>CPU $cpu1 $core_type</span><span class='w72'><span class='cpu$cpu1 load resize'>0%</span><div class='usage-disk sys'><span id='cpu$cpu1'></span><span></span></div></span></td>";
426+ echo "</tr>";
427+ }
428+ }
417429 ?>
418430 <tr id='cpu_chart'>
419431 <td>
@@ -1441,6 +1453,7 @@ var startup = true;
14411453var stopgap = '<thead class="stopgap"><tr><td class="stopgap"></td></tr></thead>';
14421454var recall = null;
14431455var recover = null;
1456+ var tempunit="<?=_var($display,'unit','C');?>";
14441457
14451458// Helper function to calculate millisPerPixel based on container width
14461459function getMillisPerPixel(timeInSeconds, containerId) {
@@ -1695,6 +1708,39 @@ function addChartNet(rx, tx) {
16951708 txTimeSeries.append(now, Math.floor(tx / 1000));
16961709}
16971710
1711+ function updateCPUPower() {
1712+ if (!cpupower) return;
1713+
1714+ // Update total power
1715+ const totalEl = document.getElementById('cpu-total-power');
1716+ const totalPower = cpupower.totalPower ?? 0;
1717+ if (totalEl) {
1718+ totalEl.innerHTML = `<i class="fa fa-fw fa-plug"></i> _(Total)_ _(Power)_: ${totalPower.toFixed(2)} W`;
1719+ }
1720+
1721+ // Update each core's span
1722+ const cpuspower = cpupower.power ?? [];
1723+ cpuspower.forEach((power, index) => {
1724+ const coreEl = document.getElementById(`cpu-power${index}`);
1725+ if (coreEl) {
1726+ coreEl.innerHTML = `${power.toFixed(2)} W`;
1727+ }
1728+ });
1729+
1730+ const cpustemps = cpupower.temp ?? [];
1731+ cpustemps.forEach((temp, index) => {
1732+ const coreTempEl = document.getElementById(`cpu-temp${index}`);
1733+ if (coreTempEl) {
1734+ tempdisplay = temp.toFixed(0);
1735+ if (tempunit === "F") {
1736+ tempdisplay = ((temp.toFixed(0))* 9 / 5) + 32;
1737+ }
1738+ coreTempEl.innerHTML = Math.round(tempdisplay)+` °`+tempunit;;
1739+ }
1740+ });
1741+
1742+ }
1743+
16981744// Cache for last values to avoid unnecessary DOM updates
16991745var lastCpuValues = {
17001746 load: -1,
@@ -2770,6 +2816,60 @@ $(function() {
27702816 setTimeout(function() {
27712817 // Charts initialized
27722818 },500);
2819+
2820+
2821+
2822+ // Start GraphQL CPU power subscription with retry logic
2823+ let cpuInitPWRAttempts = 0, cpuPWRRetryMs = 100;
2824+ function initPwrCpuSubscription() {
2825+
2826+
2827+ if (window.gql && window.apolloClient) {
2828+ // Define the subscription query when GraphQL is available
2829+ // corepower has the temps currently.
2830+ CPU_POWER_SUBSCRIPTION = window.gql(`
2831+ subscription SystemMetricsCpuTelemetry {
2832+ systemMetricsCpuTelemetry {
2833+ totalPower,
2834+ power,
2835+ temp,
2836+ }
2837+ }
2838+ `);
2839+ cpuPowerSubscription = window.apolloClient.subscribe({
2840+ query: CPU_POWER_SUBSCRIPTION
2841+ }).subscribe({
2842+ next: (result) => {
2843+
2844+
2845+ if (result.data?.systemMetricsCpuTelemetry){
2846+ cpupower = result.data.systemMetricsCpuTelemetry;
2847+
2848+ updateCPUPower();
2849+ }
2850+ },
2851+ error: (err) => {
2852+ console.error('CPU power subscription error:', err);
2853+ // Try to resubscribe with capped backoff
2854+ if (cpuPowerSubscription) { try { cpuPowerSubscription.unsubscribe(); } catch(e){} }
2855+ setTimeout(initPwrCpuSubscription, Math.min(cpuPWRRetryMs *= 2, 5000));
2856+ }
2857+ });
2858+ } else {
2859+ // Retry with capped backoff if GraphQL client not ready
2860+ cpuInitPWRAttempts++;
2861+ setTimeout(initPwrCpuSubscription, Math.min(cpuPWRRetryMs *= 2, 2000));
2862+ }
2863+ }
2864+ initPwrCpuSubscription();
2865+ // Cleanup GraphQL subscription on page unload
2866+ $(window).on('beforeunload', function() {
2867+ if (cpuPowerSubscription) {
2868+ cpuPowerSubscription.unsubscribe();
2869+ }
2870+ });
2871+
2872+
27732873
27742874 // Cleanup GraphQL subscription on page unload
27752875 $(window).on('beforeunload', function() {
0 commit comments