Jour faible : session HC midi et nuit engagee pour le chauffe-eau ; alerte « passe en BOOST » si pompe a chaleur en HC ; HANDOFF

This commit is contained in:
Tallagrand Thierry
2026-10-07 07:50:39 +02:00
parent b142429920
commit 9094984069
13 changed files with 199 additions and 13 deletions

View File

@@ -1983,5 +1983,32 @@ sur VRM comme le bilan, un seul workflow, securite eau chaude 1,5 kWh / 24 h.
Forecast.Solar), bloc « Jour faible », historique avec jour faible / coupure / EDF. Rendus verifies par
`/api/template`.
### 07/10 ~07:50 — HC pleine consommation pour le chauffe-eau, alerte BOOST, Victron Mobile refait
**Regle du proprietaire** : « aux HC de midi, consommation MAX toute la duree, AUTO ne fera pas le job » ;
si le ballon consomme peu en HC (pompe a chaleur), une alarme lui demande de passer en BOOST, sinon la
douche ne sera pas a 65 °C (06:00 et 20:00, tous les jours). Journee test : le 07/10 (jour faible).
- **Controleur (deploye 07:46, golden 142/142, +4, mutations qui mordent)** : `input_boolean.evcs_balance_ecs_nuit`
-> `params.balanceEcsNuit` (gabarit + INPUT_PARSE) ; WINDOWS : `hcEcsGridNeeded` engage la session HC de
MIDI, et la nuit `nightGridSessionUncovered` = batterie sous la cible OU jour faible. Memes gardes que la
cible (bilan frais, statut ok). Effet : jour faible -> EDF ferme les deux fenetres HC entieres, le
workflow ECS alimente le ballon (session engagee + contacteur ferme). ACM 20/20, hysteresis 24/24.
- **Workflow ECS (deploye 07:48, tests 18/18)** : alerte `input_text.evcs_alerte_chauffe_eau` (paquet
`evcs_chauffe_eau_nuit.yaml`, max 255) = JSON {active, since = debut de la fenetre HC, fenetre,
puissance_w, message} quand, 15 min apres le debut d'une fenetre HC, session engagee, contacteur ferme,
ballon sous tension et regime `hp_low` (pompe a chaleur) ; vide sinon. 0 W (thermostat satisfait) ou
resistance -> pas d'alerte. Fenetres lues dans `input_datetime.victron_evcs_hc_*`. Envoi WhatsApp par le
concierge (SPARK), une fois par fenetre (dedup `since`). Premier passage reel : vide (07:50, hors HC).
Aussi : chauffe-eau coupe = 0 W (le compteur Tuya remonte avec retard : « arret — 1595 W »).
- **A observer aujourd'hui** : 12:24 session de midi engagee pour le chauffe-eau (EDF ferme), regime mesure,
alerte a 12:39 si pompe a chaleur ; kWh pris en HC ; securite 16 h-20 h ; nuit du 07->08 (session de nuit
engagee par le jour faible), douche de 06:00.
- **Victron Mobile refait (lecture seule)** : alertes reelles seulement (`sensor.evcs_reseau` muet ou
incoherent, cellules perimees/muettes, auto batterie OFF, override ; heartbeat dans la carte du jour),
batterie (W, A, cible du matin, requis), reseau sans action + achete du jour, energie du jour (produit,
VRM prevu/reste, consomme, achete, diagnostic PV), nuit (`texte_rapport` prevision le soir / bilan le
matin + mode de charge), borne, chauffe-eau, cellules, flux 4 h. Plus aucune fiche switch ouvrable
(contacteur, borne, chauffe-eau). Flux : `sensor.maison_hors_chauffe_eau` (template, sans chauffe-eau NI
borne malgre le nom) + courbes chauffe-eau et borne a part. Sauvegarde `victron_mobile.yaml.bak-20261007`.
---
*Document mis a jour le : 07/10/2026 (~07:45) — 1re decision jour faible en reel, mesure ECS reparee, douches 06:00/20:00, Grafana chauffe-eau, tableaux ECS ; chauffe-eau en HC de nuit les jours faibles (decision du bilan, workflow ECS sous controle du depot, VRM, V2.3 desactive) ; garde batterie reseau : voiture bridee a 6 A au lieu d'un arret ; garde-fou concierge 2 h ; allers-retours brefs de la borne retrouves dans l'historique HA (echange VW -> JEEP de 20 s), production 14,5 kWh contre 22 prevus, defaut garde batterie en mode reseau a trancher ; voiture a midi : la batterie n'est plus comptee comme du solaire (EDF automatique les jours de depart si le surplus ne couvre pas) ; nuit 05->06 : JEEP chargee sur EDF en complete (6,32 kWh), budget 0 du a la prevision, Windy/ECMWF contre VRM, a comparer ce soir ; concierge aligne sur la preuve fin de trajet ; a verifier : nuit 05->06 et mardi faible, comparaison VRM/Forecast.Solar ; JEEP identifiee aussi par sa fin de trajet, prevision de la nuit 05->06 ; identification JEEP reussie en reel, correction humaine qui prime (refus supprime), session du 04/10 coupee ; EVCS Master en quatre onglets ; Jeep lue par Uconnect et identifiee seule, capacite JEEP 10 kWh, concierge variante (a) ; releve par photo (SPARK), hass-uconnect en attente ; ecart semaine/week-end mesure (pas de profil week-end la nuit) ; nuit du budget : budget borne au plancher prudent, sans EDF = voiture bloquee meme EDF ferme (batterie seule) ; Energie : sauts corriges ; tableau Energie complete (Sud/Ouest, batterie par integration, borne ; aucun redemarrage HA) ; kilometrage des vehicules (km/kWh, capacite, releves de reference, agent cable 15/15) ; a verifier le 04/10 au matin : nuit du budget JEEP ; concierge : vehicule non confirme demande, heure de saisie ; Grafana vehicules en tableau ; Grafana vehicules : ZERO et Invite ajoutes, session 16:46 reetiquetee ZERO ; prevision SOC 10 h ~35 % ; concierge fiable : niveau note par le script, une ligne, dedoublonnage, simulation par drapeau ; agent : message incompris = question, bourse sur demande explicite (banc final 6/6) ; a verifier : nuit du samedi 03 au dimanche 04/10 (budget < besoin JEEP), cron orange-cloture lundi 05/10 apres 17:40, comparaison VRM / Forecast.Solar lundi 05/10*
*Document mis a jour le : 07/10/2026 (~07:55) — jour faible = EDF les deux fenetres HC pour le chauffe-eau, alerte BOOST, Victron Mobile refait ; 1re decision jour faible en reel, mesure ECS reparee, douches 06:00/20:00, Grafana chauffe-eau, tableaux ECS ; chauffe-eau en HC de nuit les jours faibles (decision du bilan, workflow ECS sous controle du depot, VRM, V2.3 desactive) ; garde batterie reseau : voiture bridee a 6 A au lieu d'un arret ; garde-fou concierge 2 h ; allers-retours brefs de la borne retrouves dans l'historique HA (echange VW -> JEEP de 20 s), production 14,5 kWh contre 22 prevus, defaut garde batterie en mode reseau a trancher ; voiture a midi : la batterie n'est plus comptee comme du solaire (EDF automatique les jours de depart si le surplus ne couvre pas) ; nuit 05->06 : JEEP chargee sur EDF en complete (6,32 kWh), budget 0 du a la prevision, Windy/ECMWF contre VRM, a comparer ce soir ; concierge aligne sur la preuve fin de trajet ; a verifier : nuit 05->06 et mardi faible, comparaison VRM/Forecast.Solar ; JEEP identifiee aussi par sa fin de trajet, prevision de la nuit 05->06 ; identification JEEP reussie en reel, correction humaine qui prime (refus supprime), session du 04/10 coupee ; EVCS Master en quatre onglets ; Jeep lue par Uconnect et identifiee seule, capacite JEEP 10 kWh, concierge variante (a) ; releve par photo (SPARK), hass-uconnect en attente ; ecart semaine/week-end mesure (pas de profil week-end la nuit) ; nuit du budget : budget borne au plancher prudent, sans EDF = voiture bloquee meme EDF ferme (batterie seule) ; Energie : sauts corriges ; tableau Energie complete (Sud/Ouest, batterie par integration, borne ; aucun redemarrage HA) ; kilometrage des vehicules (km/kWh, capacite, releves de reference, agent cable 15/15) ; a verifier le 04/10 au matin : nuit du budget JEEP ; concierge : vehicule non confirme demande, heure de saisie ; Grafana vehicules en tableau ; Grafana vehicules : ZERO et Invite ajoutes, session 16:46 reetiquetee ZERO ; prevision SOC 10 h ~35 % ; concierge fiable : niveau note par le script, une ligne, dedoublonnage, simulation par drapeau ; agent : message incompris = question, bourse sur demande explicite (banc final 6/6) ; a verifier : nuit du samedi 03 au dimanche 04/10 (budget < besoin JEEP), cron orange-cloture lundi 05/10 apres 17:40, comparaison VRM / Forecast.Solar lundi 05/10*

