Fronius: Allow discovering alternate mac manufacturer
parent
c141467b24
commit
060ebeef98
|
|
@ -3,11 +3,13 @@ include(../plugins.pri)
|
|||
QT += network
|
||||
|
||||
SOURCES += \
|
||||
froniusdiscovery.cpp \
|
||||
froniusnetworkreply.cpp \
|
||||
froniussolarconnection.cpp \
|
||||
integrationpluginfronius.cpp \
|
||||
|
||||
HEADERS += \
|
||||
froniusdiscovery.h \
|
||||
froniusnetworkreply.h \
|
||||
froniussolarconnection.h \
|
||||
integrationpluginfronius.h \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,137 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2023, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "froniusdiscovery.h"
|
||||
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonParseError>
|
||||
|
||||
FroniusDiscovery::FroniusDiscovery(NetworkAccessManager *networkManager, NetworkDeviceDiscovery *networkDeviceDiscovery, QObject *parent):
|
||||
QObject(parent),
|
||||
m_networkManager(networkManager),
|
||||
m_networkDeviceDiscovery{networkDeviceDiscovery}
|
||||
{
|
||||
m_gracePeriodTimer.setSingleShot(true);
|
||||
m_gracePeriodTimer.setInterval(3000);
|
||||
connect(&m_gracePeriodTimer, &QTimer::timeout, this, [this](){
|
||||
qCDebug(dcFronius()) << "Discovery: Grace period timer triggered.";
|
||||
finishDiscovery();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void FroniusDiscovery::startDiscovery()
|
||||
{
|
||||
qCInfo(dcFronius()) << "Discovery: Searching for Fronius solar devices in the network...";
|
||||
NetworkDeviceDiscoveryReply *discoveryReply = m_networkDeviceDiscovery->discover();
|
||||
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::networkDeviceInfoAdded, this, &FroniusDiscovery::checkNetworkDevice);
|
||||
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){
|
||||
qCDebug(dcFronius()) << "Discovery: Network discovery finished. Found" << discoveryReply->networkDeviceInfos().count() << "network devices";
|
||||
m_gracePeriodTimer.start();
|
||||
discoveryReply->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
QList<NetworkDeviceInfo> FroniusDiscovery::discoveryResults() const
|
||||
{
|
||||
return m_discoveryResults;
|
||||
}
|
||||
|
||||
void FroniusDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo)
|
||||
{
|
||||
qCDebug(dcFronius()) << "Checking network device:" << networkDeviceInfo;
|
||||
|
||||
FroniusSolarConnection *connection = new FroniusSolarConnection(m_networkManager, networkDeviceInfo.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()) << "The device does not reply to our requests. Please verify that the Fronius Solar API is enabled on the device.";
|
||||
} else {
|
||||
qCDebug(dcFronius()) << "device" << networkDeviceInfo.address() << "is not reachable.";
|
||||
}
|
||||
cleanupConnection(connection);
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcFronius()) << "Failed to parse JSON data" << data << ":" << error.errorString() << data;
|
||||
cleanupConnection(connection);
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap versionResponseMap = jsonDoc.toVariant().toMap();
|
||||
if (!versionResponseMap.contains("CompatibilityRange")) {
|
||||
qCInfo(dcFronius()) << "Unexpected JSON reply. PRobably not a Fronius device.";
|
||||
cleanupConnection(connection);
|
||||
return;
|
||||
}
|
||||
qCDebug(dcFronius()) << "Compatibility version" << versionResponseMap.value("CompatibilityRange").toString();
|
||||
|
||||
// Knwon version with broken JSON API. Still allowing to discover so the user will get a proper error message during setup
|
||||
if (versionResponseMap.value("CompatibilityRange").toString() == "1.6-2") {
|
||||
qCWarning(dcFronius()) << "The Fronius data logger has a version which is known to have a broken JSON API firmware.";
|
||||
}
|
||||
|
||||
m_discoveryResults.append(networkDeviceInfo);
|
||||
cleanupConnection(connection);
|
||||
});
|
||||
}
|
||||
|
||||
void FroniusDiscovery::cleanupConnection(FroniusSolarConnection *connection)
|
||||
{
|
||||
m_connections.removeAll(connection);
|
||||
connection->deleteLater();
|
||||
}
|
||||
|
||||
void FroniusDiscovery::finishDiscovery()
|
||||
{
|
||||
qint64 durationMilliSeconds = QDateTime::currentMSecsSinceEpoch() - m_startDateTime.toMSecsSinceEpoch();
|
||||
|
||||
foreach (FroniusSolarConnection *connection, m_connections) {
|
||||
cleanupConnection(connection);
|
||||
}
|
||||
|
||||
qCInfo(dcFronius()) << "Discovery: Finished the discovery process. Found" << m_discoveryResults.count()
|
||||
<< "Fronius devices in" << QTime::fromMSecsSinceStartOfDay(durationMilliSeconds).toString("mm:ss.zzz");
|
||||
m_gracePeriodTimer.stop();
|
||||
|
||||
emit discoveryFinished();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2023, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef FRONIUSDISCOVERY_H
|
||||
#define FRONIUSDISCOVERY_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
#include <network/networkdevicediscovery.h>
|
||||
#include "froniussolarconnection.h"
|
||||
|
||||
class FroniusDiscovery : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FroniusDiscovery(NetworkAccessManager *networkManager, NetworkDeviceDiscovery *networkDeviceDiscovery, QObject *parent = nullptr);
|
||||
|
||||
void startDiscovery();
|
||||
|
||||
QList<NetworkDeviceInfo> discoveryResults() const;
|
||||
|
||||
signals:
|
||||
void discoveryFinished();
|
||||
|
||||
private:
|
||||
NetworkAccessManager *m_networkManager = nullptr;
|
||||
NetworkDeviceDiscovery *m_networkDeviceDiscovery = nullptr;
|
||||
|
||||
QTimer m_gracePeriodTimer;
|
||||
QDateTime m_startDateTime;
|
||||
|
||||
QList<FroniusSolarConnection *> m_connections;
|
||||
|
||||
QList<NetworkDeviceInfo> m_discoveryResults;
|
||||
|
||||
void checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo);
|
||||
void cleanupConnection(FroniusSolarConnection *connection);
|
||||
|
||||
void finishDiscovery();
|
||||
};
|
||||
|
||||
#endif // FRONIUSDISCOVERY_H
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
#include "plugininfo.h"
|
||||
#include "plugintimer.h"
|
||||
#include "integrationpluginfronius.h"
|
||||
#include "froniusdiscovery.h"
|
||||
#include "network/networkaccessmanager.h"
|
||||
#include "network/networkdevicediscovery.h"
|
||||
|
||||
|
|
@ -56,20 +57,15 @@ void IntegrationPluginFronius::discoverThings(ThingDiscoveryInfo *info)
|
|||
}
|
||||
|
||||
qCInfo(dcFronius()) << "Starting network discovery...";
|
||||
NetworkDeviceDiscoveryReply *discoveryReply = hardwareManager()->networkDeviceDiscovery()->discover();
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, discoveryReply, &NetworkDeviceDiscoveryReply::deleteLater);
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, info, [=](){
|
||||
FroniusDiscovery *discovery = new FroniusDiscovery(hardwareManager()->networkManager(), hardwareManager()->networkDeviceDiscovery(), info);
|
||||
connect(discovery, &FroniusDiscovery::discoveryFinished, info, [=](){
|
||||
ThingDescriptors descriptors;
|
||||
qCDebug(dcFronius()) << "Discovery finished. Found" << discoveryReply->networkDeviceInfos().count() << "devices";
|
||||
foreach (const NetworkDeviceInfo &networkDeviceInfo, discoveryReply->networkDeviceInfos()) {
|
||||
qCDebug(dcFronius()) << "Discovery finished. Found" << discovery->discoveryResults().count() << "devices";
|
||||
foreach (const NetworkDeviceInfo &networkDeviceInfo, discovery->discoveryResults()) {
|
||||
qCDebug(dcFronius()) << networkDeviceInfo;
|
||||
if (networkDeviceInfo.macAddress().isNull())
|
||||
continue;
|
||||
|
||||
// Hostname or MAC manufacturer must include Fronius
|
||||
if (!(networkDeviceInfo.macAddressManufacturer().toLower().contains("fronius") || networkDeviceInfo.hostName().toLower().contains("fronius")))
|
||||
continue;
|
||||
|
||||
QString title;
|
||||
if (networkDeviceInfo.hostName().isEmpty()) {
|
||||
title += "Fronius Solar";
|
||||
|
|
|
|||
Loading…
Reference in New Issue