added alert interface

This commit is contained in:
Boernsman 2020-01-03 14:26:18 +01:00
parent 9e53feb985
commit 6771504edf
6 changed files with 510 additions and 175 deletions

View File

@ -1 +1,34 @@
# Nanoleaf # Nanoleaf
This Plug-In allows to control Nanoleaf Light Panels.
## Features
Controls:
* Power
* Brightness
* Color Temperature
* Color
* Set Effect
States:
* Connected
Browsing:
This plug-in implements also browsing for light effects, means if a new light effect is beeing added
nymea will find that.
## Device Setup
The Nanoleaf App is required to connect the device to the WiFi Network.
This Plug-In uses the local API of Nanoleaf devices, means
nymea must be in the same local area network.
The device will be discovered through Zeroconf, if it
can't be discovered the Network might not support Zeroconf
and the IP-Address must be entered manually.
More about Nanoleaf devices:
https://nanoleaf.me

View File

@ -1,24 +1,30 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * *
* Copyright (C) 2020 Bernhard Trinnes <bernhard.trinnes@nymea.io> * * Copyright 2013 - 2020, nymea GmbH
* * * Contact: contact@nymea.io
* This file is part of nymea. * *
* * * This file is part of nymea.
* This library is free software; you can redistribute it and/or * * This project including source code and documentation is protected by copyright law, and
* modify it under the terms of the GNU Lesser General Public * * remains the property of nymea GmbH. All rights, including reproduction, publication,
* License as published by the Free Software Foundation; either * * editing and translation, are reserved. The use of this project is subject to the terms of a
* version 2.1 of the License, or (at your option) any later version. * * license agreement to be concluded with nymea GmbH in accordance with the terms
* * * of use of nymea GmbH, available under https://nymea.io/license
* This library is distributed in the hope that it will be useful, * *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * GNU Lesser General Public License Usage
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * This project may also contain libraries licensed under the open source software license GNU GPL v.3.
* Lesser General Public License for more details. * * 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.
* You should have received a copy of the GNU Lesser General Public * * this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* License along with this library; If not, see * * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* <http://www.gnu.org/licenses/>. * * See the GNU Lesser General Public License for more details.
* * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "devicepluginnanoleaf.h" #include "devicepluginnanoleaf.h"
#include "plugininfo.h" #include "plugininfo.h"
@ -34,13 +40,11 @@ DevicePluginNanoleaf::DevicePluginNanoleaf()
} }
void DevicePluginNanoleaf::init() void DevicePluginNanoleaf::init()
{ {
m_zeroconfBrowser = hardwareManager()->zeroConfController()->createServiceBrowser("_nanoleafapi._tcp"); m_zeroconfBrowser = hardwareManager()->zeroConfController()->createServiceBrowser("_nanoleafapi._tcp");
} }
void DevicePluginNanoleaf::discoverDevices(DeviceDiscoveryInfo *info) void DevicePluginNanoleaf::discoverDevices(DeviceDiscoveryInfo *info)
{ {
QStringList serialNumbers; QStringList serialNumbers;
@ -68,6 +72,7 @@ void DevicePluginNanoleaf::discoverDevices(DeviceDiscoveryInfo *info)
Device *existingDevice = myDevices().findByParams(ParamList() << Param(lightPanelsDeviceSerialNoParamTypeId, serialNo)); Device *existingDevice = myDevices().findByParams(ParamList() << Param(lightPanelsDeviceSerialNoParamTypeId, serialNo));
if (existingDevice) { if (existingDevice) {
//For device rediscovery
descriptor.setDeviceId(existingDevice->id()); descriptor.setDeviceId(existingDevice->id());
} }
@ -81,47 +86,30 @@ void DevicePluginNanoleaf::discoverDevices(DeviceDiscoveryInfo *info)
descriptor.setParams(params); descriptor.setParams(params);
info->addDeviceDescriptor(descriptor); info->addDeviceDescriptor(descriptor);
} }
info->finish(Device::DeviceErrorNoError); info->finish(Device::DeviceErrorNoError);
} }
void DevicePluginNanoleaf::startPairing(DevicePairingInfo *info) void DevicePluginNanoleaf::startPairing(DevicePairingInfo *info)
{ {
info->finish(Device::DeviceErrorNoError, tr("On the Nanoleaf controller, hold the on-off button for 5-7 seconds until the LED starts flashing.")); info->finish(Device::DeviceErrorNoError, tr("On the Nanoleaf controller, hold the on-off button for 5-7 seconds until the LED starts flashing."));
} }
void DevicePluginNanoleaf::confirmPairing(DevicePairingInfo *info, const QString &username, const QString &secret) void DevicePluginNanoleaf::confirmPairing(DevicePairingInfo *info, const QString &username, const QString &secret)
{ {
Q_UNUSED(username) Q_UNUSED(username)
Q_UNUSED(secret) Q_UNUSED(secret)
Nanoleaf *nanoleaf = new Nanoleaf(hardwareManager()->networkManager(), QHostAddress(info->params().paramValue(lightPanelsDeviceAddressParamTypeId).toString()), info->params().paramValue(lightPanelsDevicePortParamTypeId).toInt(), this); Nanoleaf *nanoleaf = createNanoleafConnection(QHostAddress(info->params().paramValue(lightPanelsDeviceAddressParamTypeId).toString()), info->params().paramValue(lightPanelsDevicePortParamTypeId).toInt());
connect(nanoleaf, &Nanoleaf::authTokenRecieved, this, &DevicePluginNanoleaf::onAuthTokenReceived);
connect(nanoleaf, &Nanoleaf::authenticationStatusChanged, this, &DevicePluginNanoleaf::onAuthenticationStatusChanged);
connect(nanoleaf, &Nanoleaf::requestExecuted, this, &DevicePluginNanoleaf::onRequestExecuted);
connect(nanoleaf, &Nanoleaf::connectionChanged, this, &DevicePluginNanoleaf::onConnectionChanged);
connect(nanoleaf, &Nanoleaf::brightnessReceived, this, &DevicePluginNanoleaf::onBrightnessReceived);
connect(nanoleaf, &Nanoleaf::powerReceived, this, &DevicePluginNanoleaf::onPowerReceived);
connect(nanoleaf, &Nanoleaf::colorModeReceived, this, &DevicePluginNanoleaf::onColorModeReceived);
connect(nanoleaf, &Nanoleaf::colorTemperatureReceived, this, &DevicePluginNanoleaf::onColorTemperatureReceived);
connect(nanoleaf, &Nanoleaf::saturationReceived, this, &DevicePluginNanoleaf::onSaturationReceived);
connect(nanoleaf, &Nanoleaf::hueReceived, this, &DevicePluginNanoleaf::onHueReceived);
connect(nanoleaf, &Nanoleaf::effectListReceived, this, &DevicePluginNanoleaf::onEffectListReceived);
connect(nanoleaf, &Nanoleaf::selectedEffectReceived, this, &DevicePluginNanoleaf::onSelectedEffectReceived);
nanoleaf->addUser(); //push button pairing nanoleaf->addUser(); //push button pairing
m_unfinishedNanoleafConnections.insert(info->deviceId(), nanoleaf); m_unfinishedNanoleafConnections.insert(info->deviceId(), nanoleaf);
m_unfinishedPairing.insert(nanoleaf, info); m_unfinishedPairing.insert(nanoleaf, info);
connect(info, &DevicePairingInfo::aborted, this, [info, this] { connect(info, &DevicePairingInfo::aborted, this, [info, this] {
Nanoleaf *nanoleaf = m_unfinishedNanoleafConnections.take(info->deviceId()); Nanoleaf *nanoleaf = m_unfinishedNanoleafConnections.take(info->deviceId());
m_unfinishedPairing.remove(nanoleaf); m_unfinishedPairing.remove(nanoleaf);
nanoleaf->deleteLater(); nanoleaf->deleteLater();
}); });
} }
void DevicePluginNanoleaf::setupDevice(DeviceSetupInfo *info) void DevicePluginNanoleaf::setupDevice(DeviceSetupInfo *info)
{ {
Device *device = info->device(); Device *device = info->device();
@ -132,29 +120,17 @@ void DevicePluginNanoleaf::setupDevice(DeviceSetupInfo *info)
Nanoleaf *nanoleaf; Nanoleaf *nanoleaf;
if (m_unfinishedNanoleafConnections.contains(device->id())) { if (m_unfinishedNanoleafConnections.contains(device->id())) {
// This setupDevice is called after a discovery
nanoleaf = m_unfinishedNanoleafConnections.take(device->id()); nanoleaf = m_unfinishedNanoleafConnections.take(device->id());
m_nanoleafConnections.insert(device->id(), nanoleaf); m_nanoleafConnections.insert(device->id(), nanoleaf);
return info->finish(Device::DeviceErrorNoError); return info->finish(Device::DeviceErrorNoError);
} else { } else {
// This setupDevice is called after a (re)start, with an already added device
QHostAddress address(device->paramValue(lightPanelsDeviceAddressParamTypeId).toString()); QHostAddress address(device->paramValue(lightPanelsDeviceAddressParamTypeId).toString());
int port = device->paramValue(lightPanelsDevicePortParamTypeId).toInt(); int port = device->paramValue(lightPanelsDevicePortParamTypeId).toInt();
nanoleaf = new Nanoleaf(hardwareManager()->networkManager(), address, port, this); nanoleaf = createNanoleafConnection(address, port);
connect(nanoleaf, &Nanoleaf::authTokenRecieved, this, &DevicePluginNanoleaf::onAuthTokenReceived);
connect(nanoleaf, &Nanoleaf::authenticationStatusChanged, this, &DevicePluginNanoleaf::onAuthenticationStatusChanged);
connect(nanoleaf, &Nanoleaf::requestExecuted, this, &DevicePluginNanoleaf::onRequestExecuted);
connect(nanoleaf, &Nanoleaf::connectionChanged, this, &DevicePluginNanoleaf::onConnectionChanged);
connect(nanoleaf, &Nanoleaf::brightnessReceived, this, &DevicePluginNanoleaf::onBrightnessReceived);
connect(nanoleaf, &Nanoleaf::powerReceived, this, &DevicePluginNanoleaf::onPowerReceived);
connect(nanoleaf, &Nanoleaf::colorModeReceived, this, &DevicePluginNanoleaf::onColorModeReceived);
connect(nanoleaf, &Nanoleaf::saturationReceived, this, &DevicePluginNanoleaf::onSaturationReceived);
connect(nanoleaf, &Nanoleaf::hueReceived, this, &DevicePluginNanoleaf::onHueReceived);
connect(nanoleaf, &Nanoleaf::colorTemperatureReceived, this, &DevicePluginNanoleaf::onColorTemperatureReceived);
connect(nanoleaf, &Nanoleaf::effectListReceived, this, &DevicePluginNanoleaf::onEffectListReceived);
connect(nanoleaf, &Nanoleaf::selectedEffectReceived, this, &DevicePluginNanoleaf::onSelectedEffectReceived);
nanoleaf->setAuthToken(token); nanoleaf->setAuthToken(token);
nanoleaf->getControllerInfo(); //we don't care about the controller info, this is just to check if the device is available nanoleaf->getControllerInfo(); //This is just to check if the device is available
m_nanoleafConnections.insert(device->id(), nanoleaf); m_nanoleafConnections.insert(device->id(), nanoleaf);
m_asyncDeviceSetup.insert(nanoleaf, info); m_asyncDeviceSetup.insert(nanoleaf, info);
@ -164,19 +140,21 @@ void DevicePluginNanoleaf::setupDevice(DeviceSetupInfo *info)
} }
} }
void DevicePluginNanoleaf::postSetupDevice(Device *device) void DevicePluginNanoleaf::postSetupDevice(Device *device)
{ {
if (device->deviceClassId() == lightPanelsDeviceClassId) { if (device->deviceClassId() == lightPanelsDeviceClassId) {
//Nanoleaf *nanoleaf = m_nanoleafConnections.value(device->id()); Nanoleaf *nanoleaf = m_nanoleafConnections.value(device->id());
//getDeviceStates(nanoleaf); if (!nanoleaf)
return;
nanoleaf->getControllerInfo();
nanoleaf->registerForEvents();
} }
if(!m_pluginTimer) { if(!m_pluginTimer) {
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(5); m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(5);
connect(m_pluginTimer, &PluginTimer::timeout, this, [this]() { connect(m_pluginTimer, &PluginTimer::timeout, this, [this]() {
foreach (Nanoleaf *nanoleaf, m_nanoleafConnections) { foreach (Nanoleaf *nanoleaf, m_nanoleafConnections) {
getDeviceStates(nanoleaf); nanoleaf->getControllerInfo();
} }
}); });
} }
@ -204,6 +182,10 @@ void DevicePluginNanoleaf::executeAction(DeviceActionInfo *info)
if (device->deviceClassId() == lightPanelsDeviceClassId) { if (device->deviceClassId() == lightPanelsDeviceClassId) {
Nanoleaf *nanoleaf = m_nanoleafConnections.value(device->id()); Nanoleaf *nanoleaf = m_nanoleafConnections.value(device->id());
if (!nanoleaf) {
return info->finish(Device::DeviceErrorHardwareFailure);
}
if (action.actionTypeId() == lightPanelsPowerActionTypeId) { if (action.actionTypeId() == lightPanelsPowerActionTypeId) {
bool power = action.param(lightPanelsPowerActionPowerParamTypeId).value().toBool(); bool power = action.param(lightPanelsPowerActionPowerParamTypeId).value().toBool();
QUuid requestId = nanoleaf->setPower(power); QUuid requestId = nanoleaf->setPower(power);
@ -218,13 +200,17 @@ void DevicePluginNanoleaf::executeAction(DeviceActionInfo *info)
} else if (action.actionTypeId() == lightPanelsColorActionTypeId) { } else if (action.actionTypeId() == lightPanelsColorActionTypeId) {
QColor color(action.param(lightPanelsColorActionColorParamTypeId).value().toString()); QColor color(action.param(lightPanelsColorActionColorParamTypeId).value().toString());
QUuid requestId = nanoleaf->setHue(color); QUuid requestId = nanoleaf->setColor(color);
connect(info, &DeviceActionInfo::aborted,[requestId, this](){m_asyncActions.remove(requestId);}); connect(info, &DeviceActionInfo::aborted,[requestId, this](){m_asyncActions.remove(requestId);});
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
} else if (action.actionTypeId() == lightPanelsColorTemperatureActionTypeId) { } else if (action.actionTypeId() == lightPanelsColorTemperatureActionTypeId) {
int colorTemperature = action.param(lightPanelsColorTemperatureActionColorTemperatureParamTypeId).value().toInt(); int colorTemperature = action.param(lightPanelsColorTemperatureActionColorTemperatureParamTypeId).value().toInt();
QUuid requestId = nanoleaf->setColorTemperature(colorTemperature); QUuid requestId = nanoleaf->setMired(colorTemperature);
connect(info, &DeviceActionInfo::aborted,[requestId, this](){m_asyncActions.remove(requestId);});
m_asyncActions.insert(requestId, info);
} else if (action.actionTypeId() == lightPanelsAlertActionTypeId) {
QUuid requestId = nanoleaf->identify();
connect(info, &DeviceActionInfo::aborted,[requestId, this](){m_asyncActions.remove(requestId);}); connect(info, &DeviceActionInfo::aborted,[requestId, this](){m_asyncActions.remove(requestId);});
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
} }
@ -234,10 +220,10 @@ void DevicePluginNanoleaf::executeAction(DeviceActionInfo *info)
void DevicePluginNanoleaf::browseDevice(BrowseResult *result) void DevicePluginNanoleaf::browseDevice(BrowseResult *result)
{ {
Device *device = result->device(); Device *device = result->device();
Nanoleaf *nanoleaf = m_nanoleafConnections.value(device->id()); Nanoleaf *nanoleaf = m_nanoleafConnections.value(device->id());
nanoleaf->getEffects(); nanoleaf->getEffects();
m_asyncBrowseResults.insert(nanoleaf, result); m_asyncBrowseResults.insert(nanoleaf, result);
connect(result, &BrowseResult::aborted, this, [nanoleaf, this]{m_asyncBrowseResults.remove(nanoleaf);}); connect(result, &BrowseResult::aborted, this, [nanoleaf, this]{m_asyncBrowseResults.remove(nanoleaf);});
} }
void DevicePluginNanoleaf::browserItem(BrowserItemResult *result) void DevicePluginNanoleaf::browserItem(BrowserItemResult *result)
@ -260,15 +246,24 @@ void DevicePluginNanoleaf::executeBrowserItem(BrowserActionInfo *info)
connect(info, &BrowserActionInfo::aborted, this, [requestId, this]{m_asyncBrowserItem.remove(requestId);}); connect(info, &BrowserActionInfo::aborted, this, [requestId, this]{m_asyncBrowserItem.remove(requestId);});
} }
Nanoleaf *DevicePluginNanoleaf::createNanoleafConnection(const QHostAddress &address, int port)
void DevicePluginNanoleaf::getDeviceStates(Nanoleaf *nanoleaf)
{ {
nanoleaf->getPower(); Nanoleaf *nanoleaf = new Nanoleaf(hardwareManager()->networkManager(), address, port, this);
nanoleaf->getHue(); connect(nanoleaf, &Nanoleaf::authTokenRecieved, this, &DevicePluginNanoleaf::onAuthTokenReceived);
nanoleaf->getColorMode(); connect(nanoleaf, &Nanoleaf::authenticationStatusChanged, this, &DevicePluginNanoleaf::onAuthenticationStatusChanged);
nanoleaf->getBrightness(); connect(nanoleaf, &Nanoleaf::requestExecuted, this, &DevicePluginNanoleaf::onRequestExecuted);
nanoleaf->getColorTemperature(); connect(nanoleaf, &Nanoleaf::connectionChanged, this, &DevicePluginNanoleaf::onConnectionChanged);
nanoleaf->getSelectedEffect();
connect(nanoleaf, &Nanoleaf::controllerInfoReceived, this, &DevicePluginNanoleaf::onControllerInfoReceived);
connect(nanoleaf, &Nanoleaf::brightnessReceived, this, &DevicePluginNanoleaf::onBrightnessReceived);
connect(nanoleaf, &Nanoleaf::powerReceived, this, &DevicePluginNanoleaf::onPowerReceived);
connect(nanoleaf, &Nanoleaf::colorModeReceived, this, &DevicePluginNanoleaf::onColorModeReceived);
connect(nanoleaf, &Nanoleaf::saturationReceived, this, &DevicePluginNanoleaf::onSaturationReceived);
connect(nanoleaf, &Nanoleaf::hueReceived, this, &DevicePluginNanoleaf::onHueReceived);
connect(nanoleaf, &Nanoleaf::colorTemperatureReceived, this, &DevicePluginNanoleaf::onColorTemperatureReceived);
connect(nanoleaf, &Nanoleaf::effectListReceived, this, &DevicePluginNanoleaf::onEffectListReceived);
connect(nanoleaf, &Nanoleaf::selectedEffectReceived, this, &DevicePluginNanoleaf::onSelectedEffectReceived);
return nanoleaf;
} }
void DevicePluginNanoleaf::onAuthTokenReceived(const QString &token) void DevicePluginNanoleaf::onAuthTokenReceived(const QString &token)
@ -326,12 +321,23 @@ void DevicePluginNanoleaf::onConnectionChanged(bool connected)
device->setStateValue(lightPanelsConnectedStateTypeId, connected); device->setStateValue(lightPanelsConnectedStateTypeId, connected);
} }
void DevicePluginNanoleaf::onControllerInfoReceived(const Nanoleaf::ControllerInfo &controllerInfo)
{
Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender());
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device)
return;
qCDebug(dcNanoleaf()) << "Controller Info received" << controllerInfo.name << controllerInfo.firmwareVersion;
device->setParamValue(lightPanelsDeviceFirmwareVersionParamTypeId, controllerInfo.firmwareVersion);
}
void DevicePluginNanoleaf::onPowerReceived(bool power) void DevicePluginNanoleaf::onPowerReceived(bool power)
{ {
Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender()); Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender());
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf)); Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device) if (!device)
return; return;
qCDebug(dcNanoleaf()) << "Power received" << power;
device->setStateValue(lightPanelsPowerStateTypeId, power); device->setStateValue(lightPanelsPowerStateTypeId, power);
} }
@ -341,6 +347,7 @@ void DevicePluginNanoleaf::onBrightnessReceived(int percentage)
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf)); Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device) if (!device)
return; return;
qCDebug(dcNanoleaf()) << "Brightness received" << percentage;
device->setStateValue(lightPanelsBrightnessStateTypeId, percentage); device->setStateValue(lightPanelsBrightnessStateTypeId, percentage);
} }
@ -350,6 +357,7 @@ void DevicePluginNanoleaf::onColorModeReceived(const QString &colorMode)
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf)); Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device) if (!device)
return; return;
qCDebug(dcNanoleaf()) << "Color mode received" << colorMode;
device->setStateValue(lightPanelsColorModeStateTypeId, colorMode); device->setStateValue(lightPanelsColorModeStateTypeId, colorMode);
} }
@ -359,6 +367,7 @@ void DevicePluginNanoleaf::onHueReceived(int hue)
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf)); Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device) if (!device)
return; return;
qCDebug(dcNanoleaf()) << "Hue received" << hue;
m_hues.insert(device->id(), hue); m_hues.insert(device->id(), hue);
nanoleaf->getSaturation(); nanoleaf->getSaturation();
} }
@ -372,7 +381,6 @@ void DevicePluginNanoleaf::onSaturationReceived(int saturation)
qCDebug(dcNanoleaf()) << "Saturation received" << saturation; qCDebug(dcNanoleaf()) << "Saturation received" << saturation;
QColor color; QColor color;
color.setHsv(m_hues.value(device->id()), saturation, 100); color.setHsv(m_hues.value(device->id()), saturation, 100);
//TODO get hue
device->setStateValue(lightPanelsColorStateTypeId, color); device->setStateValue(lightPanelsColorStateTypeId, color);
} }
@ -394,17 +402,20 @@ void DevicePluginNanoleaf::onEffectListReceived(const QStringList &effects)
item.setDisplayName(effect); item.setDisplayName(effect);
item.setDisabled(false); item.setDisabled(false);
result->addItem(item); result->addItem(item);
} }
result->finish(Device::DeviceErrorNoError); result->finish(Device::DeviceErrorNoError);
} }
} }
void DevicePluginNanoleaf::onColorTemperatureReceived(int mired) void DevicePluginNanoleaf::onColorTemperatureReceived(int kelvin)
{ {
Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender()); Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender());
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf)); Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device) if (!device)
return; return;
qCDebug(dcNanoleaf()) << "Color temperature received" << kelvin;
//NOTE: this is just a rough estimation of the mired value
int mired = static_cast<int>(kelvin/11.12); //FIXME
device->setStateValue(lightPanelsColorTemperatureStateTypeId, mired); device->setStateValue(lightPanelsColorTemperatureStateTypeId, mired);
} }
@ -414,6 +425,7 @@ void DevicePluginNanoleaf::onSelectedEffectReceived(const QString &effect)
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf)); Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device) if (!device)
return; return;
device->setStateValue(lightPanelsEffectNameStateTypeId, effect); qCDebug(dcNanoleaf()) << "Selected effect received" << effect;
device->setStateValue(lightPanelsEffectNameStateTypeId, QString(effect).remove('"').remove('*'));
} }

