feat(espnow): broadcast delivery with group-filtered routing
Send presets and select on broadcast with groups; unicast only for per-device settings. V1 select as [preset_id, step?]. Sequence steps use beat counts; manual presets get select each beat, auto only on step change. Bridge downlink router, Pi envelope delivery, and tests. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -43,7 +43,7 @@ def test_suppress_next_notify_skips_one_select(monkeypatch):
|
||||
assert delivered == []
|
||||
|
||||
bdr.notify_beat_detected()
|
||||
assert delivered == [(["desk"], "5")]
|
||||
assert delivered == [("5", None)]
|
||||
|
||||
|
||||
def test_suppress_does_not_advance_beat_counter(monkeypatch):
|
||||
@@ -52,8 +52,8 @@ def test_suppress_does_not_advance_beat_counter(monkeypatch):
|
||||
bdr.set_sequence_manual_lane_route(
|
||||
0,
|
||||
["desk"],
|
||||
"42",
|
||||
{"p": "radiate", "a": False, "manual_beat_n": 2},
|
||||
"5",
|
||||
{"p": "chase", "a": False, "manual_beat_n": 2},
|
||||
)
|
||||
bdr.mark_sequence_manual_lane_select_sent(0)
|
||||
|
||||
@@ -61,14 +61,14 @@ def test_suppress_does_not_advance_beat_counter(monkeypatch):
|
||||
assert delivered == []
|
||||
|
||||
bdr.notify_beat_detected()
|
||||
assert delivered == [(["desk"], "42")]
|
||||
assert delivered == [("5", None)]
|
||||
|
||||
delivered.clear()
|
||||
bdr.notify_beat_detected()
|
||||
assert delivered == []
|
||||
|
||||
bdr.notify_beat_detected()
|
||||
assert delivered == [(["desk"], "42")]
|
||||
assert delivered == [("5", None)]
|
||||
|
||||
|
||||
def test_duplicate_lanes_dedupe_to_one_select_per_beat(monkeypatch):
|
||||
@@ -87,19 +87,57 @@ def test_duplicate_lanes_dedupe_to_one_select_per_beat(monkeypatch):
|
||||
bdr._lane_manual[0] = dict(entry)
|
||||
|
||||
bdr.notify_beat_detected()
|
||||
assert delivered == [(["desk"], "42")]
|
||||
assert delivered == [("42", None)]
|
||||
|
||||
|
||||
def test_sequence_lane_manual_delivers_per_beat_select(monkeypatch):
|
||||
delivered = _patch_delivery(monkeypatch)
|
||||
bdr.set_sequence_manual_lane_route(
|
||||
0,
|
||||
["desk"],
|
||||
"42",
|
||||
{"p": "radiate", "a": False, "manual_beat_n": 1},
|
||||
)
|
||||
bdr.notify_beat_detected()
|
||||
assert delivered == [("42", None)]
|
||||
|
||||
|
||||
def test_sequence_auto_lane_skips_per_beat_select(monkeypatch):
|
||||
delivered = _patch_delivery(monkeypatch)
|
||||
bdr.set_sequence_manual_lane_route(
|
||||
0,
|
||||
["desk"],
|
||||
"3",
|
||||
{"p": "colour_cycle", "a": True, "manual_beat_n": 1},
|
||||
)
|
||||
with bdr._route_lock:
|
||||
assert 0 not in bdr._lane_manual
|
||||
bdr.notify_beat_detected()
|
||||
assert delivered == []
|
||||
|
||||
|
||||
def test_sequence_lane_chase_delivers_per_beat_select(monkeypatch):
|
||||
delivered = _patch_delivery(monkeypatch)
|
||||
bdr.set_sequence_manual_lane_route(
|
||||
0,
|
||||
["desk"],
|
||||
"5",
|
||||
{"p": "chase", "a": False, "manual_beat_n": 1},
|
||||
)
|
||||
bdr.notify_beat_detected()
|
||||
assert delivered == [("5", None)]
|
||||
|
||||
|
||||
def test_standalone_overlay_skipped_when_sequence_lane_covers(monkeypatch):
|
||||
delivered = _patch_delivery(monkeypatch)
|
||||
body = {"p": "radiate", "a": False, "manual_beat_n": 1}
|
||||
body = {"p": "chase", "a": False, "manual_beat_n": 1}
|
||||
|
||||
bdr.set_sequence_manual_lane_route(1, ["desk"], "42", body)
|
||||
bdr._apply_manual_beat_route_standalone_overlay(["desk"], "42", body)
|
||||
bdr.set_sequence_manual_lane_route(1, ["desk"], "5", body)
|
||||
bdr._apply_manual_beat_route_standalone_overlay(["desk"], "5", body)
|
||||
|
||||
with bdr._route_lock:
|
||||
assert -1 not in bdr._lane_manual
|
||||
assert 1 in bdr._lane_manual
|
||||
|
||||
bdr.notify_beat_detected()
|
||||
assert delivered == [(["desk"], "42")]
|
||||
assert delivered == [("5", None)]
|
||||
|
||||
Reference in New Issue
Block a user