binlog.py¶
Source: tools/binlog.py
Host-side reader for the data logger’s binary flight logs — the format
described in Binary Flight-Time Log and written by the bin
formatter on all three backends (flash partition, raw disk region,
filesystem file).
What it does¶
The binary log is the lossless record of a flight: it preserves the
sensor_value channels exactly, so a host can re-run the filters and
the state machine bit-for-bit. On target it is normally translated to
CSV or InfluxDB line protocol by data_logger_convert(). This module
does that translation on the host instead, which matters whenever the
conversion pass never ran — a watchdog reset, a freeze, or a flat pack
between touchdown and conversion all leave a perfectly good .bin
behind and nothing else.
It decodes a log into the same streams dictionary that
plot_flight_data.py builds from
flights.influx, so the existing plotting helpers accept it unchanged.
Decoding is vectorised through NumPy: a 4 MiB, 140 000-record log reads
in well under a tenth of a second.
Readers for the converter’s .csv and .influx output are included as
well, so a caller can load anything found in a DATA directory through
one interface.
What it handles¶
Frame-size detection.
CONFIG_DATA_LOGGER_BIN_FRAME_SIZEis not recorded in the file, so the reader finds it: the frame size is the smallest stride that lands on a valid header for every whole frame in the file. Records never start with the magic, so the probe cannot be fooled by a smaller stride.Torn tails. A file cut short mid-frame by a reset or a power loss is read up to its last whole frame, and the leftover bytes are reported as a warning.
Segments. Frames are grouped into runs sharing a
flight_idwith a monotonicseq. A new segment starts when theflight_idchanges, when the sequence skips, or when the per-framebase_ts_nsgoes backwards — the last of which is the seam a mid-flight reset leaves, since the FS backend keeps theflight_idbut re-derives the timestamp base from the restarted uptime clock.Unwritten and unsupported frames are skipped and counted rather than aborting the read.
Usage¶
python3 tools/binlog.py PATH [--frame-size BYTES] [--csv OUT]
PATH— a.binflight log to inspect, or a directory to list.--frame-size BYTES— override the frame-size probe.--csv OUT— write the decoded records to a CSV file laid out like the on-target converter’s output.
Inspecting a log prints the frame and record counts, then one block per segment:
$ python3 tools/binlog.py DATA/flight_0.bin
DATA/flight_0.bin
frame size : 4096 B
frames : 1106 (0 unwritten/invalid)
records : 140400
segment 1: flight_id=123456789 seq 0..1105 (1106 frames, 140400 records)
duration : 200.000 s (5000000000 .. 204990000000 ns)
accel 20000 samples
baro 20000 samples
...
Reuse from other scripts¶
read_binary_log(path, frame_size=None)— full decode, returning aBinLogwith aSegmentper run. Each segment carries its ownstreamsdict plus frame/record counts andflight_id.load_streams(path)— onestreamsdict for any supported log type (.bin,.csv,.influx), concatenating segments if there are several.scan_data_dir(directory)— list the flight logs in aDATAdirectory, lossless.binfirst.find_data_dir(directory)— theDATAdirectory of a card, given either it or the card root it sits on.find_audit_dir(directory)/scan_audit_dir(directory)— the card’sSTATEdirectory and theAUDIT.<n>dumps in it, in index order.scan_audits(path)— every audit reachable from a log, aDATAdirectory or a card root, including a legacystate_auditsitting next to the logs.find_state_audit(path)— locate a singlestate_auditdump next to a log.detect_frame_size(raw)— the frame-size probe on its own.STREAM_SPECS— stream name to (enum aurora_datavalue, record channels), the mapping that keeps the decoder aligned withdata_logger.h.
A streams value is (t_ns, values): an int64 array of nanosecond
timestamps and an (N, K) float array whose columns follow
plot_flight_data.FIELD_SPECS.
Warning
The constants at the top of this module mirror data_logger.h.
Bumping AURORA_BIN_VERSION in the firmware means updating
BIN_VERSION (and whatever changed) here — the reader refuses frames
whose version it does not know rather than misreading them.
Requirements¶
Python 3.10+
numpy