added effect browsing

This commit is contained in:
Boernsman 2019-12-24 00:57:45 +01:00
parent 1a8ed79269
commit 9e53feb985
5 changed files with 669 additions and 22 deletions

View File

@ -40,14 +40,11 @@ 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;
foreach (const ZeroConfServiceEntry &entry, m_zeroconfBrowser->serviceEntries()) { foreach (const ZeroConfServiceEntry &entry, m_zeroconfBrowser->serviceEntries()) {
if (info->deviceClassId() == lightPanelsDeviceClassId) {
}
//TODO skip duplicated devices
DeviceDescriptor descriptor(lightPanelsDeviceClassId, entry.name(), entry.hostAddress().toString()); DeviceDescriptor descriptor(lightPanelsDeviceClassId, entry.name(), entry.hostAddress().toString());
ParamList params; ParamList params;
@ -89,46 +86,108 @@ void DevicePluginNanoleaf::discoverDevices(DeviceDiscoveryInfo *info)
info->finish(Device::DeviceErrorNoError); info->finish(Device::DeviceErrorNoError);
} }
void DevicePluginNanoleaf::startPairing(DevicePairingInfo *info) void DevicePluginNanoleaf::startPairing(DevicePairingInfo *info)
{ {
info->finish(Device::DeviceErrorNoError, tr("Please press the button")); 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 = new Nanoleaf(hardwareManager()->networkManager(), QHostAddress(info->params().paramValue(lightPanelsDeviceAddressParamTypeId).toString()), info->params().paramValue(lightPanelsDevicePortParamTypeId).toInt(), this);
nanoleaf->addUser(); connect(nanoleaf, &Nanoleaf::authTokenRecieved, this, &DevicePluginNanoleaf::onAuthTokenReceived);
info->finish(Device::DeviceErrorNoError); 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
m_unfinishedNanoleafConnections.insert(info->deviceId(), nanoleaf);
m_unfinishedPairing.insert(nanoleaf, info);
connect(info, &DevicePairingInfo::aborted, this, [info, this] {
Nanoleaf *nanoleaf = m_unfinishedNanoleafConnections.take(info->deviceId());
m_unfinishedPairing.remove(nanoleaf);
nanoleaf->deleteLater();
});
} }
void DevicePluginNanoleaf::setupDevice(DeviceSetupInfo *info) void DevicePluginNanoleaf::setupDevice(DeviceSetupInfo *info)
{ {
Device *device = info->device(); Device *device = info->device();
if(device->deviceClassId() == lightPanelsDeviceClassId) { if(device->deviceClassId() == lightPanelsDeviceClassId) {
return info->finish(Device::DeviceErrorNoError); pluginStorage()->beginGroup(device->id().toString());
QString token = pluginStorage()->value("authToken").toString();
pluginStorage()->endGroup();
Nanoleaf *nanoleaf;
if (m_unfinishedNanoleafConnections.contains(device->id())) {
nanoleaf = m_unfinishedNanoleafConnections.take(device->id());
m_nanoleafConnections.insert(device->id(), nanoleaf);
return info->finish(Device::DeviceErrorNoError);
} else {
QHostAddress address(device->paramValue(lightPanelsDeviceAddressParamTypeId).toString());
int port = device->paramValue(lightPanelsDevicePortParamTypeId).toInt();
nanoleaf = new Nanoleaf(hardwareManager()->networkManager(), address, port, this);
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->getControllerInfo(); //we don't care about the controller info, this is just to check if the device is available
m_nanoleafConnections.insert(device->id(), nanoleaf);
m_asyncDeviceSetup.insert(nanoleaf, info);
connect(info, &DeviceSetupInfo::aborted, this, [nanoleaf, this](){m_asyncDeviceSetup.remove(nanoleaf);});
return;
}
} }
} }
void DevicePluginNanoleaf::postSetupDevice(Device *device) void DevicePluginNanoleaf::postSetupDevice(Device *device)
{ {
if (device->deviceClassId() == lightPanelsDeviceClassId) { if (device->deviceClassId() == lightPanelsDeviceClassId) {
//TODO get all the information and set the device states //Nanoleaf *nanoleaf = m_nanoleafConnections.value(device->id());
//getDeviceStates(nanoleaf);
} }
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) {
getDeviceStates(nanoleaf);
}
}); });
} }
} }
void DevicePluginNanoleaf::deviceRemoved(Device *device) void DevicePluginNanoleaf::deviceRemoved(Device *device)
{ {
if(device->deviceClassId() == lightPanelsDeviceClassId) { if(device->deviceClassId() == lightPanelsDeviceClassId) {
Nanoleaf *nanoleaf = m_nanoleafConnections.take(device->id());
nanoleaf->deleteLater();
} }
if (myDevices().isEmpty()) { if (myDevices().isEmpty()) {
@ -137,6 +196,7 @@ void DevicePluginNanoleaf::deviceRemoved(Device *device)
} }
} }
void DevicePluginNanoleaf::executeAction(DeviceActionInfo *info) void DevicePluginNanoleaf::executeAction(DeviceActionInfo *info)
{ {
Device *device = info->device(); Device *device = info->device();
@ -171,13 +231,189 @@ void DevicePluginNanoleaf::executeAction(DeviceActionInfo *info)
} }
} }
void DevicePluginNanoleaf::browseDevice(BrowseResult *result)
{
Device *device = result->device();
Nanoleaf *nanoleaf = m_nanoleafConnections.value(device->id());
nanoleaf->getEffects();
m_asyncBrowseResults.insert(nanoleaf, result);
connect(result, &BrowseResult::aborted, this, [nanoleaf, this]{m_asyncBrowseResults.remove(nanoleaf);});
}
void DevicePluginNanoleaf::browserItem(BrowserItemResult *result)
{
Q_UNUSED(result)
qCDebug(dcNanoleaf()) << "BrowserItem called";
//Device *device = result->device();
//Nanoleaf *nanoleaf = m_nanoleafConnections.value(device->id());
//nanoleaf->setEffect(info.);
//result->
//m_asyncBrowseItems.insert(nanoleaf, result);*/
}
void DevicePluginNanoleaf::executeBrowserItem(BrowserActionInfo *info)
{
Device *device = info->device();
Nanoleaf *nanoleaf = m_nanoleafConnections.value(device->id());
QUuid requestId = nanoleaf->setEffect(info->browserAction().itemId());
m_asyncBrowserItem.insert(requestId, info);
connect(info, &BrowserActionInfo::aborted, this, [requestId, this]{m_asyncBrowserItem.remove(requestId);});
}
void DevicePluginNanoleaf::getDeviceStates(Nanoleaf *nanoleaf) void DevicePluginNanoleaf::getDeviceStates(Nanoleaf *nanoleaf)
{ {
nanoleaf->getPower(); nanoleaf->getPower();
nanoleaf->getHue(); nanoleaf->getHue();
nanoleaf->getColorMode(); nanoleaf->getColorMode();
nanoleaf->getBrightness(); nanoleaf->getBrightness();
nanoleaf->getSaturation();
nanoleaf->getColorTemperature(); nanoleaf->getColorTemperature();
nanoleaf->getSelectedEffect();
}
void DevicePluginNanoleaf::onAuthTokenReceived(const QString &token)
{
Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender());
if (m_unfinishedPairing.contains(nanoleaf)) {
DevicePairingInfo *info = m_unfinishedPairing.take(nanoleaf);
pluginStorage()->beginGroup(info->deviceId().toString());
pluginStorage()->setValue("authToken", token);
pluginStorage()->endGroup();
info->finish(Device::DeviceErrorNoError);
}
}
void DevicePluginNanoleaf::onAuthenticationStatusChanged(bool authenticated)
{
Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender());
if (m_asyncDeviceSetup.contains(nanoleaf)) {
DeviceSetupInfo *info = m_asyncDeviceSetup.take(nanoleaf);
if (authenticated) {
info->finish(Device::DeviceErrorNoError);
} else {
info->finish(Device::DeviceErrorSetupFailed);
}
}
}
void DevicePluginNanoleaf::onRequestExecuted(QUuid requestId, bool success)
{
if (m_asyncActions.contains(requestId)) {
DeviceActionInfo *info = m_asyncActions.take(requestId);
if (success) {
info->finish(Device::DeviceErrorNoError);
} else {
info->finish(Device::DeviceErrorHardwareNotAvailable);
}
}
if (m_asyncBrowserItem.contains(requestId)) {
BrowserActionInfo *info = m_asyncBrowserItem.take(requestId);
if (success) {
info->finish(Device::DeviceErrorNoError);
} else {
info->finish(Device::DeviceErrorHardwareNotAvailable);
}
}
}
void DevicePluginNanoleaf::onConnectionChanged(bool connected)
{
Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender());
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device)
return;
device->setStateValue(lightPanelsConnectedStateTypeId, connected);
}
void DevicePluginNanoleaf::onPowerReceived(bool power)
{
Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender());
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device)
return;
device->setStateValue(lightPanelsPowerStateTypeId, power);
}
void DevicePluginNanoleaf::onBrightnessReceived(int percentage)
{
Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender());
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device)
return;
device->setStateValue(lightPanelsBrightnessStateTypeId, percentage);
}
void DevicePluginNanoleaf::onColorModeReceived(const QString &colorMode)
{
Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender());
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device)
return;
device->setStateValue(lightPanelsColorModeStateTypeId, colorMode);
}
void DevicePluginNanoleaf::onHueReceived(int hue)
{
Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender());
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device)
return;
m_hues.insert(device->id(), hue);
nanoleaf->getSaturation();
}
void DevicePluginNanoleaf::onSaturationReceived(int saturation)
{
Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender());
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device)
return;
qCDebug(dcNanoleaf()) << "Saturation received" << saturation;
QColor color;
color.setHsv(m_hues.value(device->id()), saturation, 100);
//TODO get hue
device->setStateValue(lightPanelsColorStateTypeId, color);
}
void DevicePluginNanoleaf::onEffectListReceived(const QStringList &effects)
{
Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender());
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device)
return;
qCDebug(dcNanoleaf()) << "Effect list received" << effects;
if (m_asyncBrowseResults.contains(nanoleaf)) {
BrowseResult *result = m_asyncBrowseResults.take(nanoleaf);
foreach (QString effect, effects) {
BrowserItem item;
item.setId(effect);
item.setBrowsable(false);
item.setExecutable(true);
item.setDisplayName(effect);
item.setDisabled(false);
result->addItem(item);
}
result->finish(Device::DeviceErrorNoError);
}
}
void DevicePluginNanoleaf::onColorTemperatureReceived(int mired)
{
Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender());
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device)
return;
device->setStateValue(lightPanelsColorTemperatureStateTypeId, mired);
}
void DevicePluginNanoleaf::onSelectedEffectReceived(const QString &effect)
{
Nanoleaf *nanoleaf = static_cast<Nanoleaf *>(sender());
Device *device = myDevices().findById(m_nanoleafConnections.key(nanoleaf));
if (!device)
return;
device->setStateValue(lightPanelsEffectNameStateTypeId, effect);
} }

View File

@ -51,14 +51,39 @@ public:
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void executeAction(DeviceActionInfo *info) override; void executeAction(DeviceActionInfo *info) override;
void browseDevice(BrowseResult *result) override;
void browserItem(BrowserItemResult *result) override;
void executeBrowserItem(BrowserActionInfo *info) override;
private: private:
ZeroConfServiceBrowser *m_zeroconfBrowser = nullptr; ZeroConfServiceBrowser *m_zeroconfBrowser = nullptr;
PluginTimer *m_pluginTimer = nullptr; PluginTimer *m_pluginTimer = nullptr;
QHash<DeviceId, Nanoleaf*> m_nanoleafConnections; QHash<DeviceId, Nanoleaf*> m_nanoleafConnections;
QHash<DeviceId, Nanoleaf*> m_unfinishedNanoleafConnections;
QHash<QUuid, DeviceActionInfo *> m_asyncActions; QHash<QUuid, DeviceActionInfo *> m_asyncActions;
QHash<Nanoleaf *, DevicePairingInfo *> m_unfinishedPairing;
QHash<Nanoleaf *, DeviceSetupInfo *> m_asyncDeviceSetup;
QHash<Nanoleaf *, BrowseResult *> m_asyncBrowseResults;
QHash<QUuid, BrowserActionInfo *> m_asyncBrowserItem;
QHash<DeviceId, int> m_hues;
void getDeviceStates(Nanoleaf *nanoleaf); void getDeviceStates(Nanoleaf *nanoleaf);
public slots:
void onAuthTokenReceived(const QString &token);
void onAuthenticationStatusChanged(bool authenticated);
void onRequestExecuted(QUuid requestId, bool success);
void onConnectionChanged(bool connected);
void onPowerReceived(bool power);
void onBrightnessReceived(int percentage);
void onColorModeReceived(const QString &colorMode);
void onHueReceived(int hue);
void onSaturationReceived(int percentage);
void onEffectListReceived(const QStringList &effects);
void onColorTemperatureReceived(int mired);
void onSelectedEffectReceived(const QString &effect);
}; };
#endif // DEVICEPLUGINNANOLEAF_H #endif // DEVICEPLUGINNANOLEAF_H

