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:
137
HANDOFF.md
137
HANDOFF.md
@@ -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*
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
Reference in New Issue
Block a user