Settings: one window for how far back every graph reaches, 1 minute to 24 hours
Each machine keeps 300 points per curve whatever the window, so memory doesn't follow it; a wider window means wider points, each the average of its bucket rather than one instant out of it. The hub passes the setting to every machine it manages. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
885b050d02
commit
04dd98e2cd
+19
-5
@@ -41,17 +41,31 @@ function Gauge({ s }: { s: Sensor }) {
|
||||
function Spark({ s, src }: { s: Sensor; src?: Source }) {
|
||||
const pts = useRef<number[]>([])
|
||||
const lastT = useRef(0)
|
||||
const stride = useRef(0) // how far apart the machine's own points are, as they arrive
|
||||
const [, bump] = useState(0)
|
||||
useEffect(() => {
|
||||
let stop = false
|
||||
pts.current = []; lastT.current = 0
|
||||
fetchHistory(s.id, src).then((h) => { if (!stop && h) { pts.current = h.v.slice(-MAX_POINTS); lastT.current = h.t[h.t.length - 1] ?? 0; bump((n) => n + 1) } })
|
||||
pts.current = []; lastT.current = 0; stride.current = 0
|
||||
fetchHistory(s.id, src).then((h) => {
|
||||
if (stop || !h) return
|
||||
pts.current = h.v.slice(-MAX_POINTS); lastT.current = h.t[h.t.length - 1] ?? 0
|
||||
const t = h.t.slice(-MAX_POINTS)
|
||||
const gaps = t.slice(1).map((x, i) => x - t[i]).sort((a, b) => a - b)
|
||||
stride.current = gaps.length ? gaps[gaps.length >> 1] : 0 // the median: one long gap is a restart, not the spacing
|
||||
bump((n) => n + 1)
|
||||
})
|
||||
return () => { stop = true }
|
||||
}, [s.id, src?.machine, src?.token]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
if (typeof s.value === 'number' && s.t > lastT.current) {
|
||||
lastT.current = s.t
|
||||
pts.current.push(s.value)
|
||||
if (pts.current.length > MAX_POINTS) pts.current.shift()
|
||||
// a new point once a stride has passed; until then the newest point keeps being refined,
|
||||
// so a wide window's curve isn't squeezed by a fast stream of live values
|
||||
if (pts.current.length && s.t - lastT.current < stride.current) {
|
||||
pts.current[pts.current.length - 1] = s.value
|
||||
} else {
|
||||
lastT.current = s.t
|
||||
pts.current.push(s.value)
|
||||
if (pts.current.length > MAX_POINTS) pts.current.shift()
|
||||
}
|
||||
}
|
||||
return <Sparkline series={[{ name: s.name, values: pts.current, color: 'var(--s1)' }]} max={s.unit === '%' ? 100 : s.max} format={(v) => fmtValue(v, s.unit)} height={40} />
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user