/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright 2013 - 2024, nymea GmbH * Contact: contact@nymea.io * * This file is part of nymea. * This project including source code and documentation is protected by * copyright law, and remains the property of nymea GmbH. All rights, including * reproduction, publication, editing and translation, are reserved. The use of * this project is subject to the terms of a license agreement to be concluded * with nymea GmbH in accordance with the terms of use of nymea GmbH, available * under https://nymea.io/license * * GNU General Public License Usage * Alternatively, this project may be redistributed and/or modified under the * terms of the GNU General Public License as published by the Free Software * Foundation, GNU version 3. This project is 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 * this project. If not, see . * * For any further details and any questions please contact us under * contact@nymea.io or see our FAQ/Licensing Information on * https://nymea.io/license/faq * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "energyjsonhandler.h" #include "energymanagerimpl.h" Q_DECLARE_LOGGING_CATEGORY(dcEnergyExperience) EnergyJsonHandler::EnergyJsonHandler(EnergyManager *energyManager, QObject *parent): JsonHandler(parent), m_energyManager(energyManager) { registerEnum(); registerEnum(); registerObject(); registerObject(); QVariantMap params, returns; QString description; params.clear(); returns.clear(); description = "Get the root meter ID. If there is no root meter set, the params will be empty."; returns.insert("o:rootMeterThingId", enumValueName(Uuid)); registerMethod("GetRootMeter", description, params, returns, Types::PermissionScopeNone); params.clear(); returns.clear(); description = "Set the root meter."; params.insert("rootMeterThingId", enumValueName(Uuid)); returns.insert("energyError", enumRef()); registerMethod("SetRootMeter", description, params, returns, Types::PermissionScopeAdmin); params.clear(); returns.clear(); description = "Get the current power balance. That is, production, consumption and acquisition."; returns.insert("currentPowerConsumption", enumValueName(Double)); returns.insert("currentPowerProduction", enumValueName(Double)); returns.insert("currentPowerAcquisition", enumValueName(Double)); returns.insert("currentPowerStorage", enumValueName(Double)); returns.insert("totalConsumption", enumValueName(Double)); returns.insert("totalProduction", enumValueName(Double)); returns.insert("totalAcquisition", enumValueName(Double)); returns.insert("totalReturn", enumValueName(Double)); registerMethod("GetPowerBalance", description, params, returns, Types::PermissionScopeNone); params.clear(); returns.clear(); description = "Get logs for the power balance. If from is not give, the log will start at the beginning of " "recording. If to is not given, the logs will and at the last sample for this sample rate before now."; params.insert("sampleRate", enumRef()); params.insert("o:from", enumValueName(Uint)); params.insert("o:to", enumValueName(Uint)); returns.insert("powerBalanceLogEntries", objectRef()); registerMethod("GetPowerBalanceLogs", description, params, returns, Types::PermissionScopeNone); params.clear(); returns.clear(); description = "Get logs for one or more things power values. If thingIds is not given, logs for all energy related " "things will be returned. If from is not given, the log will start at the beginning of recording. If " "to is not given, the logs will and at the last sample for this sample rate before now. If the parameter " "\"includeCurrent\" is set to true, the result will contain the newest log entries available, regardless " "of the sample rate (that is, 1 minute). This may be useful to calculate the difference to the newest " "entry of the fetched sample rate and the current values to display the live value until the current sample " "is completed."; params.insert("sampleRate", enumRef()); params.insert("o:thingIds", QVariantList() << enumValueName(Uuid)); params.insert("o:from", enumValueName(Uint)); params.insert("o:to", enumValueName(Uint)); params.insert("o:includeCurrent", enumValueName(Bool)); returns.insert("o:currentEntries", objectRef()); returns.insert("thingPowerLogEntries", objectRef()); registerMethod("GetThingPowerLogs", description, params, returns, Types::PermissionScopeNone); params.clear(); description = "Emitted whenever the root meter id changes. If the root meter has been unset, the params will be empty."; params.insert("o:rootMeterThingId", enumValueName(Uuid)); registerNotification("RootMeterChanged", description, params); params.clear(); description = "Emitted whenever the energy balance changes. That is, when the current consumption, production or " "acquisition changes. Typically they will all change at the same time."; params.insert("currentPowerConsumption", enumValueName(Double)); params.insert("currentPowerProduction", enumValueName(Double)); params.insert("currentPowerAcquisition", enumValueName(Double)); params.insert("currentPowerStorage", enumValueName(Double)); params.insert("totalConsumption", enumValueName(Double)); params.insert("totalProduction", enumValueName(Double)); params.insert("totalAcquisition", enumValueName(Double)); params.insert("totalReturn", enumValueName(Double)); registerNotification("PowerBalanceChanged", description, params); params.clear(); description = "Emitted whenever an entry is added to the power balance log."; params.insert("sampleRate", enumRef()); params.insert("powerBalanceLogEntry", objectRef()); registerNotification("PowerBalanceLogEntryAdded", description, params); params.clear(); description = "Emitted whenever an entry is added to the thing power log."; params.insert("sampleRate", enumRef()); params.insert("thingPowerLogEntry", objectRef()); registerNotification("ThingPowerLogEntryAdded", description, params); connect(m_energyManager, &EnergyManager::rootMeterChanged, this, [=](){ QVariantMap params; if (m_energyManager->rootMeter()) { params.insert("rootMeterThingId", m_energyManager->rootMeter()->id()); } emit RootMeterChanged(params); }); connect(m_energyManager, &EnergyManager::powerBalanceChanged, this, [=](){ QVariantMap params; params.insert("currentPowerConsumption", m_energyManager->currentPowerConsumption()); params.insert("currentPowerProduction", m_energyManager->currentPowerProduction()); params.insert("currentPowerAcquisition", m_energyManager->currentPowerAcquisition()); params.insert("currentPowerStorage", m_energyManager->currentPowerStorage()); params.insert("totalConsumption", m_energyManager->totalConsumption()); params.insert("totalProduction", m_energyManager->totalProduction()); params.insert("totalAcquisition", m_energyManager->totalAcquisition()); params.insert("totalReturn", m_energyManager->totalReturn()); emit PowerBalanceChanged(params); }); connect(m_energyManager->logs(), &EnergyLogs::powerBalanceEntryAdded, this, [=](EnergyLogs::SampleRate sampleRate, const PowerBalanceLogEntry &entry){ QVariantMap params; params.insert("sampleRate", enumValueName(sampleRate)); params.insert("powerBalanceLogEntry", pack(entry)); emit PowerBalanceLogEntryAdded(params); }); connect(m_energyManager->logs(), &EnergyLogs::thingPowerEntryAdded, this, [=](EnergyLogs::SampleRate sampleRate, const ThingPowerLogEntry &entry){ QVariantMap params; params.insert("sampleRate", enumValueName(sampleRate)); params.insert("thingPowerLogEntry", pack(entry)); emit ThingPowerLogEntryAdded(params); }); } QString EnergyJsonHandler::name() const { return "Energy"; } JsonReply *EnergyJsonHandler::GetRootMeter(const QVariantMap ¶ms) { Q_UNUSED(params) QVariantMap ret; if (m_energyManager->rootMeter()) { ret.insert("rootMeterThingId", m_energyManager->rootMeter()->id()); } return createReply(ret); } JsonReply *EnergyJsonHandler::SetRootMeter(const QVariantMap ¶ms) { QVariantMap returns; if (!params.contains("rootMeterThingId")) { returns.insert("energyError", enumValueName(EnergyManager::EnergyErrorMissingParameter)); return createReply(returns); } EnergyManager::EnergyError status = m_energyManager->setRootMeter(params.value("rootMeterThingId").toUuid()); returns.insert("energyError", enumValueName(status)); return createReply(returns); } JsonReply *EnergyJsonHandler::GetPowerBalance(const QVariantMap ¶ms) { Q_UNUSED(params) QVariantMap ret; ret.insert("currentPowerConsumption", m_energyManager->currentPowerConsumption()); ret.insert("currentPowerProduction", m_energyManager->currentPowerProduction()); ret.insert("currentPowerAcquisition", m_energyManager->currentPowerAcquisition()); ret.insert("currentPowerStorage", m_energyManager->currentPowerStorage()); ret.insert("totalConsumption", m_energyManager->totalConsumption()); ret.insert("totalProduction", m_energyManager->totalProduction()); ret.insert("totalAcquisition", m_energyManager->totalAcquisition()); ret.insert("totalReturn", m_energyManager->totalReturn()); return createReply(ret); } JsonReply *EnergyJsonHandler::GetPowerBalanceLogs(const QVariantMap ¶ms) { EnergyLogs::SampleRate sampleRate = enumNameToValue(params.value("sampleRate").toString()); QDateTime from = params.contains("from") ? QDateTime::fromMSecsSinceEpoch(params.value("from").toLongLong() * 1000) : QDateTime(); QDateTime to = params.contains("to") ? QDateTime::fromMSecsSinceEpoch(params.value("to").toLongLong() * 1000) : QDateTime(); QVariantMap returns; returns.insert("powerBalanceLogEntries", pack(m_energyManager->logs()->powerBalanceLogs(sampleRate, from, to))); return createReply(returns); } JsonReply *EnergyJsonHandler::GetThingPowerLogs(const QVariantMap ¶ms) { EnergyLogs::SampleRate sampleRate = enumNameToValue(params.value("sampleRate").toString()); QList thingIds; foreach (const QVariant &thingId, params.value("thingIds").toList()) { thingIds.append(thingId.toUuid()); } QDateTime from = params.contains("from") ? QDateTime::fromMSecsSinceEpoch(params.value("from").toLongLong() * 1000) : QDateTime(); QDateTime to = params.contains("to") ? QDateTime::fromMSecsSinceEpoch(params.value("to").toLongLong() * 1000) : QDateTime(); QVariantMap returns; returns.insert("thingPowerLogEntries", pack(m_energyManager->logs()->thingPowerLogs(sampleRate, thingIds, from, to))); if (params.contains("includeCurrent") && params.value("includeCurrent").toBool()) { returns.insert("currentEntries", pack(m_energyManager->logs()->thingPowerLogs(EnergyLogs::SampleRate1Min, thingIds, QDateTime::currentDateTime().addSecs(-60)))); } return createReply(returns); }