Controleur : trois ecritures jamais relayees (budget, verrou P12, reset borne) + garde-fou ; verrou P12 leve en fin de session

This commit is contained in:
Tallagrand Thierry
2026-10-01 07:26:28 +02:00
parent baf62bb3d5
commit eeaa7636b2
6 changed files with 101 additions and 7 deletions

View File

@@ -1317,5 +1317,32 @@ autoriser une charge complete avec EDF.** Decisions (30/09) : profil **prudent +
integration de la puissance, le compteur fait foi). Charge dans Grafana, requetes OK integration de la puissance, le compteur fait foi). Charge dans Grafana, requetes OK
(la courbe « donne » se remplit a partir de 01:24). (la courbe « donne » se remplit a partir de 01:24).
### 01/10 matin — Premiere nuit du budget : il n'a pas joue, et deux defauts anciens
**Constat** : JEEP chargee de 01:25 a 06:37 en « Assistance batterie nuit », **7,5 kWh**
(pleine, 8,9 kWh au compteur depuis 17:29) ; batterie 64 % a 01:00 -> 37 % a 06:00 ; EDF
ferme **06:00 -> 06:38** (2,15 kWh importes, HC). Mode sans_edf, budget publie 5,93 kWh a
01:25.
1. **Le budget n'a jamais ete fige** : `input_text.victron_evcs_night_budget` est reste
« unknown ». Cause : « Build EVCS Surplus Controller V2.0 Actions » ne relaie QUE les
appels qu'il nomme. **Trois ecritures produites n'etaient jamais executees** : le budget
(30/09), le **verrou P12 `night_battery_done` (depuis le 15/09)** et l'acquittement du
bouton reset borne (depuis le 19/09). Les golden s'arretent a HA_SERVICE_CALLS_OUTPUT et ne
le voyaient pas. Corrige (`src/nodes/BUILD_ACTIONS.js`) + **garde-fou golden
`build-actions-transmet-tout`** (tout appel produit doit etre nomme dans le Build : 51/51,
echouait sur les trois avant).
2. **Le verrou P12 ne se relachait jamais** (`prev || …`) : invisible tant qu'il n'etait pas
ecrit ; avec l'ecriture retablie, P12 serait mort pour toutes les nuits suivantes. Il ne
vaut plus que pendant la session de nuit. Golden **132/132** (+2 : verrou pose au budget,
leve en fin de session), mutation qui mord. Deploye 07:22 ; **verifie en reel** : budget
fige « 2,76|4016,2 » a 07:23 (fin de fenetre, JEEP pleine, sans effet), efface a 07:24.
3. **EDF a 06:00 = faux positif de `batteryRecoveryUrgent`** (WINDOWS_SOURCEV2 l.390) : depart
JEEP du matin `input_datetime.victron_evcs_departure_time_jeep` = 06:30, marge
`evcs_night_departure_safety_min` = 30 min -> a 06:00, 0 min de recharge necessaire + 30
>= 30 = « urgent », alors qu'il manquait **0 kWh** (SOC 37 > cible 35). `grid_forced` :
maison ET voiture sur EDF. **Recurrent** : fermeture vers 06:00 les 21, 22, 25, 27/09 et
01/10. Mon exception « EDF deja engage pour la batterie » l'a laisse passer en sans_edf.
Correctif propose (exiger un manque > 0), **decision du proprietaire en attente**, ainsi
que la realite du depart de la JEEP a 06:30.
--- ---
*Document mis a jour le : 30/09/2026 (~18:30) — commande vocale du mode de nuit validee, premiere nuit budget a suivre ; budget voiture de la nuit sans EDF (bilan + controleur) ; fiche de l'agent allegee (25 831 car.), concierge sans silence, calendrier JEEP mar/sam ; 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* *Document mis a jour le : 01/10/2026 (~07:35) — premiere nuit du budget : ecritures perdues et verrou P12 corriges, faux positif de depart a 06:00 ; commande vocale du mode de nuit validee, premiere nuit budget a suivre ; budget voiture de la nuit sans EDF (bilan + controleur) ; fiche de l'agent allegee (25 831 car.), concierge sans silence, calendrier JEEP mar/sam ; 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

