Prevision de nuit : annoncer l'achat EDF reel (maison en HC + manque batterie)

Nuit du 28-29/09 : « environ 0,14 kWh a prendre sur EDF » annonces, 4,6 importes.
0,14 etait le manque de la batterie ; une session engagee fait passer toute la
maison sur le reseau jusqu'a 07:24. Le bilan publie la maison non couverte sur
la fenetre HC de nuit (input_number.evcs_balance_night_hc_house_kwh) et
sensor.evcs_prevision_nuit annonce import_prevu_kwh = maison + manque ;
reseau_necessaire_kwh supprime. Bilan 72/72, diagnostics 85/85.

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-29 10:46:13 +02:00
parent ebcba4637b
commit 24ccecbc02
11 changed files with 198 additions and 14 deletions

View File

@@ -336,7 +336,8 @@ for (const [nom, r, test] of imp) {
const t = new Date('2026-09-27T23:30:00Z'); // 01:30 a Paris
const pn = [
['nuit 28/09 : 5,77 kWh EDF, 5,47 a couvrir, retour 09 h, aucune voiture', previsionNuit(base(), t),
(r) => r.etat === 5.77 && r.attributs.voiture === 'aucune' && /5.77 kWh a prendre sur EDF/.test(r.attributs.explication)],
(r) => r.etat === 5.77 && r.attributs.voiture === 'aucune' && /au moins 5,77 kWh achetes/.test(r.attributs.explication)
&& /plus la consommation de la maison/.test(r.attributs.explication)],
['jamais 73,7 ni 26,95 dans la prevision (incident 27/09)', previsionNuit(base(), t),
(r) => !/73\.7|26\.95/.test(JSON.stringify(r))],
['bilan perime (> 30 min) -> indisponible', previsionNuit(base(), new Date('2026-09-28T00:30:00Z')),
@@ -370,6 +371,34 @@ for (const [nom, r, test] of imp) {
'sensor.victron_battery_soc': '70', 'input_boolean.victron_evcs_night_grid_session_committed': 'off',
})) m.set(k, { state: v }); return previsionNuit(m, t); })(),
(r) => r.attributs.verdict === 'juste'],
// Releve REEL du 28/09 21:32 : verdict reseau_necessaire, manque 0,14 kWh.
// L'agent a dit « environ 0,14 kWh a prendre sur EDF » ; le reseau en a
// fourni 4,6 (la maison sur le reseau de 01:24 a 07:24).
['28/09 21:32 : manque 0,14 mais la maison passe la nuit sur le reseau -> « environ 4,6 kWh achetes »', (() => {
const m = base(); for (const [k, v] of Object.entries({
'input_number.evcs_balance_grid_energy_needed_kwh': '0.14', 'input_boolean.victron_evcs_night_grid_session_committed': 'off',
'input_number.evcs_balance_night_hc_house_kwh': '4.5', 'sensor.evcs_reseau': 'non_raccorde',
'input_datetime.victron_evcs_hc_night_start': '01:24:00', 'input_datetime.victron_evcs_hc_night_stop': '07:24:00',
})) m.set(k, { state: v }); return previsionNuit(m, t); })(),
(r) => r.etat === 4.6 && r.attributs.verdict === 'reseau_necessaire' && r.attributs.import_prevu_kwh === 4.6
&& r.attributs.manque_batterie_kwh === 0.14
&& /EDF sera branche de 01:24 a 07:24 : environ 4,6 kWh achetes/.test(r.attributs.explication)
&& /maison 4,5, batterie 0,14/.test(r.attributs.explication)
&& !/0,14 kWh a prendre/.test(r.attributs.explication)],
['session engagee avec la maison connue -> achat = maison + batterie, jusqu a 07:24', (() => {
const m = base(); for (const [k, v] of Object.entries({
'input_number.evcs_balance_night_hc_house_kwh': '3.2', 'input_datetime.victron_evcs_hc_night_stop': '07:24:00',
})) m.set(k, { state: v }); return previsionNuit(m, t); })(),
(r) => r.etat === 9 && /jusqu a 07:24 : environ 9 kWh achetes/.test(r.attributs.explication)],
['« c est juste » annonce aussi l achat si EDF s engage', (() => {
const m = base(); for (const [k, v] of Object.entries({
'input_boolean.evcs_balance_grid_needed': 'off', 'input_number.evcs_balance_required_soc': '57.5',
'input_number.evcs_balance_required_soc_prudent': '68.5', 'sensor.victron_battery_soc': '58',
'input_boolean.victron_evcs_night_grid_session_committed': 'off', 'input_number.evcs_balance_night_hc_house_kwh': '4.46',
})) m.set(k, { state: v }); return previsionNuit(m, t); })(),
(r) => r.etat === 0 && r.attributs.verdict === 'juste' && /la maison y achetera alors environ 4,5 kWh/.test(r.attributs.explication)],
['plus jamais d attribut reseau_necessaire_kwh (lu comme un achat le 28/09)', previsionNuit(base(), t),
(r) => !('reseau_necessaire_kwh' in r.attributs) && 'import_prevu_kwh' in r.attributs],
['jamais d attribut qui ressemble a un SOC du matin (incident 21:16)', previsionNuit(base(), t),
(r) => !('soc_requis_au_retour_solaire_pct' in r.attributs) && 'soc_requis_maintenant_pct' in r.attributs],
];

