RECAP.md porte les neuf commits du jour et les trois défauts que seul l'appareil a montrés : deux cibles tactiles hors norme (26 px, 18 px), et une correction naïve laide que le test validait — c'est la capture qui a tranché, pas l'assertion. Ce qui manquait dans le suivi, et qui est écrit noir sur blanc : AUCUN BILAN JOURNALIER N'EXISTE DANS L'APP. Les quatre tuiles du tableau de bord mêlent deux natures de grandeur, et aucune n'est journalière — Autoconsommation et Autonomie sont des pourcentages instantanés, Vers réseau et Depuis réseau des kWh cumulés depuis l'origine. Les deux dernières portaient « aujourd'hui » : totalReturn n'est pas remis à zéro chaque nuit, d'où le « · cumulé ». Le bilan du jour reste à écrire, et le TODO porte les trois pièges de sa mise en œuvre — bornes à minuit local, clés de log SANS le préfixe currentPower, et les cumulés corrompus de .75. Et la question ouverte au moteur, telle qu'elle s'est posée : « ECS d'abord, batterie ensuite » n'est pas exprimable aujourd'hui, et batteryLevelConsideration fait l'inverse — il annule le budget SOUS le seuil, donc la batterie passe avant. La cause est structurelle : la batterie n'est dans aucun GetLoadConfig et le plugin ne la commande nulle part. Le levier existe pourtant, la classe SunSpec Storage de .75 déclare enableCharging, chargingRate et enableDischarging. Deux entrées du TODO étaient devenues fausses : kCodesReserveBatterie est fait, et « Zones — à ne pas entreprendre » est revu puisque le lot est cadré. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016vrTVifar2GN5rtUh89Wkq
106 lines
6.3 KiB
Markdown
106 lines
6.3 KiB
Markdown
# TODO — ETM PowerSync App
|
|
|
|
## Ouvert au 2026-08-27
|
|
|
|
- [ ] 🔴 **Bilan JOURNALIER — il n'en existe aucun dans l'app.** Les quatre tuiles du
|
|
tableau de bord (`features/dashboard/widgets/kpi_row.dart`) mêlent deux natures de
|
|
grandeur, et aucune n'est journalière : *Autoconsommation* et *Autonomie* sont des
|
|
**pourcentages instantanés**, *Vers réseau* et *Depuis réseau* des **kWh cumulés depuis
|
|
l'origine** — `totalReturn` / `totalAcquisition` ne sont pas remis à zéro chaque nuit.
|
|
Le libellé disait « aujourd'hui » ; il porte « · cumulé » depuis, mais **le bilan du jour
|
|
reste à écrire**.
|
|
- il passe par `Energy.GetPowerBalanceLogs` avec des bornes à **minuit local**, jamais par
|
|
les totaux de `GetPowerBalance` ;
|
|
- piège vérifié : les entrées de log portent `production` / `consumption` / `acquisition`
|
|
/ `storage`, **sans** le préfixe `currentPower` de `GetPowerBalance`. Réutiliser les
|
|
mauvaises clés ne produit **aucune erreur** — tout tombe sur `0` ;
|
|
- `.75` publie des cumulés corrompus (9,1e+33 kWh exportés) : `EnergyData.isPlausibleKwh`
|
|
existe pour ça, ne pas le contourner.
|
|
|
|
- [ ] ❓ **« 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à.
|
|
|
|
- [ ] **`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)
|
|
|
|
- [x] ~~**`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
|