From ba6100fd17b358c4a949e86b2c5283d089e1f181 Mon Sep 17 00:00:00 2001 From: Mikkeli Date: Wed, 14 Oct 2026 08:59:51 +0900 Subject: [PATCH] replay-session.sh: a recorded session's frames through the decoder, live to displays Frames go onto vcan_replay (the recorder never sees them); the decoder service stands aside for the replay and comes back however it ends. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01DDwfd6Ki8UfG4hK6W5YpJz --- README.md | 2 ++ scripts/replay-session.sh | 41 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100755 scripts/replay-session.sh 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"