add support for a connected smartmeter to collect totals

This commit is contained in:
frankenbubble 2023-10-11 00:05:34 +01:00
parent 63387535cb
commit 1875a2361d
4 changed files with 175 additions and 1 deletions

View File

@ -247,6 +247,32 @@
"defaultValue": "0",
"access": "RO"
},
{
"id": "powerMeterEnergyReturned",
"address": 37119,
"size": 2,
"type": "int32",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": " Positive active electricity - To Grid",
"unit": "kWh",
"staticScaleFactor": -2,
"defaultValue": "0",
"access": "RO"
},
{
"id": "powerMeterEnergyAquired",
"address": 37121,
"size": 2,
"type": "int32",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Reverse active power - From Grid",
"unit": "kWh",
"staticScaleFactor": -2,
"defaultValue": "0",
"access": "RO"
},
{
"id": "lunaBattery1Status",
"address": 37000,

View File

@ -330,6 +330,32 @@
"defaultValue": "0",
"access": "RO"
},
{
"id": "powerMeterEnergyReturned",
"address": 37119,
"size": 2,
"type": "int32",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": " Positive active electricity - To Grid",
"unit": "kWh",
"staticScaleFactor": -2,
"defaultValue": "0",
"access": "RO"
},
{
"id": "powerMeterEnergyAquired",
"address": 37121,
"size": 2,
"type": "int32",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Reverse active power - From Grid",
"unit": "kWh",
"staticScaleFactor": -2,
"defaultValue": "0",
"access": "RO"
},
{
"id": "lunaBattery1Status",
"address": 37000,

View File

@ -1,4 +1,4 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io
@ -71,6 +71,8 @@ bool HuaweiFusionSolar::update()
m_registersQueue.enqueue(HuaweiFusionModbusTcpConnection::RegisterLunaBattery2Power);
m_registersQueue.enqueue(HuaweiFusionModbusTcpConnection::RegisterPowerMeterActivePower);
m_registersQueue.enqueue(HuaweiFusionModbusTcpConnection::RegisterPowerMeterEnergyReturned);
m_registersQueue.enqueue(HuaweiFusionModbusTcpConnection::RegisterPowerMeterEnergyAquired);
m_registersQueue.enqueue(HuaweiFusionModbusTcpConnection::RegisterInverterEnergyProduced);
m_registersQueue.enqueue(HuaweiFusionModbusTcpConnection::RegisterInverterDeviceStatus);
@ -330,6 +332,96 @@ void HuaweiFusionSolar::readNextRegister()
break;
}
case HuaweiFusionModbusTcpConnection::RegisterPowerMeterEnergyReturned: {
// Update registers from Power meter active power
qCDebug(dcHuaweiFusionSolar()) << "--> Read \"Power meter Positive active electricity\" register:" << 37119 << "size:" << 2;
QModbusReply *reply = readPowerMeterEnergyReturned();
if (!reply) {
qCWarning(dcHuaweiFusionSolar()) << "Error occurred while reading \"Power meter Positive active electricity\" registers from" << modbusTcpMaster()->hostAddress().toString() << modbusTcpMaster()->errorString();
finishRequest();
return;
}
if (reply->isFinished()) {
reply->deleteLater(); // Broadcast reply returns immediatly
finishRequest();
return;
}
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
handleModbusError(reply->error());
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Power meter Positive active electricity\" register" << 37119 << "size:" << 2 << "valueCount:" << unit.valueCount() << unit.values() << unit.values().count();
if (!valuesAreVaild(unit.values(), 2)) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values. Requested" << 2 << "but received" << unit.values();
} else {
processPowerMeterEnergyReturnedRegisterValues(unit.values());
}
}
finishRequest();
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
if (reply->error() == QModbusDevice::ProtocolError) {
QModbusResponse response = reply->rawResult();
if (response.isException()) {
qCDebug(dcHuaweiFusionSolar()) << "Modbus reply error occurred while updating \"Power meter Positive active electricity\" registers from" << modbusTcpMaster()->hostAddress().toString() << exceptionToString(response.exceptionCode());
}
} else {
qCWarning(dcHuaweiFusionSolar()) << "Modbus reply error occurred while updating \"Power meter Positive active electricity\" registers from" << modbusTcpMaster()->hostAddress().toString() << error << reply->errorString();
}
});
break;
}
case HuaweiFusionModbusTcpConnection::RegisterPowerMeterEnergyAquired: {
// Update registers from Power meter active power
qCDebug(dcHuaweiFusionSolar()) << "--> Read \"Power meter Reverse active power\" register:" << 37121 << "size:" << 2;
QModbusReply *reply = readPowerMeterEnergyAquired();
if (!reply) {
qCWarning(dcHuaweiFusionSolar()) << "Error occurred while reading \"Power meter Reverse active power\" registers from" << modbusTcpMaster()->hostAddress().toString() << modbusTcpMaster()->errorString();
finishRequest();
return;
}
if (reply->isFinished()) {
reply->deleteLater(); // Broadcast reply returns immediatly
finishRequest();
return;
}
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
handleModbusError(reply->error());
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Power meter Reverse active power\" register" << 37121 << "size:" << 2 << "valueCount:" << unit.valueCount() << unit.values() << unit.values().count();
if (!valuesAreVaild(unit.values(), 2)) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values. Requested" << 2 << "but received" << unit.values();
} else {
processPowerMeterEnergyAquiredRegisterValues(unit.values());
}
}
finishRequest();
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
if (reply->error() == QModbusDevice::ProtocolError) {
QModbusResponse response = reply->rawResult();
if (response.isException()) {
qCDebug(dcHuaweiFusionSolar()) << "Modbus reply error occurred while updating \"Power meter Reverse active power\" registers from" << modbusTcpMaster()->hostAddress().toString() << exceptionToString(response.exceptionCode());
}
} else {
qCWarning(dcHuaweiFusionSolar()) << "Modbus reply error occurred while updating \"Power meter Reverse active power\" registers from" << modbusTcpMaster()->hostAddress().toString() << error << reply->errorString();
}
});
break;
}
case HuaweiFusionModbusTcpConnection::RegisterLunaBattery1Status: {
// Update registers from Luna 2000 Battery 1 status
qCDebug(dcHuaweiFusionSolar()) << "--> Read \"Luna 2000 Battery 1 status\" register:" << 37000 << "size:" << 1;

View File

@ -241,6 +241,22 @@ void IntegrationPluginHuawei::setupThing(ThingSetupInfo *info)
}
});
connect(connection, &HuaweiModbusRtuConnection::powerMeterEnergyReturnedChanged, thing, [this, thing](qint32 powerMeterEnergyReturned){
Things meterThings = myThings().filterByParentId(thing->id()).filterByThingClassId(huaweiMeterThingClassId);
if (!meterThings.isEmpty()) {
qCDebug(dcHuawei()) << "Meter Total Energy Returned changed" << powerMeterEnergyReturned << "KWh";
meterThings.first()->setStateValue(huaweiMeterTotalEnergyProducedStateTypeId, powerMeterEnergyReturned);
}
});
connect(connection, &HuaweiModbusRtuConnection::powerMeterEnergyAquiredChanged, thing, [this, thing](qint32 powerMeterEnergyAquired){
Things meterThings = myThings().filterByParentId(thing->id()).filterByThingClassId(huaweiMeterThingClassId);
if (!meterThings.isEmpty()) {
qCDebug(dcHuawei()) << "Meter power Energy Aquired changed" << powerMeterEnergyAquired << "KWh";
meterThings.first()->setStateValue(huaweiMeterTotalEnergyConsumedStateTypeId, powerMeterEnergyAquired);
}
});
// Battery 1
connect(connection, &HuaweiModbusRtuConnection::lunaBattery1StatusChanged, thing, [this, thing](HuaweiModbusRtuConnection::BatteryDeviceStatus lunaBattery1Status){
qCDebug(dcHuawei()) << "Battery 1 status changed" << lunaBattery1Status;
@ -526,6 +542,20 @@ void IntegrationPluginHuawei::setupFusionSolar(ThingSetupInfo *info)
meterThings.first()->setStateValue(huaweiMeterCurrentPowerStateTypeId, -powerMeterActivePower);
}
});
connect(connection, &HuaweiFusionSolar::powerMeterEnergyReturnedReadFinished, thing, [this, thing](qint32 powerMeterEnergyReturned){
Things meterThings = myThings().filterByParentId(thing->id()).filterByThingClassId(huaweiMeterThingClassId);
if (!meterThings.isEmpty()) {
qCDebug(dcHuawei()) << "Meter power Returned changed" << powerMeterEnergyReturned << "kWh";
meterThings.first()->setStateValue(huaweiMeterTotalEnergyProducedStateTypeId, powerMeterEnergyReturned);
}
});
connect(connection, &HuaweiFusionSolar::powerMeterEnergyAquiredReadFinished, thing, [this, thing](qint32 powerMeterEnergyAquired){
Things meterThings = myThings().filterByParentId(thing->id()).filterByThingClassId(huaweiMeterThingClassId);
if (!meterThings.isEmpty()) {
qCDebug(dcHuawei()) << "Meter power Aquired changed" << powerMeterEnergyAquired << "kWh";
meterThings.first()->setStateValue(huaweiMeterTotalEnergyConsumedStateTypeId, powerMeterEnergyAquired);
}
});
// Battery 1
connect(connection, &HuaweiFusionSolar::lunaBattery1StatusReadFinished, thing, [this, thing](HuaweiFusionSolar::BatteryDeviceStatus lunaBattery1Status){