mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-07-30 02:38:00 +02:00
added connection layer
This commit is contained in:
parent
3206f285ba
commit
f3e003eae2
513
philipshue/bridgeconnection.cpp
Normal file
513
philipshue/bridgeconnection.cpp
Normal file
@ -0,0 +1,513 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
|
||||
* Copyright (C) 2015 - 2019 Simon Stürz <simon.stuerz@nymea.io> *
|
||||
* Copyright (C) 2019 Bernhard Trinns <bernhard.trinnes@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
|
||||
#include "bridgeconnection.h"
|
||||
#include "devices/device.h"
|
||||
#include "types/param.h"
|
||||
#include "plugininfo.h"
|
||||
#include "network/upnp/upnpdiscovery.h"
|
||||
#include "network/upnp/upnpdiscoveryreply.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QColor>
|
||||
#include <QDateTime>
|
||||
#include <QStringList>
|
||||
#include <QJsonDocument>
|
||||
|
||||
|
||||
BridgeConnection::BridgeConnection(HueBridge *bridge, HardwareManager *hardwareManager, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_hardwareManager(hardwareManager),
|
||||
m_bridge(bridge)
|
||||
{
|
||||
m_bridge = new HueBridge(this);
|
||||
|
||||
}
|
||||
|
||||
BridgeConnection::~BridgeConnection()
|
||||
{
|
||||
m_hardwareManager->pluginTimerManager()->unregisterTimer(m_pluginTimer1Sec);
|
||||
m_hardwareManager->pluginTimerManager()->unregisterTimer(m_pluginTimer5Sec);
|
||||
m_hardwareManager->pluginTimerManager()->unregisterTimer(m_pluginTimer15Sec);
|
||||
}
|
||||
|
||||
void BridgeConnection::init()
|
||||
{
|
||||
m_pluginTimer1Sec = m_hardwareManager->pluginTimerManager()->registerTimer(1);
|
||||
connect(m_pluginTimer1Sec, &PluginTimer::timeout, this, [this]() {
|
||||
// refresh sensors every second
|
||||
if (m_remotes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
refreshSensors();
|
||||
});
|
||||
m_pluginTimer5Sec = m_hardwareManager->pluginTimerManager()->registerTimer(5);
|
||||
connect(m_pluginTimer5Sec, &PluginTimer::timeout, this, [this]() {
|
||||
// refresh lights every 5 seconds
|
||||
refreshLights();
|
||||
|
||||
});
|
||||
m_pluginTimer15Sec = m_hardwareManager->pluginTimerManager()->registerTimer(15);
|
||||
connect(m_pluginTimer15Sec, &PluginTimer::timeout, this, [this]() {
|
||||
// refresh bridges every 15 seconds
|
||||
refreshBridge();
|
||||
// search for new devices connected to the bridge
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
void BridgeConnection::refreshLight(const QString &uuid)
|
||||
{
|
||||
HueLight *light = m_lights.value(uuid);
|
||||
|
||||
QNetworkRequest request(QUrl("http://" + light->hostAddress().toString() + "/api/" + light->apiKey() + "/lights/" + QString::number(light->id())));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
QNetworkReply *reply = m_hardwareManager->networkManager()->get(request);
|
||||
connect(reply, &QNetworkReply::finished, this, &BridgeConnection::networkManagerReplyReady);
|
||||
|
||||
//m_lightRefreshRequests.insert(reply);
|
||||
}
|
||||
|
||||
void BridgeConnection::refreshBridge()
|
||||
{
|
||||
// qCDebug(dcPhilipsHue()) << "refreshing bridge";
|
||||
|
||||
QNetworkRequest request(QUrl("http://" + m_bridge->hostAddress().toString() + "/api/" + m_bridge->apiKey() + "/config"));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
QNetworkReply *reply = m_hardwareManager->networkManager()->get(request);
|
||||
connect(reply, &QNetworkReply::finished, this, &BridgeConnection::networkManagerReplyReady);
|
||||
//TODO abort old request and start new one
|
||||
//m_bridgeRefreshRequests.insert(reply);
|
||||
}
|
||||
|
||||
void BridgeConnection::refreshLights()
|
||||
{
|
||||
// qCDebug(dcPhilipsHue()) << "refreshing lights";
|
||||
QNetworkRequest request(QUrl("http://" + m_bridge->hostAddress().toString() + "/api/" + m_bridge->apiKey() + "/lights"));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
QNetworkReply *reply = m_hardwareManager->networkManager()->get(request);
|
||||
connect(reply, &QNetworkReply::finished, this, &BridgeConnection::networkManagerReplyReady);
|
||||
//m_lightsRefreshRequests.insert(reply, device);
|
||||
}
|
||||
|
||||
void BridgeConnection::refreshSensors()
|
||||
{
|
||||
// qCDebug(dcPhilipsHue()) << "refreshing sensors";
|
||||
|
||||
QNetworkRequest request(QUrl("http://" + m_bridge->hostAddress().toString() + "/api/" + m_bridge->apiKey() + "/sensors"));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
QNetworkReply *reply = m_hardwareManager->networkManager()->get(request);
|
||||
connect(reply, &QNetworkReply::finished, this, &BridgeConnection::networkManagerReplyReady);
|
||||
//m_sensorsRefreshRequests.insert(reply, device);
|
||||
}
|
||||
|
||||
void BridgeConnection::discoverBridgeDevices()
|
||||
{
|
||||
qCDebug(dcPhilipsHue) << "Discover bridge devices" << m_bridge->hostAddress();
|
||||
|
||||
QPair<QNetworkRequest, QByteArray> lightsRequest = m_bridge->createDiscoverLightsRequest();
|
||||
QNetworkReply *lightsReply = m_hardwareManager->networkManager()->get(lightsRequest.first);
|
||||
connect(lightsReply, &QNetworkReply::finished, this, &BridgeConnection::networkManagerReplyReady);
|
||||
//m_bridgeLightsDiscoveryRequests.insert(lightsReply, device);
|
||||
|
||||
QPair<QNetworkRequest, QByteArray> sensorsRequest = m_bridge->createSearchSensorsRequest();
|
||||
QNetworkReply *reply = m_hardwareManager->networkManager()->get(sensorsRequest.first);
|
||||
connect(reply, &QNetworkReply::finished, this, &BridgeConnection::networkManagerReplyReady);
|
||||
//m_bridgeSensorsDiscoveryRequests.insert(reply, device);
|
||||
}
|
||||
|
||||
void BridgeConnection::searchNewDevices(const QString &serialNumber)
|
||||
{
|
||||
qCDebug(dcPhilipsHue) << "Discover bridge devices" << m_bridge->hostAddress();
|
||||
|
||||
QPair<QNetworkRequest, QByteArray> request = m_bridge->createSearchLightsRequest(serialNumber);
|
||||
QNetworkReply *reply = m_hardwareManager->networkManager()->post(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &BridgeConnection::networkManagerReplyReady);
|
||||
//m_bridgeSearchDevicesRequests.insert(reply, device);
|
||||
}
|
||||
|
||||
void BridgeConnection::setPower(const QString &uuid, bool power)
|
||||
{
|
||||
HueLight *light = m_lights.value(uuid);
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetPowerRequest(power);
|
||||
QNetworkReply *reply = m_hardwareManager->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &BridgeConnection::networkManagerReplyReady);
|
||||
}
|
||||
|
||||
void BridgeConnection::setBrightness(const QString &uuid, quint8 percent)
|
||||
{
|
||||
HueLight *light = m_lights.value(uuid);
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetBrightnessRequest(percent);
|
||||
QNetworkReply *reply = m_hardwareManager->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &BridgeConnection::networkManagerReplyReady);
|
||||
}
|
||||
|
||||
void BridgeConnection::setColor(const QString &uuid, QColor color)
|
||||
{
|
||||
HueLight *light = m_lights.value(uuid);
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetColorRequest(color);
|
||||
QNetworkReply *reply = m_hardwareManager->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &BridgeConnection::networkManagerReplyReady);
|
||||
}
|
||||
|
||||
void BridgeConnection::setEffect(const QString &uuid, const QString &effect)
|
||||
{
|
||||
HueLight *light = m_lights.value(uuid);
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetEffectRequest(effect);
|
||||
QNetworkReply *reply = m_hardwareManager->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &BridgeConnection::networkManagerReplyReady);
|
||||
}
|
||||
|
||||
void BridgeConnection::setTemperature(const QString &uuid, quint16 temperature)
|
||||
{
|
||||
HueLight *light = m_lights.value(uuid);
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetTemperatureRequest(temperature);
|
||||
QNetworkReply *reply = m_hardwareManager->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &BridgeConnection::networkManagerReplyReady);
|
||||
}
|
||||
|
||||
void BridgeConnection::setFlash(const QString &uuid, const QString &mode)
|
||||
{
|
||||
HueLight *light = m_lights.value(uuid);
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createFlashRequest(mode);
|
||||
QNetworkReply *reply = m_hardwareManager->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &BridgeConnection::networkManagerReplyReady);
|
||||
}
|
||||
|
||||
|
||||
void BridgeConnection::processLightRefreshResponse(QString uuid, const QByteArray &data)
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
|
||||
// check JSON error
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Hue Bridge json error in response" << error.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
// check response error
|
||||
if (data.contains("error")) {
|
||||
if (!jsonDoc.toVariant().toList().isEmpty()) {
|
||||
qCWarning(dcPhilipsHue) << "Failed to refresh Hue Light:" << jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString();
|
||||
} else {
|
||||
qCWarning(dcPhilipsHue) << "Failed to refresh Hue Light: Invalid error message format";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
HueLight *light = m_lights.value(uuid);
|
||||
light->updateStates(jsonDoc.toVariant().toMap().value("state").toMap());
|
||||
}
|
||||
|
||||
void BridgeConnection::processBridgeRefreshResponse(const QByteArray &data)
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
|
||||
// check JSON error
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Hue Bridge json error in response" << error.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!jsonDoc.toVariant().toList().isEmpty()) {
|
||||
qCWarning(dcPhilipsHue) << "Failed to refresh Hue Bridge:" << jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString();
|
||||
bridgeReachableChanged(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//qCDebug(dcPhilipsHue()) << "Bridge refresh response" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented));
|
||||
|
||||
QVariantMap configMap = jsonDoc.toVariant().toMap();
|
||||
|
||||
// mark bridge as reachable
|
||||
bridgeReachableChanged(true);
|
||||
//device->setStateValue(bridgeApiVersionStateTypeId, configMap.value("apiversion").toString());
|
||||
//device->setStateValue(bridgeSoftwareVersionStateTypeId, configMap.value("swversion").toString());
|
||||
|
||||
int updateStatus = configMap.value("swupdate").toMap().value("updatestate").toInt();
|
||||
switch (updateStatus) {
|
||||
case 0:
|
||||
//device->setStateValue(bridgeUpdateStatusStateTypeId, "Up to date");
|
||||
break;
|
||||
case 1:
|
||||
//device->setStateValue(bridgeUpdateStatusStateTypeId, "Downloading updates");
|
||||
break;
|
||||
case 2:
|
||||
//device->setStateValue(bridgeUpdateStatusStateTypeId, "Updates ready to install");
|
||||
break;
|
||||
case 3:
|
||||
//device->setStateValue(bridgeUpdateStatusStateTypeId, "Installing updates");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BridgeConnection::processLightsRefreshResponse(const QByteArray &data)
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
|
||||
// check JSON error
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Hue Bridge json error in response" << error.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
// check response error
|
||||
if (data.contains("error")) {
|
||||
if (!jsonDoc.toVariant().toList().isEmpty()) {
|
||||
qCWarning(dcPhilipsHue) << "Failed to refresh Hue Lights:" << jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString();
|
||||
} else {
|
||||
qCWarning(dcPhilipsHue) << "Failed to refresh Hue Lights: Invalid error message format";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Update light states
|
||||
QVariantMap lightsMap = jsonDoc.toVariant().toMap();
|
||||
foreach (const QString &lightId, lightsMap.keys()) {
|
||||
QVariantMap lightMap = lightsMap.value(lightId).toMap();
|
||||
// get the light of this bridge
|
||||
foreach (HueLight *light, m_lights.values()) {
|
||||
if (light->id() == lightId.toInt()) {
|
||||
light->updateStates(lightMap.value("state").toMap());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BridgeConnection::processSensorsRefreshResponse(const QByteArray &data)
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
|
||||
// check JSON error
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Hue Bridge json error in response" << error.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
// check response error
|
||||
if (!jsonDoc.toVariant().toList().isEmpty()) {
|
||||
qCWarning(dcPhilipsHue) << "Failed to refresh Hue Sensors:" << jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString();
|
||||
return;
|
||||
}
|
||||
|
||||
// Update sensor states
|
||||
QVariantMap sensorsMap = jsonDoc.toVariant().toMap();
|
||||
foreach (const QString &sensorId, sensorsMap.keys()) {
|
||||
QVariantMap sensorMap = sensorsMap.value(sensorId).toMap();
|
||||
|
||||
// Remotes
|
||||
foreach (HueRemote *remote, m_remotes.values()) {
|
||||
if (remote->id() == sensorId.toInt()) {
|
||||
remote->updateStates(sensorMap.value("state").toMap(), sensorMap.value("config").toMap());
|
||||
}
|
||||
}
|
||||
|
||||
// Outdoor sensors
|
||||
foreach (HueMotionSensor *motionSensor, m_motionSensors.values()) {
|
||||
if (motionSensor->hasSensor(sensorId.toInt())) {
|
||||
motionSensor->updateStates(sensorMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BridgeConnection::processSetNameResponse(const QByteArray &data)
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
|
||||
// check JSON error
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Hue Bridge json error in response" << error.errorString();
|
||||
//emit deviceSetupFinished(device, Device::DeviceSetupStatusFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
// check response error
|
||||
if (data.contains("error")) {
|
||||
if (!jsonDoc.toVariant().toList().isEmpty()) {
|
||||
qCWarning(dcPhilipsHue) << "Failed to set name of Hue:" << jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString();
|
||||
} else {
|
||||
qCWarning(dcPhilipsHue) << "Failed to set name of Hue: Invalid error message format";
|
||||
}
|
||||
//emit setNameFinished(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BridgeConnection::networkManagerReplyReady()
|
||||
{
|
||||
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
||||
reply->deleteLater();
|
||||
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
// qCDebug(dcPhilipsHue()) << "Hue reply:" << status << reply->error() << reply->errorString();
|
||||
|
||||
// create user finished
|
||||
if (m_pairingRequests.contains(reply)) {
|
||||
PairingInfo *pairingInfo = m_pairingRequests.take(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Request error:" << status << reply->errorString();
|
||||
pairingInfo->deleteLater();
|
||||
return;
|
||||
}
|
||||
processPairingResponse(pairingInfo, reply->readAll());
|
||||
|
||||
} else if (m_informationRequests.contains(reply)) {
|
||||
PairingInfo *pairingInfo = m_informationRequests.take(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Request error:" << status << reply->errorString();
|
||||
pairingInfo->deleteLater();
|
||||
return;
|
||||
}
|
||||
processInformationResponse(pairingInfo, reply->readAll());
|
||||
|
||||
} else if (reply == m_bridgeLightsDiscoveryRequests) {
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Bridge light discovery error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(false);
|
||||
return;
|
||||
}
|
||||
processBridgeLightDiscoveryResponse(reply->readAll());
|
||||
|
||||
} else if (reply == m_bridgeSensorsDiscoveryRequests) {
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Bridge sensor discovery error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(false);
|
||||
return;
|
||||
}
|
||||
processBridgeSensorDiscoveryResponse(reply->readAll());
|
||||
|
||||
} else if (reply == m_bridgeSearchDevicesRequests) {
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Bridge search new devices error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(false);
|
||||
return;
|
||||
}
|
||||
discoverBridgeDevices();
|
||||
|
||||
} else if (m_bridgeRefreshRequests == reply) {;
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Refresh Hue Bridge request error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(false);
|
||||
return;
|
||||
}
|
||||
processBridgeRefreshResponse(reply->readAll());
|
||||
|
||||
} else if (reply == m_lightRefreshRequests) {
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Refresh Hue Light request error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(false);
|
||||
return;
|
||||
}
|
||||
processLightRefreshResponse(reply->readAll());
|
||||
|
||||
} else if (reply == m_lightsRefreshRequests) {
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Refresh Hue lights request error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(false);
|
||||
return;
|
||||
}
|
||||
processLightsRefreshResponse(reply->readAll());
|
||||
|
||||
} else if (reply == m_sensorsRefreshRequests) {
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Refresh Hue sensors request error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(false);
|
||||
return;
|
||||
}
|
||||
processSensorsRefreshResponse(reply->readAll());
|
||||
|
||||
} else if (m_asyncActions.contains(reply)) {
|
||||
QPair<Device *, ActionId> actionInfo = m_asyncActions.take(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Execute Hue Light action request error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(false);
|
||||
//emit actionExecutionFinished(actionInfo.second, Device::DeviceErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
processActionResponse(actionInfo.second, reply->readAll());
|
||||
|
||||
} else if (reply == m_setNameRequests) {
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Set name of Hue Light request error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(false);
|
||||
return;
|
||||
}
|
||||
processSetNameResponse(reply->readAll());
|
||||
} else {
|
||||
qCWarning(dcPhilipsHue()) << "Unhandled bridge reply" << reply->error() << reply->readAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int BridgeConnection::brightnessToPercentage(int brightness)
|
||||
{
|
||||
return qRound((100.0 * brightness) / 255.0);
|
||||
}
|
||||
|
||||
int BridgeConnection::percentageToBrightness(int percentage)
|
||||
{
|
||||
return qRound((255.0 * percentage) / 100.0);
|
||||
}
|
||||
|
||||
void BridgeConnection::abortRequests(QHash<QNetworkReply *, Device *> requestList, Device *device)
|
||||
{
|
||||
foreach (QNetworkReply* reply, requestList.keys()) {
|
||||
if (requestList.value(reply) == device) {
|
||||
reply->abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
135
philipshue/bridgeconnection.h
Normal file
135
philipshue/bridgeconnection.h
Normal file
@ -0,0 +1,135 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
|
||||
* Copyright (C) 2015 - 2019 Simon Stürz <simon.stuerz@nymea.io> *
|
||||
* Copyright (C) 2019 Bernhard Trinns <bernhard.trinnes@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
|
||||
#ifndef BRIDGECONNECTION_H
|
||||
#define BRIDGECONNECTION_H
|
||||
|
||||
#include "devices/deviceplugin.h"
|
||||
#include "huebridge.h"
|
||||
#include "huelight.h"
|
||||
#include "hueremote.h"
|
||||
#include "pairinginfo.h"
|
||||
#include "huemotionsensor.h"
|
||||
|
||||
#include "plugintimer.h"
|
||||
#include "network/networkaccessmanager.h"
|
||||
#include "network/upnp/upnpdiscovery.h"
|
||||
#include "devices/devicemanager.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class BridgeConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BridgeConnection(HueBridge *bridge, HardwareManager *hardwaremanager, QObject *parent = nullptr);
|
||||
~BridgeConnection();
|
||||
void init();
|
||||
|
||||
//bridge actions
|
||||
void discoverBridgeDevices();
|
||||
void searchNewDevices(const QString &serialNumber);
|
||||
|
||||
//light actions
|
||||
void setPower(const QString &uuid, bool power);
|
||||
void setBrightness(const QString &uuid, quint8 percent);
|
||||
void setColor(const QString &uuid, QColor percent);
|
||||
void setEffect(const QString &uuid, const QString &effect);
|
||||
void setFlash(const QString &uuid, const QString &flashMode);
|
||||
void setTemperature(const QString &uuid, quint16 temperature);
|
||||
|
||||
void setLightName();
|
||||
void setRemoteName();
|
||||
|
||||
private slots:
|
||||
void lightStateChanged();
|
||||
void remoteStateChanged();
|
||||
void onRemoteButtonEvent(int buttonCode);
|
||||
|
||||
// Motion sensor
|
||||
void onMotionSensorReachableChanged(bool reachable);
|
||||
void onMotionSensorBatteryLevelChanged(int batteryLevel);
|
||||
void onMotionSensorTemperatureChanged(double temperature);
|
||||
void onMotionSensorPresenceChanged(bool presence);
|
||||
void onMotionSensorLightIntensityChanged(double lightIntensity);
|
||||
|
||||
private slots:
|
||||
void networkManagerReplyReady();
|
||||
void onDeviceNameChanged();
|
||||
|
||||
private:
|
||||
HardwareManager *m_hardwareManager = nullptr;
|
||||
|
||||
PluginTimer *m_pluginTimer1Sec = nullptr;
|
||||
PluginTimer *m_pluginTimer5Sec = nullptr;
|
||||
PluginTimer *m_pluginTimer15Sec = nullptr;
|
||||
|
||||
QHash<QNetworkReply *, PairingInfo *> m_pairingRequests;
|
||||
QHash<QNetworkReply *, PairingInfo *> m_informationRequests;
|
||||
|
||||
QNetworkReply *m_lightRefreshRequests;
|
||||
QNetworkReply *m_setNameRequests;
|
||||
QNetworkReply *m_bridgeRefreshRequests;
|
||||
QNetworkReply *m_lightsRefreshRequests;
|
||||
QNetworkReply *m_sensorsRefreshRequests;
|
||||
QNetworkReply *m_bridgeLightsDiscoveryRequests;
|
||||
QNetworkReply *m_bridgeSensorsDiscoveryRequests;
|
||||
QNetworkReply *m_bridgeSearchDevicesRequests;
|
||||
|
||||
QHash<QNetworkReply *, QPair<Device *, ActionId> > m_asyncActions;
|
||||
|
||||
HueBridge *m_bridge;
|
||||
QHash<QString, HueLight *> m_lights;
|
||||
QHash<QString, HueRemote *> m_remotes;
|
||||
QHash<QString, HueMotionSensor *> m_motionSensors;
|
||||
|
||||
void refreshLight(const QString &uuid); //
|
||||
void refreshBridge();
|
||||
void refreshLights();
|
||||
void refreshSensors();
|
||||
|
||||
void processBridgeLightDiscoveryResponse(const QByteArray &data);
|
||||
void processBridgeSensorDiscoveryResponse(const QByteArray &data);
|
||||
void processLightRefreshResponse(const QByteArray &data);
|
||||
void processBridgeRefreshResponse(const QByteArray &data);
|
||||
void processLightsRefreshResponse(const QByteArray &data);
|
||||
void processSensorsRefreshResponse(const QByteArray &data);
|
||||
void processSetNameResponse(const QByteArray &data);
|
||||
void processPairingResponse(PairingInfo *pairingInfo, const QByteArray &data);
|
||||
void processInformationResponse(PairingInfo *pairingInfo, const QByteArray &data);
|
||||
void processActionResponse(const ActionId actionId, const QByteArray &data);
|
||||
|
||||
void bridgeReachableChanged(const bool &reachable);
|
||||
|
||||
bool lightAlreadyAdded(const QString &uuid);
|
||||
bool sensorAlreadyAdded(const QString &uuid);
|
||||
|
||||
int brightnessToPercentage(int brightness);
|
||||
int percentageToBrightness(int percentage);
|
||||
|
||||
void abortRequests(QHash<QNetworkReply *, Device *> requestList);
|
||||
};
|
||||
|
||||
#endif // BRIDGECONNECTION_H
|
||||
@ -1,8 +1,9 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
|
||||
* Copyright (C) 2015 - 2019 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* Copyright (C) 2018 Michael Zanetti <michael.zanetti@guh.io> *
|
||||
* Copyright (C) 2015 - 2019 Simon Stürz <simon.stuerz@nymea.io> *
|
||||
* Copyright (C) 2018 Michael Zanetti <michael.zanetti@nymea.io> *
|
||||
* Copyright (C) 2019 Bernhard Trinnes <bernhard.trinnes@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
@ -41,42 +42,6 @@ DevicePluginPhilipsHue::DevicePluginPhilipsHue()
|
||||
|
||||
}
|
||||
|
||||
DevicePluginPhilipsHue::~DevicePluginPhilipsHue()
|
||||
{
|
||||
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer1Sec);
|
||||
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer5Sec);
|
||||
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer15Sec);
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::init()
|
||||
{
|
||||
m_pluginTimer1Sec = hardwareManager()->pluginTimerManager()->registerTimer(1);
|
||||
connect(m_pluginTimer1Sec, &PluginTimer::timeout, this, [this]() {
|
||||
// refresh sensors every second
|
||||
if (m_remotes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
foreach (HueBridge *bridge, m_bridges.keys()) {
|
||||
refreshSensors(bridge);
|
||||
}
|
||||
});
|
||||
m_pluginTimer5Sec = hardwareManager()->pluginTimerManager()->registerTimer(5);
|
||||
connect(m_pluginTimer5Sec, &PluginTimer::timeout, this, [this]() {
|
||||
// refresh lights every 5 seconds
|
||||
foreach (HueBridge *bridge, m_bridges.keys()) {
|
||||
refreshLights(bridge);
|
||||
}
|
||||
});
|
||||
m_pluginTimer15Sec = hardwareManager()->pluginTimerManager()->registerTimer(15);
|
||||
connect(m_pluginTimer15Sec, &PluginTimer::timeout, this, [this]() {
|
||||
// refresh bridges every 15 seconds
|
||||
foreach (Device *device, m_bridges.values()) {
|
||||
refreshBridge(device);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
Device::DeviceError DevicePluginPhilipsHue::discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms)
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
@ -117,7 +82,6 @@ Device::DeviceError DevicePluginPhilipsHue::discoverDevices(const DeviceClassId
|
||||
discovery->results.append(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
finishDiscovery(discovery);
|
||||
});
|
||||
|
||||
@ -160,10 +124,8 @@ Device::DeviceError DevicePluginPhilipsHue::discoverDevices(const DeviceClassId
|
||||
qCDebug(dcPhilipsHue()) << "N-UPnP: Found Hue bridge:" << bridgeId;
|
||||
discovery->results.append(descriptor);
|
||||
}
|
||||
|
||||
finishDiscovery(discovery);
|
||||
});
|
||||
|
||||
return Device::DeviceErrorAsync;
|
||||
}
|
||||
|
||||
@ -183,7 +145,7 @@ Device::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *device)
|
||||
device->setParamValue(bridgeDeviceApiKeyParamTypeId, b->apiKey());
|
||||
device->setParamValue(bridgeDeviceZigbeeChannelParamTypeId, b->zigbeeChannel());
|
||||
device->setParamValue(bridgeDeviceMacParamTypeId, b->macAddress());
|
||||
m_bridges.insert(b, device);
|
||||
m_bridgeConnections.insert(device->id(), );
|
||||
device->setStateValue(bridgeConnectedStateTypeId, true);
|
||||
discoverBridgeDevices(b);
|
||||
return Device::DeviceSetupStatusSuccess;
|
||||
@ -193,15 +155,18 @@ Device::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *device)
|
||||
// Loaded bridge
|
||||
qCDebug(dcPhilipsHue) << "Setup Hue Bridge" << device->params();
|
||||
|
||||
|
||||
HueBridge *bridge = new HueBridge(this);
|
||||
bridge->setId(device->paramValue(bridgeDeviceIdParamTypeId).toString());
|
||||
bridge->setApiKey(device->paramValue(bridgeDeviceApiKeyParamTypeId).toString());
|
||||
bridge->setHostAddress(QHostAddress(device->paramValue(bridgeDeviceHostParamTypeId).toString()));
|
||||
bridge->setMacAddress(device->paramValue(bridgeDeviceMacParamTypeId).toString());
|
||||
bridge->setZigbeeChannel(device->paramValue(bridgeDeviceZigbeeChannelParamTypeId).toInt());
|
||||
m_bridges.insert(bridge, device);
|
||||
|
||||
discoverBridgeDevices(bridge);
|
||||
BridgeConnection *bridgeConnection = new BridgeConnection(bridge, hardwareManager(), this);
|
||||
m_bridgeConnections.insert(device->id(), bridgeConnection);
|
||||
|
||||
bridgeConnection->discoverBridgeDevices();
|
||||
return Device::DeviceSetupStatusSuccess;
|
||||
}
|
||||
|
||||
@ -209,7 +174,7 @@ Device::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *device)
|
||||
if (device->deviceClassId() == colorLightDeviceClassId) {
|
||||
qCDebug(dcPhilipsHue) << "Setup Hue color light" << device->params();
|
||||
|
||||
HueBridge *bridge = m_bridges.key(myDevices().findById(device->parentId()));
|
||||
BridgeConnection *bridge = m_bridgeConnections;
|
||||
HueLight *hueLight = new HueLight(this);
|
||||
hueLight->setHostAddress(bridge->hostAddress());
|
||||
hueLight->setApiKey(bridge->apiKey());
|
||||
@ -297,7 +262,7 @@ Device::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *device)
|
||||
if (device->deviceClassId() == remoteDeviceClassId) {
|
||||
qCDebug(dcPhilipsHue) << "Setup Hue remote" << device->params() << device->deviceClassId();
|
||||
|
||||
HueBridge *bridge = m_bridges.key(myDevices().findById(device->parentId()));
|
||||
BridgeConnection *bridge = m_bridgeConnections.value(device->parentId());
|
||||
HueRemote *hueRemote = new HueRemote(this);
|
||||
hueRemote->setHostAddress(bridge->hostAddress());
|
||||
hueRemote->setApiKey(bridge->apiKey());
|
||||
@ -486,148 +451,6 @@ Device::DeviceSetupStatus DevicePluginPhilipsHue::confirmPairing(const PairingTr
|
||||
return Device::DeviceSetupStatusAsync;
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::networkManagerReplyReady()
|
||||
{
|
||||
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
||||
reply->deleteLater();
|
||||
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
// qCDebug(dcPhilipsHue()) << "Hue reply:" << status << reply->error() << reply->errorString();
|
||||
|
||||
// create user finished
|
||||
if (m_pairingRequests.contains(reply)) {
|
||||
PairingInfo *pairingInfo = m_pairingRequests.take(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Request error:" << status << reply->errorString();
|
||||
pairingInfo->deleteLater();
|
||||
return;
|
||||
}
|
||||
processPairingResponse(pairingInfo, reply->readAll());
|
||||
|
||||
} else if (m_informationRequests.contains(reply)) {
|
||||
PairingInfo *pairingInfo = m_informationRequests.take(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Request error:" << status << reply->errorString();
|
||||
pairingInfo->deleteLater();
|
||||
return;
|
||||
}
|
||||
processInformationResponse(pairingInfo, reply->readAll());
|
||||
|
||||
} else if (m_bridgeLightsDiscoveryRequests.contains(reply)) {
|
||||
Device *device = m_bridgeLightsDiscoveryRequests.take(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Bridge light discovery error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(device, false);
|
||||
return;
|
||||
}
|
||||
processBridgeLightDiscoveryResponse(device, reply->readAll());
|
||||
|
||||
} else if (m_bridgeSensorsDiscoveryRequests.contains(reply)) {
|
||||
Device *device = m_bridgeSensorsDiscoveryRequests.take(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Bridge sensor discovery error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(device, false);
|
||||
return;
|
||||
}
|
||||
processBridgeSensorDiscoveryResponse(device, reply->readAll());
|
||||
|
||||
} else if (m_bridgeSearchDevicesRequests.contains(reply)) {
|
||||
Device *device = m_bridgeSearchDevicesRequests.take(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Bridge search new devices error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(device, false);
|
||||
return;
|
||||
}
|
||||
discoverBridgeDevices(m_bridges.key(device));
|
||||
|
||||
} else if (m_bridgeRefreshRequests.contains(reply)) {
|
||||
Device *device = m_bridgeRefreshRequests.take(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
if (device->stateValue(bridgeConnectedStateTypeId).toBool()) {
|
||||
qCWarning(dcPhilipsHue) << "Refresh Hue Bridge request error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(device, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
processBridgeRefreshResponse(device, reply->readAll());
|
||||
|
||||
} else if (m_lightRefreshRequests.contains(reply)) {
|
||||
Device *device = m_lightRefreshRequests.take(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Refresh Hue Light request error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(device, false);
|
||||
return;
|
||||
}
|
||||
processLightRefreshResponse(device, reply->readAll());
|
||||
|
||||
} else if (m_lightsRefreshRequests.contains(reply)) {
|
||||
Device *device = m_lightsRefreshRequests.take(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
if (device->stateValue(bridgeConnectedStateTypeId).toBool()) {
|
||||
qCWarning(dcPhilipsHue) << "Refresh Hue lights request error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(device, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
processLightsRefreshResponse(device, reply->readAll());
|
||||
|
||||
} else if (m_sensorsRefreshRequests.contains(reply)) {
|
||||
Device *device = m_sensorsRefreshRequests.take(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
if (device->stateValue(bridgeConnectedStateTypeId).toBool()) {
|
||||
qCWarning(dcPhilipsHue) << "Refresh Hue sensors request error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(device, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
processSensorsRefreshResponse(device, reply->readAll());
|
||||
|
||||
} else if (m_asyncActions.contains(reply)) {
|
||||
QPair<Device *, ActionId> actionInfo = m_asyncActions.take(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Execute Hue Light action request error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(actionInfo.first, false);
|
||||
emit actionExecutionFinished(actionInfo.second, Device::DeviceErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
processActionResponse(actionInfo.first, actionInfo.second, reply->readAll());
|
||||
|
||||
} else if (m_setNameRequests.contains(reply)) {
|
||||
Device *device = m_setNameRequests.take(reply);
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Set name of Hue Light request error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(device, false);
|
||||
return;
|
||||
}
|
||||
processSetNameResponse(device, reply->readAll());
|
||||
} else {
|
||||
qCWarning(dcPhilipsHue()) << "Unhandled bridge reply" << reply->error() << reply->readAll();
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::onDeviceNameChanged()
|
||||
{
|
||||
Device *device = static_cast<Device*>(sender());
|
||||
@ -672,48 +495,39 @@ Device::DeviceError DevicePluginPhilipsHue::executeAction(Device *device, const
|
||||
|
||||
// Color light
|
||||
if (device->deviceClassId() == colorLightDeviceClassId) {
|
||||
HueLight *light = m_lights.key(device);
|
||||
|
||||
if (!light->reachable()) {
|
||||
BridgeConnection* bridge = m_bridgeConnections.value(device->parentId());
|
||||
QString uuid = device->paramValue(colorLightDeviceUuidParamTypeId).toString();
|
||||
|
||||
/*if (!light->reachable()) {
|
||||
qCWarning(dcPhilipsHue) << "Light" << light->name() << "not reachable";
|
||||
return Device::DeviceErrorHardwareNotAvailable;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (action.actionTypeId() == colorLightPowerActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetPowerRequest(action.param(colorLightPowerActionPowerParamTypeId).value().toBool());
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
//get bridge
|
||||
bridge->setPower(uuid, action.param(colorLightPowerActionPowerParamTypeId).value().toBool())
|
||||
//m_asyncActions.insert(device, action.id());
|
||||
return Device::DeviceErrorAsync;
|
||||
} else if (action.actionTypeId() == colorLightColorActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetColorRequest(action.param(colorLightColorActionColorParamTypeId).value().value<QColor>());
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_asyncActions.insert(reply,QPair<Device *, ActionId>(device, action.id()));
|
||||
bridge->setColor(uuid, action.param(colorLightColorActionColorParamTypeId).value().value<QColor>());
|
||||
//m_asyncActions.insert(reply,QPair<Device *, ActionId>(device, action.id()));
|
||||
return Device::DeviceErrorAsync;
|
||||
} else if (action.actionTypeId() == colorLightBrightnessActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetBrightnessRequest(percentageToBrightness(action.param(colorLightBrightnessActionBrightnessParamTypeId).value().toInt()));
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
bridge->setBrightness(uuid, action.param(colorLightBrightnessActionBrightnessParamTypeId).value().toInt());
|
||||
//m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
return Device::DeviceErrorAsync;
|
||||
} else if (action.actionTypeId() == colorLightEffectActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetEffectRequest(action.param(colorLightEffectActionEffectParamTypeId).value().toString());
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
bridge->setEffect(uuid, action.param(colorLightEffectActionEffectParamTypeId).value().toString());
|
||||
//m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
return Device::DeviceErrorAsync;
|
||||
} else if (action.actionTypeId() == colorLightAlertActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createFlashRequest(action.param(colorLightAlertActionAlertParamTypeId).value().toString());
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
bridge->setFlash(uuid, action.param(colorLightAlertActionAlertParamTypeId).value().toString());
|
||||
//m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
return Device::DeviceErrorAsync;
|
||||
} else if (action.actionTypeId() == colorLightColorTemperatureActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetTemperatureRequest(action.param(colorLightColorTemperatureActionColorTemperatureParamTypeId).value().toInt());
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
bridge->setTemperature(uuid, action.param(colorLightColorTemperatureActionColorTemperatureParamTypeId).value().toInt());
|
||||
//m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
return Device::DeviceErrorAsync;
|
||||
}
|
||||
return Device::DeviceErrorActionTypeNotFound;
|
||||
@ -721,36 +535,29 @@ Device::DeviceError DevicePluginPhilipsHue::executeAction(Device *device, const
|
||||
|
||||
// Color temperature light
|
||||
if (device->deviceClassId() == colorTemperatureLightDeviceClassId) {
|
||||
HueLight *light = m_lights.key(device);
|
||||
BridgeConnection* bridge = m_bridgeConnections.value(device->parentId());
|
||||
QString uuid = device->paramValue(colorTemperatureLightDeviceUuidParamTypeId).toString();
|
||||
|
||||
if (!light->reachable()) {
|
||||
/*if (!light->reachable()) {
|
||||
qCWarning(dcPhilipsHue) << "Light" << light->name() << "not reachable";
|
||||
return Device::DeviceErrorHardwareNotAvailable;
|
||||
}
|
||||
}*/ //TODO
|
||||
|
||||
if (action.actionTypeId() == colorTemperatureLightPowerActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetPowerRequest(action.param(colorTemperatureLightPowerActionPowerParamTypeId).value().toBool());
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
bridge->setTemperature(uuid, action.param(colorTemperatureLightPowerActionPowerParamTypeId).value().toBool());
|
||||
//m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
return Device::DeviceErrorAsync;
|
||||
} else if (action.actionTypeId() == colorTemperatureLightBrightnessActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetBrightnessRequest(percentageToBrightness(action.param(colorTemperatureLightBrightnessActionBrightnessParamTypeId).value().toInt()));
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
bridge->setBrightness(uuid, action.param(colorTemperatureLightBrightnessActionBrightnessParamTypeId).value().toInt());
|
||||
//m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
return Device::DeviceErrorAsync;
|
||||
} else if (action.actionTypeId() == colorTemperatureLightAlertActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createFlashRequest(action.param(colorTemperatureLightAlertActionAlertParamTypeId).value().toString());
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
bridge->setFlash(uuid, action.param(colorTemperatureLightAlertActionAlertParamTypeId).value().toString());
|
||||
//m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
return Device::DeviceErrorAsync;
|
||||
} else if (action.actionTypeId() == colorTemperatureLightColorTemperatureActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetTemperatureRequest(action.param(colorTemperatureLightColorTemperatureActionColorTemperatureParamTypeId).value().toInt());
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
bridge->setTemperature(uuid, action.param(colorTemperatureLightColorTemperatureActionColorTemperatureParamTypeId).value().toInt());
|
||||
//m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
return Device::DeviceErrorAsync;
|
||||
}
|
||||
return Device::DeviceErrorActionTypeNotFound;
|
||||
@ -758,30 +565,28 @@ Device::DeviceError DevicePluginPhilipsHue::executeAction(Device *device, const
|
||||
|
||||
// Dimmable light
|
||||
if (device->deviceClassId() == dimmableLightDeviceClassId) {
|
||||
HueLight *light = m_lights.key(device);
|
||||
|
||||
if (!light->reachable()) {
|
||||
BridgeConnection* bridge = m_bridgeConnections.value(device->parentId());
|
||||
QString uuid = device->paramValue(dimmableLightDeviceUuidParamTypeId).toString();
|
||||
|
||||
/*if (!light->reachable()) {
|
||||
qCWarning(dcPhilipsHue) << "Light" << light->name() << "not reachable";
|
||||
return Device::DeviceErrorHardwareNotAvailable;
|
||||
}
|
||||
}*/ //TODO
|
||||
|
||||
if (action.actionTypeId() == dimmableLightPowerActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetPowerRequest(action.param(dimmableLightPowerActionPowerParamTypeId).value().toBool());
|
||||
bridge->setPower(uuid, action.param(dimmableLightPowerActionPowerParamTypeId).value().toBool());
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
//m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
return Device::DeviceErrorAsync;
|
||||
} else if (action.actionTypeId() == dimmableLightBrightnessActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createSetBrightnessRequest(percentageToBrightness(action.param(dimmableLightBrightnessActionBrightnessParamTypeId).value().toInt()));
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
bridge->setBrightness(uuid, action.param(dimmableLightBrightnessActionBrightnessParamTypeId).value().toInt());
|
||||
//m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
return Device::DeviceErrorAsync;
|
||||
} else if (action.actionTypeId() == dimmableLightAlertActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = light->createFlashRequest(action.param(dimmableLightAlertActionAlertParamTypeId).value().toString());
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->put(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
bridge->setFlash(uuid, action.param(dimmableLightAlertActionAlertParamTypeId).value().toString());
|
||||
//m_asyncActions.insert(reply, QPair<Device *, ActionId>(device, action.id()));
|
||||
return Device::DeviceErrorAsync;
|
||||
}
|
||||
return Device::DeviceErrorActionTypeNotFound;
|
||||
@ -789,14 +594,15 @@ Device::DeviceError DevicePluginPhilipsHue::executeAction(Device *device, const
|
||||
|
||||
// Hue bridge
|
||||
if (device->deviceClassId() == bridgeDeviceClassId) {
|
||||
HueBridge *bridge = m_bridges.key(device);
|
||||
BridgeConnection* bridge = m_bridgeConnections.value(device->id());
|
||||
|
||||
if (!device->stateValue(bridgeConnectedStateTypeId).toBool()) {
|
||||
qCWarning(dcPhilipsHue) << "Bridge" << bridge->hostAddress().toString() << "not reachable";
|
||||
return Device::DeviceErrorHardwareNotAvailable;
|
||||
}
|
||||
|
||||
if (action.actionTypeId() == bridgeSearchNewDevicesActionTypeId) {
|
||||
searchNewDevices(bridge, action.param(bridgeSearchNewDevicesActionSerialParamTypeId).value().toString());
|
||||
bridge->searchNewDevices(action.param(bridgeSearchNewDevicesActionSerialParamTypeId).value().toString());
|
||||
return Device::DeviceErrorNoError;
|
||||
} else if (action.actionTypeId() == bridgeCheckForUpdatesActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = bridge->createCheckUpdatesRequest();
|
||||
@ -962,79 +768,7 @@ void DevicePluginPhilipsHue::onMotionSensorLightIntensityChanged(double lightInt
|
||||
sensorDevice->setStateValue(sensor->lightIntensityStateTypeId(), lightIntensity);
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::refreshLight(Device *device)
|
||||
{
|
||||
HueLight *light = m_lights.key(device);
|
||||
|
||||
QNetworkRequest request(QUrl("http://" + light->hostAddress().toString() + "/api/" + light->apiKey() + "/lights/" + QString::number(light->id())));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_lightRefreshRequests.insert(reply, device);
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::refreshBridge(Device *device)
|
||||
{
|
||||
HueBridge *bridge = m_bridges.key(device);
|
||||
// qCDebug(dcPhilipsHue()) << "refreshing bridge";
|
||||
|
||||
QNetworkRequest request(QUrl("http://" + bridge->hostAddress().toString() + "/api/" + bridge->apiKey() + "/config"));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_bridgeRefreshRequests.insert(reply, device);
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::refreshLights(HueBridge *bridge)
|
||||
{
|
||||
Device *device = m_bridges.value(bridge);
|
||||
// qCDebug(dcPhilipsHue()) << "refreshing lights";
|
||||
|
||||
QNetworkRequest request(QUrl("http://" + bridge->hostAddress().toString() + "/api/" + bridge->apiKey() + "/lights"));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_lightsRefreshRequests.insert(reply, device);
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::refreshSensors(HueBridge *bridge)
|
||||
{
|
||||
Device *device = m_bridges.value(bridge);
|
||||
// qCDebug(dcPhilipsHue()) << "refreshing sensors";
|
||||
|
||||
QNetworkRequest request(QUrl("http://" + bridge->hostAddress().toString() + "/api/" + bridge->apiKey() + "/sensors"));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_sensorsRefreshRequests.insert(reply, device);
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::discoverBridgeDevices(HueBridge *bridge)
|
||||
{
|
||||
Device *device = m_bridges.value(bridge);
|
||||
qCDebug(dcPhilipsHue) << "Discover bridge devices" << bridge->hostAddress();
|
||||
|
||||
QPair<QNetworkRequest, QByteArray> lightsRequest = bridge->createDiscoverLightsRequest();
|
||||
QNetworkReply *lightsReply = hardwareManager()->networkManager()->get(lightsRequest.first);
|
||||
connect(lightsReply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_bridgeLightsDiscoveryRequests.insert(lightsReply, device);
|
||||
|
||||
QPair<QNetworkRequest, QByteArray> sensorsRequest = bridge->createSearchSensorsRequest();
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(sensorsRequest.first);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_bridgeSensorsDiscoveryRequests.insert(reply, device);
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::searchNewDevices(HueBridge *bridge, const QString &serialNumber)
|
||||
{
|
||||
Device *device = m_bridges.value(bridge);
|
||||
qCDebug(dcPhilipsHue) << "Discover bridge devices" << bridge->hostAddress();
|
||||
|
||||
QPair<QNetworkRequest, QByteArray> request = bridge->createSearchLightsRequest(serialNumber);
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
|
||||
m_bridgeSearchDevicesRequests.insert(reply, device);
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::setLightName(Device *device)
|
||||
{
|
||||
@ -1321,175 +1055,7 @@ void DevicePluginPhilipsHue::processBridgeSensorDiscoveryResponse(Device *device
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::processLightRefreshResponse(Device *device, const QByteArray &data)
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
|
||||
// check JSON error
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Hue Bridge json error in response" << error.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
// check response error
|
||||
if (data.contains("error")) {
|
||||
if (!jsonDoc.toVariant().toList().isEmpty()) {
|
||||
qCWarning(dcPhilipsHue) << "Failed to refresh Hue Light:" << jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString();
|
||||
} else {
|
||||
qCWarning(dcPhilipsHue) << "Failed to refresh Hue Light: Invalid error message format";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
HueLight *light = m_lights.key(device);
|
||||
light->updateStates(jsonDoc.toVariant().toMap().value("state").toMap());
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::processBridgeRefreshResponse(Device *device, const QByteArray &data)
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
|
||||
// check JSON error
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Hue Bridge json error in response" << error.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!jsonDoc.toVariant().toList().isEmpty()) {
|
||||
qCWarning(dcPhilipsHue) << "Failed to refresh Hue Bridge:" << jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString();
|
||||
bridgeReachableChanged(device, false);
|
||||
return;
|
||||
}
|
||||
|
||||
//qCDebug(dcPhilipsHue()) << "Bridge refresh response" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented));
|
||||
|
||||
QVariantMap configMap = jsonDoc.toVariant().toMap();
|
||||
|
||||
// mark bridge as reachable
|
||||
bridgeReachableChanged(device, true);
|
||||
device->setStateValue(bridgeApiVersionStateTypeId, configMap.value("apiversion").toString());
|
||||
device->setStateValue(bridgeSoftwareVersionStateTypeId, configMap.value("swversion").toString());
|
||||
|
||||
int updateStatus = configMap.value("swupdate").toMap().value("updatestate").toInt();
|
||||
switch (updateStatus) {
|
||||
case 0:
|
||||
device->setStateValue(bridgeUpdateStatusStateTypeId, "Up to date");
|
||||
break;
|
||||
case 1:
|
||||
device->setStateValue(bridgeUpdateStatusStateTypeId, "Downloading updates");
|
||||
break;
|
||||
case 2:
|
||||
device->setStateValue(bridgeUpdateStatusStateTypeId, "Updates ready to install");
|
||||
break;
|
||||
case 3:
|
||||
device->setStateValue(bridgeUpdateStatusStateTypeId, "Installing updates");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::processLightsRefreshResponse(Device *device, const QByteArray &data)
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
|
||||
// check JSON error
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Hue Bridge json error in response" << error.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
// check response error
|
||||
if (data.contains("error")) {
|
||||
if (!jsonDoc.toVariant().toList().isEmpty()) {
|
||||
qCWarning(dcPhilipsHue) << "Failed to refresh Hue Lights:" << jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString();
|
||||
} else {
|
||||
qCWarning(dcPhilipsHue) << "Failed to refresh Hue Lights: Invalid error message format";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Update light states
|
||||
QVariantMap lightsMap = jsonDoc.toVariant().toMap();
|
||||
foreach (const QString &lightId, lightsMap.keys()) {
|
||||
QVariantMap lightMap = lightsMap.value(lightId).toMap();
|
||||
// get the light of this bridge
|
||||
foreach (HueLight *light, m_lights.keys()) {
|
||||
if (light->id() == lightId.toInt() && m_lights.value(light)->parentId() == device->id()) {
|
||||
light->updateStates(lightMap.value("state").toMap());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::processSensorsRefreshResponse(Device *device, const QByteArray &data)
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
|
||||
// check JSON error
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Hue Bridge json error in response" << error.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
// check response error
|
||||
if (!jsonDoc.toVariant().toList().isEmpty()) {
|
||||
qCWarning(dcPhilipsHue) << "Failed to refresh Hue Sensors:" << jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString();
|
||||
return;
|
||||
}
|
||||
|
||||
// Update sensor states
|
||||
QVariantMap sensorsMap = jsonDoc.toVariant().toMap();
|
||||
foreach (const QString &sensorId, sensorsMap.keys()) {
|
||||
QVariantMap sensorMap = sensorsMap.value(sensorId).toMap();
|
||||
|
||||
// Remotes
|
||||
foreach (HueRemote *remote, m_remotes.keys()) {
|
||||
if (remote->id() == sensorId.toInt() && m_remotes.value(remote)->parentId() == device->id()) {
|
||||
remote->updateStates(sensorMap.value("state").toMap(), sensorMap.value("config").toMap());
|
||||
}
|
||||
}
|
||||
|
||||
// Outdoor sensors
|
||||
foreach (HueMotionSensor *motionSensor, m_motionSensors.keys()) {
|
||||
if (motionSensor->hasSensor(sensorId.toInt()) && m_motionSensors.value(motionSensor)->parentId() == device->id()) {
|
||||
motionSensor->updateStates(sensorMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::processSetNameResponse(Device *device, const QByteArray &data)
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
|
||||
// check JSON error
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcPhilipsHue) << "Hue Bridge json error in response" << error.errorString();
|
||||
emit deviceSetupFinished(device, Device::DeviceSetupStatusFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
// check response error
|
||||
if (data.contains("error")) {
|
||||
if (!jsonDoc.toVariant().toList().isEmpty()) {
|
||||
qCWarning(dcPhilipsHue) << "Failed to set name of Hue:" << jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString();
|
||||
} else {
|
||||
qCWarning(dcPhilipsHue) << "Failed to set name of Hue: Invalid error message format";
|
||||
}
|
||||
emit deviceSetupFinished(device, Device::DeviceSetupStatusFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->deviceClassId() == colorLightDeviceClassId || device->deviceClassId() == dimmableLightDeviceClassId)
|
||||
refreshLight(device);
|
||||
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::processPairingResponse(PairingInfo *pairingInfo, const QByteArray &data)
|
||||
{
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
|
||||
* Copyright (C) 2015 - 2019 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* Copyright (C) 2015 - 2019 Simon Stürz <simon.stuerz@nymea.io> *
|
||||
* Copyright (C) 2019 Bernhard Trinns <bernhard.trinnes@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
@ -25,12 +26,12 @@
|
||||
#define DEVICEPLUGINPHILIPSHUE_H
|
||||
|
||||
#include "devices/deviceplugin.h"
|
||||
#include "bridgeconnection.h"
|
||||
#include "huebridge.h"
|
||||
#include "huelight.h"
|
||||
#include "hueremote.h"
|
||||
#include "pairinginfo.h"
|
||||
#include "huemotionsensor.h"
|
||||
#include "huemotionsensor.h"
|
||||
|
||||
#include "plugintimer.h"
|
||||
#include "network/networkaccessmanager.h"
|
||||
@ -47,31 +48,28 @@ class DevicePluginPhilipsHue: public DevicePlugin
|
||||
|
||||
public:
|
||||
explicit DevicePluginPhilipsHue();
|
||||
~DevicePluginPhilipsHue();
|
||||
|
||||
void init() override;
|
||||
Device::DeviceSetupStatus setupDevice(Device *device) override;
|
||||
Device::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) override;
|
||||
void deviceRemoved(Device *device) override;
|
||||
Device::DeviceSetupStatus confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList ¶ms, const QString &secret) override;
|
||||
|
||||
public slots:
|
||||
Device::DeviceError executeAction(Device *device, const Action &action);
|
||||
Device::DeviceError executeAction(Device *device, const Action &action) override;
|
||||
|
||||
private slots:
|
||||
void lightStateChanged();
|
||||
void remoteStateChanged();
|
||||
// Light Device Events
|
||||
void onLightStateChanged();
|
||||
|
||||
// Remote Device Eventes
|
||||
void onRemoteStateChanged();
|
||||
void onRemoteButtonEvent(int buttonCode);
|
||||
|
||||
// Motion sensor
|
||||
// Motion Sensor Events
|
||||
void onMotionSensorReachableChanged(bool reachable);
|
||||
void onMotionSensorBatteryLevelChanged(int batteryLevel);
|
||||
void onMotionSensorTemperatureChanged(double temperature);
|
||||
void onMotionSensorPresenceChanged(bool presence);
|
||||
void onMotionSensorLightIntensityChanged(double lightIntensity);
|
||||
|
||||
private slots:
|
||||
void networkManagerReplyReady();
|
||||
void onDeviceNameChanged();
|
||||
|
||||
private:
|
||||
@ -83,66 +81,18 @@ private:
|
||||
};
|
||||
void finishDiscovery(DiscoveryJob* job);
|
||||
|
||||
PluginTimer *m_pluginTimer1Sec = nullptr;
|
||||
PluginTimer *m_pluginTimer5Sec = nullptr;
|
||||
PluginTimer *m_pluginTimer15Sec = nullptr;
|
||||
|
||||
QHash<QNetworkReply *, PairingInfo *> m_pairingRequests;
|
||||
QHash<QNetworkReply *, PairingInfo *> m_informationRequests;
|
||||
|
||||
QHash<DeviceId, BridgeConnection *> m_bridgeConnections;
|
||||
|
||||
QList<HueBridge *> m_unconfiguredBridges;
|
||||
QList<HueLight *> m_unconfiguredLights;
|
||||
|
||||
QHash<QNetworkReply *, Device *> m_lightRefreshRequests;
|
||||
QHash<QNetworkReply *, Device *> m_setNameRequests;
|
||||
QHash<QNetworkReply *, Device *> m_bridgeRefreshRequests;
|
||||
QHash<QNetworkReply *, Device *> m_lightsRefreshRequests;
|
||||
QHash<QNetworkReply *, Device *> m_sensorsRefreshRequests;
|
||||
QHash<QNetworkReply *, Device *> m_bridgeLightsDiscoveryRequests;
|
||||
QHash<QNetworkReply *, Device *> m_bridgeSensorsDiscoveryRequests;
|
||||
QHash<QNetworkReply *, Device *> m_bridgeSearchDevicesRequests;
|
||||
|
||||
QHash<QNetworkReply *, QPair<Device *, ActionId> > m_asyncActions;
|
||||
|
||||
QHash<HueBridge *, Device *> m_bridges;
|
||||
QHash<HueLight *, Device *> m_lights;
|
||||
QHash<HueRemote *, Device *> m_remotes;
|
||||
QHash<HueMotionSensor *, Device *> m_motionSensors;
|
||||
|
||||
void refreshLight(Device *device);
|
||||
void refreshBridge(Device *device);
|
||||
|
||||
void refreshLights(HueBridge *bridge);
|
||||
void refreshSensors(HueBridge *bridge);
|
||||
|
||||
void discoverBridgeDevices(HueBridge *bridge);
|
||||
void searchNewDevices(HueBridge *bridge, const QString &serialNumber);
|
||||
|
||||
void setLightName(Device *device);
|
||||
void setRemoteName(Device *device);
|
||||
|
||||
void processNUpnpResponse(const QByteArray &data);
|
||||
void processBridgeLightDiscoveryResponse(Device *device, const QByteArray &data);
|
||||
void processBridgeSensorDiscoveryResponse(Device *device, const QByteArray &data);
|
||||
void processLightRefreshResponse(Device *device, const QByteArray &data);
|
||||
void processBridgeRefreshResponse(Device *device, const QByteArray &data);
|
||||
void processLightsRefreshResponse(Device *device, const QByteArray &data);
|
||||
void processSensorsRefreshResponse(Device *device, const QByteArray &data);
|
||||
void processSetNameResponse(Device *device, const QByteArray &data);
|
||||
void processPairingResponse(PairingInfo *pairingInfo, const QByteArray &data);
|
||||
void processInformationResponse(PairingInfo *pairingInfo, const QByteArray &data);
|
||||
void processActionResponse(Device *device, const ActionId actionId, const QByteArray &data);
|
||||
|
||||
void bridgeReachableChanged(Device *device, const bool &reachable);
|
||||
|
||||
Device* bridgeForBridgeId(const QString &id);
|
||||
bool lightAlreadyAdded(const QString &uuid);
|
||||
bool sensorAlreadyAdded(const QString &uuid);
|
||||
|
||||
int brightnessToPercentage(int brightness);
|
||||
int percentageToBrightness(int percentage);
|
||||
|
||||
void abortRequests(QHash<QNetworkReply *, Device *> requestList, Device* device);
|
||||
};
|
||||
|
||||
#endif // DEVICEPLUGINBOBLIGHT_H
|
||||
#endif // DEVICEPLUGINPHILIPSHUE_H
|
||||
|
||||
@ -103,7 +103,6 @@ private:
|
||||
|
||||
signals:
|
||||
void stateChanged();
|
||||
|
||||
};
|
||||
|
||||
#endif // HUELIGHT_H
|
||||
|
||||
@ -13,7 +13,8 @@ SOURCES += \
|
||||
huemotionsensor.cpp \
|
||||
pairinginfo.cpp \
|
||||
hueremote.cpp \
|
||||
huedevice.cpp
|
||||
huedevice.cpp \
|
||||
bridgeconnection.cpp
|
||||
|
||||
HEADERS += \
|
||||
devicepluginphilipshue.h \
|
||||
@ -25,7 +26,8 @@ HEADERS += \
|
||||
huemotionsensor.h \
|
||||
pairinginfo.h \
|
||||
hueremote.h \
|
||||
huedevice.h
|
||||
huedevice.h \
|
||||
bridgeconnection.h
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user