"""The BW filename encodes the serial NUMBER, never the family prefix. "BE" is a MiniMate Plus; "BA" is a BlastMate. Both are Series III and their files are byte-compatible — the whole archive's 1,493 BlastMate binaries decode through the same codec at 100% — so the only thing that distinguishes them downstream is the serial string, and that lives in the file body. Synthesising the prefix as "BE" files a BlastMate under a unit that does not exist. Four units in the DL2 archive are affected: BA9229, BA10060, BA10895 and BA15957. """ from __future__ import annotations import pytest from minimateplus.client import _decode_0a_partial_header from sfm.waveform_store import ( _serial_from_bw_bytes, _serial_from_bw_filename, _serial_number_from_bw_filename, ) # ── the filename gives a number, and only a number ────────────────────────── @pytest.mark.parametrize("name,num", [ ("P036L318.C80H", 14036), # BE14036 ("H907KWRK.WB0H", 6907), # BE6907 ("M529LKIQ.G10", 11529), # BE11529 ("T003LQ9K.OE0H", 18003), # BE18003 ("L895K63F.GE0W", 10895), # BA10895 — a BlastMate ("K229HGQI.XO0W", 9229), # BA9229 — a BlastMate ]) def test_number_from_filename(name, num): assert _serial_number_from_bw_filename(name) == num @pytest.mark.parametrize("name", ["", "not_a_bw_file.bin", "AB12", "1234ABCD.XX0W"]) def test_number_from_filename_rejects_junk(name): assert _serial_number_from_bw_filename(name) is None def test_filename_only_decoder_is_a_guess(): """It still answers "BE" — that is why it must not be the first choice.""" assert _serial_from_bw_filename("L895K63F.GE0W") == "BE10895" assert _serial_from_bw_filename("M529LKIQ.G10") == "BE11529" assert _serial_from_bw_filename("nonsense") is None # ── the body carries the truth ────────────────────────────────────────────── def _body(serial: bytes) -> bytes: return b"\x00" * 32 + b"STRT" + b"\xff\xfe" + serial + b"\x00Geo: 0.254 in/s\x00" def test_body_wins_for_a_blastmate(): assert _serial_from_bw_bytes(_body(b"BA10895"), "L895K63F.GE0W") == "BA10895" def test_body_wins_for_a_minimate(): assert _serial_from_bw_bytes(_body(b"BE11529"), "M529LKIQ.G10") == "BE11529" def test_body_candidate_must_match_the_filename_number(): """A serial-shaped byte run that disagrees with the filename is ignored.""" assert _serial_from_bw_bytes(_body(b"XX99999"), "L895K63F.GE0W") is None def test_body_tolerates_a_leading_zero(): assert _serial_from_bw_bytes(_body(b"BA09229"), "K229HGQI.XO0W") == "BA09229" @pytest.mark.parametrize("data,name", [ (b"", "L895K63F.GE0W"), # no bytes (_body(b"BA10895"), "junk.bin"), # no derivable number ]) def test_body_returns_none_when_it_cannot_decide(data, name): assert _serial_from_bw_bytes(data, name) is None # ── the live monitor-log path ─────────────────────────────────────────────── def _partial_record(serial: bytes) -> bytes: """0x2C partial record: type, prefix, two 9-byte timestamps, then ASCII.""" ts = bytes([11, 0x10, 4, 0x07, 0xE9, 0, 16, 2, 0]) # 2025-04-11 16:02:00 return (bytes([0x2C]) + b"\x00" * 10 + ts + ts + b"\x00\x00\x00\x00" + serial + b"\x00Geo: 0.254 in/s\x00") @pytest.mark.parametrize("serial", [b"BE11529", b"BA10895", b"UM11719"]) def test_monitor_log_reads_any_family_prefix(serial): entry = _decode_0a_partial_header(_partial_record(serial), 0, b"\x01\x11\x00\x00") assert entry is not None assert entry.serial == serial.decode() def test_monitor_log_geo_threshold_survives_a_blastmate(): """The old find(b"BE") skipped the whole block, losing geo too.""" entry = _decode_0a_partial_header(_partial_record(b"BA10895"), 0, b"\x01\x11\x00\x00") assert entry is not None assert entry.geo_threshold_ips == pytest.approx(0.254)