Files
EVCS/docs/MANUEL_COMPLET.md
Tallagrand Thierry 522f47e821 Retrait de Fix G + garde-fous anti-yoyo + diagnostic des deux oscillateurs
Fix G provoquait un yoyo EDF de 2-4 min (coupure a SOC 21 en bypass min_on
contre rallumage a SOC 20 en bypass cooldown) : son garde `soc > gridSocOn`
ne protegeait que l'instant de l'engagement sur SOC bas, pas la phase de
remontee 20 -> 30. jsCode restaure byte-identique a la version pre-Fix-G.

Le fixture de test portait les fallbacks du code (22/35) au lieu des valeurs
de production lues via MCP (20/30), et le scenario de non-regression testait
SOC 18 %, le seul point que Fix G epargnait. Suite reecrite avec les
garde-fous manquants h-recovery-band-no-cut-21/-25. Mutation : Fix G
reapplique -> 4/7 echecs, retire -> 7/7.

Documentation du diagnostic des deux oscillateurs (yoyo EDF et oscillation
de la charge EVCS en plein soleil) dans MANUEL_COMPLET 11.8 et HANDOFF 25.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-08-24 12:20:12 +02:00

33 KiB
Raw Blame History

Manuel Utilisateur - Système EVCS Solaire

Document généré le 17/07/2026 — dernière mise à jour le 22/08/2026 (fixes anti-rebond A→G, câblage advisor cible SOC, P9 départ, véhicules VW/JEEP) Projet: n8n / Home Assistant / EVCS Solaire sans injection réseau


1. Architecture Globale

┌─────────────────────────────────────────────────────────────────┐
│                         DGX Spark (10.10.10.8)                  │
│  ┌─────────────────┐    ┌─────────────────┐                     │
│  │  Qwen3.6-35B    │    │  Qwen3-VL       │                     │
│  │  (texte, code)  │    │  (vision)       │                     │
│  └────────┬────────┘    └────────┬────────┘                     │
└───────────┼──────────────────────┼──────────────────────────────┘
            │                      │
            ▼                      ▼
┌───────────────────────────────────────────────────────────────────┐
│                     opencode (minimax-m2.5)                       │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │ Skills: n8n-code-javascript, n8n-expression-syntax,         │ │
│  │         n8n-mcp-tools-expert, n8n-node-configuration,       │ │
│  │         n8n-validation-expert                               │ │
│  └─────────────────────────────────────────────────────────────┘ │
└───────────┬──────────────────────┬───────────────────────────────┘
            │                      │
            ▼                      ▼
┌──────────────────────┐    ┌──────────────────────────────────────┐
│   n8n (cloud)        │    │   Home Assistant (10.10.10.17:8123)  │
│   https://n8n.airtria.pro    │    ┌──────────────────────────────────┐ │
│  ┌────────────────┐ │    │ │ Dashboards YAML (17 fichiers)      │ │
│  │ 40 workflows   │ │    │ │ - evcs_master.yaml                 │ │
│  │ 13 actifs      │ │    │ │ - evcs_mobile.yaml                 │ │
│  └────────┬───────┘ │    │ │ - victron_master.yaml              │ │
│           │         │    │ │ - etc.                              │ │
│           ▼         │    │ └──────────────────────────────────┘ │
│  ┌────────────────┐ │    └──────────────────────────────────────┘
│  │ MCP Servers    │ │
│  │ (6 outils)     │ │
│  └────────┬───────┘ │
└───────────┼─────────┘
            │
            ▼
┌───────────────────────────────────────────────────────────────────┐
│                     Équipements physiques                          │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐               │
│  │ EVCS HQ229  │  │ Victron ESS │  │ MultiPlus   │               │
│  │ (borne VE)  │  │ (batterie)  │  │ (onduleur)  │               │
│  └─────────────┘  └─────────────┘  └─────────────┘               │
└───────────────────────────────────────────────────────────────────┘

2. Workflows n8n Actifs

2.1 Gestion Énergie (EVCS + Grid)