@@ -127,6 +127,34 @@ pushAction(
!!calls.helper_evcs_no_demand_filter_eval_at?.execute !!calls.helper_evcs_no_demand_filter_eval_at?.execute
); );
// =====================================================
// ECRITURES CONDITIONNELLES OUBLIEES (01/10/2026)
// Produites par HA_SERVICE_CALLS_OUTPUT mais jamais relayees jusqu'ici :
// - verrou P12 (`night_battery_done`, une seule passe sur batterie) depuis
// le 15/09 ;
// - acquittement du bouton reset borne (momentane) depuis le 19/09 ;
// - budget voiture de la nuit fige (30/09) : la nuit du 30/09 la JEEP a pris
// 7,5 kWh sur la batterie au lieu du budget.
// Garde-fou : tests/golden/run.mjs verifie que tout appel produit est nomme ici.
// =====================================================
pushAction(
'helper_night_battery_done',
calls.helper_night_battery_done,
!!calls.helper_night_battery_done?.execute
);
pushAction(
'helper_reset_borne_ack',
calls.helper_reset_borne_ack,
!!calls.helper_reset_borne_ack?.execute
);
pushAction(
'helper_night_budget',
calls.helper_night_budget,
!!calls.helper_night_budget?.execute
);
// ===================================================== // =====================================================
// DEMANDE RÉSEAU EDF SI SOURCE GRID // DEMANDE RÉSEAU EDF SI SOURCE GRID
// ===================================================== // =====================================================

View File

@@ -659,10 +659,16 @@ const nightBudgetReached =
nightBudgetDeliveredKwh >= nightBudget.budgetKwh - 0.05; nightBudgetDeliveredKwh >= nightBudget.budgetKwh - 0.05;
const nightChargeComplete = params.nightChargeMode === 'complete'; const nightChargeComplete = params.nightChargeMode === 'complete';
// Le verrou ne vaut QUE pendant la session de nuit (01/10/2026). Ecrit sous la
// forme `prev || …`, il restait vrai pour toujours une fois pose ; invisible
// tant que son ecriture n'atteignait pas HA (jamais relayee du 15/09 au 01/10).
// Fin de session (debranchement ou fin de fenetre HC) = verrou leve.
const nightBatterySurplusExhausted = const nightBatterySurplusExhausted =
params.nightBatteryDonePrev || nightSessionActive && (
(nightSessionActive && parsed.soc <= nightBatterySurplusFloorPct) || params.nightBatteryDonePrev ||
(nightSessionActive && nightBudgetReached); parsed.soc <= nightBatterySurplusFloorPct ||
nightBudgetReached
);
const nightBatterySurplusAvailable = const nightBatterySurplusAvailable =
nightSessionActive && nightSessionActive &&

View File

