// 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 . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "batteryadapter.h" #include "types/action.h" #include "integrations/thingmanager.h" #include "integrations/thingactioninfo.h" #include Q_DECLARE_LOGGING_CATEGORY(dcNymeaEnergy) BatteryAdapter::BatteryAdapter(ThingManager *thingManager, const ThingId &thingId, double capacityKwh, double maxChargeW, double maxDischargeW, QObject *parent) : ILoadAdapter(parent), m_thingManager(thingManager), m_capacityKwh(capacityKwh), m_maxChargeW(maxChargeW), m_maxDischargeW(maxDischargeW) { m_thing = thingManager->findConfiguredThing(thingId); if (!m_thing) qCWarning(dcNymeaEnergy()) << "BatteryAdapter: thing not found:" << thingId; } QString BatteryAdapter::adapterId() const { return QStringLiteral("battery"); } LoadRole BatteryAdapter::role() const { return LoadRole::Battery; } ThingId BatteryAdapter::thingId() const { return m_thing ? m_thing->id() : ThingId(); } void BatteryAdapter::applyPower(double targetPowerW) { if (!m_thing) { qCWarning(dcNymeaEnergy()) << "BatteryAdapter::applyPower: no thing"; emit powerApplied(0, false); return; } QString actionName; double powerArg = 0; if (targetPowerW > 0) { actionName = QStringLiteral("setChargingPower"); powerArg = qMin(targetPowerW, m_maxChargeW); } else if (targetPowerW < 0) { actionName = QStringLiteral("setDischargingPower"); powerArg = qMin(-targetPowerW, m_maxDischargeW); } else { actionName = QStringLiteral("setStandby"); } ActionType actionType; foreach (const ActionType &at, m_thing->thingClass().actionTypes()) { if (at.name() == actionName) { actionType = at; break; } } if (actionType.id().isNull()) { qCWarning(dcNymeaEnergy()) << "BatteryAdapter: action" << actionName << "not found on" << m_thing->name(); emit powerApplied(0, false); return; } Action action(actionType.id(), m_thing->id(), Action::TriggeredByRule); // For setStandby there are no params; for charge/discharge add the power param if (targetPowerW != 0) { ParamTypeId powerParamId; foreach (const ParamType &pt, actionType.paramTypes()) { if (pt.name() == QLatin1String("power")) { powerParamId = pt.id(); break; } } if (!powerParamId.isNull()) action.setParams(ParamList() << Param(powerParamId, powerArg)); } ThingActionInfo *info = m_thingManager->executeAction(action); connect(info, &ThingActionInfo::finished, this, [this, targetPowerW, info]() { bool ok = (info->status() == Thing::ThingErrorNoError); emit powerApplied(targetPowerW, ok); if (!ok) qCWarning(dcNymeaEnergy()) << "BatteryAdapter: action failed on" << m_thing->name(); }); } void BatteryAdapter::testConnection() { if (!m_thing) { emit testResult(false, QStringLiteral("Thing not found")); return; } // Try reading batteryLevel or currentPower state foreach (const StateType &st, m_thing->thingClass().stateTypes()) { if (st.name() == QLatin1String("batteryLevel") || st.name() == QLatin1String("currentPower")) { emit testResult(true, QStringLiteral("Battery state readable: %1 = %2") .arg(st.name()) .arg(m_thing->stateValue(st.id()).toDouble())); return; } } emit testResult(true, QStringLiteral("Battery reachable")); } double BatteryAdapter::currentPowerW() const { if (!m_thing) return 0; foreach (const StateType &st, m_thing->thingClass().stateTypes()) { if (st.name() == QLatin1String("currentPower")) return m_thing->stateValue(st.id()).toDouble(); } return 0; } bool BatteryAdapter::isReachable() const { if (!m_thing) return false; foreach (const StateType &st, m_thing->thingClass().stateTypes()) { if (st.name() == QLatin1String("connected")) return m_thing->stateValue(st.id()).toBool(); } return true; }