Add Logilink plug-in
parent
d4d9ad698d
commit
b9a46d21bb
|
|
@ -352,6 +352,16 @@ Conflicts: nymea-plugins-translations (< 1.0.1)
|
|||
Description: nymea integration plugin for lifx
|
||||
This package contains the nymea integration plugin for lifx devices
|
||||
|
||||
Package: nymea-plugin-logilink
|
||||
Architecture: any
|
||||
Section: libs
|
||||
Depends: ${shlibs:Depends},
|
||||
${misc:Depends},
|
||||
Conflicts: nymea-plugins-translations (< 1.0.1)
|
||||
Description: nymea integration plugin for Logilink power sockets
|
||||
This package contains the nymea integration plugin for Logilink PDU
|
||||
network controlled power sockets.
|
||||
|
||||
Package: nymea-plugin-mecelectronics
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginlogilink.so
|
||||
logilink/translations/*qm usr/share/nymea/translations/
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# Logilink
|
||||
|
||||
This integration allows nymea to control Logilink power sockets.
|
||||
|
||||
## Supported things
|
||||
|
||||
* PDU8P01
|
||||
|
||||
* Secure connection with username and password
|
||||
* Get and set the state of each socket
|
||||
* No internet or cloud connection required
|
||||
|
||||
## Requirements
|
||||
|
||||
* The Logilink device must be in the same local area network as nymea.
|
||||
* TCP Sockets on port 80 must not be blocked by the router.
|
||||
* Access to the device login credentials.
|
||||
* The package “nymea-plugin-logilink” must be installed
|
||||
|
||||
## More
|
||||
|
||||
See https://logilink.de for a detailed description of the devices.
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2024, 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 "integrationpluginlogilink.h"
|
||||
#include "plugininfo.h"
|
||||
#include "plugintimer.h"
|
||||
|
||||
#include <network/networkaccessmanager.h>
|
||||
#include <QNetworkReply>
|
||||
#include <QAuthenticator>
|
||||
#include <QUrlQuery>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
IntegrationPluginLogilink::IntegrationPluginLogilink()
|
||||
{
|
||||
}
|
||||
|
||||
IntegrationPluginLogilink::~IntegrationPluginLogilink()
|
||||
{
|
||||
m_pollTimer->deleteLater();
|
||||
}
|
||||
|
||||
void IntegrationPluginLogilink::startPairing(ThingPairingInfo *info)
|
||||
{
|
||||
info->finish(Thing::ThingErrorNoError, QT_TR_NOOP("Please enter the login credentials for your device."));
|
||||
}
|
||||
|
||||
void IntegrationPluginLogilink::init()
|
||||
{
|
||||
m_pollTimer = hardwareManager()->pluginTimerManager()->registerTimer(m_pollInterval);
|
||||
connect(m_pollTimer, &PluginTimer::timeout, this, &IntegrationPluginLogilink::refreshStates);
|
||||
}
|
||||
|
||||
void IntegrationPluginLogilink::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &password)
|
||||
{
|
||||
if (info->thingClassId() == pdu8p01ThingClassId) {
|
||||
QString ipAddress = info->params().paramValue(pdu8p01ThingIpv4AddressParamTypeId).toString();
|
||||
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(QString("http://%1/status.xml").arg(ipAddress)));
|
||||
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username).arg(password).toUtf8().toBase64());
|
||||
qCDebug(dcLogilink()) << "ConfirmPairing fetching:" << request.url() << request.rawHeader("Authorization");
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, info, [=](){
|
||||
if (reply->error() == QNetworkReply::NoError) {
|
||||
pluginStorage()->beginGroup(info->thingId().toString());
|
||||
pluginStorage()->setValue("username", username);
|
||||
pluginStorage()->setValue("password", password);
|
||||
pluginStorage()->endGroup();
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Wrong username or password."));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
qCWarning(dcLogilink()) << "Unhandled ThingClass in confirmPairing" << info->thingClassId();
|
||||
info->finish(Thing::ThingErrorThingClassNotFound);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginLogilink::setupThing(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
qCDebug(dcLogilink()) << "Setup" << thing->name();
|
||||
|
||||
if (thing->thingClassId() == pdu8p01ThingClassId) {
|
||||
if (!m_pollTimer->running()) {
|
||||
m_pollTimer->start();
|
||||
}
|
||||
|
||||
QString ipAddress = thing->paramValue(pdu8p01ThingIpv4AddressParamTypeId).toString();
|
||||
|
||||
QNetworkRequest request;
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
const QString username = pluginStorage()->value("username").toString();
|
||||
const QString password = pluginStorage()->value("password").toString();
|
||||
pluginStorage()->endGroup();
|
||||
|
||||
request.setUrl(QUrl(QString("http://%1/status.xml").arg(ipAddress)));
|
||||
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username).arg(password).toUtf8().toBase64());
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, info, [=](){
|
||||
if (reply->error() == QNetworkReply::NoError) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
|
||||
if (myThings().filterByParentId(thing->id()).isEmpty()) {
|
||||
// Creating sockets as child 'things'
|
||||
ThingDescriptors descriptorList;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
QString deviceName = thing->name() + " socket " + QString::number(i);
|
||||
ThingDescriptor d(socketThingClassId, deviceName, thing->name(), thing->id());
|
||||
d.setParams(ParamList() << Param(socketThingNumberParamTypeId, i));
|
||||
descriptorList << d;
|
||||
}
|
||||
emit autoThingsAppeared(descriptorList);
|
||||
}
|
||||
} else if (reply->error() == QNetworkReply::AuthenticationRequiredError) {
|
||||
info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Wrong username or password"));
|
||||
} else {
|
||||
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("Device not found"));
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == socketThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
qCWarning(dcLogilink()) << "Unhandled ThingClass in setupDevice" << thing->thingClassId();
|
||||
info->finish(Thing::ThingErrorThingClassNotFound);
|
||||
}
|
||||
|
||||
void IntegrationPluginLogilink::postSetupThing(Thing *thing)
|
||||
{
|
||||
qCDebug(dcLogilink()) << "Post setup" << thing->name();
|
||||
if (thing->thingClassId() == pdu8p01ThingClassId) {
|
||||
getStates(thing);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginLogilink::thingRemoved(Thing *thing)
|
||||
{
|
||||
qCDebug(dcLogilink()) << "Thing removed" << thing->name();
|
||||
if (thing->thingClassId() == pdu8p01ThingClassId) {
|
||||
pluginStorage()->remove(thing->id().toString());
|
||||
}
|
||||
|
||||
if (myThings().filterByThingClassId(pdu8p01ThingClassId).isEmpty()) {
|
||||
m_pollTimer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginLogilink::executeAction(ThingActionInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
Action action = info->action();
|
||||
|
||||
if (thing->thingClassId() == socketThingClassId) {
|
||||
if (action.actionTypeId() == socketPowerActionTypeId) {
|
||||
|
||||
Thing *parentDevice = myThings().findById(thing->parentId());
|
||||
auto ipAddress = parentDevice->paramValue(pdu8p01ThingIpv4AddressParamTypeId).toString();
|
||||
pluginStorage()->beginGroup(parentDevice->id().toString());
|
||||
QString username = pluginStorage()->value("username").toString();
|
||||
QString password = pluginStorage()->value("password").toString();
|
||||
pluginStorage()->endGroup();
|
||||
|
||||
QUrl url(QString("http://%1/control_outlet.htm").arg(ipAddress));
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("outlet" + thing->paramValue(socketThingNumberParamTypeId).toString(), "1");
|
||||
query.addQueryItem("op", action.param(socketPowerActionPowerParamTypeId).value().toBool() ? "0" : "1"); // op code 0 is on, 1 is off
|
||||
query.addQueryItem("submit", "Apply");
|
||||
url.setQuery(query);
|
||||
QNetworkRequest request(url);
|
||||
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username, password).toUtf8().toBase64());
|
||||
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
||||
qCDebug(dcLogilink()) << "Requesting:" << url.toString() << request.rawHeader("Authorization");
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, info, [reply, info](){
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcLogilink()) << "Execute action failed:" << reply->error() << reply->errorString();
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
return;
|
||||
}
|
||||
info->finish(Thing::ThingErrorActionTypeNotFound);
|
||||
}
|
||||
info->finish(Thing::ThingErrorThingClassNotFound);
|
||||
}
|
||||
|
||||
void IntegrationPluginLogilink::refreshStates()
|
||||
{
|
||||
foreach (Thing *thing, myThings().filterByThingClassId(pdu8p01ThingClassId)) {
|
||||
getStates(thing);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginLogilink::getStates(Thing *thing)
|
||||
{
|
||||
auto ipAddress = thing->paramValue(pdu8p01ThingIpv4AddressParamTypeId).toString();
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
QString username = pluginStorage()->value("username").toString();
|
||||
QString password = pluginStorage()->value("password").toString();
|
||||
pluginStorage()->endGroup();
|
||||
|
||||
QUrl url(QString("http://%1/status.xml").arg(ipAddress));
|
||||
|
||||
QNetworkRequest request;
|
||||
request.setUrl(url);
|
||||
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username, password).toUtf8().toBase64());
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, thing, [this, thing, reply](){
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcLogilink()) << "Error fetching stats for" << thing->name() << reply->errorString();
|
||||
thing->setStateValue(pdu8p01ConnectedStateTypeId, false);
|
||||
foreach (auto child, myThings().filterByParentId(thing->id())) {
|
||||
child->setStateValue(socketConnectedStateTypeId, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
QXmlStreamReader xml;
|
||||
xml.addData(reply->readAll());
|
||||
if (xml.hasError()) {
|
||||
qCDebug(dcLogilink()) << "XML Error:" << xml.errorString();
|
||||
return;
|
||||
}
|
||||
thing->setStateValue(pdu8p01ConnectedStateTypeId, true);
|
||||
if (xml.readNextStartElement()) {
|
||||
if (xml.name() == "response") {
|
||||
qCDebug(dcLogilink()) << "XML contains response";
|
||||
} else {
|
||||
qCWarning(dcLogilink()) << "xml name" << xml.name();
|
||||
}
|
||||
while(xml.readNextStartElement()) {
|
||||
qCDebug(dcLogilink()) << "XML name" << xml.name();
|
||||
if (xml.name() == "curBan") {
|
||||
auto current = xml.readElementText().toDouble();
|
||||
qCDebug(dcLogilink()) << "Current" << current;
|
||||
thing->setStateValue(pdu8p01TotalLoadStateTypeId, current);
|
||||
} else if (xml.name() == "statBan") {
|
||||
auto status = xml.readElementText();
|
||||
qCDebug(dcLogilink()) << "Status" << status;
|
||||
thing->setStateValue(pdu8p01StatusStateTypeId, status);
|
||||
} else if (xml.name() == "tempBan") {
|
||||
auto temperature = xml.readElementText().toDouble();
|
||||
qCDebug(dcLogilink()) << "Temperature" << temperature;
|
||||
thing->setStateValue(pdu8p01TemperatureStateTypeId, temperature);
|
||||
} else if (xml.name() == "humBan") {
|
||||
auto humidity = xml.readElementText().toDouble();
|
||||
qCDebug(dcLogilink()) << "hummidity" << humidity;
|
||||
thing->setStateValue(pdu8p01HumidityStateTypeId, humidity);
|
||||
} else if (xml.name().startsWith("outletStat")){
|
||||
int socketNumber = xml.name().right(1).toInt();
|
||||
bool socketValue = xml.readElementText().startsWith("on");
|
||||
auto socketThing = myThings().filterByParentId(thing->id())
|
||||
.filterByParam(socketThingNumberParamTypeId, socketNumber)
|
||||
.first();
|
||||
if (!socketThing) {
|
||||
// Socket not yet setup
|
||||
continue;
|
||||
}
|
||||
qCDebug(dcLogilink()) << "Socket" << socketNumber << socketValue;
|
||||
socketThing->setStateValue(socketPowerStateTypeId, socketValue);
|
||||
socketThing->setStateValue(socketConnectedStateTypeId, true);
|
||||
} else {
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2024, 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 INTEGRATIONPLUGINLOGILINK_H
|
||||
#define INTEGRATIONPLUGINLOGILINK_H
|
||||
|
||||
#include "integrations/integrationplugin.h"
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
class PluginTimer;
|
||||
|
||||
class IntegrationPluginLogilink: public IntegrationPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginlogilink.json")
|
||||
Q_INTERFACES(IntegrationPlugin)
|
||||
|
||||
public:
|
||||
explicit IntegrationPluginLogilink();
|
||||
~IntegrationPluginLogilink();
|
||||
|
||||
void startPairing(ThingPairingInfo *info) override;
|
||||
void init() override;
|
||||
void confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret) override;
|
||||
void setupThing(ThingSetupInfo *info) override;
|
||||
void postSetupThing(Thing *thing) override;
|
||||
void thingRemoved(Thing *thing) override;
|
||||
void executeAction(ThingActionInfo *info) override;
|
||||
|
||||
private slots:
|
||||
void refreshStates();
|
||||
|
||||
private:
|
||||
PluginTimer *m_pollTimer = nullptr;
|
||||
const int m_pollInterval = 1; // seconds
|
||||
|
||||
void getStates(Thing *thing);
|
||||
};
|
||||
|
||||
#endif // INTEGRATIONPLUGINLOGILINK_H
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
"name": "logilink",
|
||||
"displayName": "Logilink",
|
||||
"id": "3e80496e-06b5-11ef-8f86-2be8f966eb8d",
|
||||
"vendors": [
|
||||
{
|
||||
"name": "logilink",
|
||||
"displayName": "Logilink",
|
||||
"id": "4aed2c3a-06b5-11ef-8a6b-ff770ac74f51",
|
||||
"thingClasses": [
|
||||
{
|
||||
"id": "d8162d6e-06b5-11ef-888f-13a1e6eca98c",
|
||||
"name": "pdu8p01",
|
||||
"displayName": "PDU8P01",
|
||||
"createMethods": ["user"],
|
||||
"setupMethod": "userandpassword",
|
||||
"interfaces": [ "gateway", "temperaturesensor", "humiditysensor"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "d2e1a63e-06b5-11ef-bf2d-5f0d67f222af",
|
||||
"name":"ipv4Address",
|
||||
"displayName": "IPv4 address",
|
||||
"type": "QString",
|
||||
"inputType": "IPv4Address",
|
||||
"defaultValue": "192.168.0.100"
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "c5c7f1ba-06b5-11ef-ad08-03562210396e",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "413af8c0-0796-11ef-bd2b-4fde50f95418",
|
||||
"name": "totalLoad",
|
||||
"displayName": "Total load",
|
||||
"displayNameEvent": "Total load changed",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"unit": "Ampere"
|
||||
},
|
||||
{
|
||||
"id": "c0ce082a-06b5-11ef-b71a-7f0e8b9a48c0",
|
||||
"name": "temperature",
|
||||
"displayName": "Temperature",
|
||||
"displayNameEvent": "Temperature changed",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"unit": "DegreeCelsius"
|
||||
},
|
||||
{
|
||||
"id": "1aaaf3ca-0793-11ef-8b3e-f7eff48006c2",
|
||||
"name": "humidity",
|
||||
"displayName": "Humidity",
|
||||
"displayNameEvent": "Humidity changed",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
"maxValue": 100,
|
||||
"unit": "Percentage"
|
||||
},
|
||||
{
|
||||
"id": "6ec71e40-0796-11ef-a8f8-a33a504a66bb",
|
||||
"name": "status",
|
||||
"displayName": "Status",
|
||||
"displayNameEvent": "Status changed",
|
||||
"type": "QString",
|
||||
"defaultValue": "Unknown"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "a320bfb6-06b5-11ef-81e4-834aeaf5fe45",
|
||||
"name": "socket",
|
||||
"displayName": "Logilink Socket",
|
||||
"createMethods": ["auto"],
|
||||
"interfaces": ["powersocket", "connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "b329edba-06b5-11ef-b04e-d3622c766dd0",
|
||||
"name": "number",
|
||||
"displayName": "Socket number",
|
||||
"type": "int"
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "b8d9679a-06b5-11ef-9812-fb840afffc88",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "47329958-c33f-478f-b2a0-910abd150da8",
|
||||
"name": "power",
|
||||
"displayName": "Power",
|
||||
"displayNameEvent": "Power changed",
|
||||
"displayNameAction": "Set power",
|
||||
"writable": true,
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"ioType": "digitalOutput"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
|
|
@ -0,0 +1,11 @@
|
|||
include(../plugins.pri)
|
||||
|
||||
QT += network xml
|
||||
|
||||
TARGET = $$qtLibraryTarget(nymea_integrationpluginlogilink)
|
||||
|
||||
SOURCES += \
|
||||
integrationpluginlogilink.cpp \
|
||||
|
||||
HEADERS += \
|
||||
integrationpluginlogilink.h \
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"title": "Logilink",
|
||||
"tagline": "Integrates Logilink with nymea.",
|
||||
"icon": "logilink.png",
|
||||
"stability": "consumer",
|
||||
"offline": true,
|
||||
"technologies": [
|
||||
"network"
|
||||
],
|
||||
"categories": [
|
||||
"sensor",
|
||||
"socket"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1">
|
||||
<context>
|
||||
<name>IntegrationPluginLogilink</name>
|
||||
<message>
|
||||
<location filename="../integrationpluginlogilink.cpp" line="52"/>
|
||||
<source>Please enter the login credentials for your device.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../integrationpluginlogilink.cpp" line="80"/>
|
||||
<source>Wrong username or password.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../integrationpluginlogilink.cpp" line="127"/>
|
||||
<source>Wrong username or password</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../integrationpluginlogilink.cpp" line="129"/>
|
||||
<source>Device not found</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>logilink</name>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="40"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="43"/>
|
||||
<source>Connected</source>
|
||||
<extracomment>The name of the StateType ({b8d9679a-06b5-11ef-9812-fb840afffc88}) of ThingClass socket
|
||||
----------
|
||||
The name of the StateType ({c5c7f1ba-06b5-11ef-ad08-03562210396e}) of ThingClass pdu8p01</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="46"/>
|
||||
<source>Humidity</source>
|
||||
<extracomment>The name of the StateType ({1aaaf3ca-0793-11ef-8b3e-f7eff48006c2}) of ThingClass pdu8p01</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="49"/>
|
||||
<source>IPv4 address</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: pdu8p01, Type: thing, ID: {d2e1a63e-06b5-11ef-bf2d-5f0d67f222af})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="52"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="55"/>
|
||||
<source>Logilink</source>
|
||||
<extracomment>The name of the vendor ({4aed2c3a-06b5-11ef-8a6b-ff770ac74f51})
|
||||
----------
|
||||
The name of the plugin logilink ({3e80496e-06b5-11ef-8f86-2be8f966eb8d})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="58"/>
|
||||
<source>Logilink Socket</source>
|
||||
<extracomment>The name of the ThingClass ({a320bfb6-06b5-11ef-81e4-834aeaf5fe45})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="61"/>
|
||||
<source>PDU8P01</source>
|
||||
<extracomment>The name of the ThingClass ({d8162d6e-06b5-11ef-888f-13a1e6eca98c})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="64"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="67"/>
|
||||
<source>Power</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: socket, ActionType: power, ID: {47329958-c33f-478f-b2a0-910abd150da8})
|
||||
----------
|
||||
The name of the StateType ({47329958-c33f-478f-b2a0-910abd150da8}) of ThingClass socket</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="70"/>
|
||||
<source>Set power</source>
|
||||
<extracomment>The name of the ActionType ({47329958-c33f-478f-b2a0-910abd150da8}) of ThingClass socket</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="73"/>
|
||||
<source>Socket number</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: socket, Type: thing, ID: {b329edba-06b5-11ef-b04e-d3622c766dd0})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="76"/>
|
||||
<source>Status</source>
|
||||
<extracomment>The name of the StateType ({6ec71e40-0796-11ef-a8f8-a33a504a66bb}) of ThingClass pdu8p01</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="79"/>
|
||||
<source>Temperature</source>
|
||||
<extracomment>The name of the StateType ({c0ce082a-06b5-11ef-b71a-7f0e8b9a48c0}) of ThingClass pdu8p01</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop_Qt5-Debug/logilink/plugininfo.h" line="82"/>
|
||||
<source>Total load</source>
|
||||
<extracomment>The name of the StateType ({413af8c0-0796-11ef-bd2b-4fde50f95418}) of ThingClass pdu8p01</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
|
@ -37,6 +37,7 @@ PLUGIN_DIRS = \
|
|||
kodi \
|
||||
lgsmarttv \
|
||||
lifx \
|
||||
logilink \
|
||||
mecelectronics \
|
||||
meross \
|
||||
mailnotification \
|
||||
|
|
|
|||
Loading…
Reference in New Issue