- specs -> docs/ (DASHBOARD_SPEC compagnon du contrat) - ref introspection nymea-jsonRPC -> docs/reference/ - mockups HTML -> docs/mockups/ ; briefs consommés -> docs/archive/ - track AGENTS.md + INTERFACE_etmvariableload.md (étaient untracked) - INTERFACE_*: marqué miroir, canonique = repo plugin
81 lines
4.6 KiB
Markdown
81 lines
4.6 KiB
Markdown
# BRIEF — Agent App · lot **Connexions multi-HEMS** (`etm-powersync-app`)
|
|
|
|
Gestionnaire d'installations : découverte mDNS, liste persistée, bascule, auth par box.
|
|
|
|
> **À lancer APRÈS le lot Rôles & appareils, pas en parallèle.** Ce lot retouche
|
|
> `nymea_service.dart`, la persistance des tokens et le chargement au switch — les fichiers que
|
|
> le lot rôles vient de toucher. Deux agents dessus en même temps = collision.
|
|
|
|
## Fichiers de référence (joints)
|
|
|
|
1. **`installations_mockup.html`** — écrans Installations + Connexion (intention visuelle).
|
|
2. `jsonRpc.txt` — introspect (namespaces `Authentication.*`, mDNS, `System.GetServerUuid`/About).
|
|
|
|
## Modèle (décisions verrouillées)
|
|
|
|
- **Identité stable d'une installation = Server UUID**, jamais l'IP (DHCP → l'IP change).
|
|
Une installation enregistrée = `{ uuid (clé), nom, host, port, token, lastSeen }`.
|
|
- **Une seule connexion active à la fois.** `nymea_service` reste mono-connexion ; un
|
|
**`ConnectionManager`** au-dessus gère la liste + le switch (déconnecte l'active, connecte la
|
|
cible). **Pas** de N sockets parallèles.
|
|
- **Token par UUID.** La persistance actuelle stocke *un* token → passer à un token **par UUID**
|
|
(clé = uuid de la box). En basculant, réutiliser le token de la box cible. C'est le piège
|
|
mono→multi : ne pas réutiliser le token de la box précédente.
|
|
- **Découverte mDNS** (`_nymea._tcp`) **+ ajout manuel** (host/port) en repli. Au scan, matcher
|
|
par **UUID** : box connue → réutiliser son token ; nouvelle → proposer de l'ajouter.
|
|
- **Auth à deux branches**, détectées au handshake : box neuve (pas d'admin) → **créer** un
|
|
utilisateur (`Authentication.CreateUser`) ; box initialisée → **login**
|
|
(`Authentication.Authenticate`). Le segmenteur UI n'est qu'un repli ; la détection est auto.
|
|
|
|
## Transport — attention
|
|
|
|
- En LAN c'est **`ws://IP:4444`** (clair). Le code actuel ne fait **pas** de TLS (`Socket.connect`
|
|
nu, `ws://`). Ne pas coder un champ `wss://` qui ne marche pas encore — le TLS (port 2222
|
|
`nymeas://`) est une dette séparée. Champ « port » par défaut **4444**.
|
|
|
|
## Routage / gate
|
|
|
|
- Condition du gate = **« pas de connexion active »** (≠ « liste vide »).
|
|
- Pas de connexion active au démarrage → **Installations en racine** (plein écran).
|
|
- Connexion active → **dashboard** ; Installations reste accessible.
|
|
- **Réentrée** : le **nom de la box active dans l'en-tête du drawer** (le « Site démo » déjà présent
|
|
sous le logo) devient **cliquable → ouvre Installations** pour basculer. Pas d'entrée de menu
|
|
dédiée à enfouir : l'en-tête du drawer EST l'accès.
|
|
|
|
## Trois états de l'écran Installations
|
|
|
|
1. **Vierge** (liste vide, 1ʳᵉ fois) → découverte mDNS + « Ajouter manuellement » au premier plan.
|
|
2. **Liste sans active** (box connues, aucune connectée) → liste en « hors-ligne », tap = reconnecter.
|
|
3. **Liste avec active** (ouvert depuis le drawer) → une box « actif », les autres pour basculer.
|
|
|
|
Mêmes composants, trois configurations.
|
|
|
|
## Niveaux d'accès (client vs installateur)
|
|
|
|
- **Client / général** : lister + **basculer** entre installations. Pas de déverrouillage requis.
|
|
- **Installateur** (gated) : **ajout manuel**, **créer l'admin**, **supprimer** une installation.
|
|
Mêmes écran ; ces actions grisées/masquées hors mode installateur.
|
|
|
|
## Bascule (switch) — invalidation
|
|
|
|
- Switcher = déconnecter l'active → connecter la cible (token par UUID) → **ré-déclencher le
|
|
chargement** (rôles, things, powerbalance) pour la nouvelle box.
|
|
- **Vider les caches** des écrans (dashboard, rôles, things) au switch : aucune donnée de la box
|
|
précédente ne doit subsister. C'est le vrai risque d'intégration.
|
|
- Transition courte avec le **nom de la box cible** (« Connexion à Client Kutzenhausen… ») avant
|
|
d'atterrir sur le dashboard, pour que l'installateur soit sûr d'être sur la bonne installation.
|
|
|
|
## Hors lot (séparé, plus tard)
|
|
|
|
- **Wizard de commissioning d'une box neuve** (réseau filaire/wifi de nymea:core, façon nymea-app
|
|
écrans 2-3). C'est l'installation d'un système, distinct de « connecter l'app à un HEMS
|
|
existant ». Pas dans ce lot.
|
|
|
|
## Avant de coder
|
|
|
|
Explore le repo (`nymea_service.dart`, `etm_tokens.dart`, `nymea_user.dart`, le drawer, le routeur),
|
|
`flutter analyze`, et **propose un plan ordonné** (modèle installation + persistance par UUID →
|
|
`ConnectionManager` + switch → mDNS → écran Installations 3 états → auth 2 branches → gate/routage →
|
|
en-tête drawer cliquable) **avant** d'écrire. Lis `jsonRpc.txt` pour les signatures `Authentication.*`.
|
|
Ne devine pas.
|