diff --git a/energyplugin/smartchargingmanager.cpp b/energyplugin/smartchargingmanager.cpp index 14dbdb7..c3d2665 100644 --- a/energyplugin/smartchargingmanager.cpp +++ b/energyplugin/smartchargingmanager.cpp @@ -564,10 +564,17 @@ void SmartChargingManager::prepareInformation(const QDateTime ¤tDateTime) QDateTime endDateTime = m_chargingInfos.value(evCharger->id()).nextEndTime(currentDateTime); if (!endDateTime.isValid() && m_chargingInfos.value(evCharger->id()).chargingMode() != ChargingInfo::ChargingModeNormal) { qCDebug(dcNymeaEnergy()).nospace() << "No valid target time set for " << evCharger->name(); - if (m_chargingInfos.value(evCharger->id()).chargingMode() == ChargingInfo::ChargingModeEcoWithTargetTime) { - qCDebug(dcNymeaEnergy()) << "Resetting to ECO mode without time."; + const ChargingInfo::ChargingMode currentMode = m_chargingInfos.value(evCharger->id()).chargingMode(); + ChargingInfo::ChargingMode fallbackMode; + if (currentMode == ChargingInfo::ChargingModeEcoMinWithTargetTime) { + qCDebug(dcNymeaEnergy()) << "Resetting to ECO with min current mode."; + fallbackMode = ChargingInfo::ChargingModeEcoWithMinCurrent; + } else { + if (currentMode == ChargingInfo::ChargingModeEcoWithTargetTime) + qCDebug(dcNymeaEnergy()) << "Resetting to ECO mode without time."; + fallbackMode = ChargingInfo::ChargingModeEco; } - m_chargingInfos[evCharger->id()].setChargingMode(ChargingInfo::ChargingModeEco); + m_chargingInfos[evCharger->id()].setChargingMode(fallbackMode); storeChargingInfo(m_chargingInfos.value(evCharger->id())); emit chargingInfoChanged(m_chargingInfos.value(evCharger->id())); } @@ -754,7 +761,9 @@ void SmartChargingManager::planSpotMarketCharging(const QDateTime ¤tDateTi continue; } - if (m_chargingInfos.value(evCharger->id()).chargingMode() == ChargingInfo::ChargingModeEco && m_chargingInfos.value(evCharger->id()).dailySpotMarketPercentage() == 0) { + if ((m_chargingInfos.value(evCharger->id()).chargingMode() == ChargingInfo::ChargingModeEco + || m_chargingInfos.value(evCharger->id()).chargingMode() == ChargingInfo::ChargingModeEcoWithMinCurrent) + && m_chargingInfos.value(evCharger->id()).dailySpotMarketPercentage() == 0) { qCDebug(dcNymeaEnergy()) << evCharger->name() << "has no target time set nor any daily percentage to charge with spot market. Ignoring..."; schedulesChanged |= (m_chargingSchedules[evCharger].removeAllIssuer(ChargingAction::ChargingActionIssuerSpotMarketCharging) > 0); m_processInfos[evCharger].chargingUntilTargetTimeUsingSpotmarket = false; @@ -774,15 +783,21 @@ void SmartChargingManager::planSpotMarketCharging(const QDateTime ¤tDateTi const ChargingInfo info = m_chargingInfos.value(evCharger->id()); - if (info.chargingMode() == ChargingInfo::ChargingModeEcoWithTargetTime) { + if (info.chargingMode() == ChargingInfo::ChargingModeEcoWithTargetTime + || info.chargingMode() == ChargingInfo::ChargingModeEcoMinWithTargetTime) { QDateTime endDateTime = info.nextEndTime(currentDateTime); if (!endDateTime.isValid()) { qCDebug(dcNymeaEnergy()).nospace() << "No valid target time set for " << evCharger->name(); - if (info.chargingMode() == ChargingInfo::ChargingModeEcoWithTargetTime) { + ChargingInfo::ChargingMode fallbackMode; + if (info.chargingMode() == ChargingInfo::ChargingModeEcoMinWithTargetTime) { + qCDebug(dcNymeaEnergy()) << "Resetting to ECO with min current mode."; + fallbackMode = ChargingInfo::ChargingModeEcoWithMinCurrent; + } else { qCDebug(dcNymeaEnergy()) << "Resetting to ECO mode without time."; + fallbackMode = ChargingInfo::ChargingModeEco; } - m_chargingInfos[evCharger->id()].setChargingMode(ChargingInfo::ChargingModeEco); + m_chargingInfos[evCharger->id()].setChargingMode(fallbackMode); storeChargingInfo(m_chargingInfos.value(evCharger->id())); emit chargingInfoChanged(m_chargingInfos.value(evCharger->id())); continue; @@ -1038,7 +1053,8 @@ void SmartChargingManager::planSurplusCharging(const QDateTime ¤tDateTime) qCDebug(dcNymeaEnergy()) << "**** Evaluating" << evCharger->name(); ChargingInfo info = m_chargingInfos.value(evCharger->id()); - if (info.chargingMode() != ChargingInfo::ChargingModeEcoWithTargetTime) { + if (info.chargingMode() != ChargingInfo::ChargingModeEcoWithTargetTime + && info.chargingMode() != ChargingInfo::ChargingModeEcoMinWithTargetTime) { qCDebug(dcNymeaEnergy()) << evCharger->name() << "does not use a target time."; m_chargingSchedules[evCharger].removeAllIssuer(ChargingAction::ChargingActionIssuerTimeRequirement); continue; @@ -1047,10 +1063,15 @@ void SmartChargingManager::planSurplusCharging(const QDateTime ¤tDateTime) QDateTime endDateTime = info.nextEndTime(currentDateTime); if (!endDateTime.isValid()) { qCDebug(dcNymeaEnergy()).nospace() << "No valid target time set for " << evCharger->name(); - if (info.chargingMode() == ChargingInfo::ChargingModeEcoWithTargetTime) { + ChargingInfo::ChargingMode fallbackMode; + if (info.chargingMode() == ChargingInfo::ChargingModeEcoMinWithTargetTime) { + qCDebug(dcNymeaEnergy()) << "Resetting to ECO with min current mode."; + fallbackMode = ChargingInfo::ChargingModeEcoWithMinCurrent; + } else { qCDebug(dcNymeaEnergy()) << "Resetting to ECO mode without time."; + fallbackMode = ChargingInfo::ChargingModeEco; } - m_chargingInfos[evCharger->id()].setChargingMode(ChargingInfo::ChargingModeEco); + m_chargingInfos[evCharger->id()].setChargingMode(fallbackMode); storeChargingInfo(m_chargingInfos.value(evCharger->id())); emit chargingInfoChanged(m_chargingInfos.value(evCharger->id())); continue; @@ -1345,7 +1366,26 @@ void SmartChargingManager::adjustEvChargers(const QDateTime ¤tDateTime) continue; } - // 4. Else ... idle, switch off + // 4. Min current fallback (EcoWithMinCurrent / EcoMinWithTargetTime) + { + const ChargingInfo::ChargingMode mode = m_chargingInfos.value(evCharger->thing()->id()).chargingMode(); + if (mode == ChargingInfo::ChargingModeEcoWithMinCurrent + || mode == ChargingInfo::ChargingModeEcoMinWithTargetTime) { + uint minCurrent = qMax(EcoMinChargingCurrent, evCharger->maxChargingCurrentMinValue()); + qCDebug(dcNymeaEnergy()).nospace() << "No surplus available for " << evCharger->name() + << " — applying min current " << minCurrent << " A on " << processInfo.effectivePhaseCount << " phase(s)."; + ChargingAction minAction(true, minCurrent, processInfo.effectivePhaseCount, + ChargingAction::ChargingActionIssuerSurplusCharging); + executeChargingAction(evCharger, minAction, currentDateTime); + if (m_chargingInfos[evCharger->thing()->id()].chargingState() != ChargingInfo::ChargingStateSurplusCharging) { + m_chargingInfos[evCharger->thing()->id()].setChargingState(ChargingInfo::ChargingStateSurplusCharging); + emit chargingInfoChanged(m_chargingInfos[evCharger->thing()->id()]); + } + continue; + } + } + + // 5. Else ... idle, switch off qCDebug(dcNymeaEnergy()).nospace() << "Setting " << evCharger->name() << " to power OFF. Idle state."; evCharger->setChargingEnabled(false, currentDateTime); diff --git a/energyplugin/smartchargingmanager.h b/energyplugin/smartchargingmanager.h index 1099c34..2ec115a 100644 --- a/energyplugin/smartchargingmanager.h +++ b/energyplugin/smartchargingmanager.h @@ -45,6 +45,9 @@ 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 diff --git a/energyplugin/types/charginginfo.h b/energyplugin/types/charginginfo.h index 44fcd54..9d2435d 100644 --- a/energyplugin/types/charginginfo.h +++ b/energyplugin/types/charginginfo.h @@ -48,7 +48,9 @@ public: enum ChargingMode { ChargingModeNormal = 0, // implicit default ChargingModeEco, - ChargingModeEcoWithTargetTime + ChargingModeEcoWithTargetTime, + ChargingModeEcoWithMinCurrent, // Eco + guaranteed minimum current (6 A) when no surplus + ChargingModeEcoMinWithTargetTime // Eco + minimum current + target time deadline }; Q_ENUM(ChargingMode)