Vehicule branche a midi : JEEP, VW et moto ZERO (calendrier, capacite et puissance par vehicule)

ZERO ajoutee au selecteur avec son heure de depart (P9). Le bilan lit la
capacite et la puissance de charge mesurees du vehicule selectionne ; 0 =
inconnue (regle muette / pas de borne). Bilan 64/64, golden 123/123.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011uJ47NxgfpGnuuMr3f2n7Z
This commit is contained in:
Tallagrand Thierry
2026-09-28 14:05:04 +02:00
parent 3b9b67268c
commit be1b12969e
13 changed files with 207 additions and 32 deletions

View File

@@ -1014,6 +1014,19 @@ fermer le contacteur a midi n'y gagnerait rien et etoufferait le solaire.
- ⚠️ A surveiller : le niveau doit etre saisi a chaque branchement (sinon la regle se - ⚠️ A surveiller : le niveau doit etre saisi a chaque branchement (sinon la regle se
tait) ; la capacite JEEP 8,7 est a affiner sur une charge complete depuis un niveau tait) ; la capacite JEEP 8,7 est a affiner sur une charge complete depuis un niveau
connu. connu.
- **Etendu aux TROIS vehicules le meme jour** (remarque du proprietaire : « pas logique
de ne traiter que la JEEP ») : par vehicule, jours + heure de depart apres midi,
capacite et puissance de charge MESUREES (`victron_evcs_{jeep,vw,zero}_*`) ; le bilan
lit celles du vehicule selectionne. JEEP 8,7 kWh / 3,66 kW, VW 7,7 / 3,68, ZERO 0 / 0
= inconnues -> regle muette pour la moto. VW : aucun jour de depart apres midi
(routine MANUEL §0). Puissance inconnue -> pas de borne (erreur vers « reseau
justifie », jamais vers la batterie videe). `ZERO` ajoute au selecteur + heure de
depart du matin (P9) ; ⚠️ creee a 00:00, recalee sur 08:50 (VW) sinon P9 ouvrait
une fenetre vers minuit. Bilan 64/64, golden 123/123. Deploye 14:04.
- Agent vocal (SPARK, accord du proprietaire) : script d'ecriture limite au selecteur
`victron_evcs_vehicle` puis au niveau (jamais `target_vehicle`, helper mort ; jamais
`level_ref_kwh`). ⚠️ un niveau identique reecrit ne change pas l'etat HA -> la
reference du compteur n'est pas recalee.
--- ---
*Document mis a jour le : 28/09/2026 (~02:15) — VRM remplace Forecast.Solar (comparaison le 05/10), tenir jusqu'a la prochaine HC, prevision de nuit pour l'agent* *Document mis a jour le : 28/09/2026 (~02:15) — VRM remplace Forecast.Solar (comparaison le 05/10), tenir jusqu'a la prochaine HC, prevision de nuit pour l'agent*

View File

