Updated philipshue plugin

This commit is contained in:
Michael Zanetti 2019-09-19 17:54:32 +02:00
parent bc3d2f3b4a
commit 6bcdc50d13
6 changed files with 262 additions and 509 deletions

View File

@ -74,18 +74,35 @@ void DevicePluginPhilipsHue::init()
}
Device::DeviceError DevicePluginPhilipsHue::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
void DevicePluginPhilipsHue::discoverDevices(DeviceDiscoveryInfo *info)
{
Q_UNUSED(params)
Q_UNUSED(deviceClassId)
// We're starting a UpnpDiscovery and a NUpnpDiscovery.
// For that, we create a tracking object holding pointers to both of those discoveries.
// Both discoveries add their results to a temporary list.
// Once a discovery is finished, it will remove itself from the tracking object.
// When both discoveries are gone from the tracking object, the results are processed
// deduped (a bridge can be found on both discovieries) and handed over to the DeviceDiscoveryInfo.
// Tracking object
DiscoveryJob *discovery = new DiscoveryJob();
m_discoveries.insert(info, discovery);
// clean up the discovery job when the DeviceDiscoveryInfo is destroyed (either finished or cancelled)
connect(info, &DeviceDiscoveryInfo::destroyed, this, [this, info](){
delete m_discoveries.take(info);
});
qCDebug(dcPhilipsHue()) << "Starting UPnP discovery...";
UpnpDiscoveryReply *upnpReply = hardwareManager()->upnpDiscovery()->discoverDevices("libhue:idl");
discovery->upnpReply = upnpReply;
connect(upnpReply, &UpnpDiscoveryReply::finished, this, [this, upnpReply, discovery](){
upnpReply->deleteLater();
// Always clean up the upnp discovery
connect(upnpReply, &UpnpDiscoveryReply::finished, upnpReply, &UpnpDiscoveryReply::deleteLater);
// Process results if info is still around
connect(upnpReply, &UpnpDiscoveryReply::finished, info, [this, upnpReply, discovery](){
// Indicate we're done...
discovery->upnpReply = nullptr;
if (upnpReply->error() != UpnpDiscoveryReply::UpnpDiscoveryReplyErrorNoError) {
@ -105,10 +122,6 @@ Device::DeviceError DevicePluginPhilipsHue::discoverDevices(const DeviceClassId
}
params.append(Param(bridgeDeviceHostParamTypeId, upnpDevice.hostAddress().toString()));
params.append(Param(bridgeDeviceIdParamTypeId, bridgeId));
// Not known yet...
params.append(Param(bridgeDeviceApiKeyParamTypeId, QString()));
params.append(Param(bridgeDeviceMacParamTypeId, QString()));
params.append(Param(bridgeDeviceZigbeeChannelParamTypeId, -1));
descriptor.setParams(params);
qCDebug(dcPhilipsHue()) << "UPnP: Found Hue bridge:" << bridgeId;
discovery->results.append(descriptor);
@ -123,7 +136,12 @@ Device::DeviceError DevicePluginPhilipsHue::discoverDevices(const DeviceClassId
QNetworkRequest request(QUrl("https://www.meethue.com/api/nupnp"));
QNetworkReply *nUpnpReply = hardwareManager()->networkManager()->get(request);
discovery->nUpnpReply = nUpnpReply;
connect(nUpnpReply, &QNetworkReply::finished, this, [this, nUpnpReply, discovery](){
// Always clean up the network reply
connect(nUpnpReply, &QNetworkReply::finished, nUpnpReply, &QNetworkReply::deleteLater);
// Process results if info is still around
connect(nUpnpReply, &QNetworkReply::finished, info, [this, nUpnpReply, discovery](){
nUpnpReply->deleteLater();
discovery->nUpnpReply = nullptr;
@ -136,6 +154,7 @@ Device::DeviceError DevicePluginPhilipsHue::discoverDevices(const DeviceClassId
QJsonDocument jsonDoc = QJsonDocument::fromJson(nUpnpReply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcPhilipsHue) << "N-UPNP discovery JSON error in response" << error.errorString();
finishDiscovery(discovery);
return;
}
@ -150,9 +169,6 @@ Device::DeviceError DevicePluginPhilipsHue::discoverDevices(const DeviceClassId
}
params.append(Param(bridgeDeviceHostParamTypeId, bridgeMap.value("internalipaddress").toString()));
params.append(Param(bridgeDeviceIdParamTypeId, bridgeId));
params.append(Param(bridgeDeviceApiKeyParamTypeId, QString()));
params.append(Param(bridgeDeviceMacParamTypeId, QString()));
params.append(Param(bridgeDeviceZigbeeChannelParamTypeId, -1));
descriptor.setParams(params);
qCDebug(dcPhilipsHue()) << "N-UPnP: Found Hue bridge:" << bridgeId;
discovery->results.append(descriptor);
@ -160,48 +176,93 @@ Device::DeviceError DevicePluginPhilipsHue::discoverDevices(const DeviceClassId
finishDiscovery(discovery);
});
return Device::DeviceErrorAsync;
}
Device::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *device)
void DevicePluginPhilipsHue::finishDiscovery(DevicePluginPhilipsHue::DiscoveryJob *job)
{
if (job->upnpReply || job->nUpnpReply) {
// still pending...
return;
}
QHash<QString, DeviceDescriptor> results;
foreach (DeviceDescriptor result, job->results) {
// dedupe
QString bridgeId = result.params().paramValue(bridgeDeviceIdParamTypeId).toString();
if (results.contains(bridgeId)) {
qCDebug(dcPhilipsHue()) << "Discarding duplicate search result" << bridgeId;
continue;
}
Device *dev = bridgeForBridgeId(bridgeId);
if (dev) {
qCDebug(dcPhilipsHue()) << "Bridge already added in system:" << bridgeId;
result.setDeviceId(dev->id());
}
results.insert(bridgeId, result);
}
DeviceDiscoveryInfo *info = m_discoveries.key(job);
info->addDeviceDescriptors(results.values());
info->finish(Device::DeviceErrorNoError);
}
void DevicePluginPhilipsHue::startPairing(DevicePairingInfo *info)
{
Q_ASSERT_X(info->deviceClassId() == bridgeDeviceClassId, "DevicePluginPhilipsHue::startPairing", "Unexpected device class.");
info->finish(Device::DeviceErrorNoError, QT_TR_NOOP("Please press the button on the Hue Bridge within 30 seconds before you continue"));
}
void DevicePluginPhilipsHue::setupDevice(DeviceSetupInfo *info)
{
Device *device = info->device();
// Update the name on the bridge if the user changes the device name
connect(device, &Device::nameChanged, this, &DevicePluginPhilipsHue::onDeviceNameChanged);
// hue bridge
if (device->deviceClassId() == bridgeDeviceClassId) {
// unconfigured bridges (from pairing)
foreach (HueBridge *b, m_unconfiguredBridges) {
if (b->hostAddress().toString() == device->paramValue(bridgeDeviceHostParamTypeId).toString()) {
m_unconfiguredBridges.removeAll(b);
qCDebug(dcPhilipsHue) << "Setup unconfigured Hue Bridge" << b->name();
// Set data which was not known during discovery
device->setParamValue(bridgeDeviceApiKeyParamTypeId, b->apiKey());
device->setParamValue(bridgeDeviceZigbeeChannelParamTypeId, b->zigbeeChannel());
device->setParamValue(bridgeDeviceMacParamTypeId, b->macAddress());
m_bridges.insert(b, device);
device->setStateValue(bridgeConnectedStateTypeId, true);
discoverBridgeDevices(b);
return Device::DeviceSetupStatusSuccess;
}
}
// Loaded bridge
qCDebug(dcPhilipsHue) << "Setup Hue Bridge" << device->params();
pluginStorage()->beginGroup(device->id().toString());
QString apiKey = pluginStorage()->value("apiKey").toString();
pluginStorage()->endGroup();
// For legacy reasons we might not have the api key in the pluginstorage yet. Check if there is a key in the device params.
if (apiKey.isEmpty()) {
qCWarning(dcPhilipsHue()) << "Loading api key from device params!";
// Used to be in json, not any more.
ParamTypeId bridgeDeviceApiKeyParamTypeId = ParamTypeId("{8bf5776a-d5a6-4600-8b27-481f0d803a8f}");
apiKey = device->paramValue(bridgeDeviceApiKeyParamTypeId).toString();
}
if (apiKey.isEmpty()) {
qCWarning(dcPhilipsHue()) << "Failed to load api key";
info->finish(Device::DeviceErrorAuthenticationFailure, QT_TR_NOOP("Not authenticated to bridge. Please reconfigure the device."));
return;
}
HueBridge *bridge = new HueBridge(this);
bridge->setId(device->paramValue(bridgeDeviceIdParamTypeId).toString());
bridge->setApiKey(device->paramValue(bridgeDeviceApiKeyParamTypeId).toString());
bridge->setApiKey(apiKey);
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);
return Device::DeviceSetupStatusSuccess;
return info->finish(Device::DeviceErrorNoError);
}
// At this point we need to have a bridge or we can't continue anyways
HueBridge *bridge = m_bridges.key(myDevices().findById(device->parentId()));
if (!bridge) {
qCWarning(dcPhilipsHue()) << "No hue bridge set up. Cannot continue.";
info->finish(Device::DeviceErrorHardwareNotAvailable);
return;
}
// Hue color light
if (device->deviceClassId() == colorLightDeviceClassId) {
qCDebug(dcPhilipsHue) << "Setup Hue color light" << device->params();
@ -220,7 +281,7 @@ Device::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *device)
refreshLight(device);
return Device::DeviceSetupStatusSuccess;
return info->finish(Device::DeviceErrorNoError);
}
// Hue color temperature light
@ -241,7 +302,7 @@ Device::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *device)
refreshLight(device);
return Device::DeviceSetupStatusSuccess;
return info->finish(Device::DeviceErrorNoError);
}
// Hue white light
@ -287,7 +348,7 @@ Device::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *device)
m_lights.insert(hueLight, device);
refreshLight(device);
return Device::DeviceSetupStatusSuccess;
return info->finish(Device::DeviceErrorNoError);
}
// Hue remote
@ -332,7 +393,7 @@ Device::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *device)
connect(hueRemote, &HueRemote::buttonPressed, this, &DevicePluginPhilipsHue::onRemoteButtonEvent);
m_remotes.insert(hueRemote, device);
return Device::DeviceSetupStatusSuccess;
return info->finish(Device::DeviceErrorNoError);
}
// Hue tap
@ -346,7 +407,7 @@ Device::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *device)
connect(hueTap, &HueRemote::buttonPressed, this, &DevicePluginPhilipsHue::onRemoteButtonEvent);
m_remotes.insert(hueTap, device);
return Device::DeviceSetupStatusSuccess;
return info->finish(Device::DeviceErrorNoError);
}
// Hue Motion sensor
@ -378,7 +439,7 @@ Device::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *device)
m_motionSensors.insert(motionSensor, device);
return Device::DeviceSetupStatusSuccess;
return info->finish(Device::DeviceErrorNoError);
}
// Hue Outdoor sensor
@ -410,12 +471,10 @@ Device::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *device)
m_motionSensors.insert(outdoorSensor, device);
return Device::DeviceSetupStatusSuccess;
return info->finish(Device::DeviceErrorNoError);
}
qCWarning(dcPhilipsHue()) << "Unhandled setupDevice call" << device->deviceClassId();
return Device::DeviceSetupStatusFailure;
}
void DevicePluginPhilipsHue::deviceRemoved(Device *device)
@ -456,31 +515,65 @@ void DevicePluginPhilipsHue::deviceRemoved(Device *device)
}
}
Device::DeviceSetupStatus DevicePluginPhilipsHue::confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params, const QString &secret)
void DevicePluginPhilipsHue::confirmPairing(DevicePairingInfo *info, const QString &username, const QString &secret)
{
Q_UNUSED(username)
Q_UNUSED(secret)
qCDebug(dcPhilipsHue()) << "Confirming pairing for transactionId" << pairingTransactionId;
if (deviceClassId != bridgeDeviceClassId)
return Device::DeviceSetupStatusFailure;
PairingInfo *pairingInfo = new PairingInfo(this);
pairingInfo->setPairingTransactionId(pairingTransactionId);
pairingInfo->setHost(QHostAddress(params.paramValue(bridgeDeviceHostParamTypeId).toString()));
QVariantMap deviceTypeParam;
deviceTypeParam.insert("devicetype", "nymea");
QJsonDocument jsonDoc = QJsonDocument::fromVariant(deviceTypeParam);
QNetworkRequest request(QUrl("http://" + pairingInfo->host().toString() + "/api"));
QString host = info->params().paramValue(bridgeDeviceHostParamTypeId).toString();
QNetworkRequest request(QUrl("http://" + host + "/api"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply *reply = hardwareManager()->networkManager()->post(request, jsonDoc.toJson());
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
m_pairingRequests.insert(reply, pairingInfo);
connect(reply, &QNetworkReply::finished, info, [this, info, reply](){
if (reply->error() != QNetworkReply::NoError) {
info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Error connecting to hue bridge."));
return;
}
QByteArray data = reply->readAll();
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
return Device::DeviceSetupStatusAsync;
// check JSON error
if (error.error != QJsonParseError::NoError) {
qCWarning(dcPhilipsHue) << "Hue Bridge json error in response" << error.errorString();
info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Received unexpected data from hue bridge."));
return;
}
// check response error
if (data.contains("error")) {
if (!jsonDoc.toVariant().toList().isEmpty()) {
qCWarning(dcPhilipsHue) << "Failed to pair Hue Bridge:" << jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString();
} else {
qCWarning(dcPhilipsHue) << "Failed to pair Hue Bridge: Invalid error message format";
}
info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("An error happened pairing the hue bridge."));
return;
}
QString apiKey = jsonDoc.toVariant().toList().first().toMap().value("success").toMap().value("username").toString();
if (apiKey.isEmpty()) {
qCWarning(dcPhilipsHue) << "Failed to pair Hue Bridge: did not get any key from the bridge";
return info->finish(Device::DeviceErrorAuthenticationFailure, QT_TR_NOOP("The hue bridge has rejected the connection request."));
}
qCDebug(dcPhilipsHue) << "Got api key from bridge:" << apiKey;
// All good. Store the API key
pluginStorage()->beginGroup(info->deviceId().toString());
pluginStorage()->setValue("apiKey", apiKey);
pluginStorage()->endGroup();
info->finish(Device::DeviceErrorNoError);
});
}
void DevicePluginPhilipsHue::networkManagerReplyReady()
@ -493,29 +586,7 @@ void DevicePluginPhilipsHue::networkManagerReplyReady()
// 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)) {
if (m_bridgeLightsDiscoveryRequests.contains(reply)) {
Device *device = m_bridgeLightsDiscoveryRequests.take(reply);
// check HTTP status code
@ -598,18 +669,6 @@ void DevicePluginPhilipsHue::networkManagerReplyReady()
}
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);
@ -637,151 +696,71 @@ void DevicePluginPhilipsHue::onDeviceNameChanged()
}
}
void DevicePluginPhilipsHue::finishDiscovery(DevicePluginPhilipsHue::DiscoveryJob *job)
void DevicePluginPhilipsHue::executeAction(DeviceActionInfo *info)
{
if (job->upnpReply || job->nUpnpReply) {
// still pending...
return;
}
QHash<QString, DeviceDescriptor> results;
foreach (DeviceDescriptor result, job->results) {
// dedupe
QString bridgeId = result.params().paramValue(bridgeDeviceIdParamTypeId).toString();
if (results.contains(bridgeId)) {
qCDebug(dcPhilipsHue()) << "Discarding duplicate search result" << bridgeId;
continue;
}
Device *dev = bridgeForBridgeId(bridgeId);
if (dev) {
qCDebug(dcPhilipsHue()) << "Bridge already added in system:" << bridgeId;
result.setDeviceId(dev->id());
}
results.insert(bridgeId, result);
Device *device = info->device();
Action action = info->action();
}
emit devicesDiscovered(bridgeDeviceClassId, results.values());
delete job;
}
Device::DeviceError DevicePluginPhilipsHue::executeAction(Device *device, const Action &action)
{
qCDebug(dcPhilipsHue) << "Execute action" << action.actionTypeId() << action.params();
// Color light
if (device->deviceClassId() == colorLightDeviceClassId) {
QNetworkReply *reply = nullptr;
// lights
if (device->deviceClassId() == colorLightDeviceClassId ||
device->deviceClassId() == colorTemperatureLightDeviceClassId ||
device->deviceClassId() == dimmableLightDeviceClassId) {
HueLight *light = m_lights.key(device);
if (!light->reachable()) {
qCWarning(dcPhilipsHue) << "Light" << light->name() << "not reachable";
return Device::DeviceErrorHardwareNotAvailable;
return info->finish(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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
} 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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
} 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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
} 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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
} 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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
} 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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
}
return Device::DeviceErrorActionTypeNotFound;
}
// Color temperature light
if (device->deviceClassId() == colorTemperatureLightDeviceClassId) {
HueLight *light = m_lights.key(device);
if (!light->reachable()) {
qCWarning(dcPhilipsHue) << "Light" << light->name() << "not reachable";
return Device::DeviceErrorHardwareNotAvailable;
}
if (action.actionTypeId() == colorTemperatureLightPowerActionTypeId) {
else 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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
} 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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
} 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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
} 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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
}
return Device::DeviceErrorActionTypeNotFound;
}
// Dimmable light
if (device->deviceClassId() == dimmableLightDeviceClassId) {
HueLight *light = m_lights.key(device);
if (!light->reachable()) {
qCWarning(dcPhilipsHue) << "Light" << light->name() << "not reachable";
return Device::DeviceErrorHardwareNotAvailable;
}
if (action.actionTypeId() == dimmableLightPowerActionTypeId) {
else if (action.actionTypeId() == dimmableLightPowerActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = light->createSetPowerRequest(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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
} 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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
} 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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
}
return Device::DeviceErrorActionTypeNotFound;
}
// Hue bridge
@ -789,28 +768,64 @@ Device::DeviceError DevicePluginPhilipsHue::executeAction(Device *device, const
HueBridge *bridge = m_bridges.key(device);
if (!device->stateValue(bridgeConnectedStateTypeId).toBool()) {
qCWarning(dcPhilipsHue) << "Bridge" << bridge->hostAddress().toString() << "not reachable";
return Device::DeviceErrorHardwareNotAvailable;
return info->finish(Device::DeviceErrorHardwareNotAvailable);
}
if (action.actionTypeId() == bridgeSearchNewDevicesActionTypeId) {
searchNewDevices(bridge, action.param(bridgeSearchNewDevicesActionSerialParamTypeId).value().toString());
return Device::DeviceErrorNoError;
return info->finish(Device::DeviceErrorNoError);
} else if (action.actionTypeId() == bridgeCheckForUpdatesActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = bridge->createCheckUpdatesRequest();
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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
} else if (action.actionTypeId() == bridgeUpgradeActionTypeId) {
QPair<QNetworkRequest, QByteArray> request = bridge->createUpgradeRequest();
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()));
return Device::DeviceErrorAsync;
reply = hardwareManager()->networkManager()->put(request.first, request.second);
}
return Device::DeviceErrorActionTypeNotFound;
}
return Device::DeviceErrorDeviceClassNotFound;
if (!reply) {
qCWarning(dcPhilipsHue()) << "Unhandled Hue action! Plugin bug!";
Q_ASSERT_X(false, "HuePlugin", "Unhandled action");
info->finish(Device::DeviceErrorUnsupportedFeature);
return;
}
// Always clean up the reply when it finishes
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
// Handle response if info is still around
connect(reply, &QNetworkReply::finished, info, [this, info, reply](){
if (reply->error() != QNetworkReply::NoError) {
info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Error sending command to hue bridge."));
return;
}
QByteArray data = reply->readAll();
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(dcPhilipsHue) << "Hue Bridge json error in response" << error.errorString();
info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Received unexpected data from hue bridge."));
return;
}
if (data.contains("error")) {
if (!jsonDoc.toVariant().toList().isEmpty()) {
qCWarning(dcPhilipsHue) << "Failed to execute Hue action:" << jsonDoc.toJson(); //jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString();
} else {
qCWarning(dcPhilipsHue) << "Failed to execute Hue action: Invalid error message format";
}
info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("An unexpected error happened when sending the command to the hue bridge."));
return;
}
if (info->device()->deviceClassId() != bridgeDeviceClassId) {
m_lights.key(info->device())->processActionResponse(jsonDoc.toVariant().toList());
}
info->finish(Device::DeviceErrorNoError);
});
}
void DevicePluginPhilipsHue::lightStateChanged()
@ -1089,9 +1104,7 @@ void DevicePluginPhilipsHue::processBridgeLightDiscoveryResponse(Device *device,
}
// Create Lights if not already added
QList<DeviceDescriptor> colorLightDescriptors;
QList<DeviceDescriptor> colorTemperatureLightDescriptors;
QList<DeviceDescriptor> dimmableLightDescriptors;
DeviceDescriptors descriptors;
QVariantMap lightsMap = jsonDoc.toVariant().toMap();
foreach (QString lightId, lightsMap.keys()) {
@ -1111,7 +1124,7 @@ void DevicePluginPhilipsHue::processBridgeLightDiscoveryResponse(Device *device,
params.append(Param(dimmableLightDeviceUuidParamTypeId, uuid));
params.append(Param(dimmableLightDeviceLightIdParamTypeId, lightId));
descriptor.setParams(params);
dimmableLightDescriptors.append(descriptor);
descriptors.append(descriptor);
qCDebug(dcPhilipsHue) << "Found new dimmable light" << lightMap.value("name").toString() << model;
} else if (lightMap.value("type").toString() == "Color temperature light") {
@ -1122,7 +1135,7 @@ void DevicePluginPhilipsHue::processBridgeLightDiscoveryResponse(Device *device,
params.append(Param(colorTemperatureLightDeviceUuidParamTypeId, uuid));
params.append(Param(colorTemperatureLightDeviceLightIdParamTypeId, lightId));
descriptor.setParams(params);
colorTemperatureLightDescriptors.append(descriptor);
descriptors.append(descriptor);
qCDebug(dcPhilipsHue) << "Found new color temperature light" << lightMap.value("name").toString() << model;
} else {
@ -1133,17 +1146,14 @@ void DevicePluginPhilipsHue::processBridgeLightDiscoveryResponse(Device *device,
params.append(Param(colorLightDeviceUuidParamTypeId, uuid));
params.append(Param(colorLightDeviceLightIdParamTypeId, lightId));
descriptor.setParams(params);
colorLightDescriptors.append(descriptor);
descriptors.append(descriptor);
qCDebug(dcPhilipsHue) << "Found new color light" << lightMap.value("name").toString() << model;
}
}
if (!colorLightDescriptors.isEmpty())
emit autoDevicesAppeared(colorLightDeviceClassId, colorLightDescriptors);
if (!colorTemperatureLightDescriptors.isEmpty())
emit autoDevicesAppeared(colorTemperatureLightDeviceClassId, colorTemperatureLightDescriptors);
if (!dimmableLightDescriptors.isEmpty())
emit autoDevicesAppeared(dimmableLightDeviceClassId, dimmableLightDescriptors);
if (!descriptors.isEmpty()) {
emit autoDevicesAppeared(descriptors);
}
}
void DevicePluginPhilipsHue::processBridgeSensorDiscoveryResponse(Device *device, const QByteArray &data)
@ -1187,7 +1197,7 @@ void DevicePluginPhilipsHue::processBridgeSensorDiscoveryResponse(Device *device
params.append(Param(remoteDeviceUuidParamTypeId, uuid));
params.append(Param(remoteDeviceSensorIdParamTypeId, sensorId));
descriptor.setParams(params);
emit autoDevicesAppeared(remoteDeviceClassId, {descriptor});
emit autoDevicesAppeared({descriptor});
qCDebug(dcPhilipsHue) << "Found new remote" << sensorMap.value("name").toString() << model;
} else if (sensorMap.value("type").toString() == "ZGPSwitch") {
DeviceDescriptor descriptor(tapDeviceClassId, sensorMap.value("name").toString(), "Philips Hue Tap", device->id());
@ -1196,7 +1206,7 @@ void DevicePluginPhilipsHue::processBridgeSensorDiscoveryResponse(Device *device
params.append(Param(tapDeviceModelIdParamTypeId, model));
params.append(Param(tapDeviceSensorIdParamTypeId, sensorId));
descriptor.setParams(params);
emit autoDevicesAppeared(tapDeviceClassId, {descriptor});
emit autoDevicesAppeared({descriptor});
qCDebug(dcPhilipsHue()) << "Found hue tap:" << sensorMap << tapDeviceClassId;
} else if (model == "SML001" || model == "SML002") {
@ -1294,7 +1304,7 @@ void DevicePluginPhilipsHue::processBridgeSensorDiscoveryResponse(Device *device
params.append(Param(motionSensorDeviceSensorIdLightParamTypeId, motionSensor->lightSensorId()));
descriptor.setParams(params);
qCDebug(dcPhilipsHue()) << "Found new motion sensor" << baseUuid << motionSensorDeviceClassId;
emit autoDevicesAppeared(motionSensorDeviceClassId, {descriptor});
emit autoDevicesAppeared({descriptor});
} else if (motionSensor->modelId() == "SML002") {
DeviceDescriptor descriptor(outdoorSensorDeviceClassId, tr("Philips Hue Outdoor sensor"), baseUuid, device->id());
ParamList params;
@ -1308,7 +1318,7 @@ void DevicePluginPhilipsHue::processBridgeSensorDiscoveryResponse(Device *device
params.append(Param(outdoorSensorDeviceSensorIdLightParamTypeId, motionSensor->lightSensorId()));
descriptor.setParams(params);
qCDebug(dcPhilipsHue()) << "Found new outdoor sensor" << baseUuid << outdoorSensorDeviceClassId;
emit autoDevicesAppeared(outdoorSensorDeviceClassId, {descriptor});
emit autoDevicesAppeared({descriptor});
}
}
@ -1468,7 +1478,6 @@ void DevicePluginPhilipsHue::processSetNameResponse(Device *device, const QByteA
// check JSON error
if (error.error != QJsonParseError::NoError) {
qCWarning(dcPhilipsHue) << "Hue Bridge json error in response" << error.errorString();
emit deviceSetupFinished(device, Device::DeviceSetupStatusFailure);
return;
}
@ -1479,7 +1488,6 @@ void DevicePluginPhilipsHue::processSetNameResponse(Device *device, const QByteA
} else {
qCWarning(dcPhilipsHue) << "Failed to set name of Hue: Invalid error message format";
}
emit deviceSetupFinished(device, Device::DeviceSetupStatusFailure);
return;
}
@ -1488,119 +1496,6 @@ void DevicePluginPhilipsHue::processSetNameResponse(Device *device, const QByteA
}
void DevicePluginPhilipsHue::processPairingResponse(PairingInfo *pairingInfo, 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 pairingFinished(pairingInfo->pairingTransactionId(), Device::DeviceSetupStatusFailure);
pairingInfo->deleteLater();
return;
}
// check response error
if (data.contains("error")) {
if (!jsonDoc.toVariant().toList().isEmpty()) {
qCWarning(dcPhilipsHue) << "Failed to pair Hue Bridge:" << jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString();
} else {
qCWarning(dcPhilipsHue) << "Failed to pair Hue Bridge: Invalid error message format";
}
emit pairingFinished(pairingInfo->pairingTransactionId(), Device::DeviceSetupStatusFailure);
pairingInfo->deleteLater();
return;
}
pairingInfo->setApiKey(jsonDoc.toVariant().toList().first().toMap().value("success").toMap().value("username").toString());
qCDebug(dcPhilipsHue) << "Got api key from bridge:" << pairingInfo->apiKey();
if (pairingInfo->apiKey().isEmpty()) {
qCWarning(dcPhilipsHue) << "Failed to pair Hue Bridge: did not get any key from the bridge";
emit pairingFinished(pairingInfo->pairingTransactionId(), Device::DeviceSetupStatusFailure);
pairingInfo->deleteLater();
return;
}
// Paired successfully, check bridge information
QNetworkRequest request(QUrl("http://" + pairingInfo->host().toString() + "/api/" + pairingInfo->apiKey() + "/config"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::networkManagerReplyReady);
m_informationRequests.insert(reply, pairingInfo);
}
void DevicePluginPhilipsHue::processInformationResponse(PairingInfo *pairingInfo, 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 pairingFinished(pairingInfo->pairingTransactionId(), Device::DeviceSetupStatusFailure);
pairingInfo->deleteLater();
return;
}
QVariantMap response = jsonDoc.toVariant().toMap();
// check response error
if (response.contains("error")) {
qCWarning(dcPhilipsHue) << "Failed to get information from Hue Bridge:" << response.value("error").toMap().value("description").toString();
emit pairingFinished(pairingInfo->pairingTransactionId(), Device::DeviceSetupStatusFailure);
pairingInfo->deleteLater();
return;
}
// create Bridge
HueBridge *bridge = new HueBridge(this);
bridge->setId(response.value("bridgeid").toString());
bridge->setApiKey(pairingInfo->apiKey());
bridge->setHostAddress(pairingInfo->host());
bridge->setApiVersion(response.value("apiversion").toString());
bridge->setSoftwareVersion(response.value("swversion").toString());
bridge->setMacAddress(response.value("mac").toString());
bridge->setName(response.value("name").toString());
bridge->setZigbeeChannel(response.value("zigbeechannel").toInt());
m_unconfiguredBridges.append(bridge);
emit pairingFinished(pairingInfo->pairingTransactionId(), Device::DeviceSetupStatusSuccess);
pairingInfo->deleteLater();
}
void DevicePluginPhilipsHue::processActionResponse(Device *device, const ActionId actionId, 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 actionExecutionFinished(actionId, Device::DeviceErrorHardwareFailure);
return;
}
// check response error
if (data.contains("error")) {
if (!jsonDoc.toVariant().toList().isEmpty()) {
qCWarning(dcPhilipsHue) << "Failed to execute Hue action:" << jsonDoc.toJson(); //jsonDoc.toVariant().toList().first().toMap().value("error").toMap().value("description").toString();
} else {
qCWarning(dcPhilipsHue) << "Failed to execute Hue action: Invalid error message format";
}
emit actionExecutionFinished(actionId, Device::DeviceErrorHardwareFailure);
return;
}
if (device->deviceClassId() != bridgeDeviceClassId)
m_lights.key(device)->processActionResponse(jsonDoc.toVariant().toList());
emit actionExecutionFinished(actionId, Device::DeviceErrorNoError);
}
void DevicePluginPhilipsHue::bridgeReachableChanged(Device *device, const bool &reachable)
{
if (reachable) {

View File

@ -28,7 +28,6 @@
#include "huebridge.h"
#include "huelight.h"
#include "hueremote.h"
#include "pairinginfo.h"
#include "huemotionsensor.h"
#include "huemotionsensor.h"
@ -50,13 +49,12 @@ public:
~DevicePluginPhilipsHue();
void init() override;
Device::DeviceSetupStatus setupDevice(Device *device) override;
Device::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
void discoverDevices(DeviceDiscoveryInfo *info) override;
void startPairing(DevicePairingInfo *info) override;
void confirmPairing(DevicePairingInfo *info, const QString &username, const QString &secret) override;
void setupDevice(DeviceSetupInfo *info) override;
void deviceRemoved(Device *device) override;
Device::DeviceSetupStatus confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params, const QString &secret) override;
public slots:
Device::DeviceError executeAction(Device *device, const Action &action);
void executeAction(DeviceActionInfo *info) override;
private slots:
void lightStateChanged();
@ -79,18 +77,15 @@ private:
public:
UpnpDiscoveryReply* upnpReply;
QNetworkReply* nUpnpReply;
QList<DeviceDescriptor> results;
DeviceDescriptors results;
};
QHash<DeviceDiscoveryInfo*, DiscoveryJob*> m_discoveries;
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;
QList<HueBridge *> m_unconfiguredBridges;
QList<HueLight *> m_unconfiguredLights;
QHash<QNetworkReply *, Device *> m_lightRefreshRequests;
@ -129,8 +124,6 @@ private:
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);

