From 2a2955fb3e912b05431c8a506b4f7532e5dcb9d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Wed, 18 Dec 2024 16:04:56 +0100 Subject: [PATCH] Sungrow: Update to networkdevice interface --- sungrow/integrationpluginsungrow.cpp | 32 ++++++++++++++------------- sungrow/integrationpluginsungrow.json | 18 ++++++++++++++- sungrow/sungrowdiscovery.cpp | 29 ++++++++++++++---------- sungrow/sungrowdiscovery.h | 4 +++- 4 files changed, 54 insertions(+), 29 deletions(-) diff --git a/sungrow/integrationpluginsungrow.cpp b/sungrow/integrationpluginsungrow.cpp index 5fe2cb16..c508b3c3 100644 --- a/sungrow/integrationpluginsungrow.cpp +++ b/sungrow/integrationpluginsungrow.cpp @@ -50,7 +50,6 @@ void IntegrationPluginSungrow::discoverThings(ThingDiscoveryInfo *info) // Create a discovery with the info as parent for auto deleting the object once the discovery info is done SungrowDiscovery *discovery = new SungrowDiscovery(hardwareManager()->networkDeviceDiscovery(), m_modbusTcpPort, m_modbusSlaveAddress, info); - connect(discovery, &SungrowDiscovery::discoveryFinished, discovery, &SungrowDiscovery::deleteLater); connect(discovery, &SungrowDiscovery::discoveryFinished, info, [=](){ foreach (const SungrowDiscovery::SungrowDiscoveryResult &result, discovery->discoveryResults()) { QString title = "Sungrow " + QString::number(result.nominalOutputPower) + "kW Inverter"; @@ -58,19 +57,22 @@ void IntegrationPluginSungrow::discoverThings(ThingDiscoveryInfo *info) if (!result.serialNumber.isEmpty()) title.append(" " + result.serialNumber); - ThingDescriptor descriptor(sungrowInverterTcpThingClassId, title, result.networkDeviceInfo.address().toString() + " " + result.networkDeviceInfo.macAddress()); + ThingDescriptor descriptor(sungrowInverterTcpThingClassId, title, result.networkDeviceInfo.address().toString()); qCInfo(dcSungrow()) << "Discovered:" << descriptor.title() << descriptor.description(); + ParamList params; + params << Param(sungrowInverterTcpThingMacAddressParamTypeId, result.networkDeviceInfo.thingParamValueMacAddress()); + params << Param(sungrowInverterTcpThingHostNameParamTypeId, result.networkDeviceInfo.thingParamValueHostName()); + params << Param(sungrowInverterTcpThingAddressParamTypeId, result.networkDeviceInfo.thingParamValueAddress()); + descriptor.setParams(params); + // Check if we already have set up this device - Things existingThings = myThings().filterByParam(sungrowInverterTcpThingMacAddressParamTypeId, result.networkDeviceInfo.macAddress()); - if (existingThings.count() == 1) { - qCDebug(dcSungrow()) << "This Sungrow inverter already exists in the system:" << result.networkDeviceInfo; - descriptor.setThingId(existingThings.first()->id()); + Thing *existingThing = myThings().findByParams(params); + if (existingThing) { + qCDebug(dcSungrow()) << "This thing already exists in the system:" << result.networkDeviceInfo; + descriptor.setThingId(existingThing->id()); } - ParamList params; - params << Param(sungrowInverterTcpThingMacAddressParamTypeId, result.networkDeviceInfo.macAddress()); - descriptor.setParams(params); info->addThingDescriptor(descriptor); } @@ -97,16 +99,16 @@ void IntegrationPluginSungrow::setupThing(ThingSetupInfo *info) } } - MacAddress macAddress = MacAddress(thing->paramValue(sungrowInverterTcpThingMacAddressParamTypeId).toString()); - if (!macAddress.isValid()) { - qCWarning(dcSungrow()) << "The configured MAC address is not valid" << thing->params(); - info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("The MAC address is not known. Please reconfigure this inverter.")); + // Create the monitor + NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(thing); + if (!monitor) { + qCWarning(dcSungrow()) << "Unable to register monitor with the given params" << thing->params(); + info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("Unable to set up the connection with this configuration, please reconfigure the connection.")); return; } - // Create the monitor - NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(macAddress); m_monitors.insert(thing, monitor); + connect(info, &ThingSetupInfo::aborted, monitor, [=](){ // Clean up in case the setup gets aborted if (m_monitors.contains(thing)) { diff --git a/sungrow/integrationpluginsungrow.json b/sungrow/integrationpluginsungrow.json index 8a894d03..33175bf7 100644 --- a/sungrow/integrationpluginsungrow.json +++ b/sungrow/integrationpluginsungrow.json @@ -14,9 +14,25 @@ "id": "59cb2da4-da07-11ee-adea-7397f8a9afe9", "createMethods": ["discovery"], "discoveryType": "weak", - "interfaces": ["solarinverter", "connectable"], + "interfaces": ["solarinverter", "connectable", "networkdevice"], "providedInterfaces": [ "energymeter", "energystorage"], "paramTypes": [ + { + "id": "311c0038-0134-4d91-878d-57526c3eec11", + "name": "address", + "displayName": "Host address", + "type": "QString", + "inputType": "IPv4Address", + "defaultValue": "" + }, + { + "id": "6676fcea-1f3a-4241-ae03-18dae96c5d8d", + "name": "hostName", + "displayName": "Host name", + "type": "QString", + "inputType": "TextLine", + "defaultValue": "" + }, { "id": "62137142-da07-11ee-9522-2f74f3b1fc5d", "name":"macAddress", diff --git a/sungrow/sungrowdiscovery.cpp b/sungrow/sungrowdiscovery.cpp index 1d1888ef..d4ee9d29 100644 --- a/sungrow/sungrowdiscovery.cpp +++ b/sungrow/sungrowdiscovery.cpp @@ -46,10 +46,11 @@ void SungrowDiscovery::startDiscovery() m_startDateTime = QDateTime::currentDateTime(); NetworkDeviceDiscoveryReply *discoveryReply = m_networkDeviceDiscovery->discover(); - connect(discoveryReply, &NetworkDeviceDiscoveryReply::networkDeviceInfoAdded, this, &SungrowDiscovery::checkNetworkDevice); + connect(discoveryReply, &NetworkDeviceDiscoveryReply::hostAddressDiscovered, this, &SungrowDiscovery::checkNetworkDevice); connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, discoveryReply, &NetworkDeviceDiscoveryReply::deleteLater); connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=] () { qCDebug(dcSungrow()) << "Discovery: Network discovery finished. Found" << discoveryReply->networkDeviceInfos().count() << "network devices"; + m_networkDeviceInfos = discoveryReply->networkDeviceInfos(); // Give the last connections added right before the network discovery finished a chance to check the device... QTimer::singleShot(3000, this, [this] () { @@ -64,15 +65,15 @@ QList SungrowDiscovery::discoveryResul return m_discoveryResults; } -void SungrowDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo) +void SungrowDiscovery::checkNetworkDevice(const QHostAddress &address) { /* Create a Sungrow connection and try to initialize it. * Only if initialized successfully and all information have been fetched correctly from * the device we can assume this is what we are locking for (ip, port, modbus address, correct registers). */ - qCDebug(dcSungrow()) << "Creating Sungrow Modbus TCP connection for" << networkDeviceInfo.address() << "Port:" << m_port << "Slave Address" << m_modbusAddress; - SungrowModbusTcpConnection *connection = new SungrowModbusTcpConnection(networkDeviceInfo.address(), m_port, m_modbusAddress, this); + qCDebug(dcSungrow()) << "Creating Sungrow Modbus TCP connection for" << address << "Port:" << m_port << "Slave Address" << m_modbusAddress; + SungrowModbusTcpConnection *connection = new SungrowModbusTcpConnection(address, m_port, m_modbusAddress, this); connection->modbusTcpMaster()->setTimeout(5000); connection->modbusTcpMaster()->setNumberOfRetries(0); m_connections.append(connection); @@ -87,12 +88,12 @@ void SungrowDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDevice connect(connection, &SungrowModbusTcpConnection::initializationFinished, this, [=](bool success){ if (!success) { - qCDebug(dcSungrow()) << "Discovery: Initialization failed on" << networkDeviceInfo.address().toString() << "Continue..."; + qCDebug(dcSungrow()) << "Discovery: Initialization failed on" << address.toString() << "Continue..."; cleanupConnection(connection); return; } - qCDebug(dcSungrow()) << "Discovery: Initialized successfully" << networkDeviceInfo << connection->serialNumber(); + qCDebug(dcSungrow()) << "Discovery: Initialized successfully" << address.toString() << connection->serialNumber(); qCDebug(dcSungrow()) << " - Protocol number:" << connection->protocolNumber(); qCDebug(dcSungrow()) << " - Protocol version:" << connection->protocolVersion(); qCDebug(dcSungrow()) << " - ARM software version:" << connection->armSoftwareVersion(); @@ -100,7 +101,7 @@ void SungrowDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDevice if (connection->deviceTypeCode() >= 0xd00 && connection->deviceTypeCode() <= 0xeff) { SungrowDiscoveryResult result; - result.networkDeviceInfo = networkDeviceInfo; + result.address = address; result.serialNumber = connection->serialNumber(); result.nominalOutputPower = connection->nominalOutputPower(); result.deviceType = connection->deviceTypeCode(); @@ -110,9 +111,9 @@ void SungrowDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDevice connection->disconnectDevice(); }); - qCDebug(dcSungrow()) << "Discovery: The host" << networkDeviceInfo << "is reachable. Starting with initialization."; + qCDebug(dcSungrow()) << "Discovery: The host" << address << "is reachable. Starting with initialization."; if (!connection->initialize()) { - qCDebug(dcSungrow()) << "Discovery: Unable to initialize connection on" << networkDeviceInfo.address().toString() << "Continue..."; + qCDebug(dcSungrow()) << "Discovery: Unable to initialize connection on" << address.toString() << "Continue..."; cleanupConnection(connection); } }); @@ -120,21 +121,21 @@ void SungrowDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDevice // In case of an error skip the host connect(connection->modbusTcpMaster(), &ModbusTcpMaster::connectionStateChanged, this, [=](bool connected){ if (connected) { - qCDebug(dcSungrow()) << "Discovery: Connected with" << networkDeviceInfo.address().toString() << m_port; + qCDebug(dcSungrow()) << "Discovery: Connected with" << address.toString() << m_port; } }); // In case of an error skip the host connect(connection->modbusTcpMaster(), &ModbusTcpMaster::connectionErrorOccurred, this, [=](QModbusDevice::Error error){ if (error != QModbusDevice::NoError) { - qCDebug(dcSungrow()) << "Discovery: Connection error on" << networkDeviceInfo.address().toString() << "Continue..."; + qCDebug(dcSungrow()) << "Discovery: Connection error on" << address.toString() << "Continue..."; cleanupConnection(connection); } }); // If the reachability check failed skip the host connect(connection, &SungrowModbusTcpConnection::checkReachabilityFailed, this, [=](){ - qCDebug(dcSungrow()) << "Discovery: Check reachability failed on" << networkDeviceInfo.address().toString() << "Continue..."; + qCDebug(dcSungrow()) << "Discovery: Check reachability failed on" << address.toString() << "Continue..."; cleanupConnection(connection); }); @@ -153,6 +154,10 @@ void SungrowDiscovery::finishDiscovery() { qint64 durationMilliSeconds = QDateTime::currentMSecsSinceEpoch() - m_startDateTime.toMSecsSinceEpoch(); + // Fill in all network device infos we have + for (int i = 0; i < m_discoveryResults.count(); i++) + m_discoveryResults[i].networkDeviceInfo = m_networkDeviceInfos.get(m_discoveryResults.at(i).address); + foreach (SungrowModbusTcpConnection *connection, m_connections) cleanupConnection(connection); diff --git a/sungrow/sungrowdiscovery.h b/sungrow/sungrowdiscovery.h index 6dc497df..6cdf2ca0 100644 --- a/sungrow/sungrowdiscovery.h +++ b/sungrow/sungrowdiscovery.h @@ -45,6 +45,7 @@ class SungrowDiscovery : public QObject explicit SungrowDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, quint16 port = 502, quint16 modbusAddress = 1, QObject *parent = nullptr); typedef struct SungrowDiscoveryResult { QString serialNumber; + QHostAddress address; NetworkDeviceInfo networkDeviceInfo; float nominalOutputPower; int deviceType; @@ -64,10 +65,11 @@ class SungrowDiscovery : public QObject QDateTime m_startDateTime; + NetworkDeviceInfos m_networkDeviceInfos; QList m_connections; QList m_discoveryResults; - void checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo); + void checkNetworkDevice(const QHostAddress &address); void cleanupConnection(SungrowModbusTcpConnection *connection); void finishDiscovery();