Skip to content

feat(ambiance): configuration serveur et écran d'administration Éclairage #207

Description

@CCoupel

Contexte

Quatrième issue du milestone v10.0.0. Rend l'éclairage configurable et associable par
l'utilisateur final, sans qu'aucun événement de jeu ne soit encore câblé.

Re-planifiée le 2026-09-03 : la voie BLE est abandonnée (spike #204 — défaut systémique entre
la pile Bluetooth de Windows 11 et les ampoules Hue). L'appairage hors bande par bluetoothctl /
Paramètres Windows qui figurait ici est caduc. La voie retenue est le pont Hue en REST
local
, validée sur matériel réel.

Contrat : contracts/hue-bridge.md §6 et §7.

🎨 Maquette — à valider AVANT tout développement frontend

docs/mockups/lighting-hue-config-207.html

Règle projet : une maquette d'interface est validée par l'utilisateur avant le dispatch de
dev-frontend. Révision 2 (2026-09-03) : la configuration vit désormais dans une page dédiée atteignable
par une entrée « Ambiance » du menu abeille
, et non plus dans une section de /admin/settings.
La maquette couvre les quatre états, les trois étapes du parcours, l'aperçu de ce que #213
ajoutera, les cas dégradés et les décisions de conception.

Révision 3 (2026-09-04) — maquette VALIDÉE, gate UI levé. Les deux points d'arbitrage sont
tranchés et intégrés :

  1. Renommage — la case « Configuration Ambiance » de BackupPage.jsx (chore(admin): game-config.json rattaché au flag history dans backup/restore — checkbox dédiée à envisager #152) devient
    « Réglages de jeu ». Libellé visible seul : la clé de l'option, le paramètre
    ambiance=true de la requête et le format des archives sont inchangés, donc aucune archive
    existante n'est invalidée. (La clé serveur reste lighting.)
  2. Ampoule d'état sur l'entrée de menu « Ambiance », et non la pastille booléenne de
    « Mises à jour ». Révision 4 : trois glyphes distincts, pas une même forme recolorée
    ampoule pleine avec rayons (verte) = pont configuré et qui répond · ampoule en contour +
    pastille d'alerte
    (orange) = pont configuré mais qui ne répond plus, ou qui refuse la clé ·
    ampoule en contour nu (grise) = aucun pont configuré. Correspondance normative des états de
    GET /api/lighting/status en contracts/hue-bridge.md §7.1 ; tracés de référence en §01 de
    la maquette.
    C'est la forme qui porte l'état, la couleur ne fait que renforcer : la distinction reste
    lisible en niveaux de gris et pour un daltonien, là où trois teintes sur une forme unique
    auraient été indiscernables à 15 pixels.
    ⚠️ Ni la couleur ni la forme d'un emoji ne sont pilotables — elles viennent de la police
    système. Les trois glyphes sont donc des SVG en ligne tracés en currentColor.
    Aucune modification du code de rendu du menu : Navbar.jsx écrit déjà
    <span className="menu-icon">{item.icon}</span> et React y accepte un élément comme une
    chaîne — seule la définition de l'entrée change.
    ⚠️ title en toutes lettres malgré tout, SVG aria-hidden : un lecteur d'écran ne voit aucune
    forme.
    Rafraîchissement au montage, toutes les 30 s, et après tout enregistrement — l'endpoint ne
    fait aucune I/O. Le précédent useUpdates (appel unique au montage, Navbar.jsx:87-89) ne
    suffit pas : un pont peut devenir injoignable pendant une session.

Contrainte de déploiement qui simplifie l'écran

Le pont de production sera dédié à BuzzMaster — pas le pont domestique de l'utilisateur. Il n'y
a donc pas de lumières étrangères à filtrer. L'écran propose toutes les ampoules cochées par
défaut
, mais les affiche explicitement et permet de les décocher : on ne suppose jamais en
silence que tout ce qui est sur le pont nous appartient.

Portée

  • Section lighting de config.json (config système), déclarée selon la procédure établie :
    struct + champ dans Config, défauts dans ApplyDefaults, bloc de décodage additif par
    section
    dans handleConfig (internal/server/http.go ~1400-1440).
    ⚠️ Le schéma complet est figé dès cette issue, role: "team" compris (§6 du contrat), même
    si feat(ambiance): configuration serveur et écran d'administration Éclairage #207 n'expose que role: "general". Le casser en feat(ambiance): éclairage différencié par équipe #213 imposerait une migration de
    config.json sur une section livrée quelques jours plus tôt.
    ⚠️ Nommer la section lighting, jamais ambiance : ce mot désigne déjà la catégorie de
    sauvegarde couvrant game-config.json (BackupPage.jsx, chore(admin): game-config.json rattaché au flag history dans backup/restore — checkbox dédiée à envisager #152).
  • La clé du pont est un secret, même régime que les clés IA : masquée dans GET /config.json
    (maskedConfigJSON, http.go:1320), motif « absente ⇒ préservée, clear_api_key ⇒ effacée,
    api_key_configured dérivé jamais persisté », surcharge BUZZCONTROL_HUE_API_KEY sans
    écriture disque
    , jamais journalisée.
    ⚠️ Aucun champ de saisie de clé dans l'écran : elle s'obtient par l'appui sur le bouton du
    pont, pas au clavier. Un champ vide proposerait un geste impossible.
  • Endpoints (§7 du contrat) : POST /api/lighting/discover, POST /api/lighting/register,
    GET /api/lighting/lights, POST /api/lighting/test, GET /api/lighting/status.
    GET /api/lighting/status ne fait aucun appel bloquant — il renvoie l'état connu du pilote.
  • Page dédiée /admin/ambiance, atteignable par une entrée « Ambiance » du menu abeille
    (révision du 2026-09-03 — décision utilisateur). Concrètement :
    • une entrée dans menuItems (web/src/components/Navbar.jsx l. 146-155) :
      { path: 'ambiance', label: 'Ambiance', icon: '💡' }, placée juste après Config ;
    • une entrée dans adminRoutes (web/src/App.jsx l. 27-40) :
      { path: 'ambiance', element: <AmbiancePage /> } — mécanisme de routage existant, rien de neuf ;
    • web/src/pages/AmbiancePage.jsx + .css + .test.jsx, sur le squelette des autres pages
      admin (header.page-header puis une <Card>).
    • ConfigPage.jsx n'est pas modifiée — c'est tout l'objet de la révision.
    • web/src/hooks/useLightingStatus.js — hook sur le modèle de useUpdates.js, alimentant
      l'ampoule du menu.
    • web/src/pages/BackupPage.jsxrenommage du seul libellé « Configuration Ambiance » →
      « Réglages de jeu » (3 occurrences : l. 79, 149, 227). Ne toucher ni la clé ambiance de
      l'objet d'options, ni le paramètre ambiance=true de la requête.
      Le POST de configuration ré-émet toujours la section lighting complète (précédent normatif
      de la section IA : un payload partiel remet les autres champs à leurs défauts).
  • Badge d'état à quatre valeurs : Non configuré / Pont connecté / Pont injoignable /
    Association refusée. Forme reprise du badge tri-état des clés IA (ai-key-badge).
    ⚠️ Ne jamais fondre « injoignable » et « refusée » — les gestes correctifs sont opposés.
  • Parcours d'association en ligne, pas en modale : l'appui sur le bouton du pont est une
    attente temporisée, pas une décision binaire. Le projet ne réserve la modale qu'à l'aide
    statique (ApiKeyHelpModal) et aux décisions bloquantes (ApiKeyValidationDialog) ; il n'existe
    aucun précédent de modale d'attente dans cette page.
    L'erreur « bouton non pressé » (Hue 101) est un cas nominal : l'écran attend et propose de
    réessayer, il ne s'alarme pas.
  • Test d'éclairage par ampoule et global : un flash bref, puis retour à l'état antérieur.
  • À corriger au passage : .wifi-toast-warning n'est défini nulle part dans
    server-go/web/src/ — un toast d'avertissement s'affiche aujourd'hui en texte blanc sur fond
    transparent. Cet écran en a besoin.

Hors portée

Câblage sur les événements de jeu (#205, livré). Affectation par équipe (#213). Conduite manuelle
et restitution d'état (#208).

Critère de fait

  • Maquette validée par l'utilisateur avant le dispatch de dev-frontend.
  • Serveur sans section lighting : démarrage, sauvegarde et rechargement de config.json
    inchangés, aucune découverte réseau, aucune ligne de log. La page /admin/ambiance s'affiche
    quand même, réduite à son bouton « Rechercher un pont ».
  • Aucune régression sur ConfigPage.jsx, qui n'est pas touchée par cette issue.
  • L'ampoule du menu montre les trois glyphes conformément à hue-bridge.md §7.1, et le title
    dit l'état en toutes lettres. Vérifié en niveaux de gris : les trois états restent
    distinguables sans la couleur. Vérifié aussi sans pont configuré : contour nu, sans pastille,
    et aucune apparence d'alerte.
  • BackupPage.jsx : libellé renommé, et une archive produite avant le renommage se
    restaure toujours (le format n'a pas changé).
  • Round-trip de config.json : enregistrer une autre section (IA, serveur) ne détruit ni ne
    vide
    lighting, et réciproquement.
  • Aucun secret dans GET /config.json, dans les logs, ni dans une archive de sauvegarde.
    (Vérifié au cadrage : config.json vit à la racine du serveur, hors du dataDir archivé par
    handleFSBackup — ne pas déplacer la section vers game-config.json.)
  • Clé fournie par BUZZCONTROL_HUE_API_KEY : rien n'est écrit sur disque (précédent explicite,
    docs/TEST_PROCEDURE.md §9 scénario 7).
  • Aucun pont sur le réseau ⇒ message explicite et repli « saisir l'adresse manuellement » ; l'écran
    ne reste jamais à charger indéfiniment.
  • Le bouton « Tester » allume réellement l'ampoule — seul scénario exigeant du matériel.

Dépendances

contracts/hue-bridge.md (écrit). Parallélisable avec #206 : le front travaille depuis le contrat,
et test-writer depuis la maquette.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    backendServeur GobacklogItem du backlog BuzzMasterenhancementNew feature or requestfrontendInterface React

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions