// 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 SMARTCHARGINGMANAGER_H
#define SMARTCHARGINGMANAGER_H
#include
#include
#include "energymanagerconfiguration.h"
#include "types/charginginfo.h"
#include "types/chargingaction.h"
#include "types/chargingschedule.h"
#include "types/chargingprocessinfo.h"
#include "spotmarket/spotmarketmanager.h"
// from libnymea
#include
#include
// from libnymea-energy
#include
class EvCharger;
class RootMeter;
// Minimum charging current (A) applied when EcoWithMinCurrent is active and no surplus is available
static constexpr uint EcoMinChargingCurrent = 6;
class SmartChargingManager : public QObject
{
Q_OBJECT
public:
explicit SmartChargingManager(EnergyManager *energyManager, ThingManager *thingManager, SpotMarketManager *spotMarketManager, EnergyManagerConfiguration *configuration, QObject *parent = nullptr);
uint phasePowerLimit() const;
void setPhasePowerLimit(uint phasePowerLimit);
double acquisitionTolerance() const;
void setAcquisitionTolerance(double acquisitionTolerance);
double batteryLevelConsideration() const;
void setBatteryLevelConsideration(double batteryLevelConsideration);
bool lockOnUnplug() const;
void setLockOnUnplug(bool lockOnUnplug);
ChargingInfos chargingInfos() const;
ChargingInfo chargingInfo(const ThingId &evChargerId) const;
EnergyManager::EnergyError setChargingInfo(const ChargingInfo &chargingInfo);
ChargingSchedules chargingSchedules() const;
// [ETM] Mode dégradé L2 (watchdog fraîcheur compteur). Base = false ;
// overridé dans EnergyArbitrator. Exposé pour la notification JSON-RPC.
virtual bool degradedMode() const { return false; }
SpotMarketManager *spotMarketManager() const;
#ifdef ENERGY_SIMULATION
void simulationCallUpdate(const QDateTime &dateTime);
void simulationCallUpdateManualSoCsWithMeter(EnergyLogs::SampleRate sampleRate, const ThingPowerLogEntry &entry);
#endif
signals:
void phasePowerLimitChanged(int phasePowerLimit);
void acquisitionToleranceChanged(double acquisitionTolerance);
void batteryLevelConsiderationChanged(double batteryLevelConsideration);
void lockOnUnplugChanged(bool lockOnUnplug);
void chargingInfoAdded(const ChargingInfo &chargingInfo);
void chargingInfoRemoved(const ThingId &evChargerThingId);
void chargingInfoChanged(const ChargingInfo &chargingInfo);
void chargingSchedulesChanged();
#ifdef ENERGY_SIMULATION
void chargingUpdated();
#endif
// [ETM] BEGIN — SmartChargingManager protected API for EnergyArbitrator (etm/).
// All changes below are visibility-only (private → protected / virtual added).
// Zero logic change. Revert by deleting this block and restoring private slots.
protected slots:
virtual void update(const QDateTime ¤tDateTime); // [ETM] virtual added
void prepareInformation(const QDateTime ¤tDateTime); // [ETM] private → protected
void planSpotMarketCharging(const QDateTime ¤tDateTime); // [ETM] private → protected
void planSurplusCharging(const QDateTime ¤tDateTime); // [ETM] private → protected
void adjustEvChargers(const QDateTime ¤tDateTime); // [ETM] private → protected
void updateManualSoCsWithoutMeter(const QDateTime ¤tDateTime); // [ETM] private → protected
void verifyOverloadProtection(const QDateTime ¤tDateTime); // [ETM] private → protected
void verifyOverloadProtectionRecovery(const QDateTime ¤tDateTime); // [ETM] private → protected
protected:
void executeChargingAction(EvCharger *evCharger, const ChargingAction &chargingAction, const QDateTime ¤tDateTime); // [ETM] private → protected
// [ETM] Read-only state accessors — inline, no copies, no logic.
const QHash &internalEvChargers() const { return m_evChargers; } // [ETM] new
const QHash &internalChargingActions() const { return m_chargingActions; } // [ETM] new
RootMeter *internalRootMeter() const { return m_rootMeter; } // [ETM] new
// [ETM] END
private slots:
void updateManualSoCsWithMeter(EnergyLogs::SampleRate sampleRate, const ThingPowerLogEntry &entry);
void onThingAdded(Thing *thing);
void onThingRemoved(const ThingId &thingId);
void onActionExecuted(const Action &action, Thing::ThingError status);
void onChargingModeChanged(const ThingId &evChargerId, const ChargingInfo &chargingInfo);
private:
void setupRootMeter(Thing *thing);
void setupEvCharger(Thing *thing);
void setupPluggedInHandlers(const Thing *thing);
void storeChargingInfo(const ChargingInfo &chargingInfo);
void storeManualChargingParameters(const ThingId &evChargerId, bool enabled, int maxChargingCurrent, uint desiredPhaseCount);
bool manualChargingEnabled(const ThingId &evChargerId) const;
uint manualMaxChargingCurrent(const ThingId &evChargerId) const;
uint manualDesiredPhaseCount(const ThingId &evChargerId) const;
Electricity::Phases getAscendingPhasesForCount(uint phaseCount);
uint getBestPhaseCount(EvCharger *evCharger, double surplusAmpere);
QString chargerPhaseKey(EvCharger *evCharger) const;
EnergyManager *m_energyManager = nullptr;
ThingManager *m_thingManager = nullptr;
SpotMarketManager *m_spotMarketManager = nullptr;
EnergyManagerConfiguration *m_configuration = nullptr;
QHash m_chargingSchedules;
QHash m_processInfos;
QHash m_chargingActions;
QDateTime m_lastSpotMarketPlanning;
// Overload protection
QHash m_overloadProtectionActive;
uint m_phasePowerConsumptionLimit = 25;
double m_acquisitionTolerance = 0.5;
double m_batteryLevelConsideration = 0.9;
QHash m_chargingInfos;
RootMeter *m_rootMeter = nullptr;
QHash m_evChargers;
};
#endif // SMARTCHARGINGMANAGER_H