From 526b71b45fa1ab7eda4d237eb052969df92c2c9b Mon Sep 17 00:00:00 2001 From: ARIA Date: Sat, 3 Oct 2026 13:20:56 +0200 Subject: [PATCH 1/4] 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. --- Makefile | 1 + frontend/src/App.tsx | 20 +- .../src/components/WireView/WireViewPanel.tsx | 309 ++++++++ frontend/src/hooks/useWireview.ts | 40 ++ frontend/src/types.ts | 47 ++ nvcurve/server.py | 212 ++++++ nvcurve/wireview.py | 659 ++++++++++++++++++ pyproject.toml | 1 + tests/test_wireview.py | 493 +++++++++++++ uv.lock | 11 + 10 files changed, 1792 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/WireView/WireViewPanel.tsx create mode 100644 frontend/src/hooks/useWireview.ts create mode 100644 nvcurve/wireview.py create mode 100644 tests/test_wireview.py diff --git a/Makefile b/Makefile index eca3bef..b66c615 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ dev: ## Create/refresh the dev environment (uv sync) test: ## Run the test suite $(UV) run python tests/test_security.py $(UV) run python tests/test_rm_power.py + $(UV) run python tests/test_wireview.py clean: ## Remove build artifacts rm -rf frontend/dist frontend/node_modules \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index d763434..bed0e49 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -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(null); const [activeDomain, setActiveDomain] = useState<"gpu" | "memory">("gpu"); @@ -195,6 +198,15 @@ function MainApp({ > Fans + {wireview.available && ( + + )}
+ ) : activeTab === "wireview" ? ( + ) : (
diff --git a/frontend/src/components/WireView/WireViewPanel.tsx b/frontend/src/components/WireView/WireViewPanel.tsx new file mode 100644 index 0000000..b5f76bd --- /dev/null +++ b/frontend/src/components/WireView/WireViewPanel.tsx @@ -0,0 +1,309 @@ +import { GaugeCard } from "../Monitor/GaugeCard.js"; +import { fmt } from "../../utils/units.js"; +import type { WireViewInfo, WireViewSample } from "../../types.js"; + +interface Props { + info: WireViewInfo | null; + sample: WireViewSample | null; + history: WireViewSample[]; +} + +// Per-pin over-current protection of the 12 VHPWR connector (A). +const PIN_OCP_A = 55; + +const FAULT_NAMES: Record = { + 0: "Chip over-temperature", + 1: "Sensor over-temperature", + 2: "Over-current (OCP)", + 3: "Wire over-current", + 4: "Over-power (OPP)", + 5: "Current imbalance", +}; + +function decodeFaults(mask: number): string[] { + return Object.entries(FAULT_NAMES) + .filter(([bit]) => mask & (1 << Number(bit))) + .map(([, name]) => name); +} + +function pluck(history: WireViewSample[], key: keyof WireViewSample): number[] { + return history.map((s) => (s[key] as number | null) ?? 0); +} + +function FaultBadge({ + label, + mask, +}: { + label: string; + mask: number; +}) { + const faults = decodeFaults(mask); + return ( +
0 + ? "bg-red-500/10 border-red-500/40" + : "bg-zinc-900 border-zinc-800" + }`} + > +
+ + {label} + + 0 ? "text-red-400" : "text-zinc-600" + }`} + > + 0x{mask.toString(16).toUpperCase().padStart(4, "0")} + +
+ {faults.length > 0 ? ( +
+ {faults.map((f) => ( + + {f} + + ))} +
+ ) : ( +
No faults
+ )} +
+ ); +} + +function PinCard({ + index, + voltage, + current, + power, +}: { + index: number; + voltage: number; + current: number; + power: number; +}) { + const loadPct = Math.min(100, (current / PIN_OCP_A) * 100); + const barColor = + loadPct >= 90 ? "#f87171" : loadPct >= 75 ? "#fbbf24" : "#34d399"; + return ( +
+
+ + Pin {index + 1} + + + {current.toFixed(1)} / {PIN_OCP_A} A + +
+
+
+
V
+
+ {voltage.toFixed(2)} +
+
+
+
A
+
+ {current.toFixed(2)} +
+
+
+
W
+
+ {power.toFixed(1)} +
+
+
+
+
+
+
+ ); +} + +function InfoItem({ + label, + value, +}: { + label: string; + value: string | null | undefined; +}) { + if (!value) return null; + return ( +
+ {label} + + {value} + +
+ ); +} + +export function WireViewPanel({ info, sample, history }: Props) { + if (!sample) { + return ( +
+
+ WireView Pro II not connected +
+
+ Plug in the device — the tab appears automatically once it is + detected. +
+
+ ); + } + + const psuCap = sample.psu_capability_w > 0 ? sample.psu_capability_w : 600; + + return ( +
+ {/* ── Header ─────────────────────────────────────────────────── */} +
+
+ + + {info?.device_name ?? "WireView Pro II"} + +
+ + {info?.hw_rev ? `HW ${info.hw_rev}` : ""} + {info?.firmware_version ? ` · FW ${info.firmware_version}` : ""} + + + PSU {psuCap} W + + + {info?.transport === "hwmon" + ? `hwmon: ${info.port}` + : `serial: ${info?.port ?? ""}`} + +
+ + {/* ── Main gauges ────────────────────────────────────────────── */} +
+
+ 12 VHPWR Connector +
+
+ + + + +
+
+ + {/* ── Per-pin ────────────────────────────────────────────────── */} +
+
+ Per-Pin Readings +
+
+ {sample.pins.map((pin, i) => ( + + ))} +
+
+ + {/* ── Temperatures ───────────────────────────────────────────── */} +
+
+ Temperatures +
+
+ + + + +
+
+ + {/* ── Faults + device info ───────────────────────────────────── */} +
+
+ + +
+
+
+ Device +
+
+ + + + + + +
+
+
+
+ ); +} diff --git a/frontend/src/hooks/useWireview.ts b/frontend/src/hooks/useWireview.ts new file mode 100644 index 0000000..9221ac9 --- /dev/null +++ b/frontend/src/hooks/useWireview.ts @@ -0,0 +1,40 @@ +import { useEffect, useRef, useState } from "react"; +import { createWsConnection } from "../api/websocket.js"; +import type { + WireViewInfo, + WireViewSample, + WireViewWsMessage, +} from "../types.js"; + +const MAX_HISTORY = 120; // ~2 min at 1 s polling + +export function useWireview() { + const [available, setAvailable] = useState(false); + const [info, setInfo] = useState(null); + const [sample, setSample] = useState(null); + const [history, setHistory] = useState([]); + const wsRef = useRef | null>(null); + + useEffect(() => { + wsRef.current = createWsConnection( + "/ws/wireview", + (msg) => { + if (msg.type === "sample") { + setAvailable(true); + setInfo(msg.info); + setSample(msg.sample); + setHistory((h) => [...h.slice(-(MAX_HISTORY - 1)), msg.sample]); + } else { + setAvailable(false); + setInfo(null); + setSample(null); + setHistory([]); + } + }, + () => {}, + ); + return () => wsRef.current?.close(); + }, []); + + return { available, info, sample, history }; +} diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 2e8b8bd..ae7226a 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -145,3 +145,50 @@ export interface ProfileData { fan_curve: FanPoint[] | null; fan_targets: number[] | null; } + +// ── WireView Pro II (Thermal Grizzly 12 VHPWR connector monitor) ── + +export interface WireViewPin { + voltage_v: number; + current_a: number; + power_w: number; +} + +export interface WireViewSample { + timestamp: number; + power_total_w: number; + current_total_a: number; + voltage_avg_v: number; + pins: WireViewPin[]; + // Temperatures are null when the source has no channel for them + // (e.g. an hwmon module without external-sensor channels). + temp_in_c: number | null; + temp_out_c: number | null; + temp_ext1_c: number | null; + temp_ext2_c: number | null; + fan_duty_pct: number; + fault_status: number; + fault_log: number; + psu_capability_w: number; +} + +export interface WireViewInfo { + device_name: string; + hw_rev: string; + firmware_version: string; + uid: string; + build: string; + transport: "serial" | "hwmon"; + port: string; +} + +export interface WireViewState { + available: boolean; + connected: boolean; + info: WireViewInfo | null; + sample: WireViewSample | null; +} + +export type WireViewWsMessage = + | { type: "unavailable" } + | { type: "sample"; info: WireViewInfo; sample: WireViewSample }; diff --git a/nvcurve/server.py b/nvcurve/server.py index 25c6028..d433abe 100644 --- a/nvcurve/server.py +++ b/nvcurve/server.py @@ -72,6 +72,7 @@ from .profiles.native import ( rename_profile, save_profile, ) +from .wireview import create_device, find_wireview_ports from .safety import check_negative_freq_warnings, validate_write log = logging.getLogger("nvcurve.server") @@ -103,6 +104,15 @@ def _open_browser_as_user(url: str) -> None: _state: dict[str, Any] = { "gpus": {}, # dict[int, dict] mapping gpu_index -> gpu state "config": default_config, + "wireview": { + "clients": set(), # connected /ws/wireview clients + "device": None, # WireViewSerialDevice | WireViewHwmonDevice | None + "info": None, # device identity (static per connection) + "last_sample": None, # most recent sensor sample + "connected": False, # last read succeeded + "failures": 0, # consecutive failed reads + "rejected_ports": set(), # ports reporting an unsupported product + }, } @@ -258,6 +268,126 @@ async def _fan_poller(gpu_index: int) -> None: await asyncio.sleep(2.0) +# ── WireView Pro II (Thermal Grizzly) ───────────────────────────────────────── +# Consecutive failed reads after which a connected device is given up. Same +# rule as the exporter: one corrupt frame or a slow read never trips it, and +# an unplug is caught at once by the port-node check. +WIREVIEW_MAX_FAILED_READS = 6 +WIREVIEW_WATCHDOG_INTERVAL_S = 5.0 + + +async def _wireview_disconnect() -> None: + """Drop the connected WireView device and tell clients it is gone.""" + wv = _state["wireview"] + device = wv["device"] + if device is None: + return + wv["device"] = None + wv["connected"] = False + wv["info"] = None + wv["last_sample"] = None + wv["failures"] = 0 + await _run(device.close) + log.info("WireView disconnected") + await _broadcast(wv["clients"], {"type": "unavailable"}) + + +async def _wireview_connect() -> None: + """Detect and connect a WireView Pro II. No-op when none is attached or + one is already connected.""" + wv = _state["wireview"] + if wv["device"] is not None: + return + # Forget rejected ports that disappeared, so a re-plug gets a fresh probe. + if wv["rejected_ports"]: + present = set(await _run(find_wireview_ports)) + wv["rejected_ports"] &= present + device = await _run(create_device) + if device is None: + return + # A port that reported an unsupported product is not re-probed (and + # re-logged) on every watchdog tick. + if device.port in wv["rejected_ports"]: + return + ok = await _run(device.connect) + if not ok: + await _run(device.close) + if device.rejected: + wv["rejected_ports"].add(device.port) + return + wv["device"] = device + wv["failures"] = 0 + wv["connected"] = True + wv["info"] = await _run(device.info) + # Push the first sample right away so clients don't wait for the next tick. + sample = await _run(device.read_sample) + if sample is not None: + wv["last_sample"] = sample + await _broadcast( + wv["clients"], {"type": "sample", "info": wv["info"], "sample": sample} + ) + else: + wv["connected"] = False + + +async def _wireview_poller() -> None: + """Read the WireView at poll_interval_s and push to connected WS clients. + + Skips reads while no client is subscribed (like the monitor poller), so + idle polling never contends for the port with other tools (official GUI, + wireviewd).""" + cfg: Config = _state["config"] + while True: + try: + wv = _state["wireview"] + device = wv["device"] + if device is not None and wv["clients"]: + sample = await _run(device.read_sample) + if wv["device"] is not device: + # The device was disconnected (unplug) while the read was + # in flight — drop the stale result instead of + # resurrecting state. + pass + elif sample is not None: + wv["failures"] = 0 + wv["connected"] = True + wv["last_sample"] = sample + await _broadcast( + wv["clients"], + {"type": "sample", "info": wv["info"], "sample": sample}, + ) + else: + wv["failures"] += 1 + if ( + not await _run(device.node_exists) + or wv["failures"] >= WIREVIEW_MAX_FAILED_READS + ): + await _wireview_disconnect() + except asyncio.CancelledError: + return + except Exception as exc: + log.warning("WireView poller error: %s", exc) + await asyncio.sleep(cfg.poll_interval_s) + + +async def _wireview_watchdog() -> None: + """Hot-plug detection: connect when a WireView appears, disconnect when + its device node disappears.""" + while True: + await asyncio.sleep(WIREVIEW_WATCHDOG_INTERVAL_S) + try: + wv = _state["wireview"] + device = wv["device"] + if device is None: + await _wireview_connect() + elif not await _run(device.node_exists): + await _wireview_disconnect() + except asyncio.CancelledError: + return + except Exception as exc: + log.warning("WireView watchdog error: %s", exc) + + async def _activate_fan_curve( gpu_index: int, curve: list, fans: list[int] | None = None ) -> None: @@ -380,6 +510,16 @@ async def lifespan(app: FastAPI): except Exception as exc: log.error("Failed to initialize GPU %d: %s", idx, exc) + # ── WireView Pro II detection ───────────────────────────────────────────── + # Independent of GPU discovery: the tab appears whenever the connector + # monitor is attached, and the watchdog handles hot-plug afterwards. + try: + await _wireview_connect() + except Exception as exc: + log.warning("WireView initial detection failed: %s", exc) + poller_tasks.append(asyncio.create_task(_wireview_poller())) + poller_tasks.append(asyncio.create_task(_wireview_watchdog())) + # ── Backward Compatibility Bridge ────────────────────────────────────────── # NOTE: This auto-load path is for users running the server directly (e.g. # via an old systemd unit file that lacks the new daemon mode). @@ -465,6 +605,14 @@ async def lifespan(app: FastAPI): with suppress(asyncio.CancelledError): await task + # Release the WireView port (if connected) so other tools can use it. + wv = _state["wireview"] + if wv["device"] is not None: + with suppress(Exception): + await _run(wv["device"].close) + wv["device"] = None + wv["connected"] = False + for gpu_index, g_state in _state["gpus"].items(): if g_state.get("fan_poller_task"): g_state["fan_poller_task"].cancel() @@ -1442,6 +1590,25 @@ async def api_fans_speed(req: FanSpeedRequest, gpu_index: int = 0): return {"ok": True} +# ── WireView Pro II (Thermal Grizzly) ───────────────────────────────────────── + + +@app.get("/api/wireview") +async def api_wireview(): + """WireView Pro II availability and the most recent sensor sample. + + available: a device is connected (the UI shows the WireView tab). + sample: None until the first successful read. + """ + wv = _state["wireview"] + return { + "available": wv["device"] is not None, + "connected": wv["connected"], + "info": wv["info"], + "sample": wv["last_sample"], + } + + # ── Write endpoints ──────────────────────────────────────────────────────────── @@ -1832,6 +1999,51 @@ async def ws_curve(ws: WebSocket): g_state["curve_clients"].discard(ws) +@app.websocket("/ws/wireview") +async def ws_wireview(ws: WebSocket): + """Stream WireView Pro II sensor samples at poll_interval_s. + + Messages: + {"type": "unavailable"} — no device connected + {"type": "sample", "info": {...}, "sample": {...}} — new reading + """ + if not _ws_authenticated(ws): + await ws.close(code=1008) + return + await ws.accept() + try: + data = await ws.receive_json() + if data.get("action") != "subscribe": + await ws.close() + return + except WebSocketDisconnect: + return + except Exception: + await ws.close() + return + + wv = _state["wireview"] + wv["clients"].add(ws) + try: + # Send the current state immediately so the client does not have to + # wait for the next poll tick. + if wv["device"] is not None and wv["last_sample"] is not None: + await ws.send_json( + {"type": "sample", "info": wv["info"], "sample": wv["last_sample"]} + ) + else: + await ws.send_json({"type": "unavailable"}) + + while True: + await ws.receive_text() + except WebSocketDisconnect: + pass + except Exception: + log.debug("wireview ws client error", exc_info=True) + finally: + wv["clients"].discard(ws) + + # ── Frontend SPA ────────────────────────────────────────────────────────────── diff --git a/nvcurve/wireview.py b/nvcurve/wireview.py new file mode 100644 index 0000000..b93cd61 --- /dev/null +++ b/nvcurve/wireview.py @@ -0,0 +1,659 @@ +"""Native reader for the Thermal Grizzly WireView Pro II. + +Talks to the 12 VHPWR connector monitor directly over its USB CDC/ACM +serial port (STM32, VID 0483 / PID 5740) — no exporter, no GUI, no kernel +module required. When the wireview-hwmon kernel module is loaded, the +sysfs node is used instead (the wireviewd daemon owns the port in that +case, so direct serial would corrupt frames). + +Protocol notes (matches the firmware's DEVICE_STR_LEN=32 layout): + * No framing/CRC — a desynced read corrupts arbitrary fields for one + poll. Real frames always carry zero padding bytes and a fan duty + <= 100; anything else is discarded and the next poll realigns. + * The firmware occasionally stops answering the RTS welcome handshake + (observed after USB state changes) while still answering every data + command, so identification falls back to the vendor-data reply. +""" + +import logging +import os +import struct +import time + +import serial + +log = logging.getLogger("nvcurve.wireview") + +# ── Device identification ───────────────────────────────────────────────────── + +USB_VENDOR_ID = "0483" # STMicroelectronics (CDC/ACM) +USB_PRODUCT_ID = "5740" # WireView Pro II normal mode +WELCOME_MESSAGE = "Thermal Grizzly WireView Pro II" +MAX_WELCOME_LENGTH = 64 + +# Vendor/product ids reported by CMD_READ_VENDOR_DATA (not the USB ids). +VENDOR_ID_THERMAL_GRIZZLY = 0xEF +PRODUCT_ID_PRO2 = 0x05 +PRODUCT_ID_PRO2_NOCTUA = 0x06 + +DEVICE_NAMES = { + PRODUCT_ID_PRO2: "WireView Pro II", + PRODUCT_ID_PRO2_NOCTUA: "WireView Pro II Noctua Edition", +} + +BAUD_RATE = 115200 +READ_TIMEOUT_S = 1.0 + +# ── Serial protocol commands ────────────────────────────────────────────────── + +CMD_READ_VENDOR_DATA = 0x01 +CMD_READ_UID = 0x02 +CMD_READ_SENSOR_VALUES = 0x04 +CMD_READ_CONFIG = 0x05 +CMD_SCREEN_CHANGE = 0x0C +CMD_READ_BUILD_INFO = 0x0D + +SCREEN_RESUME_UPDATES = 0xF1 + +# ── Wire layout ─────────────────────────────────────────────────────────────── +# SensorStruct (100 bytes, little-endian, pack=4): +# 4x int16 temperatures (0.1 °C): in, out, ext1, ext2 +# uint16 Vdd (mV) +# uint8 fan duty (%) +# pad +# 6x { int16 voltage (mV), pad, uint32 current (mA), uint32 power (mW) } +# uint32 total power (mW) +# uint32 total current (mA) +# uint16 avg voltage (mV) +# uint8 PSU capability (0=600W, 1=450W, 2=300W, 3=150W) +# pad +# uint16 fault status mask +# uint16 fault log mask +SENSOR_STRUCT = struct.Struct( + "<4hHBx" + "".join("hxxII" for _ in range(6)) + "IIHBxHH" +) +SENSOR_STRUCT_SIZE = SENSOR_STRUCT.size # 100 + +# BuildStruct: VendorData(3) + ProductName(32) + BuildInfo(32) + NameLength(1) +BUILD_STRUCT_SIZE = 3 + 32 + 32 + 1 +BUILD_INFO_OFFSET = 3 + 32 # 35 + +PSU_CAPABILITY_W = {0: 600, 1: 450, 2: 300, 3: 150} + +# Fault bitmask (both the active status and the latched log use these bits). +FAULT_BITS = { + 0: "Chip over-temperature", + 1: "Sensor over-temperature", + 2: "Over-current (OCP)", + 3: "Wire over-current", + 4: "Over-power (OPP)", + 5: "Current imbalance", +} + + +def decode_faults(mask: int) -> list[str]: + """Human-readable names of the active fault bits in a status/log mask.""" + return [ + FAULT_BITS[bit] + for bit in sorted(FAULT_BITS) + if mask & (1 << bit) + ] + + +def is_supported_product(vendor_id: int, product_id: int) -> bool: + """True for the products the Pro II protocol serves (5 and 6).""" + return ( + vendor_id == VENDOR_ID_THERMAL_GRIZZLY + and product_id in (PRODUCT_ID_PRO2, PRODUCT_ID_PRO2_NOCTUA) + ) + + +def parse_sensor_struct(buf: bytes) -> dict: + """Decode a 100-byte sensor frame into a JSON-serializable sample. + + Totals are computed from the per-pin readings (voltage * current), + matching the exporter's output; the device's own total fields are + not used. + """ + fields = SENSOR_STRUCT.unpack(buf) + ts_in, ts_out, ts_ext1, ts_ext2, _vdd, fan_duty = fields[:6] + pin_fields = fields[6:24] + ( + _total_power, + _total_current, + _avg_voltage, + psu_cap, + fault_status, + fault_log, + ) = fields[24:] + + pins = [] + power_total = 0.0 + current_total = 0.0 + for i in range(6): + voltage_v = pin_fields[i * 3] / 1000.0 + current_a = pin_fields[i * 3 + 1] / 1000.0 + power_w = pin_fields[i * 3 + 2] / 1000.0 + pins.append( + { + "voltage_v": round(voltage_v, 3), + "current_a": round(current_a, 3), + "power_w": round(power_w, 3), + } + ) + power_total += voltage_v * current_a + current_total += current_a + + return { + "timestamp": time.time(), + "power_total_w": round(power_total, 3), + "current_total_a": round(current_total, 3), + "voltage_avg_v": ( + round(power_total / current_total, 3) if current_total > 0 else 0.0 + ), + "pins": pins, + "temp_in_c": ts_in / 10.0, + "temp_out_c": ts_out / 10.0, + "temp_ext1_c": ts_ext1 / 10.0, + "temp_ext2_c": ts_ext2 / 10.0, + "fan_duty_pct": fan_duty, + "fault_status": fault_status, + "fault_log": fault_log, + "psu_capability_w": PSU_CAPABILITY_W.get(psu_cap, 0), + } + + +def sensor_frame_is_corrupt(buf: bytes) -> bool: + """Corruption check for a sensor frame: real frames always carry zero + padding bytes and a fan duty <= 100. Wire layout: fan duty at offset + 10, pad1 at 11, pad2 five bytes from the end (before the two 16-bit + fault masks).""" + if len(buf) < SENSOR_STRUCT_SIZE: + return True + return buf[10] > 100 or buf[11] != 0 or buf[SENSOR_STRUCT_SIZE - 5] != 0 + + +# ── Device discovery ────────────────────────────────────────────────────────── + + +def _sysfs_matches_wireview(tty_sysfs_dir: str) -> bool: + """Walk up from a resolved tty sysfs path to the USB device and check + its idVendor/idProduct.""" + path = tty_sysfs_dir + while path and path != "/": + vid_file = os.path.join(path, "idVendor") + pid_file = os.path.join(path, "idProduct") + if os.path.isfile(vid_file) and os.path.isfile(pid_file): + try: + with open(vid_file) as f: + vid = f.read().strip().lower() + with open(pid_file) as f: + pid = f.read().strip().lower() + except OSError: + return False + return vid == USB_VENDOR_ID and pid == USB_PRODUCT_ID + path = os.path.dirname(path) + return False + + +def find_wireview_ports() -> list[str]: + """Find /dev nodes of connected WireView Pro II devices. + + Checks the stable /dev/wireview-pro2 symlink (created by the + 99-wireview.rules udev rule) and falls back to a sysfs scan of all + ttyACM* ports matched by USB VID/PID. + """ + ports: set[str] = set() + + link = "/dev/wireview-pro2" + if os.path.islink(link) or os.path.exists(link): + try: + target = os.path.realpath(link) + if os.path.exists(target): + ports.add(target) + except OSError: + pass + + sys_class = "/sys/class/tty" + if os.path.isdir(sys_class): + try: + entries = os.listdir(sys_class) + except OSError: + entries = [] + for entry in entries: + if not entry.startswith("ttyACM"): + continue + tty_dir = os.path.join(sys_class, entry) + try: + resolved = os.path.realpath(tty_dir) + except OSError: + continue + if _sysfs_matches_wireview(resolved): + ports.add(f"/dev/{entry}") + + return sorted(ports) + + +def find_hwmon_path() -> str | None: + """Find the wireview-hwmon sysfs node, if the kernel module is loaded.""" + base = "/sys/class/hwmon" + if not os.path.isdir(base): + return None + try: + entries = os.listdir(base) + except OSError: + return None + for entry in entries: + name_path = os.path.join(base, entry, "name") + try: + with open(name_path) as f: + if f.read().strip().lower() == "wireview": + return os.path.join(base, entry) + except OSError: + continue + return None + + +# ── Serial transport ────────────────────────────────────────────────────────── + + +class WireViewSerialDevice: + """Direct serial access to a WireView Pro II. + + The port is opened and closed per transaction (open → flush → write → + read → close), matching the proven behavior of the exporter: it keeps + the port unheld between polls so other tools (official GUI, wireviewd) + can share the device, and a fresh open realigns a desynced stream. + """ + + def __init__(self, port: str, baud: int = BAUD_RATE) -> None: + self._port = port + self._baud = baud + self._connected = False + self._rejected = False + self._vendor_id = 0 + self._product_id = 0 + self._firmware_version = "" + self._uid = "" + self._build = "" + self._config_version = -1 + + # ── Identity ── + + @property + def connected(self) -> bool: + return self._connected + + @property + def rejected(self) -> bool: + """True when the device reported an unsupported product id. Callers + can memoize this so the port is not re-probed (and re-logged) on + every watchdog tick.""" + return self._rejected + + @property + def transport(self) -> str: + return "serial" + + @property + def port(self) -> str: + return self._port + + def info(self) -> dict: + return { + "device_name": DEVICE_NAMES.get( + self._product_id, "WireView Pro II" + ), + "hw_rev": f"{self._vendor_id:02X}{self._product_id:02X}", + "firmware_version": self._firmware_version, + "uid": self._uid, + "build": self._build, + "transport": self.transport, + "port": self._port, + } + + def node_exists(self) -> bool: + """Whether the serial device node still exists (unplug check).""" + return os.path.exists(self._port) + + # ── Connection ── + + def connect(self) -> bool: + """Identify the device and prepare it for sensor reads. + + The welcome handshake (RTS edge) is the primary identification, + but the firmware occasionally stops answering it while still + answering every command — a supported vendor-data reply is + equally conclusive, so accept either. + """ + if self._connected: + return True + + # The welcome handshake (RTS edge) is the primary identification, but + # the firmware occasionally stops answering it while still answering + # every command — the supported vendor-data reply below is equally + # conclusive, so the welcome is read for logging only. + welcome = self._read_welcome() + if welcome and welcome != WELCOME_MESSAGE: + log.debug( + "WireView: unexpected welcome string %r on %s", + welcome, + self._port, + ) + + vd = self._transaction(bytes([CMD_READ_VENDOR_DATA]), 3) + if vd is None or len(vd) < 3: + return False + vendor, product, fw = vd[0], vd[1], vd[2] + if not is_supported_product(vendor, product): + self._rejected = True + log.info( + "WireView: unsupported product %02X%02X on %s, skipped", + vendor, + product, + self._port, + ) + return False + + self._vendor_id = vendor + self._product_id = product + self._firmware_version = str(fw) + + cfg = self._transaction(bytes([CMD_READ_CONFIG]), 4) + if cfg is None or len(cfg) < 3: + return False + self._config_version = cfg[2] + + uid = self._transaction(bytes([CMD_READ_UID]), 12) + if uid is not None and len(uid) == 12: + self._uid = uid.hex().upper() + + # Enable display updates just in case. + self._transaction( + bytes([CMD_SCREEN_CHANGE, SCREEN_RESUME_UPDATES]), 0 + ) + + build = self._transaction(bytes([CMD_READ_BUILD_INFO]), BUILD_STRUCT_SIZE) + if build is not None and len(build) >= BUILD_INFO_OFFSET + 1: + self._build = ( + build[BUILD_INFO_OFFSET : BUILD_INFO_OFFSET + 32] + .split(b"\x00")[0] + .decode("ascii", errors="replace") + ) + + self._connected = True + log.info( + "WireView connected on %s (%s, fw %s)", + self._port, + self.info()["hw_rev"], + self._firmware_version, + ) + return True + + def close(self) -> None: + self._connected = False + + # ── Sensor reads ── + + def read_sample(self) -> dict | None: + """Read one sensor sample, or None when the device is unresponsive + or the frame is corrupt.""" + if not self._connected: + return None + buf = self._transaction(bytes([CMD_READ_SENSOR_VALUES]), SENSOR_STRUCT_SIZE) + if buf is None or sensor_frame_is_corrupt(buf): + return None + return parse_sensor_struct(buf) + + # ── Transport ── + + def _read_welcome(self) -> str | None: + """Assert RTS and read the NUL-terminated welcome string the device + answers with. Null when nothing (or no terminator) arrives in time.""" + try: + ser = serial.Serial(self._port, self._baud, timeout=READ_TIMEOUT_S) + except (serial.SerialException, OSError): + return None + try: + ser.reset_input_buffer() + ser.rts = False + time.sleep(0.01) + ser.rts = True + time.sleep(0.01) + buf = bytearray() + deadline = time.monotonic() + READ_TIMEOUT_S + while len(buf) < MAX_WELCOME_LENGTH: + remaining = deadline - time.monotonic() + if remaining <= 0: + break + ser.timeout = min(READ_TIMEOUT_S, remaining) + chunk = ser.read(MAX_WELCOME_LENGTH - len(buf)) + if not chunk: + break + buf.extend(chunk) + if b"\x00" in chunk: + break + time.sleep(0.01) + ser.rts = False + nul = buf.find(b"\x00") + if nul >= 0: + return bytes(buf[:nul]).decode("ascii", errors="replace") + return None + except (serial.SerialException, OSError): + return None + finally: + ser.close() + + def _transaction(self, cmd: bytes, response_size: int) -> bytes | None: + """Open the port, send cmd, read exactly response_size bytes (one + second budget), close the port. None when the port is unavailable + or the reply is incomplete.""" + try: + ser = serial.Serial(self._port, self._baud, timeout=READ_TIMEOUT_S) + except (serial.SerialException, OSError): + return None + try: + ser.reset_input_buffer() + if cmd: + ser.write(cmd) + if response_size == 0: + return b"" + return self._read_exact(ser, response_size) + except (serial.SerialException, OSError): + return None + finally: + ser.close() + + @staticmethod + def _read_exact(ser: serial.Serial, size: int) -> bytes | None: + """Read exactly size bytes within one second, or None.""" + buf = bytearray() + deadline = time.monotonic() + READ_TIMEOUT_S + while len(buf) < size: + remaining = deadline - time.monotonic() + if remaining <= 0: + return None + ser.timeout = min(READ_TIMEOUT_S, remaining) + chunk = ser.read(size - len(buf)) + if not chunk: + return None + buf.extend(chunk) + return bytes(buf) + + +# ── hwmon (sysfs) transport ─────────────────────────────────────────────────── + + +class WireViewHwmonDevice: + """Reads the wireview-hwmon sysfs node (kernel module + wireviewd). + + Used when the module is loaded: the daemon owns the serial port in + that case, so direct serial would corrupt frames. + """ + + def __init__(self, hwmon_path: str) -> None: + self._path = hwmon_path + self._connected = False + + @property + def connected(self) -> bool: + return self._connected + + @property + def rejected(self) -> bool: + return False + + @property + def transport(self) -> str: + return "hwmon" + + @property + def port(self) -> str: + return self._path + + def info(self) -> dict: + return { + "device_name": "WireView Pro II", + "hw_rev": "", + "firmware_version": "", + "uid": "", + "build": "", + "transport": self.transport, + "port": self._path, + } + + def node_exists(self) -> bool: + return os.path.isdir(self._path) + + def connect(self) -> bool: + if self._connected: + return True + name_path = os.path.join(self._path, "name") + try: + with open(name_path) as f: + if f.read().strip().lower() != "wireview": + return False + # Probe that the node actually serves data. + with open(os.path.join(self._path, "in0_input")) as f: + f.read().strip() + except OSError: + return False + self._connected = True + log.info("WireView connected via hwmon (%s)", self._path) + return True + + def close(self) -> None: + self._connected = False + + def read_sample(self) -> dict | None: + if not self._connected: + return None + try: + pin_voltage = [ + self._read_int(f"in{i}_input") / 1000.0 for i in range(6) + ] + pin_current = [ + self._read_int(f"curr{i + 1}_input") / 1000.0 for i in range(6) + ] + temp_in = self._read_temp("temp1_input") + temp_out = self._read_temp("temp2_input") + temp_ext1 = self._read_temp("temp3_input") + temp_ext2 = self._read_temp("temp4_input") + + fault_status = self._read_int_or("fault_status_raw") + if fault_status is None: + fault_status = 0xFFFF if self._read_int("intrusion0_alarm") else 0 + fault_log = self._read_int_or("fault_log_raw") + if fault_log is None: + fault_log = 0xFFFF if self._read_int("intrusion1_alarm") else 0 + + psu_cap_uw = self._read_int_or("power1_cap") + if psu_cap_uw is not None: + psu_capability = int(round(psu_cap_uw / 1_000_000.0)) + else: + psu_cap = self._read_int_or("psu_cap") + psu_capability = PSU_CAPABILITY_W.get(psu_cap or 0, 0) + + pwm = self._read_int_or("pwm1") + if pwm is not None: + fan_duty = int(round(min(255, max(0, pwm)) * 100 / 255.0)) + else: + fan_duty = self._read_int("fan1_input") + + power_total = sum( + v * i + for v, i in zip(pin_voltage, pin_current, strict=True) + ) + current_total = sum(pin_current) + + return { + "timestamp": time.time(), + "power_total_w": round(power_total, 3), + "current_total_a": round(current_total, 3), + "voltage_avg_v": ( + round(power_total / current_total, 3) + if current_total > 0 + else 0.0 + ), + "pins": [ + { + "voltage_v": round(v, 3), + "current_a": round(i, 3), + "power_w": round(v * i, 3), + } + for v, i in zip(pin_voltage, pin_current, strict=True) + ], + "temp_in_c": temp_in, + "temp_out_c": temp_out, + "temp_ext1_c": temp_ext1, + "temp_ext2_c": temp_ext2, + "fan_duty_pct": fan_duty, + "fault_status": fault_status, + "fault_log": fault_log, + "psu_capability_w": psu_capability, + } + except OSError: + return None + + def _read_int(self, filename: str) -> int: + """Read an integer sysfs attribute; 0 when missing or unreadable + (matches the exporter's ReadIntFile).""" + try: + with open(os.path.join(self._path, filename)) as f: + return int(f.read().strip()) + except (OSError, ValueError): + return 0 + + def _read_int_or(self, filename: str) -> int | None: + try: + with open(os.path.join(self._path, filename)) as f: + return int(f.read().strip()) + except (OSError, ValueError): + return None + + def _read_temp(self, filename: str) -> float | None: + """Read a temperature sysfs attribute (m°C); None when missing or + unreadable. NaN would poison the whole sample: the WebSocket + serializer emits a bare NaN token (invalid JSON) and the REST + JSONResponse rejects it with a 500.""" + try: + with open(os.path.join(self._path, filename)) as f: + return int(f.read().strip()) / 1000.0 + except (OSError, ValueError): + return None + + +def create_device() -> WireViewSerialDevice | WireViewHwmonDevice | None: + """Create a device for the first available WireView, or None. + + Preference: the wireview-hwmon sysfs node (the wireviewd daemon owns + the serial port in that case), otherwise direct serial on the first + matching /dev/ttyACM*. + """ + hwmon_path = find_hwmon_path() + if hwmon_path: + return WireViewHwmonDevice(hwmon_path) + ports = find_wireview_ports() + if ports: + return WireViewSerialDevice(ports[0]) + return None diff --git a/pyproject.toml b/pyproject.toml index 6a0d03e..c3afc02 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ dependencies = [ "pydantic>=2.0", "httpx>=0.27", "bcrypt>=4.0", + "pyserial>=3.5", ] [project.scripts] diff --git a/tests/test_wireview.py b/tests/test_wireview.py new file mode 100644 index 0000000..fa0fe72 --- /dev/null +++ b/tests/test_wireview.py @@ -0,0 +1,493 @@ +"""Tests for the native WireView Pro II reader (nvcurve/wireview.py). + +Standalone (no pytest required): + + python tests/test_wireview.py + +Also works under pytest. Covers the sensor-frame parser, corruption +detection, fault decoding, USB port discovery, and the hwmon (sysfs) +transport. +""" + +import builtins +import io +import os +import struct +import sys +import tempfile +from unittest import mock + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) + +from nvcurve import wireview as wv # noqa: E402 + +PASS = 0 +FAIL = 0 + + +def check(name: str, cond: bool) -> None: + global PASS, FAIL + if cond: + PASS += 1 + print(f" PASS {name}") + else: + FAIL += 1 + print(f" FAIL {name}") + + +def make_frame( + ts=(392, 352, 273, 395), + vdd=11900, + fan=0, + pins=((11904, 6221, 74055),) * 6, + total_power=450568, + total_current=37863, + avg_voltage=11900, + psu_cap=0, + fault_status=0, + fault_log=0, + pad1=0, + pad2=0, +) -> bytes: + """Build a 100-byte sensor frame with controllable fields.""" + frame = struct.pack("<4hHB", *ts, vdd, fan) + frame += bytes([pad1]) + for voltage, current, power in pins: + frame += struct.pack(" {watts}W", s["psu_capability_w"] == watts) + + +def test_parse_negative_temps(): + s = wv.parse_sensor_struct(make_frame(ts=(-10, 0, 555, 999))) + check("negative temp", abs(s["temp_in_c"] - (-1.0)) < 1e-9) + check("zero temp", s["temp_out_c"] == 0.0) + check("high temp", abs(s["temp_ext2_c"] - 99.9) < 1e-9) + + +# ── Corruption detection ────────────────────────────────────────────────────── + + +def test_corruption_check(): + check("clean frame accepted", not wv.sensor_frame_is_corrupt(make_frame())) + check( + "fan duty > 100 rejected", + wv.sensor_frame_is_corrupt(make_frame(fan=101)), + ) + check( + "fan duty 100 accepted", + not wv.sensor_frame_is_corrupt(make_frame(fan=100)), + ) + check("pad1 dirty rejected", wv.sensor_frame_is_corrupt(make_frame(pad1=1))) + check("pad2 dirty rejected", wv.sensor_frame_is_corrupt(make_frame(pad2=1))) + check( + "short frame rejected", + wv.sensor_frame_is_corrupt(make_frame()[:50]), + ) + + +# ── Fault decoding ──────────────────────────────────────────────────────────── + + +def test_decode_faults(): + check("no faults", wv.decode_faults(0) == []) + check( + "chip over-temp", + wv.decode_faults(1) == ["Chip over-temperature"], + ) + check( + "over-power", + wv.decode_faults(16) == ["Over-power (OPP)"], + ) + check( + "multiple faults", + wv.decode_faults(1 | 32) + == ["Chip over-temperature", "Current imbalance"], + ) + check( + "unknown bits ignored", + wv.decode_faults(1 | 0x80) == ["Chip over-temperature"], + ) + + +def test_product_support(): + check("Pro II supported", wv.is_supported_product(0xEF, 0x05)) + check("Noctua Edition supported", wv.is_supported_product(0xEF, 0x06)) + check("WireView II unsupported", not wv.is_supported_product(0xEF, 0x07)) + check("other vendor unsupported", not wv.is_supported_product(0x12, 0x05)) + + +# ── USB port discovery ──────────────────────────────────────────────────────── + + +def test_find_wireview_ports(): + """Fake a sysfs tree with one WireView (ttyACM0) and one other CDC + device (ttyACM1), plus the udev symlink.""" + contents = { + "/sys/devices/fake/usb0/idVendor": "0483\n", + "/sys/devices/fake/usb0/idProduct": "5740\n", + "/sys/devices/fake/usb1/idVendor": "1234\n", + "/sys/devices/fake/usb1/idProduct": "5678\n", + } + + def fake_islink(p): + return p == "/dev/wireview-pro2" + + def fake_realpath(p): + return { + "/dev/wireview-pro2": "/dev/ttyACM0", + "/sys/class/tty/ttyACM0": "/sys/devices/fake/usb0", + "/sys/class/tty/ttyACM1": "/sys/devices/fake/usb1", + }.get(p, p) + + def fake_isdir(p): + return p == "/sys/class/tty" + + def fake_listdir(p): + return ["ttyACM0", "ttyACM1"] if p == "/sys/class/tty" else [] + + def fake_isfile(p): + return p in contents + + def fake_exists(p): + return p == "/dev/ttyACM0" + + def fake_open(p, *a, **k): + if p in contents: + return io.StringIO(contents[p]) + return real_open(p, *a, **k) + + real_open = open + with mock.patch.object(wv.os.path, "islink", fake_islink), mock.patch.object( + wv.os.path, "realpath", fake_realpath + ), mock.patch.object(wv.os.path, "isdir", fake_isdir), mock.patch.object( + wv.os, "listdir", fake_listdir + ), mock.patch.object(wv.os.path, "isfile", fake_isfile), mock.patch.object( + wv.os.path, "exists", fake_exists + ), mock.patch.object( + wv.os.path, "dirname", os.path.dirname + ), mock.patch.object( + builtins, "open", fake_open + ): + ports = wv.find_wireview_ports() + check("exactly one port found", ports == ["/dev/ttyACM0"]) + + +def test_find_wireview_ports_none(): + with mock.patch.object(wv.os.path, "islink", lambda p: False), mock.patch.object( + wv.os.path, "isdir", lambda p: False + ), mock.patch.object(wv.os.path, "exists", lambda p: False): + check("no ports", wv.find_wireview_ports() == []) + + +def test_find_hwmon_path(): + with tempfile.TemporaryDirectory() as tmp: + # A non-wireview hwmon and a wireview one. + for name, dev in (("hwmon0", "coretemp"), ("hwmon1", "wireview")): + d = os.path.join(tmp, name) + os.makedirs(d) + with open(os.path.join(d, "name"), "w") as f: + f.write(dev + "\n") + + real_join = os.path.join + real_listdir = os.listdir + + def fake_join(*parts): + if parts and parts[0] == "/sys/class/hwmon": + parts = (tmp,) + parts[1:] + return real_join(*parts) + + def fake_listdir(p): + if p == "/sys/class/hwmon": + return real_listdir(tmp) + return real_listdir(p) + + with mock.patch.object(wv.os.path, "join", fake_join), mock.patch.object( + wv.os, "listdir", fake_listdir + ): + found = wv.find_hwmon_path() + check("hwmon path found", found == os.path.join(tmp, "hwmon1")) + + with mock.patch.object(wv.os.path, "isdir", lambda p: False): + check("hwmon absent", wv.find_hwmon_path() is None) + + +# ── hwmon transport ─────────────────────────────────────────────────────────── + + +def test_hwmon_device(): + with tempfile.TemporaryDirectory() as tmp: + p = os.path.join(tmp, "hwmon2") + os.makedirs(p) + with open(os.path.join(p, "name"), "w") as f: + f.write("wireview\n") + for i in range(6): + with open(os.path.join(p, f"in{i}_input"), "w") as f: + f.write("11904\n") + with open(os.path.join(p, f"curr{i + 1}_input"), "w") as f: + f.write("6221\n") + for name, val in ( + ("temp1_input", "39200"), + ("temp2_input", "35200"), + ("temp3_input", "27300"), + ("temp4_input", "39500"), + ("fault_status_raw", "0"), + ("fault_log_raw", "0"), + ("power1_cap", "600000000"), + ("pwm1", "128"), + ): + with open(os.path.join(p, name), "w") as f: + f.write(val + "\n") + + dev = wv.WireViewHwmonDevice(p) + check("hwmon connect", dev.connect()) + check("hwmon node exists", dev.node_exists()) + s = dev.read_sample() + check("hwmon sample", s is not None) + if s: + check("hwmon temp in", abs(s["temp_in_c"] - 39.2) < 1e-9) + check("hwmon fan duty ~50%", 49 <= s["fan_duty_pct"] <= 51) + check("hwmon psu cap", s["psu_capability_w"] == 600) + check("hwmon 6 pins", len(s["pins"]) == 6) + check( + "hwmon total current", + abs(s["current_total_a"] - round(6 * 6.221, 3)) < 1e-9, + ) + dev.close() + check("hwmon closed", not dev.connected) + + # A missing temp channel must yield null (not NaN): NaN would break + # the WebSocket JSON (bare NaN token) and 500 the REST endpoint. + os.remove(os.path.join(p, "temp3_input")) + dev3 = wv.WireViewHwmonDevice(p) + dev3.connect() + s3 = dev3.read_sample() + check("hwmon missing temp sample", s3 is not None) + if s3: + check("hwmon missing temp is None", s3["temp_ext1_c"] is None) + check("hwmon missing temp present", s3["temp_in_c"] == 39.2) + import json + + check( + "hwmon sample JSON-safe", + json.dumps(s3, allow_nan=False) is not None, + ) + dev3.close() + + # Wrong device name is rejected. + with open(os.path.join(p, "name"), "w") as f: + f.write("coretemp\n") + dev2 = wv.WireViewHwmonDevice(p) + check("wrong name rejected", not dev2.connect()) + + +def test_hwmon_legacy_attrs(): + """Older modules expose psu_cap/fan1_input instead of power1_cap/pwm1.""" + with tempfile.TemporaryDirectory() as tmp: + p = os.path.join(tmp, "hwmon3") + os.makedirs(p) + with open(os.path.join(p, "name"), "w") as f: + f.write("wireview\n") + for i in range(6): + with open(os.path.join(p, f"in{i}_input"), "w") as f: + f.write("12000\n") + with open(os.path.join(p, f"curr{i + 1}_input"), "w") as f: + f.write("1000\n") + for name, val in ( + ("temp1_input", "30000"), + ("temp2_input", "30000"), + ("temp3_input", "30000"), + ("temp4_input", "30000"), + ("psu_cap", "2"), + ("fan1_input", "42"), + ("intrusion0_alarm", "0"), + ("intrusion1_alarm", "0"), + ): + with open(os.path.join(p, name), "w") as f: + f.write(val + "\n") + + dev = wv.WireViewHwmonDevice(p) + check("legacy connect", dev.connect()) + s = dev.read_sample() + check("legacy sample", s is not None) + if s: + check("legacy psu cap 300W", s["psu_capability_w"] == 300) + check("legacy fan pct", s["fan_duty_pct"] == 42) + + +# ── Serial transport (pty-based fake device) ────────────────────────────────── + + +def _build_info_struct(product_name: str, build_info: str) -> bytes: + """BuildStruct: VendorData(3) + ProductName(32) + BuildInfo(32) + NameLength(1).""" + return ( + bytes([0xEF, 0x05, 1]) + + product_name.encode().ljust(32, b"\x00") + + build_info.encode().ljust(32, b"\x00") + + bytes([len(product_name)]) + ) + + +def _pty_fake_device(responses: dict): + """Create a pty pair whose master side answers protocol commands in a + background thread. Returns (slave_path, master_fd, thread). + + The fake never sends the welcome string, so the device exercises its + documented fallback: identification via the vendor-data reply. + """ + import pty + import threading + + master, slave = pty.openpty() + slave_path = os.ttyname(slave) + + def run(): + while True: + try: + cmd = os.read(master, 1) + except OSError: + return + if not cmd: + return + resp = responses.get(cmd[0]) + if resp: + try: + os.write(master, resp) + except OSError: + return + + t = threading.Thread(target=run, daemon=True) + t.start() + return slave_path, master, t + + +def test_serial_device_protocol(): + """Full connect handshake + sensor read against a fake device.""" + uid = bytes.fromhex("A7003100015045324B383120") + responses = { + wv.CMD_READ_VENDOR_DATA: bytes([0xEF, 0x05, 1]), + wv.CMD_READ_CONFIG: bytes([0, 0, 1, 0]), # version at offset 2 + wv.CMD_READ_UID: uid, + wv.CMD_READ_BUILD_INFO: _build_info_struct( + "WireView Pro II", "TG-WV-PRO2-FW_20251211_1547" + ), + wv.CMD_READ_SENSOR_VALUES: make_frame(), + # CMD_SCREEN_CHANGE expects no response. + } + slave_path, master, t = _pty_fake_device(responses) + try: + dev = wv.WireViewSerialDevice(slave_path) + check("serial connect", dev.connect()) + check("serial not rejected", not dev.rejected) + info = dev.info() + check("serial device name", info["device_name"] == "WireView Pro II") + check("serial hw_rev", info["hw_rev"] == "EF05") + check("serial firmware", info["firmware_version"] == "1") + check("serial uid", info["uid"] == "A7003100015045324B383120") + check("serial build", info["build"] == "TG-WV-PRO2-FW_20251211_1547") + check("serial transport", info["transport"] == "serial") + + s = dev.read_sample() + check("serial sample", s is not None) + if s: + check("serial sample temp", abs(s["temp_in_c"] - 39.2) < 1e-9) + check("serial sample pins", len(s["pins"]) == 6) + + dev.close() + check("serial closed", not dev.connected) + finally: + os.close(master) + t.join(timeout=2) + + +def test_serial_device_rejected_product(): + """An unsupported product id is rejected and memoized via .rejected.""" + responses = {wv.CMD_READ_VENDOR_DATA: bytes([0xEF, 0x07, 1])} + slave_path, master, t = _pty_fake_device(responses) + try: + dev = wv.WireViewSerialDevice(slave_path) + check("serial reject connect", not dev.connect()) + check("serial rejected flag", dev.rejected) + finally: + os.close(master) + t.join(timeout=2) + + +def test_serial_device_no_response(): + """A silent port fails the connect (vendor-data read times out).""" + slave_path, master, t = _pty_fake_device({}) + try: + dev = wv.WireViewSerialDevice(slave_path) + check("serial no-response connect", not dev.connect()) + check("serial no-response not rejected", not dev.rejected) + check("serial no-response sample", dev.read_sample() is None) + finally: + os.close(master) + t.join(timeout=2) + + +def main() -> int: + print("wireview tests:") + test_parse_sensor_struct() + test_parse_psu_capabilities() + test_parse_negative_temps() + test_corruption_check() + test_decode_faults() + test_product_support() + test_find_wireview_ports() + test_find_wireview_ports_none() + test_find_hwmon_path() + test_hwmon_device() + test_hwmon_legacy_attrs() + test_serial_device_protocol() + test_serial_device_rejected_product() + test_serial_device_no_response() + print(f"\n{PASS} passed, {FAIL} failed") + return 1 if FAIL else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/uv.lock b/uv.lock index 30d4f5b..2d16afb 100644 --- a/uv.lock +++ b/uv.lock @@ -246,6 +246,7 @@ dependencies = [ { name = "httpx" }, { name = "nvidia-ml-py" }, { name = "pydantic" }, + { name = "pyserial" }, { name = "uvicorn", extra = ["standard"] }, ] @@ -261,6 +262,7 @@ requires-dist = [ { name = "httpx", specifier = ">=0.27" }, { name = "nvidia-ml-py", specifier = ">=12.0" }, { name = "pydantic", specifier = ">=2.0" }, + { name = "pyserial", specifier = ">=3.5" }, { name = "uvicorn", extras = ["standard"], specifier = ">=0.30" }, ] @@ -389,6 +391,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, ] +[[package]] +name = "pyserial" +version = "3.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/7d/ae3f0a63f41e4d2f6cb66a5b57197850f919f59e558159a4dd3a818f5082/pyserial-3.5.tar.gz", hash = "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb", size = 159125, upload-time = "2020-11-23T03:59:15.045Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/bc/587a445451b253b285629263eb51c2d8e9bcea4fc97826266d186f96f558/pyserial-3.5-py2.py3-none-any.whl", hash = "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0", size = 90585, upload-time = "2020-11-23T03:59:13.41Z" }, +] + [[package]] name = "python-dotenv" version = "1.2.2" From b8e91e3c91dc3303dd96d878d43f25d4cd558f4c Mon Sep 17 00:00:00 2001 From: ARIA Date: Sat, 3 Oct 2026 13:32:43 +0200 Subject: [PATCH 2/4] fix: degrade gracefully when pyserial is missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A stale venv after a code update (editable install + git pull) left pyserial out of the environment, and the hard module-level import in wireview.py took the entire web server down — even on machines without a WireView device. Guard the import: without pyserial the serial transport is disabled (one-time warning, connect fails, reads return None) while the rest of the server keeps running. The hwmon transport is unaffected. Also simplify the except clauses to OSError (SerialException is an OSError subclass) so they no longer reference the possibly-None module. --- nvcurve/wireview.py | 43 ++++++++++++++++++++++++++++++++---------- tests/test_wireview.py | 35 ++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/nvcurve/wireview.py b/nvcurve/wireview.py index b93cd61..2be0c22 100644 --- a/nvcurve/wireview.py +++ b/nvcurve/wireview.py @@ -19,11 +19,19 @@ import logging import os import struct import time +from typing import Any -import serial +try: + import serial +except ImportError: # pyserial missing — the serial transport is disabled, + # but the rest of the server keeps running (a stale venv after a code + # update must not take the whole web server down). + serial = None log = logging.getLogger("nvcurve.wireview") +_serial_missing_warned = False + # ── Device identification ───────────────────────────────────────────────────── USB_VENDOR_ID = "0483" # STMicroelectronics (CDC/ACM) @@ -407,12 +415,28 @@ class WireViewSerialDevice: # ── Transport ── + def _open_port(self): + """Open the serial port, or None when pyserial is missing or the + port is unavailable.""" + global _serial_missing_warned + if serial is None: + if not _serial_missing_warned: + _serial_missing_warned = True + log.warning( + "pyserial is not installed — WireView serial transport " + "disabled (install pyserial, e.g. `uv sync`)" + ) + return None + try: + return serial.Serial(self._port, self._baud, timeout=READ_TIMEOUT_S) + except OSError: # SerialException is an OSError + return None + def _read_welcome(self) -> str | None: """Assert RTS and read the NUL-terminated welcome string the device answers with. Null when nothing (or no terminator) arrives in time.""" - try: - ser = serial.Serial(self._port, self._baud, timeout=READ_TIMEOUT_S) - except (serial.SerialException, OSError): + ser = self._open_port() + if ser is None: return None try: ser.reset_input_buffer() @@ -439,7 +463,7 @@ class WireViewSerialDevice: if nul >= 0: return bytes(buf[:nul]).decode("ascii", errors="replace") return None - except (serial.SerialException, OSError): + except OSError: # SerialException is an OSError return None finally: ser.close() @@ -448,9 +472,8 @@ class WireViewSerialDevice: """Open the port, send cmd, read exactly response_size bytes (one second budget), close the port. None when the port is unavailable or the reply is incomplete.""" - try: - ser = serial.Serial(self._port, self._baud, timeout=READ_TIMEOUT_S) - except (serial.SerialException, OSError): + ser = self._open_port() + if ser is None: return None try: ser.reset_input_buffer() @@ -459,13 +482,13 @@ class WireViewSerialDevice: if response_size == 0: return b"" return self._read_exact(ser, response_size) - except (serial.SerialException, OSError): + except OSError: # SerialException is an OSError return None finally: ser.close() @staticmethod - def _read_exact(ser: serial.Serial, size: int) -> bytes | None: + def _read_exact(ser: Any, size: int) -> bytes | None: """Read exactly size bytes within one second, or None.""" buf = bytearray() deadline = time.monotonic() + READ_TIMEOUT_S diff --git a/tests/test_wireview.py b/tests/test_wireview.py index fa0fe72..2f2a8fb 100644 --- a/tests/test_wireview.py +++ b/tests/test_wireview.py @@ -469,6 +469,40 @@ def test_serial_device_no_response(): t.join(timeout=2) +def test_serial_transport_missing_pyserial(): + """A missing pyserial degrades gracefully: connect fails, reads are + None, and the warning is logged once — not on every attempt.""" + import logging + + records: list[str] = [] + + class Capture(logging.Handler): + def emit(self, record: logging.LogRecord) -> None: + records.append(record.getMessage()) + + logger = logging.getLogger("nvcurve.wireview") + handler = Capture() + old_level = logger.level + logger.addHandler(handler) + logger.setLevel(logging.WARNING) + try: + with mock.patch.object(wv, "serial", None): + wv._serial_missing_warned = False + dev = wv.WireViewSerialDevice("/dev/ttyACM99") + check("no-pyserial connect", not dev.connect()) + check("no-pyserial not rejected", not dev.rejected) + check("no-pyserial sample", dev.read_sample() is None) + # A second attempt must not re-warn. + dev2 = wv.WireViewSerialDevice("/dev/ttyACM99") + check("no-pyserial second attempt", not dev2.connect()) + warnings = [r for r in records if "pyserial" in r] + check("no-pyserial warns once", len(warnings) == 1) + finally: + logger.removeHandler(handler) + logger.setLevel(old_level) + wv._serial_missing_warned = False + + def main() -> int: print("wireview tests:") test_parse_sensor_struct() @@ -485,6 +519,7 @@ def main() -> int: test_serial_device_protocol() test_serial_device_rejected_product() test_serial_device_no_response() + test_serial_transport_missing_pyserial() print(f"\n{PASS} passed, {FAIL} failed") return 1 if FAIL else 0 From 6f5c046a59f83dd31f894d48fa86721257c11f65 Mon Sep 17 00:00:00 2001 From: ARIA Date: Sat, 3 Oct 2026 13:37:39 +0200 Subject: [PATCH 3/4] docs: mention WireView Pro II monitoring in README fork-features block --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 78e31ef..af34569 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ NVCurve brings MSI Afterburner-style per-point voltage-frequency curve control t > **Blackwell GPU memory** — This is a specialized fork with extended memory offset support (up to +3000 MHz) for Blackwell GPUs (RTX 50-series). \ > **Fan Controls** — There is an additional "Fans" tab to setup a customized fan curve, controlling all fans or individual fans. \ > **Dashboard** — The default tab is an Dashboard with additional information (PCIe link speed, VBIOS information, Max Core Clock, Throttle Reason and much much more.) \ +> **WireView Pro II** — Native monitoring of the Thermal Grizzly WireView Pro II 12VHPWR connector: the device is auto-detected over USB and a dedicated tab shows live temperature, power and current readings — no external exporter or kernel module required. The tab only appears while the device is connected.\ > **Authentification** — For production deplyoment, I added authentification with bcrypt hashing to allow only one or multiple people to have access. \ > Installing the pre-built PyPI package will NOT include these features. You must build from source. From 457ca5c3a6c60a10be0326475e97f570de686503 Mon Sep 17 00:00:00 2001 From: ARIA Date: Sat, 3 Oct 2026 13:43:14 +0200 Subject: [PATCH 4/4] docs: add WireView tab screenshot to README --- README.md | 3 +++ docs/wireview.png | Bin 0 -> 134452 bytes 2 files changed, 3 insertions(+) create mode 100644 docs/wireview.png diff --git a/README.md b/README.md index af34569..db88bcd 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,9 @@ NVCurve brings MSI Afterburner-style per-point voltage-frequency curve control t Performance Fans + + WireView + ## Prerequisites diff --git a/docs/wireview.png b/docs/wireview.png new file mode 100644 index 0000000000000000000000000000000000000000..6024605385f57e7243d7236a1fea6cbf49f0d252 GIT binary patch literal 134452 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≤LnKY(Zb$A4!O52pCXq#|9EbO)GEvKGjt? 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 P#XngYCFy)g!&m