From c5f3352c3e4fb60786aa75656a0c720869c3c34c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Tue, 18 Jul 2023 14:19:44 +0200 Subject: [PATCH] SMA: Improve speedwire interface handling and sharing --- sma/integrationpluginsma.cpp | 65 ++++---- sma/integrationpluginsma.h | 5 +- sma/speedwire/speedwire.h | 7 + sma/speedwire/speedwirediscovery.cpp | 219 +++------------------------ sma/speedwire/speedwirediscovery.h | 35 +---- sma/speedwire/speedwireinterface.cpp | 214 ++++++++++++++++---------- sma/speedwire/speedwireinterface.h | 43 ++---- sma/speedwire/speedwireinverter.cpp | 32 ++-- sma/speedwire/speedwireinverter.h | 7 +- sma/speedwire/speedwiremeter.cpp | 26 +--- sma/speedwire/speedwiremeter.h | 9 +- 11 files changed, 253 insertions(+), 409 deletions(-) diff --git a/sma/integrationpluginsma.cpp b/sma/integrationpluginsma.cpp index d842ab4..93a82d6 100644 --- a/sma/integrationpluginsma.cpp +++ b/sma/integrationpluginsma.cpp @@ -94,15 +94,15 @@ void IntegrationPluginSma::discoverThings(ThingDiscoveryInfo *info) webBoxDiscovery->startDiscovery(); } else if (info->thingClassId() == speedwireMeterThingClassId) { - - // Note: does not require the network device discovery... - SpeedwireDiscovery *speedwireDiscovery = new SpeedwireDiscovery(hardwareManager()->networkDeviceDiscovery(), getLocalSerialNumber(), info); - if (!speedwireDiscovery->initialize()) { + SpeedwireInterface *speedwireInterface = getSpeedwireInterface(); + if (!speedwireInterface || !speedwireInterface->available()) { qCWarning(dcSma()) << "Could not discovery inverter. The speedwire interface initialization failed."; info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Unable to discover the network.")); return; } + // Note: does not require the network device discovery... + SpeedwireDiscovery *speedwireDiscovery = new SpeedwireDiscovery(hardwareManager()->networkDeviceDiscovery(), speedwireInterface, getLocalSerialNumber(), info); connect(speedwireDiscovery, &SpeedwireDiscovery::discoveryFinished, this, [=](){ qCDebug(dcSma()) << "Speed wire discovery finished."; speedwireDiscovery->deleteLater(); @@ -110,7 +110,7 @@ void IntegrationPluginSma::discoverThings(ThingDiscoveryInfo *info) ThingDescriptors descriptors; foreach (const SpeedwireDiscovery::SpeedwireDiscoveryResult &result, speedwireDiscovery->discoveryResult()) { - if (result.deviceType != SpeedwireInterface::DeviceTypeMeter) + if (result.deviceType != Speedwire::DeviceTypeMeter) continue; if (result.serialNumber == 0) @@ -151,13 +151,14 @@ void IntegrationPluginSma::discoverThings(ThingDiscoveryInfo *info) return; } - SpeedwireDiscovery *speedwireDiscovery = new SpeedwireDiscovery(hardwareManager()->networkDeviceDiscovery(), getLocalSerialNumber(), info); - if (!speedwireDiscovery->initialize()) { + SpeedwireInterface *speedwireInterface = getSpeedwireInterface(); + if (!speedwireInterface || !speedwireInterface->available()) { qCWarning(dcSma()) << "Could not discovery inverter. The speedwire interface initialization failed."; info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Unable to discover the network.")); return; } + SpeedwireDiscovery *speedwireDiscovery = new SpeedwireDiscovery(hardwareManager()->networkDeviceDiscovery(), speedwireInterface, getLocalSerialNumber(), info); connect(speedwireDiscovery, &SpeedwireDiscovery::discoveryFinished, this, [=](){ qCDebug(dcSma()) << "Speed wire discovery finished."; speedwireDiscovery->deleteLater(); @@ -165,7 +166,7 @@ void IntegrationPluginSma::discoverThings(ThingDiscoveryInfo *info) ThingDescriptors descriptors; foreach (const SpeedwireDiscovery::SpeedwireDiscoveryResult &result, speedwireDiscovery->discoveryResult()) { - if (result.deviceType != SpeedwireInterface::DeviceTypeInverter) + if (result.deviceType != Speedwire::DeviceTypeInverter) continue; if (result.serialNumber == 0) @@ -302,9 +303,12 @@ void IntegrationPluginSma::setupThing(ThingSetupInfo *info) } else if (thing->thingClassId() == speedwireMeterThingClassId) { - // Create the multicast interface if not created already. - if (!m_multicastInterface) - m_multicastInterface = new SpeedwireInterface(true, getLocalSerialNumber(), this); + SpeedwireInterface *speedwireInterface = getSpeedwireInterface(); + if (!speedwireInterface || !speedwireInterface->available()) { + qCWarning(dcSma()) << "Could not set up speedwire meter. The speedwire interface is not available."; + info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Unable to communicate with the meter.")); + return; + } quint32 serialNumber = static_cast(thing->paramValue(speedwireMeterThingSerialNumberParamTypeId).toUInt()); quint16 modelId = static_cast(thing->paramValue(speedwireMeterThingModelIdParamTypeId).toUInt()); @@ -313,14 +317,7 @@ void IntegrationPluginSma::setupThing(ThingSetupInfo *info) if (m_speedwireMeters.contains(thing)) m_speedwireMeters.take(thing)->deleteLater(); - SpeedwireMeter *meter = new SpeedwireMeter(m_multicastInterface, modelId, serialNumber, this); - if (!meter->initialize()) { - meter->deleteLater(); - qCWarning(dcSma()) << "Setup failed. Could not initialize meter interface."; - info->finish(Thing::ThingErrorHardwareFailure); - return; - } - + SpeedwireMeter *meter = new SpeedwireMeter(speedwireInterface, modelId, serialNumber, this); connect(meter, &SpeedwireMeter::reachableChanged, thing, [=](bool reachable){ thing->setStateValue(speedwireMeterConnectedStateTypeId, reachable); if (!reachable) { @@ -358,6 +355,9 @@ void IntegrationPluginSma::setupThing(ThingSetupInfo *info) } else if (thing->thingClassId() == speedwireInverterThingClassId) { QHostAddress address = QHostAddress(thing->paramValue(speedwireInverterThingHostParamTypeId).toString()); + + // FIXME: use the monitor here since the IP might change + quint32 serialNumber = static_cast(thing->paramValue(speedwireInverterThingSerialNumberParamTypeId).toUInt()); quint16 modelId = static_cast(thing->paramValue(speedwireInverterThingModelIdParamTypeId).toUInt()); @@ -365,13 +365,7 @@ void IntegrationPluginSma::setupThing(ThingSetupInfo *info) m_speedwireInverters.take(thing)->deleteLater(); } - SpeedwireInverter *inverter = new SpeedwireInverter(address, modelId, serialNumber, this); - if (!inverter->initialize()) { - qCWarning(dcSma()) << "Setup failed. Could not initialize inverter interface."; - info->finish(Thing::ThingErrorHardwareFailure); - return; - } - + SpeedwireInverter *inverter = new SpeedwireInverter(getSpeedwireInterface(), address, modelId, serialNumber, this); qCDebug(dcSma()) << "Inverter: Interface initialized successfully."; QString password; @@ -620,10 +614,12 @@ void IntegrationPluginSma::thingRemoved(Thing *thing) hardwareManager()->networkDeviceDiscovery()->unregisterMonitor(m_monitors.take(thing)); } - if (myThings().filterByThingClassId(speedwireMeterThingClassId).isEmpty() && m_multicastInterface) { + if (myThings().filterByThingClassId(speedwireMeterThingClassId).isEmpty() + && myThings().filterByThingClassId(speedwireInverterThingClassId).isEmpty() + && myThings().filterByThingClassId(speedwireBatteryThingClassId).isEmpty()) { // Delete shared multicast socket... - m_multicastInterface->deleteLater(); - m_multicastInterface = nullptr; + m_speedwireInterface->deleteLater(); + m_speedwireInterface = nullptr; } if (myThings().isEmpty()) { @@ -823,6 +819,17 @@ void IntegrationPluginSma::setupModbusInverterConnection(ThingSetupInfo *info) connection->connectDevice(); } +SpeedwireInterface *IntegrationPluginSma::getSpeedwireInterface() +{ + if (!m_speedwireInterface) + m_speedwireInterface = new SpeedwireInterface(getLocalSerialNumber(), this); + + if (!m_speedwireInterface->available()) + m_speedwireInterface->initialize(); + + return m_speedwireInterface; +} + void IntegrationPluginSma::markSpeedwireMeterAsDisconnected(Thing *thing) { thing->setStateValue(speedwireMeterCurrentPowerPhaseAStateTypeId, 0); diff --git a/sma/integrationpluginsma.h b/sma/integrationpluginsma.h index d0cb9fd..3ffd43b 100644 --- a/sma/integrationpluginsma.h +++ b/sma/integrationpluginsma.h @@ -82,8 +82,9 @@ private: quint32 m_localSerialNumber = 0; - // Shared interface accross meters - SpeedwireInterface *m_multicastInterface = nullptr; + // Shared interface accross all speedwire devices + SpeedwireInterface *m_speedwireInterface = nullptr; + SpeedwireInterface *getSpeedwireInterface(); void markSpeedwireMeterAsDisconnected(Thing *thing); void markSpeedwireInverterAsDisconnected(Thing *thing); diff --git a/sma/speedwire/speedwire.h b/sma/speedwire/speedwire.h index 916a34b..9e63f09 100644 --- a/sma/speedwire/speedwire.h +++ b/sma/speedwire/speedwire.h @@ -41,6 +41,13 @@ class Speedwire { Q_GADGET public: + enum DeviceType { + DeviceTypeUnknown, + DeviceTypeMeter, + DeviceTypeInverter + }; + Q_ENUM(DeviceType) + enum Command { CommandIdentify = 0x00000201, CommandQueryStatus = 0x51800200, diff --git a/sma/speedwire/speedwirediscovery.cpp b/sma/speedwire/speedwirediscovery.cpp index 1392009..023836d 100644 --- a/sma/speedwire/speedwirediscovery.cpp +++ b/sma/speedwire/speedwirediscovery.cpp @@ -30,12 +30,14 @@ #include "speedwirediscovery.h" #include "extern-plugininfo.h" +#include "speedwire.h" #include -SpeedwireDiscovery::SpeedwireDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, quint32 localSerialNumber, QObject *parent) : +SpeedwireDiscovery::SpeedwireDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, SpeedwireInterface *speedwireInterface, quint32 localSerialNumber, QObject *parent) : QObject(parent), m_networkDeviceDiscovery(networkDeviceDiscovery), + m_speedwireInterface(speedwireInterface), m_localSerialNumber(localSerialNumber) { // More details: https://github.com/RalfOGit/libspeedwire/ @@ -45,44 +47,14 @@ SpeedwireDiscovery::SpeedwireDiscovery(NetworkDeviceDiscovery *networkDeviceDisc m_multicastSearchRequestTimer.setInterval(1000); m_multicastSearchRequestTimer.setSingleShot(false); + + connect(m_speedwireInterface, &SpeedwireInterface::dataReceived, this, &SpeedwireDiscovery::processDatagram); connect(&m_multicastSearchRequestTimer, &QTimer::timeout, this, &SpeedwireDiscovery::sendDiscoveryRequest); } SpeedwireDiscovery::~SpeedwireDiscovery() { - if (m_initialized && m_multicastSocket) { - if (!m_multicastSocket->leaveMulticastGroup(Speedwire::multicastAddress())) { - qCWarning(dcSma()) << "SpeedwireDiscovery: Failed to leave multicast group" << Speedwire::multicastAddress().toString(); - } - m_multicastSocket->close(); - } -} - -bool SpeedwireDiscovery::initialize(SpeedwireInterface::DeviceType deviceType) -{ - m_deviceType = deviceType; - switch(deviceType) { - case SpeedwireInterface::DeviceTypeMeter: - m_initialized = setupMulticastSocket(); - break; - case SpeedwireInterface::DeviceTypeInverter: - m_initialized = setupUnicastSocket(); - break; - default: - m_initialized = setupMulticastSocket() && setupUnicastSocket(); - break; - } - - if (m_initialized) - qCDebug(dcSma()) << "SpeedwireDiscovery: Interfaces initialized successfully."; - - return m_initialized; -} - -bool SpeedwireDiscovery::initialized() const -{ - return m_initialized; } bool SpeedwireDiscovery::startDiscovery() @@ -90,20 +62,17 @@ bool SpeedwireDiscovery::startDiscovery() if (discoveryRunning()) return true; - if (!m_initialized) { - qCDebug(dcSma()) << "SpeedwireDiscovery: Failed to start discovery because the socket has not been initialized successfully."; + if (!m_speedwireInterface->available()) { + qCDebug(dcSma()) << "SpeedwireDiscovery: Failed to start discovery because the speedwire interface is not available."; return false; } // Start clean m_results.clear(); m_networkDeviceInfos.clear(); - m_multicastRunning = false; - m_unicastRunning = false; startUnicastDiscovery(); startMulticastDiscovery(); - return true; } @@ -117,49 +86,6 @@ QList SpeedwireDiscovery::discover return m_results; } -bool SpeedwireDiscovery::setupMulticastSocket() -{ - if (m_multicastSocket) - return true; - - m_multicastSocket = new QUdpSocket(this); - connect(m_multicastSocket, &QUdpSocket::readyRead, this, &SpeedwireDiscovery::readPendingDatagramsMulticast); - connect(m_multicastSocket, &QUdpSocket::stateChanged, this, &SpeedwireDiscovery::onSocketStateChanged); - connect(m_multicastSocket, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(onSocketError(QAbstractSocket::SocketError))); - - // Setup multicast socket - if (!m_multicastSocket->bind(QHostAddress::AnyIPv4, Speedwire::port(), QAbstractSocket::ShareAddress | QAbstractSocket::ReuseAddressHint)) { - qCWarning(dcSma()) << "SpeedwireDiscovery: Initialization failed. Could not bind multicast socket to port" << Speedwire::port() << m_multicastSocket->errorString(); - m_multicastSocket->deleteLater(); - m_multicastSocket = nullptr; - return false; - } - - - // Join all available interfaces the multicast group - foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) { - if(interface.isValid() && !interface.flags().testFlag(QNetworkInterface::IsLoopBack) - && interface.flags().testFlag(QNetworkInterface::CanMulticast) - && interface.flags().testFlag(QNetworkInterface::IsRunning)) { - - QList addressEntries = interface.addressEntries(); - for (int i = 0; i < addressEntries.length(); i++) { - - - if (addressEntries.at(i).ip().protocol() == QAbstractSocket::IPv4Protocol) { - if (!m_multicastSocket->joinMulticastGroup(Speedwire::multicastAddress(), interface)) { - qCWarning(dcSma()) << "SpeedwireDiscovery: Could not join multicast group" << Speedwire::multicastAddress().toString() << "on interface" << interface << m_multicastSocket->errorString(); - } else { - qCDebug(dcSma()) << "SpeedwireDiscovery: Joined successfully multicast group on" << interface; - } - } - } - } - } - - return true; -} - void SpeedwireDiscovery::startMulticastDiscovery() { qCDebug(dcSma()) << "SpeedwireDiscovery: Start multicast discovery..."; @@ -170,26 +96,6 @@ void SpeedwireDiscovery::startMulticastDiscovery() sendDiscoveryRequest(); } -bool SpeedwireDiscovery::setupUnicastSocket() -{ - if (m_unicastSocket) - return true; - - m_unicastSocket = new QUdpSocket(this); - connect(m_unicastSocket, &QUdpSocket::readyRead, this, &SpeedwireDiscovery::readPendingDatagramsUnicast); - connect(m_unicastSocket, &QUdpSocket::stateChanged, this, &SpeedwireDiscovery::onSocketStateChanged); - connect(m_unicastSocket, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(onSocketError(QAbstractSocket::SocketError))); - - // Setup unicast socket - if (!m_unicastSocket->bind(QHostAddress::AnyIPv4, Speedwire::port(), QAbstractSocket::ShareAddress | QAbstractSocket::ReuseAddressHint)) { - qCWarning(dcSma()) << "SpeedwireDiscovery: Initialization failed. Could not bind to port" << Speedwire::port() << m_multicastSocket->errorString(); - m_unicastSocket->deleteLater(); - m_unicastSocket = nullptr; - return false; - } - - return true; -} void SpeedwireDiscovery::startUnicastDiscovery() { @@ -218,70 +124,14 @@ void SpeedwireDiscovery::startUnicastDiscovery() void SpeedwireDiscovery::sendUnicastDiscoveryRequest(const QHostAddress &targetHostAddress) { - if (m_unicastSocket->writeDatagram(Speedwire::pingRequest(Speedwire::sourceModelId(), m_localSerialNumber), targetHostAddress, Speedwire::port()) < 0) { - qCWarning(dcSma()) << "SpeedwireDiscovery: Failed to send unicast discovery datagram to address" << targetHostAddress.toString(); - return; - } - - qCDebug(dcSma()) << "SpeedwireDiscovery: Sent successfully the discovery request to unicast address" << targetHostAddress.toString(); + qCDebug(dcSma()) << "SpeedwireDiscovery: Sent discovery request to unicast address" << targetHostAddress.toString(); + m_speedwireInterface->sendDataUnicast(targetHostAddress, Speedwire::pingRequest(Speedwire::sourceModelId(), m_localSerialNumber)); } -void SpeedwireDiscovery::readPendingDatagramsMulticast() +void SpeedwireDiscovery::processDatagram(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &datagram, bool multicast) { - QUdpSocket *socket = qobject_cast(sender()); + Q_UNUSED(multicast) - QByteArray datagram; - QHostAddress senderAddress; - quint16 senderPort; - - while (socket->hasPendingDatagrams()) { - datagram.resize(socket->pendingDatagramSize()); - socket->readDatagram(datagram.data(), datagram.size(), &senderAddress, &senderPort); - - // Ignore our own requests - if (QNetworkInterface::allAddresses().contains(senderAddress)) - continue; - - qCDebug(dcSma()) << "SpeedwireDiscovery: Received multicast data from" << QString("%1:%2").arg(senderAddress.toString()).arg(senderPort); - qCDebug(dcSma()) << "SpeedwireDiscovery: " << datagram.toHex(); - processDatagram(senderAddress, senderPort, datagram); - } -} - -void SpeedwireDiscovery::readPendingDatagramsUnicast() -{ - QUdpSocket *socket = qobject_cast(sender()); - - QByteArray datagram; - QHostAddress senderAddress; - quint16 senderPort; - - while (socket->hasPendingDatagrams()) { - datagram.resize(socket->pendingDatagramSize()); - socket->readDatagram(datagram.data(), datagram.size(), &senderAddress, &senderPort); - - // Ignore our own requests - if (QNetworkInterface::allAddresses().contains(senderAddress)) - continue; - - qCDebug(dcSma()) << "SpeedwireDiscovery: Received unicast data from" << QString("%1:%2").arg(senderAddress.toString()).arg(senderPort); - qCDebug(dcSma()) << "SpeedwireDiscovery: " << datagram.toHex(); - processDatagram(senderAddress, senderPort, datagram); - } -} - -void SpeedwireDiscovery::onSocketError(QAbstractSocket::SocketError error) -{ - qCDebug(dcSma()) << "SpeedwireDiscovery: Socket error" << error; -} - -void SpeedwireDiscovery::onSocketStateChanged(QAbstractSocket::SocketState socketState) -{ - qCDebug(dcSma()) << "SpeedwireDiscovery: Socket state changed" << socketState; -} - -void SpeedwireDiscovery::processDatagram(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &datagram) -{ // Check min size of SMA datagrams if (datagram.size() < 18) { qCDebug(dcSma()) << "SpeedwireDiscovery: Received datagram is to short to be a SMA speedwire message. Ignoring data..."; @@ -324,7 +174,7 @@ void SpeedwireDiscovery::processDatagram(const QHostAddress &senderAddress, quin if (!m_resultMeters.contains(senderAddress)) { SpeedwireDiscoveryResult result; result.address = senderAddress; - result.deviceType = SpeedwireInterface::DeviceTypeMeter; + result.deviceType = Speedwire::DeviceTypeMeter; m_resultMeters.insert(senderAddress, result); } @@ -342,7 +192,7 @@ void SpeedwireDiscovery::processDatagram(const QHostAddress &senderAddress, quin if (!m_resultInverters.contains(senderAddress)) { SpeedwireDiscoveryResult result; result.address = senderAddress; - result.deviceType = SpeedwireInterface::DeviceTypeInverter; + result.deviceType = Speedwire::DeviceTypeInverter; m_resultInverters.insert(senderAddress, result); } @@ -359,20 +209,20 @@ void SpeedwireDiscovery::processDatagram(const QHostAddress &senderAddress, quin if (m_inverters.contains(senderAddress)) { inverter = m_inverters.value(senderAddress); } else { - inverter = new SpeedwireInverter(senderAddress, Speedwire::sourceModelId(), m_localSerialNumber, this); + inverter = new SpeedwireInverter(m_speedwireInterface, senderAddress, Speedwire::sourceModelId(), m_localSerialNumber, this); m_inverters.insert(senderAddress, inverter); } SpeedwireInverterReply *reply = inverter->sendIdentifyRequest(); - qCDebug(dcSma()) << "SpeedwireDiscovery: send identify request to" << senderAddress.toString(); - connect(reply, &SpeedwireInverterReply::finished, this, [this, inverter, senderAddress, reply](){ - qCDebug(dcSma()) << "SpeedwireDiscovery: identify request finished from" << senderAddress.toString() << reply->error(); + qCDebug(dcSma()) << "SpeedwireDiscovery: Send identify request to" << senderAddress.toString(); + connect(reply, &SpeedwireInverterReply::finished, this, [/*this, inverter,*/ senderAddress, reply](){ + qCDebug(dcSma()) << "SpeedwireDiscovery: Identify request finished from" << senderAddress.toString() << reply->error(); - SpeedwireInverterReply *loginReply = inverter->sendLoginRequest(); - qCDebug(dcSma()) << "SpeedwireDiscovery: make login attempt using the default password."; - connect(loginReply, &SpeedwireInverterReply::finished, this, [loginReply, senderAddress](){ - qCDebug(dcSma()) << "SpeedwireDiscovery: login attempt finished" << senderAddress.toString() << loginReply->error(); - }); +// SpeedwireInverterReply *loginReply = inverter->sendLoginRequest(); +// qCDebug(dcSma()) << "SpeedwireDiscovery: make login attempt using the default password."; +// connect(loginReply, &SpeedwireInverterReply::finished, this, [loginReply, senderAddress](){ +// qCDebug(dcSma()) << "SpeedwireDiscovery: login attempt finished" << senderAddress.toString() << loginReply->error(); +// }); }); } else { @@ -383,12 +233,8 @@ void SpeedwireDiscovery::processDatagram(const QHostAddress &senderAddress, quin void SpeedwireDiscovery::sendDiscoveryRequest() { - if (m_multicastSocket->writeDatagram(Speedwire::discoveryDatagramMulticast(), Speedwire::multicastAddress(), Speedwire::port()) < 0) { - qCWarning(dcSma()) << "SpeedwireDiscovery: Failed to send discovery datagram to multicast address" << Speedwire::multicastAddress().toString(); - return; - } - - qCDebug(dcSma()) << "SpeedwireDiscovery: Sent successfully the discovery request to multicast address" << Speedwire::multicastAddress().toString(); + qCDebug(dcSma()) << "SpeedwireDiscovery: Sent discovery request to multicast address" << Speedwire::multicastAddress().toString(); + m_speedwireInterface->sendDataMulticast(Speedwire::discoveryDatagramMulticast()); } void SpeedwireDiscovery::evaluateDiscoveryFinished() @@ -405,23 +251,6 @@ void SpeedwireDiscovery::finishDiscovery() qCDebug(dcSma()) << "SpeedwireDiscovery: Discovey finished. Found" << m_results.count() << "SMA devices in the network"; m_multicastSearchRequestTimer.stop(); - if (m_multicastSocket) { - if (!m_multicastSocket->leaveMulticastGroup(Speedwire::multicastAddress())) { - qCWarning(dcSma()) << "SpeedwireDiscovery: Failed to leave multicast group" << Speedwire::multicastAddress().toString(); - } - - m_multicastSocket->close(); - m_multicastSocket->deleteLater(); - m_multicastSocket = nullptr; - } - - if (m_unicastSocket) { - m_unicastSocket->close(); - m_unicastSocket->deleteLater(); - m_unicastSocket = nullptr; - } - - foreach (const SpeedwireDiscoveryResult &result, m_results) { qCDebug(dcSma()) << "SpeedwireDiscovery: ============================================"; qCDebug(dcSma()) << "SpeedwireDiscovery: Device type:" << result.deviceType; diff --git a/sma/speedwire/speedwirediscovery.h b/sma/speedwire/speedwirediscovery.h index 9c461b5..d9ef586 100644 --- a/sma/speedwire/speedwirediscovery.h +++ b/sma/speedwire/speedwirediscovery.h @@ -48,17 +48,14 @@ public: typedef struct SpeedwireDiscoveryResult { QHostAddress address; NetworkDeviceInfo networkDeviceInfo; - SpeedwireInterface::DeviceType deviceType = SpeedwireInterface::DeviceTypeUnknown; + Speedwire::DeviceType deviceType = Speedwire::DeviceTypeUnknown; quint16 modelId = 0; quint32 serialNumber = 0; } SpeedwireDiscoveryResult; - explicit SpeedwireDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, quint32 localSerialNumber, QObject *parent = nullptr); + explicit SpeedwireDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, SpeedwireInterface *speedwireInterface, quint32 localSerialNumber, QObject *parent = nullptr); ~SpeedwireDiscovery(); - bool initialize(SpeedwireInterface::DeviceType deviceType = SpeedwireInterface::DeviceTypeUnknown); - bool initialized() const; - bool startDiscovery(); bool discoveryRunning() const; @@ -69,11 +66,8 @@ signals: private: NetworkDeviceDiscovery *m_networkDeviceDiscovery = nullptr; - SpeedwireInterface::DeviceType m_deviceType = SpeedwireInterface::DeviceTypeUnknown; - QUdpSocket *m_multicastSocket = nullptr; - QUdpSocket *m_unicastSocket = nullptr; + SpeedwireInterface *m_speedwireInterface = nullptr; quint32 m_localSerialNumber = 0; - bool m_initialized = false; // Discovery QTimer m_multicastSearchRequestTimer; @@ -81,34 +75,21 @@ private: QList m_results; QHash m_resultMeters; QHash m_resultInverters; + bool m_unicastRunning = false; + bool m_multicastRunning = false; QHash m_inverters; - - bool m_multicastRunning = false; - bool m_unicastRunning = false; - - bool setupMulticastSocket(); - void startMulticastDiscovery(); - - bool setupUnicastSocket(); - void startUnicastDiscovery(); - void sendUnicastDiscoveryRequest(const QHostAddress &targetHostAddress); private slots: - void readPendingDatagramsMulticast(); - void readPendingDatagramsUnicast(); - void onSocketError(QAbstractSocket::SocketError error); - void onSocketStateChanged(QAbstractSocket::SocketState socketState); + void startUnicastDiscovery(); + void startMulticastDiscovery(); - void processDatagram(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &datagram); + void processDatagram(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &datagram, bool multicast); void sendDiscoveryRequest(); - void evaluateDiscoveryFinished(); - void finishDiscovery(); - }; #endif // SPEEDWIREDISCOVERY_H diff --git a/sma/speedwire/speedwireinterface.cpp b/sma/speedwire/speedwireinterface.cpp index 323c10f..08ae14e 100644 --- a/sma/speedwire/speedwireinterface.cpp +++ b/sma/speedwire/speedwireinterface.cpp @@ -31,74 +31,117 @@ #include "speedwireinterface.h" #include "extern-plugininfo.h" -SpeedwireInterface::SpeedwireInterface(bool multicast, quint32 sourceSerialNumber, QObject *parent) : +#include + +SpeedwireInterface::SpeedwireInterface(quint32 sourceSerialNumber, QObject *parent) : QObject(parent), - m_multicast(multicast), m_sourceSerialNumber(sourceSerialNumber) { + m_unicast = new QUdpSocket(this); + connect(m_unicast, &QUdpSocket::readyRead, this, [=](){ + QByteArray datagram; + QHostAddress senderAddress; + quint16 senderPort; - m_socket = new QUdpSocket(this); - connect(m_socket, &QUdpSocket::readyRead, this, &SpeedwireInterface::readPendingDatagrams); - connect(m_socket, &QUdpSocket::stateChanged, this, &SpeedwireInterface::onSocketStateChanged); - connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(onSocketError(QAbstractSocket::SocketError))); + while (m_unicast->hasPendingDatagrams()) { + datagram.resize(m_unicast->pendingDatagramSize()); + m_unicast->readDatagram(datagram.data(), datagram.size(), &senderAddress, &senderPort); + + qCDebug(dcSma()).noquote() << "SpeedwireInterface: Unicast socket received data from" << QString("%1:%2").arg(senderAddress.toString()).arg(senderPort); + qCDebug(dcSma()) << "SpeedwireInterface: " << datagram.toHex(); + emit dataReceived(senderAddress, senderPort, datagram, false); + } + }); + + connect(m_unicast, &QUdpSocket::stateChanged, this, [=](QAbstractSocket::SocketState socketState){ + qCDebug(dcSma()) << "SpeedwireInterface: Unicast socket state changed" << socketState; + }); + + connect(m_unicast, static_cast(&QAbstractSocket::error), this, [=](QAbstractSocket::SocketError error){ + qCWarning(dcSma()) << "SpeedwireInterface: Unicast socket error occurred" << error << m_unicast->errorString(); + }); + + + m_multicast = new QUdpSocket(this); + connect(m_multicast, &QUdpSocket::readyRead, this, [=](){ + QByteArray datagram; + QHostAddress senderAddress; + quint16 senderPort; + + while (m_multicast->hasPendingDatagrams()) { + datagram.resize(m_multicast->pendingDatagramSize()); + m_multicast->readDatagram(datagram.data(), datagram.size(), &senderAddress, &senderPort); + + qCDebug(dcSma()).noquote() << "SpeedwireInterface: Multicast socket received data from" << QString("%1:%2").arg(senderAddress.toString()).arg(senderPort); + //qCDebug(dcSma()) << "SpeedwireInterface: " << datagram.toHex(); + emit dataReceived(senderAddress, senderPort, datagram, true); + } + }); + + connect(m_multicast, &QUdpSocket::stateChanged, this, [=](QAbstractSocket::SocketState socketState){ + qCDebug(dcSma()) << "SpeedwireInterface: Multicast socket state changed" << socketState; + }); + connect(m_multicast, static_cast(&QAbstractSocket::error), this, [=](QAbstractSocket::SocketError error){ + qCWarning(dcSma()) << "SpeedwireInterface: Multicast socket error occurred" << error << m_multicast->errorString(); + }); + + if (initialize()) { + qCDebug(dcSma()) << "SpeedwireInterface: Initialized sucessfully unicast and multicast interface."; + } else { + qCWarning(dcSma()) << "SpeedwireInterface: Failed to initialize."; + } } SpeedwireInterface::~SpeedwireInterface() { - deinitialize(); -} + if (m_unicast) + m_unicast->close(); -bool SpeedwireInterface::initialize(const QHostAddress &address) -{ - if (m_initialized && !m_multicast) { - qCWarning(dcSma()) << "Try to initialize an already initialized speed wire interface. Please deinitialize() before calling this method again."; - return false; - } - - // If already initialized and multicast, nothing could have changed...done here - if (m_initialized && m_multicast) - return true; - - - if (!m_socket->bind(QHostAddress::AnyIPv4, Speedwire::port(), QAbstractSocket::ShareAddress | QAbstractSocket::ReuseAddressHint)) { - qCWarning(dcSma()) << "SpeedwireInterface: Initialization failed. Could not bind to port" << Speedwire::port(); - return false; - } - - if (m_multicast && !m_socket->joinMulticastGroup(Speedwire::multicastAddress())) { - qCWarning(dcSma()) << "SpeedwireInterface: Initialization failed. Could not join multicast group" << Speedwire::multicastAddress().toString() << m_socket->errorString(); - return false; - } - - qCDebug(dcSma()) << "SpeedwireInterface: Interface initialized successfully for" << address.toString() << (m_multicast ? "multicast" : "unicast"); - m_address = address; - m_initialized = true; - return m_initialized; -} - -void SpeedwireInterface::deinitialize() -{ - if (m_initialized) { - if (m_multicast) { - if (!m_socket->leaveMulticastGroup(Speedwire::multicastAddress())) { - qCWarning(dcSma()) << "SpeedwireInterface: Failed to leave multicast group" << Speedwire::multicastAddress().toString(); - } + if (m_multicast) { + if (!m_multicast->leaveMulticastGroup(Speedwire::multicastAddress())) { + qCWarning(dcSma()) << "SpeedwireInterface: Failed to leave multicast group" << Speedwire::multicastAddress().toString(); } - m_address = QHostAddress(); - m_socket->close(); - m_initialized = false; + m_multicast->close(); } } -bool SpeedwireInterface::multicast() const +bool SpeedwireInterface::available() const { - return m_multicast; + return m_available; } -bool SpeedwireInterface::initialized() const +void SpeedwireInterface::reconfigureMulticastGroup() { - return m_initialized; + qCDebug(dcSma()) << "Reconfigure multicast interfaces"; + if (m_multicast->joinMulticastGroup(Speedwire::multicastAddress())) { + qCDebug(dcSma()) << "SpeedwireInterface: Joined successfully multicast group" << Speedwire::multicastAddress().toString(); + } else { + qCWarning(dcSma()) << "SpeedwireInterface: Failed to join multicast group" << Speedwire::multicastAddress().toString() << m_multicast->errorString() << "Retrying in 5 seconds..."; + // FIXME: It would probably be better to monitor the network interfaces and re-join if necessary + QTimer::singleShot(5000, this, &SpeedwireInterface::reconfigureMulticastGroup); + } + + // foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) { + // if(interface.isValid() && !interface.flags().testFlag(QNetworkInterface::IsLoopBack) + // && interface.flags().testFlag(QNetworkInterface::CanMulticast) + // && interface.flags().testFlag(QNetworkInterface::IsRunning)) { + + // QList addressEntries = interface.addressEntries(); + // for (int i = 0; i < addressEntries.length(); i++) { + // if (addressEntries.at(i).ip().protocol() == QAbstractSocket::IPv4Protocol) { + + // if (!m_multicast->joinMulticastGroup(Speedwire::multicastAddress(), interface)) { + // qCWarning(dcSma()) << "SpeedwireInterface: Could not join multicast group" << Speedwire::multicastAddress().toString() << "on interface" << interface << m_multicast->errorString(); + // } else { + // qCDebug(dcSma()) << "SpeedwireInterface: Joined successfully multicast group" << Speedwire::multicastAddress().toString() << "on interface" << interface ; + // } + // } + // } + // } + // } + + // qCDebug(dcSma()) << "Multicast outgoing interface" << m_multicast->multicastInterface(); } quint32 SpeedwireInterface::sourceSerialNumber() const @@ -106,40 +149,53 @@ quint32 SpeedwireInterface::sourceSerialNumber() const return m_sourceSerialNumber; } -void SpeedwireInterface::sendData(const QByteArray &data) +bool SpeedwireInterface::initialize() { - qCDebug(dcSma()) << "SpeedwireInterface: -->" << m_address.toString() << Speedwire::port() << data.toHex(); - if (m_socket->writeDatagram(data, m_address, Speedwire::port()) < 0) { - qCWarning(dcSma()) << "SpeedwireInterface: failed to send data" << m_socket->errorString(); + bool success = true; + if (m_unicast->state() != QUdpSocket::BoundState) { + m_unicast->close(); + if (!m_unicast->bind(QHostAddress::AnyIPv4, Speedwire::port(), QAbstractSocket::ShareAddress | QAbstractSocket::ReuseAddressHint)) { + qCWarning(dcSma()) << "SpeedwireInterface: Unicast socket could not be bound to port" << Speedwire::port(); + success = false; + } + } + + if (m_multicast->state() != QUdpSocket::BoundState) { + if (!m_multicast->bind(QHostAddress::AnyIPv4, Speedwire::port(), QAbstractSocket::ShareAddress | QAbstractSocket::ReuseAddressHint)) { + qCWarning(dcSma()) << "SpeedwireInterface: Unicast socket could not be bound to port" << Speedwire::port(); + success = false; + } + } + + + reconfigureMulticastGroup(); + m_available = success; + return success; +} + +void SpeedwireInterface::sendDataUnicast(const QHostAddress &address, const QByteArray &data) +{ + qCDebug(dcSma()) << "SpeedwireInterface: Unicast -->" << address.toString() << Speedwire::port() << data.toHex(); + + if (!m_unicast) { + qCWarning(dcSma()) << "SpeedwireInterface: Failed to send unicast data, the socket is not available"; + return; + } + + if (m_unicast->writeDatagram(data, address, Speedwire::port()) < 0) { + qCWarning(dcSma()) << "SpeedwireInterface: Failed to send unicast data to" << address.toString() << m_unicast->errorString(); } } -void SpeedwireInterface::readPendingDatagrams() +void SpeedwireInterface::sendDataMulticast(const QByteArray &data) { - QByteArray datagram; - QHostAddress senderAddress; - quint16 senderPort; + qCDebug(dcSma()) << "SpeedwireInterface: Multicast -->" << Speedwire::multicastAddress().toString() << Speedwire::port() << data.toHex(); + if (!m_multicast) { + qCWarning(dcSma()) << "SpeedwireInterface: Failed to send multicast data, the socket is not available"; + return; + } - while (m_socket->hasPendingDatagrams()) { - datagram.resize(m_socket->pendingDatagramSize()); - m_socket->readDatagram(datagram.data(), datagram.size(), &senderAddress, &senderPort); - - // Process only data coming from our target address if there is any - if (!m_address.isNull() && senderAddress != m_address) - continue; - - qCDebug(dcSma()) << "SpeedwireInterface: Received data from" << QString("%1:%2").arg(senderAddress.toString()).arg(senderPort); - //qCDebug(dcSma()) << "SpeedwireInterface: " << datagram.toHex(); - emit dataReceived(senderAddress, senderPort, datagram); + if (m_multicast->writeDatagram(data, Speedwire::multicastAddress(), Speedwire::port()) < 0) { + qCWarning(dcSma()) << "SpeedwireInterface: Failed to send multicast data to" << Speedwire::multicastAddress().toString() << m_multicast->errorString(); } } - -void SpeedwireInterface::onSocketError(QAbstractSocket::SocketError error) -{ - qCDebug(dcSma()) << "SpeedwireInterface: Socket error" << error; -} - -void SpeedwireInterface::onSocketStateChanged(QAbstractSocket::SocketState socketState) -{ - qCDebug(dcSma()) << "SpeedwireInterface: Socket state changed" << socketState; -} diff --git a/sma/speedwire/speedwireinterface.h b/sma/speedwire/speedwireinterface.h index 2730334..566e4aa 100644 --- a/sma/speedwire/speedwireinterface.h +++ b/sma/speedwire/speedwireinterface.h @@ -34,6 +34,7 @@ #include #include #include +#include #include "speedwire.h" @@ -41,46 +42,32 @@ class SpeedwireInterface : public QObject { Q_OBJECT public: - enum DeviceType { - DeviceTypeUnknown, - DeviceTypeMeter, - DeviceTypeInverter - }; - Q_ENUM(DeviceType) - explicit SpeedwireInterface(bool multicast, quint32 sourceSerialNumber, QObject *parent = nullptr); + explicit SpeedwireInterface(quint32 sourceSerialNumber, QObject *parent = nullptr); ~SpeedwireInterface(); - bool initialize(const QHostAddress &address = QHostAddress()); - void deinitialize(); + bool available() const; - bool multicast() const; - - bool initialized() const; - - quint16 sourceModelId() const; quint32 sourceSerialNumber() const; + bool initialize(); + public slots: - void sendData(const QByteArray &data); + void sendDataUnicast(const QHostAddress &address, const QByteArray &data); + void sendDataMulticast(const QByteArray &data); signals: - void dataReceived(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &data); - -private: - QUdpSocket *m_socket = nullptr; - QHostAddress m_address; - bool m_multicast = false; - bool m_initialized = false; - - // Requester - quint32 m_sourceSerialNumber = 0; + void dataReceived(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &data, bool multicast = false); private slots: - void readPendingDatagrams(); - void onSocketError(QAbstractSocket::SocketError error); - void onSocketStateChanged(QAbstractSocket::SocketState socketState); + void reconfigureMulticastGroup(); +private: + QUdpSocket *m_unicast = nullptr; + QUdpSocket *m_multicast = nullptr; + quint32 m_sourceSerialNumber = 0; + bool m_available = false; + QTimer m_multicastReconfigureationTimer; }; diff --git a/sma/speedwire/speedwireinverter.cpp b/sma/speedwire/speedwireinverter.cpp index 7a6039b..6296e20 100644 --- a/sma/speedwire/speedwireinverter.cpp +++ b/sma/speedwire/speedwireinverter.cpp @@ -33,25 +33,15 @@ #include -SpeedwireInverter::SpeedwireInverter(const QHostAddress &address, quint16 modelId, quint32 serialNumber, QObject *parent) : +SpeedwireInverter::SpeedwireInverter(SpeedwireInterface *speedwireInterface, const QHostAddress &address, quint16 modelId, quint32 serialNumber, QObject *parent) : QObject(parent), + m_speedwireInterface(speedwireInterface), m_address(address), m_modelId(modelId), m_serialNumber(serialNumber) { qCDebug(dcSma()) << "Inverter: setup interface on" << m_address.toString(); - m_interface = new SpeedwireInterface(false, serialNumber, this); - connect(m_interface, &SpeedwireInterface::dataReceived, this, &SpeedwireInverter::processData); -} - -bool SpeedwireInverter::initialize() -{ - return m_interface->initialize(m_address); -} - -bool SpeedwireInverter::initialized() const -{ - return m_interface->initialized(); + connect(m_speedwireInterface, &SpeedwireInterface::dataReceived, this, &SpeedwireInverter::processData); } SpeedwireInverter::State SpeedwireInverter::state() const @@ -270,7 +260,7 @@ SpeedwireInverterReply *SpeedwireInverter::sendLogoutRequest() // Source stream << Speedwire::sourceModelId(); - stream << m_interface->sourceSerialNumber(); + stream << m_speedwireInterface->sourceSerialNumber(); stream << static_cast(0x0300); stream << static_cast(0); @@ -413,7 +403,7 @@ void SpeedwireInverter::sendNextReply() // Pick the next reply and send request m_currentReply = m_replyQueue.dequeue(); qCDebug(dcSma()) << "Inverter: --> Sending" << m_currentReply->request().command() << "packet ID:" << m_currentReply->request().packetId(); - m_interface->sendData(m_currentReply->request().requestData()); + m_speedwireInterface->sendDataUnicast(m_address, m_currentReply->request().requestData()); m_currentReply->startWaiting(); } @@ -489,7 +479,7 @@ void SpeedwireInverter::buildPacket(QDataStream &stream, quint32 command, quint1 // Destination Ctrl stream << static_cast(0x0100); // Source - stream << Speedwire::sourceModelId() << m_interface->sourceSerialNumber(); + stream << Speedwire::sourceModelId() << m_speedwireInterface->sourceSerialNumber(); // Destination Ctrl stream << static_cast(0x0100); @@ -1176,10 +1166,12 @@ void SpeedwireInverter::setBatteryAvailable(bool available) void SpeedwireInverter::processData(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &data) { - // Note: the interface is already filtering out data from other hosts m_address - Q_UNUSED(senderAddress) Q_UNUSED(senderPort) + // Process only data coming from our target address if there is any + if (!m_address.isNull() && senderAddress != m_address) + return; + if (data.size() < 18) { qCDebug(dcSma()) << "Inverter: The received datagram is to short to be a SMA speedwire message. Ignoring data..."; return; @@ -1193,7 +1185,7 @@ void SpeedwireInverter::processData(const QHostAddress &senderAddress, quint16 s } if (header.protocolId != Speedwire::ProtocolIdInverter) { - qCWarning(dcSma()) << "Inverter: Received datagram from different protocol" << header.protocolId << "Ignoring data..."; + //qCWarning(dcSma()) << "Inverter: Received datagram from different protocol" << header.protocolId << "Ignoring data..."; return; } @@ -1478,6 +1470,7 @@ void SpeedwireInverter::setState(State state) qCDebug(dcSma()) << "Inverter: Failed to query battery info from inverter:" << reply->request().command() << reply->error(); setBatteryAvailable(false); setState(StateIdle); + return; } else { qCDebug(dcSma()) << "Inverter: Process battery info response" << reply->responsePayload().toHex(); processBatteryInfoResponse(reply->responsePayload()); @@ -1490,6 +1483,7 @@ void SpeedwireInverter::setState(State state) qCWarning(dcSma()) << "Inverter: Failed to query battery charge status from inverter:" << reply->request().command() << reply->error(); setBatteryAvailable(false); setState(StateIdle); + return; } else { qCDebug(dcSma()) << "Inverter: Process battery charge status response" << reply->responsePayload().toHex(); processBatteryChargeResponse(reply->responsePayload()); diff --git a/sma/speedwire/speedwireinverter.h b/sma/speedwire/speedwireinverter.h index 3843fa8..b6b0ed6 100644 --- a/sma/speedwire/speedwireinverter.h +++ b/sma/speedwire/speedwireinverter.h @@ -54,10 +54,7 @@ public: }; Q_ENUM(State) - explicit SpeedwireInverter(const QHostAddress &address, quint16 modelId, quint32 serialNumber, QObject *parent = nullptr); - - bool initialize(); - bool initialized() const; + explicit SpeedwireInverter(SpeedwireInterface *speedwireInterface, const QHostAddress &address, quint16 modelId, quint32 serialNumber, QObject *parent = nullptr); State state() const; @@ -124,7 +121,7 @@ signals: void batteryValuesUpdated(); private: - SpeedwireInterface *m_interface = nullptr; + SpeedwireInterface *m_speedwireInterface = nullptr; QHostAddress m_address; QString m_password; diff --git a/sma/speedwire/speedwiremeter.cpp b/sma/speedwire/speedwiremeter.cpp index f90354b..03b167f 100644 --- a/sma/speedwire/speedwiremeter.cpp +++ b/sma/speedwire/speedwiremeter.cpp @@ -33,13 +33,13 @@ #include "sma.h" -SpeedwireMeter::SpeedwireMeter(SpeedwireInterface *multicastInterface, quint16 modelId, quint32 serialNumber, QObject *parent) : +SpeedwireMeter::SpeedwireMeter(SpeedwireInterface *speedwireInterface, quint16 modelId, quint32 serialNumber, QObject *parent) : QObject(parent), - m_interface(multicastInterface), + m_speedwireInterface(speedwireInterface), m_modelId(modelId), m_serialNumber(serialNumber) { - connect(m_interface, &SpeedwireInterface::dataReceived, this, &SpeedwireMeter::processData); + connect(m_speedwireInterface, &SpeedwireInterface::dataReceived, this, &SpeedwireMeter::processData); // Reachable timestamp m_timer.setInterval(5000); @@ -47,20 +47,6 @@ SpeedwireMeter::SpeedwireMeter(SpeedwireInterface *multicastInterface, quint16 m connect(&m_timer, &QTimer::timeout, this, &SpeedwireMeter::evaluateReachable); } -bool SpeedwireMeter::initialize() -{ - bool initSuccess = m_interface->initialize(); - if (initSuccess) - m_timer.start(); - - return initSuccess; -} - -bool SpeedwireMeter::initialized() const -{ - return m_interface->initialized(); -} - bool SpeedwireMeter::reachable() const { return m_reachable; @@ -186,8 +172,10 @@ void SpeedwireMeter::evaluateReachable() } } -void SpeedwireMeter::processData(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &data) +void SpeedwireMeter::processData(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &data, bool multicast) { + Q_UNUSED(multicast) + QDataStream stream(data); stream.setByteOrder(QDataStream::BigEndian); @@ -220,7 +208,7 @@ void SpeedwireMeter::processData(const QHostAddress &senderAddress, quint16 send qCDebug(dcSma()) << "Meter: ======================= Meter measurements"; quint32 timestamp; stream >> timestamp; - qCDebug(dcSma()) << "Meter: Timestamp:" << timestamp << QDateTime::fromMSecsSinceEpoch(timestamp * 1000); + qCDebug(dcSma()) << "Meter: Timestamp:" << timestamp << QDateTime::fromMSecsSinceEpoch(static_cast(timestamp) * 1000); // Obis data //00 01 04 00 00000000 00 01 08 00 0000002139122910 00 02 04 00 00004415 00 02 08 00 0000001575a137d8 00 03 04 00 00000000 00 03 08 00 00000003debed0e8 00040400000017c6000408000000001008c2070000090400000000000009080000000027c77bed20000a04000000481d000a08000000001722823410000d0400000003b00015040000000000001508000000000d1e1e0e3000160400000015120016080000000006c5a2d8b800170400000000000017080000000001bd6f680000180400000007990018080000000004def712b8001d040000000000001d08000000000eeefaafd0001e040000001666001e0800000000074b38bf88001f040000000a300020040000037bcb00210400000003ad0029040000000000002908000000000a9b1afec8002a040000001a81002a08000000000803e62b88002b040000000000002b080000000001511459b8002c0400000006d5002c0800000000052c8455b80031040000000000003108000000000cf83b37100032040000001b5f0032080000000008a6e257f80033040000000c3f003404000003747900350400000003c8003d040000000000003d08000000000a53d0ba08003e040000001482003e080000000007800fd188003f040000000000003f080000000001185820c8004004000000095800400800000000064563b1900045040000000000004508000000000d26d3eae0004604000000168900460800000000082b4fc5a80047040000000a440048040000037ed1004904000000038e90000000 01020852 00000000 diff --git a/sma/speedwire/speedwiremeter.h b/sma/speedwire/speedwiremeter.h index e689c02..f1fe0c1 100644 --- a/sma/speedwire/speedwiremeter.h +++ b/sma/speedwire/speedwiremeter.h @@ -41,10 +41,7 @@ class SpeedwireMeter : public QObject { Q_OBJECT public: - explicit SpeedwireMeter(SpeedwireInterface *multicastInterface, quint16 modelId, quint32 serialNumber, QObject *parent = nullptr); - - bool initialize(); - bool initialized() const; + explicit SpeedwireMeter(SpeedwireInterface *speedwireInterface, quint16 modelId, quint32 serialNumber, QObject *parent = nullptr); bool reachable() const; @@ -79,7 +76,7 @@ signals: void valuesUpdated(); private: - SpeedwireInterface *m_interface = nullptr; + SpeedwireInterface *m_speedwireInterface = nullptr; QHostAddress m_address; bool m_initialized = false; quint16 m_modelId = 0; @@ -118,7 +115,7 @@ private: private slots: void evaluateReachable(); - void processData(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &data); + void processData(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &data, bool multicast); };