View File

@@ -18,6 +18,14 @@ input_boolean:
icon: mdi:water-boiler-off
input_text:
# Alerte « passe en BOOST » (07/10/2026) : ecrite par le workflow ECS quand,
# en heures creuses sur EDF, le ballon ne tire que la pompe a chaleur. JSON
# {active, since, fenetre, puissance_w, message} ou chaine vide. Le concierge
# OpenClaw envoie le WhatsApp une fois par fenetre (dedup sur `since`).
evcs_alerte_chauffe_eau:
name: "Alerte : chauffe-eau, passer en BOOST"
max: 255
icon: mdi:water-boiler-alert
# « AAAA-MM-JJ|on|raison » : date de la decision, decision, explication.
evcs_balance_ecs_nuit_jour:
name: "EVCS - Chauffe-eau : decision du jour"

View File

@@ -175,6 +175,7 @@
"balance_status": states("input_text.evcs_balance_status"),
"balance_last_run": states("input_text.evcs_balance_last_run"),
"balance_vehicle_grid_needed": states("input_boolean.evcs_balance_vehicle_grid_needed"),
"balance_ecs_nuit": states("input_boolean.evcs_balance_ecs_nuit"),
"allow_grid_hc_midday": states("input_boolean.victron_evcs_allow_grid_hc_midday"),
"probe_enabled": states("input_boolean.victron_evcs_probe_enabled"),