View File

@@ -109,6 +109,9 @@ const SUMMARIZE = {
// Nuit prevue par la soiree (28/09).
nightModelActive: o.nightModel ? o.nightModel.active : false,
nightFactor: o.nightModel ? o.nightModel.factor : null,
// Maison sur le reseau pendant la fenetre HC de nuit (29/09).
nightHcActive: o.nightHcImport ? o.nightHcImport.active : false,
nightHcHouseKwh: o.nightHcImport ? o.nightHcImport.houseKwh : null,
// Voiture branchee en HC, depart avant la prochaine HC (28/09).
vehicleActive: o.vehicleMidday ? o.vehicleMidday.active : false,
vehicleNeedKwh: o.vehicleMidday ? o.vehicleMidday.needKwh : null,

View File

@@ -557,4 +557,47 @@ export const balanceScenarios = [
night_house_computed_ms: Date.parse('2026-09-27T22:57:00+02:00') }),
expect: { usable: true, nightModelActive: true, nightFactor: 1.45, requiredSocPct: 59.8, prudentRequiredSocPct: 62.2 },
},
// ======== CE QUE LA SESSION DE NUIT ACHETERA (29/09/2026) ========
// Nuit du 28-29/09 : « 0,14 kWh a prendre sur EDF » annonces, 4,6 importes :
// la session engagee fait passer TOUTE la maison sur le reseau de 01:24 a
// 07:24. Verifie a la main sur le profil p50 (pas de soleil avant 8 h) :
// 0,6 x 0,80 + 0,70 + 0,60 + 0,70 + 0,70 + 0,70 + 0,4 x 0,70 = 4,16 kWh.
{
node: 'BALANCE',
id: 'bilan-hc-nuit-maison-sur-le-reseau',
label: '23:00, fenetre HC de nuit 01:24-07:24 a venir : la maison y prendra 4,16 kWh au reseau',
snapshot: Object.assign(snap2709('2026-09-27T23:00:00+02:00', 52, null), {
night_hc_start_ms: Date.parse('2026-09-28T01:24:00+02:00'), night_hc_end_ms: Date.parse('2026-09-28T07:24:00+02:00') }),
expect: { usable: true, nightHcActive: true, nightHcHouseKwh: 4.16, requiredSocPct: 47.9 },
},
{
node: 'BALANCE',
id: 'bilan-hc-nuit-maison-recalee-sur-la-soiree',
label: 'Soiree chargee (facteur 1,092) : la maison en HC de nuit monte a 4,53 kWh',
// Tranches recalees puis arrondies : 0,87 / 0,76 / 0,66 -> 0,6 x 0,87 +
// 0,76 + 0,66 + 3 x 0,76 + 0,4 x 0,76 = 4,53.
snapshot: Object.assign(snap2709('2026-09-27T23:00:00+02:00', 52, null), {
night_house_factor: 1.092,
night_house_start_ms: Date.parse('2026-09-27T21:30:00+02:00'), night_house_end_ms: Date.parse('2026-09-28T09:00:00+02:00'),
night_house_computed_ms: Date.parse('2026-09-27T22:57:00+02:00'),
night_hc_start_ms: Date.parse('2026-09-28T01:24:00+02:00'), night_hc_end_ms: Date.parse('2026-09-28T07:24:00+02:00') }),
expect: { usable: true, nightModelActive: true, nightHcActive: true, nightHcHouseKwh: 4.53 },
},
{
node: 'BALANCE',
id: 'bilan-hc-nuit-fenetre-ouverte-depuis-maintenant',
label: '03:30, fenetre ouverte : seul le reste de la fenetre compte (2,68 kWh)',
// La tranche de 03 h n'est comptee que pour sa demi-heure restante :
// 0,5 x 0,60 + 0,70 + 0,70 + 0,70 + 0,4 x 0,70 = 2,68.
snapshot: Object.assign(snap2709('2026-09-28T03:30:00+02:00', 45, null), {
night_hc_start_ms: Date.parse('2026-09-28T01:24:00+02:00'), night_hc_end_ms: Date.parse('2026-09-28T07:24:00+02:00') }),
expect: { usable: true, nightHcActive: true, nightHcHouseKwh: 2.68 },
},
{
node: 'BALANCE',
id: 'bilan-hc-nuit-fenetre-inconnue',
label: 'Fenetre HC de nuit non transmise : rien n est annonce',
snapshot: snap2709('2026-09-27T23:00:00+02:00', 52, null),
expect: { usable: true, nightHcActive: false, nightHcHouseKwh: null },
},
];