flatudp: vector rows as channels or as a waveform, a re-openable source, probes for both

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-11-02 01:18:43 +01:00
1 parent a523bc2bd9
commit e3bc1f72f3
10 files changed
+446 -100

No files matched your search

+21 -15
View File
@@ -443,22 +443,28 @@ precedent, not an exception.
later checks the frame count moved on. The reading's own entry is in `probe-readings.md`.
- `UDPSCOPE_PROBE_FLATUDP=2500` with `UDPSCOPE_EXIT_AFTER_MS`, run as `--source flatudp` against
`tools/mock_flatudp.py` -- the flat UDP source end to end: a hand-computed codec and decode check (it
needs no source), the stream's signal names and declared rate, the channel count (one per signal), value
continuity across the first two signals (all-scalar lists only), the wrong-size accounting and the capture
button. It enables the signals itself, so do **not** add `UDPSCOPE_ENABLE_ALL_MS`. Runs, each short and
serial, with the mock killed afterwards (quote the `signals` value: zsh globs the `[4]`):
- **mixed list, gap and bad datagrams:** mock `--rate 1000 --signals Trigger:uint8,Ia:float32,Cnt:uint64,Wave:int16[4]
--gap 9,5 --bad-every 1 --log /tmp/flatudp-mock.log` started 1 s before the app, the same `signals` as a
`--source-opt`, with `UDPSCOPE_PROBE_FLATUDP=2500 UDPSCOPE_PROBE_FLATUDP_GAP=8000 UDPSCOPE_EXIT_AFTER_MS=14500`;
stderr carries exactly one `datagram of 22 bytes, expected 21` line. The mock's clock starts about 4 s
before the app's probe clock (`xvfb-run` and the app's own startup), so a gap of 9 s to 14 s on the mock's
clock covers the app's 8 s probe (silence) and ends before its 12 s one (resumed); a mock gap measured in
the app's own seconds would miss both;
- **scalar list, big endian (batching, continuity):** mock `--signals Trigger:uint8,Ia:float32,Cnt:uint64 --big-endian`,
app `--source-opt endian=big`, `UDPSCOPE_PROBE_FLATUDP=2500 UDPSCOPE_EXIT_AFTER_MS=5000`;
needs no source; it covers the `w` suffix, the waveform and 256-channel rules, the channel decode and the
float64/uint16/int32/uint32/int64 types in both byte orders), the stream's channel names (`Wave[0]`..
for a `channels` vector) and declared rates (`rate * count` for a waveform), the channel count, value
continuity per row (and the offset between a vector's elements, or a waveform's block phase), the
wrong-size accounting and the capture button. It enables the signals itself, so do **not** add
`UDPSCOPE_ENABLE_ALL_MS`. Runs, each short and serial, with the mock killed afterwards (quote the `signals`
value: zsh globs the `[4]`):
- **mixed list, gap and bad datagrams:** mock `--rate 1000 --signals 'Trigger:uint8,Ia:float32,Cnt:uint64,Wave:int16[4]'
--gap 8,4 --bad-every 1` started 1 s before the app, the same `signals` as a `--source-opt`, with
`UDPSCOPE_PROBE_FLATUDP=2500 UDPSCOPE_PROBE_FLATUDP_GAP=1500 UDPSCOPE_EXIT_AFTER_MS=14500`; stderr carries
exactly one `datagram of 22 bytes, expected 21` line. The silence probe is a 100 ms poll that waits for the
stream, then for the 2 s of silence to take the source down, then for it to come back, so it does not
depend on when `xvfb-run` finished starting; the only requirement is that the mock's gap begins after
the app connected (the mock's clock starts about 4 s before the app's) and ends in time to read the return
(`--gap 8,4` with a 14.5 s run does both with several seconds of margin);
- **waveform-only list:** mock `--signals 'Wave:int16[4]w'`, app `--source-opt 'signals=Wave:int16[4]w'`,
`UDPSCOPE_PROBE_FLATUDP=2500 UDPSCOPE_EXIT_AFTER_MS=5000`: one channel at `rate=4000`;
- **big endian (decode of every width through the stream):** mock `--big-endian` on the mixed list, app
`--source-opt endian=big`, `UDPSCOPE_PROBE_FLATUDP=2500 UDPSCOPE_EXIT_AFTER_MS=5000`;
- **no sender:** `connected=0` throughout, a reading and not a failure.
- `UDPSCOPE_PROBE_FLATUDP_GAP=8000` -- reads the source inside the mock's silence (2 s after its last datagram
the source is disconnected) and 4 s later checks it reconnected and the stream moved on.
- `UDPSCOPE_PROBE_FLATUDP_GAP=1500` -- starts the silence poll described above (2 s after the source's last
datagram it must be disconnected; then it must reconnect and the frame count move on).
- `UDPSCOPE_PROBE_SEARCH_MS` — runs a buffer search for the armed condition, cross-checks the live
trigger's own `t0` against the nearest hit (`agree=1` is the load-bearing reading), and jumps to
hit 0. Reports the resulting `mode=`, `axis=` and `marks placed=`.