"""Build binary ESP-NOW CMD / GROUP_CMD packets from preset/select data.""" from __future__ import annotations from typing import Any, Dict, List, Optional from util.binary_envelope import pack_binary_envelope_v2 from util.espnow_wire import MAX_ESPNOW_PAYLOAD, pack_cmd, pack_group_cmd def v1_dict_to_cmd_packet(body: Dict[str, Any]) -> bytes: save = bool(body.get("save")) kw: Dict[str, Any] = {} if "presets" in body: kw["presets"] = body["presets"] if "select" in body: kw["select"] = body["select"] if "default" in body: kw["default"] = body["default"] kw["default_targets"] = body.get("targets") if "b" in body: kw["brightness_0_255"] = int(body["b"]) return pack_cmd(pack_binary_envelope_v2(**kw), save=save) def build_preset_cmd_chunks( presets_by_name: Dict[str, Any], *, save: bool = False, default: Optional[str] = None, max_payload: int = MAX_ESPNOW_PAYLOAD, ) -> List[bytes]: """Chunk presets into CMD packets each ≤ max_payload bytes.""" entries = list(presets_by_name.items()) chunks: List[bytes] = [] batch: Dict[str, Any] = {} def _packet_for(presets_map: Dict[str, Any], *, final_save: bool, def_id: Optional[str]): kw: Dict[str, Any] = {"presets": presets_map} if def_id is not None: kw["default"] = def_id return pack_cmd(pack_binary_envelope_v2(**kw), save=final_save) for name, preset_obj in entries: trial = dict(batch) trial[name] = preset_obj try: pkt = _packet_for(trial, final_save=False, def_id=None) except ValueError: pkt = b"\xff\xff" if len(pkt) <= max_payload or not batch: batch = trial else: chunks.append(_packet_for(batch, final_save=False, def_id=None)) batch = {name: preset_obj} if batch: chunks.append( _packet_for(batch, final_save=save, def_id=str(default) if default else None), ) return [c for c in chunks if c and c[0] == 0x4C]