Chantier etape 5 : bilan energetique publie en mode ombre
Workflow n8n "EVCS Energy Balance V1" (id QoSfPeyGq35orF1K), actif, cycle de 5 min : snapshot HA -> CENSORSHIP et RESOURCE_ESTIMATE en parallele -> PREPARE_BALANCE -> BALANCE -> BUILD_HA_CALLS -> appels de service HA. MODE OMBRE garanti structurellement : BUILD_HA_CALLS n'ecrit que vers des entites evcs_balance_* plus une trace logbook. La suite de tests echoue si une ecriture sort de ce perimetre — verifie par mutation, l'injection d'un turn_on sur switch.edf_general_ok_switch fait rougir la suite. Kill-switch input_boolean.evcs_balance_enabled : a OFF, aucune ecriture du tout. Package HA evcs_energy_balance.yaml : 18 helpers. Profils de consommation, enveloppe de production et taux de censure amorces avec les valeurs calculees sur 28 jours reels ; capacite utile posee a 15 kWh (7 modules actifs). Outillage : gen-energy-balance-workflow.mjs, enregistrement dans lib-node-map.mjs, suite cablee dans n8n-push.mjs (bloquante). Suite a 24 scenarios. Premiere execution reelle : le bilan s'est declare indisponible faute d'entrees, exactement comme prevu, au lieu d'inventer des valeurs. Le format du snapshot (corps JSON dans `data`) et la lecture des profils CSV ont ete corriges ensuite. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
This commit is contained in:
81
tests/energy-balance/scenarios-shadow.mjs
Normal file
81
tests/energy-balance/scenarios-shadow.mjs
Normal file
@@ -0,0 +1,81 @@
|
||||
// Scénarios de BUILD_HA_CALLS — garantie du mode ombre.
|
||||
// La suite doit ÉCHOUER si une écriture sort du périmètre `evcs_balance_*`.
|
||||
// C'est la seule protection structurelle contre un câblage réel accidentel.
|
||||
|
||||
const SNAPSHOT = {
|
||||
balance_enabled: 'on',
|
||||
grid_soc_off: '30.0',
|
||||
soc_percent: '21',
|
||||
usable_capacity_kwh: '15',
|
||||
};
|
||||
|
||||
const CENSORSHIP_CENSURE = {
|
||||
censorship: { pvCensored: true, reasons: ['batterie_pleine_sans_puits'] },
|
||||
};
|
||||
const CENSORSHIP_LIBRE = {
|
||||
censorship: { pvCensored: false, reasons: [] },
|
||||
};
|
||||
|
||||
const BALANCE_OK = {
|
||||
usable: true,
|
||||
crossing: { found: true, hour: 8 },
|
||||
coverage: {
|
||||
energyToCoverKwh: 0.82,
|
||||
requiredSocPct: 27.5,
|
||||
currentSocPct: 21,
|
||||
socMarginPct: -6.5,
|
||||
gridNeeded: true,
|
||||
gridEnergyNeededKwh: 0.97,
|
||||
prudent: { requiredSocPct: 38.1 },
|
||||
},
|
||||
vehicle: { surplusAvailableKwh: 20.17 },
|
||||
};
|
||||
|
||||
export const shadowScenarios = [
|
||||
{
|
||||
node: 'BUILD_HA_CALLS',
|
||||
id: 'ombre-perimetre-respecte',
|
||||
label: 'Bilan complet : toutes les écritures restent dans evcs_balance_*',
|
||||
snapshot: {
|
||||
...BALANCE_OK,
|
||||
__nodes: { 'HA Snapshot Balance': SNAPSHOT, CENSORSHIP: CENSORSHIP_CENSURE },
|
||||
},
|
||||
expect: {
|
||||
outOfScope: '',
|
||||
wroteRequiredSoc: true,
|
||||
wroteGridNeeded: true,
|
||||
hasLogbook: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
node: 'BUILD_HA_CALLS',
|
||||
id: 'ombre-bilan-indisponible',
|
||||
label: 'Bilan inutilisable : statut publié, aucune valeur inventée',
|
||||
snapshot: {
|
||||
usable: false,
|
||||
missing: ['usable_capacity_kwh'],
|
||||
__nodes: { 'HA Snapshot Balance': SNAPSHOT, CENSORSHIP: CENSORSHIP_LIBRE },
|
||||
},
|
||||
expect: {
|
||||
outOfScope: '',
|
||||
wroteRequiredSoc: false,
|
||||
hasLogbook: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
node: 'BUILD_HA_CALLS',
|
||||
id: 'ombre-kill-switch',
|
||||
label: 'Kill-switch à OFF : absolument aucune écriture',
|
||||
snapshot: {
|
||||
...BALANCE_OK,
|
||||
__nodes: {
|
||||
'HA Snapshot Balance': { ...SNAPSHOT, balance_enabled: 'off' },
|
||||
CENSORSHIP: CENSORSHIP_CENSURE,
|
||||
},
|
||||
},
|
||||
expect: {
|
||||
callCount: 0,
|
||||
outOfScope: '',
|
||||
},
|
||||
},
|
||||
];
|
||||
Reference in New Issue
Block a user