docs(ev): le « Min » de Min+PV ne sert aucun plancher — mesuré, et le plancher est dérivable

Sémantique voulue (Patrick, 2026-09-07) : Min+PV charge toujours au minimum de
la borne, acheté au réseau s'il le faut, et ajoute le surplus par-dessus. 400 W
d'injection sur un plancher de 4 140 W donnent 4 540 W.

Mesuré sur .75, voiture branchée et borne joignable : la borne ne reçoit qu'un
niveau `comfort`, aucun niveau `eco`, décision `SURPLUS_INSUFFICIENT`,
`chargingEnabled: false`. ChargingModeEcoWithMinCurrent se comporte exactement
comme ChargingModeEco.

Le mécanisme existe déjà — `ECO_FLOOR_GRID`, ce que le chauffe-eau fait dans la
même trame : plancher servi, acheté au réseau, compté dans draw.committedW,
surplus distribué au-dessus par comfort. Il n'est pas câblé sur la borne.

Et le blocage noté depuis longtemps (« minCurrent n'existe nulle part ») n'en
est pas un : la valeur est sur la box, dans la classe du Thing —
maxChargingCurrent.minValue = 6 A, phaseCount = 3, soit les 4 140 W attendus.
Aucun champ de contrat à ajouter, et rien à saisir côté app : une limite
matérielle se lit sur le matériel.

Pourquoi ça n'a pas été vu : sur ce banc le surplus n'atteint jamais le
plancher — 0 quart d'heure sur 97 le 2026-09-06, meilleur 2 214 W — donc les
deux modes rendent le même rien et ne se distinguent par aucune observation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw
This commit is contained in:
Patrick Schurig 2026-09-07 10:24:12 +02:00
parent 3710401ad6
commit f2bd07d538
2 changed files with 110 additions and 5 deletions

View File

@ -87,11 +87,34 @@ PV + échéance → ChargingModeEcoWithTargetTime + targetPercentage +
Min+PV + échéance → ChargingModeEcoMinWithTargetTime + targetPercentage + endDateTime
```
> ⚠️ **`minCurrent` n'existe nulle part.** Le mode `ChargingModeEcoWithMinCurrent` est bien
> dans l'énumération, mais `ChargingInfo` ne porte **aucun champ** de courant minimum. Soit
> il est fixé ailleurs (paramètre du Thing borne), soit il manque côté plugin. **Ne pas
> proposer de réglage de courant minimum tant que ce n'est pas tranché** — un champ qui ne
> part nulle part est pire que pas de champ.
> ⚠️ **`minCurrent` n'existe nulle part dans `ChargingInfo`** — et c'est normal : ce n'est
> pas un réglage. **Tranché le 2026-09-07.** Le plancher est une limite MATÉRIELLE, et elle
> est déjà sur la box, dans la classe du Thing borne :
>
> ```jsonc
> // Integrations.GetThingClasses, classe "trydan"
> { "name": "maxChargingCurrent", "minValue": 6, "maxValue": 32, "unit": "UnitAmpere" }
> { "name": "phaseCount", "minValue": 1, "maxValue": 3 } // état courant sur .75 : 3
> ```
>
> `6 A × 3 phases × 230 V = 4 140 W`. Donc **ne jamais proposer de saisir un courant
> minimum** — la règle tient, mais pour une meilleure raison qu'avant : une limite matérielle
> se lit sur le matériel, elle ne se demande pas à l'utilisateur.
>
> 🔴 **Et le mode ne fait rien pour l'instant.** Sémantique voulue (Patrick, 2026-09-07) :
> Min+PV charge **toujours** au minimum de la borne, acheté au réseau s'il le faut, **et
> ajoute le surplus par-dessus** — 400 W d'injection sur un plancher de 4 140 W donnent
> 4 540 W. Mesuré sur `.75` : la borne ne reçoit **qu'un niveau `comfort`**, aucun niveau
> `eco`, et la décision est `SURPLUS_INSUFFICIENT`. `ChargingModeEcoWithMinCurrent` se
> comporte donc **exactement** comme `ChargingModeEco`.
>
> Le mécanisme existe pourtant déjà : c'est `ECO_FLOOR_GRID`, ce que le chauffe-eau fait dans
> la même trame. Demande portée au moteur (`BRIEF_plugin_depuis_maquettes.md`, 2026-09-07).
>
> ⚠️ **Les deux modes sont indiscernables tant que le surplus reste sous le plancher** — à
> l'œil comme à la sonde. Sur `.75` le 2026-09-06, **zéro** quart d'heure sur 97 n'atteint
> 4 140 W (meilleur : 2 214 W). C'est ce qui a permis de croire le mode implémenté : deux
> modes qui rendent le même rien ne se distinguent par aucune observation.
---

View File

@ -2,6 +2,88 @@
---
## 2026-09-07 — `ChargingModeEcoWithMinCurrent` ne sert aucun plancher : le « Min » ne fait rien
**Ce que le mode doit faire, spécifié par Patrick aujourd'hui** : Min+PV charge **toujours**
au minimum de la borne, acheté au réseau s'il le faut, **et ajoute le surplus par-dessus**.
Avec 400 W d'injection, une borne dont le minimum vaut 4 140 W doit charger à **4 540 W**.
**Ce qu'il fait sur `.75`** : rien. Mesuré ce matin, voiture branchée et borne joignable —
```jsonc
// GetChargingInfos
{ "evChargerId": "4d1adafd-…", "chargingMode": "ChargingModeEcoWithMinCurrent",
"chargingState": "ChargingStateIdle" }
// GetLoadTelemetry, la borne
{ "loadId": "{4d1adafd-…}", "allocatedW": 0, "available": true,
"mechanism": { "kind": "evcharger", "chargingEnabled": false, "currentA": 6,
"phaseCount": 3, "pluggedIn": true },
"decision": { "code": "SURPLUS_INSUFFICIENT", "level": "comfort",
"params": { "budgetW": -3 } },
"levels": [ { "level": "comfort", "targetW": 0, "decision": {…} } ] }
```
**Un seul niveau `comfort`, aucun niveau `eco`.** La borne est arbitrée sur le surplus seul :
`ChargingModeEcoWithMinCurrent` se comporte donc **exactement** comme `ChargingModeEco`. Le
mode existe dans l'énumération, il traverse la frontière RPC, il est persisté — et il ne
change aucune décision.
### Le mécanisme existe déjà, il n'est simplement pas câblé sur la borne
Le chauffe-eau, dans la même trame, fait précisément ce qui est demandé :
```jsonc
{ "level": "eco", "targetW": 1071.6,
"decision": { "code": "ECO_FLOOR_GRID", "params": { "gridW": 1072, "regime": "measured", … } },
"counts": { "draw.committedW": 1071.6 } }
```
Un plancher servi, acheté au réseau, compté dans `draw.committedW`, avec le surplus
distribué au-dessus par le niveau `comfort`. **C'est le même objet.** La demande est donc :
donner à une borne en `…WithMinCurrent` (et en `…EcoMinWithTargetTime`) un niveau `eco`
dont la cible est le minimum de la borne.
### Et le plancher n'a besoin d'AUCUN champ de contrat
`minCurrent` n'existe nulle part dans `ChargingInfo`, et c'est noté depuis longtemps chez
moi comme un blocage. **Ce n'en est pas un** : la valeur est déjà sur la box, dans la classe
du Thing.
```jsonc
// Integrations.GetThingClasses, classe "trydan"
{ "name": "maxChargingCurrent", "type": "Double", "minValue": 6, "maxValue": 32,
"unit": "UnitAmpere" }
{ "name": "phaseCount", "minValue": 1, "maxValue": 3 } // état courant : 3
```
`6 A × 3 phases × 230 V = 4 140 W`, exactement le nombre attendu par Patrick. Le moteur
peut donc dériver le plancher de `maxChargingCurrent.minValue × phaseCount` sans qu'aucun
champ nouveau ne traverse la frontière, et sans que l'app ait à saisir quoi que ce soit —
ce qui est le bon partage : une limite matérielle se lit sur le matériel.
### Pourquoi ça se voit maintenant et pas avant
Parce que sur ce banc le surplus n'atteint **jamais** le plancher, donc le mode PV et le mode
Min+PV rendent le même résultat visible — rien. Sur les 97 quarts d'heure du 2026-09-06,
**zéro** dépasse 4 140 W ; le meilleur fait 2 214 W. Tant que le « Min » n'est pas servi, les
deux modes sont indiscernables **à l'œil comme à la sonde**, et c'est ce qui a permis de
croire le mode implémenté.
> Conséquence pour la borne, côté client : elle affiche « désactivé ». Ce n'est pas une
> panne — `optimizerSuspended: true`, le HEMS a pris la main sur l'optimiseur interne V2C et
> la laisse à `chargingEnabled: false`. L'utilisateur voit donc le HEMS éteindre sa borne
> dans le mode censé garantir une charge minimale.
### Une piste séparée, à trancher par vous
La borne simulée expose `desiredPhaseCount`, la V2C non. En monophasé le plancher tomberait à
**1 380 W**, et les 2 214 W du 6 septembre auraient suffi. Si la bascule de phases est
pilotable sur la Trydan, elle change la réponse pour toutes les installations à petit
surplus — mais c'est un autre lot, et je ne l'ouvre pas.
---
## 2026-09-06 — état du banc laissé en place pour le week-end
**Rien écrit par l'app.** L'obligation était déjà posée quand j'ai regardé, et déjà à la