// SPDX-License-Identifier: GPL-3.0-or-later // Copyright (C) 2025 - 2026, Patrick Schurig / ETM PowerSync #pragma once #include #include "ischeduler.h" class EvCharger; class ChargingAction; class EnergyArbitrator; /*! * \brief Planificateur réglementaire basé sur les règles GPL (EV surplus + aWATTar). * * En phase 3b, wraps la logique de SmartChargingManager (planSurplusCharging + * planSpotMarketCharging) et l'expose via IScheduler en annotant chaque action * d'un \c reason en français. * * \invariant getPlan() retourne IMMÉDIATEMENT (AGENTS invariant 5). * \invariant getPlan() retourne toujours un Plan valide (isValid() == true). * \invariant Toute LoadAction a un \c reason non vide, en français. * \invariant Priorité : Deadline VE > Surplus PV > aWATTar > Min courant > Idle. * Identique à adjustEvChargers() amont (iso-fonctionnel 3b). */ class RuleBasedScheduler : public QObject, public IScheduler { Q_OBJECT public: /*! * \brief Constructeur. * \param arbitrator Arbitre propriétaire — fournit l'accès à la planification et à l'état. * \param parent Propriétaire Qt. */ explicit RuleBasedScheduler(EnergyArbitrator *arbitrator, QObject *parent = nullptr); /*! * \brief Calcule le plan d'action pour le slot courant. * * Appelle les méthodes de planification héritées (surplus + spot market) puis * traduit les ChargingActions résultantes en LoadActions annotées d'un \c reason. * * \param ctx SurplusContext courant. En 3b : seul \c ctx.timestamp est utilisé. * \return Plan avec un Slot couvrant les 60 secondes à venir depuis ctx.timestamp. */ Plan getPlan(const SurplusContext &ctx) override; private: /*! * \brief Construit un LoadAction pour le cas "délai requis" (TimeRequirement). * \param ev EvCharger concerné. * \param ca ChargingAction planifiée (courant et phases déjà calculés par planSurplusCharging). * \return LoadAction avec funding=Grid et reason "Deadline VE". */ LoadAction buildTimeRequirementAction(EvCharger *ev, const ChargingAction &ca) const; /*! * \brief Construit un LoadAction "courant minimum" pour les modes EcoMin. * \param ev EvCharger concerné. * \return LoadAction avec funding=Surplus, chargingEnabled=true, currentA=min. */ LoadAction buildMinCurrentAction(EvCharger *ev) const; /*! * \brief Construit un LoadAction "idle" (recharge désactivée, aucun surplus). * \param ev EvCharger concerné. * \return LoadAction avec chargingEnabled=false et reason appropriée. */ LoadAction buildIdleAction(EvCharger *ev) const; EnergyArbitrator *m_arbitrator; };