Cinquante reglages batterie qui disparaissaient au redemarrage

Le proprietaire demande d assouplir la garde de decharge souple en bande 40-60,
de -12 a -15 A de base — 39 a 49 A appliques sur treize modules, soit 3,5 A par
equivalent US2000 et 19 % de ce que le BMS autorise. Son argument : en ete, avec
52 panneaux et une production bridee des midi, garder le parc plein n a aucun
sens, et cette nuit a coute 8 kWh de reseau en touchant a peine la batterie.

Le reglage aurait ete perdu. Les cinquante helpers de la table de politique
batterie portaient un `initial:`, qui DESACTIVE la restauration d etat : chaque
redemarrage de Home Assistant les remet a leur valeur d origine, en silence. Et
un redemarrage etait prevu le soir meme pour le tableau du moniteur LLM.

Meme defaut que les cinq helpers corriges le 06/09 — selecteur de vehicule,
toggles de cablage — mais ici sur une table entiere de REGLAGE, donc sur tout
ajustement futur et pas seulement celui-ci.

Les valeurs par defaut restent dans INPUT_PARSE, qui les applique quand le
helper est absent. Rien n est perdu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
This commit is contained in:
Tallagrand Thierry
2026-09-15 04:55:31 +02:00
parent 9fb73415b4
commit 66daac2933
5 changed files with 115 additions and 51 deletions

View File

@@ -142,6 +142,9 @@
"evcs_night_session_start_soc": states("input_text.victron_evcs_night_session_start_soc"),
"evcs_night_session_start_at": states("input_text.victron_evcs_night_session_start_at"),
"balance_required_soc_prudent": states("input_number.evcs_balance_required_soc_prudent"),
"night_battery_charge_enabled": states("input_boolean.victron_evcs_night_battery_charge"),
"night_battery_done_prev": states("input_boolean.victron_evcs_night_battery_done"),
"balance_required_soc": states("input_number.evcs_balance_required_soc"),
"balance_energy_to_cover_kwh": states("input_number.evcs_balance_energy_to_cover_kwh"),
"balance_status": states("input_text.evcs_balance_status"),

View File

@@ -470,6 +470,13 @@ const params = {
// BILAN ENERGETIQUE (03/09/2026). Meme format d'horodatage que l'advisor
// ("DD/MM HH:mm"), d'ou la reutilisation du parseur.
balanceRequiredSocPct: num(input.balance_required_soc, NaN),
// P12 — charge nuit sur batterie. Le plancher est le SOC requis PRUDENT (p80)
// et non le p50 : la marge est mesuree, pas inventee. On descend la voiture
// jusqu'a ce que la batterie n'ait plus que ce qu'il lui faut pour tenir
// jusqu'au croisement PV.
balanceRequiredSocPrudentPct: num(input.balance_required_soc_prudent, NaN),
nightBatteryChargeEnabled: low(input.night_battery_charge_enabled || 'off') === 'on',
nightBatteryDonePrev: low(input.night_battery_done_prev || 'off') === 'on',
balanceEnergyToCoverKwh: num(input.balance_energy_to_cover_kwh, NaN),
balanceStatusOk: cleanText(input.balance_status).toLowerCase() === 'ok',
balanceLastRunMs: parseRunStampToMs(cleanText(input.balance_last_run)),

View File

@@ -561,10 +561,61 @@ const nightTakeoverLatched =
parsed.soc < NIGHT_TAKEOVER_RELEASE_SOC_PCT &&
!vehicleChargeCompleted;
// =====================================================
// P12 — CHARGE NUIT SUR LA BATTERIE (15/09/2026)
// =====================================================
// Idee du proprietaire : plutot qu'acheter du reseau la nuit pour charger la
// voiture, lui donner le solaire DEJA STOCKE, doucement, et laisser ainsi de la
// place dans la batterie pour la production du lendemain. Payer du reseau la
// nuit pour ecreter le solaire le lendemain, c'est perdre deux fois.
//
// Le mode `battery_assist_night` existe depuis toujours pour exactement ca, et
// il est MORT depuis toujours : il exige `batteryCurrentA >= plancher de
// decharge` (0 A), impossible la nuit puisque la maison tire sur la batterie
// (§11 du HANDOFF, ~ -14 A). On ne cree donc pas un chemin, on rend viable
// celui qui existe — en remplacant un test de COURANT impossible par un test
// d'ENERGIE : rester au-dessus de ce qu'il faut pour tenir jusqu'au croisement.
//
// Le plancher n'est PAS une constante nouvelle : c'est `required_soc_prudent`,
// que le bilan publie deja, en profil p80. La marge est mesuree, pas inventee.
const nightBatterySurplusFloorPct = Math.max(
batteryHardFloorPct,
Number.isFinite(params.balanceRequiredSocPrudentPct)
? params.balanceRequiredSocPrudentPct
: Infinity,
);
// ⚠️ LE VERROU, ET IL N'EST PAS DECORATIF. Le plancher DESCEND pendant la nuit
// (il reste moins de nuit a couvrir) et le SOC aussi. Mesure du 15/09 :
//
// voiture en charge : SOC -7,1 pt/h, plancher -3,7 pt/h -> le surplus s'epuise
// voiture arretee : SOC -2,6 pt/h, plancher -3,7 pt/h -> le surplus REVIENT
//
// Sans verrou, la charge repartirait des qu'elle s'arrete : cinquieme
// oscillateur du projet, par construction. UNE SEULE PASSE de surplus par
// session de nuit, comme la recovery batterie depuis le 27/08.
const nightBatterySurplusExhausted =
params.nightBatteryDonePrev ||
(nightSessionActive && parsed.soc <= nightBatterySurplusFloorPct);
const nightBatterySurplusAvailable =
nightSessionActive &&
params.nightBatteryChargeEnabled &&
balanceMorningTargetApplied &&
Number.isFinite(params.balanceRequiredSocPrudentPct) &&
!vehicleChargeCompleted &&
!nightBatterySurplusExhausted &&
parsed.soc > nightBatterySurplusFloorPct;
// La batterie d'abord, le reseau quand le surplus est epuise. C'est la soupape
// decrite par le proprietaire — « quitte a fermer EDF entre 6h et 7h24 pour
// completer » — et elle devient automatique : l'epuisement du surplus rend
// `nightGridHcPreferred` vrai, donc P7 prend le relais.
const nightGridHcPreferred =
nightSessionActive &&
params.allowGridHcNight &&
!vehicleChargeCompleted;
!vehicleChargeCompleted &&
!nightBatterySurplusAvailable;
const batteryAssistAllowed =
nightSessionActive &&
@@ -1041,6 +1092,9 @@ return [{
batteryMorningTargetPct,
batteryMorningTargetBasePct,
balanceMorningTargetApplied,
nightBatterySurplusFloorPct,
nightBatterySurplusAvailable,
nightBatterySurplusExhausted,
nightGridSessionCommitted,
nightGridSessionUncovered,
balanceTargetAgeMin: