SMA: add speedwire battery handling
This commit is contained in:
parent
e4721de1c5
commit
3c42c4837d
@ -116,7 +116,13 @@ void IntegrationPluginSma::discoverThings(ThingDiscoveryInfo *info)
|
|||||||
if (result.serialNumber == 0)
|
if (result.serialNumber == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ThingDescriptor descriptor(speedwireMeterThingClassId, "SMA Energy Meter (" + QString::number(result.serialNumber) + ")" , result.address.toString());
|
QString thingName = "SMA Energy Meter (" + QString::number(result.serialNumber) + ")";
|
||||||
|
|
||||||
|
// Note: the SMA Homemanager 2 identifies it self as inverter / data provider...we filter it out here.
|
||||||
|
if (result.modelId == 372)
|
||||||
|
thingName = "SMA Home Manager 2.0 (" + QString::number(result.serialNumber) + ")";
|
||||||
|
|
||||||
|
ThingDescriptor descriptor(speedwireMeterThingClassId, thingName, result.address.toString());
|
||||||
// We found an energy meter, let's check if we already added this one
|
// We found an energy meter, let's check if we already added this one
|
||||||
foreach (Thing *existingThing, myThings()) {
|
foreach (Thing *existingThing, myThings()) {
|
||||||
if (existingThing->paramValue(speedwireMeterThingSerialNumberParamTypeId).toUInt() == result.serialNumber) {
|
if (existingThing->paramValue(speedwireMeterThingSerialNumberParamTypeId).toUInt() == result.serialNumber) {
|
||||||
@ -165,6 +171,11 @@ void IntegrationPluginSma::discoverThings(ThingDiscoveryInfo *info)
|
|||||||
if (result.serialNumber == 0)
|
if (result.serialNumber == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Note: the SMA Homemanager 2 identifies him self as inverter / data provider...
|
||||||
|
// we filter it out here since it is a meter and also should identify as one.
|
||||||
|
if (result.modelId == 372)
|
||||||
|
continue;
|
||||||
|
|
||||||
ThingDescriptor descriptor(speedwireInverterThingClassId, "SMA inverter (" + QString::number(result.serialNumber) + ")", result.address.toString());
|
ThingDescriptor descriptor(speedwireInverterThingClassId, "SMA inverter (" + QString::number(result.serialNumber) + ")", result.address.toString());
|
||||||
// We found an inverter, let's check if we already added this one
|
// We found an inverter, let's check if we already added this one
|
||||||
foreach (Thing *existingThing, myThings()) {
|
foreach (Thing *existingThing, myThings()) {
|
||||||
@ -327,6 +338,7 @@ void IntegrationPluginSma::setupThing(ThingSetupInfo *info)
|
|||||||
});
|
});
|
||||||
|
|
||||||
connect(meter, &SpeedwireMeter::valuesUpdated, thing, [=](){
|
connect(meter, &SpeedwireMeter::valuesUpdated, thing, [=](){
|
||||||
|
qCDebug(dcSma()) << "Meter values updated for" << thing->name() << meter->currentPower() << "W";
|
||||||
thing->setStateValue(speedwireMeterConnectedStateTypeId, true);
|
thing->setStateValue(speedwireMeterConnectedStateTypeId, true);
|
||||||
thing->setStateValue(speedwireMeterCurrentPowerStateTypeId, meter->currentPower());
|
thing->setStateValue(speedwireMeterCurrentPowerStateTypeId, meter->currentPower());
|
||||||
thing->setStateValue(speedwireMeterCurrentPowerPhaseAStateTypeId, meter->currentPowerPhaseA());
|
thing->setStateValue(speedwireMeterCurrentPowerPhaseAStateTypeId, meter->currentPowerPhaseA());
|
||||||
@ -406,9 +418,18 @@ void IntegrationPluginSma::setupThing(ThingSetupInfo *info)
|
|||||||
if (!reachable) {
|
if (!reachable) {
|
||||||
markSpeedwireInverterAsDisconnected(thing);
|
markSpeedwireInverterAsDisconnected(thing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (Thing *batteryThing, myThings().filterByParentId(thing->id()).filterByThingClassId(speedwireBatteryThingClassId)) {
|
||||||
|
if (reachable) {
|
||||||
|
thing->setStateValue(speedwireBatteryConnectedStateTypeId, true);
|
||||||
|
} else {
|
||||||
|
markSpeedwireBatteryAsDisconnected(batteryThing);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(inverter, &SpeedwireInverter::valuesUpdated, thing, [=](){
|
connect(inverter, &SpeedwireInverter::valuesUpdated, thing, [=](){
|
||||||
|
qCDebug(dcSma()) << "Inverter values updated for" << thing->name() << -inverter->totalAcPower() << "W" << inverter->totalEnergyProduced() << "kWh";
|
||||||
thing->setStateValue(speedwireInverterConnectedStateTypeId, true);
|
thing->setStateValue(speedwireInverterConnectedStateTypeId, true);
|
||||||
thing->setStateValue(speedwireInverterTotalEnergyProducedStateTypeId, inverter->totalEnergyProduced());
|
thing->setStateValue(speedwireInverterTotalEnergyProducedStateTypeId, inverter->totalEnergyProduced());
|
||||||
thing->setStateValue(speedwireInverterEnergyProducedTodayStateTypeId, inverter->todayEnergyProduced());
|
thing->setStateValue(speedwireInverterEnergyProducedTodayStateTypeId, inverter->todayEnergyProduced());
|
||||||
@ -427,9 +448,46 @@ void IntegrationPluginSma::setupThing(ThingSetupInfo *info)
|
|||||||
thing->setStateValue(speedwireInverterCurrentPowerMpp2StateTypeId, inverter->powerDcMpp2());
|
thing->setStateValue(speedwireInverterCurrentPowerMpp2StateTypeId, inverter->powerDcMpp2());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(inverter, &SpeedwireInverter::batteryValuesUpdated, thing, [=](){
|
||||||
|
if (!thing->setupComplete() || !inverter->batteryAvailable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// First check if we already set up a battery for this inverter
|
||||||
|
Things childThings = myThings().filterByParentId(thing->id()).filterByThingClassId(speedwireBatteryThingClassId);
|
||||||
|
if (childThings.isEmpty()) {
|
||||||
|
// Autocreate battery
|
||||||
|
emit autoThingsAppeared(ThingDescriptors() << ThingDescriptor(speedwireBatteryThingClassId, "SMA Battery", QString(), thing->id()));
|
||||||
|
} else {
|
||||||
|
// We can only have one battery as a child
|
||||||
|
Thing *batteryThing = childThings.first();
|
||||||
|
batteryThing->setStateValue(speedwireBatteryConnectedStateTypeId, true);
|
||||||
|
batteryThing->setStateValue(speedwireBatteryBatteryLevelStateTypeId, inverter->batteryCharge());
|
||||||
|
batteryThing->setStateValue(speedwireBatteryBatteryCriticalStateTypeId, inverter->batteryCharge() < 10);
|
||||||
|
batteryThing->setStateValue(speedwireBatteryTemperatureStateTypeId, inverter->batteryTemperature());
|
||||||
|
batteryThing->setStateValue(speedwireBatteryVoltageStateTypeId, inverter->batteryVoltage());
|
||||||
|
batteryThing->setStateValue(speedwireBatteryCurrentStateTypeId, inverter->batteryCurrent());
|
||||||
|
|
||||||
|
double batteryPower = inverter->batteryVoltage() * inverter->batteryCurrent(); // P = U * I
|
||||||
|
qCDebug(dcSma()) << "Battery values updated for" << batteryThing->name() << batteryPower << "W";
|
||||||
|
batteryThing->setStateValue(speedwireBatteryCurrentPowerStateTypeId, batteryPower);
|
||||||
|
if (batteryPower == 0) {
|
||||||
|
batteryThing->setStateValue(speedwireBatteryChargingStateStateTypeId, "idle");
|
||||||
|
} else if (batteryPower < 0) {
|
||||||
|
batteryThing->setStateValue(speedwireBatteryChargingStateStateTypeId, "discharging");
|
||||||
|
} else if (batteryPower > 0) {
|
||||||
|
batteryThing->setStateValue(speedwireBatteryChargingStateStateTypeId, "charging");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
qCDebug(dcSma()) << "Inverter: Start connecting using password" << password;
|
qCDebug(dcSma()) << "Inverter: Start connecting using password" << password;
|
||||||
inverter->startConnecting(password);
|
inverter->startConnecting(password);
|
||||||
|
|
||||||
|
} else if (thing->thingClassId() == speedwireBatteryThingClassId) {
|
||||||
|
|
||||||
|
qCDebug(dcSma()) << "Battery: Setup SMA battery" << thing;
|
||||||
|
info->finish(Thing::ThingErrorNoError);
|
||||||
|
|
||||||
} else if (thing->thingClassId() == modbusInverterThingClassId) {
|
} else if (thing->thingClassId() == modbusInverterThingClassId) {
|
||||||
|
|
||||||
// Handle reconfigure
|
// Handle reconfigure
|
||||||
@ -514,6 +572,20 @@ void IntegrationPluginSma::postSetupThing(Thing *thing)
|
|||||||
|
|
||||||
setupRefreshTimer();
|
setupRefreshTimer();
|
||||||
|
|
||||||
|
} else if (thing->thingClassId() == speedwireBatteryThingClassId) {
|
||||||
|
SpeedwireInverter *inverter = m_speedwireInverters.value(myThings().findById(thing->parentId()));
|
||||||
|
if (inverter) {
|
||||||
|
if (inverter->reachable()) {
|
||||||
|
thing->setStateValue(speedwireBatteryConnectedStateTypeId, true);
|
||||||
|
} else {
|
||||||
|
markSpeedwireBatteryAsDisconnected(thing);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
markSpeedwireBatteryAsDisconnected(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
setupRefreshTimer();
|
||||||
|
|
||||||
} else if (thing->thingClassId() == modbusInverterThingClassId) {
|
} else if (thing->thingClassId() == modbusInverterThingClassId) {
|
||||||
SmaInverterModbusTcpConnection *connection = m_modbusInverters.value(thing);
|
SmaInverterModbusTcpConnection *connection = m_modbusInverters.value(thing);
|
||||||
if (connection) {
|
if (connection) {
|
||||||
@ -787,6 +859,15 @@ void IntegrationPluginSma::markSpeedwireInverterAsDisconnected(Thing *thing)
|
|||||||
thing->setStateValue(speedwireInverterCurrentPowerStateTypeId, 0);
|
thing->setStateValue(speedwireInverterCurrentPowerStateTypeId, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginSma::markSpeedwireBatteryAsDisconnected(Thing *thing)
|
||||||
|
{
|
||||||
|
thing->setStateValue(speedwireBatteryConnectedStateTypeId, false);
|
||||||
|
thing->setStateValue(speedwireBatteryVoltageStateTypeId, 0);
|
||||||
|
thing->setStateValue(speedwireBatteryCurrentStateTypeId, 0);
|
||||||
|
thing->setStateValue(speedwireBatteryCurrentPowerStateTypeId, 0);
|
||||||
|
thing->setStateValue(speedwireBatteryChargingStateStateTypeId, "idle");
|
||||||
|
}
|
||||||
|
|
||||||
void IntegrationPluginSma::markModbusInverterAsDisconnected(Thing *thing)
|
void IntegrationPluginSma::markModbusInverterAsDisconnected(Thing *thing)
|
||||||
{
|
{
|
||||||
thing->setStateValue(modbusInverterVoltagePhaseAStateTypeId, 0);
|
thing->setStateValue(modbusInverterVoltagePhaseAStateTypeId, 0);
|
||||||
|
|||||||
@ -87,6 +87,7 @@ private:
|
|||||||
|
|
||||||
void markSpeedwireMeterAsDisconnected(Thing *thing);
|
void markSpeedwireMeterAsDisconnected(Thing *thing);
|
||||||
void markSpeedwireInverterAsDisconnected(Thing *thing);
|
void markSpeedwireInverterAsDisconnected(Thing *thing);
|
||||||
|
void markSpeedwireBatteryAsDisconnected(Thing *thing);
|
||||||
void markModbusInverterAsDisconnected(Thing *thing);
|
void markModbusInverterAsDisconnected(Thing *thing);
|
||||||
|
|
||||||
quint64 getLocalSerialNumber();
|
quint64 getLocalSerialNumber();
|
||||||
|
|||||||
@ -88,7 +88,7 @@
|
|||||||
"name": "speedwireMeter",
|
"name": "speedwireMeter",
|
||||||
"displayName": "SMA Energy Meter",
|
"displayName": "SMA Energy Meter",
|
||||||
"createMethods": ["discovery", "user"],
|
"createMethods": ["discovery", "user"],
|
||||||
"interfaces": [ "energymeter" ],
|
"interfaces": [ "energymeter", "connectable"],
|
||||||
"paramTypes": [
|
"paramTypes": [
|
||||||
{
|
{
|
||||||
"id": "7c81a0c5-9bc6-43bb-a01a-4de5fe656bba",
|
"id": "7c81a0c5-9bc6-43bb-a01a-4de5fe656bba",
|
||||||
@ -286,7 +286,7 @@
|
|||||||
"displayName": "SMA Inverter",
|
"displayName": "SMA Inverter",
|
||||||
"createMethods": ["discovery", "user"],
|
"createMethods": ["discovery", "user"],
|
||||||
"setupMethod": "EnterPin",
|
"setupMethod": "EnterPin",
|
||||||
"interfaces": [ "solarinverter" ],
|
"interfaces": [ "solarinverter", "connectable"],
|
||||||
"paramTypes": [
|
"paramTypes": [
|
||||||
{
|
{
|
||||||
"id": "c8098d53-69eb-4d0b-9f07-e43c4a0ea9a9",
|
"id": "c8098d53-69eb-4d0b-9f07-e43c4a0ea9a9",
|
||||||
@ -447,6 +447,91 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "b459dad2-f78b-4a87-a7f3-22f3147b83d8",
|
||||||
|
"name": "speedwireBattery",
|
||||||
|
"displayName": "SMA Battery",
|
||||||
|
"createMethods": ["auto"],
|
||||||
|
"setupMethod": "JustAdd",
|
||||||
|
"interfaces": [ "energystorage", "connectable"],
|
||||||
|
"paramTypes": [ ],
|
||||||
|
"stateTypes": [
|
||||||
|
{
|
||||||
|
"id": "7f242169-c01a-4c9a-ac71-4f9fa5409875",
|
||||||
|
"name": "connected",
|
||||||
|
"displayName": "Connected",
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d2144cad-e507-433b-a9d3-2ab9cf0c1014",
|
||||||
|
"name": "voltage",
|
||||||
|
"displayName": "Voltage",
|
||||||
|
"type": "double",
|
||||||
|
"unit": "Volt",
|
||||||
|
"defaultValue": 0,
|
||||||
|
"cached": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "541c110d-2f56-44bb-8f7e-de55759b942d",
|
||||||
|
"name": "current",
|
||||||
|
"displayName": "Current",
|
||||||
|
"type": "double",
|
||||||
|
"unit": "Ampere",
|
||||||
|
"defaultValue": 0,
|
||||||
|
"cached": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6a146a40-84da-4392-8466-4176b21280d2",
|
||||||
|
"name": "temperature",
|
||||||
|
"displayName": "Temperature",
|
||||||
|
"type": "double",
|
||||||
|
"unit": "DegreeCelsius",
|
||||||
|
"defaultValue": 0.00
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "f0f69109-83a4-4b2a-9e16-66aa33c2e169",
|
||||||
|
"name": "currentPower",
|
||||||
|
"displayName": "Current power",
|
||||||
|
"type": "double",
|
||||||
|
"unit": "Watt",
|
||||||
|
"defaultValue": 0.00
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "38a413cd-3d09-482d-8d25-b602db3b6540",
|
||||||
|
"name": "capacity",
|
||||||
|
"displayName": "Available energy",
|
||||||
|
"type": "double",
|
||||||
|
"unit": "KiloWattHour",
|
||||||
|
"defaultValue": 0.00
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d815aedf-e836-4274-9b51-2f0128420c46",
|
||||||
|
"name": "batteryCritical",
|
||||||
|
"displayName": "Battery critical",
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ec534954-8ee4-46f4-94b6-b48b375b1d7d",
|
||||||
|
"name": "batteryLevel",
|
||||||
|
"displayName": "Battery level",
|
||||||
|
"type": "int",
|
||||||
|
"unit": "Percentage",
|
||||||
|
"minValue": 0,
|
||||||
|
"maxValue": 100,
|
||||||
|
"defaultValue": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "93310fa3-8237-423b-9062-62e0626e8c70",
|
||||||
|
"name": "chargingState",
|
||||||
|
"displayName": "Charging state",
|
||||||
|
"type": "QString",
|
||||||
|
"possibleValues": ["idle", "charging", "discharging"],
|
||||||
|
"defaultValue": "idle"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "12e0429e-e8ce-48bd-a11c-faaf0bd71856",
|
"id": "12e0429e-e8ce-48bd-a11c-faaf0bd71856",
|
||||||
"name": "modbusInverter",
|
"name": "modbusInverter",
|
||||||
|
|||||||
@ -101,18 +101,8 @@ bool SpeedwireDiscovery::startDiscovery()
|
|||||||
m_multicastRunning = false;
|
m_multicastRunning = false;
|
||||||
m_unicastRunning = false;
|
m_unicastRunning = false;
|
||||||
|
|
||||||
switch(m_deviceType) {
|
startUnicastDiscovery();
|
||||||
case SpeedwireInterface::DeviceTypeMeter:
|
startMulticastDiscovery();
|
||||||
startMulticastDiscovery();
|
|
||||||
break;
|
|
||||||
case SpeedwireInterface::DeviceTypeInverter:
|
|
||||||
startUnicastDiscovery();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
startUnicastDiscovery();
|
|
||||||
startMulticastDiscovery();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -376,17 +366,15 @@ void SpeedwireDiscovery::processDatagram(const QHostAddress &senderAddress, quin
|
|||||||
SpeedwireInverterReply *reply = inverter->sendIdentifyRequest();
|
SpeedwireInverterReply *reply = inverter->sendIdentifyRequest();
|
||||||
qCDebug(dcSma()) << "SpeedwireDiscovery: send identify request to" << senderAddress.toString();
|
qCDebug(dcSma()) << "SpeedwireDiscovery: send identify request to" << senderAddress.toString();
|
||||||
connect(reply, &SpeedwireInverterReply::finished, this, [this, inverter, senderAddress, reply](){
|
connect(reply, &SpeedwireInverterReply::finished, this, [this, inverter, senderAddress, reply](){
|
||||||
qCDebug(dcSma()) << "SpeedwireDiscovery: ############### identify request finished from" << senderAddress.toString() << reply->error();
|
qCDebug(dcSma()) << "SpeedwireDiscovery: identify request finished from" << senderAddress.toString() << reply->error();
|
||||||
|
|
||||||
SpeedwireInverterReply *loginReply = inverter->sendLoginRequest();
|
SpeedwireInverterReply *loginReply = inverter->sendLoginRequest();
|
||||||
qCDebug(dcSma()) << "SpeedwireDiscovery: make login attempt using the default password.";
|
qCDebug(dcSma()) << "SpeedwireDiscovery: make login attempt using the default password.";
|
||||||
connect(loginReply, &SpeedwireInverterReply::finished, this, [loginReply, senderAddress](){
|
connect(loginReply, &SpeedwireInverterReply::finished, this, [loginReply, senderAddress](){
|
||||||
qCDebug(dcSma()) << "SpeedwireDiscovery: ########################## login attempt finished" << senderAddress.toString() << loginReply->error();
|
qCDebug(dcSma()) << "SpeedwireDiscovery: login attempt finished" << senderAddress.toString() << loginReply->error();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
qCWarning(dcSma()) << "SpeedwireDiscovery: Unhandled data received" << datagram.toHex();
|
qCWarning(dcSma()) << "SpeedwireDiscovery: Unhandled data received" << datagram.toHex();
|
||||||
return;
|
return;
|
||||||
@ -418,7 +406,7 @@ void SpeedwireDiscovery::finishDiscovery()
|
|||||||
m_multicastSearchRequestTimer.stop();
|
m_multicastSearchRequestTimer.stop();
|
||||||
|
|
||||||
if (m_multicastSocket) {
|
if (m_multicastSocket) {
|
||||||
if (!m_multicastSocket->leaveMultic astGroup(Speedwire::multicastAddress())) {
|
if (!m_multicastSocket->leaveMulticastGroup(Speedwire::multicastAddress())) {
|
||||||
qCWarning(dcSma()) << "SpeedwireDiscovery: Failed to leave multicast group" << Speedwire::multicastAddress().toString();
|
qCWarning(dcSma()) << "SpeedwireDiscovery: Failed to leave multicast group" << Speedwire::multicastAddress().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -144,6 +144,36 @@ double SpeedwireInverter::powerDcMpp2() const
|
|||||||
return m_powerDcMpp2;
|
return m_powerDcMpp2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SpeedwireInverter::batteryAvailable() const
|
||||||
|
{
|
||||||
|
return m_batteryAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
double SpeedwireInverter::batteryCycles() const
|
||||||
|
{
|
||||||
|
return m_batteryCycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
double SpeedwireInverter::batteryCharge() const
|
||||||
|
{
|
||||||
|
return m_batteryCharge;
|
||||||
|
}
|
||||||
|
|
||||||
|
double SpeedwireInverter::batteryTemperature() const
|
||||||
|
{
|
||||||
|
return m_batteryTemperature;
|
||||||
|
}
|
||||||
|
|
||||||
|
double SpeedwireInverter::batteryCurrent() const
|
||||||
|
{
|
||||||
|
return m_batteryCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
double SpeedwireInverter::batteryVoltage() const
|
||||||
|
{
|
||||||
|
return m_batteryVoltage;
|
||||||
|
}
|
||||||
|
|
||||||
SpeedwireInverterReply *SpeedwireInverter::sendIdentifyRequest()
|
SpeedwireInverterReply *SpeedwireInverter::sendIdentifyRequest()
|
||||||
{
|
{
|
||||||
// Request 534d4100000402a000000001002600106065 09 a0 ffff ffffffff 0000 7d00 52be283a 0000 0000 0000 0180 00020000 000000000000000000000000
|
// Request 534d4100000402a000000001002600106065 09 a0 ffff ffffffff 0000 7d00 52be283a 0000 0000 0000 0180 00020000 000000000000000000000000
|
||||||
@ -968,42 +998,122 @@ void SpeedwireInverter::processGridFrequencyResponse(const QByteArray &response)
|
|||||||
|
|
||||||
void SpeedwireInverter::processBatteryInfoResponse(const QByteArray &response)
|
void SpeedwireInverter::processBatteryInfoResponse(const QByteArray &response)
|
||||||
{
|
{
|
||||||
// 10000000 10000000
|
// Charging
|
||||||
// 01574600 c20cbb61 89130000 89130000 89130000 89130000 010000000
|
// 32000000 34000000
|
||||||
// 0000000
|
// 095b4940 95ed5064 d2000000 d2000000 d2000000 d2000000 01000000
|
||||||
qCDebug(dcSma()) << "Inverter: ################ Process battery info response" << response.toHex();
|
// 095c4900 95ed5064 98530000 98530000 98530000 98530000 01000000
|
||||||
// QDataStream stream(response);
|
// 095d4940 95ed5064 e1010000 e1010000 e1010000 e1010000 01000000
|
||||||
// stream.setByteOrder(QDataStream::LittleEndian);
|
// 00000000
|
||||||
// quint32 firstWord, secondWord;
|
|
||||||
// stream >> firstWord >> secondWord;
|
|
||||||
|
|
||||||
//// // Each line has 7 words
|
// Disacharging
|
||||||
//// quint32 measurementId;
|
// 32000000 34000000
|
||||||
//// quint32 measurementType; // ?
|
// 095b4940 b74e5364 dc000000 dc000000 dc000000 dc000000 01000000
|
||||||
|
// 095c4900 b74e5364 e87b0000 e87b0000 e87b0000 e87b0000 01000000
|
||||||
|
// 095d4940 b74e5364 b6f8ffff b6f8ffff b6f8ffff b6f8ffff 01000000
|
||||||
|
// 00000000
|
||||||
|
qCDebug(dcSma()) << "Inverter: Process battery info response" << response.toHex();
|
||||||
|
|
||||||
////// while (!stream.atEnd()) {
|
QDataStream stream(response);
|
||||||
////// // First row
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
////// stream >> measurementId;
|
quint32 firstWord, secondWord;
|
||||||
|
stream >> firstWord >> secondWord;
|
||||||
|
|
||||||
////// // End of data, we are done
|
// Each line has 7 words
|
||||||
////// if (measurementId == 0)
|
quint32 measurementId;
|
||||||
////// return;
|
quint32 measurementType; // ?
|
||||||
|
|
||||||
////// // Unknown
|
while (!stream.atEnd()) {
|
||||||
////// stream >> measurementType;
|
// First row
|
||||||
|
stream >> measurementId;
|
||||||
|
|
||||||
////// quint8 measurmentNumber = static_cast<quint8>(measurementId & 0xff);
|
// End of data, we are done
|
||||||
////// measurementId = measurementId & 0x00ffff00;
|
if (measurementId == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
////// // Read measurent lines
|
// Unknown
|
||||||
////// if (measurementId == 0x465700 && measurmentNumber == 0x01) {
|
stream >> measurementType;
|
||||||
////// quint32 frequency;
|
|
||||||
////// stream >> frequency;
|
quint8 measurmentNumber = static_cast<quint8>(measurementId & 0xff);
|
||||||
////// m_gridFrequency = readValue(frequency, 100.0);
|
measurementId = measurementId & 0x00ffff00;
|
||||||
////// qCDebug(dcSma()) << "Inverter: Grid frequency" << m_gridFrequency << "Hz";
|
|
||||||
////// readUntilEndOfMeasurement(stream);
|
// Read measurent lines
|
||||||
////// }
|
if (measurementId == 0x495a00) {
|
||||||
////// }
|
quint32 batteryCycles;
|
||||||
|
stream >> batteryCycles;
|
||||||
|
m_batteryCycles = readValue(batteryCycles);
|
||||||
|
qCDebug(dcSma()) << "Battery: Cycle count" << m_batteryCycles;
|
||||||
|
readUntilEndOfMeasurement(stream);
|
||||||
|
} else if (measurementId == 0x495b00) {
|
||||||
|
qint32 batteryTemperature;
|
||||||
|
stream >> batteryTemperature;
|
||||||
|
m_batteryTemperature = readValue(batteryTemperature, 10.0);
|
||||||
|
qCDebug(dcSma()) << "Battery: Temperature" << m_batteryTemperature << "°C";
|
||||||
|
readUntilEndOfMeasurement(stream);
|
||||||
|
} else if (measurementId == 0x495c00) {
|
||||||
|
quint32 batteryVoltage;
|
||||||
|
stream >> batteryVoltage;
|
||||||
|
m_batteryVoltage = readValue(batteryVoltage, 100.0);
|
||||||
|
qCDebug(dcSma()) << "Battery: Voltage" << m_batteryVoltage << "V";
|
||||||
|
readUntilEndOfMeasurement(stream);
|
||||||
|
} else if (measurementId == 0x495d00) {
|
||||||
|
qint32 batteryCurrent;
|
||||||
|
stream >> batteryCurrent;
|
||||||
|
m_batteryCurrent = readValue(batteryCurrent, 1000.0);
|
||||||
|
qCDebug(dcSma()) << "Battery: Current" << m_batteryCurrent << "A";
|
||||||
|
readUntilEndOfMeasurement(stream);
|
||||||
|
} else {
|
||||||
|
quint32 unknwonValue;
|
||||||
|
stream >> unknwonValue;
|
||||||
|
qCDebug(dcSma()) << "Battery: Measurement ID:" << QString("0x%1").arg(measurementId , 0, 16) << "Measurement number:" << QString("0x%1").arg(measurmentNumber, 0, 16);
|
||||||
|
qCDebug(dcSma()) << "Battery: Unknown value:" << QString("0x%1").arg(unknwonValue , 0, 16) << unknwonValue;
|
||||||
|
readUntilEndOfMeasurement(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpeedwireInverter::processBatteryChargeResponse(const QByteArray &response)
|
||||||
|
{
|
||||||
|
qCDebug(dcSma()) << "Inverter: Process battery charge response" << response.toHex();
|
||||||
|
|
||||||
|
QDataStream stream(response);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
quint32 firstWord, secondWord;
|
||||||
|
stream >> firstWord >> secondWord;
|
||||||
|
|
||||||
|
// Each line has 7 words
|
||||||
|
quint32 measurementId;
|
||||||
|
quint32 measurementType; // ?
|
||||||
|
|
||||||
|
while (!stream.atEnd()) {
|
||||||
|
// First row
|
||||||
|
stream >> measurementId;
|
||||||
|
|
||||||
|
// End of data, we are done
|
||||||
|
if (measurementId == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Unknown
|
||||||
|
stream >> measurementType;
|
||||||
|
|
||||||
|
quint8 measurmentNumber = static_cast<quint8>(measurementId & 0xff);
|
||||||
|
measurementId = measurementId & 0x00ffff00;
|
||||||
|
|
||||||
|
// Read measurent lines
|
||||||
|
|
||||||
|
if (measurementId == 0x295a00) {
|
||||||
|
quint32 batteryCharge;
|
||||||
|
stream >> batteryCharge;
|
||||||
|
m_batteryCharge = readValue(batteryCharge);
|
||||||
|
qCDebug(dcSma()) << "Battery: Level" << m_batteryCharge << "%";
|
||||||
|
readUntilEndOfMeasurement(stream);
|
||||||
|
} else {
|
||||||
|
quint32 unknwonValue;
|
||||||
|
stream >> unknwonValue;
|
||||||
|
qCDebug(dcSma()) << "Battery: Measurement ID: " << QString("0x%1").arg(measurementId , 0, 16) << "Measurement number:" << QString("0x%1").arg(measurmentNumber, 0, 16);
|
||||||
|
qCDebug(dcSma()) << "Battery: Unknown value:" << QString("0x%1").arg(unknwonValue , 0, 16) << unknwonValue;
|
||||||
|
readUntilEndOfMeasurement(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpeedwireInverter::processInverterStatusResponse(const QByteArray &response)
|
void SpeedwireInverter::processInverterStatusResponse(const QByteArray &response)
|
||||||
@ -1015,6 +1125,7 @@ void SpeedwireInverter::processInverterStatusResponse(const QByteArray &response
|
|||||||
// TODO:
|
// TODO:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SpeedwireInverter::readUntilEndOfMeasurement(QDataStream &stream)
|
void SpeedwireInverter::readUntilEndOfMeasurement(QDataStream &stream)
|
||||||
{
|
{
|
||||||
// Read until end of line (0x01000000)
|
// Read until end of line (0x01000000)
|
||||||
@ -1044,6 +1155,15 @@ void SpeedwireInverter::setReachable(bool reachable)
|
|||||||
emit reachableChanged(m_reachable);
|
emit reachableChanged(m_reachable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpeedwireInverter::setBatteryAvailable(bool available)
|
||||||
|
{
|
||||||
|
if (m_batteryAvailable == available)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_batteryAvailable = available;
|
||||||
|
emit batteryAvailableChanged(m_batteryAvailable);
|
||||||
|
}
|
||||||
|
|
||||||
void SpeedwireInverter::processData(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &data)
|
void SpeedwireInverter::processData(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &data)
|
||||||
{
|
{
|
||||||
// Note: the interface is already filtering out data from other hosts m_address
|
// Note: the interface is already filtering out data from other hosts m_address
|
||||||
@ -1151,88 +1271,43 @@ void SpeedwireInverter::setState(State state)
|
|||||||
setReachable(false);
|
setReachable(false);
|
||||||
break;
|
break;
|
||||||
case StateInitializing: {
|
case StateInitializing: {
|
||||||
|
// Try to fetch ac power
|
||||||
if (m_modelId == 372) {
|
qCDebug(dcSma()) << "Inverter: Request AC power...";
|
||||||
// Home manager 2.0, no login, just fetch...testing
|
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryAc, 0x00464000, 0x004642ff);
|
||||||
|
connect(reply, &SpeedwireInverterReply::finished, this, [=](){
|
||||||
// ############# TESTING ##########
|
if (reply->error() != SpeedwireInverterReply::ErrorNoError) {
|
||||||
|
if (reply->error() == SpeedwireInverterReply::ErrorTimeout) {
|
||||||
// Query battery info
|
|
||||||
qCDebug(dcSma()) << "Inverter: Request battery info...";
|
|
||||||
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryAc, 0x00491e00, 0x00495dff); // Battery infos
|
|
||||||
connect(reply, &SpeedwireInverterReply::finished, this, [=](){
|
|
||||||
if (reply->error() != SpeedwireInverterReply::ErrorNoError) {
|
|
||||||
qCWarning(dcSma()) << "Inverter: Failed to query data from inverter:" << reply->request().command() << reply->error();
|
qCWarning(dcSma()) << "Inverter: Failed to query data from inverter:" << reply->request().command() << reply->error();
|
||||||
// setState(StateDisconnected);
|
|
||||||
// return;
|
// TODO: try to send identify request and retry 3 times before giving up,
|
||||||
|
// still need to figure out why the inverter stops responding sometimes and how we can
|
||||||
|
// make it communicative again, a reconfugre always fixes this issue...somehow...
|
||||||
|
|
||||||
|
setState(StateDisconnected);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcSma()) << "Inverter: Query request finished successfully" << reply->request().command();
|
// Reachable, but received an inverter error, probably not logged
|
||||||
processBatteryInfoResponse(reply->responsePayload());
|
if (reply->error() == SpeedwireInverterReply::ErrorInverterError) {
|
||||||
|
qCDebug(dcSma()) << "Inverter: Query data request finished with inverter error. Try to login...";
|
||||||
|
setState(StateLogin);
|
||||||
qCDebug(dcSma()) << "Inverter: Request battery SoC...";
|
return;
|
||||||
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryAc, 0x00295A00, 0x00295AFF); // SoC
|
|
||||||
connect(reply, &SpeedwireInverterReply::finished, this, [=](){
|
|
||||||
if (reply->error() != SpeedwireInverterReply::ErrorNoError) {
|
|
||||||
qCWarning(dcSma()) << "Inverter: Failed to query data from inverter:" << reply->request().command() << reply->error();
|
|
||||||
// setState(StateDisconnected);
|
|
||||||
// return;
|
|
||||||
} else {
|
|
||||||
processBatteryInfoResponse(reply->responsePayload());
|
|
||||||
}
|
|
||||||
qCDebug(dcSma()) << "Inverter: Request battery termperature...";
|
|
||||||
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryAc, 0x00491E00, 0x00495DFF); // SoC
|
|
||||||
connect(reply, &SpeedwireInverterReply::finished, this, [=](){
|
|
||||||
if (reply->error() != SpeedwireInverterReply::ErrorNoError) {
|
|
||||||
qCWarning(dcSma()) << "Inverter: Failed to query data from inverter:" << reply->request().command() << reply->error();
|
|
||||||
// setState(StateDisconnected);
|
|
||||||
// return;
|
|
||||||
} else {
|
|
||||||
processBatteryInfoResponse(reply->responsePayload());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Try to fetch ac power
|
|
||||||
qCDebug(dcSma()) << "Inverter: Request AC power...";
|
|
||||||
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryAc, 0x00464000, 0x004642ff);
|
|
||||||
connect(reply, &SpeedwireInverterReply::finished, this, [=](){
|
|
||||||
if (reply->error() != SpeedwireInverterReply::ErrorNoError) {
|
|
||||||
if (reply->error() == SpeedwireInverterReply::ErrorTimeout) {
|
|
||||||
qCWarning(dcSma()) << "Inverter: Failed to query data from inverter:" << reply->request().command() << reply->error();
|
|
||||||
|
|
||||||
// TODO: try to send identify request and retry 3 times before giving up,
|
|
||||||
// still need to figure out why the inverter stops responding sometimes and how we can
|
|
||||||
// make it communicative again, a reconfugre always fixes this issue...somehow...
|
|
||||||
|
|
||||||
setState(StateDisconnected);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reachable, but received an inverter error, probably not logged
|
|
||||||
if (reply->error() == SpeedwireInverterReply::ErrorInverterError) {
|
|
||||||
qCDebug(dcSma()) << "Inverter: Query data request finished with inverter error. Try to login...";
|
|
||||||
setState(StateLogin);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We where able to read data...emit the signal for the setup just incase
|
// We where able to read data...emit the signal for the setup just incase
|
||||||
emit loginFinished(true);
|
emit loginFinished(true);
|
||||||
|
|
||||||
qCDebug(dcSma()) << "Inverter: Query request finished successfully" << reply->request().command();
|
qCDebug(dcSma()) << "Inverter: Query request finished successfully" << reply->request().command();
|
||||||
processAcPowerResponse(reply->responseData());
|
processAcPowerResponse(reply->responseData());
|
||||||
|
|
||||||
if (m_deviceInformationFetched) {
|
|
||||||
setState(StateQueryData);
|
if (m_deviceInformationFetched) {
|
||||||
} else {
|
setState(StateQueryData);
|
||||||
setState(StateGetInformation);
|
} else {
|
||||||
}
|
setState(StateGetInformation);
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case StateLogin: {
|
case StateLogin: {
|
||||||
@ -1296,6 +1371,7 @@ void SpeedwireInverter::setState(State state)
|
|||||||
qCDebug(dcSma()) << "Inverter: Get inverter status request finished successfully" << reply->request().command();
|
qCDebug(dcSma()) << "Inverter: Get inverter status request finished successfully" << reply->request().command();
|
||||||
processInverterStatusResponse(reply->responsePayload());
|
processInverterStatusResponse(reply->responsePayload());
|
||||||
|
|
||||||
|
|
||||||
// Query AC voltage / current
|
// Query AC voltage / current
|
||||||
qCDebug(dcSma()) << "Inverter: Request AC voltage and current...";
|
qCDebug(dcSma()) << "Inverter: Request AC voltage and current...";
|
||||||
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryAc, 0x00464800, 0x004655ff);
|
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryAc, 0x00464800, 0x004655ff);
|
||||||
@ -1309,6 +1385,7 @@ void SpeedwireInverter::setState(State state)
|
|||||||
qCDebug(dcSma()) << "Inverter: Query request finished successfully" << reply->request().command();
|
qCDebug(dcSma()) << "Inverter: Query request finished successfully" << reply->request().command();
|
||||||
processAcVoltageCurrentResponse(reply->responsePayload());
|
processAcVoltageCurrentResponse(reply->responsePayload());
|
||||||
|
|
||||||
|
|
||||||
// Query DC power
|
// Query DC power
|
||||||
qCDebug(dcSma()) << "Inverter: Request DC power...";
|
qCDebug(dcSma()) << "Inverter: Request DC power...";
|
||||||
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryDc, 0x00251e00, 0x00251eff);
|
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryDc, 0x00251e00, 0x00251eff);
|
||||||
@ -1322,6 +1399,7 @@ void SpeedwireInverter::setState(State state)
|
|||||||
qCDebug(dcSma()) << "Inverter: Query request finished successfully" << reply->request().command();
|
qCDebug(dcSma()) << "Inverter: Query request finished successfully" << reply->request().command();
|
||||||
processDcPowerResponse(reply->responsePayload());
|
processDcPowerResponse(reply->responsePayload());
|
||||||
|
|
||||||
|
|
||||||
// Query DC voltage/current
|
// Query DC voltage/current
|
||||||
qCDebug(dcSma()) << "Inverter: Request DC voltage and current...";
|
qCDebug(dcSma()) << "Inverter: Request DC voltage and current...";
|
||||||
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryDc, 0x00451f00, 0x004521ff);
|
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryDc, 0x00451f00, 0x004521ff);
|
||||||
@ -1335,6 +1413,7 @@ void SpeedwireInverter::setState(State state)
|
|||||||
qCDebug(dcSma()) << "Inverter: Query request finished successfully" << reply->request().command();
|
qCDebug(dcSma()) << "Inverter: Query request finished successfully" << reply->request().command();
|
||||||
processDcVoltageCurrentResponse(reply->responsePayload());
|
processDcVoltageCurrentResponse(reply->responsePayload());
|
||||||
|
|
||||||
|
|
||||||
// Query energy production
|
// Query energy production
|
||||||
qCDebug(dcSma()) << "Inverter: Request energy production...";
|
qCDebug(dcSma()) << "Inverter: Request energy production...";
|
||||||
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryEnergy, 0x00260100, 0x002622ff);
|
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryEnergy, 0x00260100, 0x002622ff);
|
||||||
@ -1348,6 +1427,7 @@ void SpeedwireInverter::setState(State state)
|
|||||||
qCDebug(dcSma()) << "Inverter: Query request finished successfully" << reply->request().command();
|
qCDebug(dcSma()) << "Inverter: Query request finished successfully" << reply->request().command();
|
||||||
processEnergyProductionResponse(reply->responsePayload());
|
processEnergyProductionResponse(reply->responsePayload());
|
||||||
|
|
||||||
|
|
||||||
// Query total AC power
|
// Query total AC power
|
||||||
qCDebug(dcSma()) << "Inverter: Request total AC power...";
|
qCDebug(dcSma()) << "Inverter: Request total AC power...";
|
||||||
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryAc, 0x00263f00, 0x00263fff);
|
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryAc, 0x00263f00, 0x00263fff);
|
||||||
@ -1377,7 +1457,39 @@ void SpeedwireInverter::setState(State state)
|
|||||||
|
|
||||||
setReachable(true);
|
setReachable(true);
|
||||||
emit valuesUpdated();
|
emit valuesUpdated();
|
||||||
setState(StateIdle);
|
|
||||||
|
// ############# Optional ##########
|
||||||
|
|
||||||
|
// Query battery info
|
||||||
|
qCDebug(dcSma()) << "Inverter: Request battery info...";
|
||||||
|
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryAc, 0x00491e00, 0x00495dff); // Battery infos
|
||||||
|
connect(reply, &SpeedwireInverterReply::finished, this, [=](){
|
||||||
|
if (reply->error() != SpeedwireInverterReply::ErrorNoError) {
|
||||||
|
qCDebug(dcSma()) << "Inverter: Failed to query battery info from inverter:" << reply->request().command() << reply->error();
|
||||||
|
setBatteryAvailable(false);
|
||||||
|
setState(StateIdle);
|
||||||
|
} else {
|
||||||
|
qCDebug(dcSma()) << "Inverter: Process battery info response" << reply->responsePayload().toHex();
|
||||||
|
processBatteryInfoResponse(reply->responsePayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcSma()) << "Inverter: Request battery charge status...";
|
||||||
|
SpeedwireInverterReply *reply = sendQueryRequest(Speedwire::CommandQueryAc, 0x00295A00, 0x00295AFF); // Battery SoC
|
||||||
|
connect(reply, &SpeedwireInverterReply::finished, this, [=](){
|
||||||
|
if (reply->error() != SpeedwireInverterReply::ErrorNoError) {
|
||||||
|
qCWarning(dcSma()) << "Inverter: Failed to query battery charge status from inverter:" << reply->request().command() << reply->error();
|
||||||
|
setBatteryAvailable(false);
|
||||||
|
setState(StateIdle);
|
||||||
|
} else {
|
||||||
|
qCDebug(dcSma()) << "Inverter: Process battery charge status response" << reply->responsePayload().toHex();
|
||||||
|
processBatteryChargeResponse(reply->responsePayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
setBatteryAvailable(true);
|
||||||
|
emit batteryValuesUpdated();
|
||||||
|
setState(StateIdle);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -94,6 +94,13 @@ public:
|
|||||||
double currentDcMpp1() const;
|
double currentDcMpp1() const;
|
||||||
double currentDcMpp2() const;
|
double currentDcMpp2() const;
|
||||||
|
|
||||||
|
bool batteryAvailable() const;
|
||||||
|
double batteryCycles() const;
|
||||||
|
double batteryCharge() const;
|
||||||
|
double batteryTemperature() const;
|
||||||
|
double batteryCurrent() const;
|
||||||
|
double batteryVoltage() const;
|
||||||
|
|
||||||
// Query methods
|
// Query methods
|
||||||
SpeedwireInverterReply *sendIdentifyRequest();
|
SpeedwireInverterReply *sendIdentifyRequest();
|
||||||
SpeedwireInverterReply *sendLoginRequest(const QString &password = "0000", bool loginAsUser = true);
|
SpeedwireInverterReply *sendLoginRequest(const QString &password = "0000", bool loginAsUser = true);
|
||||||
@ -113,6 +120,8 @@ signals:
|
|||||||
void loginFinished(bool success);
|
void loginFinished(bool success);
|
||||||
void stateChanged(State state);
|
void stateChanged(State state);
|
||||||
void valuesUpdated();
|
void valuesUpdated();
|
||||||
|
void batteryAvailableChanged(bool available);
|
||||||
|
void batteryValuesUpdated();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SpeedwireInterface *m_interface = nullptr;
|
SpeedwireInterface *m_interface = nullptr;
|
||||||
@ -164,6 +173,14 @@ private:
|
|||||||
double m_currentDcMpp1 = 0;
|
double m_currentDcMpp1 = 0;
|
||||||
double m_currentDcMpp2 = 0;
|
double m_currentDcMpp2 = 0;
|
||||||
|
|
||||||
|
bool m_batteryAvailable = false;
|
||||||
|
|
||||||
|
double m_batteryCycles = 0;
|
||||||
|
double m_batteryVoltage = 0;
|
||||||
|
double m_batteryCurrent = 0;
|
||||||
|
double m_batteryCharge = 0;
|
||||||
|
double m_batteryTemperature = 0;
|
||||||
|
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
|
|
||||||
void sendNextReply();
|
void sendNextReply();
|
||||||
@ -187,12 +204,14 @@ private:
|
|||||||
void processEnergyProductionResponse(const QByteArray &response);
|
void processEnergyProductionResponse(const QByteArray &response);
|
||||||
void processGridFrequencyResponse(const QByteArray &response);
|
void processGridFrequencyResponse(const QByteArray &response);
|
||||||
void processBatteryInfoResponse(const QByteArray &response);
|
void processBatteryInfoResponse(const QByteArray &response);
|
||||||
|
void processBatteryChargeResponse(const QByteArray &response);
|
||||||
void processInverterStatusResponse(const QByteArray &response);
|
void processInverterStatusResponse(const QByteArray &response);
|
||||||
|
|
||||||
void readUntilEndOfMeasurement(QDataStream &stream);
|
void readUntilEndOfMeasurement(QDataStream &stream);
|
||||||
double readValue(quint32 value, double divisor = 1.0);
|
double readValue(quint32 value, double divisor = 1.0);
|
||||||
|
|
||||||
void setReachable(bool reachable);
|
void setReachable(bool reachable);
|
||||||
|
void setBatteryAvailable(bool available);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void processData(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &data);
|
void processData(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &data);
|
||||||
|
|||||||
Reference in New Issue
Block a user