// SPDX-License-Identifier: GPL-3.0-or-later /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 2013 - 2024, nymea GmbH * Copyright (C) 2024 - 2025, chargebyte austria GmbH * * This file is part of nymea-energy-plugin-nymea. * * nymea-energy-plugin-nymea.s free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * nymea-energy-plugin-nymea.s distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with nymea-energy-plugin-nymea. If not, see . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef SCHEDULERMANAGER_H #define SCHEDULERMANAGER_H #include #include #include #include #include "types/energytimeslot.h" #include "types/flexibleload.h" #include "types/schedulerconfig.h" #include "types/manualslotconfig.h" #include "schedulingstrategies/ischedulingstrategy.h" // from libnymea-energy #include // from libnymea #include class SpotMarketManager; class LoadAdapterRegistry; // SchedulerManager orchestrates the full energy scheduling pipeline. // // Every recomputeIntervalMin (default 15 min) it: // 1. Builds a forecast timeline from available data providers (stub: returns 0s). // 2. Discovers all FlexibleLoad instances from known managers. // 3. Calls strategy->computeSchedule(forecast, loads, config). // 4. Applies the CURRENT slot's decisions to the relevant managers. // 5. Stores future slots for later execution at their start time. // // Manual overrides (from UI or JSON-RPC) are respected: overridden slots are // never touched by the Scheduler until the override expires. class SchedulerManager : public QObject { Q_OBJECT public: explicit SchedulerManager( SpotMarketManager *spotMarketManager, EnergyManager *energyManager, ThingManager *thingManager, LoadAdapterRegistry *adapterRegistry = nullptr, QObject *parent = nullptr ); // --- Strategy management --- void setStrategy(ISchedulingStrategy *strategy); ISchedulingStrategy *currentStrategy() const; QList availableStrategies() const; void registerStrategy(ISchedulingStrategy *strategy); // --- Timeline access --- QList currentTimeline() const; QDateTime lastComputedAt() const; QDateTime nextRecomputeAt() const; // planHealth: "ok" | "degraded" | "no_forecast" QString planHealth() const; // --- Configuration --- SchedulerConfig config() const; void setConfig(const SchedulerConfig &config); // --- Flexible loads --- QList flexibleLoads() const; void updateLoad(const FlexibleLoad &load); // --- Manual override --- // Marks a slot as manually overridden. The Scheduler will not touch it. void overrideSlot(const QDateTime &slotStart, LoadSource source, double powerW, const QString &reason); // --- Active overrides count --- int activeOverridesCount() const; // --- Force immediate recompute --- void forceRecompute(); // --- Manual slot management (ManualStrategy) --- QList manualSlots() const; void setManualSlot(const ManualSlotConfig &config); void removeManualSlot(const QDateTime &start); void clearManualSlots(); signals: void timelineUpdated(const QList &timeline); void slotExecuted(const EnergyTimeSlot &slot, bool success); void strategyChanged(const QString &strategyId); void loadRegistered(const FlexibleLoad &load); void loadUpdated(const FlexibleLoad &load); void configChanged(const SchedulerConfig &config); void manualSlotsChanged(); private slots: void onRecomputeTimer(); void onSlotExecutionTimer(); private: // Build 24–48h forecast (stub: all predictions = 0) QList buildForecast() const; // Collect all managed flexible loads from connected managers QList collectLoads() const; // Apply the current slot's decisions to the hardware managers void applyCurrentSlot(const EnergyTimeSlot &slot); // Schedule next slot execution timer void scheduleNextSlotTimer(); // Helper: return the registered ManualStrategy, or nullptr if not found class ManualStrategy *findManualStrategy() const; SpotMarketManager *m_spotMarketManager = nullptr; EnergyManager *m_energyManager = nullptr; ThingManager *m_thingManager = nullptr; LoadAdapterRegistry *m_adapterRegistry = nullptr; class SchedulerSettings *m_settings = nullptr; ISchedulingStrategy *m_activeStrategy = nullptr; QList m_strategies; QList m_timeline; QList m_loads; SchedulerConfig m_config; QDateTime m_lastComputedAt; QDateTime m_nextRecomputeAt; QTimer m_recomputeTimer; // fires every recomputeIntervalMin QTimer m_slotTimer; // fires at the start of the next future slot }; #endif // SCHEDULERMANAGER_H