Merge PR #391: Anel: Automatically update configuration when the IP changes
This commit is contained in:
commit
3d3a706d4a
@ -5,7 +5,9 @@ QT += network
|
|||||||
TARGET = $$qtLibraryTarget(nymea_integrationpluginanel)
|
TARGET = $$qtLibraryTarget(nymea_integrationpluginanel)
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
discovery.cpp \
|
||||||
integrationpluginanel.cpp \
|
integrationpluginanel.cpp \
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
discovery.h \
|
||||||
integrationpluginanel.h \
|
integrationpluginanel.h \
|
||||||
|
|||||||
65
anel/discovery.cpp
Normal file
65
anel/discovery.cpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#include "discovery.h"
|
||||||
|
|
||||||
|
#include <QUdpSocket>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QMetaObject>
|
||||||
|
|
||||||
|
#include "extern-plugininfo.h"
|
||||||
|
|
||||||
|
Discovery::Discovery(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Discovery::discover()
|
||||||
|
{
|
||||||
|
QUdpSocket *searchSocket = new QUdpSocket(this);
|
||||||
|
|
||||||
|
// Note: This will fail, and it's not a problem, but it is required to force the socket to stick to IPv4...
|
||||||
|
searchSocket->bind(QHostAddress::AnyIPv4, 30303);
|
||||||
|
|
||||||
|
QString discoveryString = "Durchsuchen: Wer ist da?";
|
||||||
|
qint64 len = searchSocket->writeDatagram(discoveryString.toUtf8(), QHostAddress("255.255.255.255"), 30303);
|
||||||
|
if (len != discoveryString.length()) {
|
||||||
|
searchSocket->deleteLater();
|
||||||
|
qCWarning(dcAnelElektronik()) << "Error sending discovery";
|
||||||
|
QTimer::singleShot(0, this, [=](){
|
||||||
|
emit finished(true);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTimer::singleShot(2000, this, [this, searchSocket](){
|
||||||
|
while(searchSocket->hasPendingDatagrams()) {
|
||||||
|
char buffer[1024];
|
||||||
|
QHostAddress senderAddress;
|
||||||
|
int len = searchSocket->readDatagram(buffer, 1024, &senderAddress);
|
||||||
|
QByteArray data = QByteArray::fromRawData(buffer, len);
|
||||||
|
qCDebug(dcAnelElektronik()) << "Have datagram:" << data;
|
||||||
|
if (!data.startsWith("NET-CONTROL")) {
|
||||||
|
qCDebug(dcAnelElektronik()) << "Failed to parse discovery datagram from" << senderAddress << data;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QStringList parts = QString(data).split("\r\n");
|
||||||
|
if (parts.count() != 4) {
|
||||||
|
qCDebug(dcAnelElektronik()) << "Failed to parse discovery datagram from" << senderAddress << data;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
qCDebug(dcAnelElektronik()) << "Found NET-CONTROL:" << senderAddress << parts.at(0) << parts.at(1) << parts.at(2) << parts.at(3) << senderAddress.protocol();
|
||||||
|
Result result;
|
||||||
|
result.name = parts.at(2);
|
||||||
|
result.macAddress = parts.at(1);
|
||||||
|
result.ipAddress = senderAddress.toString();
|
||||||
|
result.port = parts.at(3).toInt();
|
||||||
|
|
||||||
|
m_results.insert(result.macAddress, result);
|
||||||
|
}
|
||||||
|
emit finished(false);
|
||||||
|
searchSocket->deleteLater();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<QString, Discovery::Result> Discovery::results() const
|
||||||
|
{
|
||||||
|
return m_results;
|
||||||
|
}
|
||||||
30
anel/discovery.h
Normal file
30
anel/discovery.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef DISCOVERY_H
|
||||||
|
#define DISCOVERY_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
class Discovery : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
struct Result {
|
||||||
|
QString name;
|
||||||
|
QString macAddress;
|
||||||
|
QString ipAddress;
|
||||||
|
int port;
|
||||||
|
};
|
||||||
|
explicit Discovery(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
void discover();
|
||||||
|
|
||||||
|
QHash<QString, Result> results() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished(bool error);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QHash<QString, Result> m_results;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DISCOVERY_H
|
||||||
@ -134,29 +134,31 @@ Example reply for HOME and PRO:
|
|||||||
#include "integrationpluginanel.h"
|
#include "integrationpluginanel.h"
|
||||||
#include "plugininfo.h"
|
#include "plugininfo.h"
|
||||||
#include "plugintimer.h"
|
#include "plugintimer.h"
|
||||||
|
#include "discovery.h"
|
||||||
|
|
||||||
#include <network/networkaccessmanager.h>
|
#include <network/networkaccessmanager.h>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QAuthenticator>
|
#include <QAuthenticator>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
QHash<ThingClassId, StateTypeId> connectedStateTypeIdMap = {
|
||||||
|
{netPwrCtlHomeThingClassId, netPwrCtlHomeConnectedStateTypeId},
|
||||||
|
{netPwrCtlProThingClassId, netPwrCtlProConnectedStateTypeId},
|
||||||
|
{netPwrCtlAdvThingClassId, netPwrCtlAdvConnectedStateTypeId},
|
||||||
|
{netPwrCtlHutThingClassId, netPwrCtlHutConnectedStateTypeId},
|
||||||
|
{socketThingClassId, socketConnectedStateTypeId}
|
||||||
|
};
|
||||||
|
|
||||||
|
QHash<ThingClassId, ParamTypeId> macAddressParamTypeIdMap = {
|
||||||
|
{netPwrCtlHomeThingClassId, netPwrCtlHomeThingMacAddressParamTypeId},
|
||||||
|
{netPwrCtlProThingClassId, netPwrCtlProThingMacAddressParamTypeId},
|
||||||
|
{netPwrCtlAdvThingClassId, netPwrCtlAdvThingMacAddressParamTypeId},
|
||||||
|
{netPwrCtlHutThingClassId, netPwrCtlHutThingMacAddressParamTypeId}
|
||||||
|
};
|
||||||
|
|
||||||
IntegrationPluginAnel::IntegrationPluginAnel()
|
IntegrationPluginAnel::IntegrationPluginAnel()
|
||||||
{
|
{
|
||||||
m_connectedStateTypeIdMap.insert(netPwrCtlHomeThingClassId, netPwrCtlHomeConnectedStateTypeId);
|
|
||||||
m_connectedStateTypeIdMap.insert(netPwrCtlProThingClassId, netPwrCtlProConnectedStateTypeId);
|
|
||||||
m_connectedStateTypeIdMap.insert(netPwrCtlAdvThingClassId, netPwrCtlAdvConnectedStateTypeId);
|
|
||||||
m_connectedStateTypeIdMap.insert(netPwrCtlHutThingClassId, netPwrCtlHutConnectedStateTypeId);
|
|
||||||
m_connectedStateTypeIdMap.insert(socketThingClassId, socketConnectedStateTypeId);
|
|
||||||
|
|
||||||
m_ipAddressParamTypeIdMap.insert(netPwrCtlHomeThingClassId, netPwrCtlHomeThingIpAddressParamTypeId);
|
|
||||||
m_ipAddressParamTypeIdMap.insert(netPwrCtlProThingClassId, netPwrCtlProThingIpAddressParamTypeId);
|
|
||||||
m_ipAddressParamTypeIdMap.insert(netPwrCtlAdvThingClassId, netPwrCtlAdvThingIpAddressParamTypeId);
|
|
||||||
m_ipAddressParamTypeIdMap.insert(netPwrCtlHutThingClassId, netPwrCtlHutThingIpAddressParamTypeId);
|
|
||||||
|
|
||||||
m_portParamTypeIdMap.insert(netPwrCtlHomeThingClassId, netPwrCtlHomeThingPortParamTypeId);
|
|
||||||
m_portParamTypeIdMap.insert(netPwrCtlProThingClassId, netPwrCtlProThingPortParamTypeId);
|
|
||||||
m_portParamTypeIdMap.insert(netPwrCtlAdvThingClassId, netPwrCtlAdvThingPortParamTypeId);
|
|
||||||
m_portParamTypeIdMap.insert(netPwrCtlHutThingClassId, netPwrCtlHutThingPortParamTypeId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IntegrationPluginAnel::~IntegrationPluginAnel()
|
IntegrationPluginAnel::~IntegrationPluginAnel()
|
||||||
@ -165,66 +167,70 @@ IntegrationPluginAnel::~IntegrationPluginAnel()
|
|||||||
|
|
||||||
void IntegrationPluginAnel::init()
|
void IntegrationPluginAnel::init()
|
||||||
{
|
{
|
||||||
|
m_discovery = new Discovery(this);
|
||||||
|
// Every time the discovery finish, we'll check if we need to update cached ip/port
|
||||||
|
connect(m_discovery, &Discovery::finished, this, [=](bool error){
|
||||||
|
if (error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach (Thing *thing, myThings()) {
|
||||||
|
if (!macAddressParamTypeIdMap.contains(thing->thingClassId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QString macAddress = thing->paramValue(macAddressParamTypeIdMap.value(thing->thingClassId())).toString();
|
||||||
|
|
||||||
|
// Upgrading configured things from old version where the MAC param was still holding an IP address instead
|
||||||
|
if (!QHostAddress(macAddress).isNull()) {
|
||||||
|
qCDebug(dcAnelElektronik()) << "Upgrading configuration for:" << thing->name();
|
||||||
|
foreach (const Discovery::Result &result, m_discovery->results()) {
|
||||||
|
if (result.ipAddress == macAddress) {
|
||||||
|
macAddress = result.macAddress;
|
||||||
|
thing->setParamValue(macAddressParamTypeIdMap.value(thing->thingClassId()), macAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (m_discovery->results().contains(macAddress)) {
|
||||||
|
Discovery::Result result = m_discovery->results().value(macAddress);
|
||||||
|
qCDebug(dcAnelElektronik()) << "Updating IP address for" << thing->name() << "to" << result.ipAddress << ":" << result.port;
|
||||||
|
pluginStorage()->beginGroup(thing->id().toString());
|
||||||
|
pluginStorage()->setValue("cachedAddress", result.ipAddress);
|
||||||
|
pluginStorage()->setValue("cachedPort", result.port);
|
||||||
|
pluginStorage()->endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginAnel::discoverThings(ThingDiscoveryInfo *info)
|
void IntegrationPluginAnel::discoverThings(ThingDiscoveryInfo *info)
|
||||||
{
|
{
|
||||||
QUdpSocket *searchSocket = new QUdpSocket(this);
|
connect(m_discovery, &Discovery::finished, info, [=](bool error){
|
||||||
|
if (error) {
|
||||||
|
qCWarning(dcAnelElektronik()) << "Error sending discovery";
|
||||||
|
//: Error discovering devices
|
||||||
|
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Error sending data to the network."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach (const Discovery::Result &result, m_discovery->results()) {
|
||||||
|
ThingDescriptor d(info->thingClassId(), result.name, result.ipAddress);
|
||||||
|
ParamTypeId macAddressParamTypeId = macAddressParamTypeIdMap.value(info->thingClassId());
|
||||||
|
ParamList params;
|
||||||
|
params << Param(macAddressParamTypeId, result.macAddress);
|
||||||
|
|
||||||
// Note: This will fail, and it's not a problem, but it is required to force the socket to stick to IPv4...
|
d.setParams(params);
|
||||||
searchSocket->bind(QHostAddress::AnyIPv4, 30303);
|
foreach (Thing *existingThing, myThings().filterByThingClassId(info->thingClassId())) {
|
||||||
|
if (existingThing->paramValue(macAddressParamTypeId).toString() == result.macAddress) {
|
||||||
QString discoveryString = "Durchsuchen: Wer ist da?";
|
qCDebug(dcAnelElektronik()) << "Already have" << result.macAddress << result.ipAddress << "in configured things.";
|
||||||
qint64 len = searchSocket->writeDatagram(discoveryString.toUtf8(), QHostAddress("255.255.255.255"), 30303);
|
d.setThingId(existingThing->id());
|
||||||
if (len != discoveryString.length()) {
|
break;
|
||||||
searchSocket->deleteLater();
|
|
||||||
qCWarning(dcAnelElektronik()) << "Error sending discovery";
|
|
||||||
//: Error discovering devices
|
|
||||||
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Error sending data to the network."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTimer::singleShot(2000, info, [this, searchSocket, info](){
|
|
||||||
while(searchSocket->hasPendingDatagrams()) {
|
|
||||||
char buffer[1024];
|
|
||||||
QHostAddress senderAddress;
|
|
||||||
int len = searchSocket->readDatagram(buffer, 1024, &senderAddress);
|
|
||||||
QByteArray data = QByteArray::fromRawData(buffer, len);
|
|
||||||
qCDebug(dcAnelElektronik()) << "Have datagram:" << data;
|
|
||||||
if (!data.startsWith("NET-CONTROL")) {
|
|
||||||
qCDebug(dcAnelElektronik()) << "Failed to parse discovery datagram from" << senderAddress << data;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
QStringList parts = QString(data).split("\r\n");
|
|
||||||
if (parts.count() != 4) {
|
|
||||||
qCDebug(dcAnelElektronik()) << "Failed to parse discovery datagram from" << senderAddress << data;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
qCDebug(dcAnelElektronik()) << "Found NET-CONTROL:" << senderAddress << parts.at(2) << parts.at(3) << senderAddress.protocol();
|
|
||||||
|
|
||||||
ParamTypeId ipAddressParamTypeId = m_ipAddressParamTypeIdMap.value(info->thingClassId());
|
|
||||||
ParamTypeId portParamTypeId = m_portParamTypeIdMap.value(info->thingClassId());
|
|
||||||
|
|
||||||
bool existing = false;
|
|
||||||
foreach (Thing *existingDev, myThings()) {
|
|
||||||
if (existingDev->thingClassId() == info->thingClassId() && existingDev->paramValue(ipAddressParamTypeId).toString() == senderAddress.toString()) {
|
|
||||||
existing = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (existing) {
|
|
||||||
qCDebug(dcAnelElektronik()) << "Already have" << senderAddress << "in configured things. Skipping...";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ThingDescriptor d(info->thingClassId(), parts.at(2), senderAddress.toString());
|
|
||||||
ParamList params;
|
|
||||||
params << Param(ipAddressParamTypeId, senderAddress.toString());
|
|
||||||
params << Param(portParamTypeId, parts.at(3).toInt());
|
|
||||||
d.setParams(params);
|
|
||||||
info->addThingDescriptor(d);
|
info->addThingDescriptor(d);
|
||||||
}
|
}
|
||||||
info->finish(Thing::ThingErrorNoError);
|
info->finish(Thing::ThingErrorNoError);
|
||||||
searchSocket->deleteLater();
|
|
||||||
});
|
});
|
||||||
|
m_discovery->discover();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginAnel::startPairing(ThingPairingInfo *info)
|
void IntegrationPluginAnel::startPairing(ThingPairingInfo *info)
|
||||||
@ -234,8 +240,10 @@ void IntegrationPluginAnel::startPairing(ThingPairingInfo *info)
|
|||||||
|
|
||||||
void IntegrationPluginAnel::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &password)
|
void IntegrationPluginAnel::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &password)
|
||||||
{
|
{
|
||||||
QString ipAddress = info->params().paramValue(m_ipAddressParamTypeIdMap.value(info->thingClassId())).toString();
|
QString macAddress = info->params().paramValue(macAddressParamTypeIdMap.value(info->thingClassId())).toString();
|
||||||
int port = info->params().paramValue(m_portParamTypeIdMap.value(info->thingClassId())).toInt();
|
|
||||||
|
QString ipAddress = m_discovery->results().value(macAddress).ipAddress;
|
||||||
|
int port = m_discovery->results().value(macAddress).port;
|
||||||
|
|
||||||
QNetworkRequest request;
|
QNetworkRequest request;
|
||||||
request.setUrl(QUrl(QString("http://%1:%2/strg.cfg").arg(ipAddress).arg(port)));
|
request.setUrl(QUrl(QString("http://%1:%2/strg.cfg").arg(ipAddress).arg(port)));
|
||||||
@ -243,9 +251,11 @@ void IntegrationPluginAnel::confirmPairing(ThingPairingInfo *info, const QString
|
|||||||
qCDebug(dcAnelElektronik()) << "ConfirmPairing fetching:" << request.url() << request.rawHeader("Authorization");
|
qCDebug(dcAnelElektronik()) << "ConfirmPairing fetching:" << request.url() << request.rawHeader("Authorization");
|
||||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
||||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
connect(reply, &QNetworkReply::finished, info, [this, info, reply, username, password](){
|
connect(reply, &QNetworkReply::finished, info, [=](){
|
||||||
if (reply->error() == QNetworkReply::NoError) {
|
if (reply->error() == QNetworkReply::NoError) {
|
||||||
pluginStorage()->beginGroup(info->thingId().toString());
|
pluginStorage()->beginGroup(info->thingId().toString());
|
||||||
|
pluginStorage()->setValue("cachedAddress", ipAddress);
|
||||||
|
pluginStorage()->setValue("cachedPort", port);
|
||||||
pluginStorage()->setValue("username", username);
|
pluginStorage()->setValue("username", username);
|
||||||
pluginStorage()->setValue("password", password);
|
pluginStorage()->setValue("password", password);
|
||||||
pluginStorage()->endGroup();
|
pluginStorage()->endGroup();
|
||||||
@ -285,12 +295,23 @@ void IntegrationPluginAnel::setupThing(ThingSetupInfo *info)
|
|||||||
info->finish(Thing::ThingErrorThingClassNotFound);
|
info->finish(Thing::ThingErrorThingClassNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginAnel::postSetupThing(Thing *thing)
|
||||||
|
{
|
||||||
|
Q_UNUSED(thing)
|
||||||
|
if (!m_discoverTimer) {
|
||||||
|
m_discoverTimer = hardwareManager()->pluginTimerManager()->registerTimer(60);
|
||||||
|
connect(m_discoverTimer, &PluginTimer::timeout, m_discovery, &Discovery::discover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void IntegrationPluginAnel::thingRemoved(Thing *thing)
|
void IntegrationPluginAnel::thingRemoved(Thing *thing)
|
||||||
{
|
{
|
||||||
qCDebug(dcAnelElektronik) << "Device removed" << thing->name();
|
qCDebug(dcAnelElektronik) << "Device removed" << thing->name();
|
||||||
if (myThings().isEmpty()) {
|
if (myThings().isEmpty()) {
|
||||||
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pollTimer);
|
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pollTimer);
|
||||||
m_pollTimer = nullptr;
|
m_pollTimer = nullptr;
|
||||||
|
hardwareManager()->pluginTimerManager()->unregisterTimer(m_discoverTimer);
|
||||||
|
m_discoverTimer = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,10 +325,9 @@ void IntegrationPluginAnel::executeAction(ThingActionInfo *info)
|
|||||||
|
|
||||||
Thing *parentDevice = myThings().findById(thing->parentId());
|
Thing *parentDevice = myThings().findById(thing->parentId());
|
||||||
|
|
||||||
QString ipAddress = parentDevice->paramValue(m_ipAddressParamTypeIdMap.value(parentDevice->thingClassId())).toString();
|
|
||||||
int port = parentDevice->paramValue(m_portParamTypeIdMap.value(parentDevice->thingClassId())).toInt();
|
|
||||||
|
|
||||||
pluginStorage()->beginGroup(parentDevice->id().toString());
|
pluginStorage()->beginGroup(parentDevice->id().toString());
|
||||||
|
QString ipAddress = pluginStorage()->value("cachedAddress").toString();
|
||||||
|
int port = pluginStorage()->value("cachedPort").toInt();
|
||||||
QString username = pluginStorage()->value("username").toString();
|
QString username = pluginStorage()->value("username").toString();
|
||||||
QString password = pluginStorage()->value("password").toString();
|
QString password = pluginStorage()->value("password").toString();
|
||||||
pluginStorage()->endGroup();
|
pluginStorage()->endGroup();
|
||||||
@ -351,10 +371,10 @@ void IntegrationPluginAnel::refreshStates()
|
|||||||
|
|
||||||
void IntegrationPluginAnel::setConnectedState(Thing *thing, bool connected)
|
void IntegrationPluginAnel::setConnectedState(Thing *thing, bool connected)
|
||||||
{
|
{
|
||||||
thing->setStateValue(m_connectedStateTypeIdMap.value(thing->thingClassId()), connected);
|
thing->setStateValue(connectedStateTypeIdMap.value(thing->thingClassId()), connected);
|
||||||
foreach (Thing *child, myThings()) {
|
foreach (Thing *child, myThings()) {
|
||||||
if (child->parentId() == thing->id()) {
|
if (child->parentId() == thing->id()) {
|
||||||
child->setStateValue(m_connectedStateTypeIdMap.value(child->thingClassId()), connected);
|
child->setStateValue(connectedStateTypeIdMap.value(child->thingClassId()), connected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -363,71 +383,77 @@ void IntegrationPluginAnel::setupHomeProDevice(ThingSetupInfo *info)
|
|||||||
{
|
{
|
||||||
Thing *thing = info->thing();
|
Thing *thing = info->thing();
|
||||||
|
|
||||||
QString ipAddress = thing->paramValue(m_ipAddressParamTypeIdMap.value(thing->thingClassId())).toString();
|
QString macAddress = thing->paramValue(macAddressParamTypeIdMap.value(thing->thingClassId())).toString();
|
||||||
int port = thing->paramValue(m_portParamTypeIdMap.value(thing->thingClassId())).toInt();
|
|
||||||
|
|
||||||
pluginStorage()->beginGroup(thing->id().toString());
|
// Run a discovery and wait for it to finish before setting it up.
|
||||||
QString username = pluginStorage()->value("username").toString();
|
m_discovery->discover();
|
||||||
QString password = pluginStorage()->value("password").toString();
|
connect(m_discovery, &Discovery::finished, info, [=](){
|
||||||
pluginStorage()->endGroup();
|
pluginStorage()->beginGroup(thing->id().toString());
|
||||||
|
QString ipAddress = pluginStorage()->value("cachedAddress").toString();
|
||||||
|
int port = pluginStorage()->value("cachedPort").toInt();
|
||||||
|
QString username = pluginStorage()->value("username").toString();
|
||||||
|
QString password = pluginStorage()->value("password").toString();
|
||||||
|
pluginStorage()->endGroup();
|
||||||
|
|
||||||
QNetworkRequest request;
|
QNetworkRequest request;
|
||||||
request.setUrl(QUrl(QString("http://%1:%2/strg.cfg").arg(ipAddress).arg(port)));
|
request.setUrl(QUrl(QString("http://%1:%2/strg.cfg").arg(ipAddress).arg(port)));
|
||||||
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username).arg(password).toUtf8().toBase64());
|
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username).arg(password).toUtf8().toBase64());
|
||||||
qCDebug(dcAnelElektronik()) << "SetupDevice fetching:" << request.url() << request.rawHeader("Authorization") << username << password;
|
qCDebug(dcAnelElektronik()) << "SetupDevice fetching:" << request.url() << request.rawHeader("Authorization") << username << password;
|
||||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
||||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
connect(reply, &QNetworkReply::finished, info, [this, info, reply](){
|
connect(reply, &QNetworkReply::finished, info, [this, info, reply](){
|
||||||
StateTypeId connectedStateTypeId = m_connectedStateTypeIdMap.value(info->thing()->thingClassId());
|
StateTypeId connectedStateTypeId = connectedStateTypeIdMap.value(info->thing()->thingClassId());
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
qCWarning(dcAnelElektronik()) << "Error fetching state for" << info->thing()->name() << reply->error() << reply->errorString();
|
qCWarning(dcAnelElektronik()) << "Error fetching state for" << info->thing()->name() << reply->error() << reply->errorString();
|
||||||
info->thing()->setStateValue(connectedStateTypeId, false);
|
info->thing()->setStateValue(connectedStateTypeId, false);
|
||||||
//: Error setting up thing
|
//: Error setting up thing
|
||||||
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("The thing rejected our connection. Please check the configured network ports."));
|
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("The thing rejected our connection. Please check the configured network ports."));
|
||||||
return;
|
|
||||||
}
|
|
||||||
info->thing()->setStateValue(connectedStateTypeId, true);
|
|
||||||
|
|
||||||
QByteArray data = reply->readAll();
|
|
||||||
|
|
||||||
QStringList parts = QString(data).split(';');
|
|
||||||
|
|
||||||
int startIndex = parts.indexOf("end") - 58;
|
|
||||||
if (startIndex < 0 || !parts.at(startIndex).startsWith("NET-PWRCTRL") || parts.length() < 60) {
|
|
||||||
qCWarning(dcAnelElektronik()) << "Bad data from panel:" << data << "Length:" << parts.length();
|
|
||||||
//: Error setting up thing
|
|
||||||
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Unexpected data received from NET-PWRCTL device. Perhaps it's running an old firmware?"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point we're done with gathering information about the panel. Setup defintely succeeded for the gateway thing
|
|
||||||
info->finish(Thing::ThingErrorNoError);
|
|
||||||
|
|
||||||
// If we haven't set up childs for this gateway yet, let's do it now
|
|
||||||
foreach (Thing *child, myThings()) {
|
|
||||||
if (child->parentId() == info->thing()->id()) {
|
|
||||||
// Already have childs for this panel. We're done here
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
info->thing()->setStateValue(connectedStateTypeId, true);
|
||||||
|
|
||||||
// Lets add the child devices now
|
QByteArray data = reply->readAll();
|
||||||
int childs = -1;
|
|
||||||
QString type = parts.at(startIndex + 8);
|
QStringList parts = QString(data).split(';');
|
||||||
if (type == "H") {
|
|
||||||
childs = 3;
|
int startIndex = parts.indexOf("end") - 58;
|
||||||
} else {
|
if (startIndex < 0 || !parts.at(startIndex).startsWith("NET-PWRCTRL") || parts.length() < 60) {
|
||||||
childs = 8;
|
qCWarning(dcAnelElektronik()) << "Bad data from panel:" << data << "Length:" << parts.length();
|
||||||
}
|
//: Error setting up thing
|
||||||
|
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Unexpected data received from NET-PWRCTL device. Perhaps it's running an old firmware?"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point we're done with gathering information about the panel. Setup defintely succeeded for the gateway thing
|
||||||
|
info->finish(Thing::ThingErrorNoError);
|
||||||
|
|
||||||
|
// If we haven't set up childs for this gateway yet, let's do it now
|
||||||
|
foreach (Thing *child, myThings()) {
|
||||||
|
if (child->parentId() == info->thing()->id()) {
|
||||||
|
// Already have childs for this panel. We're done here
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lets add the child devices now
|
||||||
|
int childs = -1;
|
||||||
|
QString type = parts.at(startIndex + 8);
|
||||||
|
if (type == "H") {
|
||||||
|
childs = 3;
|
||||||
|
} else {
|
||||||
|
childs = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ThingDescriptor> descriptorList;
|
||||||
|
for (int i = 0; i < childs; i++) {
|
||||||
|
QString deviceName = parts.at(startIndex + 10 + i);
|
||||||
|
ThingDescriptor d(socketThingClassId, deviceName, info->thing()->name(), info->thing()->id());
|
||||||
|
d.setParams(ParamList() << Param(socketThingNumberParamTypeId, i));
|
||||||
|
descriptorList << d;
|
||||||
|
}
|
||||||
|
emit autoThingsAppeared(descriptorList);
|
||||||
|
});
|
||||||
|
|
||||||
QList<ThingDescriptor> descriptorList;
|
|
||||||
for (int i = 0; i < childs; i++) {
|
|
||||||
QString deviceName = parts.at(startIndex + 10 + i);
|
|
||||||
ThingDescriptor d(socketThingClassId, deviceName, info->thing()->name(), info->thing()->id());
|
|
||||||
d.setParams(ParamList() << Param(socketThingNumberParamTypeId, i));
|
|
||||||
descriptorList << d;
|
|
||||||
}
|
|
||||||
emit autoThingsAppeared(descriptorList);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,71 +461,75 @@ void IntegrationPluginAnel::setupAdvDevice(ThingSetupInfo *info)
|
|||||||
{
|
{
|
||||||
Thing *thing = info->thing();
|
Thing *thing = info->thing();
|
||||||
|
|
||||||
QString ipAddress = thing->paramValue(m_ipAddressParamTypeIdMap.value(thing->thingClassId())).toString();
|
QString macAddress = thing->paramValue(macAddressParamTypeIdMap.value(thing->thingClassId())).toString();
|
||||||
int port = thing->paramValue(m_portParamTypeIdMap.value(thing->thingClassId())).toInt();
|
|
||||||
|
|
||||||
pluginStorage()->beginGroup(thing->id().toString());
|
// Run a discovery and wait for it to finish before trying to connect
|
||||||
QString username = pluginStorage()->value("username").toString();
|
m_discovery->discover();
|
||||||
QString password = pluginStorage()->value("password").toString();
|
connect(m_discovery, &Discovery::finished, info, [=](){
|
||||||
pluginStorage()->endGroup();
|
pluginStorage()->beginGroup(thing->id().toString());
|
||||||
|
QString ipAddress = pluginStorage()->value("cachedAddress").toString();
|
||||||
|
int port = pluginStorage()->value("cachedPort").toInt();
|
||||||
|
QString username = pluginStorage()->value("username").toString();
|
||||||
|
QString password = pluginStorage()->value("password").toString();
|
||||||
|
pluginStorage()->endGroup();
|
||||||
|
|
||||||
QNetworkRequest request;
|
QNetworkRequest request;
|
||||||
request.setUrl(QUrl(QString("http://%1:%2/strg.cfg").arg(ipAddress).arg(port)));
|
request.setUrl(QUrl(QString("http://%1:%2/strg.cfg").arg(ipAddress).arg(port)));
|
||||||
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username).arg(password).toUtf8().toBase64());
|
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username).arg(password).toUtf8().toBase64());
|
||||||
qCDebug(dcAnelElektronik()) << "SetupDevice fetching:" << request.url() << request.rawHeader("Authorization");
|
qCDebug(dcAnelElektronik()) << "SetupDevice fetching:" << request.url() << request.rawHeader("Authorization");
|
||||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
||||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||||
connect(reply, &QNetworkReply::finished, info, [this, info, reply](){
|
connect(reply, &QNetworkReply::finished, info, [this, info, reply]() {
|
||||||
StateTypeId connectedStateTypeId = m_connectedStateTypeIdMap.value(info->thing()->thingClassId());
|
StateTypeId connectedStateTypeId = connectedStateTypeIdMap.value(info->thing()->thingClassId());
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
qCWarning(dcAnelElektronik()) << "Error fetching state for" << info->thing()->name() << reply->error() << reply->errorString();
|
qCWarning(dcAnelElektronik()) << "Error fetching state for" << info->thing()->name() << reply->error() << reply->errorString();
|
||||||
info->thing()->setStateValue(connectedStateTypeId, false);
|
info->thing()->setStateValue(connectedStateTypeId, false);
|
||||||
//: Error setting up thing
|
//: Error setting up thing
|
||||||
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("The thing rejected our connection. Please check the configured network ports."));
|
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("The thing rejected our connection. Please check the configured network ports."));
|
||||||
return;
|
|
||||||
}
|
|
||||||
info->thing()->setStateValue(connectedStateTypeId, true);
|
|
||||||
|
|
||||||
QByteArray data = reply->readAll();
|
|
||||||
|
|
||||||
QStringList parts = QString(data).split(';');
|
|
||||||
|
|
||||||
int startIndex = parts.indexOf("end") - 40;
|
|
||||||
if (startIndex < 0 || parts.length() < 58) {
|
|
||||||
qCWarning(dcAnelElektronik()) << "Bad data from panel:" << data << "Length:" << parts.length();
|
|
||||||
//: Error setting up thing
|
|
||||||
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Unexpected data received from NET-PWRCTL device. Perhaps it's running an old firmware?"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point we're done with gathering information about the panel. Setup defintely succeeded for the gateway thing
|
|
||||||
info->finish(Thing::ThingErrorNoError);
|
|
||||||
|
|
||||||
// If we haven't set up childs for this gateway yet, let's do it now
|
|
||||||
foreach (Thing *child, myThings()) {
|
|
||||||
if (child->parentId() == info->thing()->id()) {
|
|
||||||
// Already have childs for this panel. We're done here
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
info->thing()->setStateValue(connectedStateTypeId, true);
|
||||||
|
|
||||||
QList<ThingDescriptor> descriptorList;
|
QByteArray data = reply->readAll();
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
QString deviceName = parts.at(startIndex + (i * 5));
|
QStringList parts = QString(data).split(';');
|
||||||
ThingDescriptor d(socketThingClassId, deviceName, info->thing()->name(), info->thing()->id());
|
|
||||||
d.setParams(ParamList() << Param(socketThingNumberParamTypeId, i));
|
int startIndex = parts.indexOf("end") - 40;
|
||||||
descriptorList << d;
|
if (startIndex < 0 || parts.length() < 58) {
|
||||||
}
|
qCWarning(dcAnelElektronik()) << "Bad data from panel:" << data << "Length:" << parts.length();
|
||||||
emit autoThingsAppeared(descriptorList);
|
//: Error setting up thing
|
||||||
|
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Unexpected data received from NET-PWRCTL device. Perhaps it's running an old firmware?"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point we're done with gathering information about the panel. Setup defintely succeeded for the gateway thing
|
||||||
|
info->finish(Thing::ThingErrorNoError);
|
||||||
|
|
||||||
|
// If we haven't set up childs for this gateway yet, let's do it now
|
||||||
|
foreach (Thing *child, myThings()) {
|
||||||
|
if (child->parentId() == info->thing()->id()) {
|
||||||
|
// Already have childs for this panel. We're done here
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ThingDescriptor> descriptorList;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
QString deviceName = parts.at(startIndex + (i * 5));
|
||||||
|
ThingDescriptor d(socketThingClassId, deviceName, info->thing()->name(), info->thing()->id());
|
||||||
|
d.setParams(ParamList() << Param(socketThingNumberParamTypeId, i));
|
||||||
|
descriptorList << d;
|
||||||
|
}
|
||||||
|
emit autoThingsAppeared(descriptorList);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginAnel::refreshHomePro(Thing *thing)
|
void IntegrationPluginAnel::refreshHomePro(Thing *thing)
|
||||||
{
|
{
|
||||||
QString ipAddress = thing->paramValue(m_ipAddressParamTypeIdMap.value(thing->thingClassId())).toString();
|
|
||||||
int port = thing->paramValue(m_portParamTypeIdMap.value(thing->thingClassId())).toInt();
|
|
||||||
|
|
||||||
pluginStorage()->beginGroup(thing->id().toString());
|
pluginStorage()->beginGroup(thing->id().toString());
|
||||||
|
QString ipAddress = pluginStorage()->value("cachedAddress").toString();
|
||||||
|
int port = pluginStorage()->value("cachedPort").toInt();
|
||||||
QString username = pluginStorage()->value("username").toString();
|
QString username = pluginStorage()->value("username").toString();
|
||||||
QString password = pluginStorage()->value("password").toString();
|
QString password = pluginStorage()->value("password").toString();
|
||||||
pluginStorage()->endGroup();
|
pluginStorage()->endGroup();
|
||||||
@ -553,10 +583,9 @@ void IntegrationPluginAnel::refreshHomePro(Thing *thing)
|
|||||||
|
|
||||||
void IntegrationPluginAnel::refreshAdv(Thing *thing)
|
void IntegrationPluginAnel::refreshAdv(Thing *thing)
|
||||||
{
|
{
|
||||||
QString ipAddress = thing->paramValue(m_ipAddressParamTypeIdMap.value(thing->thingClassId())).toString();
|
|
||||||
int port = thing->paramValue(m_portParamTypeIdMap.value(thing->thingClassId())).toInt();
|
|
||||||
|
|
||||||
pluginStorage()->beginGroup(thing->id().toString());
|
pluginStorage()->beginGroup(thing->id().toString());
|
||||||
|
QString ipAddress = pluginStorage()->value("cachedAddress").toString();
|
||||||
|
int port = pluginStorage()->value("cachedPort").toInt();
|
||||||
QString username = pluginStorage()->value("username").toString();
|
QString username = pluginStorage()->value("username").toString();
|
||||||
QString password = pluginStorage()->value("password").toString();
|
QString password = pluginStorage()->value("password").toString();
|
||||||
pluginStorage()->endGroup();
|
pluginStorage()->endGroup();
|
||||||
@ -605,10 +634,9 @@ void IntegrationPluginAnel::refreshAdv(Thing *thing)
|
|||||||
|
|
||||||
void IntegrationPluginAnel::refreshAdvTemp(Thing *thing)
|
void IntegrationPluginAnel::refreshAdvTemp(Thing *thing)
|
||||||
{
|
{
|
||||||
QString ipAddress = thing->paramValue(m_ipAddressParamTypeIdMap.value(thing->thingClassId())).toString();
|
|
||||||
int port = thing->paramValue(m_portParamTypeIdMap.value(thing->thingClassId())).toInt();
|
|
||||||
|
|
||||||
pluginStorage()->beginGroup(thing->id().toString());
|
pluginStorage()->beginGroup(thing->id().toString());
|
||||||
|
QString ipAddress = pluginStorage()->value("cachedAddress").toString();
|
||||||
|
int port = pluginStorage()->value("cachedPort").toInt();
|
||||||
QString username = pluginStorage()->value("username").toString();
|
QString username = pluginStorage()->value("username").toString();
|
||||||
QString password = pluginStorage()->value("password").toString();
|
QString password = pluginStorage()->value("password").toString();
|
||||||
pluginStorage()->endGroup();
|
pluginStorage()->endGroup();
|
||||||
@ -670,6 +698,5 @@ void IntegrationPluginAnel::refreshAdvTemp(Thing *thing)
|
|||||||
qCWarning(dcAnelElektronik()) << "Error fetching light intensity value:" << data;
|
qCWarning(dcAnelElektronik()) << "Error fetching light intensity value:" << data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,6 +38,7 @@
|
|||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
|
|
||||||
class PluginTimer;
|
class PluginTimer;
|
||||||
|
class Discovery;
|
||||||
|
|
||||||
class IntegrationPluginAnel: public IntegrationPlugin
|
class IntegrationPluginAnel: public IntegrationPlugin
|
||||||
{
|
{
|
||||||
@ -55,12 +56,15 @@ public:
|
|||||||
void startPairing(ThingPairingInfo *info) override;
|
void startPairing(ThingPairingInfo *info) override;
|
||||||
void confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret) override;
|
void confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret) override;
|
||||||
void setupThing(ThingSetupInfo *info) override;
|
void setupThing(ThingSetupInfo *info) override;
|
||||||
|
void postSetupThing(Thing *thing) override;
|
||||||
void thingRemoved(Thing *thing) override;
|
void thingRemoved(Thing *thing) override;
|
||||||
void executeAction(ThingActionInfo *info) override;
|
void executeAction(ThingActionInfo *info) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void refreshStates();
|
void refreshStates();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setConnectedState(Thing *thing, bool connected);
|
void setConnectedState(Thing *thing, bool connected);
|
||||||
|
|
||||||
@ -72,11 +76,11 @@ private:
|
|||||||
void refreshAdvTemp(Thing *thing);
|
void refreshAdvTemp(Thing *thing);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Discovery *m_discovery = nullptr;
|
||||||
PluginTimer *m_pollTimer = nullptr;
|
PluginTimer *m_pollTimer = nullptr;
|
||||||
|
PluginTimer *m_discoverTimer = nullptr;
|
||||||
|
|
||||||
QHash<ThingClassId, StateTypeId> m_connectedStateTypeIdMap;
|
QHash<QString, QHostAddress> m_ipCache;
|
||||||
QHash<ThingClassId, ParamTypeId> m_ipAddressParamTypeIdMap;
|
|
||||||
QHash<ThingClassId, ParamTypeId> m_portParamTypeIdMap;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INTEGRATIONPLUGINANEL_H
|
#endif // INTEGRATIONPLUGINANEL_H
|
||||||
|
|||||||
@ -18,16 +18,9 @@
|
|||||||
"paramTypes": [
|
"paramTypes": [
|
||||||
{
|
{
|
||||||
"id": "1e273e10-3ea0-4337-a221-3b8e26c6e7dc",
|
"id": "1e273e10-3ea0-4337-a221-3b8e26c6e7dc",
|
||||||
"name":"ipAddress",
|
"name":"macAddress",
|
||||||
"displayName": "IP address",
|
"displayName": "MAC address",
|
||||||
"type": "QString"
|
"type": "QString"
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "81704e09-d283-49d1-9e3f-9c06f8b98d84",
|
|
||||||
"name": "port",
|
|
||||||
"displayName": "Web control Port",
|
|
||||||
"type": "int",
|
|
||||||
"defaultValue": 80
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"stateTypes": [
|
"stateTypes": [
|
||||||
@ -51,17 +44,10 @@
|
|||||||
"paramTypes": [
|
"paramTypes": [
|
||||||
{
|
{
|
||||||
"id": "b1cf9a4f-9c2a-4ab4-a920-46f0b8a8b988",
|
"id": "b1cf9a4f-9c2a-4ab4-a920-46f0b8a8b988",
|
||||||
"name":"ipAddress",
|
"name":"macAddress",
|
||||||
"displayName": "IP address",
|
"displayName": "MAC address",
|
||||||
"type": "QString"
|
"type": "QString"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "31540acc-949f-454f-9987-982e97ce7d21",
|
|
||||||
"name": "port",
|
|
||||||
"displayName": "Web control Port",
|
|
||||||
"type": "int",
|
|
||||||
"defaultValue": 80
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "f9cae7eb-a534-404f-b041-6e5a6720494e",
|
"id": "f9cae7eb-a534-404f-b041-6e5a6720494e",
|
||||||
"name": "username",
|
"name": "username",
|
||||||
@ -105,17 +91,10 @@
|
|||||||
"paramTypes": [
|
"paramTypes": [
|
||||||
{
|
{
|
||||||
"id": "5d98ead0-e445-492c-821c-ae169af648e4",
|
"id": "5d98ead0-e445-492c-821c-ae169af648e4",
|
||||||
"name":"ipAddress",
|
"name":"macAddress",
|
||||||
"displayName": "IP address",
|
"displayName": "MAC address",
|
||||||
"type": "QString"
|
"type": "QString"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "1913912f-2579-4e8a-9e23-af1de4a2ef72",
|
|
||||||
"name": "port",
|
|
||||||
"displayName": "Web control Port",
|
|
||||||
"type": "int",
|
|
||||||
"defaultValue": 80
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "0eeaa6f0-7232-4d6e-8637-6e21f58a2018",
|
"id": "0eeaa6f0-7232-4d6e-8637-6e21f58a2018",
|
||||||
"name": "username",
|
"name": "username",
|
||||||
@ -159,17 +138,10 @@
|
|||||||
"paramTypes": [
|
"paramTypes": [
|
||||||
{
|
{
|
||||||
"id": "fb34919c-3ca0-47b3-a14a-7986b5ce24e2",
|
"id": "fb34919c-3ca0-47b3-a14a-7986b5ce24e2",
|
||||||
"name":"ipAddress",
|
"name":"macAddress",
|
||||||
"displayName": "IP address",
|
"displayName": "MAC address",
|
||||||
"type": "QString"
|
"type": "QString"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "35010dff-dde9-4acf-a60b-cf92b7edc2a5",
|
|
||||||
"name": "port",
|
|
||||||
"displayName": "Web control Port",
|
|
||||||
"type": "int",
|
|
||||||
"defaultValue": 80
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "3bf3db56-4fe4-4c87-a5cd-7c1f1acb6408",
|
"id": "3bf3db56-4fe4-4c87-a5cd-7c1f1acb6408",
|
||||||
"name": "username",
|
"name": "username",
|
||||||
|
|||||||
@ -42,28 +42,6 @@ The name of the plugin anelElektronik ({7a3e5b64-20e4-42bd-b86b-989b84afc22a})</
|
|||||||
<extracomment>The name of the ThingClass ({d70433ac-9738-49ca-932f-6d3e20bcc6d4})</extracomment>
|
<extracomment>The name of the ThingClass ({d70433ac-9738-49ca-932f-6d3e20bcc6d4})</extracomment>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<source>IP address</source>
|
|
||||||
<extracomment>The name of the ParamType (ThingClass: netPwrCtlHut, Type: thing, ID: {fb34919c-3ca0-47b3-a14a-7986b5ce24e2})
|
|
||||||
----------
|
|
||||||
The name of the ParamType (ThingClass: netPwrCtlAdv, Type: thing, ID: {5d98ead0-e445-492c-821c-ae169af648e4})
|
|
||||||
----------
|
|
||||||
The name of the ParamType (ThingClass: netPwrCtlPro, Type: thing, ID: {b1cf9a4f-9c2a-4ab4-a920-46f0b8a8b988})
|
|
||||||
----------
|
|
||||||
The name of the ParamType (ThingClass: netPwrCtlHome, Type: thing, ID: {1e273e10-3ea0-4337-a221-3b8e26c6e7dc})</extracomment>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Web control Port</source>
|
|
||||||
<extracomment>The name of the ParamType (ThingClass: netPwrCtlHut, Type: thing, ID: {35010dff-dde9-4acf-a60b-cf92b7edc2a5})
|
|
||||||
----------
|
|
||||||
The name of the ParamType (ThingClass: netPwrCtlAdv, Type: thing, ID: {1913912f-2579-4e8a-9e23-af1de4a2ef72})
|
|
||||||
----------
|
|
||||||
The name of the ParamType (ThingClass: netPwrCtlPro, Type: thing, ID: {31540acc-949f-454f-9987-982e97ce7d21})
|
|
||||||
----------
|
|
||||||
The name of the ParamType (ThingClass: netPwrCtlHome, Type: thing, ID: {81704e09-d283-49d1-9e3f-9c06f8b98d84})</extracomment>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<extracomment>The name of the ParamType (ThingClass: netPwrCtlHut, Type: thing, ID: {3bf3db56-4fe4-4c87-a5cd-7c1f1acb6408})
|
<extracomment>The name of the ParamType (ThingClass: netPwrCtlHut, Type: thing, ID: {3bf3db56-4fe4-4c87-a5cd-7c1f1acb6408})
|
||||||
@ -210,5 +188,16 @@ The name of the StateType ({47329958-c33f-478f-b2a0-910abd150da8}) of ThingClass
|
|||||||
<extracomment>The name of the ActionType ({47329958-c33f-478f-b2a0-910abd150da8}) of ThingClass socket</extracomment>
|
<extracomment>The name of the ActionType ({47329958-c33f-478f-b2a0-910abd150da8}) of ThingClass socket</extracomment>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>MAC address</source>
|
||||||
|
<extracomment>The name of the ParamType (ThingClass: netPwrCtlHut, Type: thing, ID: {fb34919c-3ca0-47b3-a14a-7986b5ce24e2})
|
||||||
|
----------
|
||||||
|
The name of the ParamType (ThingClass: netPwrCtlAdv, Type: thing, ID: {5d98ead0-e445-492c-821c-ae169af648e4})
|
||||||
|
----------
|
||||||
|
The name of the ParamType (ThingClass: netPwrCtlPro, Type: thing, ID: {b1cf9a4f-9c2a-4ab4-a920-46f0b8a8b988})
|
||||||
|
----------
|
||||||
|
The name of the ParamType (ThingClass: netPwrCtlHome, Type: thing, ID: {1e273e10-3ea0-4337-a221-3b8e26c6e7dc})</extracomment>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user