somfytahoma: Use local connection "Somfy Developer Mode"

Change the plugin from cloud based to local access.
master
Christian Fetzer 2022-05-20 10:48:06 +02:00
parent 1f411c2244
commit 4cf1449524
7 changed files with 439 additions and 494 deletions

View File

@ -1,7 +1,11 @@
# Somfy TaHoma # Somfy TaHoma
This plugin adds support for Somfy smarthome devices through the Somfy TaHoma This plugin adds support for Somfy smarthome devices through the local
API. Somfy TaHoma API offered by Somfy Gateways with 'Developer Mode'
enabled.
See <https://developer.somfy.com/developer-mode> and <https://github.com/Somfy-Developer/Somfy-TaHoma-Developer-Mode>
for more information.
## Prerequisites ## Prerequisites

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2020, nymea GmbH * Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
* *
* This file is part of nymea. * This file is part of nymea.
@ -35,128 +35,176 @@
#include <QJsonArray> #include <QJsonArray>
#include "network/networkaccessmanager.h" #include "network/networkaccessmanager.h"
#include "network/zeroconf/zeroconfservicebrowser.h"
#include "platform/platformzeroconfcontroller.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "somfytahomarequests.h" #include "somfytahomarequests.h"
void IntegrationPluginSomfyTahoma::init()
{
m_zeroConfBrowser = hardwareManager()->zeroConfController()->createServiceBrowser("_kizboxdev._tcp");
}
void IntegrationPluginSomfyTahoma::discoverThings(ThingDiscoveryInfo *info)
{
foreach (const ZeroConfServiceEntry &entry, m_zeroConfBrowser->serviceEntries()) {
qCDebug(dcSomfyTahoma()) << "Found local gateway:" << entry;
ThingDescriptor descriptor(info->thingClassId(), "Somfy Tahoma Gateway", entry.hostAddress().toString());
ParamList params;
params << Param(gatewayThingGatewayIdParamTypeId, entry.name());
params << Param(gatewayThingGatewayPinParamTypeId, entry.txt("gateway_pin"));
descriptor.setParams(params);
Things existingThings = myThings().filterByParam(gatewayThingGatewayIdParamTypeId, entry.name());
if (existingThings.count() == 1) {
qCDebug(dcSomfyTahoma()) << "This gateway already exists in the system!";
descriptor.setThingId(existingThings.first()->id());
}
info->addThingDescriptor(descriptor);
}
info->finish(Thing::ThingErrorNoError);
}
void IntegrationPluginSomfyTahoma::startPairing(ThingPairingInfo *info) void IntegrationPluginSomfyTahoma::startPairing(ThingPairingInfo *info)
{ {
info->finish(Thing::ThingErrorNoError, QT_TR_NOOP("Please enter the login credentials for Somfy Tahoma.")); info->finish(Thing::ThingErrorNoError, QT_TR_NOOP("Please enter the cloud login credentials for Somfy Tahoma in order to set up local access to the Gateway."));
} }
void IntegrationPluginSomfyTahoma::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &password) void IntegrationPluginSomfyTahoma::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &password)
{ {
SomfyTahomaRequest *request = createSomfyTahomaLoginRequest(hardwareManager()->networkManager(), username, password, this); // Request local token from cloud account.
SomfyTahomaRequest *request = createCloudSomfyTahomaLoginRequest(hardwareManager()->networkManager(), username, password, this);
connect(request, &SomfyTahomaRequest::error, info, [info](){ connect(request, &SomfyTahomaRequest::error, info, [info](){
info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Failed to login to Somfy Tahoma.")); info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Failed to login to Somfy Tahoma."));
}); });
connect(request, &SomfyTahomaRequest::finished, info, [this, info, username, password](const QVariant &/*result*/){ connect(request, &SomfyTahomaRequest::finished, info, [this, info, username, password](const QVariant &/*result*/){
pluginStorage()->beginGroup(info->thingId().toString()); SomfyTahomaRequest *request = createCloudSomfyTahomaGetRequest(hardwareManager()->networkManager(), "/config/" + info->params().paramValue(gatewayThingGatewayPinParamTypeId).toString() + "/local/tokens/generate", this);
pluginStorage()->setValue("username", username); connect(request, &SomfyTahomaRequest::error, info, [info](){
pluginStorage()->setValue("password", password); info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Failed to generate token."));
pluginStorage()->endGroup(); });
info->finish(Thing::ThingErrorNoError); connect(request, &SomfyTahomaRequest::finished, info, [this, info, username, password](const QVariant &result){
QString token = result.toMap()["token"].toString();
QJsonDocument jsonRequest{QJsonObject{
{"label", "nymea"},
{"token", token},
{"scope", "devmode"},
}};
SomfyTahomaRequest *request = createCloudSomfyTahomaPostRequest(hardwareManager()->networkManager(), "/config/" + info->params().paramValue(gatewayThingGatewayPinParamTypeId).toString() + "/local/tokens", "application/json", jsonRequest.toJson(QJsonDocument::Compact), this);
connect(request, &SomfyTahomaRequest::error, info, [info](){
info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Failed to activate token."));
});
connect(request, &SomfyTahomaRequest::finished, info, [this, info, username, password, token](const QVariant &result){
qCDebug(dcSomfyTahoma()) << "Got token uuid" << result;
QString requestId = result.toMap()["requestId"].toString();
pluginStorage()->beginGroup(info->thingId().toString());
pluginStorage()->setValue("username", username);
pluginStorage()->setValue("password", password);
pluginStorage()->setValue("token", token);
pluginStorage()->setValue("tokenRequestId", requestId);
pluginStorage()->endGroup();
info->finish(Thing::ThingErrorNoError);
});
});
}); });
} }
void IntegrationPluginSomfyTahoma::setupThing(ThingSetupInfo *info) void IntegrationPluginSomfyTahoma::setupThing(ThingSetupInfo *info)
{ {
if (info->thing()->thingClassId() == tahomaThingClassId) { // Compatibility to older cloud based versions of the plugin.
SomfyTahomaRequest *request = createLoginRequestWithStoredCredentials(info->thing()); if (info->thing()->thingClassId() == tahomaThingClassId ||
(info->thing()->thingClassId() == gatewayThingClassId && getToken(info->thing()).isEmpty())) {
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("The Somfy Plugin switched to local connection. Please enable 'Developer Mode' on somfy.com, remove the account from Nymea and re-setup the Somfy Tahoma Gateway."));
return;
}
if (info->thing()->thingClassId() == gatewayThingClassId) {
SomfyTahomaRequest *request = createLocalSomfyTahomaGetRequest(hardwareManager()->networkManager(), getHost(info->thing()), getToken(info->thing()), "/setup", this);
connect(request, &SomfyTahomaRequest::error, info, [info](){ connect(request, &SomfyTahomaRequest::error, info, [info](){
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Failed to login to Somfy Tahoma.")); info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Failed to connect to gateway."));
}); });
connect(request, &SomfyTahomaRequest::finished, info, [this, info](const QVariant &/*result*/){ connect(request, &SomfyTahomaRequest::finished, info, [info, this](const QVariant &result){
QUuid accountId = info->thing()->id(); QList<ThingDescriptor> unknownDevices;
SomfyTahomaRequest *request = createSomfyTahomaGetRequest(hardwareManager()->networkManager(), "/setup", this); QUuid gatewayId = info->thing()->id();
connect(request, &SomfyTahomaRequest::finished, this, [this, accountId](const QVariant &result){
QList<ThingDescriptor> unknownDevices; info->thing()->setParamValue(gatewayThingGatewayIdParamTypeId, result.toMap()["gateways"].toList().first().toMap().value("gatewayId").toString());
foreach (const QVariant &gatewayVariant, result.toMap()["gateways"].toList()) {
QVariantMap gatewayMap = gatewayVariant.toMap(); foreach (const QVariant &deviceVariant, result.toMap()["devices"].toList()) {
QString gatewayId = gatewayMap.value("gatewayId").toString(); QVariantMap deviceMap = deviceVariant.toMap();
Thing *thing = myThings().findByParams(ParamList() << Param(gatewayThingGatewayIdParamTypeId, gatewayId)); QString type = deviceMap.value("controllableName").toString();
QString deviceUrl = deviceMap.value("deviceURL").toString();
QString label = deviceMap.value("label").toString();
if (type.startsWith(QStringLiteral("io:RollerShutter"))) {
Thing *thing = myThings().findByParams(ParamList() << Param(rollershutterThingDeviceUrlParamTypeId, deviceUrl));
if (thing) { if (thing) {
qCDebug(dcSomfyTahoma()) << "Found existing gateway:" << gatewayId; qCDebug(dcSomfyTahoma()) << "Found existing roller shutter:" << label << deviceUrl;
} else { } else {
qCInfo(dcSomfyTahoma()) << "Found new gateway:" << gatewayId; qCInfo(dcSomfyTahoma()) << "Found new roller shutter:" << label << deviceUrl;
ThingDescriptor descriptor(gatewayThingClassId, "TaHoma Gateway", QString(), accountId); ThingDescriptor descriptor(rollershutterThingClassId, label, QString(), gatewayId);
descriptor.setParams(ParamList() << Param(gatewayThingGatewayIdParamTypeId, gatewayId)); descriptor.setParams(ParamList() << Param(rollershutterThingDeviceUrlParamTypeId, deviceUrl));
unknownDevices.append(descriptor); unknownDevices.append(descriptor);
} }
} } else if (type == QStringLiteral("io:ExteriorVenetianBlindIOComponent")) {
foreach (const QVariant &deviceVariant, result.toMap()["devices"].toList()) { Thing *thing = myThings().findByParams(ParamList() << Param(venetianblindThingDeviceUrlParamTypeId, deviceUrl));
QVariantMap deviceMap = deviceVariant.toMap(); if (thing) {
QString type = deviceMap.value("uiClass").toString(); qCDebug(dcSomfyTahoma()) << "Found existing venetian blind:" << label << deviceUrl;
QString deviceUrl = deviceMap.value("deviceURL").toString();
QString label = deviceMap.value("label").toString();
if (type == QStringLiteral("RollerShutter")) {
Thing *thing = myThings().findByParams(ParamList() << Param(rollershutterThingDeviceUrlParamTypeId, deviceUrl));
if (thing) {
qCDebug(dcSomfyTahoma()) << "Found existing roller shutter:" << label << deviceUrl;
} else {
qCInfo(dcSomfyTahoma()) << "Found new roller shutter:" << label << deviceUrl;
ThingDescriptor descriptor(rollershutterThingClassId, label, QString(), accountId);
descriptor.setParams(ParamList() << Param(rollershutterThingDeviceUrlParamTypeId, deviceUrl));
unknownDevices.append(descriptor);
}
} else if (type == QStringLiteral("ExteriorVenetianBlind")) {
Thing *thing = myThings().findByParams(ParamList() << Param(venetianblindThingDeviceUrlParamTypeId, deviceUrl));
if (thing) {
qCDebug(dcSomfyTahoma()) << "Found existing venetian blind:" << label << deviceUrl;
} else {
qCInfo(dcSomfyTahoma()) << "Found new venetian blind:" << label << deviceUrl;
ThingDescriptor descriptor(venetianblindThingClassId, label, QString(), accountId);
descriptor.setParams(ParamList() << Param(venetianblindThingDeviceUrlParamTypeId, deviceUrl));
unknownDevices.append(descriptor);
}
} else if (type == QStringLiteral("GarageDoor")) {
Thing *thing = myThings().findByParams(ParamList() << Param(garagedoorThingDeviceUrlParamTypeId, deviceUrl));
if (thing) {
qCDebug(dcSomfyTahoma()) << "Found existing garage door:" << label << deviceUrl;
} else {
qCInfo(dcSomfyTahoma()) << "Found new garage door:" << label << deviceUrl;
ThingDescriptor descriptor(garagedoorThingClassId, label, QString(), accountId);
descriptor.setParams(ParamList() << Param(garagedoorThingDeviceUrlParamTypeId, deviceUrl));
unknownDevices.append(descriptor);
}
} else if (type == QStringLiteral("Awning")) {
Thing *thing = myThings().findByParams(ParamList() << Param(awningThingDeviceUrlParamTypeId, deviceUrl));
if (thing) {
qCDebug(dcSomfyTahoma()) << "Found existing awning:" << label << deviceUrl;
} else {
qCInfo(dcSomfyTahoma()) << "Found new awning:" << label << deviceUrl;
ThingDescriptor descriptor(awningThingClassId, label, QString(), accountId);
descriptor.setParams(ParamList() << Param(awningThingDeviceUrlParamTypeId, deviceUrl));
unknownDevices.append(descriptor);
}
} else if (type == QStringLiteral("Light") && (deviceUrl.startsWith("io"))) {
Thing *thing = myThings().findByParams(ParamList() << Param(lightThingDeviceUrlParamTypeId, deviceUrl));
if (thing) {
qCDebug(dcSomfyTahoma()) << "Found existing light:" << label << deviceUrl;
} else {
qCInfo(dcSomfyTahoma()) << "Found new light:" << label << deviceUrl;
ThingDescriptor descriptor(lightThingClassId, label, QString(), accountId);
descriptor.setParams(ParamList() << Param(lightThingDeviceUrlParamTypeId, deviceUrl));
unknownDevices.append(descriptor);
}
} else if (type == QStringLiteral("ProtocolGateway") ||
type == QStringLiteral("Alarm") ||
(type == QStringLiteral("Light") && deviceUrl.startsWith("hue"))) {
continue;
} else { } else {
qCInfo(dcSomfyTahoma()) << "Found unsupperted Somfy device:" << label << type << deviceUrl; qCInfo(dcSomfyTahoma()) << "Found new venetian blind:" << label << deviceUrl;
ThingDescriptor descriptor(venetianblindThingClassId, label, QString(), gatewayId);
descriptor.setParams(ParamList() << Param(venetianblindThingDeviceUrlParamTypeId, deviceUrl));
unknownDevices.append(descriptor);
} }
} else if (type == QStringLiteral("io:GarageOpenerIOComponent")) {
Thing *thing = myThings().findByParams(ParamList() << Param(garagedoorThingDeviceUrlParamTypeId, deviceUrl));
if (thing) {
qCDebug(dcSomfyTahoma()) << "Found existing garage door:" << label << deviceUrl;
} else {
qCInfo(dcSomfyTahoma()) << "Found new garage door:" << label << deviceUrl;
ThingDescriptor descriptor(garagedoorThingClassId, label, QString(), gatewayId);
descriptor.setParams(ParamList() << Param(garagedoorThingDeviceUrlParamTypeId, deviceUrl));
unknownDevices.append(descriptor);
}
} else if (type == QStringLiteral("io:HorizontalAwningIOComponent")) {
Thing *thing = myThings().findByParams(ParamList() << Param(awningThingDeviceUrlParamTypeId, deviceUrl));
if (thing) {
qCDebug(dcSomfyTahoma()) << "Found existing awning:" << label << deviceUrl;
} else {
qCInfo(dcSomfyTahoma()) << "Found new awning:" << label << deviceUrl;
ThingDescriptor descriptor(awningThingClassId, label, QString(), gatewayId);
descriptor.setParams(ParamList() << Param(awningThingDeviceUrlParamTypeId, deviceUrl));
unknownDevices.append(descriptor);
}
} else if (type == QStringLiteral("io:DimmableLightIOComponent")) {
Thing *thing = myThings().findByParams(ParamList() << Param(lightThingDeviceUrlParamTypeId, deviceUrl));
if (thing) {
qCDebug(dcSomfyTahoma()) << "Found existing light:" << label << deviceUrl;
} else {
qCInfo(dcSomfyTahoma()) << "Found new light:" << label << deviceUrl;
ThingDescriptor descriptor(lightThingClassId, label, QString(), gatewayId);
descriptor.setParams(ParamList() << Param(lightThingDeviceUrlParamTypeId, deviceUrl));
unknownDevices.append(descriptor);
}
} else if (type == QStringLiteral("io:StackComponent") ||
type.startsWith("internal:")) {
continue;
} else {
qCInfo(dcSomfyTahoma()) << "Found unsupperted Somfy device:" << label << type << deviceUrl;
} }
if (!unknownDevices.isEmpty()) { }
emit autoThingsAppeared(unknownDevices);
}
});
info->finish(Thing::ThingErrorNoError); info->finish(Thing::ThingErrorNoError);
if (!unknownDevices.isEmpty()) {
emit autoThingsAppeared(unknownDevices);
}
}); });
} }
else if (info->thing()->thingClassId() == gatewayThingClassId || else if (info->thing()->thingClassId() == rollershutterThingClassId ||
info->thing()->thingClassId() == rollershutterThingClassId ||
info->thing()->thingClassId() == venetianblindThingClassId || info->thing()->thingClassId() == venetianblindThingClassId ||
info->thing()->thingClassId() == garagedoorThingClassId || info->thing()->thingClassId() == garagedoorThingClassId ||
info->thing()->thingClassId() == awningThingClassId || info->thing()->thingClassId() == awningThingClassId ||
@ -167,105 +215,39 @@ void IntegrationPluginSomfyTahoma::setupThing(ThingSetupInfo *info)
void IntegrationPluginSomfyTahoma::postSetupThing(Thing *thing) void IntegrationPluginSomfyTahoma::postSetupThing(Thing *thing)
{ {
if (thing->thingClassId() == tahomaThingClassId) { if (thing->thingClassId() != gatewayThingClassId) {
pluginStorage()->beginGroup(thing->id().toString()); return;
thing->setStateValue(tahomaUserDisplayNameStateTypeId, pluginStorage()->value("username"));
pluginStorage()->endGroup();
refreshAccount(thing);
} }
// Set parent of all devices to the respective gateway. We create all devices in setup() of the account. // Call /setup and update the state of all devices
// But we don't have the ThingIds of the gateways, because they're created in setup() as well. SomfyTahomaRequest *setupRequest = createLocalSomfyTahomaGetRequest(hardwareManager()->networkManager(), getHost(thing), getToken(thing), "/setup", this);
QUrl deviceUrl;
if (thing->thingClassId() == rollershutterThingClassId) {
deviceUrl = QUrl(thing->paramValue(rollershutterThingDeviceUrlParamTypeId).toString());
} else if (thing->thingClassId() == venetianblindThingClassId) {
deviceUrl = QUrl(thing->paramValue(venetianblindThingDeviceUrlParamTypeId).toString());
} else if (thing->thingClassId() == garagedoorThingClassId) {
deviceUrl = QUrl(thing->paramValue(garagedoorThingDeviceUrlParamTypeId).toString());
} else if (thing->thingClassId() == awningThingClassId) {
deviceUrl = QUrl(thing->paramValue(awningThingDeviceUrlParamTypeId).toString());
} else if (thing->thingClassId() == lightThingClassId) {
deviceUrl = QUrl(thing->paramValue(lightThingDeviceUrlParamTypeId).toString());
}
if (!deviceUrl.isEmpty()) {
Thing *gateway = myThings().findByParams(ParamList() << Param(gatewayThingGatewayIdParamTypeId, deviceUrl.host()));
if (gateway) {
thing->setParentId(gateway->parentId());
} else {
qCWarning(dcSomfyTahoma()) << "Couldn't find gateway for thing" << thing;
}
}
}
void IntegrationPluginSomfyTahoma::refreshAccount(Thing *thing)
{
// Ensure that even't polling doesn't interfere the refreshing.
if (m_eventPollTimer.contains(thing)) {
hardwareManager()->pluginTimerManager()->unregisterTimer(m_eventPollTimer[thing]);
}
SomfyTahomaRequest *setupRequest = createSomfyTahomaGetRequest(hardwareManager()->networkManager(), "/setup", this);
connect(setupRequest, &SomfyTahomaRequest::error, this, [this, thing](){ connect(setupRequest, &SomfyTahomaRequest::error, this, [this, thing](){
markDisconnected(thing); markDisconnected(thing);
}); });
connect(setupRequest, &SomfyTahomaRequest::finished, this, [this, thing](const QVariant &result){ connect(setupRequest, &SomfyTahomaRequest::finished, this, [this, thing](const QVariant &result){
thing->setStateValue(tahomaLoggedInStateTypeId, true); thing->setStateValue(gatewayConnectedStateTypeId, true);
thing->setStateValue(tahomaConnectedStateTypeId, true);
foreach (const QVariant &gatewayVariant, result.toMap()["gateways"].toList()) {
QVariantMap gatewayMap = gatewayVariant.toMap();
QString gatewayId = gatewayMap.value("gatewayId").toString();
Thing *thing = myThings().findByParams(ParamList() << Param(gatewayThingGatewayIdParamTypeId, gatewayId));
if (thing) {
qCDebug(dcSomfyTahoma()) << "Setting initial state for gateway:" << gatewayId;
thing->setStateValue(gatewayConnectedStateTypeId, gatewayMap["connectivity"].toMap()["status"] == "OK");
pluginStorage()->beginGroup(thing->id().toString());
pluginStorage()->setValue("connected", gatewayMap["connectivity"].toMap()["status"] == "OK");
pluginStorage()->endGroup();
}
}
foreach (const QVariant &deviceVariant, result.toMap()["devices"].toList()) { foreach (const QVariant &deviceVariant, result.toMap()["devices"].toList()) {
updateThingStates(deviceVariant.toMap()["deviceURL"].toString(), deviceVariant.toMap()["states"].toList()); updateThingStates(deviceVariant.toMap()["deviceURL"].toString(), deviceVariant.toMap()["states"].toList());
} }
}); });
SomfyTahomaRequest *eventRegistrationRequest = createSomfyTahomaPostRequest(hardwareManager()->networkManager(), "/events/register", "application/json", QByteArray(), this); // Register event handler
SomfyTahomaRequest *eventRegistrationRequest = createLocalSomfyTahomaPostRequest(hardwareManager()->networkManager(), getHost(thing), getToken(thing), "/events/register", "application/json", QByteArray(), this);
connect(eventRegistrationRequest, &SomfyTahomaRequest::error, this, [this, thing](){ connect(eventRegistrationRequest, &SomfyTahomaRequest::error, this, [this, thing](){
qCWarning(dcSomfyTahoma()) << "Failed to register for events.";
markDisconnected(thing); markDisconnected(thing);
}); });
connect(eventRegistrationRequest, &SomfyTahomaRequest::finished, this, [this, thing](const QVariant &result){ connect(eventRegistrationRequest, &SomfyTahomaRequest::finished, this, [this, thing](const QVariant &result){
thing->setStateValue(tahomaConnectedStateTypeId, true);
QString eventListenerId = result.toMap()["id"].toString(); QString eventListenerId = result.toMap()["id"].toString();
m_eventPollTimer[thing] = hardwareManager()->pluginTimerManager()->registerTimer(2 /*sec*/); m_eventPollTimer[thing] = hardwareManager()->pluginTimerManager()->registerTimer(2 /*sec*/);
connect(m_eventPollTimer[thing], &PluginTimer::timeout, thing, [this, thing, eventListenerId](){ connect(m_eventPollTimer[thing], &PluginTimer::timeout, thing, [this, thing, eventListenerId](){
SomfyTahomaRequest *eventFetchRequest = createSomfyTahomaEventFetchRequest(hardwareManager()->networkManager(), eventListenerId, this); SomfyTahomaRequest *eventFetchRequest = createLocalSomfyTahomaEventFetchRequest(hardwareManager()->networkManager(), getHost(thing), getToken(thing), eventListenerId, this);
connect(eventFetchRequest, &SomfyTahomaRequest::error, thing, [this, thing](QNetworkReply::NetworkError error){ connect(eventFetchRequest, &SomfyTahomaRequest::error, thing, [this, thing](QNetworkReply::NetworkError error){
qCWarning(dcSomfyTahoma()) << "Failed to fetch events:" << error;
markDisconnected(thing); markDisconnected(thing);
if (error == QNetworkReply::AuthenticationRequiredError) {
qCInfo(dcSomfyTahoma()) << "Failed to fetch events: Authentication expired, reauthenticating";
SomfyTahomaRequest *request = createLoginRequestWithStoredCredentials(thing);
connect(request, &SomfyTahomaRequest::error, this, [this, thing](){
// This is a fatal error. The user needs to reconfigure the account to provide new credentials.
qCWarning(dcSomfyTahoma()) << "Failed to reauthenticate";
hardwareManager()->pluginTimerManager()->unregisterTimer(m_eventPollTimer[thing]);
m_eventPollTimer.remove(thing);
});
connect(request, &SomfyTahomaRequest::finished, this, [this, thing](const QVariant &/*result*/){
qCInfo(dcSomfyTahoma()) << "Reauthentication successful";
refreshAccount(thing);
});
} else {
qCWarning(dcSomfyTahoma()) << "Failed to fetch events:" << error;
}
}); });
connect(eventFetchRequest, &SomfyTahomaRequest::finished, thing, [this, thing](const QVariant &result){ connect(eventFetchRequest, &SomfyTahomaRequest::finished, thing, [this, thing](const QVariant &result){
thing->setStateValue(tahomaConnectedStateTypeId, true); thing->setStateValue(gatewayConnectedStateTypeId, true);
restoreChildConnectedState(thing); restoreChildConnectedState(thing);
if (!result.toList().empty()) {
qCDebug(dcSomfyTahoma()) << "Got events:" << qUtf8Printable(QJsonDocument::fromVariant(result).toJson());
}
handleEvents(result.toList()); handleEvents(result.toList());
}); });
}); });
@ -275,13 +257,61 @@ void IntegrationPluginSomfyTahoma::refreshAccount(Thing *thing)
void IntegrationPluginSomfyTahoma::thingRemoved(Thing *thing) void IntegrationPluginSomfyTahoma::thingRemoved(Thing *thing)
{ {
m_eventPollTimer.remove(thing); m_eventPollTimer.remove(thing);
if (thing->thingClassId() != gatewayThingClassId) {
return;
}
// Unregister local token from cloud account.
pluginStorage()->beginGroup(thing->id().toString());
QString username = pluginStorage()->value("username").toString();
QString password = pluginStorage()->value("password").toString();
QString requestId = pluginStorage()->value("tokenRequestId").toString();
QString gatewayPin = thing->paramValue(gatewayThingGatewayPinParamTypeId).toString();
pluginStorage()->endGroup();
SomfyTahomaRequest *request = createCloudSomfyTahomaLoginRequest(hardwareManager()->networkManager(), username, password, this);
connect(request, &SomfyTahomaRequest::error, this, [](){
qCWarning(dcSomfyTahoma()) << "Failed to login to Somfy Tahoma cloud for deleting the Token.";
});
connect(request, &SomfyTahomaRequest::finished, this, [this, gatewayPin, requestId](const QVariant &/*result*/){
SomfyTahomaRequest *request = createCloudSomfyTahomaDeleteRequest(hardwareManager()->networkManager(), "/config/" + gatewayPin + "/local/tokens/" + requestId, this);
connect(request, &SomfyTahomaRequest::finished, this, [](const QVariant &/*result*/){
qCInfo(dcSomfyTahoma()) << "Deleted Token from Somfy Tahoma cloud.";
});
});
} }
void IntegrationPluginSomfyTahoma::handleEvents(const QVariantList &eventList) void IntegrationPluginSomfyTahoma::handleEvents(const QVariantList &events)
{ {
Thing *thing; Thing *thing;
foreach (const QVariant &eventVariant, eventList) { foreach (const QVariant &eventVariant, events) {
QVariantMap eventMap = eventVariant.toMap(); QVariantMap eventMap = eventVariant.toMap();
QString device = eventMap["deviceURL"].toString();
thing = myThings().findByParams(ParamList() << Param(rollershutterThingDeviceUrlParamTypeId, eventMap["deviceURL"]));
if (thing) {
device = thing->name();
}
thing = myThings().findByParams(ParamList() << Param(venetianblindThingDeviceUrlParamTypeId, eventMap["deviceURL"]));
if (thing) {
device = thing->name();
}
thing = myThings().findByParams(ParamList() << Param(garagedoorThingDeviceUrlParamTypeId, eventMap["deviceURL"]));
if (thing) {
device = thing->name();
}
thing = myThings().findByParams(ParamList() << Param(awningThingDeviceUrlParamTypeId, eventMap["deviceURL"]));
if (thing) {
device = thing->name();
}
thing = myThings().findByParams(ParamList() << Param(lightThingDeviceUrlParamTypeId, eventMap["deviceURL"]));
if (thing) {
device = thing->name();
}
qCDebug(dcSomfyTahoma()) << "Got event" << eventMap["name"].toString() << "for device" << device;
qCDebug(dcSomfyTahoma()) << qUtf8Printable(QJsonDocument::fromVariant(eventVariant).toJson());
if (eventMap["name"] == "DeviceStateChangedEvent") { if (eventMap["name"] == "DeviceStateChangedEvent") {
updateThingStates(eventMap["deviceURL"].toString(), eventMap["deviceStates"].toList()); updateThingStates(eventMap["deviceURL"].toString(), eventMap["deviceStates"].toList());
} else if (eventMap["name"] == "ExecutionRegisteredEvent") { } else if (eventMap["name"] == "ExecutionRegisteredEvent") {
@ -340,30 +370,6 @@ void IntegrationPluginSomfyTahoma::handleEvents(const QVariantList &eventList)
thingActionInfo->finish(Thing::ThingErrorHardwareFailure); thingActionInfo->finish(Thing::ThingErrorHardwareFailure);
} }
} }
} else if (eventMap["name"] == "GatewayAliveEvent") {
thing = myThings().findByParams(ParamList() << Param(gatewayThingGatewayIdParamTypeId, eventMap["gatewayId"]));
if (thing) {
qCInfo(dcSomfyTahoma()) << "Gateway connected event received:" << eventMap["gatewayId"];
thing->setStateValue(gatewayConnectedStateTypeId, true);
pluginStorage()->beginGroup(thing->id().toString());
pluginStorage()->setValue("connected", true);
pluginStorage()->endGroup();
restoreChildConnectedState(thing);
} else {
qCDebug(dcSomfyTahoma()) << "Ignoring gateway connected event for unknown gateway" << eventMap["gatewayId"];
}
} else if (eventMap["name"] == "GatewayDownEvent") {
thing = myThings().findByParams(ParamList() << Param(gatewayThingGatewayIdParamTypeId, eventMap["gatewayId"]));
if (thing) {
qCInfo(dcSomfyTahoma()) << "Gateway disconnected event received:" << eventMap["gatewayId"];
thing->setStateValue(gatewayConnectedStateTypeId, false);
pluginStorage()->beginGroup(thing->id().toString());
pluginStorage()->setValue("connected", false);
pluginStorage()->endGroup();
markDisconnected(thing);
} else {
qCDebug(dcSomfyTahoma()) << "Ignoring gateway disconnected event for unknown gateway" << eventMap["gatewayId"];
}
} }
} }
} }
@ -551,7 +557,7 @@ void IntegrationPluginSomfyTahoma::executeAction(ThingActionInfo *info)
{"commands", QJsonArray{QJsonObject{{"name", actionName}, {"commands", QJsonArray{QJsonObject{{"name", actionName},
{"parameters", actionParameters}}}}}}} {"parameters", actionParameters}}}}}}}
}}; }};
SomfyTahomaRequest *request = createSomfyTahomaPostRequest(hardwareManager()->networkManager(), "/exec/apply", "application/json", jsonRequest.toJson(QJsonDocument::Compact), this); SomfyTahomaRequest *request = createLocalSomfyTahomaPostRequest(hardwareManager()->networkManager(), getHost(info->thing()), getToken(info->thing()), "/exec/apply", "application/json", jsonRequest.toJson(QJsonDocument::Compact), this);
connect(request, &SomfyTahomaRequest::error, info, [info](){ connect(request, &SomfyTahomaRequest::error, info, [info](){
info->finish(Thing::ThingErrorHardwareFailure); info->finish(Thing::ThingErrorHardwareFailure);
}); });
@ -564,20 +570,9 @@ void IntegrationPluginSomfyTahoma::executeAction(ThingActionInfo *info)
} }
} }
SomfyTahomaRequest *IntegrationPluginSomfyTahoma::createLoginRequestWithStoredCredentials(Thing *thing)
{
pluginStorage()->beginGroup(thing->id().toString());
QString username = pluginStorage()->value("username").toString();
QString password = pluginStorage()->value("password").toString();
pluginStorage()->endGroup();
return createSomfyTahomaLoginRequest(hardwareManager()->networkManager(), username, password, this);
}
void IntegrationPluginSomfyTahoma::markDisconnected(Thing *thing) void IntegrationPluginSomfyTahoma::markDisconnected(Thing *thing)
{ {
if (thing->thingClassId() == tahomaThingClassId) { if (thing->thingClassId() == gatewayThingClassId) {
thing->setStateValue(tahomaConnectedStateTypeId, false);
} else if (thing->thingClassId() == gatewayThingClassId) {
thing->setStateValue(gatewayConnectedStateTypeId, false); thing->setStateValue(gatewayConnectedStateTypeId, false);
} else if (thing->thingClassId() == rollershutterThingClassId) { } else if (thing->thingClassId() == rollershutterThingClassId) {
thing->setStateValue(rollershutterConnectedStateTypeId, false); thing->setStateValue(rollershutterConnectedStateTypeId, false);
@ -599,9 +594,7 @@ void IntegrationPluginSomfyTahoma::restoreChildConnectedState(Thing *thing)
{ {
pluginStorage()->beginGroup(thing->id().toString()); pluginStorage()->beginGroup(thing->id().toString());
if (pluginStorage()->contains("connected")) { if (pluginStorage()->contains("connected")) {
if (thing->thingClassId() == gatewayThingClassId) { if (thing->thingClassId() == rollershutterThingClassId) {
thing->setStateValue(gatewayConnectedStateTypeId, pluginStorage()->value("connected").toBool());
} else if (thing->thingClassId() == rollershutterThingClassId) {
thing->setStateValue(rollershutterConnectedStateTypeId, pluginStorage()->value("connected").toBool()); thing->setStateValue(rollershutterConnectedStateTypeId, pluginStorage()->value("connected").toBool());
} else if (thing->thingClassId() == venetianblindThingClassId) { } else if (thing->thingClassId() == venetianblindThingClassId) {
thing->setStateValue(venetianblindConnectedStateTypeId, pluginStorage()->value("connected").toBool()); thing->setStateValue(venetianblindConnectedStateTypeId, pluginStorage()->value("connected").toBool());
@ -618,3 +611,46 @@ void IntegrationPluginSomfyTahoma::restoreChildConnectedState(Thing *thing)
restoreChildConnectedState(child); restoreChildConnectedState(child);
} }
} }
QString IntegrationPluginSomfyTahoma::getHost(Thing *thing) const
{
Thing *gateway = thing;
if (!thing->parentId().isNull()) {
gateway = myThings().findById(thing->parentId());
}
QString gatewayId = gateway->paramValue(gatewayThingGatewayIdParamTypeId).toString();
ZeroConfServiceEntry zeroConfEntry;
foreach (const ZeroConfServiceEntry &entry, m_zeroConfBrowser->serviceEntries()) {
if (entry.name() == gatewayId) {
zeroConfEntry = entry;
}
}
QString host;
pluginStorage()->beginGroup(gateway->id().toString());
if (zeroConfEntry.isValid()) {
host = zeroConfEntry.hostAddress().toString() + ":" + QString::number(zeroConfEntry.port());
pluginStorage()->setValue("cachedAddress", host);
} else if (pluginStorage()->contains("cachedAddress")){
host = pluginStorage()->value("cachedAddress").toString();
} else {
qCWarning(dcSomfyTahoma()) << "Unable to determine IP address for:" << gatewayId;
}
pluginStorage()->endGroup();
return host;
}
QString IntegrationPluginSomfyTahoma::getToken(Thing *thing) const
{
Thing *gateway = thing;
if (!thing->parentId().isNull()) {
gateway = myThings().findById(thing->parentId());
}
QString token;
pluginStorage()->beginGroup(gateway->id().toString());
token = pluginStorage()->value("token").toString();
pluginStorage()->endGroup();
return token;
}

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2020, nymea GmbH * Copyright 2013 - 2022, 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,12 @@
#include "integrations/integrationplugin.h" #include "integrations/integrationplugin.h"
#include "plugintimer.h" #include "plugintimer.h"
#include "extern-plugininfo.h"
class QHostAddress;
class ZeroConfServiceBrowser;
class SomfyTahomaRequest; class SomfyTahomaRequest;
class IntegrationPluginSomfyTahoma : public IntegrationPlugin class IntegrationPluginSomfyTahoma : public IntegrationPlugin
@ -44,6 +50,9 @@ class IntegrationPluginSomfyTahoma : public IntegrationPlugin
Q_INTERFACES(IntegrationPlugin) Q_INTERFACES(IntegrationPlugin)
public: public:
void init() override;
void discoverThings(ThingDiscoveryInfo *info) override;
void startPairing(ThingPairingInfo *info) override; void startPairing(ThingPairingInfo *info) override;
void confirmPairing(ThingPairingInfo *info, const QString &username, const QString &password) override; void confirmPairing(ThingPairingInfo *info, const QString &username, const QString &password) override;
@ -54,14 +63,16 @@ public:
void executeAction(ThingActionInfo *info) override; void executeAction(ThingActionInfo *info) override;
private: private:
SomfyTahomaRequest *createLoginRequestWithStoredCredentials(Thing *thing); void refreshGateway(Thing *thing);
void refreshAccount(Thing *thing); void handleEvents(const QVariantList &events);
void handleEvents(const QVariantList &eventList);
void updateThingStates(const QString &deviceUrl, const QVariantList &stateList); void updateThingStates(const QString &deviceUrl, const QVariantList &stateList);
void markDisconnected(Thing *thing); void markDisconnected(Thing *thing);
void restoreChildConnectedState(Thing *thing); void restoreChildConnectedState(Thing *thing);
QString getHost(Thing *thing) const;
QString getToken(Thing *thing) const;
private: private:
ZeroConfServiceBrowser *m_zeroConfBrowser = nullptr;
QMap<Thing *, PluginTimer *> m_eventPollTimer; QMap<Thing *, PluginTimer *> m_eventPollTimer;
QMap<QString, QPointer<ThingActionInfo>> m_pendingActions; QMap<QString, QPointer<ThingActionInfo>> m_pendingActions;
QMap<QString, QList<Thing *>> m_currentExecutions; QMap<QString, QList<Thing *>> m_currentExecutions;

View File

@ -12,8 +12,7 @@
"id": "fedd72b8-547d-4e4f-b73e-71344a8ba0c1", "id": "fedd72b8-547d-4e4f-b73e-71344a8ba0c1",
"name": "tahoma", "name": "tahoma",
"displayName": "Tahoma Account", "displayName": "Tahoma Account",
"createMethods": ["user"], "createMethods": ["auto"],
"setupMethod": "userandpassword",
"interfaces": ["account"], "interfaces": ["account"],
"stateTypes": [ "stateTypes": [
{ {
@ -46,14 +45,23 @@
"id": "6c09e0b9-f0cc-4dea-9994-9e039eff78f1", "id": "6c09e0b9-f0cc-4dea-9994-9e039eff78f1",
"name": "gateway", "name": "gateway",
"displayName": "Tahoma Gateway", "displayName": "Tahoma Gateway",
"createMethods": ["auto"], "createMethods": ["discovery"],
"setupMethod": "userandpassword",
"interfaces": ["gateway"], "interfaces": ["gateway"],
"paramTypes": [ "paramTypes": [
{ {
"id": "e321a7d6-6dcb-4a37-baf1-c7008f2d5bdb", "id": "e321a7d6-6dcb-4a37-baf1-c7008f2d5bdb",
"displayName": "Gateway Id", "displayName": "Gateway Id",
"name": "gatewayId", "name": "gatewayId",
"type": "QString" "type": "QString",
"readOnly": true
},
{
"id": "30b73244-e5bb-4c00-9332-702a60c03420",
"displayName": "Gateway pin",
"name": "gatewayPin",
"type": "QString",
"readOnly": true
} }
], ],
"stateTypes": [ "stateTypes": [

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2020, nymea GmbH * Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
* *
* This file is part of nymea. * This file is part of nymea.
@ -38,7 +38,8 @@
#include "extern-plugininfo.h" #include "extern-plugininfo.h"
static const QString somfyTahomaUrl = QStringLiteral("https://tahomalink.com/enduser-mobile-web/enduserAPI"); static const QString somfyTahomaWebUrl = QStringLiteral("https://ha101-1.overkiz.com/enduser-mobile-web/enduserAPI");
static const QString localSomfyTahomaPath = QStringLiteral("/enduser-mobile-web/1/enduserAPI");
SomfyTahomaRequest::SomfyTahomaRequest(QNetworkReply *reply, QObject *parent) : QObject(parent) SomfyTahomaRequest::SomfyTahomaRequest(QNetworkReply *reply, QObject *parent) : QObject(parent)
{ {
@ -64,32 +65,73 @@ SomfyTahomaRequest::SomfyTahomaRequest(QNetworkReply *reply, QObject *parent) :
}); });
} }
SomfyTahomaRequest *createSomfyTahomaPostRequest(NetworkAccessManager *networkManager, const QString &path, const QString &contentType, const QByteArray &body, QObject *parent) SomfyTahomaRequest *createCloudSomfyTahomaPostRequest(NetworkAccessManager *networkManager, const QString &path, const QString &contentType, const QByteArray &body, QObject *parent)
{ {
QUrl url(somfyTahomaUrl + path); QUrl url(somfyTahomaWebUrl + path);
QNetworkRequest request(url); QNetworkRequest request(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, contentType); request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, contentType);
QNetworkReply *reply = networkManager->post(request, body); QNetworkReply *reply = networkManager->post(request, body);
return new SomfyTahomaRequest(reply, parent); return new SomfyTahomaRequest(reply, parent);
} }
SomfyTahomaRequest *createSomfyTahomaGetRequest(NetworkAccessManager *networkManager, const QString &path, QObject *parent) SomfyTahomaRequest *createCloudSomfyTahomaGetRequest(NetworkAccessManager *networkManager, const QString &path, QObject *parent)
{ {
QUrl url(somfyTahomaUrl + path); QUrl url(somfyTahomaWebUrl + path);
QNetworkRequest request(url); QNetworkRequest request(url);
QNetworkReply *reply = networkManager->get(request); QNetworkReply *reply = networkManager->get(request);
return new SomfyTahomaRequest(reply, parent); return new SomfyTahomaRequest(reply, parent);
} }
SomfyTahomaRequest *createSomfyTahomaLoginRequest(NetworkAccessManager *networkManager, const QString &username, const QString &password, QObject *parent) SomfyTahomaRequest *createCloudSomfyTahomaDeleteRequest(NetworkAccessManager *networkManager, const QString &path, QObject *parent)
{
QUrl url(somfyTahomaWebUrl + path);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentLengthHeader, 0);
QNetworkReply *reply = networkManager->deleteResource(request);
return new SomfyTahomaRequest(reply, parent);
}
SomfyTahomaRequest *createCloudSomfyTahomaLoginRequest(NetworkAccessManager *networkManager, const QString &username, const QString &password, QObject *parent)
{ {
QUrlQuery postData; QUrlQuery postData;
postData.addQueryItem("userId", username); postData.addQueryItem("userId", username);
postData.addQueryItem("userPassword", password); postData.addQueryItem("userPassword", password);
return createSomfyTahomaPostRequest(networkManager, "/login", "application/x-www-form-urlencoded", postData.toString(QUrl::FullyEncoded).toUtf8(), parent); return createCloudSomfyTahomaPostRequest(networkManager, "/login", "application/x-www-form-urlencoded", postData.toString(QUrl::FullyEncoded).toUtf8(), parent);
} }
SomfyTahomaRequest *createSomfyTahomaEventFetchRequest(NetworkAccessManager *networkManager, const QString &eventListenerId, QObject *parent) SomfyTahomaRequest *createLocalSomfyTahomaPostRequest(NetworkAccessManager *networkManager, const QString &host, const QString &token, const QString &path, const QString &contentType, const QByteArray &body, QObject *parent)
{ {
return createSomfyTahomaPostRequest(networkManager, "/events/" + eventListenerId + "/fetch", "application/json", QByteArray(), parent); QUrl url("https://" + host + localSomfyTahomaPath + path);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, contentType);
request.setRawHeader("Authorization", "Bearer " + token.toUtf8());
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
config.setPeerVerifyMode(QSslSocket::VerifyNone);
request.setSslConfiguration(config);
QNetworkReply *reply = networkManager->post(request, body);
return new SomfyTahomaRequest(reply, parent);
}
SomfyTahomaRequest *createLocalSomfyTahomaGetRequest(NetworkAccessManager *networkManager, const QString &host, const QString &token, const QString &path, QObject *parent)
{
QUrl url("https://" + host + localSomfyTahomaPath + path);
QNetworkRequest request(url);
request.setRawHeader("Authorization", "Bearer " + token.toUtf8());
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
config.setPeerVerifyMode(QSslSocket::VerifyNone);
request.setSslConfiguration(config);
QNetworkReply *reply = networkManager->get(request);
return new SomfyTahomaRequest(reply, parent);
}
SomfyTahomaRequest *createLocalSomfyTahomaEventFetchRequest(NetworkAccessManager *networkManager, const QString &host, const QString &token, const QString &eventListenerId, QObject *parent)
{
return createLocalSomfyTahomaPostRequest(networkManager, host, token, "/events/" + eventListenerId + "/fetch", "application/json", QByteArray(), parent);
} }

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2020, nymea GmbH * Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
* *
* This file is part of nymea. * This file is part of nymea.
@ -47,9 +47,14 @@ signals:
void finished(const QVariant &results); void finished(const QVariant &results);
}; };
SomfyTahomaRequest *createSomfyTahomaPostRequest(NetworkAccessManager *networkManager, const QString &path, const QString &contentType, const QByteArray &body, QObject *parent); SomfyTahomaRequest *createCloudSomfyTahomaPostRequest(NetworkAccessManager *networkManager, const QString &path, const QString &contentType, const QByteArray &body, QObject *parent);
SomfyTahomaRequest *createSomfyTahomaGetRequest(NetworkAccessManager *networkManager, const QString &path, QObject *parent); SomfyTahomaRequest *createCloudSomfyTahomaGetRequest(NetworkAccessManager *networkManager, const QString &path, QObject *parent);
SomfyTahomaRequest *createSomfyTahomaLoginRequest(NetworkAccessManager *networkManager, const QString &username, const QString &password, QObject *parent); SomfyTahomaRequest *createCloudSomfyTahomaDeleteRequest(NetworkAccessManager *networkManager, const QString &path, QObject *parent);
SomfyTahomaRequest *createSomfyTahomaEventFetchRequest(NetworkAccessManager *networkManager, const QString &eventListenerId, QObject *parent); SomfyTahomaRequest *createCloudSomfyTahomaLoginRequest(NetworkAccessManager *networkManager, const QString &username, const QString &password, QObject *parent);
SomfyTahomaRequest *createLocalSomfyTahomaPostRequest(NetworkAccessManager *networkManager, const QString &host, const QString &token, const QString &path, const QString &contentType, const QByteArray &body, QObject *parent);
SomfyTahomaRequest *createLocalSomfyTahomaGetRequest(NetworkAccessManager *networkManager, const QString &host, const QString &token, const QString &path, QObject *parent);
SomfyTahomaRequest *createLocalSomfyTahomaEventFetchRequest(NetworkAccessManager *networkManager, const QString &host, const QString &token, const QString &eventListenerId, QObject *parent);
#endif // SOMFYTAHOMAREQUESTS_H #endif // SOMFYTAHOMAREQUESTS_H

View File

@ -4,66 +4,67 @@
<context> <context>
<name>IntegrationPluginSomfyTahoma</name> <name>IntegrationPluginSomfyTahoma</name>
<message> <message>
<location filename="../integrationpluginsomfytahoma.cpp" line="44"/> <location filename="../integrationpluginsomfytahoma.cpp" line="74"/>
<source>Please enter the login credentials for Somfy Tahoma.</source> <source>Please enter the cloud login credentials for Somfy Tahoma in order to set up local access to the Gateway.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../integrationpluginsomfytahoma.cpp" line="51"/> <location filename="../integrationpluginsomfytahoma.cpp" line="82"/>
<location filename="../integrationpluginsomfytahoma.cpp" line="67"/>
<source>Failed to login to Somfy Tahoma.</source> <source>Failed to login to Somfy Tahoma.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../integrationpluginsomfytahoma.cpp" line="87"/>
<source>Failed to generate token.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginsomfytahoma.cpp" line="98"/>
<source>Failed to activate token.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginsomfytahoma.cpp" line="122"/>
<source>The Somfy Plugin switched to local connection. Please enable &apos;Developer Mode&apos; on somfy.com, remove the account from Nymea and re-setup the Somfy Tahoma Gateway.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginsomfytahoma.cpp" line="129"/>
<source>Failed to connect to gateway.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SomfyTahoma</name> <name>SomfyTahoma</name>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="144"/> <location filename="../../build/somfytahoma/plugininfo.h" line="93"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="147"/> <location filename="../../build/somfytahoma/plugininfo.h" line="96"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="150"/>
<source>Angle</source> <source>Angle</source>
<extracomment>The name of the ParamType (ThingClass: venetianblind, ActionType: angle, ID: {079c7a80-8a1c-4fd7-b40c-6800120c70fb}) <extracomment>The name of the ParamType (ThingClass: venetianblind, ActionType: angle, ID: {079c7a80-8a1c-4fd7-b40c-6800120c70fb})
---------- ----------
The name of the ParamType (ThingClass: venetianblind, EventType: angle, ID: {079c7a80-8a1c-4fd7-b40c-6800120c70fb})
----------
The name of the StateType ({079c7a80-8a1c-4fd7-b40c-6800120c70fb}) of ThingClass venetianblind</extracomment> The name of the StateType ({079c7a80-8a1c-4fd7-b40c-6800120c70fb}) of ThingClass venetianblind</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="153"/> <location filename="../../build/somfytahoma/plugininfo.h" line="99"/>
<source>Angle changed</source>
<extracomment>The name of the EventType ({079c7a80-8a1c-4fd7-b40c-6800120c70fb}) of ThingClass venetianblind</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../build/somfytahoma/plugininfo.h" line="156"/>
<source>Awning</source> <source>Awning</source>
<extracomment>The name of the ThingClass ({d3a3bb40-4b2d-4bdc-989f-5254f03b4c90})</extracomment> <extracomment>The name of the ThingClass ({d3a3bb40-4b2d-4bdc-989f-5254f03b4c90})</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="159"/> <location filename="../../build/somfytahoma/plugininfo.h" line="102"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="162"/> <location filename="../../build/somfytahoma/plugininfo.h" line="105"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="165"/>
<source>Brightness</source> <source>Brightness</source>
<extracomment>The name of the ParamType (ThingClass: light, ActionType: brightness, ID: {1b51ce68-1f7e-4f06-b68d-bfca2d61b353}) <extracomment>The name of the ParamType (ThingClass: light, ActionType: brightness, ID: {1b51ce68-1f7e-4f06-b68d-bfca2d61b353})
---------- ----------
The name of the ParamType (ThingClass: light, EventType: brightness, ID: {1b51ce68-1f7e-4f06-b68d-bfca2d61b353})
----------
The name of the StateType ({1b51ce68-1f7e-4f06-b68d-bfca2d61b353}) of ThingClass light</extracomment> The name of the StateType ({1b51ce68-1f7e-4f06-b68d-bfca2d61b353}) of ThingClass light</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="168"/> <location filename="../../build/somfytahoma/plugininfo.h" line="108"/>
<source>Brightness changed</source> <location filename="../../build/somfytahoma/plugininfo.h" line="111"/>
<extracomment>The name of the EventType ({1b51ce68-1f7e-4f06-b68d-bfca2d61b353}) of ThingClass light</extracomment> <location filename="../../build/somfytahoma/plugininfo.h" line="114"/>
<translation type="unfinished"></translation> <location filename="../../build/somfytahoma/plugininfo.h" line="117"/>
</message>
<message>
<location filename="../../build/somfytahoma/plugininfo.h" line="171"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="174"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="177"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="180"/>
<source>Close</source> <source>Close</source>
<extracomment>The name of the ActionType ({20cae53b-f36d-425b-b937-3e46519893a3}) of ThingClass awning <extracomment>The name of the ActionType ({20cae53b-f36d-425b-b937-3e46519893a3}) of ThingClass awning
---------- ----------
@ -75,80 +76,35 @@ The name of the ActionType ({baf377c6-9fba-44cf-9f14-af0101f874b5}) of ThingClas
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="183"/> <location filename="../../build/somfytahoma/plugininfo.h" line="120"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="186"/> <location filename="../../build/somfytahoma/plugininfo.h" line="123"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="189"/> <location filename="../../build/somfytahoma/plugininfo.h" line="126"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="192"/> <location filename="../../build/somfytahoma/plugininfo.h" line="129"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="195"/> <location filename="../../build/somfytahoma/plugininfo.h" line="132"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="198"/> <location filename="../../build/somfytahoma/plugininfo.h" line="135"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="201"/> <location filename="../../build/somfytahoma/plugininfo.h" line="138"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="204"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="207"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="210"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="213"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="216"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="219"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="222"/>
<source>Connected</source> <source>Connected</source>
<extracomment>The name of the ParamType (ThingClass: light, EventType: connected, ID: {fb8dcd84-70ad-4f3e-97c4-93296608e33d}) <extracomment>The name of the StateType ({fb8dcd84-70ad-4f3e-97c4-93296608e33d}) of ThingClass light
----------
The name of the StateType ({fb8dcd84-70ad-4f3e-97c4-93296608e33d}) of ThingClass light
----------
The name of the ParamType (ThingClass: awning, EventType: connected, ID: {8f972969-10dd-4954-9c8b-de56070a6668})
---------- ----------
The name of the StateType ({8f972969-10dd-4954-9c8b-de56070a6668}) of ThingClass awning The name of the StateType ({8f972969-10dd-4954-9c8b-de56070a6668}) of ThingClass awning
---------- ----------
The name of the ParamType (ThingClass: garagedoor, EventType: connected, ID: {5a32cbd3-bc1c-4724-ae53-9f36cb75bf84})
----------
The name of the StateType ({5a32cbd3-bc1c-4724-ae53-9f36cb75bf84}) of ThingClass garagedoor The name of the StateType ({5a32cbd3-bc1c-4724-ae53-9f36cb75bf84}) of ThingClass garagedoor
---------- ----------
The name of the ParamType (ThingClass: venetianblind, EventType: connected, ID: {57361115-edbe-49fb-9847-408b571d3108})
----------
The name of the StateType ({57361115-edbe-49fb-9847-408b571d3108}) of ThingClass venetianblind The name of the StateType ({57361115-edbe-49fb-9847-408b571d3108}) of ThingClass venetianblind
---------- ----------
The name of the ParamType (ThingClass: rollershutter, EventType: connected, ID: {7a49865d-5ea5-43be-b61f-4e454c48e87e})
----------
The name of the StateType ({7a49865d-5ea5-43be-b61f-4e454c48e87e}) of ThingClass rollershutter The name of the StateType ({7a49865d-5ea5-43be-b61f-4e454c48e87e}) of ThingClass rollershutter
---------- ----------
The name of the ParamType (ThingClass: gateway, EventType: connected, ID: {18ba7fb7-c9e8-4c61-86b3-a8d3b825ed00})
----------
The name of the StateType ({18ba7fb7-c9e8-4c61-86b3-a8d3b825ed00}) of ThingClass gateway The name of the StateType ({18ba7fb7-c9e8-4c61-86b3-a8d3b825ed00}) of ThingClass gateway
---------- ----------
The name of the ParamType (ThingClass: tahoma, EventType: connected, ID: {10ebf650-a93a-4ee3-945b-fba10d4e35a5})
----------
The name of the StateType ({10ebf650-a93a-4ee3-945b-fba10d4e35a5}) of ThingClass tahoma</extracomment> The name of the StateType ({10ebf650-a93a-4ee3-945b-fba10d4e35a5}) of ThingClass tahoma</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="225"/> <location filename="../../build/somfytahoma/plugininfo.h" line="141"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="228"/> <location filename="../../build/somfytahoma/plugininfo.h" line="144"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="231"/> <location filename="../../build/somfytahoma/plugininfo.h" line="147"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="234"/> <location filename="../../build/somfytahoma/plugininfo.h" line="150"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="237"/> <location filename="../../build/somfytahoma/plugininfo.h" line="153"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="240"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="243"/>
<source>Connetion state changed</source>
<extracomment>The name of the EventType ({fb8dcd84-70ad-4f3e-97c4-93296608e33d}) of ThingClass light
----------
The name of the EventType ({8f972969-10dd-4954-9c8b-de56070a6668}) of ThingClass awning
----------
The name of the EventType ({5a32cbd3-bc1c-4724-ae53-9f36cb75bf84}) of ThingClass garagedoor
----------
The name of the EventType ({57361115-edbe-49fb-9847-408b571d3108}) of ThingClass venetianblind
----------
The name of the EventType ({7a49865d-5ea5-43be-b61f-4e454c48e87e}) of ThingClass rollershutter
----------
The name of the EventType ({18ba7fb7-c9e8-4c61-86b3-a8d3b825ed00}) of ThingClass gateway
----------
The name of the EventType ({10ebf650-a93a-4ee3-945b-fba10d4e35a5}) of ThingClass tahoma</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../build/somfytahoma/plugininfo.h" line="246"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="249"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="252"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="255"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="258"/>
<source>Device URL</source> <source>Device URL</source>
<extracomment>The name of the ParamType (ThingClass: light, Type: thing, ID: {9cd2e0f2-a02f-478a-9358-6ff0f5aba9f5}) <extracomment>The name of the ParamType (ThingClass: light, Type: thing, ID: {9cd2e0f2-a02f-478a-9358-6ff0f5aba9f5})
---------- ----------
@ -162,85 +118,49 @@ The name of the ParamType (ThingClass: rollershutter, Type: thing, ID: {b3d20d6a
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="261"/> <location filename="../../build/somfytahoma/plugininfo.h" line="156"/>
<source>Garage Door</source> <source>Garage Door</source>
<extracomment>The name of the ThingClass ({cb206d74-b13c-4466-98c6-070b19ebd23a})</extracomment> <extracomment>The name of the ThingClass ({cb206d74-b13c-4466-98c6-070b19ebd23a})</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="264"/> <location filename="../../build/somfytahoma/plugininfo.h" line="159"/>
<source>Gateway Id</source> <source>Gateway Id</source>
<extracomment>The name of the ParamType (ThingClass: gateway, Type: thing, ID: {e321a7d6-6dcb-4a37-baf1-c7008f2d5bdb})</extracomment> <extracomment>The name of the ParamType (ThingClass: gateway, Type: thing, ID: {e321a7d6-6dcb-4a37-baf1-c7008f2d5bdb})</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="267"/> <location filename="../../build/somfytahoma/plugininfo.h" line="165"/>
<source>Light</source> <source>Light</source>
<extracomment>The name of the ThingClass ({e569a3cc-6e79-4e24-af35-c5fa327a7314})</extracomment> <extracomment>The name of the ThingClass ({e569a3cc-6e79-4e24-af35-c5fa327a7314})</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="270"/> <location filename="../../build/somfytahoma/plugininfo.h" line="168"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="273"/>
<source>Logged in</source> <source>Logged in</source>
<extracomment>The name of the ParamType (ThingClass: tahoma, EventType: loggedIn, ID: {97fefa85-db79-4efd-8d83-4a15d72996e1}) <extracomment>The name of the StateType ({97fefa85-db79-4efd-8d83-4a15d72996e1}) of ThingClass tahoma</extracomment>
----------
The name of the StateType ({97fefa85-db79-4efd-8d83-4a15d72996e1}) of ThingClass tahoma</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="276"/> <location filename="../../build/somfytahoma/plugininfo.h" line="171"/>
<source>Login state changed</source> <location filename="../../build/somfytahoma/plugininfo.h" line="174"/>
<extracomment>The name of the EventType ({97fefa85-db79-4efd-8d83-4a15d72996e1}) of ThingClass tahoma</extracomment> <location filename="../../build/somfytahoma/plugininfo.h" line="177"/>
<translation type="unfinished"></translation> <location filename="../../build/somfytahoma/plugininfo.h" line="180"/>
</message>
<message>
<location filename="../../build/somfytahoma/plugininfo.h" line="279"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="282"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="285"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="288"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="291"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="294"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="297"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="300"/>
<source>Moving</source> <source>Moving</source>
<extracomment>The name of the ParamType (ThingClass: awning, EventType: moving, ID: {2507ac5a-9658-42cb-80f6-73f673c32771}) <extracomment>The name of the StateType ({2507ac5a-9658-42cb-80f6-73f673c32771}) of ThingClass awning
----------
The name of the StateType ({2507ac5a-9658-42cb-80f6-73f673c32771}) of ThingClass awning
----------
The name of the ParamType (ThingClass: garagedoor, EventType: moving, ID: {07175175-f95d-4cd9-a398-9aab8232c2a9})
---------- ----------
The name of the StateType ({07175175-f95d-4cd9-a398-9aab8232c2a9}) of ThingClass garagedoor The name of the StateType ({07175175-f95d-4cd9-a398-9aab8232c2a9}) of ThingClass garagedoor
---------- ----------
The name of the ParamType (ThingClass: venetianblind, EventType: moving, ID: {48d5de0a-11ab-4801-94e4-a1dd458c341d})
----------
The name of the StateType ({48d5de0a-11ab-4801-94e4-a1dd458c341d}) of ThingClass venetianblind The name of the StateType ({48d5de0a-11ab-4801-94e4-a1dd458c341d}) of ThingClass venetianblind
---------- ----------
The name of the ParamType (ThingClass: rollershutter, EventType: moving, ID: {fa9446ba-da30-4d49-8fb6-f410ecc7dba0})
----------
The name of the StateType ({fa9446ba-da30-4d49-8fb6-f410ecc7dba0}) of ThingClass rollershutter</extracomment> The name of the StateType ({fa9446ba-da30-4d49-8fb6-f410ecc7dba0}) of ThingClass rollershutter</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="303"/> <location filename="../../build/somfytahoma/plugininfo.h" line="183"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="306"/> <location filename="../../build/somfytahoma/plugininfo.h" line="186"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="309"/> <location filename="../../build/somfytahoma/plugininfo.h" line="189"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="312"/> <location filename="../../build/somfytahoma/plugininfo.h" line="192"/>
<source>Moving changed</source>
<extracomment>The name of the EventType ({2507ac5a-9658-42cb-80f6-73f673c32771}) of ThingClass awning
----------
The name of the EventType ({07175175-f95d-4cd9-a398-9aab8232c2a9}) of ThingClass garagedoor
----------
The name of the EventType ({48d5de0a-11ab-4801-94e4-a1dd458c341d}) of ThingClass venetianblind
----------
The name of the EventType ({fa9446ba-da30-4d49-8fb6-f410ecc7dba0}) of ThingClass rollershutter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../build/somfytahoma/plugininfo.h" line="315"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="318"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="321"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="324"/>
<source>Open</source> <source>Open</source>
<extracomment>The name of the ActionType ({9612954c-02cb-4159-9a29-f36eaf1c7f6a}) of ThingClass awning <extracomment>The name of the ActionType ({9612954c-02cb-4159-9a29-f36eaf1c7f6a}) of ThingClass awning
---------- ----------
@ -252,100 +172,70 @@ The name of the ActionType ({a0460180-e799-4bc6-83ba-11731ef124a3}) of ThingClas
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="327"/> <location filename="../../build/somfytahoma/plugininfo.h" line="195"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="330"/> <location filename="../../build/somfytahoma/plugininfo.h" line="198"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="333"/> <location filename="../../build/somfytahoma/plugininfo.h" line="201"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="336"/> <location filename="../../build/somfytahoma/plugininfo.h" line="204"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="339"/> <location filename="../../build/somfytahoma/plugininfo.h" line="207"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="342"/> <location filename="../../build/somfytahoma/plugininfo.h" line="210"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="345"/> <location filename="../../build/somfytahoma/plugininfo.h" line="213"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="348"/> <location filename="../../build/somfytahoma/plugininfo.h" line="216"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="351"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="354"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="357"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="360"/>
<source>Percentage</source> <source>Percentage</source>
<extracomment>The name of the ParamType (ThingClass: awning, ActionType: percentage, ID: {c409cb9b-82ef-4f59-ae89-eb783d4ebe97}) <extracomment>The name of the ParamType (ThingClass: awning, ActionType: percentage, ID: {c409cb9b-82ef-4f59-ae89-eb783d4ebe97})
---------- ----------
The name of the ParamType (ThingClass: awning, EventType: percentage, ID: {c409cb9b-82ef-4f59-ae89-eb783d4ebe97})
----------
The name of the StateType ({c409cb9b-82ef-4f59-ae89-eb783d4ebe97}) of ThingClass awning The name of the StateType ({c409cb9b-82ef-4f59-ae89-eb783d4ebe97}) of ThingClass awning
---------- ----------
The name of the ParamType (ThingClass: garagedoor, ActionType: percentage, ID: {284816aa-842b-4a86-bb4e-ef5353b76762}) The name of the ParamType (ThingClass: garagedoor, ActionType: percentage, ID: {284816aa-842b-4a86-bb4e-ef5353b76762})
---------- ----------
The name of the ParamType (ThingClass: garagedoor, EventType: percentage, ID: {284816aa-842b-4a86-bb4e-ef5353b76762})
----------
The name of the StateType ({284816aa-842b-4a86-bb4e-ef5353b76762}) of ThingClass garagedoor The name of the StateType ({284816aa-842b-4a86-bb4e-ef5353b76762}) of ThingClass garagedoor
---------- ----------
The name of the ParamType (ThingClass: venetianblind, ActionType: percentage, ID: {77ca50db-42a7-4434-83e2-8b5fc4438924}) The name of the ParamType (ThingClass: venetianblind, ActionType: percentage, ID: {77ca50db-42a7-4434-83e2-8b5fc4438924})
---------- ----------
The name of the ParamType (ThingClass: venetianblind, EventType: percentage, ID: {77ca50db-42a7-4434-83e2-8b5fc4438924})
----------
The name of the StateType ({77ca50db-42a7-4434-83e2-8b5fc4438924}) of ThingClass venetianblind The name of the StateType ({77ca50db-42a7-4434-83e2-8b5fc4438924}) of ThingClass venetianblind
---------- ----------
The name of the ParamType (ThingClass: rollershutter, ActionType: percentage, ID: {f954ffc7-a6aa-4d30-aee0-0484631c3344}) The name of the ParamType (ThingClass: rollershutter, ActionType: percentage, ID: {f954ffc7-a6aa-4d30-aee0-0484631c3344})
---------- ----------
The name of the ParamType (ThingClass: rollershutter, EventType: percentage, ID: {f954ffc7-a6aa-4d30-aee0-0484631c3344})
----------
The name of the StateType ({f954ffc7-a6aa-4d30-aee0-0484631c3344}) of ThingClass rollershutter</extracomment> The name of the StateType ({f954ffc7-a6aa-4d30-aee0-0484631c3344}) of ThingClass rollershutter</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="363"/> <location filename="../../build/somfytahoma/plugininfo.h" line="219"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="366"/> <location filename="../../build/somfytahoma/plugininfo.h" line="222"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="369"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="372"/>
<source>Percentage changed</source>
<extracomment>The name of the EventType ({c409cb9b-82ef-4f59-ae89-eb783d4ebe97}) of ThingClass awning
----------
The name of the EventType ({284816aa-842b-4a86-bb4e-ef5353b76762}) of ThingClass garagedoor
----------
The name of the EventType ({77ca50db-42a7-4434-83e2-8b5fc4438924}) of ThingClass venetianblind
----------
The name of the EventType ({f954ffc7-a6aa-4d30-aee0-0484631c3344}) of ThingClass rollershutter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../build/somfytahoma/plugininfo.h" line="375"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="378"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="381"/>
<source>Power</source> <source>Power</source>
<extracomment>The name of the ParamType (ThingClass: light, ActionType: power, ID: {654ddcdf-b0b7-4c38-a70d-878f0f3857a5}) <extracomment>The name of the ParamType (ThingClass: light, ActionType: power, ID: {654ddcdf-b0b7-4c38-a70d-878f0f3857a5})
---------- ----------
The name of the ParamType (ThingClass: light, EventType: power, ID: {654ddcdf-b0b7-4c38-a70d-878f0f3857a5})
----------
The name of the StateType ({654ddcdf-b0b7-4c38-a70d-878f0f3857a5}) of ThingClass light</extracomment> The name of the StateType ({654ddcdf-b0b7-4c38-a70d-878f0f3857a5}) of ThingClass light</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="384"/> <location filename="../../build/somfytahoma/plugininfo.h" line="162"/>
<source>Power changed</source> <source>Gateway pin</source>
<extracomment>The name of the EventType ({654ddcdf-b0b7-4c38-a70d-878f0f3857a5}) of ThingClass light</extracomment> <extracomment>The name of the ParamType (ThingClass: gateway, Type: thing, ID: {30b73244-e5bb-4c00-9332-702a60c03420})</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="387"/> <location filename="../../build/somfytahoma/plugininfo.h" line="225"/>
<source>Roller Shutter</source> <source>Roller Shutter</source>
<extracomment>The name of the ThingClass ({6b187fe0-a987-462d-90ac-c48efc0d0fc0})</extracomment> <extracomment>The name of the ThingClass ({6b187fe0-a987-462d-90ac-c48efc0d0fc0})</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="390"/> <location filename="../../build/somfytahoma/plugininfo.h" line="228"/>
<source>Set angle</source> <source>Set angle</source>
<extracomment>The name of the ActionType ({079c7a80-8a1c-4fd7-b40c-6800120c70fb}) of ThingClass venetianblind</extracomment> <extracomment>The name of the ActionType ({079c7a80-8a1c-4fd7-b40c-6800120c70fb}) of ThingClass venetianblind</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="393"/> <location filename="../../build/somfytahoma/plugininfo.h" line="231"/>
<source>Set brightness</source> <source>Set brightness</source>
<extracomment>The name of the ActionType ({1b51ce68-1f7e-4f06-b68d-bfca2d61b353}) of ThingClass light</extracomment> <extracomment>The name of the ActionType ({1b51ce68-1f7e-4f06-b68d-bfca2d61b353}) of ThingClass light</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="396"/> <location filename="../../build/somfytahoma/plugininfo.h" line="234"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="399"/> <location filename="../../build/somfytahoma/plugininfo.h" line="237"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="402"/> <location filename="../../build/somfytahoma/plugininfo.h" line="240"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="405"/> <location filename="../../build/somfytahoma/plugininfo.h" line="243"/>
<source>Set percentage</source> <source>Set percentage</source>
<extracomment>The name of the ActionType ({c409cb9b-82ef-4f59-ae89-eb783d4ebe97}) of ThingClass awning <extracomment>The name of the ActionType ({c409cb9b-82ef-4f59-ae89-eb783d4ebe97}) of ThingClass awning
---------- ----------
@ -357,94 +247,52 @@ The name of the ActionType ({f954ffc7-a6aa-4d30-aee0-0484631c3344}) of ThingClas
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="408"/> <location filename="../../build/somfytahoma/plugininfo.h" line="246"/>
<source>Set power</source> <source>Set power</source>
<extracomment>The name of the ActionType ({654ddcdf-b0b7-4c38-a70d-878f0f3857a5}) of ThingClass light</extracomment> <extracomment>The name of the ActionType ({654ddcdf-b0b7-4c38-a70d-878f0f3857a5}) of ThingClass light</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="411"/> <location filename="../../build/somfytahoma/plugininfo.h" line="249"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="414"/> <location filename="../../build/somfytahoma/plugininfo.h" line="252"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="417"/> <location filename="../../build/somfytahoma/plugininfo.h" line="255"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="420"/> <location filename="../../build/somfytahoma/plugininfo.h" line="258"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="423"/> <location filename="../../build/somfytahoma/plugininfo.h" line="261"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="426"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="429"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="432"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="435"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="438"/>
<source>Signal strength</source> <source>Signal strength</source>
<extracomment>The name of the ParamType (ThingClass: light, EventType: signalStrength, ID: {cfaa5533-d26e-4545-9f44-6567c9d7888a}) <extracomment>The name of the StateType ({cfaa5533-d26e-4545-9f44-6567c9d7888a}) of ThingClass light
----------
The name of the StateType ({cfaa5533-d26e-4545-9f44-6567c9d7888a}) of ThingClass light
----------
The name of the ParamType (ThingClass: awning, EventType: signalStrength, ID: {b2ad6f4a-c507-45c3-a951-b344603cc3fc})
---------- ----------
The name of the StateType ({b2ad6f4a-c507-45c3-a951-b344603cc3fc}) of ThingClass awning The name of the StateType ({b2ad6f4a-c507-45c3-a951-b344603cc3fc}) of ThingClass awning
---------- ----------
The name of the ParamType (ThingClass: garagedoor, EventType: signalStrength, ID: {0a194091-3073-4912-9d84-f1d52c8534bd})
----------
The name of the StateType ({0a194091-3073-4912-9d84-f1d52c8534bd}) of ThingClass garagedoor The name of the StateType ({0a194091-3073-4912-9d84-f1d52c8534bd}) of ThingClass garagedoor
---------- ----------
The name of the ParamType (ThingClass: venetianblind, EventType: signalStrength, ID: {aee4f4e3-3445-441d-bdbb-631b0c5db942})
----------
The name of the StateType ({aee4f4e3-3445-441d-bdbb-631b0c5db942}) of ThingClass venetianblind The name of the StateType ({aee4f4e3-3445-441d-bdbb-631b0c5db942}) of ThingClass venetianblind
---------- ----------
The name of the ParamType (ThingClass: rollershutter, EventType: signalStrength, ID: {67594d96-47a2-4360-a1b8-79e4f22f9ed0})
----------
The name of the StateType ({67594d96-47a2-4360-a1b8-79e4f22f9ed0}) of ThingClass rollershutter</extracomment> The name of the StateType ({67594d96-47a2-4360-a1b8-79e4f22f9ed0}) of ThingClass rollershutter</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="441"/> <location filename="../../build/somfytahoma/plugininfo.h" line="264"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="444"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="447"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="450"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="453"/>
<source>Signal strength changed</source>
<extracomment>The name of the EventType ({cfaa5533-d26e-4545-9f44-6567c9d7888a}) of ThingClass light
----------
The name of the EventType ({b2ad6f4a-c507-45c3-a951-b344603cc3fc}) of ThingClass awning
----------
The name of the EventType ({0a194091-3073-4912-9d84-f1d52c8534bd}) of ThingClass garagedoor
----------
The name of the EventType ({aee4f4e3-3445-441d-bdbb-631b0c5db942}) of ThingClass venetianblind
----------
The name of the EventType ({67594d96-47a2-4360-a1b8-79e4f22f9ed0}) of ThingClass rollershutter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../build/somfytahoma/plugininfo.h" line="456"/>
<source>Somfy</source> <source>Somfy</source>
<extracomment>The name of the vendor ({4e42a22a-ccfb-4677-89e3-f7fa16bf6be0})</extracomment> <extracomment>The name of the vendor ({4e42a22a-ccfb-4677-89e3-f7fa16bf6be0})</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="459"/> <location filename="../../build/somfytahoma/plugininfo.h" line="267"/>
<source>Somfy Tahoma</source> <source>Somfy Tahoma</source>
<extracomment>The name of the plugin SomfyTahoma ({4e8be1c1-daa8-4e21-9e85-b2372ab1a450})</extracomment> <extracomment>The name of the plugin SomfyTahoma ({4e8be1c1-daa8-4e21-9e85-b2372ab1a450})</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="462"/> <location filename="../../build/somfytahoma/plugininfo.h" line="270"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="465"/>
<source>State</source> <source>State</source>
<extracomment>The name of the ParamType (ThingClass: garagedoor, EventType: state, ID: {12af28f1-475e-4d05-9bbb-adbb86dcd69c}) <extracomment>The name of the StateType ({12af28f1-475e-4d05-9bbb-adbb86dcd69c}) of ThingClass garagedoor</extracomment>
----------
The name of the StateType ({12af28f1-475e-4d05-9bbb-adbb86dcd69c}) of ThingClass garagedoor</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="468"/> <location filename="../../build/somfytahoma/plugininfo.h" line="273"/>
<source>State changed</source> <location filename="../../build/somfytahoma/plugininfo.h" line="276"/>
<extracomment>The name of the EventType ({12af28f1-475e-4d05-9bbb-adbb86dcd69c}) of ThingClass garagedoor</extracomment> <location filename="../../build/somfytahoma/plugininfo.h" line="279"/>
<translation type="unfinished"></translation> <location filename="../../build/somfytahoma/plugininfo.h" line="282"/>
</message>
<message>
<location filename="../../build/somfytahoma/plugininfo.h" line="471"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="474"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="477"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="480"/>
<source>Stop</source> <source>Stop</source>
<extracomment>The name of the ActionType ({33bec73b-4d15-493a-b553-bcee32c40ee1}) of ThingClass awning <extracomment>The name of the ActionType ({33bec73b-4d15-493a-b553-bcee32c40ee1}) of ThingClass awning
---------- ----------
@ -456,34 +304,25 @@ The name of the ActionType ({cbccf714-1188-4ac9-9c91-17fe2c99acb3}) of ThingClas
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="483"/> <location filename="../../build/somfytahoma/plugininfo.h" line="285"/>
<source>Tahoma Account</source> <source>Tahoma Account</source>
<extracomment>The name of the ThingClass ({fedd72b8-547d-4e4f-b73e-71344a8ba0c1})</extracomment> <extracomment>The name of the ThingClass ({fedd72b8-547d-4e4f-b73e-71344a8ba0c1})</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="486"/> <location filename="../../build/somfytahoma/plugininfo.h" line="288"/>
<source>Tahoma Gateway</source> <source>Tahoma Gateway</source>
<extracomment>The name of the ThingClass ({6c09e0b9-f0cc-4dea-9994-9e039eff78f1})</extracomment> <extracomment>The name of the ThingClass ({6c09e0b9-f0cc-4dea-9994-9e039eff78f1})</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="489"/> <location filename="../../build/somfytahoma/plugininfo.h" line="291"/>
<location filename="../../build/somfytahoma/plugininfo.h" line="492"/>
<source>User display name</source> <source>User display name</source>
<extracomment>The name of the ParamType (ThingClass: tahoma, EventType: userDisplayName, ID: {75609987-be60-4932-94f6-ead791b5fa58}) <extracomment>The name of the StateType ({75609987-be60-4932-94f6-ead791b5fa58}) of ThingClass tahoma</extracomment>
----------
The name of the StateType ({75609987-be60-4932-94f6-ead791b5fa58}) of ThingClass tahoma</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../../build/somfytahoma/plugininfo.h" line="495"/> <location filename="../../build/somfytahoma/plugininfo.h" line="294"/>
<source>User display name changed</source>
<extracomment>The name of the EventType ({75609987-be60-4932-94f6-ead791b5fa58}) of ThingClass tahoma</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../build/somfytahoma/plugininfo.h" line="498"/>
<source>Venetian Blind</source> <source>Venetian Blind</source>
<extracomment>The name of the ThingClass ({c7160205-d864-4194-b418-060fff60f0cb})</extracomment> <extracomment>The name of the ThingClass ({c7160205-d864-4194-b418-060fff60f0cb})</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>