# BRIEF — Agent App (`etm-powersync-app`) Écran **Rôles & appareils** + écran **Configurer une charge pilotée**. ## Fichiers de référence (joints) 1. **`INTERFACE_etmvariableload.md`** — le **contrat**. Source de vérité. 2. **`roles_appareils_mockup.html`** — écran 1 : liste, deux zones, drag-priorité, tri-état. 3. **`config_ecs_mockup.html`** — écran 2 : config Dynamique/Fixe + assistant résistances. > **Règle d'or : le contrat (`.md`) PRIME sur les maquettes.** Les `.html` sont l'intention > visuelle (look, structure, interactions). En cas de conflit entre une maquette et le `.md`, > **le `.md` gagne.** Ne reproduis pas un pixel au détriment d'une décision du contrat. ## ⚠️ La maquette écran 1 est partiellement périmée Elle a été produite avant plusieurs décisions. **Ne la suis pas aveuglément** sur ces 3 points — applique la version ci-dessous : 1. **Paliers ≠ config matérielle.** L'écran 1 affiche les paliers comme une propriété « matériel » de l'ECS. **Faux.** Ce sont une **déclaration** (`powerLevels`), éditée dans l'écran 2. Sur la carte de liste, ne montre qu'un résumé (ex. « 5 paliers · max 2400 W »), pas un éditeur. 2. **Auto-détection solaire/batterie.** Les rôles **inférés** par interface (production solaire, batterie) apparaissent **directement en zone définitive** avec un badge « détecté » — ils ne passent **pas** par « À configurer ». La batterie garde sa carte (priorité + `needs`), mais n'est jamais « à configurer » au sens bloquant. 3. **Compteur `X / 6`.** Comptage : inférés (solaire, batterie) = configurés d'office ; pickés (réseau, EV, ECS, PAC) = comptés quand **assignés** *ou* actés **« Pas d'appareil »**. « Complet » = aucun rôle en non-configuré bloquant. ## Décisions verrouillées (ne pas re-débattre) - **Tri-état par rôle** : `present(thingId)` / `absent({status:"absent"})` / non-configuré (clé absente). Jamais `thingId:null`. - **Trois destinations** : Compteurs (réseau→rootMeter, solaire→détecté) · Charges pilotables (EV/ECS/PAC/batterie, priorisables) · Absent. - **Cycle de vie** : « À configurer » → assigné (remonte dans Compteurs *ou* Charges pilotables selon le rôle) **ou** « Pas d'appareil » (acté absent). Trois états d'écran : vierge (tout à configurer, zones du haut vides + invite) / en cours / complet. - **Drag = priorité.** Réordonner les cartes de charges pilotables écrit `priority` (rang 1 = servi en premier). Les cartes compteur ne sont **pas** draggables. L'ordre est **indicatif** (le scheduler le bouscule sur Tempo rouge / deadline) — le signaler dans l'UI, pas le présenter comme rigide. - **Config charge pilotée** (écran 2) émet un `LoadDescriptor` au format du contrat §3 : `mode` (dynamic|fixed), `powerLevels[]` **ou** `maxPowerW`, `priority`, `enabled`, `needs`. - **Assistant résistances = UI-only.** Il additionne les unités et pré-remplit `powerLevels`, puis disparaît. **Aucune résistance n'est stockée ni envoyée.** Ne calcule la combinatoire **nulle part ailleurs**. ## Plomberie / état du repo - Base de départ fournie : `energy_setup_provider.dart` (modèle tri-état + routage des sinks) est une **intention**, à adapter aux signatures réelles du repo — pas à coller tel quel. - **Persistance = côté plugin**, pas SharedPreferences. L'app appelle `NymeaEnergy.GetLoadConfig` / `SetLoadConfig`. **Ces méthodes n'existent pas encore** → **stub** : logger le JSON du `LoadDescriptor` qui partira, ne rien casser. Le câblage réel arrive quand l'agent energymanager les expose. - `gridMeter` → `Energy.SetRootMeter` (natif, testable contre `hems` maintenant). - **Bug à corriger au passage** : `nymea_service.dart` appelle `EnergyPlugin.SetChargingInfo` → doit être `NymeaEnergy.SetChargingInfo` ; et les champs `ChargingInfo` sont faux (`mode`→`chargingMode`, `targetSoc`→`targetPercentage`, `endTime`→`endDateTime`, `minCurrent` n'existe pas). Réf : introspect `jsonRpc.txt`. ## Périmètre de CE brief Les écrans Rôles & appareils + Configurer charge pilotée **uniquement**. Pas le wizard Things (autre lot), pas Système/Réseau/ModbusRTU (autre lot), pas la decision card. Lis `jsonRpc.txt` (l'introspect) avant tout appel nymea — ne devine pas les signatures.