powersync-energy-plugin-etm/energyplugin/schedulingstrategies/aistrategy.cpp

115 lines
3.7 KiB
C++

// 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 <https://www.gnu.org/licenses/>.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "aistrategy.h"
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(dcNymeaEnergy)
AIStrategy::AIStrategy(QObject *parent)
: ISchedulingStrategy(parent)
{
}
QString AIStrategy::strategyId() const
{
return QStringLiteral("ai-ml");
}
QString AIStrategy::displayName() const
{
return QStringLiteral("Intelligence Artificielle (ML)");
}
QString AIStrategy::description() const
{
return QStringLiteral("Stratégie basée sur un modèle ML (ONNX / HTTP). "
"Non disponible : aucun modèle chargé.");
}
bool AIStrategy::isAvailable() const
{
// Not available until a real model is wired in
return false;
}
QList<EnergyTimeSlot> AIStrategy::computeSchedule(
const QList<EnergyTimeSlot> &forecast,
const QList<FlexibleLoad> &loads,
const SchedulerConfig &config)
{
Q_UNUSED(loads)
Q_UNUSED(config)
qCWarning(dcNymeaEnergy()) << "AIStrategy::computeSchedule called but no AI model is loaded."
<< "Returning empty schedule. Use RuleBasedStrategy as fallback.";
// Return the forecast unchanged with a clear reason on every slot
QList<EnergyTimeSlot> result = forecast;
const QString fallbackReason = QStringLiteral(
"Modèle IA non chargé — basculement vers RuleBasedStrategy recommandé");
for (int i = 0; i < result.size(); ++i) {
EnergyTimeSlot &slot = result[i];
// Reset all allocations to zero
slot.allocatedToEV = 0;
slot.allocatedToHP = 0;
slot.allocatedToDHW = 0;
slot.allocatedToBattery = 0;
slot.allocatedToFeedIn = 0;
slot.decisionReason = fallbackReason;
slot.decisionRules = QStringList() << QStringLiteral("AIModelNotLoaded");
slot.netGridPowerW = slot.baseConsumptionW - slot.solarForecastW;
slot.estimatedCostEUR = 0;
slot.selfSufficiencyPct = 0;
}
emit strategyUnavailable(QStringLiteral("AI model not loaded — falling back to RuleBasedStrategy"));
return result;
}
QString AIStrategy::explainDecision(
const EnergyTimeSlot &slot,
const FlexibleLoad &load) const
{
Q_UNUSED(slot)
Q_UNUSED(load)
return QStringLiteral("Modèle IA non chargé — aucune décision prise");
}
void AIStrategy::setModelPath(const QString &path)
{
m_modelPath = path;
qCDebug(dcNymeaEnergy()) << "AIStrategy: model path set to" << path
<< "(loading not yet implemented)";
}
void AIStrategy::setRemoteEndpoint(const QString &url, const QString &apiKey)
{
m_remoteEndpoint = url;
m_apiKey = apiKey;
qCDebug(dcNymeaEnergy()) << "AIStrategy: remote endpoint set to" << url
<< "(not yet implemented)";
}