Fix G: coupure EDF générique quand l'override EVCS disparaît mi-session
Incident nuit 21-22/08 : la fenêtre HC nuit se ferme pendant que le véhicule est encore en session active (pas encore flag "charge terminée"). L'EVCS relâche correctement son override, mais émet un état transitoire générique (stop_source_lost/idle_wait_source) qu'aucune règle de coupure immédiate du workflow Grid Hysteresis (Fix C/E2) ne reconnaît. EDF restait alors maintenu des heures par la boucle générique jusqu'au seuil statique gridSocOff, plafonnant le MPPT Victron à ~100W et privant la maison de solaire. Nouvelle règle générique (Compute Grid Hysteresis) basée sur evcsGridOverride plutôt que sur une liste blanche de noms de surplus_state — couvre donc aussi tout futur état non énuméré. Garde anti-glitch sur lecture HA invalide. Nouvelle suite tests/golden-hysteresis/ (7 scénarios, première pour ce workflow), câblée bloquante dans tools/n8n-push.mjs. Déployé et validé (golden-hysteresis 7/7, golden EVCS 39/39 inchangé). Écarte le diagnostic incomplet laissé par un autre agent dans HANDOFF.md (edf_general_ok_off côté EVCS aurait créé un deuxième écrivain non coordonné sur le même switch). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
133
HANDOFF.md
133
HANDOFF.md
@@ -1109,5 +1109,136 @@ p11-changement-vehicule-nuit (prev=night_recovery_done_idle + charging_time 15s
|
||||
2. CHANGEMENT DE VÉHICULE / nouvelle connexion (charging_time ≤ 90 s, P11) ;
|
||||
3. force_charge_now / force_grid_now (échappatoires manuelles).
|
||||
|
||||
## Diagnostic en attente de vérification (Qwen, 22/08)
|
||||
Voici mon analyse et plan de correction :
|
||||
Diagnostic
|
||||
Le bug est dans HA_SERVICE_CALLS_OUTPUT.js:987-996 :
|
||||
edf_general_ok_on: {
|
||||
execute: ['grid_forced', 'grid_hc_allowed'].includes(context.sourceMode) && !parsed.gridAvailable,
|
||||
...
|
||||
}
|
||||
Il n'existe pas de edf_general_ok_off. Le workflow ne coupe JAMAIS activement EDF. Il ne fait que le rallumer quand sourceMode est grid ET que le réseau n'est pas encore disponible. Quand sourceMode revient à solar_only/blocked, le switch reste ON dans l'état qu'il avait.
|
||||
Conséquence : après la fenêtre HC nocturne (~06:00), EDF reste allumé. La présence du réseau bloque la production PV (Victron plafonne à ~100 W). Le débranchement du véhicule résout parce que c'est le seul mécanisme qui coupe physiquement le switch.
|
||||
Plan de correction
|
||||
Fichier : src/nodes/HA_SERVICE_CALLS_OUTPUT.js
|
||||
Ajouter un call edf_general_ok_off juste après edf_general_ok_on (ligne 996) :
|
||||
edf_general_ok_off: {
|
||||
execute:
|
||||
!['grid_forced', 'grid_hc_allowed'].includes(context.sourceMode) &&
|
||||
parsed.gridAvailable &parsed.evcsVehicle
|
||||
|
||||
**Verdict (Claude, 22/08) : diagnostic ÉCARTÉ, voir §24 ci-dessous.** Le
|
||||
symptôme est correctement identifié (EDF ne se coupe jamais activement après
|
||||
la fenêtre HC) mais la cause et le correctif proposés sont faux : le bug n'est
|
||||
pas dans `HA_SERVICE_CALLS_OUTPUT.js` (qui n'a jamais eu vocation à couper EDF
|
||||
— la coupure est le rôle exclusif du workflow séparé "Victron - Battery / Grid
|
||||
Hysteresis Fix V1"), et ajouter un `edf_general_ok_off` côté EVCS créerait un
|
||||
deuxième écrivain non coordonné sur `switch.edf_general_ok_switch` (courses
|
||||
30s/1min entre les deux workflows, le hysteresis reprenant la main au cycle
|
||||
suivant via son propre `latchIsOn` et rallumant probablement EDF quand même).
|
||||
Le vrai bug et son correctif (Fix G, côté hystérésis) sont documentés en §24.
|
||||
|
||||
---
|
||||
*Document mis à jour le : 12/08/2026 (~05:05) — P11 déployé et validé live, golden 39/39*
|
||||
*Document mis à jour le : 22/08/2026 (~18:00) — Fix G déployé (hystérésis), diagnostic Qwen écarté, golden-hysteresis 7/7*
|
||||
|
||||
## 24. Session du 22/08/2026 — Fix G : coupure EDF quand l'override EVCS disparaît mi-session (hystérésis)
|
||||
|
||||
### Incident (nuit 21-22/08)
|
||||
Le takeover nuit (P7) a correctement rechargé la batterie à ~35 % via EDF.
|
||||
Quand la fenêtre HC s'est fermée (~06:00-07:24) avec le véhicule **encore
|
||||
branché en session active** (pas encore flag "charge terminée"), EDF est resté
|
||||
allumé — le réseau a plafonné le MPPT Victron à ~100 W, privant la maison de
|
||||
600-4000 W de solaire disponible (elle tirait ~1000 W d'EDF). Seul le
|
||||
débranchement du véhicule a libéré EDF (2179 W de PV immédiatement après).
|
||||
|
||||
### Root cause
|
||||
Côté EVCS (`WINDOWS_SOURCEV2.js`/`DECISION_ENGINEV2.js`) : **pas le bug**.
|
||||
Chaque cycle, `nightSessionActive` et tout le moteur nuit sont activement
|
||||
recalculés à `false`/`'blocked'` dès la fermeture de fenêtre — `helper
|
||||
night_grid_takeover_needed` passe à `off` et `source_mode` à `'Bloqué'`
|
||||
correctement et immédiatement, même mi-session. MAIS les deux branches
|
||||
"collantes" de fin de session (Fix F, exige `profile === 'night_hc'` ; P10
|
||||
`day_vehicle_full_idle`, exige que le `surplus_state` précédent soit déjà un
|
||||
pattern "terminé") ne se déclenchent PAS sur le cycle exact où la fenêtre se
|
||||
ferme mi-session non-terminée. Le système retombe sur des états génériques
|
||||
transitoires (`stop_source_lost` puis `idle_wait_source`).
|
||||
|
||||
Côté **Grid Hysteresis** (`workflows/victron-grid-hysteresis-v1.json`, node
|
||||
"Compute Grid Hysteresis") : **c'est là le bug**. Les règles de coupure
|
||||
immédiate existantes (Fix C `turn_off_vehicle_unplugged`, Fix E2
|
||||
`turn_off_recovery_done`) ne matchent que des noms exacts de `surplus_state`
|
||||
(`vehicle_not_connected`, `night_recovery_done_idle`, `departure_done_idle`) —
|
||||
aucune ne matche `stop_source_lost`/`idle_wait_source` (ni `day_vehicle_full_idle`
|
||||
lui-même). Sans matche, le code retombe sur la boucle générique qui maintient
|
||||
EDF jusqu'au seuil statique `grid_soc_off` (35 %, `input_number.victron_grid_soc_off`),
|
||||
totalement découplé de la cible dynamique de l'EVCS — potentiellement des
|
||||
heures, d'autant qu'EDF-ON lui-même bride la recharge solaire organique.
|
||||
|
||||
### Fix G (déployé 22/08 ~18:00, golden-hysteresis 7/7)
|
||||
Au lieu d'ajouter encore un nom d'état à une liste blanche fragile, nouvelle
|
||||
règle **générique** dans "Compute Grid Hysteresis", basée sur `evcsGridOverride`
|
||||
(déjà fiable) plutôt que sur le nom de `surplus_state` — couvre donc aussi
|
||||
automatiquement tout futur nom d'état non énuméré :
|
||||
```javascript
|
||||
if (
|
||||
!forcedCut && latchIsOn && gridIsOn &&
|
||||
!evcsGridOverride &&
|
||||
soc > gridSocOn && // 22%, PAS gridSocOff 35% — protège le cas
|
||||
// indépendant "SOC bas" qui doit tenir
|
||||
// jusqu'à gridSocOff
|
||||
evcsSourceModeLooksValid // garde anti-glitch (lecture HA vide/
|
||||
// unavailable/unknown → pas d'action)
|
||||
) {
|
||||
desiredGrid = 'off'; desiredLatch = 'off';
|
||||
state = 'turn_off_evcs_override_released';
|
||||
forcedCut = true;
|
||||
}
|
||||
```
|
||||
Coupure immédiate, bypass min_on (25 min), comme Fix C/E2. Décision validée
|
||||
avec l'utilisateur : vitesse de libération prioritaire sur le risque résiduel
|
||||
(un glitch de lecture HA sur un seul cycle pourrait causer une coupure/
|
||||
rallumage isolé, auto-diagnosticable dans le logbook — pas de chatter soutenu
|
||||
car il faudrait une lecture fausse à *chaque* cycle).
|
||||
|
||||
### Nouvelle suite de tests : `tests/golden-hysteresis/` (7 scénarios, première
|
||||
suite pour ce workflow — 0 → 7)
|
||||
`g-incident-gap-mid-session`/`g-incident-gap-idle-wait-source` (les deux noms
|
||||
d'état zombies de l'incident, min_on non écoulé) · `g-incident-replay-hc-boundary`
|
||||
(rejeu complet, min_on déjà écoulé aussi — prouve que ce n'est pas seulement un
|
||||
bypass min_on) · `g-baseline-low-soc-no-override` (garde non-régression : SOC
|
||||
bas indépendant doit continuer à tenir) · `g-regression-fixc-unplugged` /
|
||||
`g-regression-fixe2-recovery-done` (Fix C/E2 toujours prioritaires, pas
|
||||
absorbés par Fix G) · `g-glitch-guard-unavailable` (garde anti-glitch).
|
||||
Lancée AVANT patch : 3 échecs (les scénarios d'incident, stuck sur
|
||||
`hold_on_min_runtime`/`hold_on_until_soc_off`) + 4 succès (gardes déjà bonnes)
|
||||
— confirme que le harnais détecte vraiment le bug. Après patch : 7/7.
|
||||
Câblée dans `tools/n8n-push.mjs` (nouveau `isHysteresisWorkflow`), bloquante
|
||||
au push comme les 2 autres workflows.
|
||||
|
||||
### Outillage
|
||||
`tools/patch-20260822-g-override-released-cut.mjs` (rejouable, même patron que
|
||||
`patch-20260809-e2-recovery-done-cut.mjs`) · `tests/golden-hysteresis/{fixture-snapshot.json,run.mjs,scenarios.mjs}`.
|
||||
|
||||
### Déploiement
|
||||
`node tools/n8n-push.mjs workflows/victron-grid-hysteresis-v1.json` → backup
|
||||
serveur auto (`modified/prepush-7iIlu7LLTW7TZA8o-*.json`) → syntaxe OK →
|
||||
golden-hysteresis 7/7 → PUT OK. `grid_min_on_minutes` réel vérifié via MCP
|
||||
`ha-get-state` avant de figer le fixture : **25** (pas le fallback 45 du code).
|
||||
|
||||
### Hors périmètre (volontairement)
|
||||
Aucun changement côté `src/nodes/*` (EVCS V2.6) — le fix est entièrement côté
|
||||
hystérésis. Amélioration cosmétique future possible, non incluse ici :
|
||||
remplacer les noms zombies `stop_source_lost`/`idle_wait_source` par un état de
|
||||
transition dédié pour la lisibilité dashboard/logbook.
|
||||
|
||||
### À surveiller (prochaine fermeture de fenêtre HC avec véhicule encore
|
||||
branché mi-session)
|
||||
1. Logbook doit montrer `turn_off_evcs_override_released` peu après la
|
||||
fermeture de fenêtre si le véhicule n'est pas encore flag "terminé" ;
|
||||
2. La PV doit remonter (MPPT non-plafonné) immédiatement après ;
|
||||
3. Aucune coupure/rallumage répété (`turn_off_evcs_override_released` suivi de
|
||||
près par `turn_on_evcs_override` répétitivement) — signe d'un glitch de
|
||||
lecture HA à investiguer si observé.
|
||||
|
||||
---
|
||||
*Document mis à jour le : 22/08/2026 (~18:05) — Fix G déployé et validé (syntaxe + golden-hysteresis 7/7 + PUT OK), à confirmer en conditions réelles à la prochaine fermeture de fenêtre HC mi-session
|
||||
|
||||
Reference in New Issue
Block a user