@@ -219,14 +219,36 @@ views:
name: Heure départ VW name: Heure départ VW
- entity: input_datetime.victron_evcs_departure_time_jeep - entity: input_datetime.victron_evcs_departure_time_jeep
name: Heure départ JEEP name: Heure départ JEEP
- entity: input_datetime.victron_evcs_departure_time_zero
name: Heure départ ZERO
- entity: input_number.victron_evcs_vehicle_level_pct - entity: input_number.victron_evcs_vehicle_level_pct
name: 🔋 Niveau de la voiture (à saisir au branchement) name: 🔋 Niveau du véhicule branché (à saisir au branchement)
- entity: input_datetime.victron_evcs_jeep_midday_departure - entity: input_datetime.victron_evcs_jeep_midday_departure
name: JEEP repart après midi à name: JEEP repart après midi à
- entity: input_text.victron_evcs_jeep_midday_departure_days - entity: input_text.victron_evcs_jeep_midday_departure_days
name: Jours où la JEEP repart (lun mar mer jeu ven sam dim) name: Jours où la JEEP repart (lun mar mer jeu ven sam dim)
- entity: input_datetime.victron_evcs_vw_midday_departure
name: VW repart après midi à
- entity: input_text.victron_evcs_vw_midday_departure_days
name: Jours où la VW repart (lun mar mer jeu ven sam dim)
- entity: input_datetime.victron_evcs_zero_midday_departure
name: ZERO repart après midi à
- entity: input_text.victron_evcs_zero_midday_departure_days
name: Jours où la ZERO repart (lun mar mer jeu ven sam dim)
- entity: input_number.victron_evcs_capacity_jeep_kwh
name: Capacité mesurée JEEP
- entity: input_number.victron_evcs_charger_kw_jeep
name: Puissance de charge JEEP
- entity: input_number.victron_evcs_capacity_vw_kwh
name: Capacité mesurée VW
- entity: input_number.victron_evcs_charger_kw_vw
name: Puissance de charge VW
- entity: input_number.victron_evcs_capacity_zero_kwh
name: Capacité mesurée ZERO
- entity: input_number.victron_evcs_charger_kw_zero
name: Puissance de charge ZERO
- entity: input_boolean.evcs_balance_vehicle_grid_needed - entity: input_boolean.evcs_balance_vehicle_grid_needed
name: Réseau justifié pour la voiture à midi (verdict du bilan) name: Réseau justifié pour le véhicule à midi (verdict du bilan)
- entity: input_number.evcs_balance_vehicle_need_kwh - entity: input_number.evcs_balance_vehicle_need_kwh
name: Besoin voiture avant départ name: Besoin voiture avant départ
- entity: input_number.evcs_balance_vehicle_solar_kwh - entity: input_number.evcs_balance_vehicle_solar_kwh

View File

