Merge PR #113: huawei: Set energy states to 0 if not connected and filter invalid energy counter values

pull/121/head
jenkins 2023-03-07 17:25:35 +01:00
commit 6cbeb64c0c
2 changed files with 112 additions and 3 deletions

View File

@ -121,7 +121,6 @@ void IntegrationPluginHuawei::setupThing(ThingSetupInfo *info)
if (m_monitors.contains(thing))
hardwareManager()->networkDeviceDiscovery()->unregisterMonitor(m_monitors.take(thing));
// Make sure we have a valid mac address, otherwise no monitor and not auto searching is possible
MacAddress macAddress = MacAddress(thing->paramValue(huaweiFusionSolarInverterThingMacAddressParamTypeId).toString());
if (macAddress.isNull()) {
@ -436,11 +435,32 @@ void IntegrationPluginHuawei::setupFusionSolar(ThingSetupInfo *info)
childThing->setStateValue("connected", true);
}
// Reset history, just incase
m_inverterEnergyProducedHistory[thing].clear();
// Add the current value to the history
evaluateEnergyProducedValue(thing, thing->stateValue(huaweiFusionSolarInverterTotalEnergyProducedStateTypeId).toFloat());
connect(connection, &HuaweiFusionSolar::reachableChanged, thing, [=](bool reachable){
qCDebug(dcHuawei()) << "Reachable changed to" << reachable << "for" << thing;
thing->setStateValue("connected", reachable);
foreach (Thing *childThing, myThings().filterByParentId(thing->id())) {
childThing->setStateValue("connected", reachable);
if (!reachable) {
// Set power values to 0 since we don't know what the current value is
if (childThing->thingClassId() == huaweiFusionSolarInverterThingClassId) {
thing->setStateValue(huaweiFusionSolarInverterCurrentPowerStateTypeId, 0);
}
if (childThing->thingClassId() == huaweiMeterThingClassId) {
thing->setStateValue(huaweiMeterCurrentPowerStateTypeId, 0);
}
if (childThing->thingClassId() == huaweiBatteryThingClassId) {
thing->setStateValue(huaweiBatteryCurrentPowerStateTypeId, 0);
}
}
}
});
@ -469,9 +489,13 @@ void IntegrationPluginHuawei::setupFusionSolar(ThingSetupInfo *info)
Q_UNUSED(thing)
});
connect(connection, &HuaweiFusionSolar::inverterEnergyProducedReadFinished, thing, [thing](float inverterEnergyProduced){
connect(connection, &HuaweiFusionSolar::inverterEnergyProducedReadFinished, thing, [this, thing](float inverterEnergyProduced){
qCDebug(dcHuawei()) << "Inverter total energy produced changed" << inverterEnergyProduced << "kWh";
thing->setStateValue(huaweiFusionSolarInverterTotalEnergyProducedStateTypeId, inverterEnergyProduced);
// Note: sometimes this value is suddenly 0 or absurd high > 100000000
// We try here to filer out such random values. Sadly the values seem to
// come like that from the device, without exception or error.
evaluateEnergyProducedValue(thing, inverterEnergyProduced);
});
// Meter
@ -585,3 +609,84 @@ void IntegrationPluginHuawei::setupFusionSolar(ThingSetupInfo *info)
connection->connectDevice();
}
void IntegrationPluginHuawei::evaluateEnergyProducedValue(Thing *inverterThing, float energyProduced)
{
// Add the value to our small history
m_inverterEnergyProducedHistory[inverterThing].append(energyProduced);
int historyMaxSize = 3;
int absurdlyHighValueLimit= 25000000;
int historySize = m_inverterEnergyProducedHistory.value(inverterThing).count();
if (historySize > historyMaxSize) {
m_inverterEnergyProducedHistory[inverterThing].removeFirst();
}
if (historySize == 1) {
// First value add very high, add it to the history, but do not set this value until we get more absurde high value
if (energyProduced > absurdlyHighValueLimit) {
qCWarning(dcHuawei()) << "Energyfilter: First energy value absurdly high" << energyProduced << "...waiting for more values before accepting such values.";
return;
}
// First value, no need to speculate here, we have no history
inverterThing->setStateValue(huaweiFusionSolarInverterTotalEnergyProducedStateTypeId, energyProduced);
return;
}
// Check if the new value is smaller than the current one, if so, we have either a counter reset or an invalid value we want to filter out
float currentEnergyProduced = inverterThing->stateValue(huaweiFusionSolarInverterTotalEnergyProducedStateTypeId).toFloat();
if (energyProduced < currentEnergyProduced) {
// If more than 3 values arrive which are smaller than the current value,
// we are sure this is a meter rest growing again and we assume they are correct
// otherwise we just add the value to the history and wait for the next value before
// we update the state
if (historySize < historyMaxSize) {
qCWarning(dcHuawei()) << "Energyfilter: Energy value" << energyProduced << "smaller than the last one. Still collecting history data" << m_inverterEnergyProducedHistory.value(inverterThing);
return;
}
// Full history available, let's verify against the older values
bool allValuesSmaller = true;
for (int i = 0; i < historySize - 1; i++) {
if (m_inverterEnergyProducedHistory.value(inverterThing).at(i) >= currentEnergyProduced) {
allValuesSmaller = false;
break;
}
}
if (allValuesSmaller) {
// We belive it, meter has been resetted
qCDebug(dcHuawei()) << "Energyfilter: Energy value" << energyProduced << "seems to be really resetted back. Beliving it... History data:" << m_inverterEnergyProducedHistory.value(inverterThing);
inverterThing->setStateValue(huaweiFusionSolarInverterTotalEnergyProducedStateTypeId, energyProduced);
}
return;
} else if (energyProduced > absurdlyHighValueLimit) {
// First value add very high, add it to the history, but do not set this value until we get more in this hight
if (historySize < historyMaxSize) {
qCWarning(dcHuawei()) << "Energyfilter: Energy value" << energyProduced << "absurdly high. Still collecting history data" << m_inverterEnergyProducedHistory.value(inverterThing);
return;
}
// Full history available, let's verify against the older values
bool allValuesAbsurdlyHigh = true;
for (int i = 0; i < historySize - 1; i++) {
if (m_inverterEnergyProducedHistory.value(inverterThing).at(i) < absurdlyHighValueLimit) {
allValuesAbsurdlyHigh = false;
break;
}
}
if (allValuesAbsurdlyHigh) {
// We belive it, they realy seem all absurdly high...
qCDebug(dcHuawei()) << "Energyfilter: Energy value" << energyProduced << "seems to be really this absurdly high. Beliving it... History data:" << m_inverterEnergyProducedHistory.value(inverterThing);
inverterThing->setStateValue(huaweiFusionSolarInverterTotalEnergyProducedStateTypeId, energyProduced);
}
} else {
// Nothing strange detected, normal state update
inverterThing->setStateValue(huaweiFusionSolarInverterTotalEnergyProducedStateTypeId, energyProduced);
}
}

View File

@ -31,6 +31,7 @@
#ifndef INTEGRATIONPLUGINHUAWEI_H
#define INTEGRATIONPLUGINHUAWEI_H
#include <QHash>
#include <plugintimer.h>
#include <integrations/integrationplugin.h>
#include <network/networkdevicediscovery.h>
@ -62,6 +63,9 @@ private:
QHash<Thing *, HuaweiModbusRtuConnection *> m_rtuConnections;
void setupFusionSolar(ThingSetupInfo *info);
QHash<Thing *, QList<float>> m_inverterEnergyProducedHistory;
void evaluateEnergyProducedValue(Thing *inverterThing, float energyProduced);
};
#endif // INTEGRATIONPLUGINHUAWEI_H