"""Tests for ESP-NOW binary wire format.""" import sys from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(PROJECT_ROOT / "src")) from util.binary_envelope import pack_binary_envelope_v2 # noqa: E402 from util.espnow_wire import ( # noqa: E402 BROADCAST_MAC, MAX_ESPNOW_PAYLOAD, MSG_ANNOUNCE, MSG_CMD, MSG_GROUPS, WIRE_MAGIC, pack_announce, pack_bridge_channel, pack_cmd, pack_cmd_from_kwargs, pack_group_cmd_from_kwargs, pack_groups, pack_ws_downlink, pack_ws_uplink, parse_announce, parse_cmd_as_v1_dict, parse_group_cmd, parse_groups, parse_ws_frame, wire_msg_type, ) def test_announce_round_trip(): raw = pack_announce( name="led-abc123", num_leds=119, color_order="grb", startup_mode="last", brightness=70, ) assert len(raw) <= MAX_ESPNOW_PAYLOAD assert raw[0] == WIRE_MAGIC assert raw[1] == MSG_ANNOUNCE d = parse_announce(raw) assert d["name"] == "led-abc123" assert d["num_leds"] == 119 assert d["color_order"] == "grb" assert d["startup_mode"] == "last" assert d["brightness"] == 70 def test_groups_round_trip(): raw = pack_groups(["5", "18", "test"]) assert wire_msg_type(raw) == MSG_GROUPS assert parse_groups(raw) == ["5", "18", "test"] def test_cmd_envelope_round_trip(): env = pack_binary_envelope_v2(brightness_0_255=128) raw = pack_cmd(env, save=True) assert wire_msg_type(raw) == MSG_CMD assert len(raw) <= MAX_ESPNOW_PAYLOAD d = parse_cmd_as_v1_dict(raw) assert d == {"v": "1", "b": 128, "save": True} def test_cmd_from_kwargs(): raw = pack_cmd_from_kwargs( select={"dev1": ["on"]}, brightness_0_255=64, ) d = parse_cmd_as_v1_dict(raw) assert d["select"]["dev1"] == ["on"] assert d["b"] == 64 def test_group_cmd_round_trip(): raw = pack_group_cmd_from_kwargs("18", brightness_0_255=32) gid, env = parse_group_cmd(raw) assert gid == "18" d = parse_cmd_as_v1_dict(bytes([WIRE_MAGIC, MSG_CMD]) + env) assert d["b"] == 32 def test_ws_frame_round_trip(): pkt = pack_announce(name="led-x", num_leds=10) peer = bytes.fromhex("e8f60a16dad0") up = pack_ws_uplink(peer, pkt) p2, pkt2, bcast = parse_ws_frame(up) assert p2 == peer assert pkt2 == pkt assert not bcast down = pack_ws_downlink(pkt, peer_mac=peer) p3, pkt3, bcast3 = parse_ws_frame(down) assert p3 == peer assert pkt3 == pkt assert not bcast3 bdown = pack_ws_downlink(pkt, broadcast=True) _, pkt4, bcast4 = parse_ws_frame(bdown) assert pkt4 == pkt assert bcast4 def test_bridge_channel(): raw = pack_bridge_channel(6) assert len(raw) == 3 assert raw[1] == 0x10