@@ -40,6 +40,22 @@ const nodeCode = Object.fromEntries(
CHAIN.map(n => [n, wf.nodes.find(x => x.name === n).parameters.jsCode]) CHAIN.map(n => [n, wf.nodes.find(x => x.name === n).parameters.jsCode])
); );
// GARDE-FOU (01/10/2026) : tout appel produit par HA_SERVICE_CALLS_OUTPUT doit
// etre transmis par « Build … Actions », qui ne relaie QUE les appels qu'il
// nomme. Trois ecritures ne partaient jamais (le verrou P12 depuis le 15/09,
// l'acquittement du bouton reset borne, le budget voiture du 30/09) : les
// scenarios s'arretent a HA_SERVICE_CALLS_OUTPUT et ne pouvaient pas le voir.
const BUILD_CODE = wf.nodes.find(x => x.name === 'Build EVCS Surplus Controller V2.0 Actions').parameters.jsCode;
const appelsProduits = [...nodeCode.HA_SERVICE_CALLS_OUTPUT.matchAll(/^ {6}([a-z_0-9]+): \{/gm)].map(m => m[1]);
const appelsPerdus = [...new Set(appelsProduits)].filter(n => !BUILD_CODE.includes(`'${n}'`));
let gardeFou = 0;
if (appelsPerdus.length) {
gardeFou = 1;
console.log(`❌ build-actions-transmet-tout | appels produits mais jamais executes : ${appelsPerdus.join(', ')}`);
} else {
console.log(`✅ build-actions-transmet-tout (${new Set(appelsProduits).size} appels)`);
}
// Horloge simulée : Date épinglée à l'instant du scénario dans la sandbox. // Horloge simulée : Date épinglée à l'instant du scénario dans la sandbox.
function makeFakeDate(fixedMs) { function makeFakeDate(fixedMs) {
return class FakeDate extends Date { return class FakeDate extends Date {
@@ -122,6 +138,8 @@ function summarize(out) {
sessionCommittedService: calls.helper_night_grid_session_committed?.execute sessionCommittedService: calls.helper_night_grid_session_committed?.execute
? calls.helper_night_grid_session_committed.service ? calls.helper_night_grid_session_committed.service
: null, : null,
// Verrou P12 : service ecrit ce cycle (turn_on/turn_off), null sinon.
nightBatteryDoneService: calls.helper_night_battery_done?.execute ? calls.helper_night_battery_done.service : null,
// Budget voiture de la nuit (30/09) : valeur ecrite ce cycle, null sinon. // Budget voiture de la nuit (30/09) : valeur ecrite ce cycle, null sinon.
nightBudgetWrite: calls.helper_night_budget?.execute ? calls.helper_night_budget.data.value : null, nightBudgetWrite: calls.helper_night_budget?.execute ? calls.helper_night_budget.data.value : null,
// Consigne de puissance reseau ecrite ce cycle (null = aucune ecriture). // Consigne de puissance reseau ecrite ce cycle (null = aucune ecriture).
@@ -132,7 +150,7 @@ function summarize(out) {
} }
const jsonResults = {}; const jsonResults = {};
let failures = 0, ran = 0; let failures = gardeFou, ran = 0;
for (const sc of scenarios) { for (const sc of scenarios) {
if (only && !sc.id.includes(only)) continue; if (only && !sc.id.includes(only)) continue;
ran++; ran++;

View File

@@ -3132,6 +3132,21 @@ export const scenarios = [
expect: { sourceMode: 'blocked', desiredCharging: false, nightBudgetWrite: null, expect: { sourceMode: 'blocked', desiredCharging: false, nightBudgetWrite: null,
takeoverNeeded: false, edfOnAction: false }, takeoverNeeded: false, edfOnAction: false },
}, },
{
id: 'p12-verrou-pose-quand-le-budget-est-atteint',
label: 'Budget atteint en session : le verrou P12 est ecrit (une seule passe sur batterie)',
time: '2026-09-30T02:30:00+02:00',
overrides: { ...BUDGET_NUIT, ...EN_CHARGE_BATTERIE, balance_last_run: '30/09 02:25', soc_percent: '50',
night_charge_mode: 'sans_edf', night_budget_prev: '3.7|4000', evcs_total_energy_kwh: '4003.75' },
expect: { nightBatteryDoneService: 'turn_on' },
},
{
id: 'p12-verrou-leve-en-fin-de-session',
label: '08:00, verrou encore pose : il est leve (sinon la charge sur batterie mourait pour toutes les nuits suivantes)',
time: '2026-09-30T08:00:00+02:00',
overrides: { ...BUDGET_NUIT, balance_last_run: '30/09 07:55', night_battery_done_prev: 'on' },
expect: { nightBatteryDoneService: 'turn_off' },
},
{ {
id: 'budget-efface-en-fin-de-session', id: 'budget-efface-en-fin-de-session',
label: 'Fin de fenetre HC (08:00) : le budget fige est efface', label: 'Fin de fenetre HC (08:00) : le budget fige est efface',

File diff suppressed because one or more lines are too long