View File

@ -14,6 +14,8 @@
"displayName": "Light panels", "displayName": "Light panels",
"interfaces": ["colorlight", "colortemperaturelight", "connectable"], "interfaces": ["colorlight", "colortemperaturelight", "connectable"],
"createMethods": ["discovery"], "createMethods": ["discovery"],
"setupMethod": "pushButton",
"browsable": true,
"paramTypes": [ "paramTypes": [
{ {
"id": "ff57079f-d5ab-4511-8a5c-0726e7b82af6", "id": "ff57079f-d5ab-4511-8a5c-0726e7b82af6",
@ -105,7 +107,25 @@
"minValue": 0, "minValue": 0,
"maxValue": 100, "maxValue": 100,
"writable": true "writable": true
},
{
"id": "bdd2ea1e-9ef9-4967-9678-2c601b826199",
"name": "colorMode",
"displayName": "Color mode",
"displayNameEvent": "Color mode changed",
"displayNameAction": "Set color",
"type": "QString",
"defaultValue": "Color temperature",
"writable": true
},
{
"id": "57f9831e-1b98-41c1-a21c-6073ff327237",
"name": "effectName",
"displayName": "Effect name",
"displayNameEvent": "Effect name changed",
"displayNameAction": "Set color",
"type": "QString",
"defaultValue": "-"
} }
] ]
} }

