feat(espnow): improve bridge transport and driver sync

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-28 00:38:09 +12:00
parent 088fe161a8
commit 8403df531d
6 changed files with 49 additions and 11 deletions

8
bulk.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/usr/bin/env bash
PORT="${1:-/dev/ttyACM0}"
while true; do
ls "$PORT" && led-cli -p "$PORT" --erase --src --patterns && led-cli -p "$PORT" --reset -f
sleep 0.5
done

View File

@@ -68,7 +68,7 @@ def process_data(payload, settings, presets, controller_ip=None, save=False):
set_groups = bool(data.get("set_groups"))
groups = data.get("groups")
if set_groups and isinstance(groups, list):
dg.groups_replace(groups)
dg.groups_replace(groups, settings)
print("groups set", dg.list_groups())
elif isinstance(groups, list) and groups:
if not any(dg.in_group(str(g)) for g in groups):
@@ -96,6 +96,7 @@ def process_data(payload, settings, presets, controller_ip=None, save=False):
settings.save()
if "save" in data and "device_config" in data:
settings.save()
_flush_pending_select(settings, presets)
_VALID_DEVICE_COLOR_ORDERS = frozenset({"rgb", "rbg", "grb", "gbr", "brg", "bgr"})
@@ -196,6 +197,18 @@ def _run_select(presets, settings, preset_name, step=None):
return False
def _flush_pending_select(settings, presets):
global _pending_select
if _pending_select is None:
return
preset_name, step = _pending_select
if preset_name not in presets.presets and preset_name not in ("on", "off"):
return
_pending_select = None
if not _run_select(presets, settings, preset_name, step):
print("select failed (pending):", preset_name)
def apply_presets(data, settings, presets):
global _pending_select
presets_map = data["presets"]
@@ -219,13 +232,10 @@ def apply_presets(data, settings, presets):
pass
presets.edit(id, preset_data)
# Same message often carries select; apply now while presets are loaded.
if "select" in data:
if "select" in data or "s" in data:
apply_select(data, settings, presets)
elif _pending_select is not None:
preset_name, step = _pending_select
_pending_select = None
if preset_name in presets.presets or preset_name in ("on", "off"):
_run_select(presets, settings, preset_name, step)
else:
_flush_pending_select(settings, presets)
def _select_list_for_this_device(select_val, settings):
@@ -276,6 +286,11 @@ def apply_select(data, settings, presets):
if not preset_name:
return
step = select_list[1] if len(select_list) > 1 else None
if preset_name not in presets.presets and preset_name not in ("on", "off"):
try:
presets.load(settings)
except Exception:
pass
if preset_name not in presets.presets and preset_name not in ("on", "off"):
_pending_select = (preset_name, step)
print("select deferred (preset not loaded yet):", preset_name)

View File

@@ -1,11 +1,23 @@
"""In-memory group membership for GROUP_CMD filtering."""
"""Group membership for GROUP_CMD filtering; persisted in settings.json."""
_groups = []
def groups_replace(group_ids):
def load_from_settings(settings):
global _groups
g = settings.get("groups") if settings is not None else None
if isinstance(g, list):
_groups = [str(x) for x in g if str(x).strip()]
else:
_groups = []
def groups_replace(group_ids, settings=None, *, persist=True):
global _groups
_groups = [str(g) for g in group_ids]
if persist and settings is not None:
settings["groups"] = list(_groups)
settings.save()
def in_group(group_id):

View File

@@ -112,7 +112,7 @@ def _handle_packet(host, pkt, settings, presets):
if mt == MSG_GROUPS:
ids = parse_groups(pkt)
if ids is not None:
dg.groups_replace(ids)
dg.groups_replace(ids, settings)
_groups_received = True
print("groups", ids)
return

View File

@@ -6,6 +6,7 @@ import gc
import json
import network
import espnow
import device_groups as dg
from presets import Presets
from controller_messages import apply_startup_pattern, process_data
from espnow_transport import _handle_packet, init_espnow
@@ -17,6 +18,7 @@ wdt.feed()
machine.freq(160000000)
settings = Settings()
dg.load_from_settings(settings)
print(settings)
gc.collect()

View File

@@ -35,7 +35,8 @@ class Settings(dict):
self["brightness"] = 32
self["wifi_channel"] = WIFI_CHANNEL_DEFAULT
self["groups"] = []
def save(self):
try: