Bilan : la nuit prevue suit la soiree reelle (regression sur 24 nuits), nuage Grafana corrige
Le service publie le facteur nuit prevue / nuit moyenne (sensor.evcs_nuit_maison_prevue_kwh), le bilan l'applique a son profil de 21:30 a 09:00. Diagnostics 81/81, bilan 68/68. 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:
@@ -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, bilanNuit, etatReseau, importJour, COMPTEURS_IMPORT, COMPTEUR_EDF, MPPT_MODES, ORIGINE_PAR_SOURCE, consoJour, COMPTEURS_CONSO, projectionSoir, previsionNuit, vrmVersCourbes } from '../../tools/diagnostics-agent.mjs';
|
||||
import { diagnosticPv, etatCellules, productionJour, chargeSolaire, bilanNuit, etatReseau, importJour, COMPTEURS_IMPORT, COMPTEUR_EDF, MPPT_MODES, ORIGINE_PAR_SOURCE, consoJour, COMPTEURS_CONSO, projectionSoir, previsionNuit, vrmVersCourbes, nuitMaisonPrevue } 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 }) {
|
||||
@@ -287,6 +287,40 @@ for (const [nom, r, test] of imp) {
|
||||
globalThis.__nConso = (globalThis.__nConso || 0) + pj.length;
|
||||
}
|
||||
|
||||
|
||||
// --- Nuit de la maison prevue par la soiree : les 24 nuits REELLES (04->27/09) ---
|
||||
{
|
||||
const N = [[4.11,10.29],[6.52,9.81],[4.65,9.9],[3.76,8.66],[3.53,8.55],[3.61,9.48],[3.73,8.7],[7.04,11.88],
|
||||
[2.96,10.36],[5.73,13.63],[5.39,8.93],[3.12,8.14],[4.35,12.44],[5.08,12.64],[3.74,10],[4.24,10.75],
|
||||
[4.96,12.18],[5.47,11.43],[6.68,13.85],[9.48,14.95],[7.48,9.56],[4.41,9.72],[3.67,10.04],[4.81,8.87]]
|
||||
.map(([soiree, nuit]) => ({ soiree, nuit }));
|
||||
const soir = new Date('2026-09-28T21:00:00Z'); // 23:00 a Paris
|
||||
const r = nuitMaisonPrevue(N, 6.27, soir);
|
||||
const cas = [
|
||||
// Verifie par un calcul independant (Python) : a 6,979, b 0,7362, r2 0,388,
|
||||
// moyenne 10,615, prevue 11,595, facteur 1,0924.
|
||||
['soir du 28/09 : soiree 6,27 -> nuit prevue 11,6 kWh (a 6,98, b 0,736, r2 0,39)', r,
|
||||
(x) => x.etat === 11.6 && x.attributs.a === 6.98 && x.attributs.b === 0.736 && x.attributs.r2 === 0.39],
|
||||
['facteur = prevue / moyenne des memes nuits (10,62) -> 1,092', r, (x) => x.attributs.facteur === 1.092 && x.attributs.nuit_moyenne_kwh === 10.62],
|
||||
['fenetre 21:30 -> 09:00 de la bonne nuit', r,
|
||||
(x) => x.attributs.debut_ms === Date.parse('2026-09-28T19:30:00Z') && x.attributs.fin_ms === Date.parse('2026-09-29T07:00:00Z')],
|
||||
['03:00 : c est la nuit commencee la veille', nuitMaisonPrevue(N, 6.27, new Date('2026-09-29T01:00:00Z')),
|
||||
(x) => x.etat === 11.6 && x.attributs.debut_ms === Date.parse('2026-09-28T19:30:00Z')],
|
||||
['14:00 -> hors_fenetre (pas de soiree complete)', nuitMaisonPrevue(N, 6.27, new Date('2026-09-28T12:00:00Z')),
|
||||
(x) => x.etat === 'hors_fenetre' && x.attributs.facteur === null],
|
||||
['10 nuits seulement -> indisponible', nuitMaisonPrevue(N.slice(0, 10), 6.27, soir),
|
||||
(x) => x.etat === 'indisponible' && x.attributs.facteur === null],
|
||||
['nuage sans relation (r2 < 0,2) -> indisponible', nuitMaisonPrevue(N.map((p, i) => ({ soiree: p.soiree, nuit: 10 + (i % 2) })), 6.27, soir),
|
||||
(x) => x.etat === 'indisponible'],
|
||||
['soiree illisible -> indisponible', nuitMaisonPrevue(N, NaN, soir), (x) => x.etat === 'indisponible'],
|
||||
];
|
||||
for (const [nom, x, test] of cas) {
|
||||
const ok = test(x); if (!ok) { ko++; console.log(JSON.stringify(x)); }
|
||||
console.log(`${ok ? 'OK ' : 'KO '} ${nom}`);
|
||||
}
|
||||
globalThis.__nConso = (globalThis.__nConso || 0) + cas.length;
|
||||
}
|
||||
|
||||
// --- Prevision de la nuit : releve reel du 28/09 01:25 ----------------------
|
||||
{
|
||||
const base = () => new Map(Object.entries({
|
||||
|
||||
@@ -106,6 +106,9 @@ const SUMMARIZE = {
|
||||
hcReachActive: o.hcReach ? o.hcReach.active : false,
|
||||
hcFloorPct: o.hcReach ? o.hcReach.floorPct : null,
|
||||
hcNightFloorPrudentPct: o.hcReach ? o.hcReach.nightFloorPrudentPct : null,
|
||||
// Nuit prevue par la soiree (28/09).
|
||||
nightModelActive: o.nightModel ? o.nightModel.active : false,
|
||||
nightFactor: o.nightModel ? o.nightModel.factor : 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,
|
||||
|
||||
@@ -512,4 +512,49 @@ export const balanceScenarios = [
|
||||
snapshot: jeep(snap2709('2026-09-27T12:30:00+02:00', 30, MIDI_2709, SOMBRE), 0, { vehicle_capacity_kwh: 15, vehicle_charger_kw: 0 }),
|
||||
expect: { usable: true, vehicleActive: true, vehicleReachableKwh: 15, vehicleGridNeeded: true },
|
||||
},
|
||||
// ======== LA NUIT PREVUE PAR LA SOIREE (28/09/2026) ========
|
||||
// Soir du 28/09 : soiree 6,27 kWh -> facteur 1,092 sur le profil de 21:30 a
|
||||
// 09:00. Meme snapshot avec et sans facteur : seule la consommation de nuit
|
||||
// bouge, donc le SOC requis monte.
|
||||
{
|
||||
node: 'BALANCE',
|
||||
id: 'bilan-nuit-soiree-reference-sans-facteur',
|
||||
label: 'Reference : 23:00, SOC 52, sans facteur de nuit',
|
||||
snapshot: snap2709('2026-09-27T23:00:00+02:00', 52, null),
|
||||
expect: { usable: true, nightModelActive: false, nightFactor: 1, energyToCoverKwh: 7.77, requiredSocPct: 47.9 },
|
||||
},
|
||||
{
|
||||
node: 'BALANCE',
|
||||
id: 'bilan-nuit-soiree-chargee-releve-le-requis',
|
||||
label: 'Soiree chargee (facteur 1,092) : la nuit est plus lourde, le SOC requis monte',
|
||||
snapshot: Object.assign(snap2709('2026-09-27T23:00:00+02:00', 52, null), {
|
||||
night_house_factor: 1.092, night_house_forecast_kwh: '11.59',
|
||||
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') }),
|
||||
// Verifie a la main : profil 23:00->09:00 = 8,0 kWh, x 0,092 = +0,74 (0,71
|
||||
// apres l'heure ou le soleil revient) ; +2,4 points = 0,71 / 0,30. Le
|
||||
// prudent (p80) est deja au-dessus du p50 recale : il ne bouge pas.
|
||||
expect: { usable: true, nightModelActive: true, nightFactor: 1.092, energyToCoverKwh: 8.48,
|
||||
requiredSocPct: 50.3, prudentRequiredSocPct: 56.7 },
|
||||
},
|
||||
{
|
||||
node: 'BALANCE',
|
||||
id: 'bilan-nuit-soiree-facteur-perime',
|
||||
label: 'Facteur calcule il y a 2 h : on ne l applique pas',
|
||||
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-27T21:00:00+02:00') }),
|
||||
expect: { usable: true, nightModelActive: false, nightFactor: 1 },
|
||||
},
|
||||
{
|
||||
node: 'BALANCE',
|
||||
id: 'bilan-nuit-soiree-facteur-aberrant-borne',
|
||||
label: 'Facteur 3 (mesure fausse) : borne a 1,45, l extreme observe',
|
||||
snapshot: Object.assign(snap2709('2026-09-27T23:00:00+02:00', 52, null), {
|
||||
night_house_factor: 3,
|
||||
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') }),
|
||||
expect: { usable: true, nightModelActive: true, nightFactor: 1.45, requiredSocPct: 59.8, prudentRequiredSocPct: 62.2 },
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user