From f5d204e5b273562a6eb4759d80492e816af71719 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Sun, 28 Sep 2025 09:54:41 +0100 Subject: [PATCH 1/7] Add power placeholder and Split physical CPUS --- emhttp/plugins/dynamix/DashStats.page | 34 +++++++++++++--------- emhttp/plugins/dynamix/include/Helpers.php | 17 +++++++++++ 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/emhttp/plugins/dynamix/DashStats.page b/emhttp/plugins/dynamix/DashStats.page index b959f60bf..68ca33c79 100755 --- a/emhttp/plugins/dynamix/DashStats.page +++ b/emhttp/plugins/dynamix/DashStats.page @@ -94,7 +94,7 @@ foreach ($devs as $disk) { } $array_percent = number_format(100*$array_used/($array_size ?: 1),1,$dot,''); -exec('cat /sys/devices/system/cpu/*/topology/thread_siblings_list|sort -nu', $cpus); +$cpus=get_cpu_packages(); $wg_up = $wireguard ? exec("wg show interfaces") : ''; $wg_up = $wg_up ? explode(' ',$wg_up) : []; $up = count($wg_up); @@ -345,6 +345,9 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout + + _(Total Power)_: N/A + @@ -395,20 +398,23 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout "; - if ($is_intel_cpu && count($core_types) > 0) - $core_type = "({$core_types[$cpu1]})"; - else - $core_type = ""; + foreach ($cpus as $cpu_index=>$package) { + echo ""._("Physical")." CPU $cpu_index "._("Power").": N/A"; + foreach ($package as $pair) { + [$cpu1, $cpu2] = my_preg_split('/[,-]/',$pair); + echo ""; + if ($is_intel_cpu && count($core_types) > 0) + $core_type = "({$core_types[$cpu1]})"; + else + $core_type = ""; - if ($cpu2) - echo "CPU $cpu1 $core_type - HT $cpu2 0%
0%
"; - else - echo "CPU $cpu1 $core_type0%
"; - echo ""; - } + if ($cpu2) + echo "CPU $cpu1 $core_type - HT $cpu2 0%
0%
"; + else + echo "CPU $cpu1 $core_type0%
"; + echo ""; + } + } ?> diff --git a/emhttp/plugins/dynamix/include/Helpers.php b/emhttp/plugins/dynamix/include/Helpers.php index 5c3dfacc5..75b152448 100644 --- a/emhttp/plugins/dynamix/include/Helpers.php +++ b/emhttp/plugins/dynamix/include/Helpers.php @@ -857,4 +857,21 @@ HTML; return $html; } + +function get_cpu_packages(string $separator = ','): array { + $packages = []; + foreach (glob("/sys/devices/system/cpu/cpu[0-9]*/topology/thread_siblings_list") as $path) { + $pkg_id = (int)file_get_contents(dirname($path) . "/physical_package_id"); + $siblings = str_replace(",", $separator, trim(file_get_contents($path))); + if (!in_array($siblings, $packages[$pkg_id] ?? [])) { + $packages[$pkg_id][] = $siblings; + } + } + foreach ($packages as &$list) { + $keys = array_map(fn($s) => (int)explode($separator, $s)[0], $list); + array_multisort($keys, SORT_ASC, SORT_NUMERIC, $list); + } + unset($list); + return $packages; +} ?> From e64211b8e5d083f99c0dbfae6ec8319b0c752e91 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Sun, 28 Sep 2025 10:11:26 +0100 Subject: [PATCH 2/7] Add icon to total power. --- emhttp/plugins/dynamix/DashStats.page | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emhttp/plugins/dynamix/DashStats.page b/emhttp/plugins/dynamix/DashStats.page index 68ca33c79..f03d557a9 100755 --- a/emhttp/plugins/dynamix/DashStats.page +++ b/emhttp/plugins/dynamix/DashStats.page @@ -346,7 +346,7 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout - _(Total Power)_: N/A + _(Total Power)_: N/A From e4ed5896f6e5fd3c7022f47c3ca0f91b1a6c0f27 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Sun, 28 Sep 2025 10:17:16 +0100 Subject: [PATCH 3/7] Fix placeholder index --- emhttp/plugins/dynamix/DashStats.page | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emhttp/plugins/dynamix/DashStats.page b/emhttp/plugins/dynamix/DashStats.page index f03d557a9..42ccf33a8 100755 --- a/emhttp/plugins/dynamix/DashStats.page +++ b/emhttp/plugins/dynamix/DashStats.page @@ -399,7 +399,7 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout $package) { - echo ""._("Physical")." CPU $cpu_index "._("Power").": N/A"; + echo ""._("Physical")." CPU $cpu_index "._("Power").": N/A"; foreach ($package as $pair) { [$cpu1, $cpu2] = my_preg_split('/[,-]/',$pair); echo ""; From 2f66cd3d021f225767ed0bc62520b01a7f1b6ee8 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Tue, 21 Oct 2025 20:30:49 +0100 Subject: [PATCH 4/7] Changes for power and temp. --- emhttp/plugins/dynamix/DashStats.page | 96 ++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/emhttp/plugins/dynamix/DashStats.page b/emhttp/plugins/dynamix/DashStats.page index 42ccf33a8..09b63a7d2 100755 --- a/emhttp/plugins/dynamix/DashStats.page +++ b/emhttp/plugins/dynamix/DashStats.page @@ -346,11 +346,13 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout - _(Total Power)_: N/A + _(Total)_ _(Power)_: N/A + - + _(Temp)_: + _(Load)_: 0% @@ -399,7 +401,11 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout $package) { - echo ""._("Physical")." CPU $cpu_index "._("Power").": N/A"; + if (count($cpus) > 1) { + echo ""._("Physical")." CPU $cpu_index "._("Power").": N/A "; + if (count($cpus)>1) echo _("Temp").": N/A"; + echo ""; + } foreach ($package as $pair) { [$cpu1, $cpu2] = my_preg_split('/[,-]/',$pair); echo ""; @@ -1696,6 +1702,36 @@ function addChartNet(rx, tx) { txTimeSeries.append(now, Math.floor(tx / 1000)); } +function updateCPUPower() { + if (!cpupower) return; + + // Update total power + const totalEl = document.getElementById('cpu-total-power'); + const totalPower = cpupower.totalPower ?? 0; + if (totalEl) { + totalEl.innerHTML = ` _(Total)_ _(Power)_: ${totalPower.toFixed(2)} W`; + } + + // Update each core's span + const cpuspower = cpupower.power ?? []; + cpuspower.forEach((power, index) => { + const coreEl = document.getElementById(`cpu-power${index}`); + const coreTempEl = document.getElementById(`cpu-temp${index}`); + if (coreEl) { + coreEl.innerHTML = `${power.toFixed(2)} W`; + } + }); + + const cpustemps = cpupower.temp ?? []; + cpustemps.forEach((temp, index) => { + const coreTempEl = document.getElementById(`cpu-temp${index}`); + if (coreTempEl) { + coreTempEl.innerHTML = `${temp.toFixed(0)} C`;; + } + }); + +} + // Cache for last values to avoid unnecessary DOM updates var lastCpuValues = { load: -1, @@ -2771,6 +2807,60 @@ $(function() { setTimeout(function() { // Charts initialized },500); + + + + // Start GraphQL CPU power subscription with retry logic + let cpuInitPWRAttempts = 0, cpuPWRRetryMs = 100; + function initPwrCpuSubscription() { + + + if (window.gql && window.apolloClient) { + // Define the subscription query when GraphQL is available + // corepower has the temps currently. + CPU_POWER_SUBSCRIPTION = window.gql(` + subscription SystemMetricsCpuTelemetry { + systemMetricsCpuTelemetry { + totalPower, + power, + temp, + } + } + `); + cpuPowerSubscription = window.apolloClient.subscribe({ + query: CPU_POWER_SUBSCRIPTION + }).subscribe({ + next: (result) => { + + + if (result.data?.systemMetricsCpuTelemetry){ + cpupower = result.data.systemMetricsCpuTelemetry; + + updateCPUPower(); + } + }, + error: (err) => { + console.error('CPU power subscription error:', err); + // Try to resubscribe with capped backoff + if (cpuPowerSubscription) { try { cpuPowerSubscription.unsubscribe(); } catch(e){} } + setTimeout(initPwrCpuSubscription, Math.min(cpuPWRRetryMs *= 2, 5000)); + } + }); + } else { + // Retry with capped backoff if GraphQL client not ready + cpuPWRInitAttempts++; + setTimeout(initPwrCpuSubscription, Math.min(cpuPWRRetryMs *= 2, 2000)); + } + } + initPwrCpuSubscription(); + // Cleanup GraphQL subscription on page unload + $(window).on('beforeunload', function() { + if (cpuPowerSubscription) { + cpuPowerSubscription.unsubscribe(); + } + }); + + // Cleanup GraphQL subscription on page unload $(window).on('beforeunload', function() { From e799c9144d925a3a0c139fec038f12f93a7f3185 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Wed, 22 Oct 2025 21:53:07 +0100 Subject: [PATCH 5/7] Layout change and fixes --- emhttp/plugins/dynamix/DashStats.page | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/emhttp/plugins/dynamix/DashStats.page b/emhttp/plugins/dynamix/DashStats.page index c4b08fbde..c2863c20e 100755 --- a/emhttp/plugins/dynamix/DashStats.page +++ b/emhttp/plugins/dynamix/DashStats.page @@ -95,6 +95,7 @@ foreach ($devs as $disk) { $array_percent = number_format(100*$array_used/($array_size ?: 1),1,$dot,''); $cpus=get_cpu_packages(); +$cpus[] = ["16,17"]; $wg_up = $wireguard ? exec("wg show interfaces") : ''; $wg_up = $wg_up ? explode(' ',$wg_up) : []; $up = count($wg_up); @@ -351,11 +352,11 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout - _(Total)_ _(Power)_: N/A + _(Total)_ _(Power)_: N/A - _(Temp)_: + _(Temperature)_: N/A @@ -403,12 +404,12 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout - + $package) { if (count($cpus) > 1) { - echo ""._("Physical")." CPU $cpu_index "._("Power").": N/A "; - if (count($cpus)>1) echo _("Temp").": N/A"; + echo " "._("Physical")." CPU $cpu_index "._("Power").": N/A "; + if (count($cpus)>1) echo " "._("Temperature").": N/A"; echo ""; } foreach ($package as $pair) { @@ -1453,6 +1454,8 @@ var startup = true; var stopgap = ''; var recall = null; var recover = null; +var tempunit=""; + // Helper function to calculate millisPerPixel based on container width function getMillisPerPixel(timeInSeconds, containerId) { @@ -1721,7 +1724,6 @@ function updateCPUPower() { const cpuspower = cpupower.power ?? []; cpuspower.forEach((power, index) => { const coreEl = document.getElementById(`cpu-power${index}`); - const coreTempEl = document.getElementById(`cpu-temp${index}`); if (coreEl) { coreEl.innerHTML = `${power.toFixed(2)} W`; } @@ -1731,7 +1733,11 @@ function updateCPUPower() { cpustemps.forEach((temp, index) => { const coreTempEl = document.getElementById(`cpu-temp${index}`); if (coreTempEl) { - coreTempEl.innerHTML = `${temp.toFixed(0)} C`;; + tempdisplay = temp.toFixed(0); + if (tempunit === "F") { + tempdisplay = ((temp.toFixed(0))* 9 / 5) + 32; + } + coreTempEl.innerHTML = Math.round(tempdisplay)+` °`+tempunit;; } }); @@ -2853,7 +2859,7 @@ $(function() { }); } else { // Retry with capped backoff if GraphQL client not ready - cpuPWRInitAttempts++; + cpuPInitPWRAttempts++; setTimeout(initPwrCpuSubscription, Math.min(cpuPWRRetryMs *= 2, 2000)); } } From 5083f85d8a298ba71f1cf4ca9a5a6aef70f9102c Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Wed, 22 Oct 2025 22:00:41 +0100 Subject: [PATCH 6/7] Remove test code --- emhttp/plugins/dynamix/DashStats.page | 2 -- emhttp/plugins/dynamix/include/cpulist.php | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 emhttp/plugins/dynamix/include/cpulist.php diff --git a/emhttp/plugins/dynamix/DashStats.page b/emhttp/plugins/dynamix/DashStats.page index c2863c20e..1259ff11b 100755 --- a/emhttp/plugins/dynamix/DashStats.page +++ b/emhttp/plugins/dynamix/DashStats.page @@ -95,7 +95,6 @@ foreach ($devs as $disk) { $array_percent = number_format(100*$array_used/($array_size ?: 1),1,$dot,''); $cpus=get_cpu_packages(); -$cpus[] = ["16,17"]; $wg_up = $wireguard ? exec("wg show interfaces") : ''; $wg_up = $wg_up ? explode(' ',$wg_up) : []; $up = count($wg_up); @@ -1456,7 +1455,6 @@ var recall = null; var recover = null; var tempunit=""; - // Helper function to calculate millisPerPixel based on container width function getMillisPerPixel(timeInSeconds, containerId) { var container = document.getElementById(containerId); diff --git a/emhttp/plugins/dynamix/include/cpulist.php b/emhttp/plugins/dynamix/include/cpulist.php new file mode 100644 index 000000000..8d1db3573 --- /dev/null +++ b/emhttp/plugins/dynamix/include/cpulist.php @@ -0,0 +1,22 @@ + (int)explode($separator, $s)[0], $list); + array_multisort($keys, SORT_ASC, SORT_NUMERIC, $list); + } + unset($list); + + return $packages; +} From 117a49491a2595f3f18267461baf18d9357df8b7 Mon Sep 17 00:00:00 2001 From: SimonFair <39065407+SimonFair@users.noreply.github.com> Date: Thu, 23 Oct 2025 12:09:13 +0100 Subject: [PATCH 7/7] Update DashStats.page --- emhttp/plugins/dynamix/DashStats.page | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emhttp/plugins/dynamix/DashStats.page b/emhttp/plugins/dynamix/DashStats.page index 1259ff11b..60fbc8f96 100755 --- a/emhttp/plugins/dynamix/DashStats.page +++ b/emhttp/plugins/dynamix/DashStats.page @@ -2857,7 +2857,7 @@ $(function() { }); } else { // Retry with capped backoff if GraphQL client not ready - cpuPInitPWRAttempts++; + cpuInitPWRAttempts++; setTimeout(initPwrCpuSubscription, Math.min(cpuPWRRetryMs *= 2, 2000)); } }