Prevision de nuit : mode jour (plus de fausse reponse sur la nuit ecoulee)

Le jour, sans rien a couvrir avant le retour du solaire, le texte parlait de
la nuit ecoulee (« 0 kWh jusqu au retour du solaire vers 10 h, la batterie
suffit »). Etat `jour` : la prevision se fait le soir, avec un repere
provisoire (prochaine traversee prudente) et l'achat si EDF s'engage.
Diagnostics 87/87.

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:53:39 +02:00
parent 24ccecbc02
commit c2f9e83a39
3 changed files with 63 additions and 2 deletions

View File

@@ -1158,8 +1158,19 @@ affiner ; demarrage solaire de l'apres-midi toujours non couvert par le besoin d
« EDF sera branche de 01:24 a 07:24 : environ 4,6 kWh achetes en heures creuses (maison
4,5, batterie 0,14), car la maison passe la nuit sur le reseau ». Bilan 72/72,
diagnostics 85/85, mutations qui mordent (une premiere ne mordait pas : scenario a
03:00 pile, horizon sans tranche anterieure -> deplace a 03:30). Fiche de l'agent a
mettre a jour par SPARK.
03:00 pile, horizon sans tranche anterieure -> deplace a 03:30). Fiche mise a jour par SPARK
(l'agent recopie `prevision-nuit.js`, qui imprime `texte_rapport` : aucun attribut lu).
- **Mode jour** (remarque de SPARK, banc 10:49 : « combien d'EDF la nuit prochaine ? » ->
« la maison doit couvrir 0 kWh jusqu'au retour du solaire vers 10 h, la batterie
suffit », qui parlait de la nuit ECOULEE). Quand plus rien n'est a couvrir avant le
retour du solaire et sans session : etat/verdict `jour`, « il est trop tot pour la
prevision de la nuit : elle se calcule le soir … repere provisoire, profil prudent :
pour passer de 18 h a 09 h sans EDF (17,87 kWh), il faudrait la batterie a 82 % a
18 h ; si EDF s'engage a 01:24, la maison y achetera environ 4,2 kWh ». Attributs
`prochaine_traversee*`. Diagnostics 87/87, mutation qui mord. En reel a 10:53.
- SPARK : les transcripts SQLite (`openclaw-agent.sqlite`, droits 600) remontent au
18/07, AUCUNE rotation ; un evenement contient le jeton HA (l'agent a lu `.ha-token`).
Signale au proprietaire par SPARK, base non modifiee.
---
*Document mis a jour le : 29/09/2026 (~10:50) — nuit du 28-29 verifiee, achat EDF annonce = maison en HC + manque batterie ; regle HC active, vehicule branche a midi (JEEP/VW/ZERO), prevision de nuit a trois verdicts, nuits superposees et bilan recale sur la soiree*

View File

@@ -397,6 +397,31 @@ for (const [nom, r, test] of imp) {
'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)],
// Releve REEL du 29/09 10:45 (banc SPARK) : « la maison doit couvrir 0 kWh
// jusqu au retour du solaire vers 10 h … la batterie suffit » en reponse a
// « combien d EDF la nuit prochaine ? ».
['29/09 10:45 : le jour, pas de fausse prevision de nuit, un repere provisoire', (() => {
const m = base(); for (const [k, v] of Object.entries({
'input_number.evcs_balance_energy_to_cover_kwh': '0', 'input_boolean.evcs_balance_grid_needed': 'off',
'input_number.evcs_balance_grid_energy_needed_kwh': '0', 'input_text.evcs_balance_crossing_hour': '10 h',
'input_number.evcs_balance_required_soc': '22', 'input_number.evcs_balance_required_soc_prudent': '22',
'sensor.victron_battery_soc': '46', 'input_boolean.victron_evcs_night_grid_session_committed': 'off',
'sensor.evcs_reseau': 'non_raccorde', 'input_number.evcs_balance_night_hc_house_kwh': '4.16',
'input_datetime.victron_evcs_hc_night_start': '01:24:00', 'input_datetime.victron_evcs_hc_night_stop': '07:24:00',
'input_text.evcs_balance_next_deficit_window': '18 h → 09 h',
'input_number.evcs_balance_next_deficit_required_soc': '81.6', 'input_number.evcs_balance_next_deficit_kwh': '17.87',
})) m.set(k, { state: v }); return previsionNuit(m, t); })(),
(r) => r.etat === 'jour' && r.attributs.verdict === 'jour'
&& /trop tot pour la prevision de la nuit/.test(r.attributs.texte_rapport)
&& /de 18 h a 09 h sans EDF \(environ 17,87 kWh\), il faudrait la batterie a 82 % a 18 h/.test(r.attributs.texte_rapport)
&& /Si EDF s engage a 01:24, la maison y achetera environ 4,2 kWh jusqu a 07:24/.test(r.attributs.texte_rapport)
&& !/batterie suffit/.test(r.attributs.texte_rapport) && !/couvrir environ 0 kWh/.test(r.attributs.texte_rapport)],
['le jour, fenetre de deficit inconnue -> pas de repere invente', (() => {
const m = base(); for (const [k, v] of Object.entries({
'input_number.evcs_balance_energy_to_cover_kwh': '0', 'input_boolean.evcs_balance_grid_needed': 'off',
'input_boolean.victron_evcs_night_grid_session_committed': 'off', 'input_text.evcs_balance_next_deficit_window': 'déficit en cours',
})) m.set(k, { state: v }); return previsionNuit(m, t); })(),
(r) => r.etat === 'jour' && !/Repere provisoire/.test(r.attributs.texte_rapport)],
['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),

View File

@@ -658,6 +658,31 @@ export function previsionNuit(st, maintenant = new Date()) {
`Le systeme refait le calcul ${hc} : si la soiree a consomme davantage, il prendra EDF en heures creuses` +
`${maisonHcKwh !== null ? `, et la maison y achetera alors environ ${kwh(Math.round(maisonHcKwh * 10) / 10)} kWh` : ''}.`,
}[verdict];
// LE JOUR (29/09, remarque de SPARK) : plus rien a couvrir avant le retour
// du solaire = le solaire couvre deja la maison. Le texte « la maison doit
// couvrir 0 kWh jusqu au retour du solaire vers 10 h » parlait alors de la
// nuit ECOULEE, et une question « et cette nuit ? » posee a midi recevait
// une reponse fausse. La vraie prevision se fait le soir, sur la soiree
// reelle (facteur de nuit) et la decision de 01:24. Le jour, on le dit, avec
// un repere provisoire : la prochaine traversee du bilan (profil PRUDENT).
if (aCouvrir <= 0 && !session) {
const fen = txt('input_text.evcs_balance_next_deficit_window');
const m = fen ? fen.match(/^(\d{2}) h → (\d{2}) h/) : null;
const ndSoc = nombre(st, 'input_number.evcs_balance_next_deficit_required_soc');
const ndKwh = nombre(st, 'input_number.evcs_balance_next_deficit_kwh');
const repere = m && ndSoc !== null && ndKwh !== null
? ` Repere provisoire, profil prudent : pour passer de ${m[1]} h a ${m[2]} h sans EDF (environ ${kwh(ndKwh)} kWh), ` +
`il faudrait la batterie a ${kwh(Math.round(ndSoc))} % a ${m[1]} h.`
: '';
const achatSi = maisonHcKwh !== null
? ` Si EDF s engage ${hc}, la maison y achetera environ ${kwh(Math.round(maisonHcKwh * 10) / 10)} kWh ${jusqua}.` : '';
const texteJour = `Il est trop tot pour la prevision de la nuit : elle se calcule le soir, sur la consommation reelle ` +
`de la soiree, et la decision d EDF se prend ${hc}.${repere}${achatSi} Batterie a ${soc !== null ? Math.round(soc) : '?'} % maintenant.`;
return { etat: 'jour', attributs: { ...attributs, verdict: 'jour', statut: 'jour',
prochaine_traversee: m ? `${m[1]} h -> ${m[2]} h` : null,
prochaine_traversee_soc_requis_pct: m ? ndSoc : null, prochaine_traversee_kwh: m ? ndKwh : null,
explication: texteJour, texte_rapport: texteJour } };
}
const texte = `La maison doit couvrir environ ${aCouvrir} kWh jusqu au retour du solaire vers ${retour}. ` +
`${edf} Batterie a ${soc !== null ? Math.round(soc) : '?'} %. ${voiture}`;
const etat = verdict === 'edf_engage' || verdict === 'reseau_necessaire' ? (importPrevu ?? manqueKwh) : 0;