replay: delay per complete frame instead of per chunk

ReplayPacer (MsgListener+MsgTalker) sits between packetizer output and
downstream listeners; sleeps after each complete NMEA/UBX frame before
forwarding. FileBackend no longer owns the delay — it reads as fast as
possible and the pacer provides back-pressure on the same thread.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 13:11:40 +02:00
co-authored by Claude Sonnet 4.6
parent ff686b64f7
commit dce570460e
4 changed files with 58 additions and 26 deletions
+20 -8
View File
@@ -8,6 +8,7 @@ from backend.network_backend import NetworkBackend
from backend.serial_backend import SerialBackend
from backend.file_backend import FileBackend, source_id_from_path
from msg.frame_logger import FrameLogger
from msg.replay_pacer import ReplayPacer
from transceiver import Transceiver
from nmea.packetizer import NmeaPacketizer
@@ -31,7 +32,7 @@ def parse_args():
help='Save current config as JSON project file')
ap.add_argument('--log-dir', default='./log',
help='Frame log directory (default: ./log)')
ap.add_argument('--delay', type=float, default=1.0,
ap.add_argument('--delay', type=float, default=0.1,
help='File replay inter-frame delay in seconds, 010 (default: 1.0)')
ap.add_argument('--network', nargs=3, action='append',
metavar=('NAME', 'HOST', 'PORT'),
@@ -86,7 +87,7 @@ def _make_listeners(name: str):
def wire_source(name: str, backend, log_dir: str | None,
loggers: list, transceivers: dict):
loggers: list, transceivers: dict, pacer_delay: float = 0.0):
xcvr = Transceiver(name)
backend.register_xcvr(xcvr)
transceivers[name] = xcvr
@@ -102,10 +103,21 @@ def wire_source(name: str, backend, log_dir: str | None,
xcvr.register_listener(ubx_pkt)
nmea_rx, ubx_rx = _make_listeners(name)
for rx in nmea_rx:
nmea_pkt.register_listener(rx)
for rx in ubx_rx:
ubx_pkt.register_listener(rx)
if pacer_delay > 0:
nmea_pacer = ReplayPacer(pacer_delay)
ubx_pacer = ReplayPacer(pacer_delay)
nmea_pkt.register_listener(nmea_pacer)
ubx_pkt.register_listener(ubx_pacer)
for rx in nmea_rx:
nmea_pacer.register_listener(rx)
for rx in ubx_rx:
ubx_pacer.register_listener(rx)
else:
for rx in nmea_rx:
nmea_pkt.register_listener(rx)
for rx in ubx_rx:
ubx_pkt.register_listener(rx)
# ---------------------------------------------------------------------------
@@ -164,13 +176,13 @@ if __name__ == '__main__':
# File sources → one shared FileBackend (no secondary logging)
file_sources = [s for s in sources if s['type'] == 'file']
if file_sources:
file_be = FileBackend([s['path'] for s in file_sources], delay=delay)
file_be = FileBackend([s['path'] for s in file_sources])
backends.append(file_be)
for s in file_sources:
name = source_id_from_path(s['path'])
if name:
wire_source(name, file_be, log_dir=None, loggers=loggers,
transceivers=transceivers)
transceivers=transceivers, pacer_delay=delay)
signal.signal(signal.SIGINT,
lambda sig, frm: handler(sig, frm, backends, loggers))