"""Run: PYTHONPATH=src python test_bm200.py Frames here are built from the APK's parser, not captured from a tag. """ from datetime import datetime, timezone from bm2.bm200 import BM200_KEY, BM200Decoder, HistoryBlock, LiveReading, Version, _history_base, history_command from bm2.encryption import encrypt def enc(hex_str: str) -> bytes: return encrypt(bytes.fromhex(hex_str), BM200_KEY) def test() -> None: d = BM200Decoder() now = 1_700_000_000.0 assert d.feed(enc("d15501010700"))[0] == Version(1.7) assert history_command(0xCA80).hex() == "d1550500000000ca80" # temp sign=1 temp=5 status=2 soc=0x55 volt=0x0508 acc=3 dec=4 live = d.feed(enc("d155070105025505080003000400"), now)[0] assert isinstance(live, LiveReading) assert (live.temperature, live.status, live.soc, live.voltage) == (-5, 2, 0x55, 12.88) assert (live.rapid_acceleration, live.rapid_deceleration) == (3, 4) assert d.feed(enc("d15507ff")) == [] assert d.feed(enc("d155050003"), now) == [] # newest first: leading zeros, stop record + 4 trailer bytes, plain record assert d.feed(enc("00000000" + "50055194" + "00030004" + "4f050140"), now) == [] # a live frame in the middle of a transfer stays out of the history assert isinstance(d.feed(enc("d155070005005505080000000000"), now)[0], LiveReading) # negative-temperature start record, then the end marker block = d.feed(enc("4e0000aa" + "fffefe00"), now)[0] assert isinstance(block, HistoryBlock) r = block.records assert [x.voltage for x in r] == [12.48, 12.64, 12.80] # oldest first assert [x.mark for x in r] == ["start", None, "stop"] assert (r[2].soc, r[2].temperature) == (0x55, 0x19) assert (r[0].soc, r[0].temperature) == (0, -0x0a) base = _history_base(now) assert datetime.fromtimestamp(base).minute % 2 == 1 assert r[2].time == datetime.fromtimestamp(base, timezone.utc) assert (r[2].time - r[0].time).total_seconds() == 240 # back to normal once the block ended assert d.feed(enc("d155050000"), now)[0] == HistoryBlock([]) try: d.feed(b"\x00" * 15) raise AssertionError("short frame accepted") except ValueError: pass test() print("ok")