Merge PR #753: Bosswerk: Update to networkdevice interface
This commit is contained in:
commit
afd8a4d360
@ -1,6 +1,6 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
*
|
*
|
||||||
* Copyright 2013 - 2022, 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.
|
||||||
@ -33,6 +33,7 @@
|
|||||||
#include "plugininfo.h"
|
#include "plugininfo.h"
|
||||||
|
|
||||||
#include <plugintimer.h>
|
#include <plugintimer.h>
|
||||||
|
#include <types/param.h>
|
||||||
#include <network/networkdevicediscovery.h>
|
#include <network/networkdevicediscovery.h>
|
||||||
#include <network/networkaccessmanager.h>
|
#include <network/networkaccessmanager.h>
|
||||||
#include <network/networkdevicediscoveryreply.h>
|
#include <network/networkdevicediscoveryreply.h>
|
||||||
@ -50,10 +51,13 @@ IntegrationPluginBosswerk::IntegrationPluginBosswerk()
|
|||||||
|
|
||||||
IntegrationPluginBosswerk::~IntegrationPluginBosswerk()
|
IntegrationPluginBosswerk::~IntegrationPluginBosswerk()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginBosswerk::discoverThings(ThingDiscoveryInfo *info)
|
void IntegrationPluginBosswerk::discoverThings(ThingDiscoveryInfo *info)
|
||||||
{
|
{
|
||||||
|
m_discoveryCache.clear();
|
||||||
|
|
||||||
NetworkDeviceDiscoveryReply *discoveryReply = hardwareManager()->networkDeviceDiscovery()->discover();
|
NetworkDeviceDiscoveryReply *discoveryReply = hardwareManager()->networkDeviceDiscovery()->discover();
|
||||||
|
|
||||||
// This device doesn't give much information without login credentials. In order to identify it we'll
|
// This device doesn't give much information without login credentials. In order to identify it we'll
|
||||||
@ -62,31 +66,47 @@ void IntegrationPluginBosswerk::discoverThings(ThingDiscoveryInfo *info)
|
|||||||
// If this proves to not be reliable enough, one more option would be to connect to TCP port 8899 which is open
|
// If this proves to not be reliable enough, one more option would be to connect to TCP port 8899 which is open
|
||||||
// and responds to a proprietary binary protocol which would need to be reverse engineered first.
|
// and responds to a proprietary binary protocol which would need to be reverse engineered first.
|
||||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, discoveryReply, &NetworkDeviceDiscoveryReply::deleteLater);
|
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, discoveryReply, &NetworkDeviceDiscoveryReply::deleteLater);
|
||||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::networkDeviceInfoAdded, info, [=](const NetworkDeviceInfo &networkDeviceInfo){
|
connect(discoveryReply, &NetworkDeviceDiscoveryReply::hostAddressDiscovered, info, [this, info](const QHostAddress &address){
|
||||||
qCDebug(dcBosswerk()) << "Probing device" << networkDeviceInfo.address();
|
qCDebug(dcBosswerk()) << "Probing device" << address.toString();
|
||||||
|
|
||||||
QUrl url("http://" + networkDeviceInfo.address().toString() + "/status.html");
|
QUrl url("http://" + address.toString() + "/status.html");
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
|
|
||||||
QNetworkReply *probeReply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
|
QNetworkReply *probeReply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
|
||||||
connect(probeReply, &QNetworkReply::finished, probeReply, &QNetworkReply::deleteLater);
|
connect(probeReply, &QNetworkReply::finished, probeReply, &QNetworkReply::deleteLater);
|
||||||
connect(probeReply, &QNetworkReply::finished, info, [=](){
|
connect(probeReply, &QNetworkReply::finished, info, [probeReply, address, this](){
|
||||||
QByteArray data = probeReply->readAll();
|
QByteArray data = probeReply->readAll();
|
||||||
qCDebug(dcBosswerk()) << "Probe reply from" << networkDeviceInfo.address() << ":" << probeReply->rawHeaderPairs() << data;
|
qCDebug(dcBosswerk()) << "Probe reply from" << address.toString() << ":" << probeReply->rawHeaderPairs() << data;
|
||||||
if (probeReply->header(QNetworkRequest::ServerHeader) == "HTTPD" && data == "<HTML><HEAD><TITLE>401 Unauthorized</TITLE></HEAD>\n<BODY BGCOLOR=\"#cc9999\"><H4>401 Unauthorized</H4>\nAuthorization required.\n</BODY></HTML>\n") {
|
if (probeReply->header(QNetworkRequest::ServerHeader) == "HTTPD" && data == "<HTML><HEAD><TITLE>401 Unauthorized</TITLE></HEAD>\n<BODY BGCOLOR=\"#cc9999\"><H4>401 Unauthorized</H4>\nAuthorization required.\n</BODY></HTML>\n") {
|
||||||
qCDebug(dcBosswerk()) << "Found bosswerk MI-300/600:" << networkDeviceInfo.address();
|
qCDebug(dcBosswerk()) << "Found bosswerk MI-300/600:" << address.toString();
|
||||||
|
// We get the discovery info once the network device discovery is finished.
|
||||||
ThingDescriptor descriptor(mix00ThingClassId, "MI-300/600", networkDeviceInfo.hostName());
|
m_discoveryCache.append(address);
|
||||||
descriptor.setParams({Param(mix00ThingMacAddressParamTypeId, networkDeviceInfo.macAddress())});
|
|
||||||
Thing *existingThing = myThings().findByParams({Param(mix00ThingMacAddressParamTypeId, networkDeviceInfo.macAddress())});
|
|
||||||
if (existingThing) {
|
|
||||||
descriptor.setThingId(existingThing->id());
|
|
||||||
}
|
|
||||||
info->addThingDescriptor(descriptor);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, info, [this, info, discoveryReply](){
|
||||||
|
foreach (const QHostAddress &address, m_discoveryCache) {
|
||||||
|
|
||||||
|
NetworkDeviceInfo networkDeviceInfo = discoveryReply->networkDeviceInfos().get(address);
|
||||||
|
|
||||||
|
ThingDescriptor descriptor(mix00ThingClassId, "MI-300/600", networkDeviceInfo.hostName());
|
||||||
|
|
||||||
|
ParamList params;
|
||||||
|
params.append(Param(mix00ThingMacAddressParamTypeId, networkDeviceInfo.thingParamValueMacAddress()));
|
||||||
|
params.append(Param(mix00ThingHostNameParamTypeId, networkDeviceInfo.thingParamValueHostName()));
|
||||||
|
params.append(Param(mix00ThingAddressParamTypeId, networkDeviceInfo.thingParamValueAddress()));
|
||||||
|
|
||||||
|
Thing *existingThing = myThings().findByParams(params);
|
||||||
|
if (existingThing)
|
||||||
|
descriptor.setThingId(existingThing->id());
|
||||||
|
|
||||||
|
info->addThingDescriptor(descriptor);
|
||||||
|
}
|
||||||
|
m_discoveryCache.clear();
|
||||||
|
});
|
||||||
|
|
||||||
QTimer *timeout = new QTimer(info);
|
QTimer *timeout = new QTimer(info);
|
||||||
timeout->start(28000);
|
timeout->start(28000);
|
||||||
connect(timeout, &QTimer::timeout, info, [=](){
|
connect(timeout, &QTimer::timeout, info, [=](){
|
||||||
@ -101,18 +121,24 @@ void IntegrationPluginBosswerk::startPairing(ThingPairingInfo *info)
|
|||||||
|
|
||||||
void IntegrationPluginBosswerk::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret)
|
void IntegrationPluginBosswerk::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret)
|
||||||
{
|
{
|
||||||
MacAddress mac(info->params().paramValue(mix00ThingMacAddressParamTypeId).toString());
|
MacAddress macAddress(info->params().paramValue(mix00ThingMacAddressParamTypeId).toString());
|
||||||
|
QString hostName(info->params().paramValue(mix00ThingHostNameParamTypeId).toString());
|
||||||
|
QHostAddress address(info->params().paramValue(mix00ThingAddressParamTypeId).toString());
|
||||||
|
|
||||||
QHash<MacAddress, NetworkDeviceInfo> cache = hardwareManager()->networkDeviceDiscovery()->cache();
|
NetworkDeviceInfos cache = hardwareManager()->networkDeviceDiscovery()->cache();
|
||||||
|
NetworkDeviceInfo networkDeviceInfo;
|
||||||
if (!cache.contains(mac)) {
|
if (!macAddress.isNull()) {
|
||||||
qCWarning(dcBosswerk()) << "MAC" << mac << "not found in network device cache.";
|
networkDeviceInfo = cache.at(cache.indexFromMacAddress(macAddress).first());
|
||||||
|
} else if (!hostName.isEmpty()) {
|
||||||
|
networkDeviceInfo = cache.at(cache.indexFromHostName(hostName));
|
||||||
|
} else if (!address.isNull()) {
|
||||||
|
networkDeviceInfo = cache.get(address);
|
||||||
|
} else {
|
||||||
|
qCWarning(dcBosswerk()) << info->params() << "not found in network device cache.";
|
||||||
info->finish(Thing::ThingErrorItemNotFound, QT_TR_NOOP("An error happened in the network communication."));
|
info->finish(Thing::ThingErrorItemNotFound, QT_TR_NOOP("An error happened in the network communication."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkDeviceInfo networkDeviceInfo = cache.value(mac);
|
|
||||||
|
|
||||||
QUrl url("http://" + username + ":" + secret + "@" + networkDeviceInfo.address().toString() + "/status.html");
|
QUrl url("http://" + username + ":" + secret + "@" + networkDeviceInfo.address().toString() + "/status.html");
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
|
|
||||||
@ -147,12 +173,13 @@ void IntegrationPluginBosswerk::setupThing(ThingSetupInfo *info)
|
|||||||
if (monitor) {
|
if (monitor) {
|
||||||
hardwareManager()->networkDeviceDiscovery()->unregisterMonitor(monitor);
|
hardwareManager()->networkDeviceDiscovery()->unregisterMonitor(monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginTimer *timer = m_timers.take(thing);
|
PluginTimer *timer = m_timers.take(thing);
|
||||||
if (timer) {
|
if (timer) {
|
||||||
hardwareManager()->pluginTimerManager()->unregisterTimer(timer);
|
hardwareManager()->pluginTimerManager()->unregisterTimer(timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(MacAddress(thing->paramValue(mix00ThingMacAddressParamTypeId).toString()));
|
monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(thing);
|
||||||
m_deviceMonitors.insert(thing, monitor);
|
m_deviceMonitors.insert(thing, monitor);
|
||||||
|
|
||||||
timer = hardwareManager()->pluginTimerManager()->registerTimer(5);
|
timer = hardwareManager()->pluginTimerManager()->registerTimer(5);
|
||||||
@ -208,7 +235,7 @@ void IntegrationPluginBosswerk::pollDevice(Thing *thing)
|
|||||||
}
|
}
|
||||||
QByteArray data = statusReply->readAll();
|
QByteArray data = statusReply->readAll();
|
||||||
|
|
||||||
// qCDebug(dcBosswerk) << "Status:" << qUtf8Printable(data);
|
// qCDebug(dcBosswerk) << "Status:" << qUtf8Printable(data);
|
||||||
foreach (const QString &line, QString(data).split("\n")) {
|
foreach (const QString &line, QString(data).split("\n")) {
|
||||||
if (line.startsWith("var ")) {
|
if (line.startsWith("var ")) {
|
||||||
qCDebug(dcBosswerk()) << "Data line:" << line;
|
qCDebug(dcBosswerk()) << "Data line:" << line;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
*
|
*
|
||||||
* Copyright 2013 - 2022, 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.
|
||||||
@ -34,6 +34,8 @@
|
|||||||
#include "integrations/integrationplugin.h"
|
#include "integrations/integrationplugin.h"
|
||||||
#include "extern-plugininfo.h"
|
#include "extern-plugininfo.h"
|
||||||
|
|
||||||
|
#include <QHostAddress>
|
||||||
|
|
||||||
class PluginTimer;
|
class PluginTimer;
|
||||||
class NetworkDeviceMonitor;
|
class NetworkDeviceMonitor;
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
@ -68,6 +70,7 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
QHash<Thing*, NetworkDeviceMonitor*> m_deviceMonitors;
|
QHash<Thing*, NetworkDeviceMonitor*> m_deviceMonitors;
|
||||||
QHash<Thing*, PluginTimer*> m_timers;
|
QHash<Thing*, PluginTimer*> m_timers;
|
||||||
|
QList<QHostAddress> m_discoveryCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INTEGRATIONPLUGINMEROSS_H
|
#endif // INTEGRATIONPLUGINMEROSS_H
|
||||||
|
|||||||
@ -14,13 +14,30 @@
|
|||||||
"displayName": "MI-300/600",
|
"displayName": "MI-300/600",
|
||||||
"createMethods": ["discovery"],
|
"createMethods": ["discovery"],
|
||||||
"setupMethod": "userandpassword",
|
"setupMethod": "userandpassword",
|
||||||
"interfaces": [ "solarinverter", "wirelessconnectable" ],
|
"interfaces": [ "solarinverter", "wirelessconnectable", "networkdevice" ],
|
||||||
"paramTypes": [
|
"paramTypes": [
|
||||||
|
{
|
||||||
|
"id": "80f6972f-a2df-4cbb-beea-672bdcf05e45",
|
||||||
|
"name": "hostName",
|
||||||
|
"displayName": "Host name",
|
||||||
|
"type": "QString",
|
||||||
|
"defaultValue": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "6fbe5f08-3539-447d-9281-916abe9d8128",
|
"id": "6fbe5f08-3539-447d-9281-916abe9d8128",
|
||||||
"name":"macAddress",
|
"name":"macAddress",
|
||||||
"displayName": "MAC address",
|
"displayName": "MAC address",
|
||||||
"type": "QString"
|
"type": "QString",
|
||||||
|
"defaultValue": "00:00:00:00:00:00",
|
||||||
|
"readOnly": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "f772600b-2a85-4459-a8a0-08b4e6adae2b",
|
||||||
|
"name": "address",
|
||||||
|
"displayName": "IP address",
|
||||||
|
"type": "QString",
|
||||||
|
"inputType": "IPv4Address",
|
||||||
|
"defaultValue": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"stateTypes": [
|
"stateTypes": [
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user