From f24f4ea8f9a427189ee59fe5d2b0aeb4e5b10e41 Mon Sep 17 00:00:00 2001 From: MacRimi Date: Thu, 9 Oct 2025 23:14:47 +0200 Subject: [PATCH] Update hardware.tsx --- AppImage/components/hardware.tsx | 305 +++++++++++++++++-------------- 1 file changed, 172 insertions(+), 133 deletions(-) diff --git a/AppImage/components/hardware.tsx b/AppImage/components/hardware.tsx index 8ef936d..e85ec0f 100644 --- a/AppImage/components/hardware.tsx +++ b/AppImage/components/hardware.tsx @@ -19,7 +19,7 @@ import { Loader2, } from "lucide-react" import useSWR from "swr" -import { useState } from "react" +import { useState, useEffect } from "react" import { type HardwareData, type GPU, type PCIDevice, type StorageDevice, fetcher } from "../types/hardware" const getDeviceTypeColor = (type: string): string => { @@ -66,51 +66,52 @@ export default function Hardware() { const [selectedDisk, setSelectedDisk] = useState(null) const [selectedNetwork, setSelectedNetwork] = useState(null) + useEffect(() => { + if (!selectedGPU) return + + const pciDevice = findPCIDeviceForGPU(selectedGPU) + const fullSlot = pciDevice?.slot || selectedGPU.slot + + if (!fullSlot) return + + const fetchRealtimeData = async () => { + try { + const response = await fetch(`http://localhost:8008/api/gpu/${fullSlot}/realtime`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + signal: AbortSignal.timeout(10000), + }) + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`) + } + + const data = await response.json() + setRealtimeGPUData(data) + setDetailsLoading(false) + } catch (error) { + console.error("[v0] Error fetching GPU realtime data:", error) + setRealtimeGPUData({ has_monitoring_tool: false }) + setDetailsLoading(false) + } + } + + // Initial fetch + fetchRealtimeData() + + // Poll every 3 seconds + const interval = setInterval(fetchRealtimeData, 3000) + + return () => clearInterval(interval) + }, [selectedGPU]) + const handleGPUClick = async (gpu: GPU) => { console.log("[v0] GPU clicked:", gpu.name) - console.log("[v0] GPU slot:", gpu.slot) - - const pciDevice = findPCIDeviceForGPU(gpu) - const fullSlot = pciDevice?.slot || gpu.slot - - console.log("[v0] Full PCI slot:", fullSlot) - setSelectedGPU(gpu) setDetailsLoading(true) setRealtimeGPUData(null) - - console.log("[v0] Modal opened, fetching realtime data...") - - if (!fullSlot) { - console.log("[v0] No slot found, showing basic info only") - setDetailsLoading(false) - return - } - - try { - const response = await fetch(`http://localhost:8008/api/gpu/${fullSlot}/realtime`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - signal: AbortSignal.timeout(10000), - }) - - if (!response.ok) { - console.log("[v0] API response not OK:", response.status) - throw new Error(`HTTP error! status: ${response.status}`) - } - - const data = await response.json() - console.log("[v0] Realtime GPU data received:", data) - setRealtimeGPUData(data) - } catch (error) { - console.error("[v0] Error fetching GPU realtime data:", error) - setRealtimeGPUData({ has_monitoring_tool: false }) - } finally { - setDetailsLoading(false) - console.log("[v0] Finished loading GPU data") - } } const findPCIDeviceForGPU = (gpu: GPU): PCIDevice | null => { @@ -398,13 +399,13 @@ export default function Hardware() { setRealtimeGPUData(null) }} > - + {selectedGPU && ( <> {selectedGPU.name} - {detailsLoading ? "Loading real-time monitoring data..." : "GPU Information"} + {detailsLoading ? "Loading real-time monitoring data..." : "GPU Real-Time Monitoring"} @@ -454,57 +455,16 @@ export default function Hardware() { ) : realtimeGPUData?.has_monitoring_tool === true ? ( <> +
+
+ Updating every 3 seconds +
+

Real-Time Metrics

-
- {realtimeGPUData.temperature !== undefined && realtimeGPUData.temperature !== null ? ( -
-
- Temperature - - {realtimeGPUData.temperature}°C - -
- -
- ) : ( -
- Temperature - N/A -
- )} - - {realtimeGPUData.utilization_gpu !== undefined && realtimeGPUData.utilization_gpu !== null ? ( -
-
- GPU Utilization - - {typeof realtimeGPUData.utilization_gpu === "string" - ? realtimeGPUData.utilization_gpu - : `${realtimeGPUData.utilization_gpu}%`} - -
- -
- ) : ( -
-
- GPU Utilization - 0.0% -
- -
- )} - +
{realtimeGPUData.clock_graphics && (
Graphics Clock @@ -517,16 +477,18 @@ export default function Hardware() { {realtimeGPUData.clock_memory}
)} - {realtimeGPUData.power_draw && realtimeGPUData.power_draw !== "N/A" && ( + {realtimeGPUData.power_draw && realtimeGPUData.power_draw !== "0.00 W" && (
Power Draw - {realtimeGPUData.power_draw} + {realtimeGPUData.power_draw}
)} - {realtimeGPUData.power_limit && ( + {realtimeGPUData.temperature !== undefined && realtimeGPUData.temperature !== null && (
- Power Limit - {realtimeGPUData.power_limit} + Temperature + + {realtimeGPUData.temperature}°C +
)}
@@ -539,16 +501,47 @@ export default function Hardware() { realtimeGPUData.engine_video_enhance !== undefined) && (

- Engine Utilization + Engine Utilization (Total)

-
+
{realtimeGPUData.engine_render !== undefined && (
Render/3D - {realtimeGPUData.engine_render.toFixed(2)}% + + {typeof realtimeGPUData.engine_render === "number" + ? `${realtimeGPUData.engine_render.toFixed(1)}%` + : realtimeGPUData.engine_render} +
- + +
+ )} + {realtimeGPUData.engine_video !== undefined && ( +
+
+ Video + + {typeof realtimeGPUData.engine_video === "number" + ? `${realtimeGPUData.engine_video.toFixed(1)}%` + : realtimeGPUData.engine_video} + +
+
)} {realtimeGPUData.engine_blitter !== undefined && ( @@ -556,19 +549,19 @@ export default function Hardware() {
Blitter - {realtimeGPUData.engine_blitter.toFixed(2)}% + {typeof realtimeGPUData.engine_blitter === "number" + ? `${realtimeGPUData.engine_blitter.toFixed(1)}%` + : realtimeGPUData.engine_blitter}
- -
- )} - {realtimeGPUData.engine_video !== undefined && ( -
-
- Video - {realtimeGPUData.engine_video.toFixed(2)}% -
- +
)} {realtimeGPUData.engine_video_enhance !== undefined && ( @@ -576,17 +569,83 @@ export default function Hardware() {
VideoEnhance - {realtimeGPUData.engine_video_enhance.toFixed(2)}% + {typeof realtimeGPUData.engine_video_enhance === "number" + ? `${realtimeGPUData.engine_video_enhance.toFixed(1)}%` + : realtimeGPUData.engine_video_enhance}
- +
)}
)} - {/* Memory Info */} + {realtimeGPUData.processes && realtimeGPUData.processes.length > 0 && ( +
+

+ Active Processes ({realtimeGPUData.processes.length}) +

+
+ {realtimeGPUData.processes.map((proc: any, idx: number) => ( +
+
+
+

{proc.name}

+

PID: {proc.pid}

+
+ {proc.memory && ( + + {typeof proc.memory === "object" + ? `${(proc.memory.resident / 1024).toFixed(0)} MB` + : proc.memory} + + )} +
+ + {proc.engines && Object.keys(proc.engines).length > 0 && ( +
+

Engine Utilization:

+ {Object.entries(proc.engines).map(([engineName, engineData]: [string, any]) => { + const utilization = + typeof engineData === "object" ? engineData.busy || 0 : engineData + const utilizationNum = + typeof utilization === "string" ? Number.parseFloat(utilization) : utilization + + if (utilizationNum === 0) return null + + return ( +
+
+ {engineName} + {utilizationNum.toFixed(1)}% +
+ +
+ ) + })} +
+ )} +
+ ))} +
+
+ )} + + {realtimeGPUData.processes && realtimeGPUData.processes.length === 0 && ( +
+

No active processes using the GPU

+
+ )} + + {/* Memory Info (NVIDIA) */} {realtimeGPUData.memory_total && (

@@ -617,26 +676,6 @@ export default function Hardware() {

)} - - {/* Running Processes (NVIDIA) */} - {realtimeGPUData.processes && realtimeGPUData.processes.length > 0 && ( -
-

- Running Processes -

-
- {realtimeGPUData.processes.map((proc: any, idx: number) => ( -
-
- PID: {proc.pid} - {proc.memory} -
-

{proc.name}

-
- ))} -
-
- )} ) : (