Patrick Schurig d9372c14ba Heures creuses : la borne attend les HC, la batterie ne se décharge pas dans la voiture (lot e1)
Décisions de Patrick du 2026-10-24. Sans heure creuse dans le tarif saisi
(aucun tarif, tarif unique, prix tous égaux), rien de ceci ne s'exécute.

LA BORNE — modes « Éco avec minimum », « Éco min + échéance », « Éco avec
échéance » (EvAdapter déclare needs.offPeakShift ; le scheduler décide) :
- hors heures creuses : surplus seulement. Le minimum réseau est retiré,
  EV_GRID_START aussi (le minimum par une autre porte). Motif
  EV_WAITING_OFF_PEAK {at "22:00", startsAt, budgetW}, rendu « … attend les
  heures creuses (22:00) ». Le plafond de soutirage et le refus gardent la tête.
- en heures creuses : le plancher de la borne est servi au réseau (passe éco,
  bornée par l'autorisation de soutirage). L'échéance reste au proxy, inchangée.
- Eco et Normal ne sont pas touchés.

LA BATTERIE — StorageDischargeGuard exécute, le rule-based décide (y compris en
ombre d'un optimiseur) :
- heure creuse ET bornes qui TIRENT ≥ 230 W (mesuré) ET batterie pilotable :
  dischargingRate = 0 PUIS enableDischarging = true (StorCtl_Mod bit DiSCHARGE
  = limite active, OutWRte = 0 : la séquence NO_DISCHARGE du plugin) ;
  rafraîchi au tiers du minuteur de retour (revertTime) ;
- sinon : levée EXPLICITE, enableDischarging = false puis dischargingRate au
  maximum. L2 lève aussi. Une limite à 0 % trouvée active au démarrage est
  reprise (rafraîchie ou levée).
- jamais gridCharging, enableCharging, chargingRate, ni un taux négatif.
- générique : interface energystorage et états présents. Sans les états
  (noDischargeControl), sans minuteur (noRevertTimer) ou minuteur < 120 s
  (revertTimerTooShort) : non commandée, STORAGE_NOT_PROTECTED.
- publié : bloc `storage` de la télémétrie (dischargeBlocked, decision,
  batteries[] avec ce qui est LU), absent sans heure creuse ou sans batterie ;
  ligne « [Arbitre] Batterie → … » au journal.

Le blocage ne verse rien au budget : surplus = compteur + PV (invariant 8),
le soutirage ajouté se mesure au cycle suivant, L4 garde le dernier mot.

Mock : classe controllableStorage (états modifiables du sunspecStorage,
paramètre revertTime). Tests : journée de la démo, 06:00 sur jours de 24/23/25 h,
etm74 sans heure creuse, batteries non pilotables ou absente, soutirage et L4,
repli L2 — les écritures lues à la frontière nymea (actionExecuted), l'onduleur
modélisé hors du moteur. Le commentaire du test §11 est réécrit comme il le
demandait.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 08:34:21 +02:00

70 lines
2.7 KiB
Plaintext

HEADERS += \
$$PWD/types/loadaction.h \
$$PWD/types/decisionreason.h \
$$PWD/types/loaddescriptor.h \
$$PWD/types/surpluscontext.h \
$$PWD/types/plan.h \
$$PWD/types/drawcap.h \
$$PWD/types/ecoprogress.h \
$$PWD/types/ecotarget.h \
$$PWD/types/loadconfig.h \
$$PWD/tariff/tariffconfig.h \
$$PWD/config/loadconfigstore.h \
$$PWD/adapters/iloadadapter.h \
$$PWD/scheduler/ischeduler.h \
$$PWD/adapters/evadapter.h \
$$PWD/adapters/sgreadyadapter.h \
$$PWD/adapters/etmvariableloadadapter.h \
$$PWD/adapters/relayrouter.h \
$$PWD/adapters/storagedischargeguard.h \
$$PWD/scheduler/rulebasedscheduler.h \
$$PWD/scheduler/optimizerprotocol.h \
$$PWD/scheduler/optimizerclient.h \
$$PWD/scheduler/optimizersecret.h \
$$PWD/scheduler/optimizerplan.h \
$$PWD/scheduler/socketscheduler.h \
$$PWD/scheduler/optimizerstatus.h \
$$PWD/scheduler/optimizertrace.h \
$$PWD/scheduler/publishedplan.h \
$$PWD/ratios/energyratioscalculator.h \
$$PWD/energyarbitrator.h \
$$PWD/spotmarketbuild.h \
SOURCES += \
$$PWD/types/decisionreason.cpp \
$$PWD/types/drawcap.cpp \
$$PWD/types/ecotarget.cpp \
$$PWD/types/loadconfig.cpp \
$$PWD/tariff/tariffconfig.cpp \
$$PWD/config/loadconfigstore.cpp \
$$PWD/ratios/energyratioscalculator.cpp \
$$PWD/adapters/evadapter.cpp \
$$PWD/adapters/sgreadyadapter.cpp \
$$PWD/adapters/etmvariableloadadapter.cpp \
$$PWD/adapters/relayrouter.cpp \
$$PWD/adapters/storagedischargeguard.cpp \
$$PWD/scheduler/rulebasedscheduler.cpp \
$$PWD/scheduler/optimizerprotocol.cpp \
$$PWD/scheduler/optimizerclient.cpp \
$$PWD/scheduler/optimizersecret.cpp \
$$PWD/scheduler/optimizerplan.cpp \
$$PWD/scheduler/socketscheduler.cpp \
$$PWD/scheduler/optimizerstatus.cpp \
$$PWD/scheduler/optimizertrace.cpp \
$$PWD/scheduler/publishedplan.cpp \
$$PWD/energyarbitrator.cpp \
$$PWD/spotmarketbuild.cpp \
# Le contrat OpenRPC du protocole optimiseur (docs/), embarqué : NymeaEnergy.GetOptimizerProtocol.
RESOURCES += $$PWD/scheduler/etm-powersync-optimizer-protocol.qrc
# Version du moteur annoncée au handshake de l'optimiseur (OPTIMIZER_PROTOCOL §3, `engine`) : lue
# dans le changelog Debian, seule source de la version livrée — une constante dans le code
# dériverait au premier `+etmN`.
ETM_CHANGELOG = $$cat($$PWD/../../debian/changelog, lines)
ETM_LIGNE_VERSION = $$first(ETM_CHANGELOG)
ETM_VERSION_MOTEUR = $$section(ETM_LIGNE_VERSION, "(", 1, 1)
ETM_VERSION_MOTEUR = $$section(ETM_VERSION_MOTEUR, ")", 0, 0)
isEmpty(ETM_VERSION_MOTEUR): ETM_VERSION_MOTEUR = inconnue
DEFINES += ETM_VERSION_MOTEUR=\\\"$$ETM_VERSION_MOTEUR\\\"