ID Nom Fréquence Fonction
ATswvGfG4KJUls0K HA Snapshot EVCS Surplus Controller V2.6 30s Pilotage borne EVCS, décision charge solaire/réseau
7iIlu7LLTW7TZA8o Victron - Battery / Grid Hysteresis Fix V1 1 min Hystérésis réseau EDF (ON ≤20%, OFF ≥30%)
cTeeHy4ePiVeELLh Victron - Auto Charge Manager V1.2 30s Limites DVCC batterie (MaxChargeCurrent/Voltage)

2.2 Gestion Charges

ID Nom Fréquence Fonction
2NhrfxuGm4pTUNs9 SDB Climate & Surplus Manager V2.2 1 min Pilotage chauffage SDB selon surplus
FtPVF7byhtu4o6Oh Victron - Garage Thermal Surplus Manager V2.2 1 min Gestion garage thermique
A11aOb50cGtpJmvn Water Heater Advisor V2.3 10 min Advisor ballon ECS
yX2j8m04e3pxaoQq Water Heater Advisor ECS 6 Nodes + Build + Execute 10 min Pilotage ballon ECS
YjiNCpEoVhPT8JMw Victron - Flexible Load Advisor V1 5 min Charge flexible

2.3 Advisor / Monitoring

ID Nom Fréquence Fonction
U0nRmdS9Pa0qzpWm Victron - PV Surplus Advisor V1 15 min Advisor surplus PV

2.4 MCP (Machine Communication Protocol)

ID Nom Fonction
76hHlVYIgt1lEHyR MCP - ha.get_state Lecture états HA
eeDmEICJ3ArjwpCt MCP - ha.set_helper Écriture helpers HA
uGZAOJjKegRuRNyb MCP - grid-set-state Pilotage ON/OFF réseau EDF
a92quWH4pokpIqdn MCP - victron-set-charge-limits Limites courant/tension batterie
RVTMdsvR4i8wSc18 MCP - pv.get_forecast Prévisions Forecast.Solar

3. Skills opencode

Skill Chemin Fonction
n8n-code-javascript .opencode/skills/n8n-code-javascript/SKILL.md Analyse/patch code JS dans nodes n8n
n8n-expression-syntax .opencode/skills/n8n-expression-syntax/SKILL.md Validation syntaxe {{ }}
n8n-mcp-tools-expert .opencode/skills/n8n-mcp-tools-expert/SKILL.md Utilisation outils MCP
n8n-node-configuration .opencode/skills/n8n-node-configuration/SKILL.md Configuration nœuds n8n
n8n-validation-expert .opencode/skills/n8n-validation-expert/SKILL.md Interprétation erreurs validation

4. MCP - Outils disponibles

4.1 Lecture

  • ha-get-state : Lire un état Home Assistant

    • Input: entity_id (ex: sensor.victron_battery_soc)
    • Output: état + attributs
  • pv-get-forecast : Prévisions solaires

    • Input: aucun
    • Output: today_remaining_kwh, tomorrow_kwh, tomorrow_peak_time

4.2 Écriture

  • ha-set-helper : Écrire un helper HA

    • Input: entity_id, value
  • grid-set-state : Piloter le réseau EDF

    • Input: state ('on' ou 'off')
  • victron-set-charge-limits : Limites de charge

    • Input: max_charge_current_a, max_charge_voltage_v

4.3 Workflows n8n

  • n8n-mcp : CRUD workflows
    • List workflows, get workflow, update workflow, activate/deactivate

5. Dashboards Home Assistant

5.1 Principaux

Fichier Titre Description
evcs_master.yaml EVCS Master Dashboard principal borne VE
evcs_mobile.yaml EVCS Mobile Version mobile
victron_master.yaml Victron Master Dashboard principal système Victron
victron_mobile.yaml Victron Mobile Version mobile

5.2 Debug