View File

@ -57,15 +57,27 @@ int Nanoleaf::port()
return m_port; return m_port;
} }
void Nanoleaf::setAuthToken(const QString &token)
{
m_authToken = token;
}
QString Nanoleaf::authToken()
{
return m_authToken;
}
void Nanoleaf::addUser() void Nanoleaf::addUser()
{ {
QUrl url; QUrl url;
url.setHost(m_address.toString()); url.setHost(m_address.toString());
url.setPort(m_port); url.setPort(m_port);
url.setScheme("http");
url.setPath("/api/v1/new"); url.setPath("/api/v1/new");
QNetworkRequest request; QNetworkRequest request;
request.setUrl(url); request.setUrl(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
QNetworkReply *reply = m_networkManager->post(request, ""); QNetworkReply *reply = m_networkManager->post(request, "");
qDebug(dcNanoleaf()) << "Sending request" << request.url(); qDebug(dcNanoleaf()) << "Sending request" << request.url();
connect(reply, &QNetworkReply::finished, this, [reply, this] { connect(reply, &QNetworkReply::finished, this, [reply, this] {
@ -77,14 +89,13 @@ void Nanoleaf::addUser()
if (reply->error() == QNetworkReply::HostNotFoundError) { if (reply->error() == QNetworkReply::HostNotFoundError) {
emit connectionChanged(false); emit connectionChanged(false);
} }
if (status == 400 || status == 401) { if (status >= 400 && status <= 410) {
emit authenticationStatusChanged(false); emit authenticationStatusChanged(false);
} }
qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString(); qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString();
return; return;
} }
emit connectionChanged(true); emit connectionChanged(true);
emit authenticationStatusChanged(true);
QJsonParseError error; QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error); QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
@ -94,6 +105,9 @@ void Nanoleaf::addUser()
} }
m_authToken = data.toVariant().toMap().value("auth_token").toString(); m_authToken = data.toVariant().toMap().value("auth_token").toString();
emit authTokenRecieved(m_authToken);
emit authenticationStatusChanged(true);
}); });
} }
@ -102,6 +116,7 @@ void Nanoleaf::deleteUser()
QUrl url; QUrl url;
url.setHost(m_address.toString()); url.setHost(m_address.toString());
url.setPort(m_port); url.setPort(m_port);
url.setScheme("http");
url.setPath("/api/v1/"+m_authToken); url.setPath("/api/v1/"+m_authToken);
QNetworkRequest request; QNetworkRequest request;
@ -116,37 +131,225 @@ void Nanoleaf::deleteUser()
qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString(); qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString();
return; return;
} }
emit authenticationStatusChanged(false);
});
}
void Nanoleaf::getControllerInfo()
{
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath("/api/v1/"+m_authToken);
QNetworkRequest request;
request.setUrl(url);
QNetworkReply *reply = m_networkManager->get(request);
qDebug(dcNanoleaf()) << "Sending request" << request.url();
connect(reply, &QNetworkReply::finished, this, [reply, this] {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (status != 204 || reply->error() != QNetworkReply::NoError) {
qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString();
emit authenticationStatusChanged(false);
return;
}
emit connectionChanged(true);
emit authenticationStatusChanged(true);
}); });
} }
void Nanoleaf::getPower() void Nanoleaf::getPower()
{ {
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath("/api/v1/"+m_authToken+"/state/on");
QNetworkRequest request;
request.setUrl(url);
QNetworkReply *reply = m_networkManager->get(request);
qDebug(dcNanoleaf()) << "Sending request" << request.url();
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;
}
bool power = data.toVariant().toMap().value("value").toBool();
emit connectionChanged(true);
emit powerReceived(power);
});
} }
void Nanoleaf::getHue() void Nanoleaf::getHue()
{ {
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath("/api/v1/"+m_authToken+"/state/hue");
QNetworkRequest request;
request.setUrl(url);
QNetworkReply *reply = m_networkManager->get(request);
qDebug(dcNanoleaf()) << "Sending request" << request.url();
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();
return;
}
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qDebug(dcNanoleaf()) << "Recieved invalide JSON object";
return;
}
int hue = data.toVariant().toMap().value("value").toBool();
emit connectionChanged(true);
emit hueReceived(hue);
});
} }
void Nanoleaf::getBrightness() void Nanoleaf::getBrightness()
{ {
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath("/api/v1/"+m_authToken+"/state/brightness");
QNetworkRequest request;
request.setUrl(url);
QNetworkReply *reply = m_networkManager->get(request);
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();
return;
}
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qDebug(dcNanoleaf()) << "Recieved invalide JSON object";
return;
}
int brightness = data.toVariant().toMap().value("value").toInt();
emit connectionChanged(true);
emit brightnessReceived(brightness);
});
} }
void Nanoleaf::getSaturation() void Nanoleaf::getSaturation()
{ {
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath("/api/v1/"+m_authToken+"/state/sat");
QNetworkRequest request;
request.setUrl(url);
QNetworkReply *reply = m_networkManager->get(request);
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();
return;
}
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qDebug(dcNanoleaf()) << "Recieved invalide JSON object";
return;
}
int brightness = data.toVariant().toMap().value("value").toInt();
emit connectionChanged(true);
emit saturationReceived(brightness);
});
} }
void Nanoleaf::getColorTemperature() void Nanoleaf::getColorTemperature()
{ {
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath("/api/v1/"+m_authToken+"/state/ct");
QNetworkRequest request;
request.setUrl(url);
QNetworkReply *reply = m_networkManager->get(request);
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;
}
int mired = data.toVariant().toMap().value("value").toInt();
emit connectionChanged(true);
emit colorTemperatureReceived(mired);
});
} }
void Nanoleaf::getColorMode() void Nanoleaf::getColorMode()
{ {
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath("/api/v1/"+m_authToken+"/state/colorMode");
QNetworkRequest request;
request.setUrl(url);
QNetworkReply *reply = m_networkManager->get(request);
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;
}
QString colorMode = data.toVariant().toMap().value("value").toString();
emit connectionChanged(true);
emit colorModeReceived(colorMode);
});
} }
QUuid Nanoleaf::setPower(bool power) QUuid Nanoleaf::setPower(bool power)
@ -155,7 +358,8 @@ QUuid Nanoleaf::setPower(bool power)
QUrl url; QUrl url;
url.setHost(m_address.toString()); url.setHost(m_address.toString());
url.setPort(m_port); url.setPort(m_port);
url.setPath(QString("/api/v1/%1/state/on").arg(m_authToken)); url.setScheme("http");
url.setPath(QString("/api/v1/%1/state").arg(m_authToken));
QVariantMap map; QVariantMap map;
QVariantMap value; QVariantMap value;
@ -165,6 +369,7 @@ QUuid Nanoleaf::setPower(bool power)
QNetworkRequest request; QNetworkRequest request;
request.setUrl(url); request.setUrl(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
QNetworkReply *reply = m_networkManager->put(request, body.toJson()); QNetworkReply *reply = m_networkManager->put(request, body.toJson());
qDebug(dcNanoleaf()) << "Sending request" << request.url(); qDebug(dcNanoleaf()) << "Sending request" << request.url();
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] { connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
@ -172,11 +377,12 @@ QUuid Nanoleaf::setPower(bool power)
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (status != 204 || reply->error() != QNetworkReply::NoError) { if (status != 204 || reply->error() != QNetworkReply::NoError) {
emit requestedExecuted(requestId, false); emit requestExecuted(requestId, false);
qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString(); qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString();
return; return;
} }
emit requestedExecuted(requestId, true); emit connectionChanged(true);
emit requestExecuted(requestId, true);
}); });
return requestId; return requestId;
} }
@ -190,8 +396,35 @@ QUuid Nanoleaf::setHue(QColor color)
QUuid Nanoleaf::setBrightness(int percentage) QUuid Nanoleaf::setBrightness(int percentage)
{ {
Q_UNUSED(percentage);
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"] = percentage;
map.insert("brightness", 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;
} }
@ -199,6 +432,34 @@ QUuid Nanoleaf::setSaturation(int percentage)
{ {
Q_UNUSED(percentage); Q_UNUSED(percentage);
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/sat").arg(m_authToken));
QVariantMap map;
QVariantMap value;
value["value"] = percentage;
map.insert("sat", 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;
} }
@ -209,5 +470,99 @@ QUuid Nanoleaf::setColorTemperature(int mired)
return requestId; return requestId;
} }
void Nanoleaf::getEffects()
{
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath("/api/v1/"+m_authToken+"/effects/effectsList");
QNetworkRequest request;
request.setUrl(url);
QNetworkReply *reply = m_networkManager->get(request);
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;
}
QStringList effects;
foreach (QVariant effect, data.toVariant().toList()) {
effects.append(effect.toString());
}
emit connectionChanged(true);
emit effectListReceived(effects);
});
}
void Nanoleaf::getSelectedEffect()
{
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath("/api/v1/"+m_authToken+"/effects/select");
QNetworkRequest request;
request.setUrl(url);
QNetworkReply *reply = m_networkManager->get(request);
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;
}
QString effect = reply->readAll();
emit connectionChanged(true);
emit selectedEffectReceived(effect);
});
}
QUuid Nanoleaf::setEffect(const QString &effect)
{
QUuid requestId = QUuid::createUuid();
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath(QString("/api/v1/%1/effects").arg(m_authToken));
QVariantMap map;
map.insert("select", effect);
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;
}

