-
- Real-Time Data
-
-
- {realtimeGPUData.data.map((data, index) => (
-
- {data.name}
- {data.value}
-
- ))}
-
+ {detailsLoading ? (
+
+
+
Loading real-time data...
- )}
+ ) : realtimeGPUData?.has_monitoring_tool === true ? (
+ <>
+
+
+
Updating every 3 seconds
+
- {/* Monitoring Tool Recommendation */}
- {!hasRealtimeData() && (
-
-
- Monitoring Tool Recommendation
-
-
- {getMonitoringToolRecommendation(selectedGPU.vendor)}
-
+
+
+ Real-Time Metrics
+
+
+ {realtimeGPUData.clock_graphics && (
+
+ Graphics Clock
+ {formatClock(realtimeGPUData.clock_graphics)}
+
+ )}
+ {realtimeGPUData.clock_memory && (
+
+ Memory Clock
+ {formatClock(realtimeGPUData.clock_memory)}
+
+ )}
+ {realtimeGPUData.power_draw && realtimeGPUData.power_draw !== "0.00 W" && (
+
+ Power Draw
+ {realtimeGPUData.power_draw}
+
+ )}
+ {realtimeGPUData.temperature !== undefined && realtimeGPUData.temperature !== null && (
+
+ Temperature
+
+ {realtimeGPUData.temperature}°C
+
+
+ )}
+
+
+
+ {/* Engine Utilization (Intel/AMD) */}
+ {(realtimeGPUData.engine_render !== undefined ||
+ realtimeGPUData.engine_blitter !== undefined ||
+ realtimeGPUData.engine_video !== undefined ||
+ realtimeGPUData.engine_video_enhance !== undefined) && (
+
+
+ Engine Utilization (Total)
+
+
+ {realtimeGPUData.engine_render !== undefined && (
+
+
+ Render/3D
+
+ {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 && (
+
+
+ Blitter
+
+ {typeof realtimeGPUData.engine_blitter === "number"
+ ? `${realtimeGPUData.engine_blitter.toFixed(1)}%`
+ : realtimeGPUData.engine_blitter}
+
+
+
+
+ )}
+ {realtimeGPUData.engine_video_enhance !== undefined && (
+
+
+ VideoEnhance
+
+ {typeof realtimeGPUData.engine_video_enhance === "number"
+ ? `${realtimeGPUData.engine_video_enhance.toFixed(1)}%`
+ : realtimeGPUData.engine_video_enhance}
+
+
+
+
+ )}
+
+
+ )}
+
+ {/* CHANGE: Changed process name badge from blue to purple to match Intel/AMD */}
+ {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"
+ ? formatMemory(proc.memory.resident / 1024)
+ : formatMemory(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 || isNaN(utilizationNum)) 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 && (
+
+
+ Memory
+
+
+
+ Total
+ {realtimeGPUData.memory_total}
+
+
+ Used
+ {realtimeGPUData.memory_used}
+
+
+ Free
+ {realtimeGPUData.memory_free}
+
+ {realtimeGPUData.utilization_memory !== undefined && (
+
+
+ Memory Utilization
+ {realtimeGPUData.utilization_memory}%
+
+
+
+ )}
+
+
+ )}
+ >
+ ) : (
+
+
+
+
+
Extended Monitoring Not Available
+
+ {getMonitoringToolRecommendation(selectedGPU.vendor)}
+
+
+
)}
@@ -827,6 +1032,692 @@ export default function Hardware() {
)}
+
+ {/* PCI Devices - Changed to modal */}
+ {hardwareData?.pci_devices && hardwareData.pci_devices.length > 0 && (
+
+
+
+
PCI Devices
+
+ {hardwareData.pci_devices.length} devices
+
+
+
+
+ {hardwareData.pci_devices.map((device, index) => (
+
setSelectedPCIDevice(device)}
+ className="cursor-pointer rounded-lg border border-white/10 sm:border-border bg-white/5 sm:bg-card sm:hover:bg-white/5 p-3 transition-colors"
+ >
+
+ {device.type}
+ {device.slot}
+
+
{device.device}
+
{device.vendor}
+ {device.driver && (
+
Driver: {device.driver}
+ )}
+
+ ))}
+
+
+ )}
+
+ {/* PCI Device Detail Modal */}
+
+
+ {/* Power Consumption */}
+ {hardwareData?.power_meter && (
+
+
+
+
Power Consumption
+
+
+
+
+
+
{hardwareData.power_meter.name}
+ {hardwareData.power_meter.adapter && (
+
{hardwareData.power_meter.adapter}
+ )}
+
+
+
{hardwareData.power_meter.watts.toFixed(1)} W
+
Current Draw
+
+
+
+
+ )}
+
+ {/* Power Supplies */}
+ {hardwareData?.power_supplies && hardwareData.power_supplies.length > 0 && (
+
+
+
+
Power Supplies
+
+ {hardwareData.power_supplies.length} PSUs
+
+
+
+
+ {hardwareData.power_supplies.map((psu, index) => (
+
+
+ {psu.name}
+ {psu.status && (
+ {psu.status}
+ )}
+
+
{psu.watts} W
+
Current Output
+
+ ))}
+
+
+ )}
+
+ {/* Fans */}
+ {hardwareData?.fans && hardwareData.fans.length > 0 && (
+
+
+
+
System Fans
+
+ {hardwareData.fans.length} fans
+
+
+
+
+ {hardwareData.fans.map((fan, index) => {
+ const isPercentage = fan.unit === "percent" || fan.unit === "%"
+ const percentage = isPercentage ? fan.speed : Math.min((fan.speed / 5000) * 100, 100)
+
+ return (
+
+
+ {fan.name}
+
+ {isPercentage ? `${fan.speed.toFixed(0)} percent` : `${fan.speed.toFixed(0)} ${fan.unit}`}
+
+
+
+ {fan.adapter &&
{fan.adapter}}
+
+ )
+ })}
+
+
+ )}
+
+ {/* UPS */}
+ {hardwareData?.ups && Array.isArray(hardwareData.ups) && hardwareData.ups.length > 0 && (
+
+
+
+
UPS Status
+
+ {hardwareData.ups.length} UPS
+
+
+
+
+ {hardwareData.ups.map((ups: any, index: number) => {
+ const batteryCharge =
+ ups.battery_charge_raw || Number.parseFloat(ups.battery_charge?.replace("%", "") || "0")
+ const loadPercent = ups.load_percent_raw || Number.parseFloat(ups.load_percent?.replace("%", "") || "0")
+
+ // Determine status badge color
+ const getStatusColor = (status: string) => {
+ if (!status) return "bg-gray-500/10 text-gray-500 border-gray-500/20"
+ const statusUpper = status.toUpperCase()
+ if (statusUpper.includes("OL")) return "bg-green-500/10 text-green-500 border-green-500/20"
+ if (statusUpper.includes("OB")) return "bg-yellow-500/10 text-yellow-500 border-yellow-500/20"
+ if (statusUpper.includes("LB")) return "bg-red-500/10 text-red-500 border-red-500/20"
+ return "bg-blue-500/10 text-blue-500 border-blue-500/20"
+ }
+
+ return (
+
setSelectedUPS(ups)}
+ className="cursor-pointer rounded-lg border border-white/10 sm:border-border bg-white/5 sm:bg-card sm:hover:bg-white/5 p-4 transition-colors"
+ >
+
+
+ {ups.model || ups.name}
+ {ups.is_remote && Remote: {ups.host}}
+
+
{ups.status || "Unknown"}
+
+
+
+ {ups.battery_charge && (
+
+
+ Battery Charge
+ {ups.battery_charge}
+
+
+
+ )}
+
+ {ups.load_percent && (
+
+
+ Load
+ {ups.load_percent}
+
+
+
+ )}
+
+ {ups.time_left && (
+
+
Runtime
+
+ {ups.time_left}
+
+
+ )}
+
+ {ups.input_voltage && (
+
+
Input Voltage
+
+ {ups.input_voltage}
+
+
+ )}
+
+
+ )
+ })}
+
+
+ )}
+
+
+
+ {/* Network Summary - Clickable */}
+ {hardwareData?.pci_devices &&
+ hardwareData.pci_devices.filter((d) => d.type.toLowerCase().includes("network")).length > 0 && (
+
+
+
+
Network Summary
+
+ {hardwareData.pci_devices.filter((d) => d.type.toLowerCase().includes("network")).length} interfaces
+
+
+
+
+ {hardwareData.pci_devices
+ .filter((d) => d.type.toLowerCase().includes("network"))
+ .map((device, index) => (
+
setSelectedNetwork(device)}
+ className="cursor-pointer rounded-lg border border-white/10 sm:border-border bg-white/5 sm:bg-card sm:hover:bg-white/5 p-3 transition-colors"
+ >
+
+ {device.device}
+
+ Ethernet
+
+
+
{device.vendor}
+ {device.driver && (
+
Driver: {device.driver}
+ )}
+
+ ))}
+
+ Click on an interface for detailed information
+
+ )}
+
+ {/* Network Detail Modal */}
+
+
+ {/* Storage Summary - Clickable */}
+ {hardwareData?.storage_devices && hardwareData.storage_devices.length > 0 && (
+
+
+
+
Storage Summary
+
+ {
+ hardwareData.storage_devices.filter(
+ (device) =>
+ device.type === "disk" && !device.name.startsWith("zd") && !device.name.startsWith("loop"),
+ ).length
+ }{" "}
+ devices
+
+
+
+
+ {hardwareData.storage_devices
+ .filter(
+ (device) => device.type === "disk" && !device.name.startsWith("zd") && !device.name.startsWith("loop"),
+ )
+ .map((device, index) => (
+
setSelectedDisk(device)}
+ className="cursor-pointer rounded-lg border border-white/10 sm:border-border bg-white/5 sm:bg-card sm:hover:bg-white/5 p-3 transition-colors"
+ >
+
+ {device.name}
+
+ {device.type}
+
+
+ {device.size &&
{formatMemory(parseLsblkSize(device.size))}
}
+ {device.model && (
+
{device.model}
+ )}
+ {device.driver && (
+
Driver: {device.driver}
+ )}
+
+ ))}
+
+ Click on a device for detailed hardware information
+
+ )}
+
+ {/* Disk Detail Modal */}
+
)
}