diff --git a/README.md b/README.md index d80581d..7e41142 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@ scripts/deploy-native.sh BIN # build BIN on the development Orin, # Redeploy after any contracts signals.json change yukart-decoder --list # the signals it decodes, and where zstdcat can-*.log.zst | yukart-decoder --replay # what it would publish for a recording +scripts/replay-session.sh SESSION_DIR [SKIP_S] # on the Orin: replay a session's frames through a + # decoder on vcan_replay, live to displays; never recorded yukart-obd-poller --elm ADDR --once # on the Orin, service stopped: adapter, protocol, # supported PIDs and one value each yukart-gnss --once # the next fix as JSON, no broker diff --git a/scripts/replay-session.sh b/scripts/replay-session.sh new file mode 100755 index 0000000..605b68e --- /dev/null +++ b/scripts/replay-session.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# Replay a recorded session's CAN frames through the decoder, so displays react as +# if the car were live. Runs on the car Orin (sudo: vcan and the decoder service). +# +# usage: scripts/replay-session.sh SESSION_DIR [SKIP_S] +# SESSION_DIR e.g. /var/lib/yukart/recordings/000001-20261013T170050 +# SKIP_S seconds of the recording to skip first (default 0) +# +# Frames go onto a virtual interface, vcan_replay, never can_pcan: the recorder only +# watches can_pcan, so a replay is never recorded as a drive. The decoder service is +# stopped for the replay (one MQTT client id) and a decoder runs on vcan_replay instead; +# however the replay ends (finished, Ctrl-C, killed), the service comes back and the +# interface goes. Values carry the replay's own timing; nothing marks them as replayed. +set -euo pipefail + +SESSION="${1:?usage: replay-session.sh SESSION_DIR [SKIP_S]}" +SKIP="${2:-0}" +IF=vcan_replay +ls "$SESSION"/can-*.log* >/dev/null + +cleanup() { + [ -n "${DEC:-}" ] && kill "$DEC" 2>/dev/null || true + sudo ip link del "$IF" 2>/dev/null || true + sudo systemctl start yukart-decoder + echo "replay: done; yukart-decoder back on can_pcan" +} +trap cleanup EXIT INT TERM + +sudo modprobe vcan +sudo ip link add "$IF" type vcan 2>/dev/null || true +sudo ip link set "$IF" up +sudo systemctl stop yukart-decoder +/usr/local/bin/yukart-decoder --can "$IF" & +DEC=$! +sleep 1 + +echo "replay: $SESSION from +${SKIP} s onto $IF" +# candump -L lines: "(1791878450.945008) can_pcan 139#...". Skip by the first frame's time. +zstdcat -f "$SESSION"/can-*.log* 2>/dev/null \ + | awk -v skip="$SKIP" '{ t = substr($1, 2, length($1) - 2) + 0; if (NR == 1) t0 = t; if (t - t0 >= skip) print }' \ + | canplayer "$IF=can_pcan"