Un demarrage se decide sur l excedent, pas sur la production

Le 03/09 a 19:44, voiture branchee : PV 758 W, maison 1202 W, batterie deja
a -12 A, nuit qui tombe. Le controleur a lance 1,6 kW de charge parce que
pv_start_min_w (700 W) est une puissance PV absolue : "758 >= 700, donc il y
a du soleil". L excedent valait -444 W. En 33 minutes la voiture a pris
0,897 kWh et la batterie en a rendu 1,479 kWh (SOC 94 -> 85), la veille d une
nuit que le bilan energetique annoncait deja deficitaire.

Rejeu du releve dans la vraie chaine : rawSolarStartOk ET
batteryAssistSolarStartOk etaient tous deux vrais. Corriger le seul seuil PV
n aurait donc rien change ; les deux chemins sont traites ensemble.

La grandeur juste est ce qui reste une fois la maison servie. Sans injection
et reseau absent, PV - maison(hors EVCS) vaut la puissance batterie au signe
pres, et separe les deux situations que la mesure PV seule confond : sous
censure la production se cale sur la maison, l excedent vaut ~0 et il y a de
la ressource refusee ; en deficit reel l excedent est negatif et la batterie
porte deja la maison. Zero est la frontiere physique entre les deux, verifiee
sur le releve du 03/09 (excedent positif sur toute la plage ou pv_censored
etait ON, negatif ensuite).

Aucune constante nouvelle, aucun champ de snapshot, aucun helper :
derived.houseNonEvcsW existait deja. Le chemin "soleil reel" reutilise
pv_start_min_w tel quel, applique a la bonne grandeur ; le chemin
"provocation" exige seulement excedent >= 0. Demarrage uniquement : les
conditions de maintien gardent leur plancher et leur tolerance temporelle.

Golden 61 -> 64, autour d une paire de releves reels pris a 54 minutes d ecart
dont les lectures PV ne different que de 11 W (769 puis 758) : le premier
demarre, le second non. apresmidi-provocation-p3 est corrige : il portait
PV 300 W, maison 600 W, batterie +2 A reseau ouvert, un trou de 300 W que rien
n alimente, et passait quand meme parce que le demarrage ne regardait jamais
le bilan. Mutation dans les deux sens : 2 echecs cibles a chaque fois,
excedent-censure-demarre restant vert (il tient par le chemin assistance).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
This commit is contained in:
Tallagrand Thierry
2026-09-03 20:53:50 +02:00
parent 10987a04d8
commit ef3d7ed7b2
5 changed files with 322 additions and 8 deletions

View File

