Skip to content

Commit

Permalink
Fronius: Update to networkdevice interface
Browse files Browse the repository at this point in the history
  • Loading branch information
t-mon committed Dec 11, 2024
1 parent a35312b commit 1aea8bd
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 63 deletions.
34 changes: 19 additions & 15 deletions fronius/froniusdiscovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ FroniusDiscovery::FroniusDiscovery(NetworkAccessManager *networkManager, Network
qCDebug(dcFronius()) << "Discovery: Grace period timer triggered.";
finishDiscovery();
});

}

void FroniusDiscovery::startDiscovery()
Expand All @@ -55,10 +54,14 @@ void FroniusDiscovery::startDiscovery()
m_startDateTime = QDateTime::currentDateTime();

NetworkDeviceDiscoveryReply *discoveryReply = m_networkDeviceDiscovery->discover();
connect(discoveryReply, &NetworkDeviceDiscoveryReply::networkDeviceInfoAdded, this, &FroniusDiscovery::checkNetworkDevice);
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){
connect(discoveryReply, &NetworkDeviceDiscoveryReply::hostAddressDiscovered, this, &FroniusDiscovery::checkHostAddress);
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [this, discoveryReply](){

m_networkDeviceInfos = discoveryReply->networkDeviceInfos();

qCDebug(dcFronius()) << "Discovery: Network discovery finished. Found" << discoveryReply->networkDeviceInfos().count() << "network devices";
m_gracePeriodTimer.start();

discoveryReply->deleteLater();
});
}
Expand All @@ -68,21 +71,21 @@ QList<NetworkDeviceInfo> FroniusDiscovery::discoveryResults() const
return m_discoveryResults;
}

void FroniusDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo)
void FroniusDiscovery::checkHostAddress(const QHostAddress &address)
{
qCDebug(dcFronius()) << "Discovery: Checking network device:" << networkDeviceInfo;
qCDebug(dcFronius()) << "Discovery: Checking host address" << address.toString();

FroniusSolarConnection *connection = new FroniusSolarConnection(m_networkManager, networkDeviceInfo.address(), this);
FroniusSolarConnection *connection = new FroniusSolarConnection(m_networkManager, address, this);
m_connections.append(connection);

FroniusNetworkReply *reply = connection->getVersion();
connect(reply, &FroniusNetworkReply::finished, this, [=] {
QByteArray data = reply->networkReply()->readAll();
if (reply->networkReply()->error() != QNetworkReply::NoError) {
if (reply->networkReply()->error() == QNetworkReply::ContentNotFoundError) {
qCInfo(dcFronius()) << "Discovery: The device on" << networkDeviceInfo.address().toString() << "does not reply to our requests. Please verify that the Fronius Solar API is enabled on the device.";
qCInfo(dcFronius()) << "Discovery: The device on" << address.toString() << "does not reply to our requests. Please verify that the Fronius Solar API is enabled on the device.";
} else {
qCDebug(dcFronius()) << "Discovery: Reply finished with error on" << networkDeviceInfo.address().toString() << reply->networkReply()->errorString();
qCDebug(dcFronius()) << "Discovery: Reply finished with error on" << address.toString() << reply->networkReply()->errorString();
}
cleanupConnection(connection);
return;
Expand All @@ -91,14 +94,14 @@ void FroniusDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDevice
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError) {
qCDebug(dcFronius()) << "Discovery: Failed to parse JSON data from" << networkDeviceInfo.address().toString() << ":" << error.errorString() << data;
qCDebug(dcFronius()) << "Discovery: Failed to parse JSON data from" << address.toString() << ":" << error.errorString() << data;
cleanupConnection(connection);
return;
}

QVariantMap versionResponseMap = jsonDoc.toVariant().toMap();
if (!versionResponseMap.contains("CompatibilityRange")) {
qCDebug(dcFronius()) << "Discovery: Unexpected JSON reply from" << networkDeviceInfo.address().toString() << "Probably not a Fronius device.";
qCDebug(dcFronius()) << "Discovery: Unexpected JSON reply from" << address.toString() << "Probably not a Fronius device.";
cleanupConnection(connection);
return;
}
Expand All @@ -109,7 +112,7 @@ void FroniusDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDevice
qCWarning(dcFronius()) << "Discovery: The Fronius data logger has a version which is known to have a broken JSON API firmware.";
}

m_discoveryResults.append(networkDeviceInfo);
m_discoveredAddresses.append(address);
cleanupConnection(connection);
});
}
Expand All @@ -124,14 +127,15 @@ void FroniusDiscovery::finishDiscovery()
{
qint64 durationMilliSeconds = QDateTime::currentMSecsSinceEpoch() - m_startDateTime.toMSecsSinceEpoch();

foreach (FroniusSolarConnection *connection, m_connections) {
foreach (FroniusSolarConnection *connection, m_connections)
cleanupConnection(connection);
}

foreach (const QHostAddress &address, m_discoveredAddresses)
m_discoveryResults.append(m_networkDeviceInfos.get(address));

qCDebug(dcFronius()) << "Discovery: Finished the discovery process. Found" << m_discoveryResults.count()
<< "Fronius devices in" << QTime::fromMSecsSinceStartOfDay(durationMilliSeconds).toString("mm:ss.zzz");
<< "Fronius devices in" << QTime::fromMSecsSinceStartOfDay(durationMilliSeconds).toString("mm:ss.zzz");
m_gracePeriodTimer.stop();

emit discoveryFinished();

}
4 changes: 3 additions & 1 deletion fronius/froniusdiscovery.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ class FroniusDiscovery : public QObject