Fichier Titre Description
big_victron_debug.yaml Victron Debug (complet) Debug étendu
victron_debug.yaml Victron Debug Debug standard
EVCS_SOLAR.yaml EVCS Solar Vue solaire EVCS

5.3 Pilotage

Fichier Titre Description
ECS_PILOTAGE.yaml ECS Pilotage Pilotage ECS
ECS_PILOTAGE_PREMIUM.yaml ECS Pilotage Premium Pilotage ECS avancé
GARAGE_PREMIUM_PILOTAGE.yaml Garage Premium Pilotage Pilotage garage
SDB_PREMIUM_PILOTAGE.yaml SDB Premium Pilotage Pilotage SDB

5.4 Debug Premium

Fichier Titre Description
ECS_DEBUG_REGLAGES.yaml ECS Debug Réglages Debug ECS
ECS_DEBUG_REGLAGES_PREMIUM.yaml ECS Debug Réglages Premium Debug ECS avancé
GARAGE_DEBUG_PREMIUM.yaml Garage Debug Premium Debug garage
SDB_DEBUG_PREMIUM.yaml SDB Debug Premium Debug SDB

6. Helpers Home Assistant (principaux)

6.1 Configuration EVCS

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 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
input_text.victron_evcs_operating_mode text Profil actif
input_text.victron_evcs_surplus_state text État interne
input_text.victron_evcs_surplus_current_decision text Décision logique
input_text.victron_evcs_source_mode text Source autorisée (Solaire/Réseau)
input_text.victron_evcs_surplus_reason text Raison courte
input_text.victron_evcs_last_block_reason text Dernier blocage

6.3 Paramètres seuils

Entity ID Type Description Valeur actuelle
input_number.victron_evcs_soc_start_min number Seuil SOC démarrage 80%
input_number.victron_evcs_soc_stop_min number Seuil SOC arrêt 70%
input_number.victron_evcs_midday_soc_min number Seuil SOC midi 75%
input_number.victron_evcs_night_target_soc number Cible SOC nuit 70%
input_number.evcs_plafond_courant_edf_on number Plafond EDF ON 20A
input_number.victron_evcs_current_max_auto_a number Plafond modes auto 22A

6.4 Hystérésis réseau

Entity ID Type Description
input_boolean.victron_grid_hysteresis_latch boolean Latch hystérésis
input_boolean.victron_evcs_night_session_active boolean Session nuit active
input_boolean.victron_evcs_night_grid_takeover_needed boolean Takeover réseau nuit

7. Capteurs clés (lecture seule)

Entity ID Description
sensor.victron_battery_soc SOC batterie (%)
sensor.victron_battery_current Courant batterie (A)
sensor.victron_pv_power_system Puissance PV totale (W)
sensor.victron_consumption_power_l1 Consommation maison (W)
sensor.victron_grid_power_l1 Puissance réseau (W)
sensor.victron_evcs_current Courant EVCS réel (A)
sensor.victron_evcs_set_current Consigne lue borne (A)
sensor.victron_evcs_ac_power Puissance EVCS (W)
sensor.victron_evcs_charging_time Durée de charge
sensor.victron_evcs_statut_fr Statut FR borne
sensor.victron_evcs_mode_fr Mode FR borne
switch.edf_general_ok_switch Interrupteur réseau EDF
binary_sensor.victron_evcs_vehicle_connected Véhicule connecté
binary_sensor.victron_evcs_device_connected Borne détectée

8. Scripts HA

Script Fonction
script.evcs_boost_edf BOOST EDF 28A (plafonds 28A + force_grid_now)
script.evcs_boost_off Retour normal (plafonds 20/22 + auto_solar_plus)
script.edf_urgence_off EDF Urgence OFF (hystérésis OFF + latch OFF + stratégie stop)
script.edf_force_on EDF forcé ON
script.edf_rendre_la_main Rendre la main au système auto

9. Stratégies de charge

