From aad4501245dee09d93281638719a1d19a3df785a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Thu, 1 Jun 2023 13:17:03 +0200 Subject: [PATCH] SMA: Fix data parsing on newer inverters and re-enable battery autocreation --- sma/integrationpluginsma.cpp | 19 +++-------- sma/speedwire/speedwireinverter.cpp | 50 +++++++++++++++++------------ sma/speedwire/speedwireinverter.h | 1 + 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/sma/integrationpluginsma.cpp b/sma/integrationpluginsma.cpp index d1d7b6d..d842ab4 100644 --- a/sma/integrationpluginsma.cpp +++ b/sma/integrationpluginsma.cpp @@ -255,19 +255,9 @@ void IntegrationPluginSma::confirmPairing(ThingPairingInfo *info, const QString return; } - // Init with the default password - QString password; - if (!secret.isEmpty()) { - qCDebug(dcSma()) << "Pairing: Using password" << secret; - password = secret; - } else { - //password = "0000"; - qCDebug(dcSma()) << "Pairing: The given password is empty. Using default password" << password; - } - // Just store details, we'll test the login in setupDevice pluginStorage()->beginGroup(info->thingId().toString()); - pluginStorage()->setValue("password", password); + pluginStorage()->setValue("password", secret); pluginStorage()->endGroup(); info->finish(Thing::ThingErrorNoError); @@ -386,7 +376,7 @@ void IntegrationPluginSma::setupThing(ThingSetupInfo *info) QString password; pluginStorage()->beginGroup(info->thing()->id().toString()); - password = pluginStorage()->value("password", "0000").toString(); + password = pluginStorage()->value("password").toString(); pluginStorage()->endGroup(); // Connection exists only as long info exists @@ -456,9 +446,8 @@ void IntegrationPluginSma::setupThing(ThingSetupInfo *info) // First check if we already set up a battery for this inverter Things childThings = myThings().filterByParentId(thing->id()).filterByThingClassId(speedwireBatteryThingClassId); if (childThings.isEmpty()) { - // FIXME: re-enable autosetup once verified to be working as expected // Autocreate battery - // emit autoThingsAppeared(ThingDescriptors() << ThingDescriptor(speedwireBatteryThingClassId, "SMA Battery", QString(), thing->id())); + emit autoThingsAppeared(ThingDescriptors() << ThingDescriptor(speedwireBatteryThingClassId, "SMA Battery", QString(), thing->id())); } else { // We can only have one battery as a child Thing *batteryThing = childThings.first(); @@ -469,7 +458,7 @@ void IntegrationPluginSma::setupThing(ThingSetupInfo *info) batteryThing->setStateValue(speedwireBatteryVoltageStateTypeId, inverter->batteryVoltage()); batteryThing->setStateValue(speedwireBatteryCurrentStateTypeId, inverter->batteryCurrent()); - double batteryPower = inverter->batteryVoltage() * inverter->batteryCurrent(); // P = U * I + double batteryPower = -1 * inverter->batteryVoltage() * inverter->batteryCurrent(); // P = U * I qCDebug(dcSma()) << "Battery values updated for" << batteryThing->name() << batteryPower << "W"; batteryThing->setStateValue(speedwireBatteryCurrentPowerStateTypeId, batteryPower); if (batteryPower == 0) { diff --git a/sma/speedwire/speedwireinverter.cpp b/sma/speedwire/speedwireinverter.cpp index 0c0e566..7a6039b 100644 --- a/sma/speedwire/speedwireinverter.cpp +++ b/sma/speedwire/speedwireinverter.cpp @@ -632,8 +632,15 @@ void SpeedwireInverter::processAcPowerResponse(const QByteArray &response) // 01 4246 40 77fbba61 23000000 23000000 23000000 23000000 01000000 // 00000000 + + // 0a000000 0c000000 + // 09 4046 40 ec767864 be050000 be050000 be050000 be050000 01000000 + // 09 4146 40 ec767864 c6050000 c6050000 c6050000 c6050000 01000000 + // 09 4246 40 ec767864 c8050000 c8050000 c8050000 c8050000 01000000 + // 00000000 + // 40464001 - qCDebug(dcSma()) << "Inverter: Process AC power query response"; // << response.toHex(); + qCDebug(dcSma()) << "Inverter: Process AC power query response" << response.toHex(); QDataStream stream(response); stream.setByteOrder(QDataStream::LittleEndian); quint32 firstWord, secondWord; @@ -654,23 +661,22 @@ void SpeedwireInverter::processAcPowerResponse(const QByteArray &response) // Unknown stream >> measurementType; - quint8 measurmentNumber = static_cast(measurementId & 0xff); measurementId = measurementId & 0x00ffff00; // Read measurent lines - if (measurementId == 0x464000 && measurmentNumber == 0x01) { + if (measurementId == 0x464000) { quint32 powerAcPhase1; stream >> powerAcPhase1; m_powerAcPhase1 = readValue(powerAcPhase1, 1000.0); qCDebug(dcSma()) << "Inverter: Power AC phase 1" << m_powerAcPhase1 << "W"; readUntilEndOfMeasurement(stream); - } else if (measurementId == 0x464100 && measurmentNumber == 0x01) { + } else if (measurementId == 0x464100) { quint32 powerAcPhase2; stream >> powerAcPhase2; m_powerAcPhase2 = readValue(powerAcPhase2, 1000.0); qCDebug(dcSma()) << "Inverter: Power AC phase 2" << m_powerAcPhase2 << "W"; readUntilEndOfMeasurement(stream); - } else if (measurementId == 0x464200 && measurmentNumber == 0x01) { + } else if (measurementId == 0x464200) { quint32 powerAcPhase3; stream >> powerAcPhase3; m_powerAcPhase3 = readValue(powerAcPhase3, 1000.0); @@ -703,7 +709,7 @@ void SpeedwireInverter::processAcVoltageCurrentResponse(const QByteArray &respon // 01524600 c1f0ba61 00000000 00000000 00000000 00000000 01000000 // 00000000 - qCDebug(dcSma()) << "Inverter: Process AC voltage/current query response"; // << response.toHex(); + qCDebug(dcSma()) << "Inverter: Process AC voltage/current query response" << response.toHex(); QDataStream stream(response); stream.setByteOrder(QDataStream::LittleEndian); quint32 firstWord, secondWord; @@ -724,41 +730,40 @@ void SpeedwireInverter::processAcVoltageCurrentResponse(const QByteArray &respon // Unknown stream >> measurementType; - quint8 measurmentNumber = static_cast(measurementId & 0xff); measurementId = measurementId & 0x00ffff00; // Read measurent lines - if (measurementId == 0x464800 && measurmentNumber == 0x01) { + if (measurementId == 0x464800) { quint32 voltageAcPhase1; stream >> voltageAcPhase1; m_voltageAcPhase1 = readValue(voltageAcPhase1, 100.0); qCDebug(dcSma()) << "Inverter: Voltage AC phase 1" << m_voltageAcPhase1 << "V"; readUntilEndOfMeasurement(stream); - } else if (measurementId == 0x464900 && measurmentNumber == 0x01) { + } else if (measurementId == 0x464900) { quint32 voltageAcPhase2; stream >> voltageAcPhase2; m_voltageAcPhase2 = readValue(voltageAcPhase2, 100.0); qCDebug(dcSma()) << "Inverter: Voltage AC phase 2" << m_voltageAcPhase2 << "V"; readUntilEndOfMeasurement(stream); - } else if (measurementId == 0x464a00 && measurmentNumber == 0x01) { + } else if (measurementId == 0x464a00) { quint32 voltageAcPhase3; stream >> voltageAcPhase3; m_voltageAcPhase3 = readValue(voltageAcPhase3, 100.0); qCDebug(dcSma()) << "Inverter: Voltage AC phase 3" << m_voltageAcPhase3 << "V"; readUntilEndOfMeasurement(stream); - } else if (measurementId == 0x465000 && measurmentNumber == 0x01) { + } else if (measurementId == 0x465000) { quint32 currentAcPhase1; stream >> currentAcPhase1; m_currentAcPhase1 = readValue(currentAcPhase1, 1000.0); qCDebug(dcSma()) << "Inverter: Current AC phase 1" << m_currentAcPhase1 << "A"; readUntilEndOfMeasurement(stream); - } else if (measurementId == 0x465100 && measurmentNumber == 0x01) { + } else if (measurementId == 0x465100) { quint32 currentAcPhase2; stream >> currentAcPhase2; m_currentAcPhase2 = readValue(currentAcPhase2, 1000.0); qCDebug(dcSma()) << "Inverter: Current AC phase 2" << m_currentAcPhase2 << "A"; readUntilEndOfMeasurement(stream); - } else if (measurementId == 0x465200 && measurmentNumber == 0x01) { + } else if (measurementId == 0x465200) { quint32 currentAcPhase3; stream >> currentAcPhase3; m_currentAcPhase3 = readValue(currentAcPhase3, 1000.0); @@ -794,11 +799,10 @@ void SpeedwireInverter::processAcTotalPowerResponse(const QByteArray &response) // Unknown stream >> measurementType; - quint8 measurmentNumber = static_cast(measurementId & 0xff); measurementId = measurementId & 0x00ffff00; // Read measurent lines - if (measurementId == 0x263f00 && measurmentNumber == 0x01) { + if (measurementId == 0x263f00) { quint32 totalAcPower; stream >> totalAcPower; m_totalAcPower = readValue(totalAcPower); @@ -808,7 +812,6 @@ void SpeedwireInverter::processAcTotalPowerResponse(const QByteArray &response) } } - void SpeedwireInverter::processDcPowerResponse(const QByteArray &response) { // No sun @@ -982,11 +985,10 @@ void SpeedwireInverter::processGridFrequencyResponse(const QByteArray &response) // Unknown stream >> measurementType; - quint8 measurmentNumber = static_cast(measurementId & 0xff); measurementId = measurementId & 0x00ffff00; // Read measurent lines - if (measurementId == 0x465700 && measurmentNumber == 0x01) { + if (measurementId == 0x465700) { quint32 frequency; stream >> frequency; m_gridFrequency = readValue(frequency, 100.0); @@ -1059,7 +1061,7 @@ void SpeedwireInverter::processBatteryInfoResponse(const QByteArray &response) qint32 batteryCurrent; stream >> batteryCurrent; m_batteryCurrent = readValue(batteryCurrent, 1000.0); - qCDebug(dcSma()) << "Battery: Current" << m_batteryCurrent << "A"; + qCDebug(dcSma()) << "Battery: Current" << batteryCurrent << m_batteryCurrent << "A"; readUntilEndOfMeasurement(stream); } else { quint32 unknwonValue; @@ -1146,6 +1148,14 @@ double SpeedwireInverter::readValue(quint32 value, double divisor) return value / divisor; } +double SpeedwireInverter::readValue(qint32 value, double divisor) +{ + if (static_cast(value) == 0x80000000 || static_cast(value) == 0xffffffff) + return 0; + + return value / divisor; +} + void SpeedwireInverter::setReachable(bool reachable) { if (m_reachable == reachable) @@ -1299,7 +1309,7 @@ void SpeedwireInverter::setState(State state) emit loginFinished(true); qCDebug(dcSma()) << "Inverter: Query request finished successfully" << reply->request().command(); - processAcPowerResponse(reply->responseData()); + processAcPowerResponse(reply->responsePayload()); if (m_deviceInformationFetched) { diff --git a/sma/speedwire/speedwireinverter.h b/sma/speedwire/speedwireinverter.h index a91a6dd..3843fa8 100644 --- a/sma/speedwire/speedwireinverter.h +++ b/sma/speedwire/speedwireinverter.h @@ -209,6 +209,7 @@ private: void readUntilEndOfMeasurement(QDataStream &stream); double readValue(quint32 value, double divisor = 1.0); + double readValue(qint32 value, double divisor = 1.0); void setReachable(bool reachable); void setBatteryAvailable(bool available);