Patrick Schurig 935cec269f test(config): les deux notes sont MONTÉES, pas seulement calculées
Vérification demandée après le relevé V2C du banc : « ta note de rangs ex æquo doit
s'afficher — vérifie qu'elle le fait ». Elle s'affiche. Mais rien ne le prouvait, et
c'est exactement le défaut qui a coûté isNotGrouped : la contiguïté était calculée
depuis le premier jour, testée en fonction, exposée par le provider — et affichée nulle
part. Un test de fonction ne peut pas voir ça.

Quatre tests de widgets sur la configuration réelle du 2026-08-28
(loadconfig_hems75_v2c.json), montés dans le harnais existant :

  · la note de rangs ex æquo est à l'écran ET nomme les charges (chauffe-eau, V2C
    Trydan) — « des rangs sont à égalité » sans dire lesquelles laisse chercher dans
    cinq cartes ;
  · la note d'ordre entrelacé est à l'écran ET annonce ce que l'enregistrement fera
    (REGROUPERA) — l'annoncer après serait un constat, pas un avertissement ;
  · contrôle négatif : sur un ordre groupé et classé, aucune des deux n'apparaît. Sans
    lui, deux notes toujours affichées deviennent du décor ;
  · THING_MISSING se lit « l'appareil n'existe plus dans nymea » + « réinstallez-le, ou
    retirez cette charge », et n'offre RIEN à lever — ni le bouton, ni l'aide qui
    l'accompagne.