Stratégie Description SourceMode Conditions
auto_solar_plus Solaire uniquement + assistance batterie haute solar_only / solar_potential SOC ≥ 90% + dette nuageuse faible
auto_solar Solaire classique solar_only -
force_grid_now Préservation batterie (remonter à seuil) grid_forced / grid_hc_allowed Si SOC < 22% → remonter à 35% été / 50% mi-saison / 75% hiver
force_charge_now Charge immédiate (solution de secours manuelle) solar_only si possible, grid_forced si SOC < 35% À la discrétion du conducteur qui doit prendre sa voiture
stop Arrêt complet - -

10. Profils temporels

Profil Horaire Description
morning_solar 07:30 - 11:00 Fenêtre solaire matin
midday_hc_or_solar 12:24 - 14:24 HC midi ou solaire
evening_high_soc 17:00 - 20:30 Soir haute priorité SOC
night_hc 01:24 - 07:24 Heures creuses nuit
outside_window Autres Hors fenêtres → Mode probe (sonde) pour relancer le PV si besoin

11. Logique de décision (DECISION_ENGINEV2)

11.1 Garde-fous (Safety)

  • commonSafetyStartOk : Vérifications sécurité au démarrage
  • commonSafetyHoldOk : Vérifications sécurité au maintien
  • mustStopHard : Arrêt d'urgence (batterie basse, surcharge)

11.2 Conditions de démarrage

Condition Seuil Description
solarStartOk SOC ≥ profil + PV ≥ 1000W Démarrage solaire
gridStartOk SOC ≤ 35% + réseau dispo Démarrage réseau
batteryAssistSolarStartOk SOC ≥ 90% + dette nuageuse faible Assistance batterie solaire
probeStartOk Mode probe actif Sonde PV

11.3 Step-up / Step-down

  • Step-up : Augmente le courant si PV suffisant ou batterie en charge
  • Step-down : Diminue si batterie décharge trop ou dette nuageuse

11.4 Cloud Debt (Dette Nuageuse) & Probe

Problème

Quand les batteries sont pleines (SOC > 90%) et que la maison consomme peu (< 1200W), le MPPT de l'onduleur Victron se bride à la consommation maison uniquement. Le PV visible reste bas tant que l'EVCS ne démarre pas.

Dette Nuageuse

  • Définition : La batterie se décharge pour alimenter la maison + VE sans production PV suffisante
  • Seuil max : 1.5 kWh
  • Durée max : 30 min
  • Cette dette doit être "remboursée" par du surplus PV ultérieur

Mode Probe (Sonde)

  • Principe : Lancer la borne à 10A pour "provoquer" une production PV qui va s'adapter en quelques secondes
  • Courant probe : 10A (augmenté de 6A à 10A)
  • Durée probe : 3 minutes
  • Retry : 45 minutes si échec
  • Activation : En dehors des fenêtres définies (outside_window) ou lors de passages nuageux

Bypass outside_window

En mode auto_solar_plus ou force_charge_now, le profil outside_window ne bloque plus la charge solaire locale si :

  • SOC batterie ≥ 90%
  • Forecast solaire fort
  • Maison consommation faible

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
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
    • 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-09/08/2026)

Deux automates coordonnés via les helpers HA (night_grid_takeover_needed, victron_evcs_surplus_state) :

  • G1 = contrôleur EVCS V2.6 (boucle 30 s)
  • G2 = hystérésis EDF (« Victron - Battery / Grid Hysteresis Fix V1 », 1 min)
G1 — SESSION NUIT EVCS
──────────────────────
X0  JOUR / attente (profils solaires)
 │   t1: fenêtre HC (01:24) ET véhicule branché
X1  SESSION NUIT ACTIVE — capture startSOC/startAt (une seule fois, Fix B)
 │   t2: toggle "Réseau HC nuit" ON → nightGridHcPreferred (P7)
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"
 │       + 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 (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 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/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)
 │   v4: es ∈ {night_recovery_done_idle, departure_done_idle} + SOC ≥ seuil OFF
 │       → coupure immédiate (turn_off_recovery_done, bypass min_on — E2+P9)
 │   (v5 "Fix G" a existé du 22 au 24/08/2026 puis a été RETIRÉ : voir §11.8)
 └─▶ retour Y0 (cooldown 15 min)

