feat: enhance waveform viewer with record type handling and improved empty state messaging
This commit is contained in:
@@ -183,21 +183,23 @@ def _build_client(
|
||||
baud: int,
|
||||
host: Optional[str],
|
||||
tcp_port: int,
|
||||
timeout: float = 30.0,
|
||||
) -> MiniMateClient:
|
||||
"""
|
||||
Return a MiniMateClient configured for either serial or TCP transport.
|
||||
|
||||
TCP takes priority if *host* is supplied; otherwise *port* (serial) is used.
|
||||
Raises HTTPException(422) if neither is provided.
|
||||
|
||||
Use timeout=120.0 (or higher) for endpoints that perform a full 5A waveform
|
||||
download — a 70-second event at 1024 sps takes 2-3 minutes to transfer over
|
||||
cellular and each individual recv must complete within the timeout window.
|
||||
"""
|
||||
if host:
|
||||
# TCP / modem / ACH path — use a longer timeout to survive cold boots
|
||||
# (unit takes 5-15s to wake from RS-232 line assertion over cellular)
|
||||
transport = TcpTransport(host, port=tcp_port)
|
||||
log.debug("TCP transport: %s:%d", host, tcp_port)
|
||||
return MiniMateClient(transport=transport, timeout=30.0)
|
||||
log.debug("TCP transport: %s:%d timeout=%.0fs", host, tcp_port, timeout)
|
||||
return MiniMateClient(transport=transport, timeout=timeout)
|
||||
elif port:
|
||||
# Direct serial path
|
||||
log.debug("Serial transport: %s baud=%d", port, baud)
|
||||
return MiniMateClient(port, baud)
|
||||
else:
|
||||
@@ -425,7 +427,7 @@ def device_event_waveform(
|
||||
|
||||
try:
|
||||
def _do():
|
||||
with _build_client(port, baud, host, tcp_port) as client:
|
||||
with _build_client(port, baud, host, tcp_port, timeout=120.0) as client:
|
||||
info = client.connect()
|
||||
# full_waveform=True fetches the complete 5A stream inside the
|
||||
# 1E→0A→0C→5A→1F loop. Issuing a second 5A after 1F times out.
|
||||
@@ -458,12 +460,14 @@ def device_event_waveform(
|
||||
|
||||
return {
|
||||
"index": ev.index,
|
||||
"record_type": ev.record_type,
|
||||
"timestamp": _serialise_timestamp(ev.timestamp),
|
||||
"total_samples": ev.total_samples,
|
||||
"pretrig_samples": ev.pretrig_samples,
|
||||
"rectime_seconds": ev.rectime_seconds,
|
||||
"samples_decoded": samples_decoded,
|
||||
"sample_rate": sample_rate,
|
||||
"peak_values": _serialise_peak_values(ev.peak_values),
|
||||
"channels": raw,
|
||||
}
|
||||
|
||||
|
||||
@@ -374,13 +374,7 @@
|
||||
const decoded = data.samples_decoded || 0;
|
||||
const total = data.total_samples || decoded;
|
||||
const channels = data.channels || {};
|
||||
|
||||
// Build time axis (ms)
|
||||
const times = Array.from({ length: decoded }, (_, i) =>
|
||||
((i - pretrig) / sr * 1000).toFixed(2)
|
||||
);
|
||||
|
||||
const triggerMs = 0; // t=0 is trigger by construction
|
||||
const recType = data.record_type || 'Unknown';
|
||||
|
||||
// Status bar
|
||||
const bar = document.getElementById('status-bar');
|
||||
@@ -392,11 +386,30 @@
|
||||
} else {
|
||||
bar.textContent = `Event #${data.index} `;
|
||||
}
|
||||
appendMeta('type', recType);
|
||||
appendMeta('sr', `${sr} sps`);
|
||||
appendMeta('samples', `${decoded.toLocaleString()} / ${total.toLocaleString()}`);
|
||||
appendMeta('pretrig', pretrig);
|
||||
appendMeta('rectime', `${data.rectime_seconds ?? '?'}s`);
|
||||
|
||||
// No waveform data — show a clear reason instead of empty charts
|
||||
if (decoded === 0) {
|
||||
document.getElementById('empty-state').style.display = 'flex';
|
||||
document.getElementById('empty-state').querySelector('p').textContent =
|
||||
recType === 'Waveform'
|
||||
? 'Waveform decode returned no samples — check server logs'
|
||||
: `Record type "${recType}" — waveform decode not yet supported for this mode`;
|
||||
document.getElementById('charts').style.display = 'none';
|
||||
Object.values(charts).forEach(c => c.destroy());
|
||||
charts = {};
|
||||
return;
|
||||
}
|
||||
|
||||
// Build time axis (ms)
|
||||
const times = Array.from({ length: decoded }, (_, i) =>
|
||||
((i - pretrig) / sr * 1000).toFixed(2)
|
||||
);
|
||||
|
||||
// Show charts area
|
||||
document.getElementById('empty-state').style.display = 'none';
|
||||
const chartsDiv = document.getElementById('charts');
|
||||
|
||||
Reference in New Issue
Block a user