docs(espnow): update docs and tests for p2p merge
Align API, architecture, and help with devices envelope transport, bridge wifi/serial settings, and MAC-keyed device registry. Fix endpoint tests for envelope identify payloads; remove obsolete p2p.py. Bump led-tool for --serial-usb bridge provisioning. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -29,15 +29,56 @@ from microdot.websocket import with_websocket # noqa: E402
|
||||
|
||||
class DummyBridge:
|
||||
def __init__(self):
|
||||
self.sent: list[tuple[str, Optional[str]]] = []
|
||||
self.sent: list[tuple[Any, Optional[str]]] = []
|
||||
|
||||
async def send(self, data: Any, addr: Optional[str] = None):
|
||||
if isinstance(data, (bytes, bytearray)):
|
||||
if isinstance(data, dict):
|
||||
from util.bridge_envelope import ( # noqa: E402
|
||||
BROADCAST_MAC,
|
||||
build_devices_envelope,
|
||||
format_mac_key,
|
||||
is_broadcast_mac,
|
||||
normalize_mac_key,
|
||||
)
|
||||
from util.v1_wire import compact_envelope # noqa: E402
|
||||
|
||||
if data.get("v") == "1" and ("devices" in data or "dv" in data):
|
||||
data = compact_envelope(data)
|
||||
elif addr is not None:
|
||||
s = str(addr).strip().lower()
|
||||
if is_broadcast_mac(s):
|
||||
mac_key = BROADCAST_MAC
|
||||
else:
|
||||
h = normalize_mac_key(s)
|
||||
mac_key = format_mac_key(h) if h else None
|
||||
if mac_key:
|
||||
body = {k: v for k, v in data.items() if k != "v"}
|
||||
data = build_devices_envelope({mac_key: body})
|
||||
else:
|
||||
data = json.dumps(data, separators=(",", ":"))
|
||||
else:
|
||||
data = json.dumps(data, separators=(",", ":"))
|
||||
elif isinstance(data, (bytes, bytearray)):
|
||||
data = bytes(data).decode(errors="ignore")
|
||||
self.sent.append((data, addr))
|
||||
return True
|
||||
|
||||
|
||||
def _bridge_sent_envelope(bridge: DummyBridge, index: int) -> Dict[str, Any]:
|
||||
data, _addr = bridge.sent[index]
|
||||
if isinstance(data, dict):
|
||||
return data
|
||||
return json.loads(data)
|
||||
|
||||
|
||||
def _device_body_from_envelope(envelope: Dict[str, Any], mac: str) -> Dict[str, Any]:
|
||||
from util.bridge_envelope import format_mac_key, normalize_mac_key # noqa: E402
|
||||
|
||||
devs = envelope.get("dv") or envelope.get("devices") or {}
|
||||
key = format_mac_key(normalize_mac_key(mac))
|
||||
return devs[key]
|
||||
|
||||
|
||||
def _json(resp: requests.Response) -> Dict[str, Any]:
|
||||
# Many endpoints already set Content-Type; but be tolerant for now.
|
||||
return resp.json() # pragma: no cover
|
||||
@@ -672,17 +713,19 @@ def test_groups_sequences_scenes_palettes_patterns_endpoints(server):
|
||||
assert resp.status_code == 200
|
||||
assert resp.json().get("message")
|
||||
assert len(bridge.sent) >= 1
|
||||
first = json.loads(bridge.sent[0][0])
|
||||
assert "presets" in first and "select" in first
|
||||
assert first["presets"]["__identify"]["p"] == "blink"
|
||||
assert first["presets"]["__identify"]["d"] == 50
|
||||
assert first["select"] == ["__identify"]
|
||||
first = _bridge_sent_envelope(bridge, 0)
|
||||
assert first["v"] == "1"
|
||||
first_body = _device_body_from_envelope(first, dev_id)
|
||||
assert first_body["p"]["__identify"]["p"] == "blink"
|
||||
assert first_body["p"]["__identify"]["d"] == 50
|
||||
assert first_body["s"] == ["__identify"]
|
||||
deadline = time.monotonic() + 2.0
|
||||
while len(bridge.sent) < 2 and time.monotonic() < deadline:
|
||||
time.sleep(0.02)
|
||||
assert len(bridge.sent) >= 2
|
||||
second = json.loads(bridge.sent[1][0])
|
||||
assert second.get("select") == ["off"]
|
||||
second = _bridge_sent_envelope(bridge, 1)
|
||||
second_body = _device_body_from_envelope(second, dev_id)
|
||||
assert second_body["s"] == ["off"]
|
||||
|
||||
resp = c.post(
|
||||
f"{base_url}/devices",
|
||||
@@ -702,7 +745,7 @@ def test_groups_sequences_scenes_palettes_patterns_endpoints(server):
|
||||
|
||||
resp = c.get(f"{base_url}/devices/{wid}")
|
||||
assert resp.status_code == 200
|
||||
assert resp.json().get("connected") is False
|
||||
assert resp.json().get("connected") is None
|
||||
|
||||
resp = c.post(
|
||||
f"{base_url}/devices",
|
||||
|
||||
Reference in New Issue
Block a user