@@ -278,6 +278,14 @@ A faire a ce moment-la, et rien avant :
3. la table `session_charge` n'a rien a changer : elle enregistre la valeur du 3. la table `session_charge` n'a rien a changer : elle enregistre la valeur du
selecteur, quelle qu'elle soit. selecteur, quelle qu'elle soit.
**FAIT le 28/09/2026** (points 1 et 2) : `ZERO` est une option du selecteur,
`input_datetime.victron_evcs_departure_time_zero` existe (cale provisoirement sur
08:50, l'heure de la VW, en attendant la sienne) et `INPUT_PARSE` la retient
quand la ZERO est selectionnee (golden `p9-depart-zero-*`). **Reste a donner** :
sa capacite mesuree (`input_number.victron_evcs_capacity_zero_kwh`, 0 = inconnue)
et sa puissance de charge (`..._charger_kw_zero`) ; tant qu'elles valent 0, la
regle de midi se tait pour la moto.
⚠️ Une moto a une batterie bien plus petite qu'une voiture (une SR/F est de ⚠️ Une moto a une batterie bien plus petite qu'une voiture (une SR/F est de
l'ordre de 14 a 17 kWh) et un chargeur embarque plus faible. **C'est donc l'ordre de 14 a 17 kWh) et un chargeur embarque plus faible. **C'est donc
peut-etre le premier vehicule du foyer qui soit electriquement distinguable peut-etre le premier vehicule du foyer qui soit electriquement distinguable

View File

@@ -30,6 +30,7 @@ input_select:
options: options:
- VW - VW
- JEEP - JEEP
- ZERO
icon: mdi:car-multiple icon: mdi:car-multiple
input_datetime: input_datetime:
@@ -37,10 +38,24 @@ input_datetime:
name: EVCS - Heure départ JEEP name: EVCS - Heure départ JEEP
has_date: false has_date: false
has_time: true has_time: true
victron_evcs_departure_time_zero:
name: EVCS - Heure départ ZERO
has_date: false
has_time: true
# Depart APRES LE DEJEUNER, par vehicule (28/09/2026) : les jours ou il
# repart, ce qu'il n'a pas pris avant ne pourra pas l'etre en HC la nuit.
victron_evcs_jeep_midday_departure: victron_evcs_jeep_midday_departure:
name: EVCS - Heure de départ JEEP après midi name: EVCS - Heure de départ JEEP après midi
has_date: false has_date: false
has_time: true has_time: true
victron_evcs_vw_midday_departure:
name: EVCS - Heure de départ VW après midi
has_date: false
has_time: true
victron_evcs_zero_midday_departure:
name: EVCS - Heure de départ ZERO après midi
has_date: false
has_time: true
input_boolean: input_boolean:
victron_evcs_allow_grid_departure_urgent: victron_evcs_allow_grid_departure_urgent:
@@ -48,7 +63,7 @@ input_boolean:
icon: mdi:car-clock icon: mdi:car-clock
# ===================================================== # =====================================================
# JEEP BRANCHEE A MIDI (28/09/2026, strategie du proprietaire) # VEHICULE BRANCHE A MIDI — JEEP, VW, ZERO (28/09/2026, strategie du proprietaire)
# « JEEP branchee engage le reseau en HC midi si l'analyse de production le # « JEEP branchee engage le reseau en HC midi si l'analyse de production le
# justifie ». Le bilan energetique compare le besoin de la voiture a ce que le # justifie ». Le bilan energetique compare le besoin de la voiture a ce que le
# solaire peut lui donner AVANT son depart sans descendre la batterie sous le # solaire peut lui donner AVANT son depart sans descendre la batterie sous le
@@ -77,7 +92,8 @@ input_number:
icon: mdi:counter icon: mdi:counter
# Capacites MESUREES au compteur de la borne (charge complete depuis un # Capacites MESUREES au compteur de la borne (charge complete depuis un
# niveau bas), pas les valeurs constructeur. VW 7,70 (15/09, MANUEL §0) ; # niveau bas), pas les valeurs constructeur. VW 7,70 (15/09, MANUEL §0) ;
# JEEP 8,7 = plus grosse session relevee (22/09), a affiner. # JEEP 8,7 = plus grosse session relevee (22/09), a affiner. 0 = INCONNUE :
# la regle de midi se tait pour ce vehicule plutot que de deviner.
victron_evcs_capacity_jeep_kwh: victron_evcs_capacity_jeep_kwh:
name: EVCS - Capacité mesurée JEEP name: EVCS - Capacité mesurée JEEP
min: 1 min: 1
@@ -94,6 +110,41 @@ input_number:
unit_of_measurement: kWh unit_of_measurement: kWh
mode: box mode: box
icon: mdi:car-battery icon: mdi:car-battery
victron_evcs_capacity_zero_kwh:
name: EVCS - Capacité mesurée ZERO (0 = inconnue)
min: 0
max: 100
step: 0.1
unit_of_measurement: kWh
mode: box
icon: mdi:motorbike-electric
# Puissance que le chargeur EMBARQUE absorbe a consigne pleine (plateau
# mesure). VW 3 680 W et JEEP 3 655 W le 05/09 (MANUEL §0). 0 = inconnue :
# le bilan ne borne alors pas ce que le vehicule peut prendre avant son depart.
victron_evcs_charger_kw_jeep:
name: EVCS - Puissance de charge JEEP (mesurée)
min: 0
max: 22
step: 0.01
unit_of_measurement: kW
mode: box
icon: mdi:ev-station
victron_evcs_charger_kw_vw:
name: EVCS - Puissance de charge VW (mesurée)
min: 0
max: 22
step: 0.01
unit_of_measurement: kW
mode: box
icon: mdi:ev-station
victron_evcs_charger_kw_zero:
name: EVCS - Puissance de charge ZERO (0 = inconnue)
min: 0
max: 22
step: 0.01
unit_of_measurement: kW
mode: box
icon: mdi:ev-station
input_text: input_text:
# Jours ou la JEEP repart apres le dejeuner (lun mar mer jeu ven sam dim). # Jours ou la JEEP repart apres le dejeuner (lun mar mer jeu ven sam dim).
@@ -101,6 +152,14 @@ input_text:
name: EVCS - Jours de départ JEEP après midi name: EVCS - Jours de départ JEEP après midi
max: 60 max: 60
icon: mdi:calendar-week icon: mdi:calendar-week
victron_evcs_vw_midday_departure_days:
name: EVCS - Jours de départ VW après midi
max: 60
icon: mdi:calendar-week
victron_evcs_zero_midday_departure_days:
name: EVCS - Jours de départ ZERO après midi
max: 60
icon: mdi:calendar-week
automation: automation:
- id: evcs_niveau_vehicule_reference - id: evcs_niveau_vehicule_reference

View File

@@ -349,7 +349,7 @@ const typical = coverage(slotsP50, hcFloorTypicalPct);
const prudent = coverage(slotsP80, hcFloorPrudentPct); const prudent = coverage(slotsP80, hcFloorPrudentPct);
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// VOITURE BRANCHEE EN HC AVEC UN DEPART AVANT LA PROCHAINE HC (28/09/2026) // VEHICULE BRANCHE EN HC AVEC UN DEPART AVANT LA PROCHAINE HC (28/09/2026)
// //
// Regle du proprietaire : « JEEP branchee engage le reseau en HC midi si // Regle du proprietaire : « JEEP branchee engage le reseau en HC midi si
// l'analyse de production le justifie ». La JEEP repart a 15:30 certains jours // l'analyse de production le justifie ». La JEEP repart a 15:30 certains jours
@@ -369,14 +369,17 @@ const prudent = coverage(slotsP80, hcFloorPrudentPct);
// moins ce que la borne a deja delivre depuis la saisie. Aucun capteur ne donne // moins ce que la borne a deja delivre depuis la saisie. Aucun capteur ne donne
// le niveau de la voiture : sans saisie valable, la regle se tait. // le niveau de la voiture : sans saisie valable, la regle se tait.
// //
// Deux constantes, justifiees : // Vaut pour les TROIS vehicules (JEEP, VW, moto ZERO) : capacite, puissance de
// - 3,7 kW : plateau MESURE des deux vehicules du foyer (3 655 et 3 680 W a // charge et calendrier viennent de HA pour le vehicule selectionne.
// consigne pleine, MANUEL §0) ; au-dela la voiture n'absorbe rien de plus. // La puissance du chargeur EMBARQUE (plateau mesure : JEEP 3,66 kW, VW
// - 0,5 kWh : seuil de manque en dessous duquel une session ne se justifie // 3,68 kW) borne ce que le vehicule peut prendre avant son depart ; inconnue
// pas — une fermeture du contacteur coute 50 a 150 Wh de transitoire (§57), // (0), on ne borne pas — l'erreur va alors vers « reseau justifie », c'est-a-
// on exige un gain d'au moins trois fois ce cout. // dire vers le vehicule charge, jamais vers la batterie videe.
const VEHICLE_CHARGER_KW = 3.7; // Seuil de 0,5 kWh : en dessous une session ne se justifie pas — une fermeture
// du contacteur coute 50 a 150 Wh de transitoire (§57), on exige un gain d'au
// moins trois fois ce cout.
const VEHICLE_GRID_MIN_SHORTFALL_KWH = 0.5; const VEHICLE_GRID_MIN_SHORTFALL_KWH = 0.5;
const vehicleChargerKw = num(input.vehicle_charger_kw, NaN);
const nowMsBalance = num(input.nowMs, Date.now()); const nowMsBalance = num(input.nowMs, Date.now());
const vehicleConnected = input.vehicle_connected === true || input.vehicle_connected === 'true'; const vehicleConnected = input.vehicle_connected === true || input.vehicle_connected === 'true';
const vehicleDepartureMs = num(input.vehicle_departure_ms, NaN); const vehicleDepartureMs = num(input.vehicle_departure_ms, NaN);
@@ -414,7 +417,9 @@ if (vehicleRuleActive) {
? energyBetweenSoc(plancherDepart, socPct) ? energyBetweenSoc(plancherDepart, socPct)
: -energyBetweenSoc(socPct, plancherDepart); : -energyBetweenSoc(socPct, plancherDepart);
vehicleSolarKwh = Math.max(0, batterieAuDessusKwh + netKwh); vehicleSolarKwh = Math.max(0, batterieAuDessusKwh + netKwh);
vehicleReachableKwh = Math.min(vehicleNeedKwh, VEHICLE_CHARGER_KW * (vehicleDepartureMs - nowMsBalance) / 3600000); vehicleReachableKwh = Number.isFinite(vehicleChargerKw) && vehicleChargerKw > 0
? Math.min(vehicleNeedKwh, vehicleChargerKw * (vehicleDepartureMs - nowMsBalance) / 3600000)
: vehicleNeedKwh;
vehicleShortfallKwh = Math.max(0, vehicleReachableKwh - vehicleSolarKwh); vehicleShortfallKwh = Math.max(0, vehicleReachableKwh - vehicleSolarKwh);
} }
const vehicleGridNeeded = vehicleRuleActive && vehicleShortfallKwh > VEHICLE_GRID_MIN_SHORTFALL_KWH; const vehicleGridNeeded = vehicleRuleActive && vehicleShortfallKwh > VEHICLE_GRID_MIN_SHORTFALL_KWH;

View File

@@ -20,20 +20,24 @@
{%- if w[0] >= repere and ns.suivant == '' -%}{%- set ns.suivant = w[0] -%}{%- endif -%} {%- if w[0] >= repere and ns.suivant == '' -%}{%- set ns.suivant = w[0] -%}{%- endif -%}
{%- if w[0] >= repere and w[2] == 'nuit' and ns.nuit == '' -%}{%- set ns.nuit = w[0] -%}{%- endif -%} {%- if w[0] >= repere and w[2] == 'nuit' and ns.nuit == '' -%}{%- set ns.nuit = w[0] -%}{%- endif -%}
{%- endfor -%} {%- endfor -%}
{#- Voiture branchee a midi (28/09/2026). Le calendrier (jours et heure de {#- Vehicule branche a midi (28/09/2026) — JEEP, VW ou ZERO, selon le
depart de la JEEP apres le dejeuner) reste dans HA : le bilan recoit un selecteur. Pour chacun, HA porte le calendrier (jours et heure de depart
instant de depart, vide si la voiture ne repart pas aujourd'hui. Le niveau apres le dejeuner), la capacite et la puissance de charge MESUREES ; le
saisi n'est retenu que s'il date de ce branchement (tolerance 1 h avant). -#} bilan recoit un instant de depart, vide si le vehicule ne repart pas
{%- set vh = namespace(dep='', valide=false, cap=none) -%} aujourd'hui. Le niveau saisi n'est retenu que s'il date de ce branchement
(tolerance 1 h avant). Capacite ou puissance a 0 = inconnue. -#}
{%- set vh = namespace(dep='', valide=false, cap=none, kw=none) -%}
{%- set jours = ['lun', 'mar', 'mer', 'jeu', 'ven', 'sam', 'dim'] -%} {%- set jours = ['lun', 'mar', 'mer', 'jeu', 'ven', 'sam', 'dim'] -%}
{%- if is_state('input_select.victron_evcs_vehicle', 'JEEP') -%} {%- set cle = {'JEEP': 'jeep', 'VW': 'vw', 'ZERO': 'zero'}.get(states('input_select.victron_evcs_vehicle')) -%}
{%- set vh.cap = states('input_number.victron_evcs_capacity_jeep_kwh') -%} {%- if cle -%}
{%- if jours[now().weekday()] in states('input_text.victron_evcs_jeep_midday_departure_days') | lower -%} {%- set vh.cap = states('input_number.victron_evcs_capacity_' ~ cle ~ '_kwh') -%}
{%- set d = today_at(states('input_datetime.victron_evcs_jeep_midday_departure')) -%} {%- set vh.kw = states('input_number.victron_evcs_charger_kw_' ~ cle) -%}
{%- set heure = states('input_datetime.victron_evcs_' ~ cle ~ '_midday_departure') -%}
{%- if jours[now().weekday()] in states('input_text.victron_evcs_' ~ cle ~ '_midday_departure_days') | lower
and heure not in ['unknown', 'unavailable', ''] -%}
{%- set d = today_at(heure) -%}
{%- if d > now() -%}{%- set vh.dep = d -%}{%- endif -%} {%- if d > now() -%}{%- set vh.dep = d -%}{%- endif -%}
{%- endif -%} {%- endif -%}
{%- elif is_state('input_select.victron_evcs_vehicle', 'VW') -%}
{%- set vh.cap = states('input_number.victron_evcs_capacity_vw_kwh') -%}
{%- endif -%} {%- endif -%}
{%- set branche = states.binary_sensor.victron_evcs_vehicle_connected -%} {%- set branche = states.binary_sensor.victron_evcs_vehicle_connected -%}
{%- set niveau = states.input_number.victron_evcs_vehicle_level_pct -%} {%- set niveau = states.input_number.victron_evcs_vehicle_level_pct -%}
@@ -47,6 +51,7 @@
"vehicle_level_pct": states("input_number.victron_evcs_vehicle_level_pct"), "vehicle_level_pct": states("input_number.victron_evcs_vehicle_level_pct"),
"vehicle_level_valid": vh.valide, "vehicle_level_valid": vh.valide,
"vehicle_capacity_kwh": vh.cap, "vehicle_capacity_kwh": vh.cap,
"vehicle_charger_kw": vh.kw,
"vehicle_delivered_since_level_kwh": ((states("sensor.evcs_hq2239dnt7p_total_energy") | float(0)) - (states("input_number.victron_evcs_vehicle_level_ref_kwh") | float(0))) if states("sensor.evcs_hq2239dnt7p_total_energy") | is_number else none, "vehicle_delivered_since_level_kwh": ((states("sensor.evcs_hq2239dnt7p_total_energy") | float(0)) - (states("input_number.victron_evcs_vehicle_level_ref_kwh") | float(0))) if states("sensor.evcs_hq2239dnt7p_total_energy") | is_number else none,
"hc_window_end_ms": (as_timestamp(ns.fin) * 1000) if ns.fin != '' else none, "hc_window_end_ms": (as_timestamp(ns.fin) * 1000) if ns.fin != '' else none,
"next_hc_start_ms": (as_timestamp(ns.suivant) * 1000) if ns.suivant != '' else none, "next_hc_start_ms": (as_timestamp(ns.suivant) * 1000) if ns.suivant != '' else none,

View File

@@ -60,12 +60,13 @@ return [{
// Plancher de charge HC manuelle (18/09) : oublie ici jusqu'au 28/09, le // Plancher de charge HC manuelle (18/09) : oublie ici jusqu'au 28/09, le
// bouton n'avait donc jamais atteint le bilan. // bouton n'avait donc jamais atteint le bilan.
manual_hc_floor_percent: snapshot.manual_hc_floor_percent, manual_hc_floor_percent: snapshot.manual_hc_floor_percent,
// Voiture branchee a midi (28/09) : depart du jour et besoin saisi. // Vehicule branche a midi (28/09, JEEP/VW/ZERO) : depart du jour et besoin saisi.
vehicle_connected: snapshot.vehicle_connected, vehicle_connected: snapshot.vehicle_connected,
vehicle_departure_ms: snapshot.vehicle_departure_ms, vehicle_departure_ms: snapshot.vehicle_departure_ms,
vehicle_level_pct: snapshot.vehicle_level_pct, vehicle_level_pct: snapshot.vehicle_level_pct,
vehicle_level_valid: snapshot.vehicle_level_valid, vehicle_level_valid: snapshot.vehicle_level_valid,
vehicle_capacity_kwh: snapshot.vehicle_capacity_kwh, vehicle_capacity_kwh: snapshot.vehicle_capacity_kwh,
vehicle_charger_kw: snapshot.vehicle_charger_kw,
vehicle_delivered_since_level_kwh: snapshot.vehicle_delivered_since_level_kwh, vehicle_delivered_since_level_kwh: snapshot.vehicle_delivered_since_level_kwh,
hc_window_end_ms: snapshot.hc_window_end_ms, hc_window_end_ms: snapshot.hc_window_end_ms,
next_hc_start_ms: snapshot.next_hc_start_ms, next_hc_start_ms: snapshot.next_hc_start_ms,

View File

@@ -100,6 +100,7 @@
"departure_time": states("input_datetime.victron_evcs_departure_time"), "departure_time": states("input_datetime.victron_evcs_departure_time"),
"departure_time_jeep": states("input_datetime.victron_evcs_departure_time_jeep"), "departure_time_jeep": states("input_datetime.victron_evcs_departure_time_jeep"),
"departure_time_zero": states("input_datetime.victron_evcs_departure_time_zero"),
"evcs_vehicle": states("input_select.victron_evcs_vehicle"), "evcs_vehicle": states("input_select.victron_evcs_vehicle"),
"allow_grid_departure_urgent": states("input_boolean.victron_evcs_allow_grid_departure_urgent"), "allow_grid_departure_urgent": states("input_boolean.victron_evcs_allow_grid_departure_urgent"),
"last_start_at": states("input_datetime.victron_evcs_last_start_at"), "last_start_at": states("input_datetime.victron_evcs_last_start_at"),

View File

@@ -445,6 +445,8 @@ const params = {
// Le sélecteur input_select.victron_evcs_vehicle choisit l'heure de départ // Le sélecteur input_select.victron_evcs_vehicle choisit l'heure de départ
// effective : VW = victron_evcs_departure_time (~08:50), // effective : VW = victron_evcs_departure_time (~08:50),
// JEEP = victron_evcs_departure_time_jeep (~06:30). // JEEP = victron_evcs_departure_time_jeep (~06:30).
// ZERO (moto, 28/09/2026) = victron_evcs_departure_time_zero. Heure absente
// ou illisible -> repli sur celle de la VW, comme la JEEP.
selectedVehicle: cleanText(input.evcs_vehicle, 'VW'), selectedVehicle: cleanText(input.evcs_vehicle, 'VW'),
departureTimeMin: departureTimeMin:
low(input.evcs_vehicle || 'vw') === 'jeep' low(input.evcs_vehicle || 'vw') === 'jeep'
@@ -452,7 +454,12 @@ const params = {
input.departure_time_jeep, input.departure_time_jeep,
parseTimeToMinutes(input.departure_time, null) parseTimeToMinutes(input.departure_time, null)
) )
: parseTimeToMinutes(input.departure_time, null), : low(input.evcs_vehicle || 'vw') === 'zero'
? parseTimeToMinutes(
input.departure_time_zero,
parseTimeToMinutes(input.departure_time, null)
)
: parseTimeToMinutes(input.departure_time, null),
allowGridDepartureUrgent: low(input.allow_grid_departure_urgent || 'off') === 'on', allowGridDepartureUrgent: low(input.allow_grid_departure_urgent || 'off') === 'on',
dayStartTimeMin: parseTimeToMinutes(input.day_start_time, 7 * 60 + 30), dayStartTimeMin: parseTimeToMinutes(input.day_start_time, 7 * 60 + 30),
dayStopTimeMin: parseTimeToMinutes(input.day_stop_time, 20 * 60 + 30), dayStopTimeMin: parseTimeToMinutes(input.day_stop_time, 20 * 60 + 30),

View File

@@ -69,7 +69,8 @@ const SOMBRE = 18 / 25.1;
function jeep(snapshot, niveau, extra = {}) { function jeep(snapshot, niveau, extra = {}) {
return Object.assign(snapshot, { vehicle_connected: true, return Object.assign(snapshot, { vehicle_connected: true,
vehicle_departure_ms: Date.parse('2026-09-27T15:30:00+02:00'), vehicle_level_pct: niveau, vehicle_departure_ms: Date.parse('2026-09-27T15:30:00+02:00'), vehicle_level_pct: niveau,
vehicle_level_valid: true, vehicle_capacity_kwh: 8.7, vehicle_delivered_since_level_kwh: 0 }, extra); vehicle_level_valid: true, vehicle_capacity_kwh: 8.7, vehicle_charger_kw: 3.7,
vehicle_delivered_since_level_kwh: 0 }, extra);
} }
export const balanceScenarios = [ export const balanceScenarios = [
@@ -489,4 +490,26 @@ export const balanceScenarios = [
snapshot: jeep(snap2709('2026-09-27T15:00:00+02:00', 30, null, SOMBRE), 12), snapshot: jeep(snap2709('2026-09-27T15:00:00+02:00', 30, null, SOMBRE), 12),
expect: { usable: true, vehicleActive: false, vehicleGridNeeded: false }, expect: { usable: true, vehicleActive: false, vehicleGridNeeded: false },
}, },
// ======== LES TROIS VEHICULES (28/09/2026) ========
{
node: 'BALANCE',
id: 'bilan-vehicule-capacite-inconnue-regle-muette',
label: 'Moto ZERO, capacite non mesuree (0) : on ne devine pas son besoin, la regle se tait',
snapshot: jeep(snap2709('2026-09-27T12:30:00+02:00', 30, MIDI_2709, SOMBRE), 12, { vehicle_capacity_kwh: 0 }),
expect: { usable: true, vehicleActive: false, vehicleGridNeeded: false },
},
{
node: 'BALANCE',
id: 'bilan-vehicule-puissance-bornee',
label: 'Chargeur embarque a 3,7 kW, 3 h avant le depart : le vehicule ne peut pas prendre plus de 11,1 kWh',
snapshot: jeep(snap2709('2026-09-27T12:30:00+02:00', 30, MIDI_2709, SOMBRE), 0, { vehicle_capacity_kwh: 15 }),
expect: { usable: true, vehicleActive: true, vehicleNeedKwh: 15, vehicleReachableKwh: 11.1, vehicleGridNeeded: true },
},
{
node: 'BALANCE',
id: 'bilan-vehicule-puissance-inconnue-non-bornee',
label: 'Puissance de charge inconnue (0) : on ne borne pas, tout le besoin est compte',
snapshot: jeep(snap2709('2026-09-27T12:30:00+02:00', 30, MIDI_2709, SOMBRE), 0, { vehicle_capacity_kwh: 15, vehicle_charger_kw: 0 }),
expect: { usable: true, vehicleActive: true, vehicleReachableKwh: 15, vehicleGridNeeded: true },
},
]; ];

View File

@@ -216,6 +216,37 @@ export const scenarios = [
takeoverHelperService: 'turn_off', takeoverHelperService: 'turn_off',
}, },
}, },
{
// ZERO (moto, 28/09/2026) : elle a SA propre heure de depart. Meme matin que
// p9-depart-vw-grid, VW a 08:50 : la ZERO part a 08:30, donc la fenetre P9
// est ouverte pour elle aussi.
id: 'p9-depart-zero-sa-propre-heure',
label: 'Matin 08:00, ZERO sélectionnée, départ ZERO 08:30, toggle P9 ON → réseau autorisé sur SON heure',
time: '2026-08-10T08:00:00+02:00',
overrides: {
...VEHICLE_NIGHT, soc_percent: '45',
evcs_vehicle: 'ZERO',
departure_time: '08:50:00',
departure_time_jeep: '06:30:00',
departure_time_zero: '08:30:00',
allow_grid_departure_urgent: 'on',
},
expect: { profile: 'morning_solar', sourceMode: 'grid_hc_allowed', edfOnAction: true },
},
{
id: 'p9-depart-zero-passe',
label: 'CONTREFACTUEL — ZERO partie a 07:00 : sa fenetre est passee, meme si celle de la VW (08:50) serait ouverte',
time: '2026-08-10T08:00:00+02:00',
overrides: {
...VEHICLE_NIGHT, soc_percent: '45',
evcs_vehicle: 'ZERO',
departure_time: '08:50:00',
departure_time_jeep: '06:30:00',
departure_time_zero: '07:00:00',
allow_grid_departure_urgent: 'on',
},
expect: { profile: 'morning_solar', sourceMode: 'blocked', edfOnAction: false },
},
{ {
id: 'p9-done-idle-collant', id: 'p9-done-idle-collant',
label: 'Matin 08:10, VW pleine détectée (prev=vehicle_full_or_paused) pendant la fenêtre départ → veille collante, réseau relâché', label: 'Matin 08:10, VW pleine détectée (prev=vehicle_full_or_paused) pendant la fenêtre départ → veille collante, réseau relâché',

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long