sensor.evcs_bilan_nuit : le bilan de nuit de l'agent vient du code du rapport du matin

Incident 25/09 11:49 : l'agent sans source avait invente 0,56 kWh / zero
reseau / 35 % pour une nuit a 7,9 kWh dont 2,2 reseau. donneesNuit() extrait
de rapport-nuit.mjs (texte identique sur 5 nuits), publie pour l'agent.
Tests 37/37.

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-25 12:31:35 +02:00
parent beed8028ca
commit c75d2ffcb8
5 changed files with 184 additions and 52 deletions

View File

@@ -266,3 +266,49 @@ export function chargeSolaire(st) {
return r('en_attente',
`Voiture branchee mais pas en charge. Le controleur dit : ${raison || 'sans raison publiee'} (source : ${source}).`);
}
// ---------------------------------------------------------------------
// Bilan de la nuit — les donnees du rapport du matin, pour l'agent
// ---------------------------------------------------------------------
// Incident du 25/09 ~11:49 : a « bilan energetique de la nuit », l'agent, qui
// n'avait de source que pour la session EN COURS (aucune a cette heure), a
// invente « 0,56 kWh, zero reseau, arrivee a la cible de 35 %, arretee vers
// 4 h ». Realite : JEEP 7,9 kWh dont 2,2 reseau, 01:25 -> 06:42. Les « 35 % »
// etaient la cible de la BATTERIE MAISON ; la voiture n'a aucun capteur de SOC.
// On publie donc ce que calcule tools/rapport-nuit.mjs (donneesNuit), le meme
// code que le courriel de 07:30 : les deux ne peuvent pas diverger.
// La nuit decrite va de 18:00 la veille a 10:00 ce matin ; avant 10:00 elle est
// `en_cours` (fenetre plafonnee a maintenant, rien d'extrapole).
const hParis = (t) => (t ? new Date(t).toLocaleTimeString('fr-FR',
{ timeZone: 'Europe/Paris', hour: '2-digit', minute: '2-digit' }) : null);
const r1 = (x) => (x === null || x === undefined || !Number.isFinite(Number(x)) ? null : Math.round(Number(x) * 10) / 10);
export function bilanNuit(d, texte, maintenant = new Date()) {
const enCours = maintenant < d.fin;
const vehicules = (d.sessions || []).map((s) => ({
vehicule: s.vehicule ?? 'non identifie',
debut: hParis(s.debut),
fin: s.terminee ? hParis(s.fin) : null,
terminee: !!s.terminee,
energie_kwh: r1(s.energie_compteur_kwh ?? s.energie_kwh),
dont_reseau_kwh: r1(s.energie_reseau_kwh),
source_controleur: s.source_mode ?? null,
}));
return {
etat: enCours ? 'en_cours' : 'complet',
attributs: {
nuit_du: d.dateLue,
fenetre: `${hParis(d.debut)} la veille -> ${hParis(d.fin)}${enCours ? ' (en cours, arretee a maintenant)' : ''}`,
reseau_fermetures: (d.fermetures || []).map((f) => hParis(f.ts)),
reseau_importe_kwh: r1(d.e?.importe),
voiture_totale_kwh: r1(d.e?.voiture),
vehicules,
batterie_maison_depart_pct: r1(d.b?.depart ?? d.b?.haut),
batterie_maison_plus_bas_pct: r1(d.b?.bas),
batterie_maison_heure_plus_bas: hParis(d.b?.heure_bas),
batterie_maison_maintenant_pct: r1(d.b?.maintenant),
soc_voiture: 'aucun capteur : ne jamais en annoncer un',
texte_rapport: texte,
},
};
}