From c7edc3ccf83e30d316bbb1ac59fb311b5adc3df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Wed, 2 Mar 2022 09:40:06 +0100 Subject: [PATCH] Fix battery power and user total pv power for the inverter --- fronius/integrationpluginfronius.cpp | 106 ++++++++++++++++----------- fronius/integrationpluginfronius.h | 1 + 2 files changed, 65 insertions(+), 42 deletions(-) diff --git a/fronius/integrationpluginfronius.cpp b/fronius/integrationpluginfronius.cpp index 829ca62f..42e81798 100644 --- a/fronius/integrationpluginfronius.cpp +++ b/fronius/integrationpluginfronius.cpp @@ -394,13 +394,68 @@ void IntegrationPluginFronius::refreshConnection(FroniusSolarConnection *connect thingDescriptors.clear(); } - // Update the inverters + // All devices + updatePowerFlow(connection); updateInverters(connection); updateMeters(connection); updateStorages(connection); }); } +void IntegrationPluginFronius::updatePowerFlow(FroniusSolarConnection *connection) +{ + Thing *parentThing = m_froniusConnections.value(connection); + + // Get power flow realtime data and update storage and pv power values according to the total values + // The inverter details inform about the PV production after feeding the storage, but we should use the total + // to make sure the sum is correct. Battery seems to be feeded DC to DC before the AC power convertion + FroniusNetworkReply *powerFlowReply = connection->getPowerFlowRealtimeData(); + connect(powerFlowReply, &FroniusNetworkReply::finished, this, [=]() { + if (powerFlowReply->networkReply()->error() != QNetworkReply::NoError) { + return; + } + + QByteArray data = powerFlowReply->networkReply()->readAll(); + + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); + if (error.error != QJsonParseError::NoError) { + qCWarning(dcFronius()) << "Meter: Failed to parse JSON data" << data << ":" << error.errorString(); + return; + } + + // Parse the data and update the states of our device + QVariantMap dataMap = jsonDoc.toVariant().toMap().value("Body").toMap().value("Data").toMap(); + //qCDebug(dcFronius()) << "Power flow data" << qUtf8Printable(QJsonDocument::fromVariant(dataMap).toJson(QJsonDocument::Indented)); + + // Find the inverter for this connection and set the total power + Things availableInverters = myThings().filterByParentId(parentThing->id()).filterByThingClassId(inverterThingClassId); + if (availableInverters.count() == 1) { + Thing *inverterThing = availableInverters.first(); + double pvPower = dataMap.value("Site").toMap().value("P_PV").toDouble(); + inverterThing->setStateValue(inverterCurrentPowerStateTypeId, - pvPower); + } + + // Find the storage for this connection and update the current power + Things availableStorages = myThings().filterByParentId(parentThing->id()).filterByThingClassId(storageThingClassId); + if (availableStorages.count() == 1) { + Thing *storageThing = availableStorages.first(); + // Note: negative (charge), positiv (discharge) + double akkuPower = - dataMap.value("Site").toMap().value("P_Akku").toDouble(); + storageThing->setStateValue(storageCurrentPowerStateTypeId, akkuPower); + if (akkuPower < 0) { + storageThing->setStateValue(storageChargingStateStateTypeId, "discharging"); + } else if (akkuPower > 0) { + storageThing->setStateValue(storageChargingStateStateTypeId, "charging"); + } else { + storageThing->setStateValue(storageChargingStateStateTypeId, "idle"); + } + } + + }); +} + + void IntegrationPluginFronius::updateInverters(FroniusSolarConnection *connection) { Thing *parentThing = m_froniusConnections.value(connection); @@ -430,14 +485,15 @@ void IntegrationPluginFronius::updateInverters(FroniusSolarConnection *connectio QVariantMap dataMap = jsonDoc.toVariant().toMap().value("Body").toMap().value("Data").toMap(); //qCDebug(dcFronius()) << "Inverter data" << qUtf8Printable(QJsonDocument::fromVariant(dataMap).toJson(QJsonDocument::Indented)); - // Set the inverter device state - if (dataMap.contains("PAC")) { - QVariantMap map = dataMap.value("PAC").toMap(); - if (map.value("Unit") == "W") { - inverterThing->setStateValue(inverterCurrentPowerStateTypeId, - map.value("Value").toDouble()); - } - } + // Note: this is the PV power after feeding the battery, we have to use the total PV production from the power flow + //if (dataMap.contains("PAC")) { + // QVariantMap map = dataMap.value("PAC").toMap(); + // if (map.value("Unit") == "W") { + // inverterThing->setStateValue(inverterCurrentPowerStateTypeId, - map.value("Value").toDouble()); + // } + //} + // Set the inverter device state if (dataMap.contains("DAY_ENERGY")) { QVariantMap map = dataMap.value("DAY_ENERGY").toMap(); if (map.value("Unit") == "Wh") { @@ -561,40 +617,6 @@ void IntegrationPluginFronius::updateStorages(FroniusSolarConnection *connection foreach (Thing *storageThing, myThings().filterByParentId(parentThing->id()).filterByThingClassId(storageThingClassId)) { int storageId = storageThing->paramValue(storageThingIdParamTypeId).toInt(); - // Get power flow realtime data - FroniusNetworkReply *powerFlowReply = connection->getPowerFlowRealtimeData(); - connect(powerFlowReply, &FroniusNetworkReply::finished, this, [=]() { - if (powerFlowReply->networkReply()->error() != QNetworkReply::NoError) { - // Thing does not seem to be reachable - storageThing->setStateValue("connected", false); - return; - } - - QByteArray data = powerFlowReply->networkReply()->readAll(); - - QJsonParseError error; - QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); - if (error.error != QJsonParseError::NoError) { - qCWarning(dcFronius()) << "Meter: Failed to parse JSON data" << data << ":" << error.errorString(); - storageThing->setStateValue("connected", false); - return; - } - - // Parse the data and update the states of our device - QVariantMap dataMap = jsonDoc.toVariant().toMap().value("Body").toMap().value("Data").toMap(); - //qCDebug(dcFronius()) << "Power flow data" << qUtf8Printable(QJsonDocument::fromVariant(dataMap).toJson(QJsonDocument::Indented)); - - float charge_akku = dataMap.value("Site").toMap().value("P_Akku").toFloat(); - storageThing->setStateValue(storageCurrentPowerStateTypeId, charge_akku); - if (charge_akku < 0) { - storageThing->setStateValue(storageChargingStateStateTypeId, "discharging"); - } else if (charge_akku > 0) { - storageThing->setStateValue(storageChargingStateStateTypeId, "charging"); - } else { - storageThing->setStateValue(storageChargingStateStateTypeId, "idle"); - } - }); - // Get the storage realtime data FroniusNetworkReply *realtimeDataReply = connection->getStorageRealtimeData(storageId); connect(realtimeDataReply, &FroniusNetworkReply::finished, this, [=]() { diff --git a/fronius/integrationpluginfronius.h b/fronius/integrationpluginfronius.h index bb801962..8fec913b 100644 --- a/fronius/integrationpluginfronius.h +++ b/fronius/integrationpluginfronius.h @@ -63,6 +63,7 @@ private: void refreshConnection(FroniusSolarConnection *connection); + void updatePowerFlow(FroniusSolarConnection *connection); void updateInverters(FroniusSolarConnection *connection); void updateMeters(FroniusSolarConnection *connection); void updateStorages(FroniusSolarConnection *connection);