É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
  • day_vehicle_full_idle (P10) : véhicule plein en journée → plus AUCUNE tentative (même solaire) jusqu'au débranchement ; héritages bidirectionnels jour↔nuit ; échappatoires force_charge_now / force_grid_now

Reset du collant "plein" (P11, 12/08/2026) : au CHANGEMENT DE VÉHICULE, sensor.victron_evcs_charging_time repart de 0 → sessionFresh (≤ 90 s) neutralise TOUS les collants (night/departure/day) → le nouveau véhicule est retesté. Remises à zéro : débranchement, session fraîche (P11), ou force_*.

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).
  • Nuit 21-22/08 : fenêtre HC fermée mi-session (véhicule pas encore flag terminé) → surplus_state retombe sur un état générique transitoire (stop_source_lost/idle_wait_source) qu'aucune règle v3/v4 ne reconnaît → EDF maintenu des heures par la boucle générique jusqu'à gridSocOff, PV plafonné ~100 W par le MPPT. → Fix G (v5), retiré le 24/08 : mauvais diagnostic, le sujet réel est le bilan énergétique (§11.8).
  • Nuit 23-24/08 (yoyo EDF de 2-4 min) : Fix G coupait à SOC 21 % ce que la branche « SOC bas » venait de rallumer à 20 % → hystérésis 20/30 réduite à 20/20,1, MPPT qui flappe à chaque bascule. → Fix G retiré, garde-fous anti-yoyo ajoutés à tests/golden-hysteresis/ (§11.8).

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.

11.8 Les deux oscillateurs identifiés le 24/08/2026

Deux boucles de rétroaction distinctes, de même nature : une décision prise sur un seuil que l'action elle-même vient détruire, sans bande morte.

A. Yoyo EDF (workflow hystérésis) — Fix G retiré

Fix G coupait EDF dès que l'override EVCS disparaissait et que soc > grid_soc_on. Or la branche « SOC bas » allume EDF à grid_soc_on (20 %) et doit tenir jusqu'à grid_soc_off (30 %) : pendant TOUTE cette remontée, soc > grid_soc_on est vrai. Fix G coupait donc à 21 % ce que la branche basse rallumait à 20 %, les deux en bypass de leur amortisseur (min_on 25 min d'un côté, cooldown 15 min de l'autre) → oscillateur libre de 2 à 4 minutes, MPPT qui flappe à chaque bascule. Retiré le 24/08.

Le problème de fond n'est pas le seuil mais son absence de sens physique. Le 24/08, conso maison ≈ 0,75 kWh/h de 07:00 à 09:00 pour une production solaire de 0,07 puis 0,63 kWh/h : rien ne peut relayer EDF avant ~09:00, où la PV passe à 2,74 kWh/h et la batterie remonte seule de 21 à 31 %. Couper EDF à 06:43 à 21 % rend le yoyo mécaniquement inévitable, quels que soient les seuils. Double peine : EDF ON bride le MPPT (ESS sans injection), donc la seule ressource capable de sortir du yoyo est étouffée par le yoyo.

Constat structurel : le snapshot du workflow hystérésis lit 25 champs et aucune prévision solaire, aucune conso projetée, aucun helper advisor. Il décide sur un point de SOC instantané comparé à deux nombres fixes. 30 % n'est pas mal réglé, il est hors sujet : la bonne valeur dépend de l'heure, de la saison et de la courbe du jour (plus haute en saison des pluies, plus basse par forte prévision). Cible retenue : une session réseau unique et dimensionnée (charger en une fois jusqu'au niveau qui permet de tenir jusqu'au croisement PV/conso), arbitrée par le conseiller IA, les règles codées restant un filet de sécurité borné.

B. Oscillation de la charge EVCS en plein soleil

