La cible du matin devient une energie a couvrir, plus un palier

La regle classait le lendemain en trois paliers a partir de son TOTAL (>= 18 kWh
-> 35 %, >= 10 -> 55 %, sinon 85 %) et ignorait donc l heure d arrivee de
l energie. Le 03/09 demain annoncait 33,9 kWh — donc "fort", donc 35 % — avec un
matin creux (0,03 kWh a 7 h, 0,77 a 8 h) et un croisement a 9 h. Meme defaut que
le plancher du soir, a l autre bout de la nuit.

Releve de la nuit 02-03/09, requis contre reel : 00:30 62,4 / 53 ; 03:00
50,4 / 45 ; 04:30 41,7 / 37 ; 06:00 37,1 / 22 — cible fixe a 35 tout du long.
Le required_soc decroit proprement avec la nuit qui se consomme (6,1 -> 0 kWh a
couvrir), la batterie est restee sous la ligne toute la nuit, et le bilan le
savait des 00:30. A 03:00 EDF a ete relache cinq points sous la ligne ; le
reseau est revenu de 07:24 a 10:33 au plein tarif, 1,49 kWh.

La cible vaut desormais min(90, max(palier ou advisor, required_soc)). Sens
unique delibere : la direction corrigee est celle de l echec observe, et le
principe unificateur des deux cablages est que le bilan ne pousse jamais dans le
sens "couvre moins bien la nuit". Plafond 90 parce qu au-dela la batterie cesse
d etre un puits et evince la production du matin, et parce que le bilan publie
sans ecretage des valeurs superieures a 100 — sans ce plafond la cible serait
inatteignable et EDF resterait allume toute la nuit. C est deja la borne du
chemin advisor, aucune constante nouvelle.

Pas d oscillateur : required_soc decroit de facon monotone pendant la nuit et la
passe unique de recovery reste en place. Gardes et repli identiques au plancher
du soir, kill-switch existant.

Golden 70 -> 75. Quatre mutations font tomber chacune exactement un scenario
different. Un cinquieme scenario fige une LIMITE CONNUE, mesuree par sonde : la
passe unique de recovery latche le relachement pour toute la session, donc la
cible dynamique n ameliore que la premiere passe. §26 avait deja designe le bon
critere de re-engagement — un budget d energie restant a couvrir, qui appartient
au bilan ; la suite touche la machine a etats de la nuit et fera l objet d un
chantier propre.

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 22:51:09 +02:00
parent 6f3f98e8b6
commit 05bdf019c2
7 changed files with 344 additions and 9 deletions

View File

