Files
le-mystere-professeur-zacus/docs/esp-now-cmd-contract.md
T
clemsail 0d736459f4
Repo State / repo-state (pull_request) Failing after 31s
Repo State / repo-state (push) Failing after 35s
Validate Zacus refactor / validate (pull_request) Failing after 5m37s
docs(esp-now): structured CMD contract for annex cards (D5 roadmap)
2026-06-14 10:10:00 +02:00

4.8 KiB

Contrat CMD ESP-NOW — cartes annexes Zacus (roadmap)

Statut : design / roadmap (D5 du redesign DSL). Aucun firmware annexe n'implémente encore ce contrat — ce document le spécifie pour que les cartes M5 / BOX-3 / PLIP / p7_coffre le décodent plus tard.

1. État actuel (constaté)

Le master Freenove relaie vers ses pairs ESP-NOW de deux façons :

  • IR de scénario : POST /game/scenario/relay {peers,ir}scenario_mesh_send (chunké, ≤64 KiB, ack 300 ms). Sert à pousser un scénario à une carte.
  • Canal CMD texte : scenario_mesh_send_texttexte libre UTF-8 ≤200 octets, déclenché par POST /game/espnow/cmd {peer, command}. Aujourd'hui le master émet la trame ({ok:true, ESP_OK}) mais aucun executor annexe ne consomme les CMD entrants (elles sont seulement loguées).

Le routage gateway D2 (/v1/media/play, /v1/step/{board}) utilise déjà ce canal en best-effort avec des commandes texte ad-hoc : play:<path>, step:<id>. D5 formalise ce texte ad-hoc en schéma structuré.

2. Schéma CMD structuré

Trame = JSON compact, UTF-8, ≤ 200 octets (limite scenario_mesh_send_text). Forme :

{"op":"<verbe>","a":{<args>}}
  • op : verbe court (≤12 car.).
  • a : objet d'arguments (clés courtes pour tenir dans 200 o). Absent si pas d'argument.
  • Pas d'espaces superflus (séparateurs ,/: compacts). Encodage côté gateway ; décodage côté carte annexe.

Verbes (v1)

op Args (a) Sémantique Carte cible typique
play {"p":"<path>","l":<0|1>} Jouer un média par chemin SD/LittleFS (l=loop) toutes (audio)
stop Stopper l'audio toutes
vol {"v":<0-100>} Volume toutes
step {"s":"<step_id>"} Armer une étape toutes
screen {"t":"<title>","u":"<subtitle>","y":"<symbol>","e":"<effect>"} Afficher une scène LCD M5/BOX-3 (écran)
led {"p":"<pattern>"} Motif LED M5/BOX-3
ring {"d":<sec>} Faire sonner (PLIP) PLIP
evt {"n":"<name>"} Remonter un événement vers le master (sens carte→master) toutes

Exemples (≤200 o)

{"op":"play","a":{"p":"zacus/box3/intro.wav","l":0}}
{"op":"step","a":{"s":"STEP_LEFOU"}}
{"op":"screen","a":{"t":"LABORATOIRE","y":"LA","e":"pulse"}}
{"op":"evt","a":{"n":"solved:1"}}

3. Sens master → carte (CMD) et carte → master (EVT)

  • CMD (master→pair) : émise par le gateway via POST /game/espnow/cmd {peer, command:<json>}. Le master relaie la trame ; la carte annexe décode {op,a} et exécute.
  • EVT (pair→master) : la carte annexe émet {"op":"evt","a":{"n":"<name>"}} ; le master la remonte au gateway (endpoint à définir, p.ex. réutiliser le log CMD/EVT entrant). Les evt (solved:<id>, button:<x>, done) alimentent les transitions réelles (D4) côté gateway : evt n="solved:1" ↔ transition onPuzzleSolved(1) (event_type:unlock, event_name:puzzle:1).

4. Implémentation gateway (présent / futur)

  • Présent (D2) : /v1/media/play et /v1/step/{board} envoient déjà du texte (play:<path>, step:<id>) via /game/espnow/cmd. À migrer vers le JSON structuré ci-dessus (changement local, sans toucher le firmware master).
  • Futur : un endpoint d'EVT entrant (le master expose les CMD/EVT reçues) pour fermer la boucle carte→gateway→transition.

5. Implémentation firmware annexe (futur, hors de ce repo-ci)

Chaque carte annexe (M5 / BOX-3 / PLIP / p7_coffre) doit :

  1. recevoir la trame ESP-NOW texte (callback existant côté master à relayer/exposer) ;
  2. parser le JSON {op,a} (parser compact, tolérant : trame inconnue → ignorée + log) ;
  3. dispatcher sur op vers ses capacités locales (audio I2S, écran, LED, sonnerie…) ;
  4. émettre des evt pour les événements joueur (énigme résolue, bouton…).

Tant que ce firmware n'existe pas, les blocs de la voie 🔬 hardware futur (M5/BOX-3/PLIP, etc.) restent validés mais non exécutés — le compilateur émet le warning « hardware non câblé » (D1), et le routage relais du gateway répond ok:false + warning D5 (cf. /v1/media/play, /v1/step sur une carte annexe).

6. Contraintes & notes

  • Budget 200 o : privilégier des clés courtes (p,s,t,v…). Un screen avec title+subtitle longs peut dépasser → tronquer côté gateway (limites firmware : title≤47, subtitle≤63, symbol≤15) avant émission.
  • Idempotence / ordre : ESP-NOW n'est pas fiable ordonné ; les op doivent être idempotents quand c'est possible (step, screen, vol). Pour les séquences critiques, préférer le push d'IR complet (/game/scenario/relay).
  • Versionnement : si le schéma évolue, ajouter un champ v au niveau racine ({"v":2,"op":...}) ; absence = v1.