debug: figuring out whats wrong with waveform viewer

This commit is contained in:
2026-04-14 16:00:14 -04:00
parent 0da88ec6aa
commit 4f4c1a8f64
3 changed files with 118 additions and 88 deletions
+8
View File
@@ -191,6 +191,14 @@ rectime_seconds = int(round((total_samples - pretrig_samples) / sample_rate))
`_decode_a5_waveform` uses `sample_rate=1024` as a default; the server overrides with
`compliance_config.sample_rate` when available. Do NOT use `strt[18]` for rectime.
**Sanity check — pretrig_samples must be less than total_samples:**
If `pretrig_samples >= total_samples` the STRT parse is invalid. Possible causes:
DLE-stuffed `0x10` byte within prev_key4 or key4 shifted field offsets, or a different
STRT record variant. `_decode_a5_waveform` logs `raw strt[0:21]` at WARNING level and
clamps `pretrig_samples = 0` so the viewer renders (showing the full waveform from t=0).
Observed once (2026-04-14) with `strt[16:18] = 0x41 0x01` → pretrig=16641 (impossible).
Root cause not yet identified — capture the warning log hex dump to diagnose.
### SUB 5A — end-of-stream signal (confirmed 2026-04-06)
After streaming all waveform chunks, the device sends exactly **1 raw byte** in response to
+15 -1
View File
@@ -1395,6 +1395,18 @@ def _decode_a5_waveform(
total_samples = struct.unpack_from(">H", strt, 14)[0]
pretrig_samples = struct.unpack_from(">H", strt, 16)[0]
# Sanity check: pretrig must be less than total_samples.
# If not, the STRT layout is suspect (DLE-stuffing shift, different record variant, etc.).
# Log the raw bytes for diagnosis and clamp pretrig to 0 so the viewer renders.
if pretrig_samples >= total_samples:
log.warning(
"_decode_a5_waveform: pretrig_samples=%d >= total_samples=%d"
"STRT layout suspect. Raw strt[0:21]: %s "
"Clamping pretrig to 0 for rendering.",
pretrig_samples, total_samples, strt[0:21].hex(' '),
)
pretrig_samples = 0
# strt[18] is a record-mode/type byte, NOT rectime in seconds.
# Confirmed from analysis of 4-9-26 ACH capture (15 distinct events):
# flags=0xFFFE (single-shot) → strt[18]=0x46 ('F') for all events regardless of duration
@@ -1412,8 +1424,10 @@ def _decode_a5_waveform(
log.debug(
"_decode_a5_waveform: STRT total_samples=%d pretrig=%d "
"strt[18]=0x%02X (mode byte, not seconds) computed_rectime=%ds",
"strt[18]=0x%02X (mode byte, not seconds) computed_rectime=%ds "
"raw strt[0:21]: %s",
total_samples, pretrig_samples, strt[18], rectime_seconds,
strt[0:21].hex(' '),
)
# ── Collect per-frame waveform bytes with global offset tracking ─────────
+11 -3
View File
@@ -573,7 +573,9 @@
renderData = plotSamples.filter((_, i) => i % step === 0);
}
const chart = new Chart(canvas, {
let chart;
try {
chart = new Chart(canvas, {
type: 'line',
data: {
labels: renderTimes,
@@ -616,7 +618,9 @@
// decode artifacts (which inflate autoscale to full range) don't
// squash the actual blast signal into an invisible flat line.
// The 0C peak value is authoritative for the true signal amplitude.
...(isGeo && peak0C !== null && peak0C > 0 ? {
// Guard: only apply if peak0C is a valid finite positive number.
...(isGeo && peak0C !== null && peak0C !== undefined
&& isFinite(peak0C) && peak0C > 0 ? {
min: -(peak0C * 1.4),
max: (peak0C * 1.4),
} : {}),
@@ -660,8 +664,12 @@
},
}],
});
} catch (err) {
console.error(`Chart.js error for channel ${ch}:`, err);
canvasWrap.innerHTML = `<p style="color:#f85149;padding:8px;font-size:11px;">Chart error: ${err.message}</p>`;
}
charts[ch] = chart;
if (chart) charts[ch] = chart;
}
}