View File

@ -1,24 +1,30 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * *
* Copyright (C) 2020 Bernhard Trinnes <bernhard.trinnes@nymea.io> * * Copyright 2013 - 2020, nymea GmbH
* * * Contact: contact@nymea.io
* This file is part of nymea. * *
* * * This file is part of nymea.
* This library is free software; you can redistribute it and/or * * This project including source code and documentation is protected by copyright law, and
* modify it under the terms of the GNU Lesser General Public * * remains the property of nymea GmbH. All rights, including reproduction, publication,
* License as published by the Free Software Foundation; either * * editing and translation, are reserved. The use of this project is subject to the terms of a
* version 2.1 of the License, or (at your option) any later version. * * license agreement to be concluded with nymea GmbH in accordance with the terms
* * * of use of nymea GmbH, available under https://nymea.io/license
* This library is distributed in the hope that it will be useful, * *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * GNU Lesser General Public License Usage
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * This project may also contain libraries licensed under the open source software license GNU GPL v.3.
* Lesser General Public License for more details. * * 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.
* You should have received a copy of the GNU Lesser General Public * * this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* License along with this library; If not, see * * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* <http://www.gnu.org/licenses/>. * * See the GNU Lesser General Public License for more details.
* * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef DEVICEPLUGINNANOLEAF_H #ifndef DEVICEPLUGINNANOLEAF_H
#define DEVICEPLUGINNANOLEAF_H #define DEVICEPLUGINNANOLEAF_H
@ -68,7 +74,7 @@ private:
QHash<QUuid, BrowserActionInfo *> m_asyncBrowserItem; QHash<QUuid, BrowserActionInfo *> m_asyncBrowserItem;
QHash<DeviceId, int> m_hues; QHash<DeviceId, int> m_hues;
void getDeviceStates(Nanoleaf *nanoleaf); Nanoleaf *createNanoleafConnection(const QHostAddress &address, int port);
public slots: public slots:
void onAuthTokenReceived(const QString &token); void onAuthTokenReceived(const QString &token);
@ -76,13 +82,14 @@ public slots:
void onRequestExecuted(QUuid requestId, bool success); void onRequestExecuted(QUuid requestId, bool success);
void onConnectionChanged(bool connected); void onConnectionChanged(bool connected);
void onControllerInfoReceived(const Nanoleaf::ControllerInfo &controllerInfo);
void onPowerReceived(bool power); void onPowerReceived(bool power);
void onBrightnessReceived(int percentage); void onBrightnessReceived(int percentage);
void onColorModeReceived(const QString &colorMode); void onColorModeReceived(const QString &colorMode);
void onHueReceived(int hue); void onHueReceived(int hue);
void onSaturationReceived(int percentage); void onSaturationReceived(int percentage);
void onEffectListReceived(const QStringList &effects); void onEffectListReceived(const QStringList &effects);
void onColorTemperatureReceived(int mired); void onColorTemperatureReceived(int kelvin);
void onSelectedEffectReceived(const QString &effect); void onSelectedEffectReceived(const QString &effect);
}; };

