SunSpec: Update to networkdevice interface

This commit is contained in:
Simon Stürz 2024-12-19 10:07:08 +01:00
parent 36f9f3c512
commit 2a27534279
5 changed files with 122 additions and 53 deletions

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2023, nymea GmbH * Copyright 2013 - 2024, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
* *
* This file is part of nymea. * This file is part of nymea.
@ -70,12 +70,18 @@ IntegrationPluginSunSpec::IntegrationPluginSunSpec()
void IntegrationPluginSunSpec::init() void IntegrationPluginSunSpec::init()
{ {
// SunSpec connection params // SunSpec connection params
m_connectionPortParamTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionThingPortParamTypeId);
m_connectionPortParamTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionThingPortParamTypeId);
m_connectionMacAddressParamTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionThingMacAddressParamTypeId); m_connectionMacAddressParamTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionThingMacAddressParamTypeId);
m_connectionMacAddressParamTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionThingMacAddressParamTypeId); m_connectionMacAddressParamTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionThingMacAddressParamTypeId);
m_connectionHostNameParamTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionThingHostNameParamTypeId);
m_connectionHostNameParamTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionThingHostNameParamTypeId);
m_connectionAddressParamTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionThingAddressParamTypeId);
m_connectionAddressParamTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionThingAddressParamTypeId);
m_connectionPortParamTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionThingPortParamTypeId);
m_connectionPortParamTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionThingPortParamTypeId);
m_connectionSlaveIdParamTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionThingSlaveIdParamTypeId); m_connectionSlaveIdParamTypeIds.insert(sunspecConnectionThingClassId, sunspecConnectionThingSlaveIdParamTypeId);
m_connectionSlaveIdParamTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionThingSlaveIdParamTypeId); m_connectionSlaveIdParamTypeIds.insert(solarEdgeConnectionThingClassId, solarEdgeConnectionThingSlaveIdParamTypeId);
@ -141,7 +147,7 @@ void IntegrationPluginSunSpec::discoverThings(ThingDiscoveryInfo *info)
SunSpecDiscovery *discovery = new SunSpecDiscovery(hardwareManager()->networkDeviceDiscovery(), slaveIds, byteOrder, info); SunSpecDiscovery *discovery = new SunSpecDiscovery(hardwareManager()->networkDeviceDiscovery(), slaveIds, byteOrder, info);
// Note: we could add here more // Note: we could add here more
connect(discovery, &SunSpecDiscovery::discoveryFinished, info, [=](){ connect(discovery, &SunSpecDiscovery::discoveryFinished, info, [this, info, discovery](){
foreach (const SunSpecDiscovery::Result &result, discovery->results()) { foreach (const SunSpecDiscovery::Result &result, discovery->results()) {
// Extract the manufacturer: we pick the first manufacturer name of the first common model having a manufacturer name for now // Extract the manufacturer: we pick the first manufacturer name of the first common model having a manufacturer name for now
@ -166,6 +172,7 @@ void IntegrationPluginSunSpec::discoverThings(ThingDiscoveryInfo *info)
// Full support of meter, inverter and storage will be provided in the kostal plugin which makes // Full support of meter, inverter and storage will be provided in the kostal plugin which makes
// use of the native modbus communication from kostal. // use of the native modbus communication from kostal.
if (hasManufacturer(result.modelManufacturers, "kostal")) { if (hasManufacturer(result.modelManufacturers, "kostal")) {
qCWarning(dcSunSpec()) << "Skipping Kostal manufacturer on SunSpec. Please use the native kostal integration plugin in order to add it to the system.";
continue; continue;
} }
} }
@ -177,26 +184,40 @@ void IntegrationPluginSunSpec::discoverThings(ThingDiscoveryInfo *info)
title.append("SunSpec connection"); title.append("SunSpec connection");
QString description; QString description;
if (result.networkDeviceInfo.macAddressManufacturer().isEmpty()) { MacAddressInfo macInfo;
description = result.networkDeviceInfo.macAddress(); switch (result.networkDeviceInfo.monitorMode()) {
} else { case NetworkDeviceInfo::MonitorModeMac:
description = result.networkDeviceInfo.macAddress() + " (" + result.networkDeviceInfo.macAddressManufacturer() + ")"; macInfo = result.networkDeviceInfo.macAddressInfos().constFirst();
description = result.networkDeviceInfo.address().toString();
if (!macInfo.vendorName().isEmpty())
description += " - " + result.networkDeviceInfo.macAddressInfos().constFirst().vendorName();
break;
case NetworkDeviceInfo::MonitorModeHostName:
description = result.networkDeviceInfo.hostName();
break;
case NetworkDeviceInfo::MonitorModeIp:
description = "Interface: " + result.networkDeviceInfo.networkInterface().name();
break;
} }
ThingDescriptor descriptor(info->thingClassId(), title, description); ThingDescriptor descriptor(info->thingClassId(), title, description);
// Check if we already have set up this device
Things existingThings = myThings().filterByParam(m_connectionMacAddressParamTypeIds.value(info->thingClassId()), result.networkDeviceInfo.macAddress());
if (existingThings.count() == 1) {
qCDebug(dcSunSpec()) << "This thing already exists in the system." << existingThings.first() << result.networkDeviceInfo;
descriptor.setThingId(existingThings.first()->id());
}
ParamList params; ParamList params;
params << Param(m_connectionMacAddressParamTypeIds.value(info->thingClassId()), result.networkDeviceInfo.thingParamValueMacAddress());
params << Param(m_connectionHostNameParamTypeIds.value(info->thingClassId()), result.networkDeviceInfo.thingParamValueHostName());
params << Param(m_connectionAddressParamTypeIds.value(info->thingClassId()), result.networkDeviceInfo.thingParamValueAddress());
params << Param(m_connectionPortParamTypeIds.value(info->thingClassId()), result.port); params << Param(m_connectionPortParamTypeIds.value(info->thingClassId()), result.port);
params << Param(m_connectionMacAddressParamTypeIds.value(info->thingClassId()), result.networkDeviceInfo.macAddress());
params << Param(m_connectionSlaveIdParamTypeIds.value(info->thingClassId()), result.slaveId); params << Param(m_connectionSlaveIdParamTypeIds.value(info->thingClassId()), result.slaveId);
descriptor.setParams(params); descriptor.setParams(params);
// Check if we already have set up this device
Thing *existingThing = myThings().findByParams(params);
if (existingThing) {
qCDebug(dcSunSpec()) << "This thing already exists in the system:" << result.networkDeviceInfo;
descriptor.setThingId(existingThing->id());
}
info->addThingDescriptor(descriptor); info->addThingDescriptor(descriptor);
} }
@ -213,7 +234,8 @@ void IntegrationPluginSunSpec::setupThing(ThingSetupInfo *info)
qCDebug(dcSunSpec()) << "Setup thing" << thing; qCDebug(dcSunSpec()) << "Setup thing" << thing;
qCDebug(dcSunSpec()) << thing->params(); qCDebug(dcSunSpec()) << thing->params();
if (thing->thingClassId() == sunspecConnectionThingClassId || thing->thingClassId() == solarEdgeConnectionThingClassId) { if (thing->thingClassId() == sunspecConnectionThingClassId ||
thing->thingClassId() == solarEdgeConnectionThingClassId) {
// Handle reconfigure // Handle reconfigure
if (m_sunSpecConnections.contains(thing->id())) { if (m_sunSpecConnections.contains(thing->id())) {
@ -225,16 +247,17 @@ void IntegrationPluginSunSpec::setupThing(ThingSetupInfo *info)
} }
} }
MacAddress macAddress = MacAddress(thing->paramValue(m_connectionMacAddressParamTypeIds.value(thing->thingClassId())).toString());
if (!macAddress.isValid()) { // Create the monitor
qCWarning(dcSunSpec()) << "The configured mac address is not valid" << thing->params(); NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(thing);
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("The MAC address is not known. Please reconfigure the connection.")); if (!monitor) {
qCWarning(dcSunSpec()) << "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; return;
} }
// Create the monitor
NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(macAddress);
m_monitors.insert(thing, monitor); m_monitors.insert(thing, monitor);
QHostAddress address = monitor->networkDeviceInfo().address(); QHostAddress address = monitor->networkDeviceInfo().address();
if (address.isNull() && info->isInitialSetup()) { if (address.isNull() && info->isInitialSetup()) {
qCWarning(dcSunSpec()) << "Cannot set up thing. The host address is not known and this is an initial setup"; qCWarning(dcSunSpec()) << "Cannot set up thing. The host address is not known and this is an initial setup";
@ -305,9 +328,9 @@ void IntegrationPluginSunSpec::setupThing(ThingSetupInfo *info)
} }
} }
} else if (thing->thingClassId() == sunspecThreePhaseInverterThingClassId } else if (thing->thingClassId() == sunspecThreePhaseInverterThingClassId ||
|| thing->thingClassId() == sunspecSplitPhaseInverterThingClassId thing->thingClassId() == sunspecSplitPhaseInverterThingClassId ||
|| thing->thingClassId() == sunspecSinglePhaseInverterThingClassId ) { thing->thingClassId() == sunspecSinglePhaseInverterThingClassId ) {
Thing *thing = info->thing(); Thing *thing = info->thing();
uint modelId = thing->paramValue(m_modelIdParamTypeIds.value(thing->thingClassId())).toInt(); uint modelId = thing->paramValue(m_modelIdParamTypeIds.value(thing->thingClassId())).toInt();
@ -420,9 +443,8 @@ void IntegrationPluginSunSpec::thingRemoved(Thing *thing)
Q_ASSERT_X(false, "thingRemoved", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8()); Q_ASSERT_X(false, "thingRemoved", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
} }
if (m_monitors.contains(thing)) { if (m_monitors.contains(thing))
hardwareManager()->networkDeviceDiscovery()->unregisterMonitor(m_monitors.take(thing)); hardwareManager()->networkDeviceDiscovery()->unregisterMonitor(m_monitors.take(thing));
}
if (myThings().isEmpty()) { if (myThings().isEmpty()) {
qCDebug(dcSunSpec()) << "Stopping refresh timer"; qCDebug(dcSunSpec()) << "Stopping refresh timer";

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2023, nymea GmbH * Copyright 2013 - 2024, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
* *
* This file is part of nymea. * This file is part of nymea.
@ -62,9 +62,10 @@ public:
private: private:
// SunSpec Connection params map // SunSpec Connection params map
QHash<ThingClassId, ParamTypeId> m_connectionIpParamTypeIds;
QHash<ThingClassId, ParamTypeId> m_connectionPortParamTypeIds;
QHash<ThingClassId, ParamTypeId> m_connectionMacAddressParamTypeIds; QHash<ThingClassId, ParamTypeId> m_connectionMacAddressParamTypeIds;
QHash<ThingClassId, ParamTypeId> m_connectionAddressParamTypeIds;
QHash<ThingClassId, ParamTypeId> m_connectionHostNameParamTypeIds;
QHash<ThingClassId, ParamTypeId> m_connectionPortParamTypeIds;
QHash<ThingClassId, ParamTypeId> m_connectionSlaveIdParamTypeIds; QHash<ThingClassId, ParamTypeId> m_connectionSlaveIdParamTypeIds;
// SunSpec thing params map // SunSpec thing params map

View File

@ -40,15 +40,32 @@
"displayName": "SunSpec Generic", "displayName": "SunSpec Generic",
"id": "f51853f3-8815-4cf3-b337-45cda1f3e6d5", "id": "f51853f3-8815-4cf3-b337-45cda1f3e6d5",
"createMethods": [ "Discovery" ], "createMethods": [ "Discovery" ],
"interfaces": ["gateway"], "interfaces": [ "gateway", "networkdevice" ],
"providedInterfaces": [ "solarinverter", "energymeter", "energystorage"], "providedInterfaces": [ "solarinverter", "energymeter", "energystorage"],
"paramTypes": [ "paramTypes": [
{
"id": "3567b389-9d42-48f9-a29b-d18388fb36a1",
"name": "address",
"displayName": "Host address",
"type": "QString",
"inputType": "IPv4Address",
"defaultValue": ""
},
{
"id": "1667b0ed-9a2b-47c6-a01f-690caee55ffa",
"name": "hostName",
"displayName": "Host name",
"type": "QString",
"inputType": "TextLine",
"defaultValue": ""
},
{ {
"id": "f65d6c36-1672-44cb-b52a-62d71837ae67", "id": "f65d6c36-1672-44cb-b52a-62d71837ae67",
"name":"macAddress", "name":"macAddress",
"displayName": "MAC address", "displayName": "MAC address",
"type": "QString", "type": "QString",
"defaultValue": "00:00:00:00:00:00" "inputType": "MacAddress",
"defaultValue": ""
}, },
{ {
"id": "1fa4fc9c-f6be-47c7-928a-bcefc1142eec", "id": "1fa4fc9c-f6be-47c7-928a-bcefc1142eec",
@ -1458,15 +1475,32 @@
"displayName": "SolarEdge", "displayName": "SolarEdge",
"id": "7a92bf65-b443-4491-a012-2bec35eb5bf0", "id": "7a92bf65-b443-4491-a012-2bec35eb5bf0",
"createMethods": [ "Discovery" ], "createMethods": [ "Discovery" ],
"interfaces": ["gateway"], "interfaces": [ "gateway", "networkdevice" ],
"providedInterfaces": [ "solarinverter", "energymeter", "energystorage" ], "providedInterfaces": [ "solarinverter", "energymeter", "energystorage" ],
"paramTypes": [ "paramTypes": [
{
"id": "9c2bafd0-6d56-42e0-8ef3-c4940b4f18b5",
"name": "address",
"displayName": "Host address",
"type": "QString",
"inputType": "IPv4Address",
"defaultValue": ""
},
{
"id": "2e22c369-8476-4908-9cdc-186472f4d472",
"name": "hostName",
"displayName": "Host name",
"type": "QString",
"inputType": "TextLine",
"defaultValue": ""
},
{ {
"id": "bb395c12-54d6-4139-b0a6-e31b28bc4d2e", "id": "bb395c12-54d6-4139-b0a6-e31b28bc4d2e",
"name":"macAddress", "name":"macAddress",
"displayName": "MAC address", "displayName": "MAC address",
"type": "QString", "type": "QString",
"defaultValue": "00:00:00:00:00:00" "inputType": "MacAddress",
"defaultValue": ""
}, },
{ {
"id": "1bcede48-d167-4ced-8f1b-bea6302dd43f", "id": "1bcede48-d167-4ced-8f1b-bea6302dd43f",

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2023, nymea GmbH * Copyright 2013 - 2024, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
* *
* This file is part of nymea. * This file is part of nymea.
@ -65,16 +65,16 @@ void SunSpecDiscovery::startDiscovery()
m_startDateTime = QDateTime::currentDateTime(); m_startDateTime = QDateTime::currentDateTime();
// Imedialty check any new device gets discovered // Imedialty check any new device gets discovered
connect(discoveryReply, &NetworkDeviceDiscoveryReply::networkDeviceInfoAdded, this, &SunSpecDiscovery::checkNetworkDevice); connect(discoveryReply, &NetworkDeviceDiscoveryReply::hostAddressDiscovered, this, &SunSpecDiscovery::checkNetworkDevice);
// Check what might be left on finished // Check what might be left on finished
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, discoveryReply, &NetworkDeviceDiscoveryReply::deleteLater); connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, discoveryReply, &NetworkDeviceDiscoveryReply::deleteLater);
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){ connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [this, discoveryReply](){
qCDebug(dcSunSpec()) << "Discovery: Network discovery finished. Give some time for pending discovery checks to finish..."; qCDebug(dcSunSpec()) << "Discovery: Network discovery finished. Give some time for pending discovery checks to finish...";
m_networkDeviceInfos = discoveryReply->networkDeviceInfos();
// Give the last connections added right before the network discovery finished a chance to check the device... // Give the last connections added right before the network discovery finished a chance to check the device...
QTimer::singleShot(3000, this, [this](){ QTimer::singleShot(3000, this, [this](){
qCDebug(dcSunSpec()) << "Discovery: Grace period timer triggered";
finishDiscovery(); finishDiscovery();
}); });
}); });
@ -121,7 +121,7 @@ void SunSpecDiscovery::testNextConnection(const QHostAddress &address)
connectionTimer->start(); connectionTimer->start();
} }
void SunSpecDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo) void SunSpecDiscovery::checkNetworkDevice(const QHostAddress &address)
{ {
// Create a connection queue for this network device // Create a connection queue for this network device
@ -132,13 +132,13 @@ void SunSpecDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDevice
foreach (quint16 slaveId, m_slaveIds) { foreach (quint16 slaveId, m_slaveIds) {
SunSpecConnection *connection = new SunSpecConnection(networkDeviceInfo.address(), port, slaveId, m_byteOrder, this); SunSpecConnection *connection = new SunSpecConnection(address, port, slaveId, m_byteOrder, this);
connection->setNumberOfRetries(1); connection->setNumberOfRetries(1);
connection->setTimeout(500); connection->setTimeout(500);
m_connections.append(connection); m_connections.append(connection);
connectionQueue.enqueue(connection); connectionQueue.enqueue(connection);
connect(connection, &SunSpecConnection::connectedChanged, this, [=](bool connected){ connect(connection, &SunSpecConnection::connectedChanged, this, [this, connection, connectionQueue, address](bool connected){
if (!connected) { if (!connected) {
// Disconnected ... done with this connection // Disconnected ... done with this connection
cleanupConnection(connection); cleanupConnection(connection);
@ -155,7 +155,9 @@ void SunSpecDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDevice
// Modbus TCP connected, try to discovery sunspec models... // Modbus TCP connected, try to discovery sunspec models...
connect(connection, &SunSpecConnection::discoveryFinished, this, [=](bool success){ connect(connection, &SunSpecConnection::discoveryFinished, this, [=](bool success){
if (!success) { if (!success) {
qCDebug(dcSunSpec()) << "Discovery: SunSpec discovery failed on" << QString("%1:%2").arg(networkDeviceInfo.address().toString()).arg(port) << "slave ID:" << slaveId << "Continue...";; qCDebug(dcSunSpec()) << "Discovery: SunSpec discovery failed on"
<< QString("%1:%2").arg(address.toString()).arg(connection->port())
<< "slave ID:" << connection->slaveId() << "Continue...";
cleanupConnection(connection); cleanupConnection(connection);
return; return;
} }
@ -163,7 +165,7 @@ void SunSpecDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDevice
// Success, we found some sunspec models here, let's read some infomation from the models // Success, we found some sunspec models here, let's read some infomation from the models
Result result; Result result;
result.networkDeviceInfo = networkDeviceInfo; result.address = address;
result.port = connection->port(); result.port = connection->port();
result.slaveId = connection->slaveId(); result.slaveId = connection->slaveId();
@ -186,7 +188,9 @@ void SunSpecDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDevice
// Run SunSpec discovery on connection... // Run SunSpec discovery on connection...
if (!connection->startDiscovery()) { if (!connection->startDiscovery()) {
qCDebug(dcSunSpec()) << "Discovery: Unable to discover SunSpec data on connection" << QString("%1:%2").arg(networkDeviceInfo.address().toString()).arg(port) << "slave ID:" << slaveId << "Continue...";; qCDebug(dcSunSpec()) << "Discovery: Unable to discover SunSpec data on connection"
<< QString("%1:%2").arg(address.toString()).arg(connection->port())
<< "slave ID:" << connection->slaveId() << "Continue...";
cleanupConnection(connection); cleanupConnection(connection);
} }
}); });
@ -194,15 +198,17 @@ void SunSpecDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDevice
// If we get any error...skip this host... // If we get any error...skip this host...
connect(connection->modbusTcpClient(), &QModbusTcpClient::errorOccurred, this, [=](QModbusDevice::Error error){ connect(connection->modbusTcpClient(), &QModbusTcpClient::errorOccurred, this, [=](QModbusDevice::Error error){
if (error != QModbusDevice::NoError) { if (error != QModbusDevice::NoError) {
qCDebug(dcSunSpec()) << "Discovery: Connection error on" << QString("%1:%2").arg(networkDeviceInfo.address().toString()).arg(port) << "slave ID:" << slaveId << "Continue...";; qCDebug(dcSunSpec()) << "Discovery: Connection error on"
<< QString("%1:%2").arg(address.toString()).arg(connection->port())
<< "slave ID:" << connection->slaveId() << "Continue...";
cleanupConnection(connection); cleanupConnection(connection);
} }
}); });
} }
} }
m_pendingConnectionAttempts[networkDeviceInfo.address()] = connectionQueue; m_pendingConnectionAttempts[address] = connectionQueue;
testNextConnection(networkDeviceInfo.address()); testNextConnection(address);
} }
void SunSpecDiscovery::cleanupConnection(SunSpecConnection *connection) void SunSpecDiscovery::cleanupConnection(SunSpecConnection *connection)
@ -223,10 +229,15 @@ void SunSpecDiscovery::finishDiscovery()
{ {
qint64 durationMilliSeconds = QDateTime::currentMSecsSinceEpoch() - m_startDateTime.toMSecsSinceEpoch(); qint64 durationMilliSeconds = QDateTime::currentMSecsSinceEpoch() - m_startDateTime.toMSecsSinceEpoch();
// Fill in all network device infos we have
for (int i = 0; i < m_results.count(); i++)
m_results[i].networkDeviceInfo = m_networkDeviceInfos.get(m_results.at(i).address);
// Cleanup any leftovers...we don't care any more // Cleanup any leftovers...we don't care any more
foreach (SunSpecConnection *connection, m_connections) foreach (SunSpecConnection *connection, m_connections)
cleanupConnection(connection); cleanupConnection(connection);
qCInfo(dcSunSpec()) << "Discovery: Finished the discovery process. Found" << m_results.count() << "SunSpec devices in" << QTime::fromMSecsSinceStartOfDay(durationMilliSeconds).toString("mm:ss.zzz"); qCInfo(dcSunSpec()) << "Discovery: Finished the discovery process. Found" << m_results.count()
<< "SunSpec devices in" << QTime::fromMSecsSinceStartOfDay(durationMilliSeconds).toString("mm:ss.zzz");
emit discoveryFinished(); emit discoveryFinished();
} }

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2023, nymea GmbH * Copyright 2013 - 2024, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
* *
* This file is part of nymea. * This file is part of nymea.
@ -44,6 +44,7 @@ class SunSpecDiscovery : public QObject
public: public:
explicit SunSpecDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, const QList<quint16> &slaveIds, SunSpecDataPoint::ByteOrder byteOrder = SunSpecDataPoint::ByteOrderLittleEndian, QObject *parent = nullptr); explicit SunSpecDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, const QList<quint16> &slaveIds, SunSpecDataPoint::ByteOrder byteOrder = SunSpecDataPoint::ByteOrderLittleEndian, QObject *parent = nullptr);
typedef struct Result { typedef struct Result {
QHostAddress address;
NetworkDeviceInfo networkDeviceInfo; NetworkDeviceInfo networkDeviceInfo;
quint16 port; quint16 port;
quint16 slaveId; quint16 slaveId;
@ -67,13 +68,13 @@ private:
QDateTime m_startDateTime; QDateTime m_startDateTime;
QHash<QHostAddress, QQueue<SunSpecConnection *>> m_pendingConnectionAttempts; QHash<QHostAddress, QQueue<SunSpecConnection *>> m_pendingConnectionAttempts;
QHash<SunSpecConnection *, QTimer *> m_connectionTimers; QHash<SunSpecConnection *, QTimer *> m_connectionTimers;
QList<SunSpecConnection *> m_connections; QList<SunSpecConnection *> m_connections;
NetworkDeviceInfos m_networkDeviceInfos;
QList<Result> m_results; QList<Result> m_results;
void testNextConnection(const QHostAddress &address); void testNextConnection(const QHostAddress &address);
void checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo); void checkNetworkDevice(const QHostAddress &address);
void cleanupConnection(SunSpecConnection *connection); void cleanupConnection(SunSpecConnection *connection);
void finishDiscovery(); void finishDiscovery();