Observée le 24/08 vers 11:58-12:00 avec PV 7,7-7,9 kW : la borne alterne Waiting for start / 0 A et Charging / 7 A. Ce n'est pas une limite 5 kVA — aucun binary_sensor.victron_ve_bus_overload depuis le 20/08, ac_loads_max_safe_w = 9000 W, AC-out L1 mesuré à 5335 W sans overload (le parallèle maître/esclave tient bien au-delà de 5 kVA), et le plafond calculé par WINDOWS_SOURCEV2 ressort à ~20 A. Deux causes réelles :

  1. Bande morte nulle. battery_discharge_soft_a = 0 A et battery_neutral_band_a = 0 A (réglés à 0 le 17/07/2026). Comme profileBatteryDischargeFloorA = max(seuil du profil, réglage global), la tolérance de −12 A prévue pour la bande SOC 40-60 % est annulée : la moindre pointe de conso (ballon, lave-vaisselle) fait passer le courant batterie sous 0 A et casse solarHoldOk. Avec min_run_minutes = 3, la période du cycle est de 3 à 6 minutes.
  2. Condition de démarrage auto-destructrice (P6). En outside_window (11:00-12:24) le plancher de démarrage est soc_start_min = 80 % alors que le SOC est à 49 %. Le seul chemin autorisant le départ est l'override d'abondance P6, qui exige pvPowerAvg10m ≥ 4000 W et batteryCurrentA ≥ +20 A. Or brancher la voiture détourne le surplus et fait tomber le courant batterie sous +20 A : l'action détruit sa propre condition d'autorisation. Système bistable → oscillateur.

Direction retenue (même logique qu'en A) : lire la conso au lieu de la deviner, la filtrer numériquement (les pointes nocturnes sont improbables hors charge EVCS), lisser le SOC pour les décisions de confort en gardant l'instantané pour la sécurité, et exploiter les messages d'état réels du Victron et de la borne plutôt que de s'auto-limiter à l'aveugle sur un proxy.


12. Configuration opencode.json

{
  "provider": {
    "openrama": {
      "models": {
        "minimax-m2.5": { "name": "minimax-m2.5" }
      }
    },
    "qwen-dgx-vl": {
      "models": {
        "qwen3-vl": { "attachment": true, "modalities": {"input": ["text","image"]} },
        "qwen3.6-35b": { "options": { "temperature": 0.15, "reasoningEffort": "none" } }
      }
    }
  },
  "mcp": {
    "n8n-mcp": { "type": "local", "command": ["npx", "-y", "n8n-mcp-server"] },
    "ha-get-state": { "type": "remote", "url": "https://n8n.airtria.pro/mcp/..." },
    "ha-set-helper": { "type": "remote", "url": "https://n8n.airtria.pro/mcp/..." },
    "grid-set-state": { "type": "remote", "url": "https://n8n.airtria.pro/mcp/grid-set-state/sse" },
    "victron-set-charge-limits": { "type": "remote", "url": "https://n8n.airtria.pro/mcp/..." },
    "pv-get-forecast": { "type": "remote", "url": "https://n8n.airtria.pro/mcp/..." }
  },
  "permission": {
    "bash": { "curl *": "deny", "wget *": "deny", "*": "ask" }
  }
}

13. Méthode de travail

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/<NODE>.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_*
  3. Attention : Le fichier commence par "Retrieved workflow: " AVANT le JSON
  4. Extraction par nœud :
    grep -n '"name": "NOM_DU_NOEUD"' <fichier>
    sed -n 'DEBUT,FINp' <fichier>
    

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.4 Interdiction

  • JAMAIS de curl/wget direct vers HA/n8n/Victron
  • JAMAIS d'IP/URL/token inventés
  • Utiliser les MCP uniquement

14. À compléter par l'utilisateur

  • Tableau détaillé des fonctionnalités (entrées/sorties/conditions)
  • Documentation EDF Urgence (créé par FABLE)
  • 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é le 17/07/2026 — mis à jour le 22/08/2026 (HANDOFF §17-24 : fixes A→G, advisor, P9, véhicules)