added effect browsing

master
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");
}
void DevicePluginNanoleaf::discoverDevices(DeviceDiscoveryInfo *info)
{
QStringList serialNumbers;
foreach (const ZeroConfServiceEntry &entry, m_zeroconfBrowser->serviceEntries()) {
if (info->deviceClassId() == lightPanelsDeviceClassId) {
}
//TODO skip duplicated devices
DeviceDescriptor descriptor(lightPanelsDeviceClassId, entry.name(), entry.hostAddress().toString());
ParamList params;
@ -89,46 +86,108 @@ void DevicePluginNanoleaf::discoverDevices(DeviceDiscoveryInfo *info)
info->finish(Device::DeviceErrorNoError);
}
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)
{
Q_UNUSED(username)
Q_UNUSED(secret)
Nanoleaf *nanoleaf = new Nanoleaf(hardwareManager()->networkManager(), QHostAddress(info->params().paramValue(lightPanelsDeviceAddressParamTypeId).toString()), info->params().paramValue(lightPanelsDevicePortParamTypeId).toInt(), this);
nanoleaf->addUser();
info->finish(Device::DeviceErrorNoError);
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
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)
{
Device *device = info->device();
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)
{
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) {
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(5);
connect(m_pluginTimer, &PluginTimer::timeout, this, [this]() {
foreach (Nanoleaf *nanoleaf, m_nanoleafConnections) {
getDeviceStates(nanoleaf);
}
});
}
}
void DevicePluginNanoleaf::deviceRemoved(Device *device)
{
if(device->deviceClassId() == lightPanelsDeviceClassId) {
Nanoleaf *nanoleaf = m_nanoleafConnections.take(device->id());
nanoleaf->deleteLater();
}
if (myDevices().isEmpty()) {
@ -137,6 +196,7 @@ void DevicePluginNanoleaf::deviceRemoved(Device *device)
}
}
void DevicePluginNanoleaf::executeAction(DeviceActionInfo *info)
{
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)
{
nanoleaf->getPower();
nanoleaf->getHue();
nanoleaf->getColorMode();
nanoleaf->getBrightness();
nanoleaf->getSaturation();
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 executeAction(DeviceActionInfo *info) override;
void browseDevice(BrowseResult *result) override;
void browserItem(BrowserItemResult *result) override;
void executeBrowserItem(BrowserActionInfo *info) override;
private:
ZeroConfServiceBrowser *m_zeroconfBrowser = nullptr;
PluginTimer *m_pluginTimer = nullptr;
QHash<DeviceId, Nanoleaf*> m_nanoleafConnections;
QHash<DeviceId, Nanoleaf*> m_unfinishedNanoleafConnections;
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);
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

View File

@ -14,6 +14,8 @@
"displayName": "Light panels",
"interfaces": ["colorlight", "colortemperaturelight", "connectable"],
"createMethods": ["discovery"],
"setupMethod": "pushButton",
"browsable": true,
"paramTypes": [
{
"id": "ff57079f-d5ab-4511-8a5c-0726e7b82af6",
@ -105,7 +107,25 @@
"minValue": 0,
"maxValue": 100,
"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;
}
void Nanoleaf::setAuthToken(const QString &token)
{
m_authToken = token;
}
QString Nanoleaf::authToken()
{
return m_authToken;
}
void Nanoleaf::addUser()
{
QUrl url;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath("/api/v1/new");
QNetworkRequest request;
request.setUrl(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
QNetworkReply *reply = m_networkManager->post(request, "");
qDebug(dcNanoleaf()) << "Sending request" << request.url();
connect(reply, &QNetworkReply::finished, this, [reply, this] {
@ -77,14 +89,13 @@ void Nanoleaf::addUser()
if (reply->error() == QNetworkReply::HostNotFoundError) {
emit connectionChanged(false);
}
if (status == 400 || status == 401) {
if (status >= 400 && status <= 410) {
emit authenticationStatusChanged(false);
}
qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString();
return;
}
emit connectionChanged(true);
emit authenticationStatusChanged(true);
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
@ -94,6 +105,9 @@ void Nanoleaf::addUser()
}
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;
url.setHost(m_address.toString());
url.setPort(m_port);
url.setScheme("http");
url.setPath("/api/v1/"+m_authToken);
QNetworkRequest request;
@ -116,37 +131,225 @@ void Nanoleaf::deleteUser()
qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString();
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()
{
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()
{
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()
{
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()
{
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()
{
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()
{
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)
@ -155,7 +358,8 @@ QUuid Nanoleaf::setPower(bool power)
QUrl url;
url.setHost(m_address.toString());
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 value;
@ -165,6 +369,7 @@ QUuid Nanoleaf::setPower(bool power)
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] {
@ -172,11 +377,12 @@ QUuid Nanoleaf::setPower(bool power)
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (status != 204 || reply->error() != QNetworkReply::NoError) {
emit requestedExecuted(requestId, false);
emit requestExecuted(requestId, false);
qCWarning(dcNanoleaf()) << "Request error:" << status << reply->errorString();
return;
}
emit requestedExecuted(requestId, true);
emit connectionChanged(true);
emit requestExecuted(requestId, true);
});
return requestId;
}
@ -190,8 +396,35 @@ QUuid Nanoleaf::setHue(QColor color)
QUuid Nanoleaf::setBrightness(int percentage)
{
Q_UNUSED(percentage);
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;
}
@ -199,6 +432,34 @@ QUuid Nanoleaf::setSaturation(int percentage)
{
Q_UNUSED(percentage);
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;
}
@ -209,5 +470,99 @@ QUuid Nanoleaf::setColorTemperature(int mired)
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);
int port();
void setAuthToken(const QString &token);
QString authToken();
//AUTHORIZATION
void addUser();
void deleteUser();
//GET ALL PANEL INFORMATION
void getControllerInfo();
//STATES
void getPower();
@ -66,6 +70,9 @@ public:
//EFFECTS
void getEffects();
void getSelectedEffect();
QUuid setEffect(const QString &effect);
//PANEL LAYOUT
@ -86,13 +93,17 @@ private:
signals:
void connectionChanged(bool connected);
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 brightnessReceived(int percentage);
void colorModeReceived();
void hueReceived(QColor color);
void colorModeReceived(const QString &colorMode);
void hueReceived(int hue);
void saturationReceived(int percentage);
void effectListReceived(const QStringList &effects);
void colorTemperatureReceived(int mired);
void selectedEffectReceived(const QString &effect);
};
#endif // NANOLEAF_H