⚠️ La télémétrie du quatrième test est COMPOSÉE, pas capturée : le banc publiait
WRITE_FAILED sur cette charge au dernier relevé (l'adaptateur épuise son échelle
d'écriture avant que THING_MISSING ne sorte). Le test éprouve le rendu du code sur le
loadId réel de la Terra AC supprimée, pas la présence du code sur la box.

Et deux traces de la campagne V2C, qui ne se câblent pas :

· tools/rpc/evcharger_watch.dart entre au dépôt, documenté. C'est la sonde qui a
  produit les deux constats bloquants — une borne hors arbitrage n'apparaît pas dans
  telemetry_watch, et c'est pendant ces transitions qu'il faut la regarder.
· ev_charging_card.dart affirmait que « les deux bornes du banc publient sessionEnergy ».
  Faux depuis l'arrivée de la V2C : elle publie chargeEnergy, remis à zéro à chaque
  interruption de charge. La note renvoie désormais à LoadMechanism et redit C1 de
  LM-1009 — « pas mesurable », jamais zéro.

TODO : entrée d'attente pour sessionEnergy et le renommage currentL1/L2/L3.

146 tests passent, flutter analyze sans remarque nouvelle.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SQbZKrWqsMFP1Lh2jjjd9f
2026-08-28 12:18:00 +02:00

6.9 KiB

TODO — ETM PowerSync App

Ouvert au 2026-08-27

  • 🔴 Bilan JOURNALIER — fait le 2026-08-28. Les quatre tuiles montrent la journée, sous un en-tête « Aujourd'hui » qui le dit une fois. Méthode : différence des compteurs entre minuit local et maintenant, jamais l'intégration des puissances — mesurée contre estimée, 0,8 % d'écart sur .75. Le contrôle qui la valide est l'identité production + soutiré == consommation + injecté, vérifiée exactement sur le banc.

    • Deux bugs d'unité trouvés en chemin : les compteurs total* sont en kWh et le modèle les nommait Wh. L'écran Énergie les divisait donc encore par mille — une journée de 78 kWh s'y lisait « 78 Wh » — et la simulation accumulait des Wh.
    • Vérifié sur appareil contre .75 en lecture seule. Le passage a trouvé quatre libellés tronqués qu'aucun des 138 tests unitaires ne pouvait voir.
  • ❓ « ECS d'abord, batterie ensuite » — à porter au moteur. Demandé le 2026-08-27, et pas exprimable aujourd'hui. batteryLevelConsideration fait l'inverse : il annule le budget sous le seuil, donc la batterie passe avant. La batterie n'est pas dans le waterfall — aucune entrée GetLoadConfig, et enableCharging / chargingRate / enableDischarging n'apparaissent nulle part dans le plugin ETM. Le levier existe pourtant : la classe SunSpec Storage de .75 déclare ces cinq actions. Question : le stockage est-il une charge arbitrable, ou reste-t-il hors du budget ? Une règle Rules.* serait un contournement — deux commandeurs sur la batterie, exactement le défaut que 3g-2 vient de supprimer sur les bornes.

  • Zones de climatisation — cadrage écrit, banc à préparer. Voir docs/CADRAGE_zones_clim.md. Le blocage n'est pas « aucune zone déclarée » : sur les 58 classes de .75, aucune ne porte thermostat, closablesensor, temperaturesensor ni notifications — aucun plugin installé ne sait en créer une. Deux paquets du dépôt apt du banc suffisent (nymea-plugin-generic-heatingcooling, nymea-plugin-generic-sensors). Six décisions à prendre avant de coder.

  • EV_GRID_START / PHASE_LIMIT — éprouvés par test seulement. Les clés ARB sont prêtes, les motifs n'ont jamais été vus sur machine. Signaler la première occurrence réelle. Ne rien bâtir autour d'ici là.

  • ⏳ Deux grandeurs de la V2C attendent le plugin — ne rien câbler d'ici là. Mesuré sur .75 le 2026-08-28, sonde tools/rpc/evcharger_watch.dart.

    • chargeEnergy est exact pendant la charge et remis à zéro à chaque interruption — donc à chaque nuage sur du pilotage par surplus. Le plugin V2C publiera un sessionEnergy construit ; attendre celui-là, et n'accumuler rien côté app. D'ici là, la condition C1 de LM-1009 s'applique en vrai sur cette borne : « pas mesurable » et « rien livré » sont deux états différents, et zéro dit le second.
    • powerL1/L2/L3 sont des ampères mal nommés ; le renommage currentL1/L2/L3 (unité Ampere) est en cours côté plugin. Ne pas les afficher avant son déploiement, et n'écrire aucune conversion côté app — elle survivrait au correctif.
  • EVChargingCard n'est montée par AUCUN écran (constaté le 2026-08-27 — le tableau de bord utilise features/dashboard/widgets/). Soit elle rejoint un écran, soit elle part ; en l'état c'est du code mort qui a l'air vivant.

  • Le passage sur appareil doit devenir une habitude, pas un rattrapage. Il a glissé deux fois, et au premier passage il a trouvé deux cibles tactiles hors norme (26 px, 18 px) qu'aucun des 129 tests unitaires ne pouvait voir. integration_test/ui_3g2_on_device_test.dart est le harnais. Rappel MIUI : la confirmation d'installation est redemandée à chaque fois — faire un adb install -r -t préalable, puis lancer le test.

Charges pilotables — ce qui attend la box (2026-08-26)

  • kCodesReserveBatterie — fait le 2026-08-27. Le motif est publié : BATTERY_RESERVE, params socPercent / reservePercent / withheldW. Les clés que le fichier cherchait (batteryLevel, threshold) n'avaient jamais existé côté plugin — le motif sortait donc en repli anglais sur le seul cas qu'aucune mesure ne révèle.
  • minPowerW == null sans véhicule branché — couvert en test unitaire (test/ev_runtime_test.dart), pas exercé sur appareil : la borne n'entre pas dans loads[] avant 3g. À reprendre quand l'arbitrage prendra la recharge en charge.
  • Réserve batterie — portée élargie. Le jour où le seuil gouverne tout le budget, reprendre le texte de BatteryReserveCard : il annonce aujourd'hui un futur, il devra décrire un présent.
  • Zones — à ne pas entreprendre — décision revue le 2026-08-27 : le lot est cadré (docs/CADRAGE_zones_clim.md), voir l'entrée en tête de ce fichier. ac_screen.dart reste de la donnée fictive — quatre pièces, huit températures crédibles affichées comme des mesures.

En cours / priorité haute

  • TariffProvider — connexion RPC réelle

    • load() appelle encore un Future.delayed fictif
    • Brancher sur nymea JSON-RPC pour récupérer les prix live (ENTSO-E, Tibber, etc.)
  • EnergySetupProvider — persistance

    • Les assignations de rôles (EV, PAC, batterie…) ne survivent pas au redémarrage
    • Sérialiser en SharedPreferences ou JSON local
  • SchedulerProvider — exécution réelle

    • forceRecalc() ne fait rien pour l'instant
    • Brancher sur l'API nymea Energy Scheduler (si disponible)

Screens à implémenter

  • DeveloperScreen — logs, introspection JSON-RPC, test ping nymea
  • AboutScreen — version app, version nymea, licences
  • SystemSettingsScreen — adresse serveur nymea, port, transport (TCP/WS)

Amélioration UX

  • Timeline — remplacer la simulation bell-curve par les vraies créneaux du scheduler nymea
  • RoleConfigFlow Step 3 — test de connexion sur RPC réel au lieu du délai simulé
  • InstallerModeProvider — persister le hash PIN dans SharedPreferences (actuellement en mémoire)
  • AppSettingsProvider — persister les préférences (thème, densité, écrans actifs) dans SharedPreferences

Intégration nymea live

  • Mapping EmsRole → nymea thingClass pour les installations réelles
  • Vérifier les interfaces nymea sur serveur réel (comparer avec docs/nymea_integrations.md)
  • Energy.GetSchedule / Energy.SetSchedule si l'API le supporte

Technique / dette

  • Ajouter des tests unitaires pour TariffProvider et EnergySetupProvider
  • Gérer le cas où NymeaService.thingClasses est vide en mode live (classes non chargées)
  • Revoir _Step1ThingList : passer en context.watch pour réactivité si les things changent