diff --git a/MEMORY.md b/MEMORY.md index 5d925dd..adbbce7 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -170,3 +170,23 @@ Le problème documenté concernait le **même état mais l'après-midi avec véh *Document créé par l'IA le : 13/06/2026* *Session précédente terminée : sauvegarde mémoire pour session suivante.* + +--- + +## 8. Mise à jour du 09/08/2026 (voir HANDOFF §17-21 pour le détail) + +⚠ La section 4 ci-dessus (decoupesurplus/) est OBSOLÈTE depuis R2 : +la source de vérité est **src/nodes/*.js** + `tools/n8n-push.mjs` (build + +golden 33 scénarios bloquants + backup + PUT). Voir MANUEL_COMPLET §13.1. + +État du système : +- Fixes anti-rebond EDF **A→F** déployés (états collants night_recovery_done_idle + / departure_done_idle, coupures immédiates hystérésis, mémoire prioritaire + sur les gardes) — incidents des nuits 07-09/08 résolus. +- **Conseiller IA** : mode ombre (workflow tdfInZns7cqo8fU2, 15 min) + + premier câblage réel = cible SOC matin (toggle evcs_advisor_apply_night_target). +- **P9** : charge réseau avant départ hors HC (toggle allow_grid_departure_urgent) + + sélecteur véhicule VW (départ 08:50) / JEEP (départ 06:30). +- Workflow hystérésis suivi en local : workflows/victron-grid-hysteresis-v1.json. + +*Mis à jour le : 09/08/2026* diff --git a/docs/MANUEL_COMPLET.md b/docs/MANUEL_COMPLET.md index 390ae68..bbcf2f2 100644 --- a/docs/MANUEL_COMPLET.md +++ b/docs/MANUEL_COMPLET.md @@ -1,6 +1,7 @@ # Manuel Utilisateur - Système EVCS Solaire -> Document généré le 17/07/2026 +> Document généré le 17/07/2026 — dernière mise à jour le 09/08/2026 +> (fixes anti-rebond A→F, câblage advisor cible SOC, P9 départ, véhicules VW/JEEP) > Projet: n8n / Home Assistant / EVCS Solaire sans injection réseau --- @@ -180,13 +181,32 @@ | Entity ID | Type | Description | |---|---|---| | `input_select.victron_evcs_strategy` | select | Stratégie (auto_solar_plus, force_grid_now, etc.) | +| `input_select.victron_evcs_vehicle` | select | **Véhicule branché : VW ou JEEP** (09/08/2026, à sélectionner au branchement) | | `input_number.victron_evcs_required_energy_kwh` | number | Énergie demandée (kWh) | | `input_boolean.victron_evcs_departure_priority_enabled` | boolean | Priorité départ | -| `input_datetime.victron_evcs_departure_time` | datetime | Heure de départ | -| `input_boolean.victron_evcs_allow_grid_hc_night` | boolean | Réseau HC nuit | +| `input_datetime.victron_evcs_departure_time` | datetime | Heure de départ **VW** (~08:50) | +| `input_datetime.victron_evcs_departure_time_jeep` | datetime | Heure de départ **JEEP** (~06:30) | +| `input_boolean.victron_evcs_allow_grid_departure_urgent` | boolean | **P9 : réseau avant départ hors HC** (fenêtre 120 min) | +| `input_boolean.victron_evcs_allow_grid_hc_night` | boolean | Réseau HC nuit (P7) | | `input_boolean.victron_evcs_allow_grid_hc_midday` | boolean | Réseau HC midi | | `input_boolean.victron_evcs_surplus_auto_enabled` | boolean | Contrôleur surplus actif | +Package : `/mnt/ARCH3/docker/HA/packages/victron_evcs_vehicles.yaml` (sélecteur, +départ JEEP, toggle P9). NB : `input_select.victron_evcs_target_vehicle` +(None/Jeep/Zero) est un ancien helper UI non câblé — ne pas l'utiliser. + +### 6.1bis Conseiller IA (advisor) + +| Entity ID | Type | Description | +|---|---|---| +| `input_boolean.evcs_advisor_enabled` | boolean | Kill-switch : l'advisor tourne (15 min) et écrit ses recommandations | +| `input_boolean.evcs_advisor_apply_night_target` | boolean | **CÂBLAGE RÉEL** : la cible SOC matin suit l'advisor (bornes 22-90, statut ok, fraîcheur ≤ 120 min) | +| `input_number.evcs_advisor_night_target_soc` | number | Cible SOC matin recommandée | +| `input_text.evcs_advisor_strategy` / `_reason` / `_status` / `_divergence` / `_last_run` / `_model` | text | Détail des recommandations (cartes + historique) | +| `input_number.evcs_advisor_agree_count` / `_diverge_count` | number | Compteurs accord/divergence vs réel | + +Package : `/mnt/ARCH3/docker/HA/packages/evcs_advisor_shadow.yaml`. + ### 6.2 État système | Entity ID | Type | Description | @@ -322,29 +342,48 @@ En mode `auto_solar_plus` ou `force_charge_now`, le profil `outside_window` ne b - Forecast solaire fort - Maison consommation faible -### 11.5 Logique Heure de départ (Night EVCS) +### 11.5 Logique Heure de départ (Night EVCS + P9) #### Objectif S'assurer que le véhicule est chargé avant l'heure de départ prévue. +#### Deux véhicules (09/08/2026) +Le sélecteur `input_select.victron_evcs_vehicle` choisit l'heure de départ +effective — **à positionner au branchement** (la borne ne détecte pas qui est +branché) : + +| Véhicule | Heure départ (helper) | Particularité | +|---|---|---| +| **VW** (défaut) | `victron_evcs_departure_time` (~08:50) | Ne publie pas franchement "charged" → fin de charge via VDF | +| **JEEP** | `victron_evcs_departure_time_jeep` (~06:30) | "Charged" franc (statut 3) ; départ DANS la fenêtre HC → logique nuit | + #### Comportement | Scénario | Action | |---|---| -| Heure départ proche + batteries suffisantes | Charge solaire prioritaire | -| Heure départ proche + batteries insuffisantes | grid_forced (HC) si disponible | -| Heure départ proche + pas de HC | grid_forced (plein tarif) | +| Départ pendant la fenêtre HC (JEEP 06:30) | Logique nuit : P7 + recovery urgent avant départ | +| Départ après la fenêtre HC (VW 08:50) + charge finie | Rien (veille collante) | +| Départ ≤ 120 min, hors HC, charge NON finie, **toggle P9 ON** | `grid_hc_allowed` → EDF ON → charge jusqu'à fin (VDF/statut) → `departure_done_idle` collant → EDF coupé immédiatement | +| Toggle P9 OFF | Comportement historique (attente solaire) | + +P9 ne s'impose jamais sur `solar_only` (solaire réel prioritaire) ni sur +`stop` / `force_*`. Pendant P9 le helper takeover est tenu ON (ACM maintient +la batterie, l'hystérésis maintient EDF). #### Paramètres - **batteryHardFloorPct** : Plancher dur batterie (ex: 22%) -- **batteryMorningTargetPct** : Objectif SOC matin selon forecast - - Forecast fort (> 15 kWh) : 40% - - Forecast moyen (8-15 kWh) : 50% - - Forecast faible (< 8 kWh) : 75% +- **batteryMorningTargetPct** : Objectif SOC matin + - Règles forecast (fort/moyen/faible) — valeurs helpers ; + - **OU la recommandation de l'advisor** si le toggle + `evcs_advisor_apply_night_target` est ON (bornes [max(22, hard floor), 90], + statut `ok`, fraîcheur ≤ 120 min ; trace `(ADVISOR)` dans la raison) — + câblage réel du 09/08/2026, HANDOFF §20. - **gridTakeoverTriggerPct** : Seuil de basculement réseau - **batteryRecoveryUrgent** : Si temps restant < temps de charge nécessaire + (utilise l'heure de départ du véhicule sélectionné) +- **P9_DEPARTURE_LEAD_MIN** : 120 min (constante WINDOWS_SOURCEV2) -### 11.6 Cycle nuit HC complet — GRAFCET (P7 + P8 + fixes 08/08/2026) +### 11.6 Cycle nuit HC complet — GRAFCET (P7 + P8 + fixes 08-09/08/2026) Deux automates coordonnés via les helpers HA (`night_grid_takeover_needed`, `victron_evcs_surplus_state`) : @@ -361,46 +400,87 @@ X1 SESSION NUIT ACTIVE — capture startSOC/startAt (une seule fois, Fix B) X2 TAKEOVER: helper ON → G2 force EDF ON ; ACM tient la batterie (~2 A) │ t3: EDF ON confirmé (gridAvailable) X3 CHARGE VE: start 6 A → step-up (plafond 20 A / boost 28 A) - │ t4: fin de charge = VDF no-demand OU statut EVCS brut 3 "charged" (Fix D) + │ t4: fin de charge = VDF no-demand OU statut EVCS brut 3 "charged" + │ + puissance ≤ 300 W (Fix D+E) X4 CHARGE TERMINÉE (collant): vehicleChargeCompleted, sourceMode='blocked' + │ ⚑ Fix F : cet état est réécrit à CHAQUE cycle AU-DESSUS des gardes + │ (hard stop batterie, source-lost...) → il survit aux micro-charges + │ du véhicule et ne peut plus être écrasé. │ - ├─ t5a: SOC < cible matin + ├─ t5a: SOC < cible matin (cible = règles forecast OU advisor si câblé) │ X5a RECOVERY BATTERIE: takeover ON (EDF ON), ACM recharge → cible │ │ t6: SOC ≥ cible │ ▼ └─ t5b: SOC ≥ cible matin X5b RECOVERY DONE (collant, Fix A): état 'night_recovery_done_idle' - │ takeover OFF définitif → G2 coupe EDF (turn_off_recovered) + │ takeover OFF définitif → G2 coupe EDF IMMÉDIATEMENT (cut E2) │ ré-engagement UNIQUEMENT si SOC ≤ cible − 2 (bande anti-rebond) │ t7: débranchement OU fin de fenêtre (07:24) X6 CLÔTURE: clear session → retour X0 (profil jour) +G1bis — P9 : DÉPART IMMINENT HORS HC (09/08/2026) +───────────────────────────────────────────────── +Z0 JOUR, hors fenêtre HC + │ w1: toggle P9 ON ET véhicule branché ET départ (véhicule sélectionné) + │ dans ≤ 120 min ET charge non terminée +Z1 RÉSEAU PRÉ-DÉPART: sourceMode='grid_hc_allowed' (bypass garde SOC 35), + │ takeover helper ON (ACM + hystérésis), EDF ON, charge du véhicule. + │ NB: solar_only réel reste prioritaire ; stop/force* restent maîtres. + │ w2: fin de charge (VDF vehicle_full_or_paused OU statut 3) +Z2 'departure_done_idle' (COLLANT, réécrit chaque cycle comme Fix F) + │ takeover OFF → G2 coupe EDF immédiatement (cut E2 étendu) + │ w3: heure de départ passée OU débranchement +Z0 retour au jour normal + G2 — HYSTÉRÉSIS EDF (seuils ON ≤ 20 % | OFF ≥ 30 % | min_on 25 | cooldown 15) ────────────────────────────────────────────────────────────────────────────── Y0 EDF OFF (observe_only) - │ u1: override EVCS (takeover/force_grid/grid_forced) sans no-demand + │ u1: override EVCS (takeover/force_grid/grid_forced/grid_hc_allowed) + │ sans no-demand sémantique │ u2: SOC ≤ seuil ON (bypass cooldown) Y1 EDF ON + latch │ v1: override disparu ET min_on écoulé ET SOC ≥ seuil OFF → turn_off_recovered │ v2: force_grid + voiture pleine → coupure immédiate │ v3: véhicule débranché + SOC ≥ seuil OFF → coupure immédiate - │ (turn_off_vehicle_unplugged, bypass min_on — Fix C 08/08/2026) + │ (turn_off_vehicle_unplugged, bypass min_on — Fix C) + │ v4: es ∈ {night_recovery_done_idle, departure_done_idle} + SOC ≥ seuil OFF + │ → coupure immédiate (turn_off_recovery_done, bypass min_on — E2+P9) └─▶ retour Y0 (cooldown 15 min) ``` -États surplus « fin de nuit » (aucun ne doit matcher les patterns no-demand +États surplus « fin de charge » (aucun ne doit matcher les patterns no-demand de G2 — full_or_paused / not_requesting_power / charge_complete / no_demand) : - `night_session_done_idle` : charge finie, recovery batterie possible (EDF maintenu si SOC < cible) - `night_recovery_done_idle` : charge finie ET batterie à la cible → EDF relâché définitivement (anti-rebond) +- `departure_done_idle` : charge finie pendant la fenêtre départ P9 (jour) + → EDF relâché définitivement -#### Incident de référence (nuit 07-08/08/2026) -SOC bloqué pile à la cible (35 %) = point dégénéré (engage `soc ≤ 35`, -release `soc > 35`) → rebond EDF ON/OFF période ~10 min + flapping ACM 2-4 s, -et EDF maintenu 25 min après débranchement. Corrigé par Fix A (flag collant + -bande 2 pts), Fix B (snapshot relit startSOC/startAt), Fix C (coupure au -débranchement), Fix D (statut charged = fin de charge immédiate). +#### Incidents de référence +- **Nuit 07-08/08 (JEEP)** : SOC bloqué pile à la cible = point dégénéré → + rebond EDF ~10 min + flapping ACM ; EDF maintenu 25 min après débranchement. + → Fix A (collant + bande 2 pts), B (snapshot startSOC/At), C (coupure au + débranchement), D (statut charged). +- **Nuit 08-09/08 (JEEP)** : statut 3 pendant la session armée → branches + source-lost zombies, état collant jamais écrit, statut retombe à l'ouverture + du relais → re-P7 ~30 min. → Fix E (latch en session active) + E2 (coupure + immédiate recovery done). +- **Matin 09/08 (VW pleine rebranchée)** : micro-charges du véhicule sur + batterie → hard stop ÉCRASAIT l'état collant → re-P7. → Fix F (mémoire + prioritaire sur les gardes, réécrite chaque cycle). + +### 11.7 Conseiller IA — mode ombre et câblages réels + +- Workflow `EVCS Advisor Shadow V1` (15 min) : snapshot HA compact → LLM local + (qwen3-vl / qwen3.6-35b sur la Spark, fallback cloud) → validation stricte → + helpers `evcs_advisor_*` + logbook. N'écrit RIEN d'autre (testé). +- **Câblage réel n°1 (09/08/2026)** : cible SOC matin + (`evcs_advisor_apply_night_target`, cf. §11.5). Garde-fous : statut ok, + fraîcheur ≤ 120 min, bornes, fallback règles, rollback toggle. +- Suivi : carte « Conseiller IA (ombre) » (accords/divergences), historique + des entités `evcs_advisor_*`, logbook « EVCS Advisor », executions n8n. +- Prochains candidats (après observation) : stratégie, plafond courant. --- @@ -439,7 +519,30 @@ débranchement), Fix D (statut charged = fin de charge immédiate). ## 13. Méthode de travail -### 13.1 Lecture d'un workflow n8n +### 13.1 Source de vérité et déploiement (R2, 07/08/2026) + +Le code des nodes du workflow EVCS V2.6 vit dans **`src/nodes/*.js`** +(+ `HA_SNAPSHOT_TEMPLATE.json.tpl`). Le JSON `workflows/*.json` est un +artefact reconstruit au push. + +``` +éditer src/nodes/.js +node tools/n8n-push.mjs workflows/evcs-surplus-controller-v2.6.json + → build src→JSON → node --check → GOLDEN 33 scénarios (bloquant) + → backup serveur → PUT +git commit && git push +``` + +- **JAMAIS** d'édition du JSON ou de l'UI n8n (écrasée au prochain push). +- Tests : `node tests/golden/run.mjs` (33 scénarios figés, exécute le JSON + **buildé** → toujours `node tools/n8n-build.mjs` avant un run manuel). +- Évolution voulue du comportement → mettre à jour + `tests/golden/scenarios.mjs` dans le même commit. +- Workflow hystérésis (`7iIlu7LLTW7TZA8o`) : fichier local + `workflows/victron-grid-hysteresis-v1.json`, patches rejouables dans + `tools/patch-*.mjs`, push via `n8n-push.mjs` (backup auto). + +### 13.2 Lecture d'un workflow n8n (hors EVCS V2.6) 1. Utiliser `n8n-mcp_get_workflow` avec l'ID 2. Le fichier est écrit dans `~/.local/share/opencode/tool-output/tool_*` @@ -450,14 +553,14 @@ débranchement), Fix D (statut charged = fin de charge immédiate). sed -n 'DEBUT,FINp' ``` -### 13.2 Modification +### 13.3 Modification 1. **TOUJOURS** backup avant modification 2. Une seule modification à la fois 3. Vérifier avec dry-run 4. Valider en production -### 13.3 Interdiction +### 13.4 Interdiction - **JAMAIS** de curl/wget direct vers HA/n8n/Victron - **JAMAIS** d'IP/URL/token inventés @@ -469,10 +572,10 @@ débranchement), Fix D (statut charged = fin de charge immédiate). - [ ] Tableau détaillé des fonctionnalités (entrées/sorties/conditions) - [ ] Documentation EDF Urgence (créé par FABLE) -- [ ] Liste des incidents récurrents +- [x] Liste des incidents récurrents → §11.6 (incidents de référence) + HANDOFF §17-21 - [ ] Procédures de dépannage - [ ] Glossaire des termes techniques --- -*Document généré automatiquement le 17/07/2026* \ No newline at end of file +*Document généré le 17/07/2026 — mis à jour le 09/08/2026 (HANDOFF §17-21 : fixes A→F, advisor, P9, véhicules)* \ No newline at end of file