@@ -2485,3 +2485,140 @@ Preuve par mutation, les deux sens séparément :
--- ---
*Document mis à jour le : 01/09/2026 (~20:15) — tolérance temporelle de la politique batterie branchée, golden 61/61* *Document mis à jour le : 01/09/2026 (~20:15) — tolérance temporelle de la politique batterie branchée, golden 61/61*
## 36. Session du 03/09/2026 — Un demarrage se decide sur l'excedent, pas sur la production
### Le releve
Le 03/09, la voiture est branchee a **19:44**. Le controleur lance la charge
dans la seconde. En 33 minutes (19:44 → 20:17, arret par `stop_source_lost`) :
| | valeur integree |
|---|---:|
| pris par la voiture | **0,897 kWh** |
| rendu par la batterie | **1,479 kWh** |
| produit par le PV | 0,327 kWh |
| SOC | **94 % → 85 %** |
Au meme moment, le bilan energetique publiait : croisement PV/conso a **9 h**,
**11,66 kWh a couvrir**, SOC requis **99,7 %**, `grid_needed` ON. Dans sa propre
arithmetique (plancher 22 %, 15 kWh utiles), la charge du soir a fait passer le
manque de la nuit de **0,86 kWh a 2,21 kWh** — elle l'a plus que double, pour
mettre dans la voiture 0,9 kWh qu'elle allait de toute facon reprendre en heures
creuses a 01:24. La fenetre du soir ferme a 20:30 ; il n'y a rien entre les deux.
Precedent immediat, nuit du 02-03/09 : EDF relache a 02:30 a 45 %, batterie a
20 % vers 05:45, reseau maintenu jusqu'a 10:33 — dont **1,49 kWh importes entre
07:24 et 10:33, hors heures creuses**. Marge perdue le soir, rachetee au plein
tarif le matin.
### La cause
`pv_start_min_w` (700 W) est une **puissance PV absolue**. A 19:44 : PV 758 W,
maison 1202 W, batterie deja a −12,2 A. Le controleur a lu « 758 ≥ 700, donc il
y a du soleil » et a lance 1,6 kW. **L'excedent valait −444 W.**
Verification dans la vraie chaine (rejeu du releve) : `rawSolarStartOk` ET
`batteryAssistSolarStartOk` etaient TOUS DEUX vrais. Un correctif sur le seul
seuil PV n'aurait donc rien change — l'assistance batterie aurait demarre la
charge de toute facon. Les deux chemins devaient etre traites ensemble.
Deux temporisations ont ensuite prolonge la faute, sans en etre la cause :
`charging_hold_cloud_tolerance` a pris **le coucher du soleil pour un passage
nuageux** (19:46 → 20:00), puis, la tolerance souple du 01/09 epuisee a 19:57,
`min_run` (29 min) a maintenu la charge **16 minutes de plus**, conditions de
maintien deja declarees perdues. Non traite ici.
### Le correctif (deploye 03/09 20:51, golden 64/64)
Une seule grandeur, dans `BATTERY_CLOUD_LOCKS.js`. `derived.houseNonEvcsW`
existait deja (calcule dans WINDOWS_SOURCEV2, deja lu par BCL) : **aucun champ
de snapshot, aucun helper, aucune constante nouvelle.**
```js
const solarSurplusW = parsed.pvPowerW - derived.houseNonEvcsW;
```
Sans injection et reseau absent, cette grandeur vaut la puissance batterie au
signe pres. C'est ce qui separe les deux situations que la mesure PV seule
confond (`PV_mesuree = min(ressource, conso + absorption batterie)`) :
- **CENSURE** — batterie pleine, MPPT bride faute de puits : la production se
cale sur la maison, l'excedent vaut ~0, la batterie ne bouge pas. Il y a de la
ressource REFUSEE : la provoquer avec la voiture est legitime (raison d'etre
de P3 et de l'assistance batterie).
- **DEFICIT** — soir, nuages : l'excedent est NEGATIF, la batterie porte deja la
maison. Charger la voiture, c'est la vider.
Zero n'est donc pas un seuil de plus, c'est la frontiere physique entre les deux.
Deux tests, parce que les deux chemins n'ont pas le meme metier :
- **chemin « soleil reel »** (`rawSolarStartOk`) : excedent ≥ `pv_start_min_w`.
Meme helper, meme valeur, appliquee a la bonne grandeur ;
- **chemin « provocation »** (assistance batterie, ou sourceMode
`solar_potential`) : excedent ≥ **0**. On n'exige pas d'excedent mesurable —
il est censure par construction — seulement que la batterie ne porte pas deja
la maison.
⚠️ **PORTEE : DEMARRAGE UNIQUEMENT.** Les conditions de MAINTIEN sont
inchangees : une charge etablie a deja son plancher de decharge et sa tolerance
temporelle (§35), et couper une charge en cours sur une mesure d'excedent
bruitee recreerait l'oscillateur qu'on venait d'eteindre.
Verification empirique de la frontiere sur le releve du 03/09 : de 17:00 a 19:41,
`pv_censored` ON et excedent **toujours positif** (+14 a +212 W) ; a partir de
19:42, excedent negatif. La frontiere a zero separe exactement les deux regimes
sur la mesure reelle.
### Golden 61 → 64, et un scenario corrige
La paire de releves REELS, prise a 54 min d'intervalle, est le coeur du test :
| scenario | PV | maison | batterie | excedent | attendu |
|---|---:|---:|---:|---:|---|
| `excedent-censure-demarre` (18:50) | 769 W | 755 W | 0 A | **+14 W** | `start_min_current` 6 A |
| `excedent-deficit-ne-demarre-pas` (19:44) | 758 W | 1202 W | −12,2 A | **−444 W** | `idle_wait_conditions` |
**11 W d'ecart sur la lecture PV.** L'ancien code voyait la meme chose dans les
deux. Sans cette paire, rien ne prouverait que la nouvelle grandeur discrimine
ce que l'ancienne confondait.
Troisieme scenario, `excedent-grosse-production-grosse-maison` : PV 3000 W,
maison 2800 W, SOC 60 — pas de censure possible, la production mesuree EST la
ressource et elle est deja prise. Il exerce le chemin « soleil reel », que la
paire ne touche pas (elle passe par l'assistance).
**`apresmidi-provocation-p3` a ete corrige** : il portait PV 300 W, maison 600 W,
batterie +2 A, reseau ouvert — un trou de 300 W que rien n'alimente, etat
physiquement inatteignable. Il passait quand meme, precisement parce que le
demarrage ne regardait que la production et jamais le bilan. Remis coherent en
gardant son intention (production sous `pv_hold_min` 500 ET sous `pv_start_min`
700, donc seul `solar_potential` peut demarrer) : PV 430 W, maison 400 W,
excedent +30 W — la vraie signature de la censure.
Preuve par mutation, dans les deux sens : retour au seuil absolu → 2 echecs
cibles ; garde neutralisee → les 2 memes. Dans les deux cas
`excedent-censure-demarre` reste VERT, ce qui prouve qu'il tient par le chemin
assistance et non par la garde. Restauration → 64/64.
### Limite connue
Si `sensor.victron_consumption_power_l1` passe `unavailable`, la maison est lue
a 0 et l'excedent redevient la production brute — c'est-a-dire le comportement
d'avant ce correctif. Degradation vers l'existant, jamais pire.
### Ce que ce correctif ne fait PAS (suite convenue avec le proprietaire)
2. **Lire `input_boolean.evcs_balance_pv_censored`** pour conditionner la
provocation `solar_potential`, au lieu de l'approximer par SOC ≥ 90. Le
03/09 la censure s'est arretee a 19:30 (`batterie_pleine_sans_puits` →
`production non bridee` a 20:00) : l'approximation disait « oui » au moment
exact ou la chose approximee devenait fausse.
3. **Lire `evcs_balance_required_soc` / `_energy_to_cover_kwh`** pour que le
plancher du soir cesse d'etre un niveau fixe (`evening_soc_start_min` = 85).
⚠️ **CONSTAT STRUCTUREL, a garder en tete pour la suite** :
`grep evcs_balance workflows/evcs-surplus-controller-v2.6.json` → **0**, idem
pour l'hysteresis. Le bilan energetique calcule et publie l'heure de croisement,
l'energie a couvrir, le SOC requis, `grid_needed` et `pv_censored` — et **aucun
des deux workflows qui decident n'en lit une seule valeur**. Meme contradiction
sur la cible du matin : `night_target_soc` = 35 % (regle sur le TOTAL de demain,
33,9 kWh ≥ 18 → « fort ») contre 99,7 % pour le bilan, qui regarde QUAND
l'energie arrive — demain matin est creux : 0,03 kWh a 7 h, 0,77 a 8 h, 1,81 a
9 h. Deux nombres, memes donnees, facteur 3.
---
*Document mis a jour le : 03/09/2026 (~20:55) — demarrage sur l'excedent, golden 64/64, deploye*

View File

@@ -748,6 +748,50 @@ reste négative à chaque échantillon.
Golden 56 → 61, dont le contrefactuel `batt-decharge-soutenue-coupe` qui prouve Golden 56 → 61, dont le contrefactuel `batt-decharge-soutenue-coupe` qui prouve
que la garde mord toujours après sa tolérance. Détail : HANDOFF §35. que la garde mord toujours après sa tolérance. Détail : HANDOFF §35.
#### D. Demarrage decide sur la production et non sur l'excedent (03/09/2026)
Quatrieme membre de la meme famille, et le plus couteux. `pv_start_min_w`
(700 W) est une **puissance PV absolue**. Le 03/09 a 19:44, voiture branchee :
PV 758 W, maison 1202 W, batterie deja a −12,2 A, nuit qui tombe. Le controleur
a lu « 758 ≥ 700, donc il y a du soleil » et a lance 1,6 kW de charge.
L'excedent valait **−444 W**.
En 33 minutes la voiture a pris 0,897 kWh et la batterie en a rendu 1,479 kWh
(SOC 94 → 85). Dans l'arithmetique du bilan energetique lui-meme, le manque de
la nuit est passe de 0,86 a 2,21 kWh — pour livrer 0,9 kWh que la voiture
reprenait de toute facon en heures creuses a 01:24.
**La grandeur juste n'est pas la production, c'est ce qui reste une fois la
maison servie.** Sans injection et reseau absent, `PV − maison(hors EVCS)` vaut
la puissance batterie au signe pres, et c'est ce qui separe les deux situations
que la mesure PV seule confond :
| | production | excedent | batterie | la voiture doit… |
|---|---|---:|---|---|
| **Censure** (batterie pleine, MPPT bride) | se cale sur la maison | **~0** | immobile | …demarrer : ressource refusee |
| **Deficit** (soir, nuages) | basse | **< 0** | decharge | …ne pas demarrer : ce serait la vider |
Zero n'est donc pas un seuil de plus : c'est la frontiere physique entre les
deux. Verifie sur le releve du 03/09 — excedent positif (+14 a +212 W) sur
toute la plage ou `pv_censored` etait ON (17:00-19:41), negatif ensuite.
Correctif : deux tests sur cette grandeur, aucune constante nouvelle. Le chemin
« soleil reel » reutilise `pv_start_min_w` tel quel ; le chemin « provocation »
(assistance batterie, `solar_potential`) exige seulement excedent ≥ 0.
**Demarrage uniquement** — les conditions de maintien gardent leur plancher et
leur tolerance temporelle (§C), sous peine de recreer l'oscillateur.
Golden 61 → 64, autour d'une paire de releves reels pris a 54 minutes d'ecart
dont les lectures PV ne different que de **11 W** (769 puis 758) : le premier
demarre, le second non — ce qui les separe est la maison. Detail : HANDOFF §36.
⚠️ Point structurel mis au jour par cet incident : le bilan energetique publie
l'heure de croisement, l'energie a couvrir, le SOC requis, `grid_needed` et
`pv_censored` — et **aucun des deux workflows de decision n'en lit une seule
valeur**. La cible du matin en est l'illustration : 35 % cote controleur
(regle sur le total de demain) contre 99,7 % cote bilan (qui regarde quand
l'energie arrive). Memes donnees, facteur 3.
--- ---
--- ---

View File

@@ -570,6 +570,54 @@ const commonSafetyHoldOk =
parsed.evcsVehicleConnected && parsed.evcsVehicleConnected &&
!parsed.evcsModeIsAuto; !parsed.evcsModeIsAuto;
// =====================================================
// EXCEDENT SOLAIRE — LA GRANDEUR QUI DECIDE D'UN DEMARRAGE (03/09/2026)
// =====================================================
// Incident du 03/09 19:44 : PV 758 W, maison 1202 W, batterie deja a -12 A,
// nuit qui tombe. Le controleur a lance 1,6 kW de charge parce que
// pv_start_min_w (700 W) est une PUISSANCE PV ABSOLUE : "758 >= 700, donc il y
// a du soleil". L'excedent, lui, valait -444 W. En 33 minutes la voiture a pris
// 0,897 kWh et la batterie en a rendu 1,479 kWh, la veille d'une nuit que le
// bilan energetique annoncait deja deficitaire (SOC requis 99,7 %).
//
// La grandeur juste n'est pas la production, c'est ce qui RESTE une fois la
// maison servie. Sans injection et reseau absent, elle vaut la puissance
// batterie au signe pres :
//
// excedent = PV - maison(hors EVCS) ~= puissance batterie
//
// C'est aussi ce qui separe les deux situations que la mesure PV seule confond
// (PV_mesuree = min(ressource, conso + absorption batterie)) :
//
// - CENSURE : batterie pleine, MPPT bride faute de puits. La production se
// cale sur la maison, l'excedent vaut ~0, la batterie ne bouge pas. Il y a
// de la ressource REFUSEE : la provoquer avec la voiture est legitime, et
// c'est toute la raison d'etre de P3 / de l'assistance batterie.
// - DEFICIT reel : soir, nuages. L'excedent est NEGATIF, la batterie porte
// deja la maison. Charger la voiture, c'est la vider.
//
// Zero n'est donc pas un seuil de plus : c'est la frontiere physique entre les
// deux, et elle etait invisible tant qu'on regardait la production seule.
// Aucune constante n'est introduite ; le chemin "soleil reel" reutilise
// pv_start_min_w tel quel, applique a la bonne grandeur.
//
// PORTEE : DEMARRAGE uniquement. Les conditions de MAINTIEN sont inchangees —
// une charge etablie a deja son plancher de decharge et sa tolerance temporelle
// (01/09), et couper une charge en cours sur une mesure d'excedent bruitee
// recreerait l'oscillateur qu'on vient d'eteindre.
const solarSurplusW = parsed.pvPowerW - derived.houseNonEvcsW;
// Chemin PROVOCATION (batterie haute, ou sourceMode solar_potential) : on
// n'exige pas d'excedent mesurable — il est censure par construction — mais on
// exige que la batterie ne porte pas deja la maison.
const solarSurplusProvocationOk = solarSurplusW >= 0;
// Chemin SOLEIL REEL : l'excedent doit atteindre le seuil de demarrage.
const solarSurplusStartOk =
context.sourceMode === 'solar_potential'
? solarSurplusProvocationOk
: solarSurplusW >= context.effectivePvStartMinW;
// ===================================================== // =====================================================
// BATTERY-ASSISTED SOLAR START/HOLD // BATTERY-ASSISTED SOLAR START/HOLD
// IMPORTANT: // IMPORTANT:
@@ -601,6 +649,7 @@ const batteryAssistSolarStartOk =
parsed.soc >= Math.max(profileSocStartFloor, batteryAssistSolarStartSocMin) && parsed.soc >= Math.max(profileSocStartFloor, batteryAssistSolarStartSocMin) &&
parsed.soc > batteryAssistSolarHoldSocMin && parsed.soc > batteryAssistSolarHoldSocMin &&
parsed.batteryCurrentA >= profileBatteryDischargeFloorA && parsed.batteryCurrentA >= profileBatteryDischargeFloorA &&
solarSurplusProvocationOk &&
cloudDebtNextKwh <= batteryAssistSolarDebtStartMaxKwh && cloudDebtNextKwh <= batteryAssistSolarDebtStartMaxKwh &&
!cloudDebtActive; !cloudDebtActive;
@@ -629,10 +678,7 @@ const rawSolarStartOk =
commonSafetyStartOk && commonSafetyStartOk &&
parsed.soc >= effectiveSocStartFloor && parsed.soc >= effectiveSocStartFloor &&
parsed.batteryCurrentA >= profileBatteryDischargeFloorA && parsed.batteryCurrentA >= profileBatteryDischargeFloorA &&
( solarSurplusStartOk;
context.sourceMode === 'solar_potential' ||
parsed.pvPowerW >= context.effectivePvStartMinW
);
const solarStartOk = const solarStartOk =
rawSolarStartOk || batteryAssistSolarStartOk; rawSolarStartOk || batteryAssistSolarStartOk;
@@ -972,6 +1018,11 @@ return [{
profileSocHoldFloor, profileSocHoldFloor,
effectiveSocHoldFloor, effectiveSocHoldFloor,
profileBatteryDischargeFloorA, profileBatteryDischargeFloorA,
// Excedent solaire (03/09/2026) : la grandeur qui autorise un demarrage.
solarSurplusW,
solarSurplusProvocationOk,
solarSurplusStartOk,
batteryCurrentHardExceeded, batteryCurrentHardExceeded,
mustStopHard, mustStopHard,
gridBatteryProtectionStop, gridBatteryProtectionStop,

View File

@@ -888,13 +888,21 @@ export const scenarios = [
}, },
{ {
id: 'apresmidi-provocation-p3', id: 'apresmidi-provocation-p3',
label: 'Après-midi hors fenêtre, SOC 95, PV bridé 300 W (< hold 500) → provocation PV (solar_potential)', // 03/09/2026 — echantillon rendu COHERENT EN ENERGIE. Il portait PV 300 W,
// maison 600 W et batterie +2 A : un trou de 300 W que rien n'alimente,
// etat physiquement inatteignable reseau ouvert. Il passait quand meme,
// parce que le demarrage ne regardait que la production. Corrige en gardant
// l'intention d'origine — production mesuree SOUS pv_hold_min (500) et sous
// pv_start_min (700), donc seul solar_potential peut demarrer — avec une
// maison qui, elle, ferme le bilan : c'est la signature de la censure
// (batterie pleine, MPPT cale sur la maison, excedent ~0).
label: 'Après-midi hors fenêtre, SOC 95, PV bridé 430 W (< hold 500) mais maison 400 W → censure, excédent +30 W → provocation PV (solar_potential)',
time: AFTERNOON, time: AFTERNOON,
overrides: { overrides: {
evcs_vehicle_connected: 'on', evcs_device_connected: 'on', evcs_vehicle_connected: 'on', evcs_device_connected: 'on',
soc_percent: '95', pv_power_w: '300', pv_power_10m_avg_w: '300', soc_percent: '95', pv_power_w: '430', pv_power_10m_avg_w: '430',
pv_trend_w: '0', battery_current_a: '2', pv_trend_w: '0', battery_current_a: '2',
house_ac_power_w: '600', vebus_ac_out_l1_power_w: '600', house_ac_power_w: '400', vebus_ac_out_l1_power_w: '400',
}, },
expect: { expect: {
profile: 'outside_window', profile: 'outside_window',
@@ -909,6 +917,80 @@ export const scenarios = [
}, },
}, },
// ===== 03/09/2026 : un demarrage se decide sur l'EXCEDENT, pas sur la PV =====
// Les deux premiers scenarios sont des releves REELS du 03/09, pris a 54 min
// d'intervalle. Leurs lectures de production ne different que de 11 W
// (769 W puis 758 W) : pour l'ancien code, deux fois "758 >= 700, il y a du
// soleil". Ce qui les separe est la MAISON — 755 W puis 1202 W — donc
// l'excedent : +14 W (production refusee, batterie pleine, rien a absorber)
// puis -444 W (la batterie porte deja la maison, la nuit tombe).
// La paire est le coeur du correctif : sans elle, aucune preuve que la
// nouvelle grandeur discrimine ce que l'ancienne confondait.
{
id: 'excedent-censure-demarre',
label: "Relevé du 03/09 18:50 (pv_censored=ON) : PV 769 W, maison 755 W, batterie 0 A, SOC 94 → excédent +14 W = ressource refusée → la voiture DOIT démarrer",
time: '2026-08-08T18:50:00+02:00',
overrides: {
evcs_vehicle_connected: 'on', evcs_device_connected: 'on',
soc_percent: '94', battery_current_a: '0',
pv_power_w: '769.1', pv_power_10m_avg_w: '800', pv_trend_w: '0',
house_ac_power_w: '755', vebus_ac_out_l1_power_w: '755',
evcs_ac_power_w: '0',
},
expect: {
profile: 'evening_high_soc',
sourceMode: 'solar_only',
state: 'start_min_current',
decision: 'start',
desiredCharging: true,
currentA: 6,
},
},
{
id: 'excedent-deficit-ne-demarre-pas',
label: "Relevé du 03/09 19:44 (l'incident) : PV 758 W mais maison 1202 W, batterie déjà à -12 A, SOC 94 → excédent -444 W → AUCUN démarrage, ni chemin solaire ni assistance batterie",
time: '2026-08-08T19:44:30+02:00',
overrides: {
evcs_vehicle_connected: 'on', evcs_device_connected: 'on',
soc_percent: '94', battery_current_a: '-12.2',
pv_power_w: '758.3', pv_power_10m_avg_w: '790', pv_trend_w: '0',
house_ac_power_w: '1202', vebus_ac_out_l1_power_w: '1202',
evcs_ac_power_w: '0',
},
expect: {
profile: 'evening_high_soc',
sourceMode: 'solar_only',
state: 'idle_wait_conditions',
decision: 'hold',
desiredCharging: false,
},
},
{
// Exerce le chemin "soleil reel" (rawSolarStartOk), que la paire ci-dessus
// ne touche pas : elle passe par l'assistance batterie. Batterie a 60 %,
// donc pas de censure possible — la production mesuree EST la ressource, et
// elle est deja prise par la maison. L'ancien code demarrait (3000 >= 700).
id: 'excedent-grosse-production-grosse-maison',
label: "Matin, PV 3000 W mais maison 2800 W et SOC 60 (pas de censure possible) → excédent 200 W < seuil de démarrage → pas de charge malgré une forte production",
time: MORNING,
overrides: {
evcs_vehicle_connected: 'on', evcs_device_connected: 'on',
soc_percent: '60', battery_current_a: '-4',
pv_power_w: '3000', pv_power_10m_avg_w: '3000', pv_trend_w: '0',
house_ac_power_w: '2800', vebus_ac_out_l1_power_w: '2800',
evcs_ac_power_w: '0',
},
expect: {
profile: 'morning_solar',
sourceMode: 'solar_only',
state: 'idle_wait_conditions',
decision: 'hold',
desiredCharging: false,
},
},
// ===== 01/09/2026 : le depassement souple de la batterie doit DURER ===== // ===== 01/09/2026 : le depassement souple de la batterie doit DURER =====
// Incident du 01/09 (14:26 et 14:56) : SOC 94, batterie en float, courant // Incident du 01/09 (14:26 et 14:56) : SOC 94, batterie en float, courant
// oscillant entre +1,8 et -2,6 A d'un echantillon a l'autre. Le controleur // oscillant entre +1,8 et -2,6 A d'un echantillon a l'autre. Le controleur

File diff suppressed because one or more lines are too long