From 5e40675829894e2ff16ee7abcfe77999ba36f5f4 Mon Sep 17 00:00:00 2001 From: "bernhard.trinnes" Date: Mon, 6 Jul 2020 19:36:38 +0200 Subject: [PATCH] cloud actions do now work --- lifx/README.md | 11 +- lifx/integrationpluginlifx.cpp | 219 ++++++++++++------ lifx/integrationpluginlifx.h | 10 +- lifx/integrationpluginlifx.json | 60 +++-- lifx/lifx.pro | 14 -- lifx/lifxcloud.cpp | 187 +++++++++------ lifx/lifxcloud.h | 23 +- lifx/{lifx.cpp => lifxlan.cpp} | 65 ++---- lifx/{lifx.h => lifxlan.h} | 24 +- lifx/meta.json | 2 +- ...4e00ee30-79e2-447b-8dcc-c34470f41992-de.ts | 91 ++++++-- ...0ee30-79e2-447b-8dcc-c34470f41992-en_US.ts | 91 ++++++-- 12 files changed, 488 insertions(+), 309 deletions(-) delete mode 100644 lifx/lifx.pro rename lifx/{lifx.cpp => lifxlan.cpp} (77%) rename lifx/{lifx.h => lifxlan.h} (87%) diff --git a/lifx/README.md b/lifx/README.md index 3ffe992e..efe39ff9 100644 --- a/lifx/README.md +++ b/lifx/README.md @@ -1,9 +1,18 @@ # Lifx -This plug-in implements the LAN API for Lifx devices +This plug-in integrates LIFX lights to nymea. ## Supported Things +* All LIFX lights + ## Requirements +* LIFX cloud access token. + ** Get the token from https://cloud.lifx.com/settings +* Internet connection +* The package 'nymea-plugin-lifx' must be installed. + ## More + +https://www.lifx.com/ diff --git a/lifx/integrationpluginlifx.cpp b/lifx/integrationpluginlifx.cpp index 81fb9731..db94783b 100644 --- a/lifx/integrationpluginlifx.cpp +++ b/lifx/integrationpluginlifx.cpp @@ -63,52 +63,45 @@ void IntegrationPluginLifx::init() m_brightnessStateTypeIds.insert(colorBulbThingClassId, colorBulbBrightnessStateTypeId); m_brightnessStateTypeIds.insert(dimmableBulbThingClassId, dimmableBulbBrightnessStateTypeId); - m_colorTemperatureStateTypeIds.insert(colorBulbThingClassId, colorBulbColorTemperatureStateTypeId); m_colorTemperatureStateTypeIds.insert(dimmableBulbThingClassId, dimmableBulbColorTemperatureStateTypeId); - m_hostAddressParamTypeIds.insert(colorBulbThingClassId, colorBulbThingHostParamTypeId); - m_hostAddressParamTypeIds.insert(dimmableBulbThingClassId, dimmableBulbThingHostParamTypeId); - - m_portParamTypeIds.insert(colorBulbThingClassId, colorBulbThingPortParamTypeId); - m_portParamTypeIds.insert(dimmableBulbThingClassId, dimmableBulbThingPortParamTypeId); - m_idParamTypeIds.insert(colorBulbThingClassId, colorBulbThingIdParamTypeId); m_idParamTypeIds.insert(dimmableBulbThingClassId, dimmableBulbThingIdParamTypeId); m_serviceBrowser = hardwareManager()->zeroConfController()->createServiceBrowser("_hap._tcp"); // discovers all homekit devices - QFile file; - file.setFileName("/tmp/products.json"); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - qCWarning(dcLifx()) << "Could not open products file" << file.errorString() << "file name:" << file.fileName(); - } else { - QJsonDocument productsJson = QJsonDocument::fromJson(file.readAll()); - file.close(); - - if (!productsJson.isArray()) { - qCWarning(dcLifx()) << "Products JSON is not a valid array"; - } else { - QJsonArray productsArray = productsJson.array().first().toObject().value("products").toArray(); - foreach (QJsonValue value, productsArray) { - QJsonObject object = value.toObject(); - Lifx::LifxProduct product; - product.pid = object["pid"].toInt(); - product.name = object["name"].toString(); - qCDebug(dcLifx()) << "Lifx product JSON, found product. PID:" << product.pid << "Name" << product.name; - QJsonObject features = object["features"].toObject(); - product.color = features["color"].toBool(); - product.infrared = features["infrared"].toBool(); - product.matrix = features["matrix"].toBool(); - product.multizone = features["multizone"].toBool(); - product.minColorTemperature = features["temperature_range"].toArray().first().toInt(); - product.maxColorTemperature = features["temperature_range"].toArray().last().toInt(); - product.chain = features["chain"].toBool(); - m_lifxProducts.insert(product.pid, product); - } - } - } + // TODO for LAN connection, get id and device features + // QFile file; + // file.setFileName("/tmp/products.json"); + // if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + // qCWarning(dcLifx()) << "Could not open products file" << file.errorString() << "file name:" << file.fileName(); + // } else { + // QJsonDocument productsJson = QJsonDocument::fromJson(file.readAll()); + // file.close(); + // if (!productsJson.isArray()) { + // qCWarning(dcLifx()) << "Products JSON is not a valid array"; + // } else { + // QJsonArray productsArray = productsJson.array().first().toObject().value("products").toArray(); + // foreach (QJsonValue value, productsArray) { + // QJsonObject object = value.toObject(); + // LifxLan::LifxProduct product; + // product.pid = object["pid"].toInt(); + // product.name = object["name"].toString(); + // qCDebug(dcLifx()) << "Lifx product JSON, found product. PID:" << product.pid << "Name" << product.name; + // QJsonObject features = object["features"].toObject(); + // product.color = features["color"].toBool(); + // product.infrared = features["infrared"].toBool(); + // product.matrix = features["matrix"].toBool(); + // product.multizone = features["multizone"].toBool(); + // product.minColorTemperature = features["temperature_range"].toArray().first().toInt(); + // product.maxColorTemperature = features["temperature_range"].toArray().last().toInt(); + // product.chain = features["chain"].toBool(); + // m_lifxProducts.insert(product.pid, product); + // } + // } + // } m_networkManager = hardwareManager()->networkManager(); } @@ -156,6 +149,7 @@ void IntegrationPluginLifx::confirmPairing(ThingPairingInfo *info, const QString void IntegrationPluginLifx::discoverThings(ThingDiscoveryInfo *info) { + // NOTE: the LAN API is not yet finished, to enable LAN discovery add "discovery" to the createMethods if ((info->thingClassId() == colorBulbThingClassId) || (info->thingClassId() == dimmableBulbThingClassId)) { QHash descriptors; foreach (const ZeroConfServiceEntry avahiEntry, m_serviceBrowser->serviceEntries()) { @@ -203,15 +197,20 @@ void IntegrationPluginLifx::setupThing(ThingSetupInfo *info) Thing *thing = info->thing(); if (thing->thingClassId() == colorBulbThingClassId || thing->thingClassId() == dimmableBulbThingClassId) { - Lifx *lifx = new Lifx(QHostAddress(thing->paramValue(m_hostAddressParamTypeIds.value(thing->thingClassId())).toString()), - thing->paramValue(m_portParamTypeIds.value(thing->thingClassId())).toInt(), this); - if(lifx->enable()) { - m_lifxConnections.insert(thing, lifx); - //TODO async setup - info->finish(Thing::ThingErrorNoError); - } else { - lifx->deleteLater(); + if (thing->parentId().isNull()) { + // Lifx LAN + //LifxLan *lifx = new LifxLan(, this); + //if(lifx->enable()) { + // m_lifxLanConnections.insert(thing, lifx); + //TODO async setup for LAN devices + // info->finish(Thing::ThingErrorNoError); + //} else { + // lifx->deleteLater(); info->finish(Thing::ThingErrorSetupFailed); + //} + } else { + // Lifx Cloud + info->finish(Thing::ThingErrorNoError); } } else if (thing->thingClassId() == lifxAccountThingClassId) { @@ -250,8 +249,9 @@ void IntegrationPluginLifx::postSetupThing(Thing *thing) if (!m_pluginTimer) { m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(60); connect(m_pluginTimer, &PluginTimer::timeout, this, [this]() { - foreach (Lifx *lifx, m_lifxConnections) { + foreach (LifxLan *lifx, m_lifxLanConnections) { Q_UNUSED(lifx) + //TODO update LAN device states } foreach (LifxCloud *lifx, m_lifxCloudConnections) { @@ -271,11 +271,11 @@ void IntegrationPluginLifx::executeAction(ThingActionInfo *info) Thing *thing = info->thing(); Action action = info->action(); bool cloudDevice = false; - Lifx *lifx; + LifxLan *lifx; LifxCloud *lifxCloud; - if (m_lifxConnections.contains(thing)) { - lifx = m_lifxConnections.value(thing); + if (m_lifxLanConnections.contains(thing)) { + lifx = m_lifxLanConnections.value(thing); } else if (m_lifxCloudConnections.contains(myThings().findById(thing->parentId()))) { lifxCloud = m_lifxCloudConnections.value(myThings().findById(thing->parentId())); cloudDevice = true; @@ -299,9 +299,13 @@ void IntegrationPluginLifx::executeAction(ThingActionInfo *info) } else if (action.actionTypeId() == colorBulbBrightnessActionTypeId) { - if (!thing->stateValue(colorBulbPowerStateTypeId).toBool()) - lifx->setPower(true); - + if (!thing->stateValue(colorBulbPowerStateTypeId).toBool()){ + if (cloudDevice) { + lifxCloud->setPower(lightId, true); + } else { + lifx->setPower(true); + } + } int brightness = info->action().param(colorBulbBrightnessActionBrightnessParamTypeId).value().toInt(); int requestId; if (cloudDevice) { @@ -313,8 +317,13 @@ void IntegrationPluginLifx::executeAction(ThingActionInfo *info) m_asyncActions.insert(requestId, info); } else if (action.actionTypeId() == colorBulbColorActionColorParamTypeId) { QRgb color = QColor(action.param(colorBulbColorActionColorParamTypeId).value().toString()).rgba(); - if (!thing->stateValue(colorBulbPowerStateTypeId).toBool()) - lifx->setPower(true); + if (!thing->stateValue(colorBulbPowerStateTypeId).toBool()){ + if (cloudDevice) { + lifxCloud->setPower(lightId, true); + } else { + lifx->setPower(true); + } + } int requestId; if (cloudDevice) { requestId = lifxCloud->setColor(lightId, color); @@ -325,8 +334,13 @@ void IntegrationPluginLifx::executeAction(ThingActionInfo *info) m_asyncActions.insert(requestId, info); } else if (action.actionTypeId() == colorBulbColorTemperatureActionTypeId) { int colorTemperature = 6500 - (action.param(colorBulbColorTemperatureActionColorTemperatureParamTypeId).value().toUInt() * -11.12); - if (!thing->stateValue(colorBulbPowerStateTypeId).toBool()) - lifx->setPower(true); + if (!thing->stateValue(colorBulbPowerStateTypeId).toBool()){ + if (cloudDevice) { + lifxCloud->setPower(lightId, true); + } else { + lifx->setPower(true); + } + } int requestId; if (cloudDevice) { requestId = lifxCloud->setColorTemperature(lightId, colorTemperature); @@ -335,6 +349,40 @@ void IntegrationPluginLifx::executeAction(ThingActionInfo *info) } connect(info, &ThingActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);}); m_asyncActions.insert(requestId, info); + } else if (action.actionTypeId() == colorBulbEffectStateTypeId) { + if (!thing->stateValue(colorBulbPowerStateTypeId).toBool()){ + if (cloudDevice) { + lifxCloud->setPower(lightId, true); + } else { + lifx->setPower(true); + } + } + QString effectString = action.param(colorBulbColorTemperatureActionColorTemperatureParamTypeId).value().toString(); + int requestId; + LifxCloud::Effect effect; + if (effectString == "None") { + effect = LifxCloud::EffectNone; + } else if (effectString == "Breathe") { + effect = LifxCloud::EffectBreathe; + } else if (effectString == "Move") { + effect = LifxCloud::EffectMove; + } else if (effectString == "Morph") { + effect = LifxCloud::EffectMove; + } else if (effectString == "Flame") { + effect = LifxCloud::EffectMove; + } else if (effectString == "Pulse") { + effect = LifxCloud::EffectMove; + } + if (cloudDevice) { + QColor color = QColor(thing->stateValue(colorBulbColorStateTypeId).toString()); + requestId = lifxCloud->setEffect(lightId, effect, color); + } else { + qCWarning(dcLifx()) << "LAN devices are not yet supported"; + info->finish(Thing::ThingErrorHardwareNotAvailable); + return; + } + connect(info, &ThingActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);}); + m_asyncActions.insert(requestId, info); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } @@ -351,8 +399,13 @@ void IntegrationPluginLifx::executeAction(ThingActionInfo *info) connect(info, &ThingActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);}); } else if (action.actionTypeId() == dimmableBulbBrightnessActionTypeId) { int brightness = action.param(dimmableBulbBrightnessActionBrightnessParamTypeId).value().toInt(); - if (!thing->stateValue(dimmableBulbPowerStateTypeId).toBool()) - lifx->setPower(true); + if (!thing->stateValue(colorBulbPowerStateTypeId).toBool()){ + if (cloudDevice) { + lifxCloud->setPower(lightId, true); + } else { + lifx->setPower(true); + } + } int requestId; if (cloudDevice) { requestId = lifxCloud->setBrightnesss(lightId, brightness); @@ -361,6 +414,39 @@ void IntegrationPluginLifx::executeAction(ThingActionInfo *info) } connect(info, &ThingActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);}); m_asyncActions.insert(requestId, info); + } else if (action.actionTypeId() == dimmableBulbEffectStateTypeId) { + if (!thing->stateValue(colorBulbPowerStateTypeId).toBool()){ + if (cloudDevice) { + lifxCloud->setPower(lightId, true); + } else { + lifx->setPower(true); + } + } + QString effectString = action.param(dimmableBulbColorTemperatureActionColorTemperatureParamTypeId).value().toString(); + int requestId; + LifxCloud::Effect effect; + if (effectString == "None") { + effect = LifxCloud::EffectNone; + } else if (effectString == "Breathe") { + effect = LifxCloud::EffectBreathe; + } else if (effectString == "Move") { + effect = LifxCloud::EffectMove; + } else if (effectString == "Morph") { + effect = LifxCloud::EffectMove; + } else if (effectString == "Flame") { + effect = LifxCloud::EffectMove; + } else if (effectString == "Pulse") { + effect = LifxCloud::EffectMove; + } + if (cloudDevice) { + requestId = lifxCloud->setEffect(lightId, effect, QColor("0xffffff")); + } else { + qCWarning(dcLifx()) << "LAN devices are not yet supported"; + info->finish(Thing::ThingErrorHardwareNotAvailable); + return; + } + connect(info, &ThingActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);}); + m_asyncActions.insert(requestId, info); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8()); } @@ -372,8 +458,8 @@ void IntegrationPluginLifx::executeAction(ThingActionInfo *info) void IntegrationPluginLifx::thingRemoved(Thing *thing) { if (thing->thingClassId() == colorBulbThingClassId || thing->thingClassId() == dimmableBulbThingClassId) { - if (m_lifxConnections.contains(thing)) - m_lifxConnections.take(thing)->deleteLater(); + if (m_lifxLanConnections.contains(thing)) + m_lifxLanConnections.take(thing)->deleteLater(); } else if (thing->thingClassId() == lifxAccountThingClassId) { if (m_lifxCloudConnections.contains(thing)) m_lifxCloudConnections.take(thing)->deleteLater(); @@ -412,17 +498,17 @@ void IntegrationPluginLifx::executeBrowserItem(BrowserActionInfo *info) connect(info, &BrowserActionInfo::aborted, this, [requestId, this] {m_asyncBrowserItem.remove(requestId);}); } -void IntegrationPluginLifx::onConnectionChanged(bool connected) +void IntegrationPluginLifx::onLifxLanConnectionChanged(bool connected) { Q_UNUSED(connected) - Lifx *lifx = static_cast(sender()); - Thing *thing = m_lifxConnections.key(lifx); + LifxLan *lifx = static_cast(sender()); + Thing *thing = m_lifxLanConnections.key(lifx); if (!thing) return; thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), connected); } -void IntegrationPluginLifx::onRequestExecuted(int requestId, bool success) +void IntegrationPluginLifx::onLifxLanRequestExecuted(int requestId, bool success) { if (m_asyncActions.contains(requestId)) { ThingActionInfo *info = m_asyncActions.take(requestId); @@ -492,8 +578,8 @@ void IntegrationPluginLifx::onLifxCloudLightsListReceived(const QListid()); foreach (Thing * thing, myThings().filterByParam(m_idParamTypeIds.value(thingClassId), light.id)) { thing->setStateValue(m_connectedStateTypeIds.value(thingClassId), light.connected); - thing->setStateValue(m_brightnessStateTypeIds.value(thingClassId), light.brightness); - thing->setStateValue(m_colorTemperatureStateTypeIds.value(thingClassId), light.colorTemperature); + thing->setStateValue(m_brightnessStateTypeIds.value(thingClassId), light.brightness*100.00); + thing->setStateValue(m_colorTemperatureStateTypeIds.value(thingClassId), light.colorTemperature); //TODO Kelvin to mired thing->setStateValue(m_powerStateTypeIds.value(thingClassId), light.power); if (thingClassId == colorBulbThingClassId) { thing->setStateValue(colorBulbColorStateTypeId, light.color); @@ -537,7 +623,6 @@ void IntegrationPluginLifx::onLifxCloudRequestExecuted(int requestId, bool succe } } - void IntegrationPluginLifx::onLifxCloudScenesListReceived(const QList &scenes) { LifxCloud *lifxCloud = static_cast(sender()); diff --git a/lifx/integrationpluginlifx.h b/lifx/integrationpluginlifx.h index 788e4b85..2b440d5d 100644 --- a/lifx/integrationpluginlifx.h +++ b/lifx/integrationpluginlifx.h @@ -33,7 +33,7 @@ #include "integrations/integrationplugin.h" #include "plugintimer.h" -#include "lifx.h" +#include "lifxlan.h" #include "lifxcloud.h" #include "network/networkaccessmanager.h" @@ -71,7 +71,7 @@ private: PluginTimer *m_pluginTimer = nullptr; QHash m_asyncCloudSetups; QHash m_asyncActions; - QHash m_lifxConnections; + QHash m_lifxLanConnections; QHash m_lifxCloudConnections; QHash m_asyncBrowseResults; QHash m_asyncBrowserItem; @@ -87,11 +87,11 @@ private: QHash m_idParamTypeIds; QHash m_pendingBrightnessAction; - QHash m_lifxProducts; + QHash m_lifxProducts; private slots: - void onConnectionChanged(bool connected); - void onRequestExecuted(int requestId, bool success); + void onLifxLanConnectionChanged(bool connected); + void onLifxLanRequestExecuted(int requestId, bool success); void onLifxCloudConnectionChanged(bool connected); void onLifxCloudAuthenticationChanged(bool authenticated); diff --git a/lifx/integrationpluginlifx.json b/lifx/integrationpluginlifx.json index eb69ebbd..59f4e486 100644 --- a/lifx/integrationpluginlifx.json +++ b/lifx/integrationpluginlifx.json @@ -51,23 +51,9 @@ "id": "12907c9c-e7f0-47f2-bd58-39d52ffdf24e", "name": "colorBulb", "displayName": "Color", - "createMethods": ["auto", "discovery"], + "createMethods": ["auto"], "interfaces": ["colorlight", "connectable"], "paramTypes": [ - { - "id": "fd1c4817-5111-433a-b5b9-fd9f49d4975c", - "name": "host", - "displayName": "Host address", - "type" : "QString", - "readOnly": true - }, - { - "id": "44c13745-300c-491f-b617-3a8d53472998", - "name": "port", - "displayName": "Port", - "type" : "int", - "readOnly": true - }, { "id": "976ecea0-ac25-47d4-9dc5-362962ddb6c0", "name": "id", @@ -139,10 +125,14 @@ "displayNameEvent": "Effect changed", "displayNameAction": "Set effect", "type": "QString", - "defaultValue": "none", + "defaultValue": "None", "possibleValues": [ - "none", - "color loop" + "None", + "Breathe", + "Move", + "Morph", + "Flame", + "Pulse" ], "writable": true } @@ -152,23 +142,9 @@ "id": "a5b02af8-7c97-4a78-9c78-bafee7407b5e", "name": "dimmableBulb", "displayName": "Day and Dusk", - "createMethods": ["auto", "discovery"], + "createMethods": ["auto"], "interfaces": ["colortemperaturelight", "connectable"], "paramTypes": [ - { - "id": "cc0a765b-a753-4e07-a6e5-47e9272c4346", - "name": "host", - "displayName": "Host address", - "type" : "QString", - "readOnly": true - }, - { - "id": "d233d9bf-6662-414d-92f6-dd3e267051b5", - "name": "port", - "displayName": "Port", - "type" : "int", - "readOnly": true - }, { "id": "f157a97b-3fe5-4d9e-b5e3-5636f80d46ed", "name": "id", @@ -221,6 +197,24 @@ "minValue": 153, "maxValue": 500, "writable": true + }, + { + "id": "be47c474-eca1-479e-9393-68281a43d72a", + "name": "effect", + "displayName": "Effect", + "displayNameEvent": "Effect changed", + "displayNameAction": "Set effect", + "type": "QString", + "defaultValue": "None", + "possibleValues": [ + "None", + "Breathe", + "Move", + "Morph", + "Flame", + "Pulse" + ], + "writable": true } ] } diff --git a/lifx/lifx.pro b/lifx/lifx.pro deleted file mode 100644 index 802b5391..00000000 --- a/lifx/lifx.pro +++ /dev/null @@ -1,14 +0,0 @@ -include(../plugins.pri) - -QT += network - -SOURCES += \ - integrationpluginlifx.cpp \ - lifx.cpp \ - lifxcloud.cpp \ - -HEADERS += \ - integrationpluginlifx.h \ - lifx.h \ - lifxcloud.h \ - diff --git a/lifx/lifxcloud.cpp b/lifx/lifxcloud.cpp index 4b3d13f9..e9c2c3a5 100644 --- a/lifx/lifxcloud.cpp +++ b/lifx/lifxcloud.cpp @@ -74,21 +74,9 @@ void LifxCloud::listLights() QNetworkReply *reply = m_networkManager->get(request); connect(reply, &QNetworkReply::finished, &QNetworkReply::deleteLater); connect(reply, &QNetworkReply::finished, this, [reply, this] { - int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - - // check HTTP status code - if (status > 207) { - qCWarning(dcLifx()) << "Error get lights list" << status << reply->errorString(); + if(!checkHttpStatusCode(reply)) { return; } - if (!m_authenticated) { - m_authenticated = true; - emit authenticationChanged(true); - } - if (!m_connected) { - m_connected = true; - emit authenticationChanged(true); - } QByteArray rawData = reply->readAll(); QJsonDocument data; QJsonParseError error; @@ -110,6 +98,11 @@ void LifxCloud::listLights() Light light; light.id = object["id"].toString().toUtf8(); light.uuid = object["uuid"].toString().toUtf8(); + if (object["power"].toString() == "on") { + light.power = true; + } else { + light.power = false; + } light.label = object["label"].toString(); light.connected = object["connected"].toBool(); light.brightness = object["brightness"].toDouble(); @@ -162,21 +155,9 @@ void LifxCloud::listScenes() QNetworkReply *reply = m_networkManager->get(request); connect(reply, &QNetworkReply::finished, &QNetworkReply::deleteLater); connect(reply, &QNetworkReply::finished, this, [reply, this] { - int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - - // check HTTP status code - if (status != 200) { - qCWarning(dcLifx()) << "Error get scene list" << status << reply->errorString(); + if(!checkHttpStatusCode(reply)) { return; } - if (!m_authenticated) { - m_authenticated = true; - emit authenticationChanged(true); - } - if (!m_connected) { - m_connected = true; - emit authenticationChanged(true); - } QByteArray rawData = reply->readAll(); qCDebug(dcLifx()) << "Got list scenes reply" << rawData; QJsonDocument data; QJsonParseError error; @@ -202,27 +183,27 @@ void LifxCloud::listScenes() int LifxCloud::setPower(const QString &lightId, bool power, int duration) { - return setState(lightId, StatePower, power, duration); + return setState("id:"+lightId, StatePower, power, duration); } int LifxCloud::setBrightnesss(const QString &lightId, int brightness, int duration) { - return setState(lightId, StateBrightness, brightness/100.00, duration); + return setState("id:"+lightId, StateBrightness, brightness/100.00, duration); } int LifxCloud::setColor(const QString &lightId, QColor color, int duration) { - return setState(lightId, StateColor, color.name(), duration); + return setState("id:"+lightId, StateColor, color.name(), duration); } -int LifxCloud::setColorTemperature(const QString &selector, int kelvin, int duration) +int LifxCloud::setColorTemperature(const QString &lightId, int kelvin, int duration) { - return setState(selector, StateColorTemperature, kelvin, duration); + return setState("id:"+lightId, StateColorTemperature, kelvin, duration); } int LifxCloud::setInfrared(const QString &lightId, int infrared, int duration) { - return setState(lightId, StateColor, infrared/100.00, duration); + return setState("id:"+lightId, StateColor, infrared/100.00, duration); } int LifxCloud::activateScene(const QString &sceneId) @@ -240,34 +221,59 @@ int LifxCloud::activateScene(const QString &sceneId) QNetworkReply *reply = m_networkManager->put(request, ""); connect(reply, &QNetworkReply::finished, &QNetworkReply::deleteLater); connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] { - int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - // check HTTP status code - if (status == 401 || status == 403) { - if (m_authenticated) { - m_authenticated = false; - emit authenticationChanged(false); - } - } - if (status > 207) { - qCWarning(dcLifx()) << "Error activate Scene" << status << reply->errorString(); - emit requestExecuted(requestId, false); - return; - } - if (!m_authenticated) { - m_authenticated = true; - emit authenticationChanged(true); - } - if (!m_connected) { - m_connected = true; - emit authenticationChanged(true); - } - emit requestExecuted(requestId, true); + emit requestExecuted(requestId, checkHttpStatusCode(reply)); QByteArray rawData = reply->readAll(); qCDebug(dcLifx()) << "Got activate scene reply" << rawData; }); return requestId; } +int LifxCloud::setEffect(const QString &lightId, LifxCloud::Effect effect, QColor color) +{ + if (m_authorizationToken.isEmpty()) { + qCWarning(dcLifx()) << "Authorization token is not set"; + return -1; + } + int requestId = qrand(); + QNetworkRequest request; + QJsonObject payload; + switch (effect) { + case LifxCloud::EffectNone: + request.setUrl(QUrl(QString("https://api.lifx.com/v1/lights/id:%1/effects/off").arg(lightId))); + break; + case LifxCloud::EffectBreathe: + request.setUrl(QUrl(QString("https://api.lifx.com/v1/lights/id:%1/effects/breathe").arg(lightId))); + payload["color"] = color.name(); + break; + case LifxCloud::EffectMove: + request.setUrl(QUrl(QString("https://api.lifx.com/v1/lights/id:%1/effects/move").arg(lightId))); + break; + case LifxCloud::EffectMorph: + request.setUrl(QUrl(QString("https://api.lifx.com/v1/lights/id:%1/effects/morph").arg(lightId))); + break; + case LifxCloud::EffectFlame: + request.setUrl(QUrl(QString("https://api.lifx.com/v1/lights/id:%1/effects/flame").arg(lightId))); + break; + case LifxCloud::EffectPulse: + request.setUrl(QUrl(QString("https://api.lifx.com/v1/lights/id:%1/effects/pulse").arg(lightId))); + payload["color"] = color.name(); + break; + } + request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json"); + request.setRawHeader("Authorization","Bearer "+m_authorizationToken); + QJsonDocument doc; + doc.setObject(payload); + QNetworkReply *reply = m_networkManager->put(request, doc.toJson()); + connect(reply, &QNetworkReply::finished, &QNetworkReply::deleteLater); + connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] { + + QByteArray rawData = reply->readAll(); + qCDebug(dcLifx()) << "Got set state reply" << rawData; + emit requestExecuted(requestId, checkHttpStatusCode(reply)); + }); + return requestId; +} + int LifxCloud::setState(const QString &selector, State state, QVariant stateValue, int duration) { if (m_authorizationToken.isEmpty()) { @@ -275,7 +281,6 @@ int LifxCloud::setState(const QString &selector, State state, QVariant stateValu return -1; } int requestId = qrand(); - QNetworkRequest request; request.setUrl(QUrl(QString("https://api.lifx.com/v1/lights/%1/state").arg(selector))); request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json"); @@ -287,45 +292,77 @@ int LifxCloud::setState(const QString &selector, State state, QVariant stateValu switch (state) { case StatePower: if (stateValue.toBool()) - payload["power"] = "ON"; + payload["power"] = "on"; else - payload["power"] = "OFF"; + payload["power"] = "off"; + + qCDebug(dcLifx()) << "Set state power" << stateValue.toBool(); break; case StateBrightness: payload["brightness"] = stateValue.toDouble(); + qCDebug(dcLifx()) << "Set state brightness" << stateValue; break; case StateColor: payload["color"] = stateValue.toString(); + qCDebug(dcLifx()) << "Set state color" << stateValue; break; case StateColorTemperature: payload["color"] = "kelvin:"+stateValue.toString(); + qCDebug(dcLifx()) << "Set state color" << stateValue; break; case StateInfrared: payload["infrared"] = stateValue.toDouble(); + qCDebug(dcLifx()) << "Set state infrared" << stateValue; } doc.setObject(payload); - QNetworkReply *reply = m_networkManager->post(request, doc.toJson()); + qCDebug(dcLifx()) << "Set state request" << request.url() << doc.toJson(); + QNetworkReply *reply = m_networkManager->put(request, doc.toJson()); connect(reply, &QNetworkReply::finished, &QNetworkReply::deleteLater); - connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] { - int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - // check HTTP status code - if (status > 207) { - qCWarning(dcLifx()) << "Error get scene list" << status << reply->errorString(); - emit requestExecuted(requestId, false); - return; - } - if (!m_authenticated) { - m_authenticated = true; - emit authenticationChanged(true); - } - if (!m_connected) { - m_connected = true; - emit authenticationChanged(true); - } + connect(reply, &QNetworkReply::finished, this, [requestId, duration,reply, this] { + QByteArray rawData = reply->readAll(); qCDebug(dcLifx()) << "Got set state reply" << rawData; - emit requestExecuted(requestId, true); + if (checkHttpStatusCode(reply)) { + emit requestExecuted(requestId, true); + QTimer::singleShot(duration*1000+500, this, [=] {listLights();}); + } else { + emit requestExecuted(requestId, false); + } }); return requestId; } + +bool LifxCloud::checkHttpStatusCode(QNetworkReply *reply) +{ + int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + + if (reply->error() != QNetworkReply::NoError) { + qCWarning(dcLifx()) << "Request error:" << status << reply->errorString(); + if (m_connected) { + m_connected = false; + emit connectionChanged(false); + } + return false; + } + // check HTTP status code + if (status == 401 || status == 403) { + if (m_authenticated) { + m_authenticated = false; + emit authenticationChanged(false); + } + } + if (status > 207) { + qCWarning(dcLifx()) << "Error get scene list" << status; + return false; + } + if (!m_authenticated) { + m_authenticated = true; + emit authenticationChanged(true); + } + if (!m_connected) { + m_connected = true; + emit connectionChanged(true); + } + return true; +} diff --git a/lifx/lifxcloud.h b/lifx/lifxcloud.h index 1e0025e1..ef4e513c 100644 --- a/lifx/lifxcloud.h +++ b/lifx/lifxcloud.h @@ -47,6 +47,16 @@ public: StateColorTemperature, StateInfrared }; + + enum Effect { + EffectNone, + EffectBreathe, + EffectMove, + EffectMorph, + EffectFlame, + EffectPulse + }; + struct Group { QByteArray id; QString name; @@ -101,19 +111,22 @@ public: void listLights(); void listScenes(); - int setPower(const QString &lightId, bool power, int duration = 3); - int setBrightnesss(const QString &lightId, int brightness, int duration = 3); - int setColor(const QString &selector, QColor color, int duration = 3); - int setColorTemperature(const QString &selector, int kelvin, int duration = 3); - int setInfrared(const QString &lightId, int infrared, int duration = 3); + int setPower(const QString &lightId, bool power, int duration = 5); + int setBrightnesss(const QString &lightId, int brightness, int duration = 5); + int setColor(const QString &lightId, QColor color, int duration = 5); + int setColorTemperature(const QString &lightId, int kelvin, int duration = 5); + int setInfrared(const QString &lightId, int infrared, int duration = 5); int activateScene(const QString &sceneId); + int setEffect(const QString &lightId, Effect effect, QColor color); + private: NetworkAccessManager *m_networkManager = nullptr; QByteArray m_authorizationToken; int setState(const QString &lightId, State state, QVariant stateValue, int duration); + bool checkHttpStatusCode(QNetworkReply *reply); bool m_authenticated = false; bool m_connected = false; signals: diff --git a/lifx/lifx.cpp b/lifx/lifxlan.cpp similarity index 77% rename from lifx/lifx.cpp rename to lifx/lifxlan.cpp index 1bb4eb73..2270b1ac 100644 --- a/lifx/lifx.cpp +++ b/lifx/lifxlan.cpp @@ -29,20 +29,16 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include "lifx.h" +#include "lifxlan.h" #include "extern-plugininfo.h" #include - -Lifx::Lifx(const QHostAddress &address, quint16 port, QObject *parent) : +LifxLan::LifxLan(const QHostAddress &address, quint16 port, QObject *parent) : QObject(parent), m_host(address), m_port(port) { - m_reconnectTimer = new QTimer(this); - m_reconnectTimer->setSingleShot(true); - connect(m_reconnectTimer, &QTimer::timeout, this, &Lifx::onReconnectTimer); m_clientId = qrand(); m_socket = new QUdpSocket(this); @@ -51,7 +47,7 @@ Lifx::Lifx(const QHostAddress &address, quint16 port, QObject *parent) : m_socket->setSocketOption(QAbstractSocket::MulticastLoopbackOption, QVariant(1)); } -Lifx::~Lifx() +LifxLan::~LifxLan() { if (m_socket) { m_socket->waitForBytesWritten(1000); @@ -59,7 +55,7 @@ Lifx::~Lifx() } } -bool Lifx::enable() +bool LifxLan::enable() { // Bind udp socket and join multicast group if(!m_socket->bind(QHostAddress::AnyIPv4, m_port, QUdpSocket::ShareAddress)){ @@ -75,21 +71,21 @@ bool Lifx::enable() m_socket = nullptr; return false; } - connect(m_socket, &QUdpSocket::readyRead, this, &Lifx::onReadyRead); + connect(m_socket, &QUdpSocket::readyRead, this, &LifxLan::onReadyRead); return true; } -void Lifx::setHostAddress(const QHostAddress &address) +void LifxLan::setHostAddress(const QHostAddress &address) { m_host = address; } -void Lifx::setPort(quint16 port) +void LifxLan::setPort(quint16 port) { m_port = port; } -int Lifx::setColorTemperature(uint mirad, uint msFadeTime) +int LifxLan::setColorTemperature(uint mirad, uint msFadeTime) { Q_UNUSED(mirad) Q_UNUSED(msFadeTime) @@ -99,59 +95,48 @@ int Lifx::setColorTemperature(uint mirad, uint msFadeTime) return requestId; } -int Lifx::setColor(QColor color, uint msFadeTime) +int LifxLan::setColor(QColor color, uint msFadeTime) { Q_UNUSED(color) Q_UNUSED(msFadeTime) int requestId = qrand(); Message message; + //TODO create LAN message sendMessage(message); return requestId; } -int Lifx::setBrightness(uint percentage, uint msFadeTime) +int LifxLan::setBrightness(uint percentage, uint msFadeTime) { Q_UNUSED(percentage) Q_UNUSED(msFadeTime) int requestId = qrand(); Message message; sendMessage(message); + //TODO create LAN message return requestId; } -int Lifx::setPower(bool power, uint msFadeTime) +int LifxLan::setPower(bool power, uint msFadeTime) { Q_UNUSED(power) Q_UNUSED(msFadeTime) int requestId = qrand(); Message message; sendMessage(message); + //TODO create LAN message return requestId; } -int Lifx::flash() -{ - int requestId = qrand(); - - return requestId; -} - -int Lifx::flash15s() -{ - int requestId = qrand(); - - return requestId; -} - -void Lifx::sendMessage(const Lifx::Message &message) +void LifxLan::sendMessage(const LifxLan::Message &message) { QByteArray header; // -- FRAME -- // Protocol number: must be 1024 (decimal) quint16 protocol = 1024; - protocol |= (0x0001 << 4); //Message includes a target address: must be one (1) + protocol |= (0x0001 << 4); //Message includes a target address: must be one (1) protocol |= (message.frame.Tagged << 5); // Determines usage of the Frame Address target field - protocol &= ~(0x0003); // Message origin indicator: must be zero (0) + protocol &= ~(0x0003); // Message origin indicator: must be zero (0) header.append(protocol >> 8); header.append(protocol & 0xff); @@ -188,15 +173,12 @@ void Lifx::sendMessage(const Lifx::Message &message) header.append(2, '0'); QByteArray fullMessage; - //message.append(header); - //message.append(payload); - //message.append(message.length()); - fullMessage = QByteArray::fromHex("0x310000340000000000000000000000000000000000000000000000000000000066000000005555FFFFFFFFAC0D00040000"); - std::reverse(fullMessage.begin(), fullMessage.end()); + //fullMessage = QByteArray::fromHex("0x310000340000000000000000000000000000000000000000000000000000000066000000005555FFFFFFFFAC0D00040000"); // test message - set all lights green + //std::reverse(fullMessage.begin(), fullMessage.end()); m_socket->writeDatagram(fullMessage, m_host, m_port); } -void Lifx::onStateChanged(QAbstractSocket::SocketState state) +void LifxLan::onStateChanged(QAbstractSocket::SocketState state) { switch (state) { case QAbstractSocket::SocketState::ConnectedState: @@ -212,13 +194,8 @@ void Lifx::onStateChanged(QAbstractSocket::SocketState state) } } -void Lifx::onReadyRead() +void LifxLan::onReadyRead() { QByteArray data = m_socket->readAll(); qCDebug(dcLifx()) << "Message received" << data; } - -void Lifx::onReconnectTimer() -{ - -} diff --git a/lifx/lifx.h b/lifx/lifxlan.h similarity index 87% rename from lifx/lifx.h rename to lifx/lifxlan.h index 6ac42447..e15dea84 100644 --- a/lifx/lifx.h +++ b/lifx/lifxlan.h @@ -28,8 +28,8 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#ifndef LIFX_H -#define LIFX_H +#ifndef LIFXLAN_H +#define LIFXLAN_H #include #include @@ -40,7 +40,7 @@ #include -class Lifx : public QObject +class LifxLan : public QObject { Q_OBJECT public: @@ -122,8 +122,8 @@ public: bool chain; }; - explicit Lifx(const QHostAddress &address, quint16 port = 56700, QObject *parent = nullptr); - ~Lifx(); + explicit LifxLan(const QHostAddress &address, quint16 port = 56700, QObject *parent = nullptr); + ~LifxLan(); bool enable(); void setHostAddress(const QHostAddress &address); void setPort(quint16 port); @@ -132,8 +132,6 @@ public: int setColor(QColor color, uint msFadeTime = 500); int setBrightness(uint percentage, uint msFadeTime = 500); int setPower(bool power, uint msFadeTime = 500); - int flash(); - int flash15s(); private: quint32 m_clientId = 0; @@ -148,19 +146,9 @@ private: private slots: void onStateChanged(QAbstractSocket::SocketState state); void onReadyRead(); - void onReconnectTimer(); signals: void connectionChanged(bool connected); void requestExecuted(int requestId, bool success); - //void errorReceived(int code, const QString &message); - - //void powerNotificationReceived(bool status); - //void brightnessNotificationReceived(int percentage); - //void colorTemperatureNotificationReceived(int kelvin); - //void rgbNotificationReceived(QRgb rgbColor); - //void hueNotificationReceived(int hueColor); - //void nameNotificationReceived(const QString &name); - //void saturationNotificationReceived(int percentage); }; -#endif // LIFX_H +#endif // LIFXLAN_H diff --git a/lifx/meta.json b/lifx/meta.json index 5a34dd9c..37064e23 100644 --- a/lifx/meta.json +++ b/lifx/meta.json @@ -3,7 +3,7 @@ "tagline": "Control LIFX light bulbs.", "icon": "lifx.png", "stability": "consumer", - "offline": true, + "offline": false, "technologies": [ "network" ], diff --git a/lifx/translations/4e00ee30-79e2-447b-8dcc-c34470f41992-de.ts b/lifx/translations/4e00ee30-79e2-447b-8dcc-c34470f41992-de.ts index 27a145ba..418b72fd 100644 --- a/lifx/translations/4e00ee30-79e2-447b-8dcc-c34470f41992-de.ts +++ b/lifx/translations/4e00ee30-79e2-447b-8dcc-c34470f41992-de.ts @@ -1,6 +1,17 @@ + + IntegrationPluginLifx + + LIFX server is not reachable. + + + + This token is invalid. + + + Lifx @@ -68,18 +79,6 @@ The name of the EventType ({dd7d7e70-5552-4531-8789-2d0f750488be}) of ThingClass The name of the ThingClass ({a5b02af8-7c97-4a78-9c78-bafee7407b5e}) Tag und Sonnenaufgang - - Host address - The name of the ParamType (ThingClass: dimmableBulb, Type: thing, ID: {cc0a765b-a753-4e07-a6e5-47e9272c4346}) ----------- -The name of the ParamType (ThingClass: colorBulb, Type: thing, ID: {fd1c4817-5111-433a-b5b9-fd9f49d4975c}) - Adresse - - - Id - The name of the ParamType (ThingClass: colorBulb, Type: thing, ID: {976ecea0-ac25-47d4-9dc5-362962ddb6c0}) - ID - LIFX The name of the vendor ({e5e48c0d-cff7-4c0f-983e-d23bd3e4ba87}) @@ -87,13 +86,6 @@ The name of the ParamType (ThingClass: colorBulb, Type: thing, ID: {fd1c4817-511 The name of the plugin Lifx ({4e00ee30-79e2-447b-8dcc-c34470f41992}) LIFX - - Port - The name of the ParamType (ThingClass: dimmableBulb, Type: thing, ID: {d233d9bf-6662-414d-92f6-dd3e267051b5}) ----------- -The name of the ParamType (ThingClass: colorBulb, Type: thing, ID: {44c13745-300c-491f-b617-3a8d53472998}) - Port - Power The name of the ParamType (ThingClass: dimmableBulb, ActionType: power, ID: {9e1344ea-cd05-4dd8-8948-8d2f5e00e1b0}) @@ -148,7 +140,9 @@ The name of the ActionType ({dd7d7e70-5552-4531-8789-2d0f750488be}) of ThingClas Set effect - The name of the ActionType ({65f88396-2958-480e-b0be-c4695400a343}) of ThingClass colorBulb + The name of the ActionType ({be47c474-eca1-479e-9393-68281a43d72a}) of ThingClass dimmableBulb +---------- +The name of the ActionType ({65f88396-2958-480e-b0be-c4695400a343}) of ThingClass colorBulb Setze Effekt @@ -160,7 +154,13 @@ The name of the ActionType ({12de3f8f-2454-4057-aa12-9290296fdbdd}) of ThingClas Effect - The name of the ParamType (ThingClass: colorBulb, ActionType: effect, ID: {65f88396-2958-480e-b0be-c4695400a343}) + The name of the ParamType (ThingClass: dimmableBulb, ActionType: effect, ID: {be47c474-eca1-479e-9393-68281a43d72a}) +---------- +The name of the ParamType (ThingClass: dimmableBulb, EventType: effect, ID: {be47c474-eca1-479e-9393-68281a43d72a}) +---------- +The name of the StateType ({be47c474-eca1-479e-9393-68281a43d72a}) of ThingClass dimmableBulb +---------- +The name of the ParamType (ThingClass: colorBulb, ActionType: effect, ID: {65f88396-2958-480e-b0be-c4695400a343}) ---------- The name of the ParamType (ThingClass: colorBulb, EventType: effect, ID: {65f88396-2958-480e-b0be-c4695400a343}) ---------- @@ -169,12 +169,16 @@ The name of the StateType ({65f88396-2958-480e-b0be-c4695400a343}) of ThingClass Effect changed - The name of the EventType ({65f88396-2958-480e-b0be-c4695400a343}) of ThingClass colorBulb + The name of the EventType ({be47c474-eca1-479e-9393-68281a43d72a}) of ThingClass dimmableBulb +---------- +The name of the EventType ({65f88396-2958-480e-b0be-c4695400a343}) of ThingClass colorBulb Effekt geƤndert ID - The name of the ParamType (ThingClass: dimmableBulb, Type: thing, ID: {f157a97b-3fe5-4d9e-b5e3-5636f80d46ed}) + The name of the ParamType (ThingClass: dimmableBulb, Type: thing, ID: {f157a97b-3fe5-4d9e-b5e3-5636f80d46ed}) +---------- +The name of the ParamType (ThingClass: colorBulb, Type: thing, ID: {976ecea0-ac25-47d4-9dc5-362962ddb6c0}) ID @@ -184,5 +188,46 @@ The name of the StateType ({65f88396-2958-480e-b0be-c4695400a343}) of ThingClass The name of the ActionType ({8bd20350-0e79-45dc-b68a-84da99356863}) of ThingClass colorBulb Setze Helligkeit + + Connected + The name of the ParamType (ThingClass: lifxAccount, EventType: connected, ID: {3e7b358b-d7de-4db4-8a3a-b9860eae186f}) +---------- +The name of the StateType ({3e7b358b-d7de-4db4-8a3a-b9860eae186f}) of ThingClass lifxAccount + + + + Connected changed + The name of the EventType ({3e7b358b-d7de-4db4-8a3a-b9860eae186f}) of ThingClass lifxAccount + + + + LIFX cloud account + The name of the ThingClass ({387c87f6-3e5b-4d6a-ba4d-372d0efad79f}) + + + + Logged in + The name of the ParamType (ThingClass: lifxAccount, EventType: loggedIn, ID: {0db34069-5de0-4233-baec-27f039228524}) +---------- +The name of the StateType ({0db34069-5de0-4233-baec-27f039228524}) of ThingClass lifxAccount + + + + Logged in changed + The name of the EventType ({0db34069-5de0-4233-baec-27f039228524}) of ThingClass lifxAccount + + + + User name + The name of the ParamType (ThingClass: lifxAccount, EventType: userDisplayName, ID: {554afd9b-a2ec-4d28-9065-2b9ab3a9e3b2}) +---------- +The name of the StateType ({554afd9b-a2ec-4d28-9065-2b9ab3a9e3b2}) of ThingClass lifxAccount + + + + User name changed + The name of the EventType ({554afd9b-a2ec-4d28-9065-2b9ab3a9e3b2}) of ThingClass lifxAccount + + diff --git a/lifx/translations/4e00ee30-79e2-447b-8dcc-c34470f41992-en_US.ts b/lifx/translations/4e00ee30-79e2-447b-8dcc-c34470f41992-en_US.ts index 722805c7..cd993a05 100644 --- a/lifx/translations/4e00ee30-79e2-447b-8dcc-c34470f41992-en_US.ts +++ b/lifx/translations/4e00ee30-79e2-447b-8dcc-c34470f41992-en_US.ts @@ -1,6 +1,17 @@ + + IntegrationPluginLifx + + LIFX server is not reachable. + + + + This token is invalid. + + + Lifx @@ -68,18 +79,6 @@ The name of the EventType ({dd7d7e70-5552-4531-8789-2d0f750488be}) of ThingClass The name of the ThingClass ({a5b02af8-7c97-4a78-9c78-bafee7407b5e}) - - Host address - The name of the ParamType (ThingClass: dimmableBulb, Type: thing, ID: {cc0a765b-a753-4e07-a6e5-47e9272c4346}) ----------- -The name of the ParamType (ThingClass: colorBulb, Type: thing, ID: {fd1c4817-5111-433a-b5b9-fd9f49d4975c}) - - - - Id - The name of the ParamType (ThingClass: colorBulb, Type: thing, ID: {976ecea0-ac25-47d4-9dc5-362962ddb6c0}) - - LIFX The name of the vendor ({e5e48c0d-cff7-4c0f-983e-d23bd3e4ba87}) @@ -87,13 +86,6 @@ The name of the ParamType (ThingClass: colorBulb, Type: thing, ID: {fd1c4817-511 The name of the plugin Lifx ({4e00ee30-79e2-447b-8dcc-c34470f41992}) - - Port - The name of the ParamType (ThingClass: dimmableBulb, Type: thing, ID: {d233d9bf-6662-414d-92f6-dd3e267051b5}) ----------- -The name of the ParamType (ThingClass: colorBulb, Type: thing, ID: {44c13745-300c-491f-b617-3a8d53472998}) - - Power The name of the ParamType (ThingClass: dimmableBulb, ActionType: power, ID: {9e1344ea-cd05-4dd8-8948-8d2f5e00e1b0}) @@ -148,7 +140,9 @@ The name of the ActionType ({dd7d7e70-5552-4531-8789-2d0f750488be}) of ThingClas Set effect - The name of the ActionType ({65f88396-2958-480e-b0be-c4695400a343}) of ThingClass colorBulb + The name of the ActionType ({be47c474-eca1-479e-9393-68281a43d72a}) of ThingClass dimmableBulb +---------- +The name of the ActionType ({65f88396-2958-480e-b0be-c4695400a343}) of ThingClass colorBulb @@ -160,7 +154,13 @@ The name of the ActionType ({12de3f8f-2454-4057-aa12-9290296fdbdd}) of ThingClas Effect - The name of the ParamType (ThingClass: colorBulb, ActionType: effect, ID: {65f88396-2958-480e-b0be-c4695400a343}) + The name of the ParamType (ThingClass: dimmableBulb, ActionType: effect, ID: {be47c474-eca1-479e-9393-68281a43d72a}) +---------- +The name of the ParamType (ThingClass: dimmableBulb, EventType: effect, ID: {be47c474-eca1-479e-9393-68281a43d72a}) +---------- +The name of the StateType ({be47c474-eca1-479e-9393-68281a43d72a}) of ThingClass dimmableBulb +---------- +The name of the ParamType (ThingClass: colorBulb, ActionType: effect, ID: {65f88396-2958-480e-b0be-c4695400a343}) ---------- The name of the ParamType (ThingClass: colorBulb, EventType: effect, ID: {65f88396-2958-480e-b0be-c4695400a343}) ---------- @@ -169,12 +169,16 @@ The name of the StateType ({65f88396-2958-480e-b0be-c4695400a343}) of ThingClass Effect changed - The name of the EventType ({65f88396-2958-480e-b0be-c4695400a343}) of ThingClass colorBulb + The name of the EventType ({be47c474-eca1-479e-9393-68281a43d72a}) of ThingClass dimmableBulb +---------- +The name of the EventType ({65f88396-2958-480e-b0be-c4695400a343}) of ThingClass colorBulb ID - The name of the ParamType (ThingClass: dimmableBulb, Type: thing, ID: {f157a97b-3fe5-4d9e-b5e3-5636f80d46ed}) + The name of the ParamType (ThingClass: dimmableBulb, Type: thing, ID: {f157a97b-3fe5-4d9e-b5e3-5636f80d46ed}) +---------- +The name of the ParamType (ThingClass: colorBulb, Type: thing, ID: {976ecea0-ac25-47d4-9dc5-362962ddb6c0}) @@ -184,5 +188,46 @@ The name of the StateType ({65f88396-2958-480e-b0be-c4695400a343}) of ThingClass The name of the ActionType ({8bd20350-0e79-45dc-b68a-84da99356863}) of ThingClass colorBulb + + Connected + The name of the ParamType (ThingClass: lifxAccount, EventType: connected, ID: {3e7b358b-d7de-4db4-8a3a-b9860eae186f}) +---------- +The name of the StateType ({3e7b358b-d7de-4db4-8a3a-b9860eae186f}) of ThingClass lifxAccount + + + + Connected changed + The name of the EventType ({3e7b358b-d7de-4db4-8a3a-b9860eae186f}) of ThingClass lifxAccount + + + + LIFX cloud account + The name of the ThingClass ({387c87f6-3e5b-4d6a-ba4d-372d0efad79f}) + + + + Logged in + The name of the ParamType (ThingClass: lifxAccount, EventType: loggedIn, ID: {0db34069-5de0-4233-baec-27f039228524}) +---------- +The name of the StateType ({0db34069-5de0-4233-baec-27f039228524}) of ThingClass lifxAccount + + + + Logged in changed + The name of the EventType ({0db34069-5de0-4233-baec-27f039228524}) of ThingClass lifxAccount + + + + User name + The name of the ParamType (ThingClass: lifxAccount, EventType: userDisplayName, ID: {554afd9b-a2ec-4d28-9065-2b9ab3a9e3b2}) +---------- +The name of the StateType ({554afd9b-a2ec-4d28-9065-2b9ab3a9e3b2}) of ThingClass lifxAccount + + + + User name changed + The name of the EventType ({554afd9b-a2ec-4d28-9065-2b9ab3a9e3b2}) of ThingClass lifxAccount + +