View File

@ -15,16 +15,7 @@
"interfaces": ["gateway"],
"createMethods": ["discovery"],
"setupMethod": "pushButton",
"pairingInfo": "Please press the button on the Hue Bridge within 30 seconds before you continue",
"paramTypes": [
{
"id": "8bf5776a-d5a6-4600-8b27-481f0d803a8f",
"name": "apiKey",
"displayName": "api key",
"type" : "QString",
"inputType": "TextLine",
"readOnly": true
},
{
"id": "1845975b-1184-4440-bc0d-73d53a9f683c",
"name": "host",
@ -33,34 +24,12 @@
"inputType": "IPv4Address",
"readOnly": true
},
{
"id": "2c67203d-a308-45ec-9a08-fc4183c06ff8",
"name": "mac",
"displayName": "mac address",
"type" : "QString",
"inputType": "MacAddress",
"readOnly": true
},
{
"id": "a496feb0-3b7b-46cb-a63a-e063447d6b1d",
"name": "id",
"displayName": "id",
"type" : "QString",
"readOnly": true
},
{
"id": "ea228c4d-975c-4b43-9445-7c9a907c29d6",
"name": "softwareVersion",
"displayName": "software version",
"type" : "QString",
"readOnly": true
},
{
"id": "53170394-956c-4511-b3a8-2c8a502ef1ed",
"name": "zigbeeChannel",
"displayName": "zigbee channel",
"type" : "int",
"readOnly": true
}
],
"stateTypes": [
@ -70,7 +39,8 @@
"displayName": "reachable",
"displayNameEvent": "reachable changed",
"defaultValue": false,
"type": "bool"
"type": "bool",
"cached": false
},
{
"id": "7a230e89-c4ce-4276-90e0-6a9ddb890603",
@ -172,7 +142,8 @@
"displayName": "reachable",
"displayNameEvent": "reachable changed",
"defaultValue": false,
"type": "bool"
"type": "bool",
"cached": false
},
{
"id": "90aaffe5-6a76-47d2-a14a-550f60390245",
@ -300,7 +271,8 @@
"displayName": "reachable",
"displayNameEvent": "reachable changed",
"defaultValue": false,
"type": "bool"
"type": "bool",
"cached": false
},
{
"id": "4e579f6a-e4b3-4876-804a-9fcc066f90f9",
@ -403,7 +375,8 @@
"displayName": "reachable",
"displayNameEvent": "reachable changed",
"defaultValue": false,
"type": "bool"
"type": "bool",
"cached": false
},
{
"id": "5995ecb7-b5e5-4f6a-b4d6-33c93497e5fb",
@ -494,7 +467,8 @@
"displayName": "reachable",
"displayNameEvent": "reachable changed",
"defaultValue": false,
"type": "bool"
"type": "bool",
"cached": false
},
{
"id": "683e493a-9796-4d5e-b0e3-61cb178d5819",
@ -590,7 +564,8 @@
"displayName": "reachable",
"displayNameEvent": "reachable changed",
"defaultValue": false,
"type": "bool"
"type": "bool",
"cached": false
}
],
"eventTypes": [
@ -693,7 +668,8 @@
"displayName": "Reachable",
"displayNameEvent": "Reachable changed",
"defaultValue": false,
"type": "bool"
"type": "bool",
"cached": false
},
{
"id": "19b18531-61e5-4998-89d1-765d740e24eb",
@ -834,7 +810,8 @@
"displayName": "Reachable",
"displayNameEvent": "Reachable changed",
"defaultValue": false,
"type": "bool"
"type": "bool",
"cached": false
},
{
"id": "ac463b30-24af-4352-84da-19a3ffc906bd",

View File

@ -1,58 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.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 "pairinginfo.h"
PairingInfo::PairingInfo(QObject *parent) :
QObject(parent)
{
}
PairingTransactionId PairingInfo::pairingTransactionId() const
{
return m_pairingTransactionId;
}
void PairingInfo::setPairingTransactionId(const PairingTransactionId &pairingTransactionId)
{
m_pairingTransactionId = pairingTransactionId;
}
QHostAddress PairingInfo::host() const
{
return m_host;
}
void PairingInfo::setHost(const QHostAddress &host)
{
m_host = host;
}
QString PairingInfo::apiKey() const
{
return m_apiKey;
}
void PairingInfo::setApiKey(const QString &apiKey)
{
m_apiKey = apiKey;
}

View File

@ -1,52 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.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 PAIRINGINFO_H
#define PAIRINGINFO_H
#include <QObject>
#include <QHostAddress>
#include "typeutils.h"
class PairingInfo : public QObject
{
Q_OBJECT
public:
explicit PairingInfo(QObject *parent = 0);
PairingTransactionId pairingTransactionId() const;
void setPairingTransactionId(const PairingTransactionId &pairingTransactionId);
QHostAddress host() const;
void setHost(const QHostAddress &host);
QString apiKey() const;
void setApiKey(const QString &apiKey);
private:
PairingTransactionId m_pairingTransactionId;
QHostAddress m_host;
QString m_apiKey;
};
#endif // PAIRINGINFO_H

View File

@ -11,7 +11,6 @@ SOURCES += \
huebridge.cpp \
huelight.cpp \
huemotionsensor.cpp \
pairinginfo.cpp \
hueremote.cpp \
huedevice.cpp
@ -23,7 +22,6 @@ HEADERS += \
huebridge.h \
huelight.h \
huemotionsensor.h \
pairinginfo.h \
hueremote.h \
huedevice.h