diff --git a/debian/control b/debian/control
index f545e939..5d021ad5 100644
--- a/debian/control
+++ b/debian/control
@@ -400,6 +400,21 @@ Description: nymea.io plugin for lgsmarttv
This package will install the nymea.io plugin for lgsmarttv
+Package: nymea-plugin-lifx
+Architecture: any
+Depends: ${shlibs:Depends},
+ ${misc:Depends},
+ nymea-plugins-translations,
+Description: nymea.io plugin for lifx
+ The nymea daemon is a plugin based IoT (Internet of Things) server. The
+ server works like a translator for devices, things and services and
+ allows them to interact.
+ With the powerful rule engine you are able to connect any device available
+ in the system and create individual scenes and behaviors for your environment.
+ .
+ This package will install the nymea.io plugin for lifx
+
+
Package: nymea-plugin-mailnotification
Architecture: any
Depends: ${shlibs:Depends},
@@ -981,6 +996,7 @@ Depends: nymea-plugin-anel,
nymea-plugin-genericthings,
nymea-plugin-kodi,
nymea-plugin-lgsmarttv,
+ nymea-plugin-lifx,
nymea-plugin-mailnotification,
nymea-plugin-texasinstruments,
nymea-plugin-nanoleaf,
diff --git a/debian/nymea-plugin-lifx.install.in b/debian/nymea-plugin-lifx.install.in
new file mode 100644
index 00000000..ea0623b7
--- /dev/null
+++ b/debian/nymea-plugin-lifx.install.in
@@ -0,0 +1 @@
+usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginlifx.so
diff --git a/lifx/README.md b/lifx/README.md
new file mode 100644
index 00000000..088654d0
--- /dev/null
+++ b/lifx/README.md
@@ -0,0 +1,3 @@
+# Lifx
+
+This plug-in implements the LAN API for Lifx devices
diff --git a/lifx/devicepluginlifx.cpp b/lifx/devicepluginlifx.cpp
index e69de29b..245a788e 100644
--- a/lifx/devicepluginlifx.cpp
+++ b/lifx/devicepluginlifx.cpp
@@ -0,0 +1,220 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This file is part of nymea.
+* This project including source code and documentation is protected by copyright law, and
+* remains the property of nymea GmbH. All rights, including reproduction, publication,
+* editing and translation, are reserved. The use of this project is subject to the terms of a
+* license agreement to be concluded with nymea GmbH in accordance with the terms
+* of use of nymea GmbH, available under https://nymea.io/license
+*
+* GNU Lesser General Public License Usage
+* This project may also contain libraries licensed under the open source software license GNU GPL v.3.
+* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
+* Lesser General Public License as published by the Free Software Foundation; version 3.
+* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along with this project.
+* If not, see .
+*
+* For any further details and any questions please contact us under contact@nymea.io
+* or see our FAQ/Licensing Information on https://nymea.io/license/faq
+*
+* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "devicepluginlifx.h"
+
+#include "devices/device.h"
+#include "types/param.h"
+#include "plugininfo.h"
+
+#include
+#include
+#include
+
+DevicePluginLifx::DevicePluginLifx()
+{
+
+}
+
+void DevicePluginLifx::init()
+{
+ m_connectedStateTypeIds.insert(colorBulbDeviceClassId, colorBulbConnectedStateTypeId);
+ m_connectedStateTypeIds.insert(dimmableBulbDeviceClassId, dimmableBulbConnectedStateTypeId);
+
+ m_powerStateTypeIds.insert(colorBulbDeviceClassId, colorBulbPowerStateTypeId);
+ m_powerStateTypeIds.insert(dimmableBulbDeviceClassId, dimmableBulbPowerStateTypeId);
+
+ m_brightnessStateTypeIds.insert(colorBulbDeviceClassId, colorBulbBrightnessStateTypeId);
+ m_brightnessStateTypeIds.insert(dimmableBulbDeviceClassId, dimmableBulbBrightnessStateTypeId);
+}
+
+void DevicePluginLifx::discoverDevices(DeviceDiscoveryInfo *info)
+{
+ if (!m_lifxConnection) {
+ m_lifxConnection = new Lifx(this);
+ m_lifxConnection->enable();
+ }
+
+ if (info->deviceClassId() == colorBulbDeviceClassId) {
+ }
+}
+
+void DevicePluginLifx::setupDevice(DeviceSetupInfo *info)
+{
+ Device *device = info->device();
+
+ if (!m_lifxConnection) {
+ m_lifxConnection = new Lifx(this);
+ m_lifxConnection->enable();
+ }
+
+ if (device->deviceClassId() == colorBulbDeviceClassId) {
+
+ info->finish(Device::DeviceErrorNoError);
+ }
+}
+
+void DevicePluginLifx::postSetupDevice(Device *device)
+{
+ connect(device, &Device::nameChanged, this, &DevicePluginLifx::onDeviceNameChanged);
+
+ if (!m_pluginTimer) {
+ m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(60);
+ connect(m_pluginTimer, &PluginTimer::timeout, this, [this]() {
+
+ });
+ }
+ m_pluginTimer->timeout();
+}
+
+void DevicePluginLifx::executeAction(DeviceActionInfo *info)
+{
+ Device *device = info->device();
+ Action action = info->action();
+
+ if (!m_lifxConnection)
+ return info->finish(Device::DeviceErrorHardwareFailure);
+
+ if (device->deviceClassId() == colorBulbDeviceClassId) {
+
+ if (action.actionTypeId() == colorBulbPowerActionTypeId) {
+ bool power = action.param(colorBulbPowerActionPowerParamTypeId).value().toBool();
+ int requestId = m_lifxConnection->setPower(power);
+ connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
+ m_asyncActions.insert(requestId, info);
+ } else if (action.actionTypeId() == colorBulbBrightnessActionTypeId) {
+
+ if (!device->stateValue(colorBulbPowerStateTypeId).toBool())
+ m_lifxConnection->setPower(true);
+
+ if (m_pendingBrightnessAction.contains(device->id())) {
+ //Scrap old info and insert new one
+ m_pendingBrightnessAction.insert(device->id(), info);
+ } else {
+ m_pendingBrightnessAction.insert(device->id(), info);
+ QTimer::singleShot(500, this, [info, this]{
+ int brightness = info->action().param(colorBulbBrightnessActionBrightnessParamTypeId).value().toInt();
+ m_pendingBrightnessAction.remove(info->device()->id());
+ int requestId = m_lifxConnection->setBrightness(brightness);
+ connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
+ m_asyncActions.insert(requestId, info);
+ });
+ }
+ } else if (action.actionTypeId() == colorBulbColorActionColorParamTypeId) {
+ QRgb color = QColor(action.param(colorBulbColorActionColorParamTypeId).value().toString()).rgba();
+ if (!device->stateValue(colorBulbPowerStateTypeId).toBool())
+ m_lifxConnection->setPower(true);
+ int requestId = m_lifxConnection->setColor(color);
+ connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
+ m_asyncActions.insert(requestId, info);
+ } else if (action.actionTypeId() == colorBulbColorTemperatureActionTypeId) {
+ int colorTemperature = 6500 - (action.param(colorBulbColorTemperatureActionColorTemperatureParamTypeId).value().toUInt() * -11.12);
+ if (!device->stateValue(colorBulbPowerStateTypeId).toBool())
+ m_lifxConnection->setPower(true);
+ int requestId = m_lifxConnection->setColorTemperature(colorTemperature);
+ connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
+ m_asyncActions.insert(requestId, info);
+ } else {
+ qCWarning(dcLifx()) << "Unhandled action";
+ }
+ } else if (device->deviceClassId() == dimmableBulbDeviceClassId) {
+ if (action.actionTypeId() == dimmableBulbPowerActionTypeId) {
+ bool power = action.param(dimmableBulbPowerActionPowerParamTypeId).value().toBool();
+ int requestId = m_lifxConnection->setPower(power);
+ connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
+ } else if (action.actionTypeId() == dimmableBulbBrightnessActionTypeId) {
+ int brightness = action.param(dimmableBulbBrightnessActionBrightnessParamTypeId).value().toInt();
+ if (!device->stateValue(dimmableBulbPowerStateTypeId).toBool())
+ m_lifxConnection->setPower(true);
+ int requestId = m_lifxConnection->setBrightness(brightness);
+ connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
+ m_asyncActions.insert(requestId, info);
+ } else {
+ qCWarning(dcLifx()) << "Unhandled action";
+ }
+ } else {
+ qCWarning(dcLifx()) << "Unhandled device class";
+ }
+}
+
+void DevicePluginLifx::deviceRemoved(Device *device)
+{
+ Q_UNUSED(device)
+
+ if (myDevices().isEmpty()) {
+ m_lifxConnection->deleteLater();
+ m_lifxConnection = nullptr;
+ }
+}
+
+void DevicePluginLifx::onDeviceNameChanged()
+{
+ Device *device = static_cast(sender());
+ Q_UNUSED(device)
+}
+
+void DevicePluginLifx::onConnectionChanged(bool connected)
+{
+ Q_UNUSED(connected)
+// device->setStateValue(m_connectedStateTypeIds.value(device->deviceClassId()), connected);
+}
+
+void DevicePluginLifx::onRequestExecuted(int requestId, bool success)
+{
+ if (m_asyncActions.contains(requestId)) {
+ DeviceActionInfo *info = m_asyncActions.take(requestId);
+ if (success) {
+ info->finish(Device::DeviceErrorNoError);
+ } else {
+ info->finish(Device::DeviceErrorHardwareFailure);
+ }
+ }
+}
+
+/*void DevicePluginLifx::onPowerNotificationReceived(bool status)
+{
+ Q_UNUSED(status)
+ Lifx *Lifx = static_cast(sender());
+ Device * device = myDevices().findById(m_LifxConnections.key(Lifx));
+ if(!device)
+ return;
+
+ device->setStateValue(m_powerStateTypeIds.value(device->deviceClassId()), status);
+
+}
+
+void DevicePluginLifx::onBrightnessNotificationReceived(int percentage)
+{
+ Q_UNUSED(percentage)
+ Lifx *lifx = static_cast(sender());
+ Device * device = myDevices().findById(m_lifxConnections.key(lifx));
+ if(!device)
+ return;
+
+ device->setStateValue(m_brightnessStateTypeIds.value(device->deviceClassId()), percentage);
+}*/
diff --git a/lifx/devicepluginlifx.h b/lifx/devicepluginlifx.h
index e69de29b..0cfb91d9 100644
--- a/lifx/devicepluginlifx.h
+++ b/lifx/devicepluginlifx.h
@@ -0,0 +1,78 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This file is part of nymea.
+* This project including source code and documentation is protected by copyright law, and
+* remains the property of nymea GmbH. All rights, including reproduction, publication,
+* editing and translation, are reserved. The use of this project is subject to the terms of a
+* license agreement to be concluded with nymea GmbH in accordance with the terms
+* of use of nymea GmbH, available under https://nymea.io/license
+*
+* GNU Lesser General Public License Usage
+* This project may also contain libraries licensed under the open source software license GNU GPL v.3.
+* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
+* Lesser General Public License as published by the Free Software Foundation; version 3.
+* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along with this project.
+* If not, see .
+*
+* For any further details and any questions please contact us under contact@nymea.io
+* or see our FAQ/Licensing Information on https://nymea.io/license/faq
+*
+* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef DEVICEPLUGINLIFX_H
+#define DEVICEPLUGINLIFX_H
+
+#include "devices/deviceplugin.h"
+#include "plugintimer.h"
+#include "lifx.h"
+
+#include
+
+class DevicePluginLifx : public DevicePlugin
+{
+ Q_OBJECT
+
+ Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginlifx.json")
+ Q_INTERFACES(DevicePlugin)
+
+public:
+ explicit DevicePluginLifx();
+
+ void init() override;
+ void discoverDevices(DeviceDiscoveryInfo *info) override;
+ void setupDevice(DeviceSetupInfo *info) override;
+ void postSetupDevice(Device *device) override;
+ void executeAction(DeviceActionInfo *info) override;
+ void deviceRemoved(Device *device) override;
+
+private:
+ PluginTimer *m_pluginTimer = nullptr;
+ QHash m_asyncActions;
+ Lifx *m_lifxConnection;
+
+ QHash m_connectedStateTypeIds;
+ QHash m_powerStateTypeIds;
+ QHash m_brightnessStateTypeIds;
+
+ QHash m_pendingBrightnessAction;
+
+private slots:
+ void onDeviceNameChanged();
+ void onConnectionChanged(bool connected);
+ void onRequestExecuted(int requestId, bool success);
+
+ /*void onPowerNotificationReceived(bool status);
+ void onBrightnessNotificationReceived(int percentage);
+ void onColorTemperatureNotificationReceived(int kelvin);
+ void onRgbNotificationReceived(QRgb rgbColor);
+ void onNameNotificationReceived(const QString &name);*/
+};
+
+#endif // DEVICEPLUGINLIFX_H
diff --git a/lifx/devicepluginlifx.json b/lifx/devicepluginlifx.json
index e69de29b..28ba9556 100644
--- a/lifx/devicepluginlifx.json
+++ b/lifx/devicepluginlifx.json
@@ -0,0 +1,192 @@
+{
+ "displayName": "LIFX",
+ "name": "Lifx",
+ "id": "4e00ee30-79e2-447b-8dcc-c34470f41992",
+ "vendors": [
+ {
+ "name": "lifx",
+ "displayName": "LIFX",
+ "id": "e5e48c0d-cff7-4c0f-983e-d23bd3e4ba87",
+ "deviceClasses": [
+ {
+ "id": "12907c9c-e7f0-47f2-bd58-39d52ffdf24e",
+ "name": "colorBulb",
+ "displayName": "Color",
+ "createMethods": ["user", "discovery"],
+ "interfaces": ["colorlight", "connectable"],
+ "paramTypes": [
+ {
+ "id": "fd1c4817-5111-433a-b5b9-fd9f49d4975c",
+ "name": "host",
+ "displayName": "Host address",
+ "type" : "QString",
+ "inputType": "IPv4Address",
+ "readOnly": true
+ },
+ {
+ "id": "44c13745-300c-491f-b617-3a8d53472998",
+ "name": "port",
+ "displayName": "Port",
+ "type" : "int",
+ "readOnly": true
+ },
+ {
+ "id": "976ecea0-ac25-47d4-9dc5-362962ddb6c0",
+ "name": "id",
+ "displayName": "Id",
+ "type" : "QString",
+ "readOnly": true
+ }
+ ],
+ "stateTypes": [
+ {
+ "id": "dc4c1640-90f3-4fe0-af9b-db7fa105f18a",
+ "name": "connected",
+ "displayName": "Reachable",
+ "displayNameEvent": "Reachable changed",
+ "defaultValue": false,
+ "type": "bool"
+ },
+ {
+ "id": "12de3f8f-2454-4057-aa12-9290296fdbdd",
+ "name": "power",
+ "displayName": "Power",
+ "displayNameEvent": "Power changed",
+ "displayNameAction": "Set power",
+ "type": "bool",
+ "defaultValue": false,
+ "writable": true
+ },
+ {
+ "id": "dd7d7e70-5552-4531-8789-2d0f750488be",
+ "name": "colorTemperature",
+ "displayName": "Color temperature",
+ "displayNameEvent": "Color temperature changed",
+ "displayNameAction": "Set color temperature",
+ "type": "int",
+ "unit": "Mired",
+ "defaultValue": 170,
+ "minValue": 153,
+ "maxValue": 500,
+ "writable": true
+ },
+ {
+ "id": "a47d8164-5023-4ffb-8298-73293e93e7f6",
+ "name": "color",
+ "displayName": "Color",
+ "displayNameEvent": "Color changed",
+ "displayNameAction": "Set color",
+ "type": "QColor",
+ "defaultValue": "#000000",
+ "writable": true
+ },
+ {
+ "id": "8bd20350-0e79-45dc-b68a-84da99356863",
+ "name": "brightness",
+ "displayName": "Brightness",
+ "displayNameEvent": "Brightness changed",
+ "displayNameAction": "Set brigtness",
+ "type": "int",
+ "unit": "Percentage",
+ "defaultValue": 0,
+ "minValue": 0,
+ "maxValue": 100,
+ "writable": true
+ },
+ {
+ "id": "65f88396-2958-480e-b0be-c4695400a343",
+ "name": "effect",
+ "displayName": "effect",
+ "displayNameEvent": "effect changed",
+ "displayNameAction": "Set effect",
+ "type": "QString",
+ "defaultValue": "none",
+ "possibleValues": [
+ "none",
+ "color loop"
+ ],
+ "writable": true
+ }
+ ]
+ },
+ {
+ "id": "a5b02af8-7c97-4a78-9c78-bafee7407b5e",
+ "name": "dimmableBulb",
+ "displayName": "Day and Dusk",
+ "createMethods": ["user", "discovery"],
+ "interfaces": ["colortemperaturelight", "connectable"],
+ "paramTypes": [
+ {
+ "id": "cc0a765b-a753-4e07-a6e5-47e9272c4346",
+ "name": "host",
+ "displayName": "Host address",
+ "type" : "QString",
+ "inputType": "IPv4Address",
+ "readOnly": true
+ },
+ {
+ "id": "d233d9bf-6662-414d-92f6-dd3e267051b5",
+ "name": "port",
+ "displayName": "Port",
+ "type" : "int",
+ "readOnly": true
+ },
+ {
+ "id": "f157a97b-3fe5-4d9e-b5e3-5636f80d46ed",
+ "name": "id",
+ "displayName": "Id",
+ "type" : "QString",
+ "readOnly": true
+ }
+ ],
+ "stateTypes": [
+ {
+ "id": "d33f98ef-5e0f-464c-afed-88b95cc701cd",
+ "name": "connected",
+ "displayName": "Reachable",
+ "displayNameEvent": "Reachable changed",
+ "defaultValue": false,
+ "type": "bool"
+ },
+ {
+ "id": "9e1344ea-cd05-4dd8-8948-8d2f5e00e1b0",
+ "name": "power",
+ "displayName": "Power",
+ "displayNameEvent": "Power changed",
+ "displayNameAction": "Set power",
+ "type": "bool",
+ "defaultValue": false,
+ "writable": true
+ },
+ {
+ "id": "a0a1bdcc-2761-4d90-85d1-5ce887546611",
+ "name": "brightness",
+ "displayName": "Brightness",
+ "displayNameEvent": "Brightness changed",
+ "displayNameAction": "Set brigtness",
+ "type": "int",
+ "unit": "Percentage",
+ "defaultValue": 0,
+ "minValue": 0,
+ "maxValue": 100,
+ "writable": true
+ },
+ {
+ "id": "95797dee-b836-4047-98d5-afbbce4f8c42",
+ "name": "colorTemperature",
+ "displayName": "Color temperature",
+ "displayNameEvent": "Color temperature changed",
+ "displayNameAction": "Set color temperature",
+ "type": "int",
+ "unit": "Mired",
+ "defaultValue": 170,
+ "minValue": 153,
+ "maxValue": 500,
+ "writable": true
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/lifx/lifx.cpp b/lifx/lifx.cpp
index e69de29b..24a037d9 100644
--- a/lifx/lifx.cpp
+++ b/lifx/lifx.cpp
@@ -0,0 +1,207 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This file is part of nymea.
+* This project including source code and documentation is protected by copyright law, and
+* remains the property of nymea GmbH. All rights, including reproduction, publication,
+* editing and translation, are reserved. The use of this project is subject to the terms of a
+* license agreement to be concluded with nymea GmbH in accordance with the terms
+* of use of nymea GmbH, available under https://nymea.io/license
+*
+* GNU Lesser General Public License Usage
+* This project may also contain libraries licensed under the open source software license GNU GPL v.3.
+* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
+* Lesser General Public License as published by the Free Software Foundation; version 3.
+* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along with this project.
+* If not, see .
+*
+* For any further details and any questions please contact us under contact@nymea.io
+* or see our FAQ/Licensing Information on https://nymea.io/license/faq
+*
+* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "lifx.h"
+#include "extern-plugininfo.h"
+
+#include
+#include
+
+Lifx::Lifx(QObject *parent) :
+ QObject(parent)
+{
+ m_reconnectTimer = new QTimer(this);
+ m_reconnectTimer->setSingleShot(true);
+ connect(m_reconnectTimer, &QTimer::timeout, this, &Lifx::onReconnectTimer);
+}
+
+Lifx::~Lifx()
+{
+ if (m_socket) {
+ m_socket->waitForBytesWritten(1000);
+ m_socket->close();
+ }
+}
+
+bool Lifx::enable()
+{
+ // Clean up
+ if (m_socket) {
+ delete m_socket;
+ m_socket = nullptr;
+ }
+
+ // Bind udp socket and join multicast group
+ m_socket = new QUdpSocket(this);
+ m_port = 56700;
+ m_host = QHostAddress("239.255.255.250");
+
+ m_socket->setSocketOption(QAbstractSocket::MulticastTtlOption,QVariant(1));
+ m_socket->setSocketOption(QAbstractSocket::MulticastLoopbackOption,QVariant(1));
+
+ if(!m_socket->bind(QHostAddress::AnyIPv4, m_port, QUdpSocket::ShareAddress)){
+ qCWarning(dcLifx()) << "could not bind to port" << m_port;
+ delete m_socket;
+ m_socket = nullptr;
+ return false;
+ }
+
+ if(!m_socket->joinMulticastGroup(m_host)){
+ qCWarning(dcLifx()) << "could not join multicast group" << m_host;
+ delete m_socket;
+ m_socket = nullptr;
+ return false;
+ }
+ connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
+ connect(m_socket, &QUdpSocket::readyRead, this, &Lifx::onReadyRead);
+ return true;
+}
+
+void Lifx::discoverDevices()
+{
+ Message message;
+ sendMessage(message);
+}
+
+int Lifx::setColorTemperature(int mirad, int msFadeTime)
+{
+ Q_UNUSED(mirad)
+ Q_UNUSED(msFadeTime)
+ int requestId = static_cast(QRandomGenerator::global()->generate());
+
+ return requestId;
+}
+
+int Lifx::setColor(QColor color, int msFadeTime)
+{
+ Q_UNUSED(color)
+ Q_UNUSED(msFadeTime)
+ int requestId = static_cast(QRandomGenerator::global()->generate());
+
+ return requestId;
+}
+
+int Lifx::setBrightness(int percentage, int msFadeTime)
+{
+ Q_UNUSED(percentage)
+ Q_UNUSED(msFadeTime)
+ int requestId = static_cast(QRandomGenerator::global()->generate());
+ Message message;
+ sendMessage(message);
+ return requestId;
+}
+
+int Lifx::setPower(bool power, int msFadeTime)
+{
+ Q_UNUSED(power)
+ Q_UNUSED(msFadeTime)
+ int requestId = static_cast(QRandomGenerator::global()->generate());
+
+ return requestId;
+}
+
+int Lifx::flash()
+{
+ int requestId = static_cast(QRandomGenerator::global()->generate());
+
+ return requestId;
+}
+
+int Lifx::flash15s()
+{
+ int requestId = static_cast(QRandomGenerator::global()->generate());
+
+ return requestId;
+}
+
+void Lifx::sendMessage(const Lifx::Message &message)
+{
+ QByteArray data;
+ // -- FRAME --
+ // Protocol number: must be 1024 (decimal)
+ quint16 protocol = 1024;
+ 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)
+ data.append(protocol >> 8);
+ data.append(protocol & 0xff);
+
+ //Source identifier: unique value set by the client, used by responses
+ data.append("nyma");
+
+ // -- FRAME ADDRESS --
+ //Target - frame address starts with 64 bits
+
+
+ //ADD RESERVED SECTION a reserved section of 48 bits (6 bytes)
+ data.append(6, '0');
+
+ //ADD ACK and RES
+
+ //ADD SEQUENCE NUMBER 1Byte
+ data.append(m_sequenceNumber + 1);
+
+ //ADD MESSAGE TYPE
+
+ //ADD SIZE
+ data.append(((static_cast(data.length()+1) & 0xff00) >> 8));
+ data.append((static_cast(data.length()+1) & 0x00ff));
+
+ //Finally another reserved field of 16 bits (2 bytes).
+ data.append(2, '0');
+ data = QByteArray::fromHex("0x310000340000000000000000000000000000000000000000000000000000000066000000005555FFFFFFFFAC0D00040000");
+ m_socket->writeDatagram(data, m_host, m_port);
+ Q_UNUSED(message)
+}
+
+void Lifx::onStateChanged(QAbstractSocket::SocketState state)
+{
+ switch (state) {
+ case QAbstractSocket::SocketState::ConnectedState:
+ emit connectionChanged(true);
+ break;
+ case QAbstractSocket::SocketState::UnconnectedState:
+ m_reconnectTimer->start(10 * 1000);
+ emit connectionChanged(false);
+ break;
+ default:
+ emit connectionChanged(false);
+ break;
+ }
+}
+
+void Lifx::onReadyRead()
+{
+ QByteArray data = m_socket->readAll();
+ qCDebug(dcLifx()) << "Message received" << data;
+}
+
+void Lifx::onReconnectTimer()
+{
+
+}
diff --git a/lifx/lifx.h b/lifx/lifx.h
index e69de29b..c0aabe83 100644
--- a/lifx/lifx.h
+++ b/lifx/lifx.h
@@ -0,0 +1,151 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This file is part of nymea.
+* This project including source code and documentation is protected by copyright law, and
+* remains the property of nymea GmbH. All rights, including reproduction, publication,
+* editing and translation, are reserved. The use of this project is subject to the terms of a
+* license agreement to be concluded with nymea GmbH in accordance with the terms
+* of use of nymea GmbH, available under https://nymea.io/license
+*
+* GNU Lesser General Public License Usage
+* This project may also contain libraries licensed under the open source software license GNU GPL v.3.
+* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
+* Lesser General Public License as published by the Free Software Foundation; version 3.
+* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along with this project.
+* If not, see .
+*
+* For any further details and any questions please contact us under contact@nymea.io
+* or see our FAQ/Licensing Information on https://nymea.io/license/faq
+*
+* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+#ifndef LIFX_H
+#define LIFX_H
+
+#include
+#include
+#include
+#include
+
+#include "network/networkaccessmanager.h"
+#include "devices/device.h"
+
+#include
+
+class Lifx : public QObject
+{
+ Q_OBJECT
+public:
+
+#pragma pack(push, 1)
+ typedef struct {
+ /* frame */
+ uint16_t size;
+ uint16_t protocol:12;
+ uint8_t addressable:1;
+ uint8_t tagged:1;
+ uint8_t origin:2;
+ uint32_t source;
+ /* frame address */
+ uint8_t target[8];
+ uint8_t reserved[6];
+ uint8_t res_required:1;
+ uint8_t ack_required:1;
+ uint8_t :6;
+ uint8_t sequence;
+ /* protocol header */
+ uint64_t :64;
+ uint16_t type;
+ uint16_t :16;
+ /* variable length payload follows */
+ } ProtocolHeader_t;
+#pragma pack(pop)
+
+ struct Frame {
+ //quint16 Size; //Size of entire message in bytes including this field
+ //quint16 Protocol; //Protocol number: must be 1024 (decimal)
+ //bool Addressable; //Message includes a target address: must be one (1)
+ bool Tagged; //Determines usage of the Frame Address target field
+ //quint8 Origin; //Message origin indicator: must be zero (0)
+ quint32 Source; //Source identifier: unique value set by the client, used by responses
+ };
+
+ struct FrameAddress {
+ quint64 Target; //6 byte device address (MAC address) or zero (0) means all devices. The last two bytes should be 0 bytes.
+ bool ResponseRequired; //Response message required
+ bool AckRequired; //Acknowledgement message required
+ quint8 Sequence; //Wrap around message sequence number
+ };
+
+ struct ProtocolHeader {
+ quint16 Type; //Message type determines the payload being used
+ };
+
+ struct Message {
+ Frame frame;
+ FrameAddress frameAddress;
+ ProtocolHeader protocolHeader;
+ QByteArray payload;
+ };
+
+ enum LightMessages {
+ Get = 101,
+ SetColor = 102,
+ SetWaveform = 103,
+ SetWaveformOptional = 119,
+ State = 107,
+ GetPower = 116,
+ SetPower = 117,
+ StatePower = 118,
+ GetInfrared = 120,
+ StateInfrared = 121,
+ SetInfrared = 122
+ };
+
+ explicit Lifx(QObject *parent = nullptr);
+ ~Lifx();
+ bool enable();
+
+ void discoverDevices();
+ int setColorTemperature(int kelvin, int msFadeTime=500);
+ int setColor(QColor color, int msFadeTime = 500);
+ int setBrightness(int percentage, int msFadeTime = 500);
+ int setPower(bool power, int msFadeTime = 500);
+ int flash();
+ int flash15s();
+
+private:
+ QTimer *m_reconnectTimer = nullptr;
+ QUdpSocket *m_socket = nullptr;
+ QHostAddress m_host;
+ quint16 m_port;
+ quint8 m_sequenceNumber = 0;
+
+ void sendMessage(const Message &message);
+
+private slots:
+ void onStateChanged(QAbstractSocket::SocketState state);
+ void onReadyRead();
+ void onReconnectTimer();
+
+signals:
+ void connectionChanged(bool connected);
+ void devicesDiscovered(QHostAddress address, int port);
+ //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
diff --git a/lifx/lifx.pro b/lifx/lifx.pro
index 0ddd32b8..564f54d1 100644
--- a/lifx/lifx.pro
+++ b/lifx/lifx.pro
@@ -1,9 +1,9 @@
include(../plugins.pri)
-QT += network
-
TARGET = $$qtLibraryTarget(nymea_devicepluginlifx)
+QT += network
+
SOURCES += \
devicepluginlifx.cpp \
lifx.cpp \
diff --git a/lifx/products.json b/lifx/products.json
new file mode 100644
index 00000000..99f8a77a
--- /dev/null
+++ b/lifx/products.json
@@ -0,0 +1,373 @@
+[
+ {
+ "vid": 1,
+ "name": "LIFX",
+ "products": [
+ {
+ "pid": 1,
+ "name": "Original 1000",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 3,
+ "name": "Color 650",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 10,
+ "name": "White 800 (Low Voltage)",
+ "features": {
+ "color": false,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2700, 6500],
+ "chain": false
+ }
+ },
+ {
+ "pid": 11,
+ "name": "White 800 (High Voltage)",
+ "features": {
+ "color": false,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2700, 6500],
+ "chain": false
+ }
+ },
+ {
+ "pid": 18,
+ "name": "White 900 BR30 (Low Voltage)",
+ "features": {
+ "color": false,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2700, 6500],
+ "chain": false
+ }
+ },
+ {
+ "pid": 20,
+ "name": "Color 1000 BR30",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 22,
+ "name": "Color 1000",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 27,
+ "name": "LIFX A19",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 28,
+ "name": "LIFX BR30",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 29,
+ "name": "LIFX+ A19",
+ "features": {
+ "color": true,
+ "infrared": true,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 30,
+ "name": "LIFX+ BR30",
+ "features": {
+ "color": true,
+ "infrared": true,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 31,
+ "name": "LIFX Z",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": true,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 32,
+ "name": "LIFX Z 2",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": true,
+ "temperature_range": [2500, 9000],
+ "chain": false,
+ "min_ext_mz_firmware": 1532997580,
+ "min_ext_mz_firmware_components": [2, 77]
+ }
+ },
+ {
+ "pid": 36,
+ "name": "LIFX Downlight",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 37,
+ "name": "LIFX Downlight",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 38,
+ "name": "LIFX Beam",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": true,
+ "temperature_range": [2500, 9000],
+ "chain": false,
+ "min_ext_mz_firmware": 1532997580,
+ "min_ext_mz_firmware_components": [2, 77]
+ }
+ },
+ {
+ "pid": 43,
+ "name": "LIFX A19",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 44,
+ "name": "LIFX BR30",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 45,
+ "name": "LIFX+ A19",
+ "features": {
+ "color": true,
+ "infrared": true,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 46,
+ "name": "LIFX+ BR30",
+ "features": {
+ "color": true,
+ "infrared": true,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 49,
+ "name": "LIFX Mini",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 50,
+ "name": "LIFX Mini Day and Dusk",
+ "features": {
+ "color": false,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [1500, 4000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 51,
+ "name": "LIFX Mini White",
+ "features": {
+ "color": false,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2700, 2700],
+ "chain": false
+ }
+ },
+ {
+ "pid": 52,
+ "name": "LIFX GU10",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 55,
+ "name": "LIFX Tile",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": true,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": true
+ }
+ },
+ {
+ "pid": 57,
+ "name": "LIFX Candle",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": true,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 59,
+ "name": "LIFX Mini Color",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 60,
+ "name": "LIFX Mini Day and Dusk",
+ "features": {
+ "color": false,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [1500, 4000],
+ "chain": false
+ }
+ },
+ {
+ "pid": 61,
+ "name": "LIFX Mini White",
+ "features": {
+ "color": false,
+ "infrared": false,
+ "matrix": false,
+ "multizone": false,
+ "temperature_range": [2700, 2700],
+ "chain": false
+ }
+ },
+ {
+ "pid": 68,
+ "name": "LIFX Candle",
+ "features": {
+ "color": true,
+ "infrared": false,
+ "matrix": true,
+ "multizone": false,
+ "temperature_range": [2500, 9000],
+ "chain": false
+ }
+ }
+ ]
+ }
+]
+
diff --git a/lifx/translations/4e00ee30-79e2-447b-8dcc-c34470f41992-en_US.ts b/lifx/translations/4e00ee30-79e2-447b-8dcc-c34470f41992-en_US.ts
new file mode 100644
index 00000000..6d128630
--- /dev/null
+++ b/lifx/translations/4e00ee30-79e2-447b-8dcc-c34470f41992-en_US.ts
@@ -0,0 +1,185 @@
+
+
+
+
+ Lifx
+
+ Brightness
+ The name of the ParamType (DeviceClass: dimmableBulb, ActionType: brightness, ID: {a0a1bdcc-2761-4d90-85d1-5ce887546611})
+----------
+The name of the ParamType (DeviceClass: dimmableBulb, EventType: brightness, ID: {a0a1bdcc-2761-4d90-85d1-5ce887546611})
+----------
+The name of the StateType ({a0a1bdcc-2761-4d90-85d1-5ce887546611}) of DeviceClass dimmableBulb
+----------
+The name of the ParamType (DeviceClass: colorBulb, ActionType: brightness, ID: {8bd20350-0e79-45dc-b68a-84da99356863})
+----------
+The name of the ParamType (DeviceClass: colorBulb, EventType: brightness, ID: {8bd20350-0e79-45dc-b68a-84da99356863})
+----------
+The name of the StateType ({8bd20350-0e79-45dc-b68a-84da99356863}) of DeviceClass colorBulb
+
+
+
+ Brightness changed
+ The name of the EventType ({a0a1bdcc-2761-4d90-85d1-5ce887546611}) of DeviceClass dimmableBulb
+----------
+The name of the EventType ({8bd20350-0e79-45dc-b68a-84da99356863}) of DeviceClass colorBulb
+
+
+
+ Color
+ The name of the ParamType (DeviceClass: colorBulb, ActionType: color, ID: {a47d8164-5023-4ffb-8298-73293e93e7f6})
+----------
+The name of the ParamType (DeviceClass: colorBulb, EventType: color, ID: {a47d8164-5023-4ffb-8298-73293e93e7f6})
+----------
+The name of the StateType ({a47d8164-5023-4ffb-8298-73293e93e7f6}) of DeviceClass colorBulb
+----------
+The name of the DeviceClass ({12907c9c-e7f0-47f2-bd58-39d52ffdf24e})
+
+
+
+ Color changed
+ The name of the EventType ({a47d8164-5023-4ffb-8298-73293e93e7f6}) of DeviceClass colorBulb
+
+
+
+ Color temperature
+ The name of the ParamType (DeviceClass: dimmableBulb, ActionType: colorTemperature, ID: {95797dee-b836-4047-98d5-afbbce4f8c42})
+----------
+The name of the ParamType (DeviceClass: dimmableBulb, EventType: colorTemperature, ID: {95797dee-b836-4047-98d5-afbbce4f8c42})
+----------
+The name of the StateType ({95797dee-b836-4047-98d5-afbbce4f8c42}) of DeviceClass dimmableBulb
+----------
+The name of the ParamType (DeviceClass: colorBulb, ActionType: colorTemperature, ID: {dd7d7e70-5552-4531-8789-2d0f750488be})
+----------
+The name of the ParamType (DeviceClass: colorBulb, EventType: colorTemperature, ID: {dd7d7e70-5552-4531-8789-2d0f750488be})
+----------
+The name of the StateType ({dd7d7e70-5552-4531-8789-2d0f750488be}) of DeviceClass colorBulb
+
+
+
+ Color temperature changed
+ The name of the EventType ({95797dee-b836-4047-98d5-afbbce4f8c42}) of DeviceClass dimmableBulb
+----------
+The name of the EventType ({dd7d7e70-5552-4531-8789-2d0f750488be}) of DeviceClass colorBulb
+
+
+
+ Day and Dusk
+ The name of the DeviceClass ({a5b02af8-7c97-4a78-9c78-bafee7407b5e})
+
+
+
+ Host address
+ The name of the ParamType (DeviceClass: dimmableBulb, Type: device, ID: {cc0a765b-a753-4e07-a6e5-47e9272c4346})
+----------
+The name of the ParamType (DeviceClass: colorBulb, Type: device, ID: {fd1c4817-5111-433a-b5b9-fd9f49d4975c})
+
+
+
+ Id
+ The name of the ParamType (DeviceClass: dimmableBulb, Type: device, ID: {f157a97b-3fe5-4d9e-b5e3-5636f80d46ed})
+----------
+The name of the ParamType (DeviceClass: colorBulb, Type: device, ID: {976ecea0-ac25-47d4-9dc5-362962ddb6c0})
+
+
+
+ LIFX
+ The name of the vendor ({e5e48c0d-cff7-4c0f-983e-d23bd3e4ba87})
+----------
+The name of the plugin Lifx ({4e00ee30-79e2-447b-8dcc-c34470f41992})
+
+
+
+ Port
+ The name of the ParamType (DeviceClass: dimmableBulb, Type: device, ID: {d233d9bf-6662-414d-92f6-dd3e267051b5})
+----------
+The name of the ParamType (DeviceClass: colorBulb, Type: device, ID: {44c13745-300c-491f-b617-3a8d53472998})
+
+
+
+ Power
+ The name of the ParamType (DeviceClass: dimmableBulb, ActionType: power, ID: {9e1344ea-cd05-4dd8-8948-8d2f5e00e1b0})
+----------
+The name of the ParamType (DeviceClass: dimmableBulb, EventType: power, ID: {9e1344ea-cd05-4dd8-8948-8d2f5e00e1b0})
+----------
+The name of the StateType ({9e1344ea-cd05-4dd8-8948-8d2f5e00e1b0}) of DeviceClass dimmableBulb
+----------
+The name of the ParamType (DeviceClass: colorBulb, ActionType: power, ID: {12de3f8f-2454-4057-aa12-9290296fdbdd})
+----------
+The name of the ParamType (DeviceClass: colorBulb, EventType: power, ID: {12de3f8f-2454-4057-aa12-9290296fdbdd})
+----------
+The name of the StateType ({12de3f8f-2454-4057-aa12-9290296fdbdd}) of DeviceClass colorBulb
+
+
+
+ Power changed
+ The name of the EventType ({9e1344ea-cd05-4dd8-8948-8d2f5e00e1b0}) of DeviceClass dimmableBulb
+----------
+The name of the EventType ({12de3f8f-2454-4057-aa12-9290296fdbdd}) of DeviceClass colorBulb
+
+
+
+ Reachable
+ The name of the ParamType (DeviceClass: dimmableBulb, EventType: connected, ID: {d33f98ef-5e0f-464c-afed-88b95cc701cd})
+----------
+The name of the StateType ({d33f98ef-5e0f-464c-afed-88b95cc701cd}) of DeviceClass dimmableBulb
+----------
+The name of the ParamType (DeviceClass: colorBulb, EventType: connected, ID: {dc4c1640-90f3-4fe0-af9b-db7fa105f18a})
+----------
+The name of the StateType ({dc4c1640-90f3-4fe0-af9b-db7fa105f18a}) of DeviceClass colorBulb
+
+
+
+ Reachable changed
+ The name of the EventType ({d33f98ef-5e0f-464c-afed-88b95cc701cd}) of DeviceClass dimmableBulb
+----------
+The name of the EventType ({dc4c1640-90f3-4fe0-af9b-db7fa105f18a}) of DeviceClass colorBulb
+
+
+
+ Set brigtness
+ The name of the ActionType ({a0a1bdcc-2761-4d90-85d1-5ce887546611}) of DeviceClass dimmableBulb
+----------
+The name of the ActionType ({8bd20350-0e79-45dc-b68a-84da99356863}) of DeviceClass colorBulb
+
+
+
+ Set color
+ The name of the ActionType ({a47d8164-5023-4ffb-8298-73293e93e7f6}) of DeviceClass colorBulb
+
+
+
+ Set color temperature
+ The name of the ActionType ({95797dee-b836-4047-98d5-afbbce4f8c42}) of DeviceClass dimmableBulb
+----------
+The name of the ActionType ({dd7d7e70-5552-4531-8789-2d0f750488be}) of DeviceClass colorBulb
+
+
+
+ Set effect
+ The name of the ActionType ({65f88396-2958-480e-b0be-c4695400a343}) of DeviceClass colorBulb
+
+
+
+ Set power
+ The name of the ActionType ({9e1344ea-cd05-4dd8-8948-8d2f5e00e1b0}) of DeviceClass dimmableBulb
+----------
+The name of the ActionType ({12de3f8f-2454-4057-aa12-9290296fdbdd}) of DeviceClass colorBulb
+
+
+
+ effect
+ The name of the ParamType (DeviceClass: colorBulb, ActionType: effect, ID: {65f88396-2958-480e-b0be-c4695400a343})
+----------
+The name of the ParamType (DeviceClass: colorBulb, EventType: effect, ID: {65f88396-2958-480e-b0be-c4695400a343})
+----------
+The name of the StateType ({65f88396-2958-480e-b0be-c4695400a343}) of DeviceClass colorBulb
+
+
+
+ effect changed
+ The name of the EventType ({65f88396-2958-480e-b0be-c4695400a343}) of DeviceClass colorBulb
+
+
+
+