diff --git a/plugins/deviceplugins/philipshue/devicepluginphilipshue.cpp b/plugins/deviceplugins/philipshue/devicepluginphilipshue.cpp index 25e51937..8015d237 100644 --- a/plugins/deviceplugins/philipshue/devicepluginphilipshue.cpp +++ b/plugins/deviceplugins/philipshue/devicepluginphilipshue.cpp @@ -136,7 +136,6 @@ DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *dev bridge->setZigbeeChannel(device->paramValue("zigbee channel").toInt()); m_bridges.insert(bridge, device); - return DeviceManager::DeviceSetupStatusSuccess; } @@ -168,15 +167,27 @@ DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *dev device->setName(hueLight->name()); m_lights.insert(hueLight, device); - refreshLight(device); + setName(device, device->paramValue("name").toString()); } - return DeviceManager::DeviceSetupStatusSuccess; + return DeviceManager::DeviceSetupStatusAsync; } void DevicePluginPhilipsHue::deviceRemoved(Device *device) { - Q_UNUSED(device) + if (device->deviceClassId() == hueBridgeDeviceClassId) { + HueBridge *bridge = m_bridges.key(device); + m_bridges.remove(bridge); + bridge->deleteLater(); + + // TODO: remove lights from this bridge (over GuhCore) + } + + if (device->deviceClassId() == hueLightDeviceClassId) { + HueLight *light = m_lights.key(device); + m_lights.remove(light); + light->deleteLater(); + } } void DevicePluginPhilipsHue::upnpDiscoveryFinished(const QList &upnpDeviceDescriptorList) @@ -240,9 +251,7 @@ void DevicePluginPhilipsHue::networkManagerReplyReady(QNetworkReply *reply) reply->deleteLater(); return; } - - QByteArray data = reply->readAll(); - processPairingResponse(pairingInfo, data); + processPairingResponse(pairingInfo, reply->readAll()); } else if (m_informationRequests.keys().contains(reply)) { PairingInfo pairingInfo = m_informationRequests.take(reply); @@ -253,9 +262,8 @@ void DevicePluginPhilipsHue::networkManagerReplyReady(QNetworkReply *reply) reply->deleteLater(); return; } + processInformationResponse(pairingInfo, reply->readAll()); - QByteArray data = reply->readAll(); - processInformationResponse(pairingInfo, data); } else if (m_lightRefreshRequests.keys().contains(reply)) { Device *device = m_lightRefreshRequests.take(reply); @@ -266,9 +274,7 @@ void DevicePluginPhilipsHue::networkManagerReplyReady(QNetworkReply *reply) reply->deleteLater(); return; } - - QByteArray data = reply->readAll(); - processLightRefreshResponse(device, data); + processLightRefreshResponse(device, reply->readAll()); } else if (m_bridgeRefreshRequests.keys().contains(reply)) { @@ -280,9 +286,7 @@ void DevicePluginPhilipsHue::networkManagerReplyReady(QNetworkReply *reply) reply->deleteLater(); return; } - - QByteArray data = reply->readAll(); - processBridgeRefreshResponse(device, data); + processBridgeRefreshResponse(device, reply->readAll()); } else if (m_asyncActions.keys().contains(reply)) { @@ -297,6 +301,17 @@ void DevicePluginPhilipsHue::networkManagerReplyReady(QNetworkReply *reply) QByteArray data = reply->readAll(); processActionResponse(actionInfo.first, actionInfo.second, data); + } else if (m_lightSetNameRequests.keys().contains(reply)) { + + Device *device = m_lightSetNameRequests.take(reply); + + // check HTTP status code + if (status != 200) { + qWarning() << "Set name of Hue Light request error:" << status << reply->errorString(); + reply->deleteLater(); + return; + } + processSetNameResponse(device, reply->readAll()); } reply->deleteLater(); @@ -347,11 +362,8 @@ DeviceManager::DeviceError DevicePluginPhilipsHue::executeAction(Device *device, } if (device->deviceClassId() == hueBridgeDeviceClassId) { - - - - - return DeviceManager::DeviceErrorActionTypeNotFound; + // TODO: search if a light was added or removed from bridge + return DeviceManager::DeviceErrorNoError; } return DeviceManager::DeviceErrorDeviceClassNotFound; } @@ -395,6 +407,36 @@ void DevicePluginPhilipsHue::refreshBridge(Device *device) m_bridgeRefreshRequests.insert(reply, device); } +void DevicePluginPhilipsHue::setName(Device *device, QString name) +{ + if (device->deviceClassId() == hueLightDeviceClassId) { + HueLight *light = m_lights.key(device); + + QVariantMap requestMap; + requestMap.insert("name", name); + QJsonDocument jsonDoc = QJsonDocument::fromVariant(requestMap); + + QNetworkRequest request(QUrl("http://" + light->hostAddress().toString() + "/api/" + light->username() + + "/lights/" + QString::number(light->lightId()))); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + + QNetworkReply *reply = networkManagerPut(request,jsonDoc.toJson()); + m_lightSetNameRequests.insert(reply, device); + } else if (device->deviceClassId() == hueBridgeDeviceClassId) { + HueBridge *bridge = m_bridges.key(device); + + QVariantMap requestMap; + requestMap.insert("name", name); + QJsonDocument jsonDoc = QJsonDocument::fromVariant(requestMap); + + QNetworkRequest request(QUrl("http://" + bridge->hostAddress().toString() + "/api/" + bridge->username() + "/config")); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + + QNetworkReply *reply = networkManagerPut(request,jsonDoc.toJson()); + m_lightSetNameRequests.insert(reply, device); + } +} + void DevicePluginPhilipsHue::processLightRefreshResponse(Device *device, const QByteArray &data) { QJsonParseError error; @@ -445,6 +487,31 @@ void DevicePluginPhilipsHue::processBridgeRefreshResponse(Device *device, const } } +void DevicePluginPhilipsHue::processSetNameResponse(Device *device, const QByteArray &data) +{ + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); + + // check JSON error + if (error.error != QJsonParseError::NoError) { + qWarning() << "Hue Bridge json error in response" << error.errorString(); + emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure); + return; + } + + // check pairing error + if (data.contains("error")) { + qWarning() << "Failed to set name of Hue:" << jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString(); + emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure); + return; + } + + emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess); + if (device->deviceClassId() == hueLightDeviceClassId) { + refreshLight(device); + } +} + void DevicePluginPhilipsHue::processPairingResponse(const DevicePluginPhilipsHue::PairingInfo &pairingInfo, const QByteArray &data) { QJsonParseError error; diff --git a/plugins/deviceplugins/philipshue/devicepluginphilipshue.h b/plugins/deviceplugins/philipshue/devicepluginphilipshue.h index 61859395..dc5f02b8 100644 --- a/plugins/deviceplugins/philipshue/devicepluginphilipshue.h +++ b/plugins/deviceplugins/philipshue/devicepluginphilipshue.h @@ -72,6 +72,7 @@ private: QList m_unconfiguredLights; QHash m_lightRefreshRequests; + QHash m_lightSetNameRequests; QHash m_bridgeRefreshRequests; QHash > m_asyncActions; @@ -81,8 +82,11 @@ private: void refreshLight(Device *device); void refreshBridge(Device *device); + void setName(Device *device, QString name); + void processLightRefreshResponse(Device *device, const QByteArray &data); void processBridgeRefreshResponse(Device *device, const QByteArray &data); + void processSetNameResponse(Device *device, const QByteArray &data); void processPairingResponse(const PairingInfo &pairingInfo, const QByteArray &data); void processInformationResponse(const PairingInfo &pairingInfo, const QByteArray &data); void processActionResponse(Device *device, const ActionId actionId, const QByteArray &data); diff --git a/plugins/deviceplugins/philipshue/devicepluginphilipshue.json b/plugins/deviceplugins/philipshue/devicepluginphilipshue.json index ccdc0358..9cf1546b 100644 --- a/plugins/deviceplugins/philipshue/devicepluginphilipshue.json +++ b/plugins/deviceplugins/philipshue/devicepluginphilipshue.json @@ -12,7 +12,7 @@ "name": "Hue Bridge", "createMethods": ["discovery"], "setupMethod": "pushButton", - "pairingInfo": "Please press the button on the Hue Bridge before you continue", + "pairingInfo": "Please press within 30 seconds the button on the Hue Bridge before you continue", "paramTypes": [ { "name": "name", @@ -55,13 +55,6 @@ "name": "reachable", "type": "bool" } - ], - "actionTypes": [ - { - "id": "001476ce-2f17-475f-939f-d4234751ef35", - "idName": "searchLamps", - "name": "search new lamps" - } ] }, {