@@ -1043,6 +1043,141 @@ export const scenarios = [
},
},
// ===== 03/09/2026 : la cible du matin est une energie, pas un palier =====
// Releve de la nuit 02-03/09 a 03:00 : le bilan demandait 50,4 % pour tenir
// jusqu'au croisement de 9 h, la regle des paliers disait 35 %, le SOC etait
// a 45 %. EDF a ete relache 5 points sous la ligne, la batterie s'est videe
// a 20 % vers 06:30, et le reseau est revenu de 07:24 a 10:33 AU PLEIN TARIF.
{
id: 'cible-bilan-tient-le-reseau',
label: "Nuit HC 03:00 (relevé du 03/09), VW pleine, SOC 45 : le bilan demande 50,4 % → cible relevée → le réseau est MAINTENU au lieu d'être relâché",
time: '2026-08-08T03:00:00+02:00',
overrides: {
...VEHICLE_NIGHT, allow_grid_hc_night: 'on',
grid_state: 'on', victron_acin1_available: '1',
battery_current_a: '2', night_takeover_prev: 'on',
evcs_charging_switch: 'off',
prev_surplus_state: 'night_session_done_idle',
soc_percent: '45',
balance_required_soc: '50.4', balance_energy_to_cover_kwh: '4.3',
balance_status: 'ok', balance_last_run: '08/08 02:58',
},
expect: {
profile: 'night_hc',
state: 'night_session_done_idle',
takeoverNeeded: true,
takeoverHelperService: 'turn_on',
},
},
{
// CONTREFACTUEL : exactement la nuit du 03/09. Bilan indisponible => regle
// des paliers (35 %) => SOC 45 >= 35 => relache. C'est ce qui s'est passe.
id: 'cible-bilan-perime-relache-comme-avant',
label: "Même relevé, bilan vieux de 2 h → repli sur le palier 35 % → EDF relâché (le comportement qui a coûté 1,49 kWh au plein tarif)",
time: '2026-08-08T03:00:00+02:00',
overrides: {
...VEHICLE_NIGHT, allow_grid_hc_night: 'on',
grid_state: 'on', victron_acin1_available: '1',
battery_current_a: '2', night_takeover_prev: 'on',
evcs_charging_switch: 'off',
prev_surplus_state: 'night_session_done_idle',
soc_percent: '45',
balance_required_soc: '50.4', balance_energy_to_cover_kwh: '4.3',
balance_status: 'ok', balance_last_run: '08/08 01:00',
},
expect: {
profile: 'night_hc',
state: 'night_recovery_done_idle',
takeoverNeeded: false,
takeoverHelperService: 'turn_off',
},
},
{
// SENS UNIQUE : le bilan ne doit jamais ABAISSER la cible.
id: 'cible-bilan-ne-baisse-pas-la-cible',
label: "Nuit HC, SOC 30, le bilan ne demande que 25 % → le palier 35 % reste maître → le réseau est maintenu",
time: '2026-08-08T03:00:00+02:00',
overrides: {
...VEHICLE_NIGHT, allow_grid_hc_night: 'on',
grid_state: 'on', victron_acin1_available: '1',
battery_current_a: '2', night_takeover_prev: 'on',
evcs_charging_switch: 'off',
prev_surplus_state: 'night_session_done_idle',
soc_percent: '30',
balance_required_soc: '25', balance_energy_to_cover_kwh: '0.5',
balance_status: 'ok', balance_last_run: '08/08 02:58',
},
expect: {
profile: 'night_hc',
state: 'night_session_done_idle',
takeoverNeeded: true,
takeoverHelperService: 'turn_on',
},
},
{
// PLAFOND 90 % : le bilan publie sans ecretage des valeurs > 100 (c'est
// voulu, §26 : signal de dimensionnement). Sans plafond ici, la cible
// deviendrait inatteignable et EDF resterait allume toute la nuit a
// charger la batterie — en evincant au passage la production du matin.
id: 'cible-bilan-plafonnee-a-90',
label: "Nuit HC, SOC 92, le bilan demande 118,9 % (stockage insuffisant) → cible plafonnée à 90 % → recovery terminée, EDF relâché",
time: '2026-08-08T03:00:00+02:00',
overrides: {
...VEHICLE_NIGHT, allow_grid_hc_night: 'on',
grid_state: 'on', victron_acin1_available: '1',
battery_current_a: '2', night_takeover_prev: 'on',
evcs_charging_switch: 'off',
prev_surplus_state: 'night_session_done_idle',
soc_percent: '92',
balance_required_soc: '118.9', balance_energy_to_cover_kwh: '14.54',
balance_status: 'ok', balance_last_run: '08/08 02:58',
},
expect: {
profile: 'night_hc',
state: 'night_recovery_done_idle',
takeoverNeeded: false,
takeoverHelperService: 'turn_off',
},
},
{
// LIMITE CONNUE, FIGEE VOLONTAIREMENT (03/09/2026).
// La passe unique de recovery (27/08, anti-oscillateur) latche
// `nightRecoveryDone` : une fois la cible atteinte, le reseau est relache
// DEFINITIVEMENT pour la session, meme si le SOC repasse ensuite sous la
// ligne du bilan. La cible dynamique n'ameliore donc que la PREMIERE passe.
// Ce scenario epingle ce comportement pour qu'un changement futur soit
// deliberе et non accidentel. Filet restant : l'hysteresis a SOC <= 20 %,
// mais elle peut tomber hors heures creuses (c'est ce qui a coute 1,49 kWh
// au plein tarif le 03/09 entre 07:24 et 10:33).
// §26 designait deja le bon critere de re-engagement : « un budget
// d'energie restant a couvrir — il appartient au bilan energetique ».
// Le bilan est desormais cable ; la suite est un chantier a part, car elle
// touche la machine a etats de la nuit.
id: 'cible-bilan-limite-passe-unique',
label: "LIMITE FIGÉE : recovery déjà latchée, SOC 30 repasse sous le requis 37,1 % → le réseau reste relâché (passe unique, §26)",
time: '2026-08-08T05:30:00+02:00',
overrides: {
...VEHICLE_NIGHT, allow_grid_hc_night: 'on',
grid_state: 'off', victron_acin1_available: '0',
battery_current_a: '-14', night_takeover_prev: 'off',
evcs_charging_switch: 'off',
prev_surplus_state: 'night_recovery_done_idle',
soc_percent: '30',
balance_required_soc: '37.1', balance_energy_to_cover_kwh: '2.3',
balance_status: 'ok', balance_last_run: '08/08 05:28',
},
expect: {
profile: 'night_hc',
state: 'night_recovery_done_idle',
takeoverNeeded: false,
takeoverHelperService: 'turn_off',
},
},
// ===== 03/09/2026 : le plancher du soir vient de l'energie a couvrir =====
// Tous ces scenarios ont un VRAI excedent (PV 2000 W, maison 1000 W) et des
// chargeurs qui se retiennent : les gardes de §36 et §37 sont donc passantes,