feat: wireview pin-imbalance warning, per-pin rating bars, pin_imbalance_a
- Per-pin bar now scales against the 9.2 A per-pin rating (10 A full scale, red at/over rating) instead of the 55 A total connector OCP - Debounced app-wide warning banner (visible on all tabs) when the current between two pins diverges by > 2 A for ~7 s - the signature of a bad pin contact that can overheat and melt the 12VHPWR connector; 5 s grace period after clearing - New pin_imbalance_a sample field (max - min pin current) in both the serial and hwmon sample builders, plus frontend type - Docs: README + WireView.md cover the warning and threshold; fresh screenshot with the new per-pin labels - Tests: vitest setup + 9 unit tests for the debounce state machine; 3 new backend checks for pin_imbalance_a
This commit is contained in:
1 parent
92356d1409
commit
b69b7502b3
14 files changed
+810
-18
No files matched your search
@@ -0,0 +1,78 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import type { WireViewSample } from "../types.js";
|
||||
|
||||
// Current difference between any two pins that indicates a bad contact.
|
||||
const PIN_IMBALANCE_A = 2;
|
||||
// Show only after the imbalance holds for this many consecutive samples (~1 s each).
|
||||
// AI workloads produce frequent short load ramps that skew one pin transiently,
|
||||
// so the threshold is deliberately high: a bad contact stays imbalanced, a ramp does not.
|
||||
const SHOW_AFTER = 7;
|
||||
// Keep showing this many samples after the imbalance clears (grace period).
|
||||
const HIDE_AFTER = 5;
|
||||
|
||||
export interface ImbalanceAlert {
|
||||
diff: number;
|
||||
maxI: number;
|
||||
minI: number;
|
||||
/** 1-based pin index carrying the most current */
|
||||
hiPin: number;
|
||||
/** 1-based pin index carrying the least current */
|
||||
loPin: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Debounced pin-current imbalance detection.
|
||||
*
|
||||
* A single sample can transiently skew (load change, measurement glitch), so
|
||||
* the alert only appears after the imbalance persists for a few samples, and
|
||||
* stays visible briefly after it clears instead of flickering.
|
||||
*/
|
||||
export function useWireviewImbalance(
|
||||
sample: WireViewSample | null,
|
||||
): ImbalanceAlert | null {
|
||||
const [alert, setAlert] = useState<ImbalanceAlert | null>(null);
|
||||
const alertRef = useRef<ImbalanceAlert | null>(null);
|
||||
const streak = useRef(0);
|
||||
const grace = useRef(0);
|
||||
|
||||
useEffect(() => {
|
||||
function update(next: ImbalanceAlert | null) {
|
||||
alertRef.current = next;
|
||||
setAlert(next);
|
||||
}
|
||||
|
||||
if (!sample || sample.pins.length < 2) {
|
||||
streak.current = 0;
|
||||
grace.current = 0;
|
||||
if (alertRef.current) update(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const currents = sample.pins.map((p) => p.current_a);
|
||||
const maxI = Math.max(...currents);
|
||||
const minI = Math.min(...currents);
|
||||
const diff = maxI - minI;
|
||||
|
||||
if (diff > PIN_IMBALANCE_A) {
|
||||
streak.current += 1;
|
||||
grace.current = 0;
|
||||
if (streak.current >= SHOW_AFTER) {
|
||||
update({
|
||||
diff,
|
||||
maxI,
|
||||
minI,
|
||||
hiPin: currents.indexOf(maxI) + 1,
|
||||
loPin: currents.indexOf(minI) + 1,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
streak.current = 0;
|
||||
if (alertRef.current) {
|
||||
grace.current += 1;
|
||||
if (grace.current >= HIDE_AFTER) update(null);
|
||||
}
|
||||
}
|
||||
}, [sample]);
|
||||
|
||||
return alert;
|
||||
}
|
||||
Reference in new issue
Block a user