// SPDX-License-Identifier: GPL-3.0-or-later // Copyright (C) 2025 - 2026, Patrick Schurig / ETM PowerSync #pragma once #include #include #include "iloadadapter.h" class EvCharger; class EnergyArbitrator; /*! * \brief Adaptateur pour une borne de recharge VE (interface evcharger nymea). * * Traduit les LoadAction(Setpoint) en appels matériels via * EnergyArbitrator::doExecuteChargingAction() — le seul chemin d'exécution. * * \invariant applyAction() rejette silencieusement toute LoadAction dont \c reason est vide. * \invariant currentA est écrêté à [maxChargingCurrentMinValue, maxChargingCurrentMaxValue]. * \invariant phaseCount est écrêté selon canSetPhaseCount() et phaseCount() du EvCharger. * \invariant Les kinds autres que Setpoint sont retournés sans effet. */ class EvAdapter : public QObject, public ILoadAdapter { Q_OBJECT public: /*! * \brief Constructeur. * \param evCharger Borne VE à piloter (doit rester valide tant que l'adaptateur existe). * \param parent EnergyArbitrator propriétaire — utilisé pour l'exécution matérielle. */ explicit EvAdapter(EvCharger *evCharger, EnergyArbitrator *parent); /*! * \brief Retourne la description statique de la charge. * \return LoadDescriptor construit depuis les capacités actuelles du EvCharger. * \note Recalculé à chaque appel depuis l'état nymea du Thing. */ LoadDescriptor descriptor() const override; /*! * \brief Retourne la télémétrie runtime (puissance mesurée, disponibilité). * \return LoadTelemetry avec currentPowerW, available et lastActionAt. */ LoadTelemetry telemetry() const override; /*! * \brief Construit l'entrée loads[] §5 du SurplusContext. * \param now Temps de cycle (\c ctx.timestamp). Inutilisé ici : l'EV n'a pas de verrou * de palier (hors waterfall ECS/SG-Ready). Présent pour l'uniformité de \c ILoadAdapter. * \return LoadContext incluant declared, limits, needs et télémétrie EV. */ LoadContext toLoadContext(const QDateTime &now) const override; /*! * \brief Applique une consigne Setpoint sur la borne VE. * * **Inactif jusqu'à 3g** : non appelée par \c EnergyArbitrator::update() en beta. * Le dispatch EV passe par \c adjustEvChargers() amont (hérité). Cette méthode * sera câblée lors de la transplantation EV dans \c RuleBasedScheduler (phase 3g). * \c descriptor() et \c telemetry() sont eux actifs dès maintenant pour le SurplusContext. * * \param action LoadAction de kind Setpoint. Autres kinds : retour sans effet. * \param now Temps de cycle (\c ctx.timestamp) — passé à \c doExecuteChargingAction() * (locks anti-rebond de la borne). MÊME source que toLoadContext() (contrat ILoadAdapter). * \return L'action après écrêtage matériel (currentA, phaseCount bornés). * * \invariant action.reason non vide requis — log warning et retour sans effet sinon. * \invariant currentA écrêté à [minValue, maxValue] avant envoi à executeChargingAction. * \invariant phaseCount ajusté selon canSetPhaseCount() du EvCharger. */ LoadAction applyAction(const LoadAction &action, const QDateTime &now) override; //! \brief Sans effet : l'EV n'est pas construit depuis \c LoadConfig (rang fixé à 100, //! cf. « Dette 3g »). \param priority Ignoré. \param needs Ignoré. void updateSoftConfig(int priority, const LoadNeeds &needs) override { Q_UNUSED(priority) Q_UNUSED(needs) } //! \brief Sans effet : l'EV n'implémente pas encore l'échelle de défaut ECS-410. //! La généralisation est portée par **ECS-414** (lot de mise en configuration //! du SgReadyAdapter). Déclaré explicitement plutôt qu'hérité d'un défaut vide. void clearFault() override {} //! \brief Sans effet : l'EV n'est pas construit depuis \c LoadConfig et ne peut donc pas //! être « désactivé » par ce chemin. \param now Ignoré. void applySafeState(const QDateTime &now) override { Q_UNUSED(now) } /*! * \brief Borne VE sous-jacente (lecture). * \return Pointeur non-propriétaire vers l'EvCharger ; jamais nul (fixé à la construction). */ EvCharger *evCharger() const { return m_charger; } private: EvCharger *m_charger; EnergyArbitrator *m_parent; QDateTime m_lastActionAt; };