8.9 KiB
HANDOFF.md — EVCS Outside-Window Solar Charging Block
1. Contexte Projet
- Installation : Victron ESS sans injection réseau. Batterie 17,5 kWh.
- Workflow actif :
HA Snapshot EVCS Surplus Controller V2.5(n8n) - Code source :
/mnt/projects/EVCS/EVCS/decoupesurplus/(architecture modulaire V2) - Fichiers critiques :
WINDOWS/WINDOW_SOURCEV2.js— DétermineprofileetsourceModeBATTERY/BATTERY_CLOUD_LOCKS.js— CalculecloudDebt,cloudToleranceOkDECISION/DECISION_ENGINEV2.js— Arbre de décision finalHYSTERESIS/COMPUTE.js— Step-up / step-downmodified/EVCS_V2.5_PATCHED.json— Export n8n de production
2. Architecture Data-Flow
Schedule Trigger (30s)
→ HA Snapshot (template)
→ INPUT_PARSE
→ WINDOWS_SOURCEV2 ← C'EST ICI QUE LE BLOCAGE SE PRODUIT
→ BATTERY_CLOUD_LOCKS
→ DECISION_ENGINEV2
→ HA_SERVICE_CALLS_OUTPUT
→ Execute HA Service
3. Problème Observé
Symptôme
L'après-midi, avec un fort ensoleillement et un SOC élevé (> 85 %), l'EVCS reste en :
- Profil :
outside_window - Décision :
stop_hardouhold/blocked - Source :
Bloqué - Action utilisateur requise : Forcer manuellement
force_charge_now
Capture d'état typique
Stratégie : auto_solar_plus
Profil : outside_window
Source : Bloqué
SOC : 91 %
Cloud Debt: 1.66 kWh
PV Power : ~800 W (aligné sur charge maison, pas d'injection)
Decision : stop_hard | battery_current_hard_stop
Note contextuelle importante : L'utilisateur a attendu ~45 min sans succès, puis a volontairement passé en force_charge_now pour charger sa moto électrique. Ce forçage a fait tirer sur les batteries à cause des nuages, augmentant encore le cloud_debt.
4. Root Cause Analysis
4.1. Définition de outside_window
outside_window = tout horaire hors des 4 fenêtres configurées :
night_hc: 23:00 → 06:00morning_solar: 07:30 → 11:00midday_hc_or_solar: 12:24 → 14:24evening_high_soc: 17:00 → 20:30
Donc outside_window couvre : 11:00→12:24, 14:24→17:00, 20:30→23:00.
4.2. Logique du sourceMode en outside_window (WINDOW_SOURCEV2.js, L454-468)
else if (profile === 'outside_window') {
if (strongSolarSignal) {
sourceMode = 'solar_only';
} else if (isHighBatteryForPotential && potentialAllowed) {
sourceMode = 'solar_potential';
} else {
sourceMode = 'blocked'; // ← TOMBE ICI
}
}
Pour sortir de blocked, il faut obligatoirement l'un des deux :
A. strongSolarSignal (L343-352)
const strongSolarSignal =
(parsed.pvPowerW > 0 && parsed.pvPowerW >= effectivePvStartMinW) ||
parsed.pvPowerAvg10mW >= params.pvHoldMinW ||
(departurePriorityActive && parsed.pvPowerAvg10mW >= params.pvHoldMinW);
pvStartMinWdéfaut = 1800 WpvHoldMinWdéfaut = 1200 W
Pourquoi c'est faux chez l'utilisateur :
Comme il n'injecte pas, quand SOC > 85 % et charge maison = 800 W, le MPPT régule les PV à ~800 W. Ni pvPowerW, ni pvPowerAvg10mW ne dépassent les seuils.
B. isHighBatteryForPotential (L335-339)
const isHighBatteryForPotential =
parsed.soc >= 85 &&
forecastBufferKwh > 0 &&
cloudDebtOkForPotential && // ← BLOQUÉ ICI
batteryOkForPotential;
Pourquoi c'est faux chez l'utilisateur :
const cloudDebtOkForPotential = params.cloudDebtPrevKwh <= params.cloudDebtMaxKwh;
// cloudDebtPrevKwh = 1.66 kWh
// cloudDebtMaxKwh = 1.2 kWh (défaut)
// → cloudDebtOkForPotential = FALSE
Donc isHighBatteryForPotential est FORCÉMENT FALSE, même avec SOC 91 %.
4.3. Pourquoi le cloud debt est à 1.66 kWh
Le cloud_debt s'accumule quand :
- Session EVCS active
sourceModen'est PASgrid_hc_allowed(donc solaire ou batterie)batteryCurrentA < -neutralBand(batterie qui décharge)
Sur une journée nuageuse avec intermittences, l'EVCS a démarré/stoppé plusieurs fois. Pendant les passages nuageux, la batterie a complété la puissance manquante → accumulation de dette. Cette dette ne se rembourse que quand batteryCurrentA > 0 (batterie en charge). Or, si le système bloque l'EVCS, il n'y a pas de passage à batteryCurrentA > 0 pendant la charge EVCS, donc la dette reste bloquée haute.
4.4. Absence de probe en outside_window
Les probes (morningProbeEligible, middayProbeEligible) sont strictement limitées aux profiles morning_solar et midday_hc_or_solar (WINDOW_SOURCEV2.js L317-330). Il n'existe aucun mécanisme de sonde en outside_window pour tester si le PV peut supporter une charge à 6 A.
4.5. Réseau HC midi / nuit
Les toggles allow_grid_hc_night et allow_grid_hc_midday ne concernent QUE les fenêtres night_hc et midday_hc_or_solar. Ils sont totalement ignorés en outside_window. Ce n'est donc PAS une solution.
4.6. Priorité départ
departurePriorityActive s'active seulement si :
departurePriorityEnabled = ONminutesUntilDeparture <= 240 min- Véhicule branché
Effet : facilite strongSolarSignal en baissant la barre si pvPowerAvg10mW >= pvHoldMinW. Mais ne résout pas le blocage cloudDebt.
5. Résumé des Verrous
| Verrou | Condition | État actuel | Impact |
|---|---|---|---|
| Seuil PV instantané | pvPowerW >= 1800 W |
~800 W | strongSolarSignal = false |
| Seuil PV moyenne | pvPowerAvg10mW >= 1200 W |
Souvent < 1200 W | strongSolarSignal = false |
| Cloud Debt | cloudDebt <= 1.2 kWh |
1.66 kWh | isHighBatteryForPotential = false |
| Probe absente | Seulement morning / midday |
N/A en afternoon | Aucun test de démarrage |
| Réseau HC | Ignoré hors fenêtre | N/A | Pas de fallback grid |
6. Options de Correction Envisagées
Option A — Relâcher cloudDebtOkForPotential en outside_window
Dans WINDOW_SOURCEV2.js, ignorer la condition cloudDebtOkForPotential pour le calcul de isHighBatteryForPotential quand profile === 'outside_window'.
Avantage : Simple, 1 ligne. Risque : Peut entraîner une décharge excessive de la batterie si le PV baisse brutalement.
Option B — Ajouter une afternoon_probe en outside_window (RECOMMANDÉ)
Créer une logique de sonde (probe) active en outside_window lorsque auto_solar_plus est sélectionné. Démarrage à 6 A pendant 3 min, puis évaluation.
Avantage : Fidèle à la philosophie du système (ne charge que si le PV confirme).
Risque : Nécessite modification de BATTERY_CLOUD_LOCKS.js + DECISION_ENGINEV2.js.
Option C — Ajouter une fenêtre afternoon_solar
Étendre la logique des fenêtres pour inclure une plage 14:24→17:00 (ou configurable) avec des seuils PV adaptés.
Avantage : Résout définitivement le "trou" de l'après-midi. Risque : Change la sémantique utilisateur des fenêtres.
Option D — Abaisser pvStartMinW / pvHoldMinW dynamiquement
En outside_window + auto_solar_plus, baisser les seuils si soc >= 90 et forecastBufferKwh > 0.
Avantage : Adaptatif. Risque : Peut causer des démarrages/stops fréquents si le PV est instable.
7. Prochaines Étapes Recommandées
- Décider quelle Option (A, B, C ou D) correspond au comportement souhaité.
- Vérifier la valeur exacte de
cloud_debt_max_kwhdans HA (input_number.victron_cloud_debt_max_kwhou équivalent). - Implémenter le patch dans le fichier cible :
- Si Option A :
WINDOWS/WINDOW_SOURCEV2.js - Si Option B :
WINDOWS/WINDOW_SOURCEV2.js+BATTERY_CLOUD_LOCKS.js+DECISION_ENGINEV2.js - Si Option C :
WINDOWS/WINDOW_SOURCEV2.js+INPUT_PARSE.js - Si Option D :
WINDOWS/WINDOW_SOURCEV2.js
- Si Option A :
- Tester en mode "dry-run" (logique uniquement, pas d'appels HA).
- Redéployer via export/import du workflow n8n.
8. Paramètres Clés à Vérifier dans Home Assistant
| Paramètre HA | Entité typique | Valeur défaut | Valeur actuelle ? |
|---|---|---|---|
pv_start_min_w |
input_number.victron_pv_start_min_w |
1800 W | ? |
pv_hold_min_w |
input_number.victron_pv_hold_min_w |
1200 W | ? |
cloud_debt_max_kwh |
input_number.victron_cloud_debt_max_kwh |
1.2 kWh | ? |
battery_neutral_band_a |
input_number.victron_battery_neutral_band_a |
3 A | ? |
allow_grid_hc_midday |
input_boolean.victron_allow_grid_hc_midday |
OFF | ON (actif) |
allow_grid_hc_night |
input_boolean.victron_allow_grid_hc_night |
OFF | ON (actif) |
9. Notes de Version
- Le workflow V2.5 utilise la chaîne modulaire (
decoupesurplus/). - Le fichier
modified/EVCS_V2.5_PATCHED.jsonest l'export de production. - Le fichier
modified/WINDOWS_SOURCEV2_patched.jsexiste mais ne semble pas utilisé dans le workflow actif (à vérifier).
Document créé le : 12/06/2026 Prochaine action : Implémenter l'Option B (afternoon_probe), validation des paramètres HA à suivre