La protection regardait la maison, pas ce qu on demande au parc
Deux fermetures ce dimanche midi. Mesurees a l instant de la decision, contacteur encore ouvert donc production non censuree : maison 4025 et 4981 W, mais parc reellement sollicite 1132 et 772 W pour un plafond de 5100. La decharge batterie mesuree aux memes instants — 1345 et 1223 W — colle a maison moins PV, pas a la maison brute. Le solaire couvrait la cuisson ; la regle a ferme le contacteur pour rien, 0,50 kWh importes en plein soleil. Elle n avait bien fonctionne hier soir que parce qu il n y avait plus de PV. Les deux seuils portent desormais sur max(0, maison - PV). Contacteur ouvert cette grandeur EST la decharge batterie ; ferme, un bridage du MPPT la fait surestimer, donc l erreur pousse a rester ferme et jamais a relacher tot. Golden 20 -> 24, dont les deux releves de midi et le contrefactuel du nuage. Le test de mutation a montre que la premiere serie ne couvrait que le seuil de fermeture : il a fallu ecrire le cas du soleil revenu pour qu elle morde. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
This commit is contained in:
76
HANDOFF.md
76
HANDOFF.md
@@ -4520,6 +4520,82 @@ qu'apres 12:26.
|
||||
4. si la tension batterie se remet a disparaitre, `plafond_decharge_w` doit
|
||||
rester a ~5100 et non tomber a 0.
|
||||
|
||||
### MEME JOUR, DEFAUT PLUS PROFOND : la regle comptait la maison BRUTE
|
||||
Dimanche 06/09, deux fermetures du contacteur : **12:07 -> 12:22** (four +
|
||||
plaque) et **13:34 -> 13:42** (cuisson + JEEP branchee a 13:31). Journee
|
||||
nuageuse, parc reduit de moitie. Mesure a la resolution native **a l'instant ou
|
||||
chaque decision a ete prise, contacteur encore ouvert** — donc sur une
|
||||
production non censuree :
|
||||
|
||||
| fermeture | maison | PV | **parc reellement sollicite** | decharge batterie mesuree |
|
||||
|---|---:|---:|---:|---:|
|
||||
| 12:07, cuisson seule | 4 025 W | ~2 890 W | **1 132 W** | 1 345 W |
|
||||
| 13:34, cuisson + JEEP | 4 981 W | ~4 210 W | **772 W** | 1 223 W |
|
||||
|
||||
La decharge batterie colle a `maison - PV`, pas a la maison brute : le controle
|
||||
croise est net. Le plafond du parc est de 5 100 W — **il etait a 22 % et 15 % de
|
||||
sa limite, et la regle a ferme le contacteur pour rien.** Meme en integrant les
|
||||
periodes fermees (ou le PV peut etre bride, donc chiffres pessimistes), la
|
||||
demande maximale sur le parc n'a atteint que 3 046 et 2 437 W. Cout : 0,50 kWh
|
||||
importes en plein soleil, pour rien.
|
||||
|
||||
Cause : la regle du 05/09 compare la MAISON BRUTE au plafond de decharge du
|
||||
parc. Elle n'avait bien fonctionne la veille au soir que parce qu'il n'y avait
|
||||
plus de PV — la maison brute valait alors la demande sur le parc, et le pic de
|
||||
-97,4 A etait reel. Des qu'il y a du soleil, elle ferme sur une charge que le
|
||||
solaire couvre deja.
|
||||
|
||||
Correctif (deploye 06/09 13:49,
|
||||
`tools/patch-20260906b-demande-sur-le-parc.mjs`) : les deux seuils portent sur
|
||||
**`max(0, maison - PV)`**. `acOverSafeLimit` n'est PAS touche — il compare la
|
||||
charge au debit des onduleurs, qui portent la maison entiere quelle qu'en soit
|
||||
la source.
|
||||
|
||||
⚠️ **Pourquoi ce n'est pas un oscillateur**, alors que la grandeur n'est pas
|
||||
invariante a la decision (fermer peut brider le MPPT, §28) : contacteur OUVERT,
|
||||
`maison - PV` EST la decharge batterie, grandeur physique exacte ; contacteur
|
||||
FERME, un bridage du MPPT fait BAISSER PV donc MONTER `maison - PV` — l'erreur
|
||||
pousse a rester ferme, jamais a relacher tot ; et le relachement exige de toute
|
||||
facon le dwell (6 a 20 min), tres au-dela du transitoire d'etablissement mesure
|
||||
a ~150 s. Erreur unilaterale et bornee, dans la direction qui menage le parc.
|
||||
|
||||
Golden 20 -> 24 : les deux releves de ce midi (aucune fermeture attendue), le
|
||||
contrefactuel du nuage (meme cuisson a 4 500 W avec PV 200 W -> on ferme), et
|
||||
`h-midi-soleil-revenu-relache` (contacteur ferme, cuisson a 3 000 W mais PV
|
||||
2 000 -> le parc n'est plus sollicite qu'a 1 000 W, on rend). Les scenarios de
|
||||
protection existants portent desormais `pv_power_w: '0'` explicitement : ils
|
||||
decrivent le soir, ou le parc est seul.
|
||||
|
||||
⚠️ Piege evite grace au test de mutation : la premiere serie de scenarios ne
|
||||
couvrait que le seuil de FERMETURE. Remettre le relachement sur la maison brute
|
||||
ne faisait echouer aucun test — il a fallu ecrire `h-midi-soleil-revenu-relache`
|
||||
pour que la mutation morde.
|
||||
|
||||
### Ce que la JEEP n'a PAS cause, et la question qu'elle pose quand meme
|
||||
Le propriétaire attribuait la fermeture de midi a la conjonction cuisson +
|
||||
voiture. Les faits : **la voiture n'etait pas branchee** pendant l'episode de
|
||||
12:07 (EVCS a 0 W de bout en bout) ; elle n'a joue que dans celui de 13:34, qui
|
||||
n'aurait pas du fermer non plus. Les deux fermetures viennent de la regle, pas
|
||||
de la charge.
|
||||
|
||||
Reste que la question de fond est juste, et elle n'est pas traitee : `houseAcPowerW`
|
||||
inclut l'EVCS, donc **la voiture est comptee comme une charge menagere
|
||||
incompressible** alors qu'elle est la seule charge entierement compressible du
|
||||
foyer — le controleur EVCS peut la ramener a 6 A ou l'arreter en un cycle. Le
|
||||
jour ou la demande sur le parc depassera vraiment le plafond avec la voiture
|
||||
dedans, la reponse economique est de brider la voiture d'abord et de ne fermer
|
||||
le contacteur que pour le reste. Aucun des deux workflows ne sait faire cela
|
||||
aujourd'hui : le controleur EVCS ignore le plafond de decharge du BMS, et
|
||||
l'hysteresis ne sait pas commander la borne. A instruire.
|
||||
|
||||
### Anomalie annexe : une session de charge comptee deux fois
|
||||
`Session de charge terminee : JEEP, 4.20 kWh` a ete emis **deux fois** — a
|
||||
02:52:31 (fin de la charge HC reelle) et a 13:42:32 (debranchement apres onze
|
||||
minutes de charge diurne), avec la MEME valeur au centieme. Le compteur de
|
||||
session de `tools/historise-evcs.mjs` semble rejouer la session de la nuit au
|
||||
lieu d'en ouvrir une nouvelle. A corriger, sans quoi la table `session_charge`
|
||||
double-compte.
|
||||
|
||||
### Reste ouvert
|
||||
- Detecteur de gel dans le service d'historisation : une grandeur qui ne bouge
|
||||
pas alors qu'une autre du meme bilan bouge = alerte. Non fait.
|
||||
|
||||
@@ -990,6 +990,36 @@ protection jusqu'a la fin du dwell.
|
||||
Golden-hysteresis 11 -> 20, six mutations tombant chacune sur un jeu different.
|
||||
Detail : HANDOFF §57.
|
||||
|
||||
#### D-ter. La protection comptait la maison brute, pas la demande sur le parc (06/09/2026)
|
||||
|
||||
La regle de fermeture comparait `sensor.victron_consumption_power_l1` au
|
||||
plafond de decharge du BMS. Or le parc n'est sollicite que de ce que le solaire
|
||||
ne couvre pas. Dimanche 06/09, deux fermetures, mesurees a l'instant de la
|
||||
decision (contacteur encore ouvert, donc production non censuree) :
|
||||
|
||||
| fermeture | maison | PV | parc sollicite | decharge batterie |
|
||||
|---|---:|---:|---:|---:|
|
||||
| 12:07, cuisson | 4 025 W | ~2 890 W | **1 132 W** | 1 345 W |
|
||||
| 13:34, cuisson + JEEP | 4 981 W | ~4 210 W | **772 W** | 1 223 W |
|
||||
|
||||
Plafond du parc : 5 100 W. Il etait a 22 % et 15 % de sa limite — deux
|
||||
fermetures pour rien, 0,50 kWh importes en plein soleil. La regle n'avait bien
|
||||
fonctionne la veille au soir que parce qu'il n'y avait plus de PV.
|
||||
|
||||
Les deux seuils portent desormais sur `max(0, maison - PV)`. Contacteur ouvert,
|
||||
cette grandeur EST la decharge batterie ; ferme, elle est le contrefactuel
|
||||
« ce que le parc devrait fournir si on ouvrait », qu'un eventuel bridage du MPPT
|
||||
fait SURESTIMER — erreur unilaterale, qui pousse a rester ferme. Golden 20 -> 24.
|
||||
Detail : HANDOFF §57.
|
||||
|
||||
⚠️ Question ouverte que cet episode souleve : `houseAcPowerW` inclut l'EVCS,
|
||||
donc la voiture est comptee comme une charge incompressible alors qu'elle est la
|
||||
seule charge entierement compressible du foyer. Le jour ou la demande sur le
|
||||
parc depassera vraiment le plafond avec la voiture dedans, il faudrait brider la
|
||||
voiture avant de fermer le contacteur — ce qu'aucun des deux workflows ne sait
|
||||
faire : le controleur EVCS ignore le plafond de decharge du BMS, et
|
||||
l'hysteresis ne commande pas la borne.
|
||||
|
||||
#### E. Le plancher du soir etait un niveau, pas une energie (03/09/2026)
|
||||
|
||||
`evening_soc_start_min` = 85 % tente de dire « garde de quoi passer la nuit ».
|
||||
|
||||
@@ -388,3 +388,19 @@ heure_reelle,etat,courant_mA,c1_mV,c2_mV,c3_mV,c4_mV,c5_mV,c6_mV,c7_mV,c8_mV,c9_
|
||||
2026-09-06T11:01:04.050Z,Y230202C30371426,,3393,3390,3390,3391,3392,3393,3390,3390,3390,3391,3393,3391,3390,3390,3393,3
|
||||
2026-09-06T11:01:04.145Z,Y230202C30371425,,3392,3390,3390,3390,3391,3391,3391,3389,3389,3391,3393,3392,3391,3391,3391,4
|
||||
2026-09-06T11:01:04.362Z,Y230202C30371427,,3392,3390,3390,3389,3391,3391,3388,3389,3389,3390,3392,3389,3389,3389,3391,4
|
||||
2026-09-06T11:11:04.465Z,Y230202C30371426,,3391,3389,3389,3389,3391,3391,3388,3389,3389,3389,3391,3389,3390,3390,3391,3392,3390,3390,3391,3392,3392,3390,3390,3390,3391,3392,3391,3390,3390,3393,5
|
||||
2026-09-06T11:11:04.593Z,Y230202C30371425,,3390,3389,3389,3390,3389,3390,3389,3388,3388,3390,3391,3390,3390,3390,3390,3
|
||||
2026-09-06T11:11:04.688Z,Y230202C30371431,,3390,3388,3389,3388,3389,3389,3386,3387,3387,3388,3390,3387,3388,3388,3389,4
|
||||
2026-09-06T11:11:04.813Z,Y230202C30371427,,3389,3388,3387,3388,3389,3390,3387,3387,3387,3388,3390,3388,3388,3388,3390,3
|
||||
2026-09-06T11:21:04.908Z,Y230202C30371426,,3391,3389,3389,3390,3390,3391,3389,3389,3388,3389,3392,3390,3389,3388,3391,4
|
||||
2026-09-06T11:21:05.006Z,Y230202C30371425,,3384,3383,3383,3384,3382,3383,3384,3382,3383,3383,3385,3384,3385,3384,3383,3
|
||||
2026-09-06T11:21:05.132Z,Y230202C30371431,,3383,3382,3383,3381,3382,3382,3380,3381,3381,3381,3384,3382,3382,3381,3381,4
|
||||
2026-09-06T11:21:05.257Z,Y230202C30371427,,3383,3382,3382,3383,3384,3383,3382,3382,3383,3382,3383,3383,3383,3384,3384,2
|
||||
2026-09-06T11:31:05.360Z,Y230202C30371426,,3385,3384,3385,3386,3386,3386,3384,3385,3383,3385,3386,3385,3385,3384,3386,3
|
||||
2026-09-06T11:31:05.460Z,Y230202C30371425,,3393,3391,3391,3392,3392,3392,3391,3390,3391,3392,3394,3393,3393,3392,3393,4
|
||||
2026-09-06T11:31:05.587Z,Y230202C30371431,,3393,3391,3391,3390,3393,3392,3389,3390,3390,3391,3394,3390,3390,3390,3391,5
|
||||
2026-09-06T11:31:05.714Z,Y230202C30371427,,3391,3389,3388,3389,3391,3391,3389,3388,3389,3389,3391,3389,3390,3390,3390,3
|
||||
2026-09-06T11:41:05.817Z,Y230202C30371426,,3391,3389,3389,3390,3390,3392,3389,3389,3388,3389,3391,3391,3389,3389,3390,4
|
||||
2026-09-06T11:41:05.944Z,Y230202C30371425,,3350,3350,3350,3350,3350,3349,3350,3349,3349,3350,3350,3350,3350,3350,3350,1
|
||||
2026-09-06T11:41:06.039Z,Y230202C30371431,,3349,3348,3348,3348,3348,3349,3347,3348,3347,3347,3349,3348,3348,3348,3347,2
|
||||
2026-09-06T11:41:06.226Z,Y230202C30371427,,3342,3342,3343,3344,3343,3342,3343,3343,3343,3343,3342,3343,3343,3344,3344,2
|
||||
|
||||
|
@@ -66,6 +66,7 @@ function summarize(out) {
|
||||
shouldNotify: !!d.should_notify,
|
||||
evcsGridOverride: !!c.evcs_grid_override,
|
||||
plafondDechargeW: c.plafond_decharge_w,
|
||||
demandeParcW: c.demande_parc_w,
|
||||
dwellMinutes: c.dwell_minutes,
|
||||
dwellEcoule: c.dwell_ecoule,
|
||||
reserveDejaCondamnee: !!c.reserve_deja_condamnee,
|
||||
|
||||
@@ -63,6 +63,13 @@ const recoveryBase = {
|
||||
const parcQuatreModules = {
|
||||
battery_max_discharge_a: '100',
|
||||
battery_voltage_v: '51',
|
||||
// ⚠️ PV NULLE, ET C'EST STRUCTUREL. Depuis le 06/09 les deux seuils portent
|
||||
// sur `max(0, maison - PV)`, ce que le parc est REELLEMENT sollicite de
|
||||
// fournir, et non sur la maison brute. Les scenarios de protection decrivent
|
||||
// le soir : le parc est seul, la maison brute EST la demande sur le parc. Les
|
||||
// scenarios `h-midi-*` couvrent le cas diurne, ou le solaire couvre la
|
||||
// cuisson et ou la regle ne doit PAS fermer.
|
||||
pv_power_w: '0',
|
||||
};
|
||||
|
||||
export const scenarios = [
|
||||
@@ -405,6 +412,7 @@ export const scenarios = [
|
||||
...recoveryBase,
|
||||
battery_max_discharge_a: '100',
|
||||
battery_voltage_v: 'unavailable',
|
||||
pv_power_w: '0',
|
||||
soc_percent: '65',
|
||||
house_ac_power_w: '2000',
|
||||
last_on_at: minutesAgo(T_MS, 40),
|
||||
@@ -426,6 +434,7 @@ export const scenarios = [
|
||||
...recoveryBase,
|
||||
battery_max_discharge_a: 'unavailable',
|
||||
battery_voltage_v: 'unavailable',
|
||||
pv_power_w: '0',
|
||||
soc_percent: '65',
|
||||
house_ac_power_w: '2000',
|
||||
last_on_at: minutesAgo(T_MS, 40),
|
||||
@@ -447,6 +456,7 @@ export const scenarios = [
|
||||
...recoveryBase,
|
||||
battery_max_discharge_a: 'unavailable',
|
||||
battery_voltage_v: 'unavailable',
|
||||
pv_power_w: '0',
|
||||
soc_percent: '65',
|
||||
house_ac_power_w: '2000',
|
||||
last_on_at: minutesAgo(T_MS, 40),
|
||||
@@ -459,4 +469,102 @@ export const scenarios = [
|
||||
gridAction: 'turn_off',
|
||||
},
|
||||
},
|
||||
// =====================================================
|
||||
// MIDI ENSOLEILLE : LE SOLAIRE COUVRE LA CUISSON (06/09/2026)
|
||||
// =====================================================
|
||||
// Deux fermetures ce dimanche, mesurees a la resolution native A L'INSTANT
|
||||
// DE LA DECISION, contacteur encore ouvert donc production non censuree :
|
||||
//
|
||||
// 12:07, cuisson seule maison 4 025 W parc sollicite 1 132 W
|
||||
// 13:34, cuisson + JEEP maison 4 981 W parc sollicite 772 W
|
||||
//
|
||||
// Controle croise : la decharge batterie valait 1 345 et 1 223 W aux memes
|
||||
// instants — elle colle a `maison - PV`, pas a la maison brute. Le plafond du
|
||||
// parc est de 5 100 W : il etait a 22 % et 15 % de sa limite, et la regle a
|
||||
// ferme le contacteur pour rien.
|
||||
{
|
||||
id: 'h-midi-solaire-couvre-la-cuisson',
|
||||
label: 'RELEVE 06/09 12:07 : maison 4025 W mais PV 2893 W, le parc ne fournit que 1132 W — aucune fermeture',
|
||||
time: T,
|
||||
overrides: {
|
||||
...recoveryBase,
|
||||
...parcQuatreModules,
|
||||
grid_latch: 'off',
|
||||
grid_state: 'off',
|
||||
soc_percent: '69',
|
||||
house_ac_power_w: '4025',
|
||||
pv_power_w: '2893',
|
||||
},
|
||||
expect: {
|
||||
state: 'observe_only',
|
||||
gridAction: 'none',
|
||||
latchAction: 'none',
|
||||
demandeParcW: 1132,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'h-midi-jeep-en-plus-solaire-couvre-encore',
|
||||
label: 'RELEVE 06/09 13:34 : maison 4981 W dont la JEEP, PV 4209 W, parc a 772 W — aucune fermeture non plus',
|
||||
time: T,
|
||||
overrides: {
|
||||
...recoveryBase,
|
||||
...parcQuatreModules,
|
||||
grid_latch: 'off',
|
||||
grid_state: 'off',
|
||||
soc_percent: '86',
|
||||
house_ac_power_w: '4981',
|
||||
pv_power_w: '4209',
|
||||
evcs_ac_power_w: '1621',
|
||||
evcs_charging: 'on',
|
||||
evcs_surplus_state: 'charging_step_up_battery',
|
||||
evcs_source_mode: 'Solaire',
|
||||
},
|
||||
expect: {
|
||||
state: 'observe_only',
|
||||
gridAction: 'none',
|
||||
demandeParcW: 772,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'h-midi-nuage-le-parc-encaisse-tout',
|
||||
label: 'CONTREFACTUEL : meme cuisson a 4500 W mais le nuage passe, PV 200 W — le parc encaisse 4300 W, on ferme',
|
||||
time: T,
|
||||
overrides: {
|
||||
...recoveryBase,
|
||||
...parcQuatreModules,
|
||||
grid_latch: 'off',
|
||||
grid_state: 'off',
|
||||
soc_percent: '69',
|
||||
house_ac_power_w: '4500',
|
||||
pv_power_w: '200',
|
||||
},
|
||||
expect: {
|
||||
state: 'turn_on_charge_au_dessus_du_parc',
|
||||
gridAction: 'turn_on',
|
||||
latchAction: 'turn_on',
|
||||
demandeParcW: 4300,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'h-midi-soleil-revenu-relache',
|
||||
label: "Le nuage est passe, contacteur ferme : la cuisson continue a 3000 W mais le PV en couvre 2000 — le parc n'est plus sollicite qu'a 1000 W, on rend le reseau",
|
||||
time: T,
|
||||
overrides: {
|
||||
...recoveryBase,
|
||||
...parcQuatreModules,
|
||||
soc_percent: '69',
|
||||
house_ac_power_w: '3000',
|
||||
pv_power_w: '2000',
|
||||
last_on_at: minutesAgo(T_MS, 40),
|
||||
charge_high_last_at: minutesAgo(T_MS, 25),
|
||||
balance_required_soc: '92',
|
||||
balance_last_run: bilanRunAgo(T_MS, 3),
|
||||
},
|
||||
expect: {
|
||||
state: 'turn_off_vehicle_unplugged',
|
||||
gridAction: 'turn_off',
|
||||
demandeParcW: 1000,
|
||||
setChargeHighLastAt: false,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
109
tools/patch-20260906b-demande-sur-le-parc.mjs
Normal file
109
tools/patch-20260906b-demande-sur-le-parc.mjs
Normal file
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env node
|
||||
// La regle de protection comptait la maison BRUTE, pas ce que le parc est
|
||||
// reellement sollicite de fournir.
|
||||
//
|
||||
// Dimanche 06/09, deux fermetures du contacteur, mesurees a la resolution
|
||||
// native (InfluxDB) A L'INSTANT OU LA DECISION A ETE PRISE, contacteur encore
|
||||
// ouvert — donc sur une production non censurée :
|
||||
//
|
||||
// fermeture 1 (12:07, cuisson seule) maison 4 025 W parc sollicite 1 132 W
|
||||
// fermeture 2 (13:34, cuisson + JEEP) maison 4 981 W parc sollicite 772 W
|
||||
//
|
||||
// Controle croise : la decharge batterie mesuree aux memes instants valait
|
||||
// 1 345 et 1 223 W — elle colle a `maison - PV`, pas a la maison brute.
|
||||
//
|
||||
// Le plafond du parc est de 5 100 W. Le parc etait donc a 22 % et 15 % de sa
|
||||
// limite, et la regle a ferme le contacteur pour rien : le solaire (3 a 4 kW)
|
||||
// couvrait la cuisson. Elle n'avait bien fonctionne hier soir que parce qu'il
|
||||
// n'y avait plus de PV — la maison brute valait alors la demande sur le parc.
|
||||
//
|
||||
// Correctif : les deux seuils portent sur `max(0, maison - PV)`.
|
||||
//
|
||||
// ⚠️ POURQUOI CE N'EST PAS UN OSCILLATEUR, alors que la grandeur n'est pas
|
||||
// invariante a la decision (fermer le contacteur peut brider le MPPT, §28) :
|
||||
// - contacteur OUVERT, `maison - PV` EST la decharge batterie, la grandeur
|
||||
// physique exacte ;
|
||||
// - contacteur FERME, brider le MPPT fait BAISSER PV, donc MONTER
|
||||
// `maison - PV` : l'erreur pousse a rester ferme, jamais a relacher tot ;
|
||||
// - et le relachement exige de toute facon le dwell (6 a 20 min), tres
|
||||
// au-dela du transitoire d'etablissement mesure a ~150 s.
|
||||
// L'erreur est donc unilaterale et bornee, dans la direction qui menage le parc.
|
||||
//
|
||||
// `acOverSafeLimit` n'est PAS touche : il compare la charge au debit des
|
||||
// onduleurs, qui portent la maison entiere quelle qu'en soit la source.
|
||||
//
|
||||
// node tools/patch-20260906b-demande-sur-le-parc.mjs
|
||||
|
||||
import fs from 'node:fs';
|
||||
|
||||
const F = 'workflows/victron-grid-hysteresis-v1.json';
|
||||
const wf = JSON.parse(fs.readFileSync(F, 'utf8'));
|
||||
const calc = wf.nodes.find((n) => n.name === 'Compute Grid Hysteresis');
|
||||
if (!calc) throw new Error('noeud introuvable');
|
||||
|
||||
function remplace(t, a, b, quoi) {
|
||||
if (!t.includes(a)) throw new Error(`ancre introuvable (${quoi}) : ${a.slice(0, 70)}`);
|
||||
return t.replace(a, b);
|
||||
}
|
||||
|
||||
let c = calc.parameters.jsCode;
|
||||
|
||||
if (c.includes('demandeParcW')) {
|
||||
console.log(' deja fait');
|
||||
} else {
|
||||
// 1. la grandeur
|
||||
c = remplace(c,
|
||||
'const chargeAuDessusDuParc = plafondDechargeW > 0 && houseAcPowerW >= seuilFermetureW;',
|
||||
`// CE QUE LE PARC EST REELLEMENT SOLLICITE DE FOURNIR (06/09/2026)
|
||||
// La maison brute n'est pas la demande sur la batterie : le solaire en couvre
|
||||
// une partie. Mesure du 06/09 a l'instant des deux fermetures, contacteur
|
||||
// encore ouvert : maison 4 025 et 4 981 W, parc sollicite 1 132 et 772 W pour
|
||||
// un plafond de 5 100 W — deux fermetures pour rien. Controle croise : la
|
||||
// decharge batterie valait alors 1 345 et 1 223 W.
|
||||
//
|
||||
// Contacteur ouvert, cette grandeur EST la decharge batterie. Ferme, elle est
|
||||
// le contrefactuel « ce que le parc devrait fournir si on ouvrait », et un
|
||||
// eventuel bridage du MPPT par la presence du reseau la fait SURESTIMER —
|
||||
// erreur unilaterale, qui pousse a rester ferme, jamais a relacher tot.
|
||||
const demandeParcW = Math.max(0, houseAcPowerW - pvPowerW);
|
||||
|
||||
const chargeAuDessusDuParc = plafondDechargeW > 0 && demandeParcW >= seuilFermetureW;`,
|
||||
'fermeture');
|
||||
|
||||
c = remplace(c,
|
||||
'const chargeSousSeuilBas = plafondDechargeW > 0 && houseAcPowerW < seuilRelachementW;',
|
||||
'const chargeSousSeuilBas = plafondDechargeW > 0 && demandeParcW < seuilRelachementW;',
|
||||
'relachement');
|
||||
|
||||
c = remplace(c,
|
||||
"const setChargeHighLastAt = plafondDechargeW > 0 && !chargeSousSeuilBas;",
|
||||
"const setChargeHighLastAt = plafondDechargeW > 0 && !chargeSousSeuilBas;",
|
||||
'ecriture'); // inchange : suit desormais demandeParcW via chargeSousSeuilBas
|
||||
|
||||
// 2. les raisons
|
||||
c = remplace(c,
|
||||
' `Charge maison ${Math.round(houseAcPowerW)}W au-dessus de ${Math.round(seuilFermetureW)}W `\n + `(80% du plafond de decharge BMS ${Math.round(plafondDechargeW)}W) : le reseau prend la difference`);',
|
||||
' `Demande sur le parc ${Math.round(demandeParcW)}W (maison ${Math.round(houseAcPowerW)}W - PV ${Math.round(pvPowerW)}W) `\n + `au-dessus de ${Math.round(seuilFermetureW)}W, soit 80% du plafond de decharge BMS ${Math.round(plafondDechargeW)}W : le reseau prend la difference`);',
|
||||
'raison fermeture');
|
||||
|
||||
c = remplace(c,
|
||||
" ? `Charge maison retombee a ${Math.round(houseAcPowerW)}W depuis ${round1(minutesDepuisChargeHaute || 0)} min : `",
|
||||
" ? `Demande sur le parc retombee a ${Math.round(demandeParcW)}W depuis ${round1(minutesDepuisChargeHaute || 0)} min : `",
|
||||
'raison dwell');
|
||||
|
||||
c = remplace(c,
|
||||
" : `Charge maison ${Math.round(houseAcPowerW)}W encore au-dessus de ${Math.round(seuilRelachementW)}W : on garde le reseau`);",
|
||||
" : `Demande sur le parc ${Math.round(demandeParcW)}W (maison ${Math.round(houseAcPowerW)}W - PV ${Math.round(pvPowerW)}W) encore au-dessus de ${Math.round(seuilRelachementW)}W : on garde le reseau`);",
|
||||
'raison maintien');
|
||||
|
||||
// 3. le debug
|
||||
c = remplace(c, ' plafond_decharge_w: Math.round(plafondDechargeW),',
|
||||
' plafond_decharge_w: Math.round(plafondDechargeW),\n demande_parc_w: Math.round(demandeParcW),',
|
||||
'debug');
|
||||
|
||||
calc.parameters.jsCode = c;
|
||||
console.log(' calcul : les deux seuils portent sur maison - PV');
|
||||
}
|
||||
|
||||
fs.writeFileSync(F, JSON.stringify(wf, null, 2) + '\n');
|
||||
console.log(`\n${F} ecrit.`);
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user