View File

@ -12,7 +12,7 @@
"id": "d44ee383-9fa5-4751-babd-1129ac20896a", "id": "d44ee383-9fa5-4751-babd-1129ac20896a",
"name": "lightPanels", "name": "lightPanels",
"displayName": "Light panels", "displayName": "Light panels",
"interfaces": ["colorlight", "colortemperaturelight", "connectable"], "interfaces": ["colorlight", "colortemperaturelight", "alert", "connectable"],
"createMethods": ["discovery"], "createMethods": ["discovery"],
"setupMethod": "pushButton", "setupMethod": "pushButton",
"browsable": true, "browsable": true,
@ -52,6 +52,13 @@
"readOnly": true "readOnly": true
} }
], ],
"actionTypes": [
{
"id": "47a6a1a1-fb90-4f24-be8c-b4dba0aaaa84",
"name": "alert",
"displayName": "Alert"
}
],
"stateTypes": [ "stateTypes": [
{ {
"id": "a3102107-a825-4ec8-a9ec-b2c2a9fb5c89", "id": "a3102107-a825-4ec8-a9ec-b2c2a9fb5c89",
@ -100,7 +107,7 @@
"name": "brightness", "name": "brightness",
"displayName": "Brightness", "displayName": "Brightness",
"displayNameEvent": "Brightness changed", "displayNameEvent": "Brightness changed",
"displayNameAction": "Set brigtness", "displayNameAction": "Set brightness",
"type": "int", "type": "int",
"unit": "Percentage", "unit": "Percentage",
"defaultValue": 0, "defaultValue": 0,
@ -113,17 +120,14 @@
"name": "colorMode", "name": "colorMode",
"displayName": "Color mode", "displayName": "Color mode",
"displayNameEvent": "Color mode changed", "displayNameEvent": "Color mode changed",
"displayNameAction": "Set color",
"type": "QString", "type": "QString",
"defaultValue": "Color temperature", "defaultValue": "Color temperature"
"writable": true
}, },
{ {
"id": "57f9831e-1b98-41c1-a21c-6073ff327237", "id": "57f9831e-1b98-41c1-a21c-6073ff327237",
"name": "effectName", "name": "effectName",
"displayName": "Effect name", "displayName": "Effect name",
"displayNameEvent": "Effect name changed", "displayNameEvent": "Effect name changed",
"displayNameAction": "Set color",
"type": "QString", "type": "QString",
"defaultValue": "-" "defaultValue": "-"
} }

View File

@ -1,24 +1,30 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * *
* Copyright (C) 2020 Bernhard Trinnes <bernhard.trinnes@nymea.io> * * Copyright 2013 - 2020, nymea GmbH
* * * Contact: contact@nymea.io
* This file is part of nymea. * *
* * * This file is part of nymea.
* This library is free software; you can redistribute it and/or * * This project including source code and documentation is protected by copyright law, and
* modify it under the terms of the GNU Lesser General Public * * remains the property of nymea GmbH. All rights, including reproduction, publication,
* License as published by the Free Software Foundation; either * * editing and translation, are reserved. The use of this project is subject to the terms of a
* version 2.1 of the License, or (at your option) any later version. * * license agreement to be concluded with nymea GmbH in accordance with the terms
* * * of use of nymea GmbH, available under https://nymea.io/license
* This library is distributed in the hope that it will be useful, * *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * GNU Lesser General Public License Usage
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * This project may also contain libraries licensed under the open source software license GNU GPL v.3.
* Lesser General Public License for more details. * * 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.
* You should have received a copy of the GNU Lesser General Public * * this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* License along with this library; If not, see * * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* <http://www.gnu.org/licenses/>. * * See the GNU Lesser General Public License for more details.
* * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "nanoleaf.h" #include "nanoleaf.h"
#include "extern-plugininfo.h" #include "extern-plugininfo.h"
@ -103,7 +109,6 @@ void Nanoleaf::addUser()
qDebug(dcNanoleaf()) << "Recieved invalide JSON object"; qDebug(dcNanoleaf()) << "Recieved invalide JSON object";
return; return;
} }
m_authToken = data.toVariant().toMap().value("auth_token").toString(); m_authToken = data.toVariant().toMap().value("auth_token").toString();
emit authTokenRecieved(m_authToken); emit authTokenRecieved(m_authToken);
@ -151,13 +156,64 @@ void Nanoleaf::getControllerInfo()
reply->deleteLater(); reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (status != 204 || reply->error() != QNetworkReply::NoError) { if (status < 200 || status > 204 || reply->error() != QNetworkReply::NoError) {
qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString(); qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString();
emit authenticationStatusChanged(false); emit authenticationStatusChanged(false);
return; return;
} }
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qDebug(dcNanoleaf()) << "Recieved invalide JSON object";
return;
}
emit connectionChanged(true); emit connectionChanged(true);
emit authenticationStatusChanged(true); emit authenticationStatusChanged(true);
QVariantMap map = data.toVariant().toMap();
ControllerInfo info;
info.name = map.value("name").toString();
info.serialNumber = map.value("serialNo").toString();
info.model = map.value("model").toString();
info.manufacturer = map.value("manufacturer").toString();
info.firmwareVersion = map.value("firmwareVersion").toString();
emit controllerInfoReceived(info);
if (map.contains("state")) {
QVariantMap state = map.value("state").toMap();
if (state.contains("on")) {
emit powerReceived(state["on"].toMap().value("value").toBool());
}
if (state.contains("brightness")) {
emit brightnessReceived(state["brightness"].toMap().value("value").toInt());
}
if (state.contains("hue")) {
emit hueReceived(state["hue"].toMap().value("value").toInt());
}
if (state.contains("sat")) {
emit saturationReceived(state["sat"].toMap().value("value").toInt());
}
if (state.contains("ct")) {
emit colorTemperatureReceived(state["ct"].toMap().value("value").toInt());
}
if (state.contains("colorMode")) {
emit colorModeReceived(state["colorMode"].toString());
}
}
if (map.contains("effects")) {
QVariantMap effects = map.value("effects").toMap();
emit selectedEffectReceived(effects.value("select").toString());
}
if (map.contains("panelLayout")) {
//QVariantMap panelLayout = map.value("panelLayout").toMap();
//emit panelLayoutReceived();
}
if (map.contains("rhythm")) {
//QVariantMap rhythm = map.value("rhythm").toMap();
//emit rhythmModulReceived(rhythm.value("select").toString());
}
}); });
} }
@ -314,9 +370,9 @@ void Nanoleaf::getColorTemperature()
qDebug(dcNanoleaf()) << "Recieved invalide JSON object"; qDebug(dcNanoleaf()) << "Recieved invalide JSON object";
return; return;
} }
int mired = data.toVariant().toMap().value("value").toInt(); int kelvin = data.toVariant().toMap().value("value").toInt();
emit connectionChanged(true); emit connectionChanged(true);
emit colorTemperatureReceived(mired); emit colorTemperatureReceived(kelvin);
}); });
} }
@ -352,6 +408,76 @@ void Nanoleaf::getColorMode()
}); });
} }
void Nanoleaf::registerForEvents()
{
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath("/api/v1/"+m_authToken+"/events");
QUrlQuery query;
query.addQueryItem("id", "1,2,3,4");
url.setQuery(query);
QNetworkRequest request;
request.setUrl(url);
QNetworkReply *reply = m_networkManager->get(request);
connect(reply, &QNetworkReply::readyRead, this, [reply, this] {
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qDebug(dcNanoleaf()) << "Recieved invalide JSON object";
return;
}
qCDebug(dcNanoleaf()) << "On event stream" << data.toJson();
});
connect(reply, &QNetworkReply::finished, this, [reply, this] {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (status != 200 || reply->error() != QNetworkReply::NoError) {
qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString();
emit connectionChanged(false);
return;
}
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qDebug(dcNanoleaf()) << "Recieved invalide JSON object";
return;
}
qCDebug(dcNanoleaf()) << "Event received" << data.toJson();
QVariantList events = data.toVariant().toList();
foreach (QVariant variant, events) {
QVariantMap event = variant.toMap();
switch (event["attr"].toInt()) {
case 1: //ON
emit powerReceived(event["value"].toBool());
break;
case 2: //Brightness
emit brightnessReceived(event["value"].toInt());
break;
case 3: //Hue
emit hueReceived(event["value"].toInt());
break;
case 4: //Saturation
emit saturationReceived(event["value"].toInt());
break;
case 5: //Color Temperature
emit colorTemperatureReceived(event["value"].toInt());
break;
case 6: //colorMode
emit colorModeReceived(event["value"].toString());
break;
default:
qCWarning(dcNanoleaf()) << "Unrecognised Event received";
}
}
});
}
QUuid Nanoleaf::setPower(bool power) QUuid Nanoleaf::setPower(bool power)
{ {
QUuid requestId = QUuid::createUuid(); QUuid requestId = QUuid::createUuid();
@ -387,10 +513,74 @@ QUuid Nanoleaf::setPower(bool power)
return requestId; return requestId;
} }
QUuid Nanoleaf::setHue(QColor color) QUuid Nanoleaf::setColor(QColor color)
{ {
Q_UNUSED(color);
QUuid requestId = QUuid::createUuid(); QUuid requestId = QUuid::createUuid();
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath(QString("/api/v1/%1/state").arg(m_authToken));
QVariantMap map;
QVariantMap hue;
hue["value"] = color.hue();
map.insert("hue", hue);
QVariantMap sat;
sat["value"] = color.saturation();
map.insert("sat", sat);
QJsonDocument body = QJsonDocument::fromVariant(map);
QNetworkRequest request;
request.setUrl(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
QNetworkReply *reply = m_networkManager->put(request, body.toJson());
qDebug(dcNanoleaf()) << "Sending request" << request.url();
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (status != 204 || reply->error() != QNetworkReply::NoError) {
emit requestExecuted(requestId, false);
qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString();
return;
}
emit requestExecuted(requestId, true);
});
return requestId;
}
QUuid Nanoleaf::setHue(int hue)
{
QUuid requestId = QUuid::createUuid();
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath(QString("/api/v1/%1/state").arg(m_authToken));
QVariantMap map;
QVariantMap hueMap;
hueMap["value"] = hue;
map.insert("hue", hueMap);
QJsonDocument body = QJsonDocument::fromVariant(map);
QNetworkRequest request;
request.setUrl(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
QNetworkReply *reply = m_networkManager->put(request, body.toJson());
qDebug(dcNanoleaf()) << "Sending request" << request.url();
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (status != 204 || reply->error() != QNetworkReply::NoError) {
emit requestExecuted(requestId, false);
qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString();
return;
}
emit requestExecuted(requestId, true);
});
return requestId; return requestId;
} }
@ -430,7 +620,6 @@ QUuid Nanoleaf::setBrightness(int percentage)
QUuid Nanoleaf::setSaturation(int percentage) QUuid Nanoleaf::setSaturation(int percentage)
{ {
Q_UNUSED(percentage);
QUuid requestId = QUuid::createUuid(); QUuid requestId = QUuid::createUuid();
QUrl url; QUrl url;
url.setHost(m_address.toString()); url.setHost(m_address.toString());
@ -463,10 +652,45 @@ QUuid Nanoleaf::setSaturation(int percentage)
return requestId; return requestId;
} }
QUuid Nanoleaf::setColorTemperature(int mired) QUuid Nanoleaf::setMired(int mired)
{
//NOTE: this is just a rough estimation
int kelvin = static_cast<int>(mired * 11.12);
QUuid requestId = setKelvin(kelvin);
return requestId;
}
QUuid Nanoleaf::setKelvin(int kelvin)
{ {
Q_UNUSED(mired);
QUuid requestId = QUuid::createUuid(); QUuid requestId = QUuid::createUuid();
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath(QString("/api/v1/%1/state").arg(m_authToken));
QVariantMap map;
QVariantMap value;
value["value"] = kelvin;
map.insert("ct", value);
QJsonDocument body = QJsonDocument::fromVariant(map);
QNetworkRequest request;
request.setUrl(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
QNetworkReply *reply = m_networkManager->put(request, body.toJson());
qDebug(dcNanoleaf()) << "Sending request" << request.url();
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (status != 204 || reply->error() != QNetworkReply::NoError) {
emit requestExecuted(requestId, false);
qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString();
return;
}
emit requestExecuted(requestId, true);
});
return requestId; return requestId;
} }
@ -564,5 +788,40 @@ QUuid Nanoleaf::setEffect(const QString &effect)
return requestId; return requestId;
} }
QUuid Nanoleaf::identify()
{
QUuid requestId = QUuid::createUuid();
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath(QString("/api/v1/%1/identify").arg(m_authToken));
QNetworkRequest request;
request.setUrl(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
QNetworkReply *reply = m_networkManager->put(request, "");
qDebug(dcNanoleaf()) << "Sending request" << request.url();
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// Check HTTP status code
if (status < 200 || status > 204 || reply->error() != QNetworkReply::NoError) {
if (reply->error() == QNetworkReply::HostNotFoundError) {
emit connectionChanged(false);
}
if (status >= 400 && status <= 410) {
emit authenticationStatusChanged(false);
}
emit requestExecuted(requestId, false);
qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString();
return;
}
emit requestExecuted(requestId, true);
});
return requestId;
}

