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

@@ -2,7 +2,7 @@
// Les cas PV reprennent les gammes du banc OpenClaw (HANDOFF §77) : G3, G4, G5, G7.
// node tests/diagnostics-agent/run.mjs
import fs from 'node:fs';
import { diagnosticPv, etatCellules, productionJour, chargeSolaire, MPPT_MODES, ORIGINE_PAR_SOURCE } from '../../tools/diagnostics-agent.mjs';
import { diagnosticPv, etatCellules, productionJour, chargeSolaire, bilanNuit, MPPT_MODES, ORIGINE_PAR_SOURCE } from '../../tools/diagnostics-agent.mjs';
const LIM = 'voltage_current_limited', ACT = 'mppt_active';
function st({ pv, conso, reseau, soc = 80, courant = 0, edf = 'off', modes }) {
@@ -146,6 +146,37 @@ const okLib = libelles.length >= 6 && nonCouverts.length === 0;
if (!okLib) ko++;
console.log(`${okLib ? 'OK ' : 'KO '} les ${libelles.length} libelles de source du controleur ont une origine${okLib ? '' : ` (manquent : ${nonCouverts.join(', ') || 'table introuvable'})`}`);
const n = cas.length + cel.length + prod.length + charge.length + 1;
// --- Bilan de la nuit : la nuit reelle du 24 au 25/09 (incident de 11:49) ---
const nuit = {
debut: new Date('2026-09-24T16:00:00Z'), fin: new Date('2026-09-25T08:00:00Z'),
dateLue: 'vendredi 25 septembre',
fermetures: [{ ts: new Date('2026-09-25T04:01:00Z') }],
e: { importe: 2.71, voiture: 7.96 },
b: { depart: 97, bas: 31, heure_bas: new Date('2026-09-25T07:16:00Z'), maintenant: 32 },
sessions: [{ debut: new Date('2026-09-24T23:25:00Z'), fin: new Date('2026-09-25T04:42:00Z'), terminee: true,
vehicule: 'JEEP', energie_kwh: 7.96, energie_compteur_kwh: 7.9, energie_reseau_kwh: 2.2, source_mode: 'Assistance batterie nuit' }],
};
const bn = [
['INCIDENT 11:49 : la session terminee est bien visible, 7,9 kWh dont 2,2 reseau, 01:25 -> 06:42',
bilanNuit(nuit, 'x', new Date('2026-09-25T09:49:00Z')),
(r) => r.etat === 'complet' && r.attributs.vehicules[0].energie_kwh === 7.9 && r.attributs.vehicules[0].dont_reseau_kwh === 2.2
&& r.attributs.vehicules[0].debut === '01:25' && r.attributs.vehicules[0].fin === '06:42'],
['aucun SOC voiture publie ; le 35 % n existe nulle part', bilanNuit(nuit, 'x', new Date('2026-09-25T09:49:00Z')),
(r) => !JSON.stringify(r).includes('35') && /aucun capteur/.test(r.attributs.soc_voiture)],
['reseau : fermeture 06:01, import 2,7', bilanNuit(nuit, 'x', new Date('2026-09-25T09:49:00Z')),
(r) => r.attributs.reseau_fermetures.join() === '06:01' && r.attributs.reseau_importe_kwh === 2.7],
['avant 10:00 -> en_cours, session ouverte sans heure de fin', bilanNuit({ ...nuit,
sessions: [{ ...nuit.sessions[0], terminee: false }] }, 'x', new Date('2026-09-25T03:00:00Z')),
(r) => r.etat === 'en_cours' && r.attributs.vehicules[0].fin === null],
['nuit sans charge -> liste vide', bilanNuit({ ...nuit, sessions: [] }, 'x', new Date('2026-09-25T09:49:00Z')),
(r) => r.attributs.vehicules.length === 0],
];
for (const [nom, r, test] of bn) {
const ok = test(r);
if (!ok) { ko++; console.log(JSON.stringify(r)); }
console.log(`${ok ? 'OK ' : 'KO '} ${nom}`);
}
const n = cas.length + cel.length + prod.length + charge.length + 1 + bn.length;
console.log(`\n${n - ko}/${n}`);
process.exit(ko ? 1 : 0);