View File

@ -44,11 +44,15 @@ public:
void setPort(int port); void setPort(int port);
int port(); int port();
void setAuthToken(const QString &token);
QString authToken();
//AUTHORIZATION //AUTHORIZATION
void addUser(); void addUser();
void deleteUser(); void deleteUser();
//GET ALL PANEL INFORMATION //GET ALL PANEL INFORMATION
void getControllerInfo();
//STATES //STATES
void getPower(); void getPower();
@ -66,6 +70,9 @@ public:
//EFFECTS //EFFECTS
void getEffects();
void getSelectedEffect();
QUuid setEffect(const QString &effect);
//PANEL LAYOUT //PANEL LAYOUT
@ -86,13 +93,17 @@ private:
signals: signals:
void connectionChanged(bool connected); void connectionChanged(bool connected);
void authenticationStatusChanged(bool authenticated); void authenticationStatusChanged(bool authenticated);
void requestedExecuted(QUuid requestId, bool success); void requestExecuted(QUuid requestId, bool success);
void authTokenRecieved(const QString &token);
void powerReceived(bool power); void powerReceived(bool power);
void brightnessReceived(int percentage); void brightnessReceived(int percentage);
void colorModeReceived(); void colorModeReceived(const QString &colorMode);
void hueReceived(QColor color); void hueReceived(int hue);
void saturationReceived(int percentage); void saturationReceived(int percentage);
void effectListReceived(const QStringList &effects);
void colorTemperatureReceived(int mired);
void selectedEffectReceived(const QString &effect);
}; };
#endif // NANOLEAF_H #endif // NANOLEAF_H