Merge PR #209: Sungrow: Fix battery calculations and add device type string
This commit is contained in:
commit
ba0b31a4b7
@ -52,12 +52,15 @@ void IntegrationPluginSungrow::discoverThings(ThingDiscoveryInfo *info)
|
|||||||
SungrowDiscovery *discovery = new SungrowDiscovery(hardwareManager()->networkDeviceDiscovery(), m_modbusTcpPort, m_modbusSlaveAddress, info);
|
SungrowDiscovery *discovery = new SungrowDiscovery(hardwareManager()->networkDeviceDiscovery(), m_modbusTcpPort, m_modbusSlaveAddress, info);
|
||||||
connect(discovery, &SungrowDiscovery::discoveryFinished, info, [=](){
|
connect(discovery, &SungrowDiscovery::discoveryFinished, info, [=](){
|
||||||
foreach (const SungrowDiscovery::SungrowDiscoveryResult &result, discovery->discoveryResults()) {
|
foreach (const SungrowDiscovery::SungrowDiscoveryResult &result, discovery->discoveryResults()) {
|
||||||
QString title = "Sungrow " + QString::number(result.nominalOutputPower) + "kW Inverter";
|
QString title = "Sungrow " + result.model;
|
||||||
|
|
||||||
if (!result.serialNumber.isEmpty())
|
if (!result.serialNumber.isEmpty())
|
||||||
title.append(" " + result.serialNumber);
|
title.append(" - " + result.serialNumber);
|
||||||
|
|
||||||
ThingDescriptor descriptor(sungrowInverterTcpThingClassId, title, result.networkDeviceInfo.address().toString());
|
QString description(QString::number(result.nominalOutputPower)+ "kW Inverter - " + result.networkDeviceInfo.address().toString());
|
||||||
|
|
||||||
|
|
||||||
|
ThingDescriptor descriptor(sungrowInverterTcpThingClassId, title, description);
|
||||||
qCInfo(dcSungrow()) << "Discovered:" << descriptor.title() << descriptor.description();
|
qCInfo(dcSungrow()) << "Discovered:" << descriptor.title() << descriptor.description();
|
||||||
|
|
||||||
ParamList params;
|
ParamList params;
|
||||||
@ -158,6 +161,9 @@ void IntegrationPluginSungrow::setupThing(ThingSetupInfo *info)
|
|||||||
child->setStateValue(sungrowMeterCurrentPhaseAStateTypeId, 0);
|
child->setStateValue(sungrowMeterCurrentPhaseAStateTypeId, 0);
|
||||||
child->setStateValue(sungrowMeterCurrentPhaseBStateTypeId, 0);
|
child->setStateValue(sungrowMeterCurrentPhaseBStateTypeId, 0);
|
||||||
child->setStateValue(sungrowMeterCurrentPhaseCStateTypeId, 0);
|
child->setStateValue(sungrowMeterCurrentPhaseCStateTypeId, 0);
|
||||||
|
child->setStateValue(sungrowMeterVoltagePhaseAStateTypeId, 0);
|
||||||
|
child->setStateValue(sungrowMeterVoltagePhaseBStateTypeId, 0);
|
||||||
|
child->setStateValue(sungrowMeterVoltagePhaseCStateTypeId, 0);
|
||||||
child->setStateValue(sungrowMeterApparentPowerPhaseAStateTypeId, 0);
|
child->setStateValue(sungrowMeterApparentPowerPhaseAStateTypeId, 0);
|
||||||
child->setStateValue(sungrowMeterApparentPowerPhaseBStateTypeId, 0);
|
child->setStateValue(sungrowMeterApparentPowerPhaseBStateTypeId, 0);
|
||||||
child->setStateValue(sungrowMeterApparentPowerPhaseCStateTypeId, 0);
|
child->setStateValue(sungrowMeterApparentPowerPhaseCStateTypeId, 0);
|
||||||
@ -214,7 +220,7 @@ void IntegrationPluginSungrow::setupThing(ThingSetupInfo *info)
|
|||||||
// Update the meter if available
|
// Update the meter if available
|
||||||
Thing *meterThing = getMeterThing(thing);
|
Thing *meterThing = getMeterThing(thing);
|
||||||
if (meterThing) {
|
if (meterThing) {
|
||||||
auto runningState = sungrowConnection->runningState();
|
quint16 runningState = sungrowConnection->runningState();
|
||||||
qCDebug(dcSungrow()) << "Power generated from PV:" << (runningState & (0x1 << 0) ? "true" : "false");
|
qCDebug(dcSungrow()) << "Power generated from PV:" << (runningState & (0x1 << 0) ? "true" : "false");
|
||||||
qCDebug(dcSungrow()) << "Battery charging:" << (runningState & (0x1 << 1) ? "true" : "false");
|
qCDebug(dcSungrow()) << "Battery charging:" << (runningState & (0x1 << 1) ? "true" : "false");
|
||||||
qCDebug(dcSungrow()) << "Battery discharging:" << (runningState & (0x1 << 2) ? "true" : "false");
|
qCDebug(dcSungrow()) << "Battery discharging:" << (runningState & (0x1 << 2) ? "true" : "false");
|
||||||
@ -245,7 +251,14 @@ void IntegrationPluginSungrow::setupThing(ThingSetupInfo *info)
|
|||||||
batteryThing->setStateValue(sungrowBatteryBatteryLevelStateTypeId, sungrowConnection->batteryLevel());
|
batteryThing->setStateValue(sungrowBatteryBatteryLevelStateTypeId, sungrowConnection->batteryLevel());
|
||||||
batteryThing->setStateValue(sungrowBatteryBatteryCriticalStateTypeId, sungrowConnection->batteryLevel() < 5);
|
batteryThing->setStateValue(sungrowBatteryBatteryCriticalStateTypeId, sungrowConnection->batteryLevel() < 5);
|
||||||
|
|
||||||
batteryThing->setStateValue(sungrowBatteryCurrentPowerStateTypeId, sungrowConnection->batteryPower());
|
// Note: since firmware 2024 this is a int16 value, and we can use the value directly without convertion
|
||||||
|
if (sungrowConnection->batteryPower() < 0) {
|
||||||
|
batteryThing->setStateValue(sungrowBatteryCurrentPowerStateTypeId, sungrowConnection->batteryPower());
|
||||||
|
} else {
|
||||||
|
qint16 batteryPower = (sungrowConnection->runningState() & (0x1 << 1) ? sungrowConnection->batteryPower() : sungrowConnection->batteryPower() * -1);
|
||||||
|
batteryThing->setStateValue(sungrowBatteryCurrentPowerStateTypeId, batteryPower);
|
||||||
|
}
|
||||||
|
|
||||||
quint16 runningState = sungrowConnection->runningState();
|
quint16 runningState = sungrowConnection->runningState();
|
||||||
if (runningState & (0x1 << 1)) { //Bit 1: Battery charging bit
|
if (runningState & (0x1 << 1)) { //Bit 1: Battery charging bit
|
||||||
batteryThing->setStateValue(sungrowBatteryChargingStateStateTypeId, "charging");
|
batteryThing->setStateValue(sungrowBatteryChargingStateStateTypeId, "charging");
|
||||||
|
|||||||
@ -66,6 +66,7 @@ private:
|
|||||||
|
|
||||||
Thing *getMeterThing(Thing *parentThing);
|
Thing *getMeterThing(Thing *parentThing);
|
||||||
Thing *getBatteryThing(Thing *parentThing);
|
Thing *getBatteryThing(Thing *parentThing);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INTEGRATIONPLUGINSUNGROW_H
|
#endif // INTEGRATIONPLUGINSUNGROW_H
|
||||||
|
|||||||
@ -310,7 +310,109 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "energyValues2",
|
"id": "energyValues3",
|
||||||
|
"readSchedule": "update",
|
||||||
|
"registers": [
|
||||||
|
{
|
||||||
|
"id": "meterVoltagePhaseA",
|
||||||
|
"address": 5740,
|
||||||
|
"size": 1,
|
||||||
|
"type": "uint16",
|
||||||
|
"registerType": "inputRegister",
|
||||||
|
"description": "Meter voltage phase A",
|
||||||
|
"defaultValue": "0",
|
||||||
|
"staticScaleFactor": -1,
|
||||||
|
"unit": "Volt",
|
||||||
|
"access": "RO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "meterVoltagePhaseB",
|
||||||
|
"address": 5741,
|
||||||
|
"size": 1,
|
||||||
|
"type": "uint16",
|
||||||
|
"registerType": "inputRegister",
|
||||||
|
"description": "Meter voltage phase B",
|
||||||
|
"defaultValue": "0",
|
||||||
|
"staticScaleFactor": -1,
|
||||||
|
"unit": "Volt",
|
||||||
|
"access": "RO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "meterVoltagePhaseC",
|
||||||
|
"address": 5742,
|
||||||
|
"size": 1,
|
||||||
|
"type": "uint16",
|
||||||
|
"registerType": "inputRegister",
|
||||||
|
"description": "Meter voltage phase C",
|
||||||
|
"defaultValue": "0",
|
||||||
|
"staticScaleFactor": -1,
|
||||||
|
"unit": "Volt",
|
||||||
|
"access": "RO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "meterCurrentPhaseA",
|
||||||
|
"address": 5743,
|
||||||
|
"size": 1,
|
||||||
|
"type": "uint16",
|
||||||
|
"registerType": "inputRegister",
|
||||||
|
"description": "Meter current phase A",
|
||||||
|
"defaultValue": "0",
|
||||||
|
"staticScaleFactor": -2,
|
||||||
|
"unit": "Amper",
|
||||||
|
"access": "RO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "meterCurrentPhaseB",
|
||||||
|
"address": 5744,
|
||||||
|
"size": 1,
|
||||||
|
"type": "uint16",
|
||||||
|
"registerType": "inputRegister",
|
||||||
|
"description": "Meter current phase B",
|
||||||
|
"defaultValue": "0",
|
||||||
|
"staticScaleFactor": -2,
|
||||||
|
"unit": "Amper",
|
||||||
|
"access": "RO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "meterCurrentPhaseC",
|
||||||
|
"address": 5745,
|
||||||
|
"size": 1,
|
||||||
|
"type": "uint16",
|
||||||
|
"registerType": "inputRegister",
|
||||||
|
"description": "Meter current phase C",
|
||||||
|
"defaultValue": "0",
|
||||||
|
"staticScaleFactor": -2,
|
||||||
|
"unit": "Amper",
|
||||||
|
"access": "RO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "meterTotalEnergyImported",
|
||||||
|
"address": 5746,
|
||||||
|
"size": 2,
|
||||||
|
"type": "uint32",
|
||||||
|
"registerType": "inputRegister",
|
||||||
|
"description": "Meter totoal energy imported",
|
||||||
|
"unit": "kWh",
|
||||||
|
"defaultValue": "0",
|
||||||
|
"staticScaleFactor": -2,
|
||||||
|
"access": "RO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "meterTotalEnergyExported",
|
||||||
|
"address": 5748,
|
||||||
|
"size": 2,
|
||||||
|
"type": "uint32",
|
||||||
|
"registerType": "inputRegister",
|
||||||
|
"description": "Meter totoal energy exported",
|
||||||
|
"unit": "kWh",
|
||||||
|
"defaultValue": "0",
|
||||||
|
"staticScaleFactor": -2,
|
||||||
|
"access": "RO"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "energyValues4",
|
||||||
"readSchedule": "update",
|
"readSchedule": "update",
|
||||||
"registers": [
|
"registers": [
|
||||||
{
|
{
|
||||||
@ -465,7 +567,7 @@
|
|||||||
"id": "batteryPower",
|
"id": "batteryPower",
|
||||||
"address": 13021,
|
"address": 13021,
|
||||||
"size": 1,
|
"size": 1,
|
||||||
"type": "uint16",
|
"type": "int16",
|
||||||
"registerType": "inputRegister",
|
"registerType": "inputRegister",
|
||||||
"description": "Battery power",
|
"description": "Battery power",
|
||||||
"unit": "W",
|
"unit": "W",
|
||||||
|
|||||||
@ -60,6 +60,115 @@ void SungrowDiscovery::startDiscovery()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString SungrowDiscovery::deviceCodeToString(quint16 deviceTypeCode)
|
||||||
|
{
|
||||||
|
QString deviceType;
|
||||||
|
switch (deviceTypeCode) {
|
||||||
|
// SH3.0-6.0RS
|
||||||
|
case 0xD17:
|
||||||
|
deviceType = "SH3.0RS";
|
||||||
|
break;
|
||||||
|
case 0xD0D:
|
||||||
|
deviceType = "SH3.6RS";
|
||||||
|
break;
|
||||||
|
case 0xD18:
|
||||||
|
deviceType = "SH4.0RS";
|
||||||
|
break;
|
||||||
|
case 0xD0F:
|
||||||
|
deviceType = "SH5.0RS";
|
||||||
|
break;
|
||||||
|
case 0xD10:
|
||||||
|
deviceType = "SH5.0RS";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// SH8.0-10RS
|
||||||
|
case 0xD1A:
|
||||||
|
deviceType = "SH8.0RS";
|
||||||
|
break;
|
||||||
|
case 0xD1B:
|
||||||
|
deviceType = "SH10RS";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// SH5.0-10RT
|
||||||
|
case 0xE00:
|
||||||
|
deviceType = "SH5.0RT";
|
||||||
|
break;
|
||||||
|
case 0xE01:
|
||||||
|
deviceType = "SH6.0RT";
|
||||||
|
break;
|
||||||
|
case 0xE02:
|
||||||
|
deviceType = "SH8.0RT";
|
||||||
|
break;
|
||||||
|
case 0xE03:
|
||||||
|
deviceType = "SH10RT";
|
||||||
|
break;
|
||||||
|
case 0xE10:
|
||||||
|
deviceType = "SH5.0RT-20";
|
||||||
|
break;
|
||||||
|
case 0xE11:
|
||||||
|
deviceType = "SH6.0RT-20";
|
||||||
|
break;
|
||||||
|
case 0xE12:
|
||||||
|
deviceType = "SH8.0RT-20";
|
||||||
|
break;
|
||||||
|
case 0xE13:
|
||||||
|
deviceType = "SH10RT-20";
|
||||||
|
break;
|
||||||
|
case 0xE0C:
|
||||||
|
deviceType = "SH5.0RT-V112";
|
||||||
|
break;
|
||||||
|
case 0xE0D:
|
||||||
|
deviceType = "SH6.0RT-V112";
|
||||||
|
break;
|
||||||
|
case 0xE0E:
|
||||||
|
deviceType = "SH8.0RT-V112";
|
||||||
|
break;
|
||||||
|
case 0xE0F:
|
||||||
|
deviceType = "SH10RT-V112";
|
||||||
|
break;
|
||||||
|
case 0xE08:
|
||||||
|
deviceType = "SH5.0RT-V122";
|
||||||
|
break;
|
||||||
|
case 0xE09:
|
||||||
|
deviceType = "SH6.0RT-V122";
|
||||||
|
break;
|
||||||
|
case 0xE0A:
|
||||||
|
deviceType = "SH8.0RT-V122";
|
||||||
|
break;
|
||||||
|
case 0xE0B:
|
||||||
|
deviceType = "SH10RT-V122";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// SH5-25T
|
||||||
|
case 0xE20:
|
||||||
|
deviceType = "SH5T-V11";
|
||||||
|
break;
|
||||||
|
case 0xE21:
|
||||||
|
deviceType = "SH6T-V11";
|
||||||
|
break;
|
||||||
|
case 0xE22:
|
||||||
|
deviceType = "SH8T-V11";
|
||||||
|
break;
|
||||||
|
case 0xE23:
|
||||||
|
deviceType = "SH10T-V11";
|
||||||
|
break;
|
||||||
|
case 0xE24:
|
||||||
|
deviceType = "SH12T-V11";
|
||||||
|
break;
|
||||||
|
case 0xE25:
|
||||||
|
deviceType = "SH15T-V11";
|
||||||
|
break;
|
||||||
|
case 0xE26:
|
||||||
|
deviceType = "SH20T-V11";
|
||||||
|
break;
|
||||||
|
case 0xE28:
|
||||||
|
deviceType = "SH25T-V11";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return deviceType;
|
||||||
|
}
|
||||||
|
|
||||||
QList<SungrowDiscovery::SungrowDiscoveryResult> SungrowDiscovery::discoveryResults() const
|
QList<SungrowDiscovery::SungrowDiscoveryResult> SungrowDiscovery::discoveryResults() const
|
||||||
{
|
{
|
||||||
return m_discoveryResults;
|
return m_discoveryResults;
|
||||||
@ -93,14 +202,19 @@ void SungrowDiscovery::checkNetworkDevice(const QHostAddress &address)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcSungrow()) << "Discovery: Initialized successfully" << address.toString() << connection->serialNumber();
|
|
||||||
qCDebug(dcSungrow()) << " - Protocol number:" << connection->protocolNumber();
|
|
||||||
qCDebug(dcSungrow()) << " - Protocol version:" << connection->protocolVersion();
|
|
||||||
qCDebug(dcSungrow()) << " - ARM software version:" << connection->armSoftwareVersion();
|
|
||||||
qCDebug(dcSungrow()) << " - DSP software version:" << connection->dspSoftwareVersion();
|
|
||||||
|
|
||||||
if (connection->deviceTypeCode() >= 0xd00 && connection->deviceTypeCode() <= 0xeff) {
|
if (connection->deviceTypeCode() >= 0xd00 && connection->deviceTypeCode() <= 0xeff) {
|
||||||
|
|
||||||
|
qCDebug(dcSungrow()) << "Discovery: Initialized successfully" << address.toString() << connection->serialNumber();
|
||||||
|
qCDebug(dcSungrow()) << " - Model:" << deviceCodeToString(connection->deviceTypeCode());
|
||||||
|
qCDebug(dcSungrow()) << " - Protocol number:" << connection->protocolNumber();
|
||||||
|
qCDebug(dcSungrow()) << " - Protocol version:" << connection->protocolVersion();
|
||||||
|
qCDebug(dcSungrow()) << " - ARM software version:" << connection->armSoftwareVersion();
|
||||||
|
qCDebug(dcSungrow()) << " - DSP software version:" << connection->dspSoftwareVersion();
|
||||||
|
|
||||||
|
|
||||||
SungrowDiscoveryResult result;
|
SungrowDiscoveryResult result;
|
||||||
|
result.model = deviceCodeToString(connection->deviceTypeCode());
|
||||||
result.address = address;
|
result.address = address;
|
||||||
result.serialNumber = connection->serialNumber();
|
result.serialNumber = connection->serialNumber();
|
||||||
result.nominalOutputPower = connection->nominalOutputPower();
|
result.nominalOutputPower = connection->nominalOutputPower();
|
||||||
|
|||||||
@ -44,6 +44,7 @@ class SungrowDiscovery : public QObject
|
|||||||
public:
|
public:
|
||||||
explicit SungrowDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, quint16 port = 502, quint16 modbusAddress = 1, QObject *parent = nullptr);
|
explicit SungrowDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, quint16 port = 502, quint16 modbusAddress = 1, QObject *parent = nullptr);
|
||||||
typedef struct SungrowDiscoveryResult {
|
typedef struct SungrowDiscoveryResult {
|
||||||
|
QString model;
|
||||||
QString serialNumber;
|
QString serialNumber;
|
||||||
QHostAddress address;
|
QHostAddress address;
|
||||||
NetworkDeviceInfo networkDeviceInfo;
|
NetworkDeviceInfo networkDeviceInfo;
|
||||||
@ -55,6 +56,8 @@ public:
|
|||||||
|
|
||||||
QList<SungrowDiscoveryResult> discoveryResults() const;
|
QList<SungrowDiscoveryResult> discoveryResults() const;
|
||||||
|
|
||||||
|
static QString deviceCodeToString(quint16 deviceTypeCode);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void discoveryFinished();
|
void discoveryFinished();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user