View File

@ -1,24 +1,30 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * *
* Copyright (C) 2020 Bernhard Trinnes <bernhard.trinnes@nymea.io> * * Copyright 2013 - 2020, nymea GmbH
* * * Contact: contact@nymea.io
* This file is part of nymea. * *
* * * This file is part of nymea.
* This library is free software; you can redistribute it and/or * * This project including source code and documentation is protected by copyright law, and
* modify it under the terms of the GNU Lesser General Public * * remains the property of nymea GmbH. All rights, including reproduction, publication,
* License as published by the Free Software Foundation; either * * editing and translation, are reserved. The use of this project is subject to the terms of a
* version 2.1 of the License, or (at your option) any later version. * * license agreement to be concluded with nymea GmbH in accordance with the terms
* * * of use of nymea GmbH, available under https://nymea.io/license
* This library is distributed in the hope that it will be useful, * *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * GNU Lesser General Public License Usage
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * This project may also contain libraries licensed under the open source software license GNU GPL v.3.
* Lesser General Public License for more details. * * 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.
* You should have received a copy of the GNU Lesser General Public * * this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* License along with this library; If not, see * * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* <http://www.gnu.org/licenses/>. * * See the GNU Lesser General Public License for more details.
* * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef NANOLEAF_H #ifndef NANOLEAF_H
#define NANOLEAF_H #define NANOLEAF_H
@ -36,6 +42,22 @@ class Nanoleaf : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
struct ControllerInfo {
QString name;
QString serialNumber;
QString manufacturer;
QString firmwareVersion;
QString model;
};
enum GestureID {
SingleTap = 0,
DoubleTap = 1,
SwipeUp = 2,
SwipeDown = 3,
SwipeLeft = 4,
SwipeRight = 5
};
explicit Nanoleaf(NetworkAccessManager *networkManager, const QHostAddress &address, int port = 16021, QObject *parent = nullptr); explicit Nanoleaf(NetworkAccessManager *networkManager, const QHostAddress &address, int port = 16021, QObject *parent = nullptr);
void setIpAddress(const QHostAddress &address); void setIpAddress(const QHostAddress &address);
@ -62,27 +84,21 @@ public:
void getColorTemperature(); void getColorTemperature();
void getColorMode(); void getColorMode();
void registerForEvents();
QUuid setPower(bool power); QUuid setPower(bool power);
QUuid setHue(QColor color); QUuid setColor(QColor color);
QUuid setHue(int hue);
QUuid setBrightness(int percentage); QUuid setBrightness(int percentage);
QUuid setSaturation(int percentage); QUuid setSaturation(int percentage);
QUuid setColorTemperature(int mired); QUuid setMired(int mired);
QUuid setKelvin(int kelvin);
//EFFECTS //EFFECTS
void getEffects(); void getEffects();
void getSelectedEffect(); void getSelectedEffect();
QUuid setEffect(const QString &effect); QUuid setEffect(const QString &effect);
//PANEL LAYOUT QUuid identify();
//IDENTIFY
//EXTERNAL CONTROL
//RHYTHM
private: private:
NetworkAccessManager *m_networkManager = nullptr; NetworkAccessManager *m_networkManager = nullptr;
@ -95,6 +111,7 @@ signals:
void authenticationStatusChanged(bool authenticated); void authenticationStatusChanged(bool authenticated);
void requestExecuted(QUuid requestId, bool success); void requestExecuted(QUuid requestId, bool success);
void controllerInfoReceived(const ControllerInfo &controllerInfo);
void authTokenRecieved(const QString &token); void authTokenRecieved(const QString &token);
void powerReceived(bool power); void powerReceived(bool power);
void brightnessReceived(int percentage); void brightnessReceived(int percentage);
@ -102,8 +119,11 @@ signals:
void hueReceived(int hue); void hueReceived(int hue);
void saturationReceived(int percentage); void saturationReceived(int percentage);
void effectListReceived(const QStringList &effects); void effectListReceived(const QStringList &effects);
void colorTemperatureReceived(int mired); void colorTemperatureReceived(int kelvin);
void selectedEffectReceived(const QString &effect); void selectedEffectReceived(const QString &effect);
//Only supported by Canvas
void touchEventReceived(GestureID gesture);
}; };
#endif // NANOLEAF_H #endif // NANOLEAF_H