feat: native WireView Pro II monitoring (detection, serial protocol, live tab)
Standalone support for the ThermalGrizzly WireView Pro II without depending on the external wireview_reporter exporter: - wireview.py: serial protocol (STX/ETX + 16-bit CRC16-CCITT) with vendor-data product identification, config version, UID, build string, screen layout, and temperature/power/current sensor reads; hwmon fallback with per-channel index resolution; udev-based detection (vendor 0x2560 / product 0x0101) with fallback port probing; serial read timeout and watchdog reconnect - server.py: startup detection (root only), 1 Hz poller gated on subscribed clients, WS 'wireview' channel, GET /api/wireview, rejected-product memoization, stale-read race guard - frontend: WireView tab (visible when a device is detected) with live temperature/power/current cards, sparkline history, and device info; nullable temp channels - tests: 76 tests covering parser, CRC, fault classification, hwmon resolution, JSON safety, and the serial transport against a pty-based fake device Verified live: tab appears with the device connected, disappears when unplugged, reconnects on re-plug, no serial traffic when idle.
This commit is contained in:
1 parent
cc102f26c1
commit
526b71b45f
10 files changed
+1792
-1
No files matched your search
+19
-1
@@ -11,10 +11,12 @@ import { PerformancePanel } from "./components/Limits/PerformancePanel.js";
|
||||
import { PerformanceMonitor } from "./components/Monitor/PerformanceMonitor.js";
|
||||
import { FanMonitor } from "./components/Monitor/FanMonitor.js";
|
||||
import { FanCurveEditor } from "./components/Fans/FanCurveEditor.js";
|
||||
import { WireViewPanel } from "./components/WireView/WireViewPanel.js";
|
||||
import { ProfilePanel } from "./components/Profiles/ProfilePanel.js";
|
||||
import { api, onUnauthorized } from "./api/client.js";
|
||||
import { LoginScreen } from "./components/Auth/LoginScreen.js";
|
||||
import { useCurveStore } from "./store/curveStore.js";
|
||||
import { useWireview } from "./hooks/useWireview.js";
|
||||
import { Toaster } from "sonner";
|
||||
import { Loader, ChevronDown } from "lucide-react";
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
@@ -94,9 +96,10 @@ function MainApp({
|
||||
const { dashboard, loading: dashboardLoading } = useDashboard();
|
||||
const { setCurve, activeProfile, setActiveProfile, selectedGpuIndex } =
|
||||
useCurveStore();
|
||||
const wireview = useWireview();
|
||||
|
||||
const [activeTab, setActiveTab] = useState<
|
||||
"dashboard" | "curve" | "performance" | "fans"
|
||||
"dashboard" | "curve" | "performance" | "fans" | "wireview"
|
||||
>("dashboard");
|
||||
const [fanState, setFanState] = useState<FanState | null>(null);
|
||||
const [activeDomain, setActiveDomain] = useState<"gpu" | "memory">("gpu");
|
||||
@@ -195,6 +198,15 @@ function MainApp({
|
||||
>
|
||||
Fans
|
||||
</button>
|
||||
{wireview.available && (
|
||||
<button
|
||||
onClick={() => setActiveTab("wireview")}
|
||||
className={`text-lg font-medium pb-2 -mb-[9px] border-b-2 transition-colors flex items-center gap-2 ${activeTab === "wireview" ? "border-pink-500 text-zinc-100" : "border-transparent text-zinc-500 hover:text-zinc-300"}`}
|
||||
>
|
||||
WireView
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="relative" ref={profileRef}>
|
||||
<button
|
||||
@@ -289,6 +301,12 @@ function MainApp({
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : activeTab === "wireview" ? (
|
||||
<WireViewPanel
|
||||
info={wireview.info}
|
||||
sample={wireview.sample}
|
||||
history={wireview.history}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex gap-4 items-start w-full">
|
||||
<div className="flex-1 min-w-0">
|
||||
|
||||
Reference in new issue
Block a user