// 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 RULEBASEDSTRATEGY_H #define RULEBASEDSTRATEGY_H #include "ischedulingstrategy.h" // Default deterministic scheduling strategy using three ordered passes. // // Pass 1 — Critical/inflexible loads // Reserve their power in every slot regardless of price or solar. // // Pass 2 — Storage loads (battery, DHW tank) // For each slot: charge if (solarForecastW - baseConsumptionW) > solarSurplusThresholdW // OR if electricityPrice < chargePriceThreshold. // Respects SOC/temperature max via targetValue. // // Pass 3 — Shiftable loads (EV, washing machine) // Sort slots by composite score (price ASC, solar DESC). // Assign the load to the N best slots before its deadline. // Each assigned slot gets a human-readable decisionReason. class RuleBasedStrategy : public ISchedulingStrategy { Q_OBJECT public: explicit RuleBasedStrategy(QObject *parent = nullptr); QString strategyId() const override; QString displayName() const override; QString description() const override; QList computeSchedule( const QList &forecast, const QList &loads, const SchedulerConfig &config ) override; QString explainDecision( const EnergyTimeSlot &slot, const FlexibleLoad &load ) const override; private: // Pass 1: reserve inflexible loads void passInflexibleLoads(QList &timeline, const QList &loads); // Pass 2: schedule storage loads (battery + DHW) void passStorageLoads(QList &timeline, const QList &loads, const SchedulerConfig &config); // Pass 3: schedule shiftable loads (EV, washing machine) void passShiftableLoads(QList &timeline, const QList &loads, const SchedulerConfig &config); // Compute derived results (netGridPower, cost, self-sufficiency) for a slot void computeSlotResults(EnergyTimeSlot &slot) const; // Ensure every active slot has a non-empty decisionReason void fillMissingReasons(QList &timeline) const; // Slot priority score: lower = better for scheduling (cheap + solar-rich) double slotScore(const EnergyTimeSlot &slot, const SchedulerConfig &config) const; }; #endif // RULEBASEDSTRATEGY_H