docs(recap): la journée du 2026-08-26 — trois recalages de contrat, et la réserve batterie
Le fil conducteur des six commits du jour tient en une phrase : l'app ne recalcule pas ce que la box publie, et n'anticipe pas ce qu'elle n'a pas encore publié. Le point à retenir est le seuil de réserve batterie : 0,9 en usine, batterie du banc à 50 %. Quand la règle montera dans le budget, `.75` ne pilotera plus rien par grand soleil, sans erreur ni panne. Le RECAP le dit, et le TODO garde les trois crochets laissés ouverts — dont le `Set` volontairement vide qui attend le code du moteur. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HajXLUczEyZd22JeewRfff
This commit is contained in:
parent
801ba15094
commit
c1af47476d
110
RECAP.md
110
RECAP.md
@ -1,8 +1,112 @@
|
||||
# RECAP — etm-powersync-app · reprise de session
|
||||
|
||||
> **Session 2026-08-25.** Branche **`feature/beta-add-config`**, **poussée**.
|
||||
> La section « État au 2026-06-30 » plus bas reste valable pour tout ce qu'elle décrit.
|
||||
> La **soirée du 25** (lot C) est en tête ci-dessous ; le reste de la journée suit.
|
||||
> **Session 2026-08-26.** Branche **`feature/beta-add-config`**, **poussée** (`801ba15`).
|
||||
> La journée du **26** est en tête ci-dessous ; la soirée du **25** (lot C) suit ; la section
|
||||
> « État au 2026-06-30 » plus bas reste valable pour tout ce qu'elle décrit.
|
||||
|
||||
---
|
||||
|
||||
## Journée 2026-08-26 — se recaler sur la box, trois fois de suite
|
||||
|
||||
La box a bougé trois fois dans la journée (`+etm16`, `+etm19`, puis `3g`). Le fil conducteur
|
||||
de tout ce qui suit tient en une phrase : **l'app ne recalcule pas ce que la box publie, et
|
||||
n'anticipe pas ce qu'elle n'a pas encore publié.**
|
||||
|
||||
| Commit | Contenu |
|
||||
|---|---|
|
||||
| `aada8e2` | Les 4 points ouverts du RECAP : glissement, sélecteur de mécanisme, chip de domaine, thème |
|
||||
| `7089148` | Le harnais vérifie lui-même le chip et l'écran de mécanisme |
|
||||
| `cd76df3` | **`+etm16`** — table de paliers, `stagesW`, compteur et sonde |
|
||||
| `ab2a27b` | **`+etm19`** — `BELOW_MIN_POWER`, compteurs rattachés depuis l'écran, glissement exercé |
|
||||
| `449c6ac` | **`3g`** — les valeurs de borne sont du RUNTIME |
|
||||
| `801ba15` | **`3g`** — la réserve batterie sort de l'usine |
|
||||
|
||||
### Ce qui a été corrigé, et pourquoi ça avait échoué
|
||||
|
||||
- **Le glissement ne marchait pas** — et c'était ma régression : j'avais imbriqué un
|
||||
`ReorderableListView` dans un autre, les deux se disputaient le geste. Le classement est
|
||||
désormais **inversé à dessein** : on glisse les *domaines*, et les flèches ordonnent *dans*
|
||||
un domaine. Restait une **zone morte de 3 px** dans la poignée : `ReorderableDragStartListener`
|
||||
délègue le test de toucher à ses enfants, un `Container` transparent la referme.
|
||||
- **Le test du glissement déclarait forfait** deux fois sur trois : le banc revient
|
||||
régulièrement à une charge par domaine, et sans domaine partagé il n'y a rien à glisser. Le
|
||||
test **pose maintenant sa propre condition** — il regroupe, exerce, puis rend le classement
|
||||
d'origine. Un test qui dépend de l'état du terrain ne teste rien.
|
||||
- **« la config du rootmeter est perdue »** — elle ne l'était pas : la box l'avait toujours,
|
||||
l'app ne la **lisait** jamais (`syncRootMeter()`). Le symptôme et la cause étaient à deux
|
||||
écrans de distance.
|
||||
- **`/energy/setup` est gardé par le mode installateur** : le routeur renvoyait ailleurs, et le
|
||||
symptôme affiché était « aucune charge lue ». Le harnais déverrouille au PIN `1234` et
|
||||
**reverrouille après** le maintien d'écran — l'ordre inverse passait au vert en montrant le
|
||||
tableau de bord.
|
||||
|
||||
### Les trois recalages de contrat
|
||||
|
||||
**`+etm16` — ce que la box compare vraiment.** `sameHardware()` est public, et la comparaison
|
||||
porte sur la **table de paliers**, pas sur la liste de relais : réordonner `relays[]` ne
|
||||
reconstruit plus rien (vérifié au banc — « 2 inchangée(s) », aucun état sûr). Mon premier
|
||||
miroir comparait des listes et criait au loup ; corrigé après lecture de
|
||||
`RelayStageTable::operator==` — chaque combinaison se compare **comme un ensemble**, mais les
|
||||
paliers s'apparient par position. Les paliers dérivés arrivent maintenant en `stagesW` : un
|
||||
miroir de moins à faire diverger. Les trois champs optionnels (`meterThingId`, `sensorThingId`,
|
||||
plancher) sont traités **comme un seul objet**, grisage dérivé du schéma, jamais anticipés dans
|
||||
le modèle.
|
||||
|
||||
**`+etm19` — `BELOW_MIN_POWER`.** Deux variantes, à distinguer de `SURPLUS_INSUFFICIENT` et
|
||||
`SG_NORMAL` qui ne se déclenchent plus que sur budget ≤ 0. Le repli aurait tenu : un code
|
||||
inconnu n'a jamais affiché de vide.
|
||||
|
||||
**`3g` — deux valeurs de runtime, et un réglage qui change de portée.** « Minimum » désigne
|
||||
deux objets différents : le **plancher déclaré** d'une charge modulable (une propriété de
|
||||
l'appareil, qui se règle) et le **minimum d'une borne**, `max(borne, voiture)`, qui dépend du
|
||||
véhicule branché et du nombre de phases — de l'ordre de 1,4 kW en monophasé contre 4,1 kW en
|
||||
triphasé, **pour le même courant**. L'app affiche la valeur telle que la box la donne : aucune
|
||||
conversion côté app, sinon il faudrait deviner laquelle des deux règles s'applique. Et le
|
||||
budget **ne se partage pas** entre bornes : aujourd'hui chacune reçoit l'enveloppe entière.
|
||||
|
||||
### La réserve batterie — le point à retenir de la journée
|
||||
|
||||
`batteryLevelConsideration` vaut **0,9** en usine. Le banc `.75` a sa batterie à **50 %** : le
|
||||
seuil est au-dessus de ce que la batterie atteint. Aujourd'hui ça ne gèle que la recharge du
|
||||
véhicule ; **quand la règle montera dans le budget, `.75` ne pilotera plus rien** — ni ECS, ni
|
||||
PAC, ni bornes — par grand soleil, sans erreur ni panne, rien à lire dans un journal.
|
||||
|
||||
Un paramètre qui peut produire ce symptôme n'est pas un paramètre d'usine.
|
||||
`BatteryReserveCard` le lit, l'écrit, **alerte quand le seuil dépasse le SOC réellement
|
||||
atteint**, et dit la portée à venir : régler ce seuil « pour la voiture » couperait le reste
|
||||
demain. Elle n'invente aucun défaut — box muette, carte muette.
|
||||
|
||||
Le motif d'arbitrage est **préparé, pas anticipé** : la clé ARB `decisionBatteryReserve` existe
|
||||
et `kCodesReserveBatterie` est un `Set` **volontairement vide** dans `telemetry_text.dart`. Le
|
||||
crochet attend le code que publiera le moteur ; deviner son nom aurait produit un affichage qui
|
||||
ne se déclenche jamais.
|
||||
|
||||
### Vérifié sur l'appareil, contre `.75`
|
||||
|
||||
Campagne verte, zéro exception. La notification précède l'accusé (4/4 écritures).
|
||||
`enabled:false` ouvre bien les contacts (ECS-413). Les deux compteurs **PAC-Meter** et
|
||||
**ECS-Meter** sont rattachés **depuis l'écran**, et `measuredW` est désormais **distinct** par
|
||||
charge — chauffe-eau 1 500 W, PAC 800 W, cette dernière affichant « Mesuré 800 W · sous la
|
||||
consigne » face à son estimation de 3 000 W.
|
||||
|
||||
> Deux pièges de méthode, notés parce qu'ils se représenteront :
|
||||
> j'ai d'abord **affirmé des `measuredW` distincts** pour prouver le rattachement — deux
|
||||
> compteurs au repos lisent légitimement 0,0 W tous les deux ; l'assertion porte maintenant sur
|
||||
> des `meterThingId` distincts plus un détachement montrant `null` ≠ 0. Et une assertion
|
||||
> cherchait les cartes **sans faire défiler** : dans un `ListView`, ce qui n'est pas à l'écran
|
||||
> n'est pas construit — elle ne prouvait que la hauteur de l'écran.
|
||||
|
||||
### Reste ouvert
|
||||
|
||||
- `minPowerW == null` **sans véhicule branché** : pas exercé sur appareil, la borne n'entre pas
|
||||
dans `loads[]` avant `3g`.
|
||||
- `kCodesReserveBatterie` à câbler quand le moteur publiera le code du motif.
|
||||
- **Les zones** (`ac_screen.dart` est encore de la donnée fictive, `.75` n'en déclare aucune) —
|
||||
explicitement **à ne pas entreprendre**.
|
||||
|
||||
---
|
||||
|
||||
## Soirée 2026-08-25 — LOT C (ci-dessous)
|
||||
|
||||
---
|
||||
|
||||
|
||||
15
TODO.md
15
TODO.md
@ -1,5 +1,20 @@
|
||||
# TODO — ETM PowerSync App
|
||||
|
||||
## Charges pilotables — ce qui attend la box (2026-08-26)
|
||||
|
||||
- [ ] **`kCodesReserveBatterie`** — le `Set` est volontairement VIDE dans
|
||||
`lib/services/telemetry_text.dart`. Y mettre le code du motif « budget annulé par la réserve
|
||||
batterie » **quand le moteur le publiera**, pas avant : deviner son nom produirait un
|
||||
affichage qui ne se déclenche jamais.
|
||||
- [ ] **`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~~ — `ac_screen.dart` est de la donnée fictive et `.75` n'en déclare aucune.
|
||||
**Décidé : à ne pas entreprendre.**
|
||||
|
||||
## En cours / priorité haute
|
||||
|
||||
- [ ] **TariffProvider — connexion RPC réelle**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user