docs : heures creuses et batterie — design, sûreté L2, inventaire du mock (lot e1)
DESIGN_HC_BATTERIE.md : la règle des heures creuses, les modes de borne concernés et le changement de comportement, la lecture du modèle SunSpec 124 (StorCtl_Mod = bit qui ACTIVE la limite, OutWRte en %, séquence NO_DISCHARGE du plugin) qui fixe l'ordre des écritures, le minuteur de retour comme sûreté (et l'hypothèse non levée du plugin sur le 124), l'invariant 8 et les règles de réserve, ce qui est publié, les preuves, et ce que le lot ne fait pas. SAFETY.md : le repli L2 lève la limite de décharge explicitement. INVENTAIRE_MOCK.md : la classe controllableStorage, et ce qu'elle n'émule pas. DESIGN_PREVISION_PV.md §32.4 : la décision e1 est prise, pointeur. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d9372c14ba
commit
4ffa8391cf
226
docs/DESIGN_HC_BATTERIE.md
Normal file
226
docs/DESIGN_HC_BATTERIE.md
Normal file
@ -0,0 +1,226 @@
|
||||
# Heures creuses pour la borne, batterie protégée pendant sa charge — lot e1 (2026-10-24)
|
||||
|
||||
*Décisions de Patrick du 2026-10-24. Ce document décrit ce que le code fait, les preuves qui le
|
||||
rejouent, et ce qu'il ne fait pas. Code : `etm/tariff/tariffconfig.*`,
|
||||
`etm/scheduler/rulebasedscheduler.cpp`, `etm/adapters/storagedischargeguard.*`,
|
||||
`etm/energyarbitrator.cpp` (`buildContext`, `update`, `applyDegradedMode`).*
|
||||
|
||||
## 1. Les heures creuses
|
||||
|
||||
**Règle** : les heures creuses sont **la ou les zones au prix le plus bas** d'un tarif à zones
|
||||
horaires (`tou`) dont les prix **diffèrent** (`TariffConfig::zonesCreuses()`).
|
||||
|
||||
- « HC » n'a pas de code : le libellé est une donnée de l'installateur. Le prix se compare.
|
||||
- Plusieurs zones au même prix minimal sont toutes creuses (une nuit et un début d'après-midi
|
||||
saisis comme deux zones).
|
||||
- **Aucune heure creuse** sans tarif, avec un tarif unique (`fixed`), ou avec des zones toutes au
|
||||
même prix. Dans ces trois cas **rien de ce lot ne s'exécute** : le moteur est celui d'etm74
|
||||
(preuve `decisions` IDENTIQUE, et `testWithoutOffPeakTheEngineIsEtm74`).
|
||||
- Lecture murale, minute **absolue** par minute (`enHeuresCreuses()`, `prochaineBascule()`), dans
|
||||
le fuseau de la box relu à chaque cycle. Les jours de 23 h et de 25 h sont exacts (nuit
|
||||
22:00-06:00 de 7 h et de 9 h), épinglés sur des époques calculées hors de Qt.
|
||||
- Le **prix** n'est toujours lu par aucune décision, et `SurplusContext::tariff` n'est toujours
|
||||
pas rempli : l'optimiseur ne reçoit rien de neuf. Les heures creuses vivent dans
|
||||
`SurplusContext::offPeak`, interne au moteur.
|
||||
|
||||
## 2. La borne : surplus le jour, complément en heures creuses
|
||||
|
||||
**Modes concernés** — `ChargingModeEcoWithMinCurrent`, `ChargingModeEcoMinWithTargetTime`,
|
||||
`ChargingModeEcoWithTargetTime` : ceux dont le besoin réseau peut attendre. `EvAdapter` le
|
||||
DÉCLARE (`LoadNeeds::offPeakShift`, `offPeakMinPowerW` = le plancher de la borne), le scheduler
|
||||
le DÉCIDE (règle 2). `ChargingModeEco` ne demande jamais le réseau, `ChargingModeNormal` est
|
||||
piloté par l'utilisateur : tous deux sont inchangés.
|
||||
|
||||
| | hors heures creuses | en heures creuses |
|
||||
|---|---|---|
|
||||
| minimum réseau (`minPowerWAlways`) | **retiré** — surplus seulement | le plancher de la borne, au moins |
|
||||
| démarrage sous tolérance (`EV_GRID_START`) | **refusé** (le minimum par une autre porte) | inchangé |
|
||||
| motif d'une consigne nulle | **`EV_WAITING_OFF_PEAK`** `{at, startsAt, budgetW}` | motifs ordinaires |
|
||||
| échéance (`EV_DEADLINE`, proxy) | inchangée | inchangée |
|
||||
|
||||
**Le changement de comportement** : une borne « Éco avec minimum » ne prend plus ses 6 A au
|
||||
réseau le soir. Elle charge au surplus tant qu'il y en a, puis attend 22:00. Le motif le dit :
|
||||
« Borne attend les heures creuses (22:00) — hors heures creuses, surplus seulement (… W) ».
|
||||
`EV_WAITING_OFF_PEAK` remplace `SURPLUS_INSUFFICIENT`, `BELOW_MIN_POWER` et `BATTERY_RESERVE`,
|
||||
parce que la cause de la consigne nulle n'est plus le manque de surplus. Le plafond de soutirage
|
||||
(`DRAW_CAP`), le refus (`RECREDIT_SUSPENDED`), la limite de phase, l'indisponibilité et les
|
||||
verrous gardent la tête : ils diraient la même chose en heures creuses.
|
||||
|
||||
**En heures creuses**, le plancher est servi au réseau par la passe éco (`ECO_FLOOR_GRID`),
|
||||
bornée par l'autorisation de soutirage ; le confort ajoute le surplus s'il y en a. La borne
|
||||
déclare un plafond écrêté par `evPhaseAllowanceW()`, `verifyOverloadProtection()` garde le dernier
|
||||
mot : l'invariant 2 tient sans rien ajouter.
|
||||
|
||||
**L'échéance** : la puissance nécessaire pour tenir une échéance reste celle du proxy amont, qui
|
||||
force la charge à pleine puissance au point de non-retour. Ce point est calculé sur l'échéance,
|
||||
pas sur la fin des heures creuses : une échéance trop proche peut donc encore se servir en
|
||||
heures pleines. Une échéance est une promesse de l'utilisateur, le tarif ne la rompt pas. Étaler
|
||||
la charge sur les heures creuses demanderait une énergie restante mesurée (LM-1009) : c'est une
|
||||
proposition, pas ce lot.
|
||||
|
||||
**À 06:00**, le minimum est retiré : une borne qui charge encore s'arrête (au premier cycle où
|
||||
son verrou d'enclenchement le permet, 300 s par défaut).
|
||||
|
||||
## 3. La batterie : décharge bloquée pendant la charge de la voiture en heures creuses
|
||||
|
||||
### 3.1 Ce que le modèle SunSpec 124 dit — et ce que le plugin écrit
|
||||
|
||||
Lu dans le plugin `sunspec` (`integrationpluginsunspec.cpp`, `sunspecstoragelogic.*`,
|
||||
`froniusrules.*`) et dans la définition du modèle 124 de `libnymea-sunspec` :
|
||||
|
||||
- `StorCtl_Mod` est un **champ de bits** — « Activate hold/discharge/charge storage control
|
||||
mode » : bit 0 `CHARGE`, bit 1 `DiSCHARGE`. Le bit **active la limite** correspondante, il
|
||||
n'« autorise » pas l'opération.
|
||||
- `OutWRte` est la limite de décharge, en **pourcentage** de la puissance maximale (`% WDisChaMax`
|
||||
dans le modèle, « % de `WChaMax` » dans la documentation du plugin). **0 % vaut 0 W quelle que
|
||||
soit la référence** : l'unité n'a pas d'incidence sur la valeur écrite ici, ni le facteur
|
||||
d'échelle `InOutWRte_SF` (que le plugin relit avant chaque écriture, AC-12).
|
||||
- L'état `enableDischarging` du plugin **est** ce bit (`readStates()`), et l'action le pose par
|
||||
lecture-modification-écriture de `StorCtl_Mod`. L'état `dischargingRate` **est** `OutWRte`.
|
||||
- Le contrat du plugin (AC-11, `FroniusRules::planBatteryMode()`) le confirme :
|
||||
`NO_DISCHARGE` = `StorCtl_Mod = 2`, `OutWRte = 0` ; `NORMAL` = `StorCtl_Mod = 0`, `OutWRte = 100`.
|
||||
|
||||
Donc **`enableDischarging = false` LÈVE la limite** — il ne bloque rien. La séquence qui bloque
|
||||
réellement la décharge est **`dischargingRate = 0`, puis `enableDischarging = true`**. Le retour
|
||||
à l'automatisme est **`enableDischarging = false`, puis `dischargingRate = 100`** (le maximum de
|
||||
l'état).
|
||||
|
||||
**Le plugin permet de l'écrire, en deux actions.** Chacune est un plan d'écriture complet (ordre
|
||||
imposé, relecture, minuteur de retour réarmé en dernier). Elles ne sont pas atomiques : le garde
|
||||
les **enchaîne** (la seconde part à la confirmation de la première), dans l'ordre qui rend
|
||||
chaque état intermédiaire sûr :
|
||||
|
||||
- pose : le taux d'abord. Tant que la limite est inactive, le taux est inerte ; quand elle
|
||||
s'active, il vaut déjà 0. Si la première écriture échoue, la seconde ne part pas — la limite
|
||||
reste inactive, la batterie en automatique ;
|
||||
- levée : la limite d'abord, l'automatisme revient tout de suite ; le taux est remis au maximum
|
||||
pour qu'une limite réactivée plus tard ne reparte pas à 0 %.
|
||||
|
||||
`FroniusRules::planBatteryMode(NO_DISCHARGE)` écrirait les deux registres en une séquence, mais
|
||||
aucune action du plugin ne l'emprunte. L'exposer serait plus propre (§7) ; ce n'est pas
|
||||
nécessaire pour ce lot.
|
||||
|
||||
### 3.2 Quand
|
||||
|
||||
**Heure creuse ET bornes qui tirent réellement ≥ 230 W (mesuré, toutes bornes, mode manuel
|
||||
compris) ET au moins une batterie pilotable.** Sinon la batterie est rendue à son automatisme,
|
||||
et une consigne tenue est **levée explicitement**. La décision est prise par le rule-based à
|
||||
chaque cycle (`RuleBasedScheduler::storageDecision()`), y compris en ombre d'un optimiseur.
|
||||
|
||||
La batterie est bloquée au cycle où la voiture **tire** : au cycle de 22:00 la borne vient d'être
|
||||
commandée et lit encore 0 W, le blocage part à 22:01. Elle est rendue au cycle où la borne ne
|
||||
tire plus (fin de charge) ou à 06:00.
|
||||
|
||||
Ce que le blocage bloque : **toute** décharge, maison comprise. « Ne pas se décharger dans la
|
||||
voiture » ne s'exprime pas autrement sans asservir `OutWRte` à la consommation de la maison —
|
||||
une boucle de régulation que le lot ne fait pas.
|
||||
|
||||
### 3.3 Pilotable, ou non
|
||||
|
||||
Par l'interface `energystorage` et les **états présents** — aucune ThingClass n'est nommée
|
||||
(`StorageDischargeGuard::capacite()`, question posée à la classe) :
|
||||
|
||||
| cause | condition | effet |
|
||||
|---|---|---|
|
||||
| — | `enableDischarging` (booléen) et `dischargingRate` (0 admis) modifiables, `revertTime` ≥ 120 s | commandée |
|
||||
| `noDischargeControl` | un des deux états absent ou non modifiable | lue comme avant, `STORAGE_NOT_PROTECTED` |
|
||||
| `noRevertTimer` | pas de paramètre `revertTime`, ou 0 | idem — un moteur arrêté la laisserait bloquée sans fin |
|
||||
| `revertTimerTooShort` | `revertTime` < 120 s | idem — elle expirerait entre deux cycles |
|
||||
|
||||
### 3.4 Le minuteur et le rafraîchissement
|
||||
|
||||
Chaque écriture du plugin se termine par `InOutWRte_RvrtTms = revertTime` (300 s sous Fronius,
|
||||
`FroniusRules::DefaultRevertTimeSeconds`). Le garde réécrit la séquence dès que la dernière a
|
||||
**le tiers du minuteur** (100 s) : à un cycle par minute, deux écritures sont espacées de 120 s,
|
||||
180 s si un cycle manque — toujours sous 300 s. Il la réécrit aussi, sans attendre, si la
|
||||
batterie ne rapporte plus la limite (onduleur revenu seul à l'automatisme).
|
||||
|
||||
**La sûreté est le minuteur**, pas le moteur : si `nymead` s'arrête, plus rien ne réécrit, et le
|
||||
GEN24 reprend son automatisme au plus 300 s après la dernière écriture. Sous compteur muet (L2),
|
||||
le garde lève la limite explicitement. Au redémarrage, une limite à 0 % trouvée active est
|
||||
reprise (rafraîchie ou levée).
|
||||
|
||||
⚠️ **Hypothèse non levée, et elle est du plugin** : la sémantique du minuteur est documentée par
|
||||
le constructeur au chapitre général et illustrée sur le modèle 123, pas sur le 124 (AC-10 du
|
||||
plugin, « décision D4 non validée »). Les tests la modélisent ; seule une mesure sur un GEN24
|
||||
réel la prouve.
|
||||
|
||||
### 3.5 Sécurité et invariant 8 (« pas de boucle »)
|
||||
|
||||
La décision ne lit **ni le budget ni la réserve**, et n'y verse rien. Le budget reste compteur +
|
||||
PV mesurés. Les règles de réserve (`rulebasedscheduler.cpp`, « Prise en compte du stockage »)
|
||||
restent justes sous blocage :
|
||||
|
||||
- **la nuit**, batterie bloquée et sans PV : `powerW` ≈ 0, aucune branche ne modifie le budget,
|
||||
qui vaut −(import). Le blocage augmente l'import, le budget le constate : aucun surplus n'est
|
||||
fabriqué (`testBlockedDischargeShowsAtTheMeterAndL4Decides`, `surplusW == −import`) ;
|
||||
- **sous la réserve**, le surplus positif est annulé : il n'y en a pas la nuit, la règle est
|
||||
sans effet ;
|
||||
- **au-dessus de la réserve et en charge** (PV avant 06:00 l'été) : la charge de la batterie
|
||||
est rendue au budget. C'est vrai sous blocage aussi : bloquer la décharge ne touche pas la
|
||||
charge, et le GEN24 réduit sa charge pour couvrir une consommation nouvelle — ce qu'il ne peut
|
||||
plus couvrir vient alors du réseau, pas de la batterie, et le compteur le montre au cycle
|
||||
suivant ;
|
||||
- **en décharge** (`powerW` < 0, si l'onduleur ignorait la consigne) : retranchée, comme avant —
|
||||
le sens prudent.
|
||||
|
||||
**Le soutirage ajouté** — ce que la batterie couvrait passe au réseau — se mesure au cycle
|
||||
suivant : la marge de soutirage du contexte (`houseDrawMargin()`) et `verifyOverloadProtection()`
|
||||
le lisent au compteur, et coupent la borne s'il dépasse (éprouvé avec une limite de 25 A). La
|
||||
borne coupée ne tire plus : la batterie est rendue au cycle d'après.
|
||||
|
||||
**Oscillation possible, signalée** : sur une installation au bord de sa limite de phase, la suite
|
||||
« bloquer → la phase dépasse → L4 coupe la borne → rendre → la batterie couvre → la borne
|
||||
redémarre » peut se répéter. Sa période est bornée par le verrou d'enclenchement de la borne
|
||||
(300 s), et L4 tient la sécurité à chaque tour.
|
||||
|
||||
**Hystérésis de la réserve de 20 %** : non touchée. Effet indirect seulement : la batterie ne se
|
||||
vide plus dans la voiture la nuit, elle passe plus souvent la réserve le matin.
|
||||
|
||||
## 4. Ce qui est publié
|
||||
|
||||
- **Journal** : `[Arbitre] Batterie → Décharge de la batterie bloquée : la voiture charge en
|
||||
heures creuses (1380 W, jusqu'à 06:00)`, à chaque cycle où la question se pose ; `[Batterie] …
|
||||
décharge BLOQUÉE` et `… RENDUE à l'automatisme` aux transitions (`qCInfo`), le rafraîchissement
|
||||
en `qCDebug`, un refus d'écriture en `qCWarning` (règle 7-d).
|
||||
- **Télémétrie** (`GetLoadTelemetry` et `LoadTelemetryChanged`, même charge utile) : un bloc
|
||||
`storage`, **absent** sans heure creuse ou sans batterie — `dischargeBlocked` (ce que le moteur
|
||||
TIENT après le dispatch), `decision` `{code, params}`, et `batteries[]` avec ce qui est LU
|
||||
(`observed.enableDischarging`, `observed.dischargingRate`). Une transition du bloc notifie.
|
||||
- **Motifs** : `EV_WAITING_OFF_PEAK`, `STORAGE_DISCHARGE_BLOCKED`, `STORAGE_AUTOMATIC`
|
||||
(`peak` | `evNotCharging` | `degraded`), `STORAGE_NOT_PROTECTED`. Aucun n'est émissible par
|
||||
un optimiseur.
|
||||
- **Aucun flux sortant nouveau** (invariant 10) : le garde parle au ThingManager, comme tous les
|
||||
adaptateurs.
|
||||
|
||||
## 5. Jamais
|
||||
|
||||
`gridCharging`, `enableCharging`, `chargingRate` ne sont jamais écrits, ni un `dischargingRate`
|
||||
négatif (charge forcée). La recharge de la batterie sur le réseau est l'offre Pro. Le test de la
|
||||
journée le vérifie sur toutes les écritures exécutées, et la contre-épreuve qui écrit
|
||||
`gridCharging` le fait rougir.
|
||||
|
||||
## 6. Preuves
|
||||
|
||||
| Preuve | Ce qu'elle rejoue |
|
||||
|---|---|
|
||||
| `testOffPeakIsTheCheapestZone` (loadmodel) | la règle ; aucun / unique / prix égaux ; jours de 23 et 25 h |
|
||||
| `testOffPeakDemoDay` | 12 h, attente à 18 h, refus d'`EV_GRID_START`, reprise à 22:00, blocage à 22:01, minuteur tenu 88 cycles, levée à la fin de charge, aucune écriture interdite |
|
||||
| `testOffPeakEndsAtSixAndOnDstDays` | arrêt et levée à 06:00, jours de 23, 24 et 25 h |
|
||||
| `testWithoutOffPeakTheEngineIsEtm74` | trois formes sans heure creuse : minimum à 18 h, ni bloc ni écriture, trames identiques |
|
||||
| `testABatteryWithoutControlIsReadAsBefore` | sans états, sans minuteur, absente |
|
||||
| `testBlockedDischargeShowsAtTheMeterAndL4Decides` | invariant 8, soutirage mesuré, L4 coupe, levée |
|
||||
| `testAMeterSilenceHandsTheBatteryBack` | L2 lève explicitement |
|
||||
| `decisions` | IDENTIQUE à la référence sans tarif |
|
||||
|
||||
Les écritures sont lues **à la frontière nymea** (`ThingManager::actionExecuted`), et le GEN24 est
|
||||
modélisé dans le test (`limiteTenue()`), jamais dans le moteur ni dans le mock.
|
||||
|
||||
## 7. Ce que ce lot ne fait pas
|
||||
|
||||
- La recharge de la batterie sur le réseau ; toute optimisation par le prix (offre Pro).
|
||||
- L'étalement d'une échéance sur les heures creuses (§2).
|
||||
- Une action atomique « limite de décharge » dans le plugin (`planBatteryMode(NO_DISCHARGE)`
|
||||
existe et n'est pas exposée), et un état au nom moins trompeur que `enableDischarging` — à
|
||||
proposer au dépôt du plugin.
|
||||
- La batterie comme charge rangée du waterfall (lot 3f, `spec_loadmodel.md` §14).
|
||||
@ -1679,3 +1679,9 @@ jours de 23 et 25 h (oracles Python `zoneinfo` dans les tests).
|
||||
**Pour e1 (plus tard, sans être lu maintenant)** : `TariffConfig::zoneAt(instant, fuseau)` rend la
|
||||
zone en vigueur ; « HC » n'a pas de code — le libellé est une donnée de l'installateur. Le lot e1
|
||||
devra décider d'une règle (par exemple : la ou les zones au prix le plus bas), pas la deviner ici.
|
||||
|
||||
> **FAIT (lot e1, 2026-10-24)** — la règle retenue est celle-là : les heures creuses sont la ou
|
||||
> les zones au prix le plus bas d'un tarif `tou` dont les prix diffèrent
|
||||
> (`TariffConfig::zonesCreuses()`). Elles décident de deux choses, et le prix d'aucune :
|
||||
> la borne en mode « avec minimum » ou « avec échéance » et la décharge de la batterie. Design,
|
||||
> preuves et limites : `docs/DESIGN_HC_BATTERIE.md`.
|
||||
|
||||
@ -28,6 +28,7 @@ rien sur les cas qu'il ne sait pas produire.
|
||||
| `powerSwitch` | ✅ | ❌ | — |
|
||||
| `etmVariableLoad` | ✅ *(`currentPowerW`)* | ❌ | — |
|
||||
| `energyStorage` | ✅ | ❌ | — |
|
||||
| `controllableStorage` *(lot e1, 2026-10-24)* | ✅ | ❌ | — |
|
||||
| `car`, `notification` | ❌ | ❌ | — |
|
||||
|
||||
**Ce que la table donne, et c'est la bonne nouvelle** : `sessionEnergy` et `totalEnergyConsumed`
|
||||
@ -228,3 +229,20 @@ qui ne mesure qu'une charge.
|
||||
site, il ne l'a pas — `snow` n'est éprouvé qu'en unitaire), et un plan **sans** les paramètres v2
|
||||
(la classe les porte toujours — le cas « openmeteo d'avant le brief 2 » n'est éprouvé qu'en
|
||||
unitaire, par `lirePlan()`).
|
||||
|
||||
## 10. Batterie pilotable — `controllableStorage` (lot e1, 2026-10-24)
|
||||
|
||||
| Classe | Porte | Ce qu'elle ouvre |
|
||||
|---|---|---|
|
||||
| `controllableStorage` | interface `energystorage` ; états MODIFIABLES `enableDischarging`, `dischargingRate`, `enableCharging`, `chargingRate`, `gridCharging` (les noms du `sunspecStorage` du plugin SunSpec, modèle 124) ; paramètre `revertTime` (minuteur de retour, 300 s par défaut, 0 = aucun) | la commande de la décharge en heures creuses, ses deux refus (`noRevertTimer` avec `revertTime = 0` ; `noDischargeControl` avec `energyStorage`, qui n'a pas ces états) |
|
||||
|
||||
**Ce que le mock ne fait PAS, à dessein** : il n'émule pas l'onduleur. Il range ce qu'on écrit,
|
||||
et c'est tout — le minuteur de retour n'expire jamais de lui-même. Le modèle de l'onduleur (« la
|
||||
limite tient tant que la dernière écriture a moins de `revertTime` ») vit dans le TEST
|
||||
(`limiteTenue()`), qui lit les écritures à la frontière nymea (`ThingManager::actionExecuted`) et
|
||||
non dans la mémoire du garde : un modèle logé dans le mock ou dans le moteur se donnerait raison.
|
||||
|
||||
**Ce qui reste introuvable ici** : une écriture ACCEPTÉE puis IGNORÉE par l'onduleur (le plugin
|
||||
la relit et publie `controlHealthy = false`, AC-13 du plugin), et le retour SPONTANÉ de l'onduleur
|
||||
à l'automatisme à l'échéance du minuteur. Le premier se lit dans `storage.batteries[].observed` ;
|
||||
le second n'est éprouvé que par le modèle du test.
|
||||
|
||||
@ -62,7 +62,7 @@ repli **conservatrice** : le repli n'INITIE rien, il borne ce qui tourne déjà.
|
||||
| EV débranché | Aucune action |
|
||||
| ECS | Relais coupé (palier 0, `force=true`) |
|
||||
| SG-Ready PAC | État **2** (normal — mains off, la PAC chauffe selon son thermostat). JAMAIS état 1 (blocage) : bloquer une PAC sous compteur muet = maison qui ne chauffe plus sans raison visible. |
|
||||
| Batterie | Aucune charge réseau (surplus uniquement, plafonné à 0 si compteur muet) |
|
||||
| Batterie | Rendue à son **automatisme** : une limite de décharge posée en heures creuses (lot e1) est **levée explicitement** à la transition (`enableDischarging = false`, puis `dischargingRate` au maximum). Le moteur ne commande jamais de charge réseau, il n'y a donc rien d'autre à replier. Si la levée échoue, le minuteur de retour de l'onduleur (`revertTime`) la fait tomber seul : c'est pour cela qu'une batterie sans minuteur n'est jamais commandée. |
|
||||
|
||||
« Maintenu » ≠ « démarré » : le mode dégradé ne force jamais l'activation d'une charge.
|
||||
La garantie *"jamais 0 A si le VE est branché"* appartient au **failsafe L1 de la borne**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user