View File

@@ -501,6 +501,9 @@ const params = {
// Voiture branchee en HC avec un depart avant la prochaine HC (28/09) : le
// bilan juge que le solaire ne lui donnera pas son besoin avant le depart.
balanceVehicleGridNeeded: low(input.balance_vehicle_grid_needed || 'off') === 'on',
// Jour faible (07/10/2026) : decision quotidienne du bilan, l'eau chaude se
// fait en HC sur EDF -> la session reseau HC (nuit ET midi) s'engage.
balanceEcsNuit: low(input.balance_ecs_nuit || 'off') === 'on',
// P12 — charge nuit sur batterie. Le plancher est le SOC requis PRUDENT (p80)
// et non le p50 : la marge est mesuree, pas inventee. On descend la voiture
// jusqu'a ce que la batterie n'ait plus que ce qu'il lui faut pour tenir

View File

@@ -763,7 +763,8 @@ const nightGridSessionCommittedPrev =
(input.night_grid_session_committed_prev ?? 'off').toString().trim().toLowerCase() === 'on';
const nightGridSessionUncovered =
balanceMorningTargetApplied && batteryBelowMorningTarget;
balanceMorningTargetApplied &&
(batteryBelowMorningTarget || params.balanceEcsNuit);
// ⚠️ SANS VEHICULE AUSSI (12/09/2026).
// Nuit du 11-12/09, voiture rendue la veille : le bilan a reclame entre 92 %
@@ -814,12 +815,23 @@ const middayVehicleGridNeeded =
params.balanceVehicleGridNeeded &&
parsed.evcsVehicleConnected;
// ET LE CHAUFFE-EAU (07/10/2026, proprietaire) : un jour faible, l'eau chaude
// se fait en heures creuses sur EDF, a PLEINE consommation toute la fenetre
// (douches de 06:00 et 20:00 a 65 °C ; le 06/10 le ballon avait pris 5,4 kWh
// de solaire de 10 h a 15 h, l'energie qui manquait a la batterie). Le bilan
// decide une fois par jour (input_boolean.evcs_balance_ecs_nuit) ; le workflow
// ECS n'alimente le ballon que si la session est engagee ET le contacteur
// ferme. Memes gardes de fraicheur et de statut que la cible.
const hcEcsGridNeeded =
balanceMorningTargetApplied && params.balanceEcsNuit;
const middayGridSessionUncovered =
balanceMorningTargetApplied &&
(
(Number.isFinite(params.balanceRequiredSocPct) &&
parsed.soc < params.balanceRequiredSocPct) ||
middayVehicleGridNeeded
middayVehicleGridNeeded ||
hcEcsGridNeeded
);
const gridSessionInHcWindow =

View File

@@ -329,6 +329,36 @@ if (advisorEnabled && ecsNuit) {
reason.push('Jour normal : chauffe-eau remis sous tension (il chauffe au solaire)');
}
// =====================================================
// ALERTE « PASSE EN BOOST » (07/10/2026, proprietaire)
// =====================================================
// En heures creuses sur EDF, le ballon doit consommer AU MAXIMUM toute la
// fenetre : en AUTO il reste sur la pompe a chaleur (lent, 55 °C) et la douche
// ne sera pas a 65 °C (20 h apres la HC de midi, 06 h apres celle de nuit).
// Si, 15 min apres le debut de la fenetre, session engagee, contacteur ferme et
// ballon sous tension, il ne tire que la puissance de la pompe a chaleur
// (regime hp_low), on le SIGNALE : input_text.evcs_alerte_chauffe_eau (JSON,
// `since` = debut de la fenetre -> un seul message par fenetre, envoye par le
// concierge OpenClaw). 0 W = thermostat satisfait : pas d'alerte.
const ALERTE_DELAI_MIN = 15;
const minNow = Number.isFinite(now.minNow) ? now.minNow : null;
const fenetreHc = (normalized.hcWindows || []).find((w) => minNow !== null && (
w.debut <= w.fin ? (minNow >= w.debut && minNow < w.fin) : (minNow >= w.debut || minNow < w.fin)));
const depuisDebutMin = fenetreHc ? ((minNow - fenetreHc.debut + 1440) % 1440) : null;
const alerteBoost = !!fenetreHc && depuisDebutMin >= ALERTE_DELAI_MIN
&& hcSessionCommitted && gridIsOn && waterHeaterSwitchOn && observedRegime === 'hp_low';
let alerteChauffeEau = '';
if (alerteBoost) {
const h = String(Math.floor(fenetreHc.debut / 60)).padStart(2, '0') + ':' + String(fenetreHc.debut % 60).padStart(2, '0');
const jourFenetre = (fenetreHc.debut > fenetreHc.fin && minNow < fenetreHc.fin)
? new Date(nowMs - 86400000).toLocaleDateString('sv-SE', { timeZone: 'Europe/Paris' }) : now.date;
alerteChauffeEau = JSON.stringify({
active: true, since: `${jourFenetre} ${h}`, fenetre: fenetreHc.nom,
puissance_w: Math.round(observedPowerW),
message: `🚿 Heures creuses EDF : le chauffe-eau ne tire que ${Math.round(observedPowerW)} W (pompe a chaleur). Passe-le en BOOST pour avoir 65 °C a ${fenetreHc.douche}.`,
});
}
return [{
json: {
...root,
@@ -366,7 +396,8 @@ return [{
powerSwitchAction,
powerSwitchDesiredOn,
offJourFaible,
jourFaibleState
jourFaibleState,
alerteChauffeEau
}
}
}];

View File

@@ -33,6 +33,10 @@
"ecs_24h_kwh": states("sensor.evcs_chauffe_eau_24h_kwh"),
"ecs_jour_kwh": states("sensor.evcs_chauffe_eau_jour_kwh"),
"off_jour_faible_prev": states("input_boolean.victron_water_heater_off_jour_faible"),
"hc_midday_start": states("input_datetime.victron_evcs_hc_midday_start"),
"hc_midday_stop": states("input_datetime.victron_evcs_hc_midday_stop"),
"hc_night_start": states("input_datetime.victron_evcs_hc_night_start"),
"hc_night_stop": states("input_datetime.victron_evcs_hc_night_stop"),
"advisor_enabled": states("input_boolean.victron_water_heater_advisor_enabled"),
"notifications_enabled": states("input_boolean.victron_water_heater_notifications"),

View File

@@ -198,6 +198,12 @@ const ecs24hKwh = num(input.ecs_24h_kwh, NaN);
const ecsJourKwh = num(input.ecs_jour_kwh, NaN);
const offJourFaiblePrev = low(input.off_jour_faible_prev) === 'on';
const forecastSource = cleanStateText(input.forecast_source) || 'forecast_solar';
// Fenetres HC (« HH:MM:SS » des input_datetime du controleur), en minutes du jour.
const hhmm = (v) => { const m = cleanStateText(v).match(/^(\d{1,2}):(\d{2})/); return m ? Number(m[1]) * 60 + Number(m[2]) : null; };
const hcWindows = [
{ nom: 'midi', debut: hhmm(input.hc_midday_start), fin: hhmm(input.hc_midday_stop), douche: '20 h' },
{ nom: 'nuit', debut: hhmm(input.hc_night_start), fin: hhmm(input.hc_night_stop), douche: '06 h' },
].filter((w) => w.debut !== null && w.fin !== null);
return [{
json: {
@@ -246,7 +252,8 @@ return [{
ecs24hKwh,
ecsJourKwh,
offJourFaiblePrev,
forecastSource
forecastSource,
hcWindows
}
}
}];

View File

@@ -196,7 +196,8 @@ let {
protectionState,
powerSwitchAction,
powerSwitchDesiredOn,
offJourFaible = false
offJourFaible = false,
alerteChauffeEau = ''
} = finalDecision;
reason = Array.isArray(reason) ? [...reason] : [];
@@ -563,6 +564,15 @@ helper_budget_margin: {
datetime: forcedOffAtSafe
}
},
// Alerte « passe en BOOST » (07/10/2026), lue par le concierge OpenClaw.
helper_alerte_chauffe_eau: {
domain: 'input_text',
service: 'set_value',
data: {
entity_id: 'input_text.evcs_alerte_chauffe_eau',
value: alerteChauffeEau
}
},
// Jour faible (07/10/2026) : la coupure appartient a la regle « eau chaude en HC de nuit ».
helper_off_jour_faible: {
domain: 'input_boolean',

View File

@@ -2639,6 +2639,67 @@ export const scenarios = [
},
expect: { profile: 'midday_hc_or_solar', sessionCommittedService: 'turn_on', takeoverNeeded: true },
},
// CHAUFFE-EAU (07/10/2026) : un jour faible, l'eau chaude se fait en HC sur
// EDF a pleine consommation -> la session HC s'engage meme sans voiture et
// sans manque batterie.
{
id: 'hc-midi-jour-faible-chauffe-eau-engage-la-session',
label: 'MIDI — jour faible (decision du bilan), pas de voiture, SOC au-dessus du requis : la session HC s engage pour le chauffe-eau',
time: MIDDAY,
overrides: {
evcs_vehicle_connected: 'off', evcs_device_connected: 'on',
soc_percent: '45', battery_current_a: '2',
pv_power_w: '1200', pv_power_10m_avg_w: '1200', pv_trend_w: '0',
house_ac_power_w: '900', vebus_ac_out_l1_power_w: '900', evcs_ac_power_w: '0',
balance_required_soc: '30', balance_energy_to_cover_kwh: '0', balance_grid_energy_needed_kwh: '0',
balance_status: 'ok', balance_last_run: '08/08 12:50',
balance_ecs_nuit: 'on',
},
expect: { profile: 'midday_hc_or_solar', sessionCommittedService: 'turn_on', takeoverNeeded: true },
},
{
id: 'hc-midi-jour-faible-bilan-perime-aucun-engagement',
label: 'CONTREFACTUEL — jour faible mais bilan vieux de 2 h : on ne relaie pas une decision perimee',
time: MIDDAY,
overrides: {
evcs_vehicle_connected: 'off', evcs_device_connected: 'on',
soc_percent: '45', battery_current_a: '2',
pv_power_w: '1200', pv_power_10m_avg_w: '1200', pv_trend_w: '0',
house_ac_power_w: '900', vebus_ac_out_l1_power_w: '900', evcs_ac_power_w: '0',
balance_required_soc: '30', balance_energy_to_cover_kwh: '0', balance_grid_energy_needed_kwh: '0',
balance_status: 'ok', balance_last_run: '08/08 11:00',
balance_ecs_nuit: 'on',
},
expect: { profile: 'midday_hc_or_solar', takeoverNeeded: false },
},
{
id: 'hc-nuit-jour-faible-chauffe-eau-engage-la-session',
label: 'NUIT 03:00 — jour faible, SOC 45 au-dessus du requis 30 : la session de nuit s engage quand meme pour le chauffe-eau',
time: '2026-08-08T03:00:00+02:00',
overrides: {
evcs_vehicle_connected: 'off', evcs_device_connected: 'on',
soc_percent: '45', battery_current_a: '-3',
house_ac_power_w: '700', vebus_ac_out_l1_power_w: '700', evcs_ac_power_w: '0',
balance_required_soc: '30', balance_energy_to_cover_kwh: '2.0',
balance_status: 'ok', balance_last_run: '08/08 02:58',
balance_ecs_nuit: 'on',
},
expect: { profile: 'night_hc', sessionCommittedService: 'turn_on', takeoverNeeded: true },
},
{
id: 'hc-nuit-jour-normal-aucun-engagement',
label: 'CONTREFACTUEL — meme nuit, jour normal : rien ne justifie EDF',
time: '2026-08-08T03:00:00+02:00',
overrides: {
evcs_vehicle_connected: 'off', evcs_device_connected: 'on',
soc_percent: '45', battery_current_a: '-3',
house_ac_power_w: '700', vebus_ac_out_l1_power_w: '700', evcs_ac_power_w: '0',
balance_required_soc: '30', balance_energy_to_cover_kwh: '2.0',
balance_status: 'ok', balance_last_run: '08/08 02:58',
balance_ecs_nuit: 'off',
},
expect: { profile: 'night_hc', takeoverNeeded: false },
},
{
id: 'hc-midi-jeep-sans-verdict-aucun-engagement',
label: 'CONTREFACTUEL — meme midi, le bilan juge le solaire suffisant : aucune session',

View File

@@ -81,6 +81,28 @@ for (const c of cas) {
if (o.observedPowerW === 0 && o.observedRegime === 'off') { ok++; console.log('✅ coupe-zero-watt'); }
else { ko++; console.log(`❌ coupe-zero-watt | ${o.observedPowerW} W ${o.observedRegime}`); }
}
// Alerte BOOST (07/10) : en HC sur EDF, le ballon ne tire que la pompe a chaleur.
{
const minuit = new Date(new Date().toLocaleDateString('sv-SE', { timeZone: 'Europe/Paris' }) + 'T00:00:00');
const nowMin = (() => { const p = new Intl.DateTimeFormat('fr-FR', { timeZone: 'Europe/Paris', hour: '2-digit', minute: '2-digit', hour12: false }).format(new Date()).split(':'); return Number(p[0]) * 60 + Number(p[1]); })();
const hm = (m) => { const x = ((m % 1440) + 1440) % 1440; return `${String(Math.floor(x / 60)).padStart(2, '0')}:${String(x % 60).padStart(2, '0')}:00`; };
const stamp = new Date(Date.now() - 5 * 60000).toLocaleString('sv-SE', { timeZone: 'Europe/Paris' });
const fenetre = { hc_midday_start: hm(nowMin - 30), hc_midday_stop: hm(nowMin + 60), hc_night_start: hm(nowMin + 300), hc_night_stop: hm(nowMin + 600) };
const base = { ...BASE, ...fenetre, grid_state: 'on', hc_session_committed: 'on', water_heater_switch: 'on',
water_heater_energy_total_kwh: '18.65', energy_total_prev_kwh: '18.60', energy_prev_at: stamp }; // 0,05 kWh / 5 min = 600 W : pompe a chaleur
const verif = (nom, snap, attenduAlerte) => {
const s = executer({ ...base, ...snap });
const a = s.ARBITRATION[0].json.finalDecision.alerteChauffeEau;
const ok1 = attenduAlerte ? (a && JSON.parse(a).active === true && JSON.parse(a).message.includes('BOOST')) : a === '';
const appel = s.BUILD_ACTIONS.map((x) => x.json).find((c) => c.data?.entity_id === 'input_text.evcs_alerte_chauffe_eau');
if (ok1 && appel) { ok++; console.log(`✅ ${nom}`); } else { ko++; console.log(`❌ ${nom} | alerte=${a} appel=${!!appel}`); }
};
verif('alerte-boost-pompe-a-chaleur-en-hc', {}, true);
verif('alerte-boost-resistance-pas-d-alerte', { water_heater_energy_total_kwh: '18.75' }, false);
verif('alerte-boost-thermostat-satisfait-pas-d-alerte', { water_heater_energy_total_kwh: '18.60' }, false);
verif('alerte-boost-debut-de-fenetre-attente', { hc_midday_start: hm(nowMin - 5) }, false);
verif('alerte-boost-edf-ouvert-pas-d-alerte', { grid_state: 'off' }, false);
}
// Prevision forte = le reste du jour seulement (06/10 : demain fort ne rend plus forte une journee faible).
{
const s = executer({ ...BASE, ecs_nuit: 'off', today_remaining_kwh: '8', tomorrow_kwh: '30' });

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long