QList<FroniusSolarConnection *> m_connections;

NetworkDeviceInfos m_networkDeviceInfos;
QList<QHostAddress> m_discoveredAddresses;
QList<NetworkDeviceInfo> m_discoveryResults;

void checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo);
void checkHostAddress(const QHostAddress &address);
void cleanupConnection(FroniusSolarConnection *connection);

void finishDiscovery();
Expand Down
80 changes: 35 additions & 45 deletions fronius/integrationpluginfronius.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ void IntegrationPluginFronius::discoverThings(ThingDiscoveryInfo *info)
qCInfo(dcFronius()) << "Discovery finished. Found" << discovery->discoveryResults().count() << "devices";
foreach (const NetworkDeviceInfo &networkDeviceInfo, discovery->discoveryResults()) {
qCInfo(dcFronius()) << "Discovered Fronius on" << networkDeviceInfo;
if (networkDeviceInfo.macAddress().isNull())
continue;

QString title;
if (networkDeviceInfo.hostName().isEmpty()) {
Expand All @@ -73,24 +71,29 @@ void IntegrationPluginFronius::discoverThings(ThingDiscoveryInfo *info)
}

QString description;
if (networkDeviceInfo.macAddressManufacturer().isEmpty()) {
description = networkDeviceInfo.macAddress();
} else {
description = networkDeviceInfo.macAddress() + " (" + networkDeviceInfo.macAddressManufacturer() + ")";
if (networkDeviceInfo.macAddressInfos().count() == 1) {
MacAddressInfo macInfo = networkDeviceInfo.macAddressInfos().constFirst();
if (macInfo.vendorName().isEmpty()) {
description = macInfo.macAddress().toString();
} else {
description = macInfo.macAddress().toString() + " (" + macInfo.vendorName() + ")";
}
}

ThingDescriptor descriptor(connectionThingClassId, title, description);
ParamList params;
params.append(Param(connectionThingMacAddressParamTypeId, networkDeviceInfo.thingParamValueMacAddress()));
params.append(Param(connectionThingHostNameParamTypeId, networkDeviceInfo.thingParamValueHostName()));
params.append(Param(connectionThingAddressParamTypeId, networkDeviceInfo.thingParamValueAddress()));
descriptor.setParams(params);

// Check if we already have set up this device
Things existingThings = myThings().filterByParam(connectionThingMacParamTypeId, networkDeviceInfo.macAddress());
if (existingThings.count() == 1) {
qCDebug(dcFronius()) << "This thing already exists in the system." << existingThings.first() << networkDeviceInfo;
descriptor.setThingId(existingThings.first()->id());
Thing *existingThing = myThings().findByParams(params);
if (existingThing) {
qCDebug(dcFronius()) << "This thing already exists in the system." << existingThing;
descriptor.setThingId(existingThing->id());
}

ParamList params;
params << Param(connectionThingMacParamTypeId, networkDeviceInfo.macAddress());
descriptor.setParams(params);
info->addThingDescriptor(descriptor);
}
info->finish(Thing::ThingErrorNoError);
Expand All @@ -113,42 +116,30 @@ void IntegrationPluginFronius::setupThing(ThingSetupInfo *info)
connection->deleteLater();
}

if (m_monitors.contains(thing)) {
if (m_monitors.contains(thing))
hardwareManager()->networkDeviceDiscovery()->unregisterMonitor(m_monitors.take(thing));
}

// Set up depending on the available params, mac can only be filled in by discovery (ro param),
// the ip could be used as static manual config for VPN networks or WAN IP's
QHostAddress address(thing->paramValue(connectionThingAddressParamTypeId).toString());
MacAddress mac(thing->paramValue(connectionThingMacParamTypeId).toString());

// Create the connection
FroniusSolarConnection *connection = nullptr;

if (mac.isValid() && !mac.isNull()) {
qCInfo(dcFronius()) << "Setting up network device monitor for Fronius connection using MAC address" << mac.toString();
NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(mac);
m_monitors.insert(thing, monitor);

connection = new FroniusSolarConnection(hardwareManager()->networkManager(), monitor->networkDeviceInfo().address(), thing);
connect(monitor, &NetworkDeviceMonitor::networkDeviceInfoChanged, this, [=](const NetworkDeviceInfo &networkDeviceInfo){
qCDebug(dcFronius()) << "Network device info changed for" << thing << networkDeviceInfo;
if (networkDeviceInfo.isValid()) {
connection->setAddress(networkDeviceInfo.address());
refreshConnection(connection);
} else {
connection->setAddress(QHostAddress());
}
});
} else if (!address.isNull()) {
qCInfo(dcFronius()) << "Setting up Fronius connection based on IP address" << address.toString() << "without monitoring. Any IP changed will not be recognized and the device will be disconnected.";
connection = new FroniusSolarConnection(hardwareManager()->networkManager(), address, thing);
} else {
qCWarning(dcFronius()) << "Unable to set up thing" << thing << ", neither IP nor MAC is valid." << thing->params();
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("Please reconfigure the device."));
NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(thing);
if (!monitor) {
qCWarning(dcFronius()) << "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;
}

qCInfo(dcFronius()) << "Set up Fronius connection " << monitor;
m_monitors.insert(thing, monitor);

FroniusSolarConnection *connection = new FroniusSolarConnection(hardwareManager()->networkManager(), monitor->networkDeviceInfo().address(), thing);
connect(monitor, &NetworkDeviceMonitor::networkDeviceInfoChanged, this, [=](const NetworkDeviceInfo &networkDeviceInfo){
qCDebug(dcFronius()) << "Network device info changed for" << thing << networkDeviceInfo;
if (networkDeviceInfo.isValid()) {
connection->setAddress(networkDeviceInfo.address());
refreshConnection(connection);
} else {
connection->setAddress(QHostAddress());
}
});

connect(connection, &FroniusSolarConnection::availableChanged, this, [=](bool available){
qCDebug(dcFronius()) << thing << "Available changed" << available;
thing->setStateValue("connected", available);
Expand All @@ -168,7 +159,6 @@ void IntegrationPluginFronius::setupThing(ThingSetupInfo *info)
}
});


if (info->isInitialSetup()) {
// Verify the version
FroniusNetworkReply *reply = connection->getVersion();
Expand Down
11 changes: 9 additions & 2 deletions fronius/integrationpluginfronius.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"name": "connection",
"displayName": "Fronius Solar",
"createMethods": ["discovery", "user"],
"interfaces": ["gateway"],
"interfaces": ["gateway", "networkdevice"],
"providedInterfaces": ["energymeter", "solarinverter", "energystorage"],
"paramTypes": [
{
Expand All @@ -24,9 +24,16 @@
"inputType": "IPv4Address",
"defaultValue": ""
},
{
"id": "05d05a5f-7da1-4198-b281-5199dc660acc",
"name": "hostName",
"displayName": "Host name",
"type": "QString",
"defaultValue": ""
},
{
"id": "2237972e-385b-4458-b5d3-1d1fb4ae8756",
"name": "mac",
"name": "macAddress",
"displayName": "Mac address",
"type": "QString",
"readOnly": true,
Expand Down

0 comments on commit 1aea8bd

Please sign in to comment.