fixed hue plugin

This commit is contained in:
Simon Stürz 2015-05-26 17:50:52 +02:00 committed by Michael Zanetti
parent cc0bd99d69
commit ea03497b15
7 changed files with 63 additions and 221 deletions

View File

@ -37,7 +37,7 @@ void UpnpDiscoveryRequest::discover()
QByteArray ssdpSearchMessage = QByteArray("M-SEARCH * HTTP/1.1\r\n"
"HOST:239.255.255.250:1900\r\n"
"MAN:\"ssdp:discover\"\r\n"
"MX:2\r\n"
"MX:4\r\n"
"ST: " + m_searchTarget.toUtf8() + "\r\n"
"USR-AGENT: " + m_userAgent.toUtf8() + "\r\n\r\n");

View File

@ -1,6 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
@ -72,18 +73,15 @@ ActionTypeId hueSetBrightnessActionTypeId = ActionTypeId("3bc95552-cba0-4222-abd
StateTypeId hueReachableStateTypeId = StateTypeId("15794d26-fde8-4a61-8f83-d7830534975f");
DevicePluginPhilipsHue::DevicePluginPhilipsHue()
//:m_discovery(new Discovery(this))
{
// connect(m_discovery, &Discovery::discoveryDone, this, &DevicePluginPhilipsHue::discoveryDone);
// m_bridge = new HueBridgeConnection(this);
// connect(m_bridge, &HueBridgeConnection::createUserFinished, this, &DevicePluginPhilipsHue::createUserFinished);
// connect(m_bridge, &HueBridgeConnection::getFinished, this, &DevicePluginPhilipsHue::getFinished);
m_bridge = new HueBridgeConnection(this);
connect(m_bridge, &HueBridgeConnection::createUserFinished, this, &DevicePluginPhilipsHue::createUserFinished);
connect(m_bridge, &HueBridgeConnection::getFinished, this, &DevicePluginPhilipsHue::getFinished);
}
DeviceManager::HardwareResources DevicePluginPhilipsHue::requiredHardware() const
{
return DeviceManager::HardwareResourceTimer;
return DeviceManager::HardwareResourceTimer | DeviceManager::HardwareResourceUpnpDisovery;
}
void DevicePluginPhilipsHue::startMonitoringAutoDevices()
@ -102,13 +100,13 @@ DeviceManager::DeviceError DevicePluginPhilipsHue::discoverDevices(const DeviceC
{
Q_UNUSED(deviceClassId)
Q_UNUSED(params)
m_discovery->findBridges(4000);
upnpDiscover("libhue:idl");
return DeviceManager::DeviceErrorAsync;
}
DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *device)
{
qDebug() << "setupDevice" << device->params();
//qDebug() << "setupDevice" << device->params();
Light *light = nullptr;
@ -117,6 +115,7 @@ DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *dev
if (m_unconfiguredLights.count() > 0) {
light = m_unconfiguredLights.takeFirst();
device->setParamValue("number", light->id());
device->setParamValue("name", QString("Hue light %1").arg(light->id()));
} else {
// this shouldn't ever happen
qWarning() << "Device not configured yet and no discovered devices around. This should not happen.";
@ -139,6 +138,7 @@ DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *dev
Light *light = m_unconfiguredLights.takeFirst();
DeviceDescriptor descriptor(hueDeviceClassId, light->name());
ParamList params;
params.append(Param("name", light->name()));
params.append(Param("number", light->id()));
params.append(Param("ip", light->ip().toString()));
params.append(Param("username", light->username()));
@ -163,6 +163,28 @@ void DevicePluginPhilipsHue::deviceRemoved(Device *device)
m_unconfiguredLights.append(light);
}
void DevicePluginPhilipsHue::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList)
{
qDebug() << "discovered bridges" << upnpDeviceDescriptorList.count();
foreach (const UpnpDeviceDescriptor &descriptor, upnpDeviceDescriptorList) {
qDebug() << descriptor;
}
QList<DeviceDescriptor> deviceDescriptors;
foreach (const UpnpDeviceDescriptor &upnpDevice, upnpDeviceDescriptorList) {
DeviceDescriptor descriptor(hueDeviceClassId, "Philips Hue bridge", upnpDevice.hostAddress().toString());
ParamList params;
params.append(Param("ip", upnpDevice.hostAddress().toString()));
params.append(Param("username", "guh-" + QUuid::createUuid().toString().remove(QRegExp("[\\{\\}]*")).remove(QRegExp("\\-[0-9a-f\\-]*"))));
params.append(Param("number", -1));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
}
emit devicesDiscovered(hueDeviceClassId, deviceDescriptors);
}
DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params)
{
Q_UNUSED(deviceClassId)
@ -212,38 +234,19 @@ DeviceManager::DeviceError DevicePluginPhilipsHue::executeAction(Device *device,
if (!light->reachable()) {
qWarning() << "Hue Bulb not reachable";
return DeviceManager::DeviceErrorSetupFailed;
return DeviceManager::DeviceErrorHardwareNotAvailable;
}
if (action.actionTypeId() == hueSetColorActionTypeId) {
if (action.actionTypeId() == hueColorActionTypeId) {
light->setColor(action.param("color").value().value<QColor>());
} else if (action.actionTypeId() == hueSetPowerActionTypeId) {
} else if (action.actionTypeId() == huePowerActionTypeId) {
light->setOn(action.param("power").value().toBool());
} else if (action.actionTypeId() == hueSetBrightnessActionTypeId) {
} else if (action.actionTypeId() == hueBrightnessActionTypeId) {
light->setBri(action.param("brightness").value().toInt());
}
return DeviceManager::DeviceErrorNoError;
}
void DevicePluginPhilipsHue::discoveryDone(const QList<QHostAddress> &bridges)
{
qDebug() << "discovered bridges" << bridges.count();
QList<DeviceDescriptor> deviceDescriptors;
foreach (const QHostAddress &bridge, bridges) {
DeviceDescriptor descriptor(hueDeviceClassId, "Philips Hue bridge", bridge.toString());
ParamList params;
Param param("ip", bridge.toString());
params.append(param);
Param userParam("username", "guh-" + QUuid::createUuid().toString().remove(QRegExp("[\\{\\}]*")).remove(QRegExp("\\-[0-9a-f\\-]*")));
params.append(userParam);
Param numberParam("number", -1);
params.append(numberParam);
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
}
emit devicesDiscovered(hueDeviceClassId, deviceDescriptors);
}
void DevicePluginPhilipsHue::createUserFinished(int id, const QVariant &response)
{
@ -301,6 +304,7 @@ void DevicePluginPhilipsHue::lightStateChanged()
if (m_asyncSetups.contains(light)) {
device = m_asyncSetups.take(light);
device->setName(light->name());
device->setParamValue("name", light->name());
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess);
} else {
device = m_lights.value(light);

View File

@ -22,7 +22,6 @@
#define DEVICEPLUGINPHILIPSHUE_H
#include "plugin/deviceplugin.h"
#include "discovery.h"
#include "huebridgeconnection.h"
#include "light.h"
@ -47,6 +46,7 @@ public:
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override;
void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList) override;
DeviceManager::DeviceSetupStatus confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params) override;
@ -56,8 +56,6 @@ public slots:
DeviceManager::DeviceError executeAction(Device *device, const Action &action);
private slots:
void discoveryDone(const QList<QHostAddress> &bridges);
void createUserFinished(int id, const QVariant &params);
void getLightsFinished(int id, const QVariant &params);
void getFinished(int id, const QVariant &params);
@ -65,7 +63,6 @@ private slots:
void lightStateChanged();
private:
Discovery *m_discovery;
class PairingInfo {
public:

View File

@ -15,18 +15,26 @@
"pairingInfo": "Please press the button on the Hue bridge and then press OK",
"paramTypes": [
{
"name": "ip",
"type" : "QString",
"inputType": "IPv4Address"
},
{
"name": "username",
"name": "name",
"type" : "QString",
"inputType": "TextLine"
},
{
"name": "ip",
"type" : "QString",
"inputType": "IPv4Address",
"readOnly": true
},
{
"name": "username",
"type" : "QString",
"inputType": "TextLine",
"readOnly": true
},
{
"name": "lightId",
"type" : "int"
"type" : "int",
"readOnly": true
}
],
"stateTypes": [
@ -40,57 +48,28 @@
"id": "d25423e7-b924-4b20-80b6-77eecc65d089",
"idName": "hueColor",
"name": "color",
"type": "color",
"defaultValue": "black"
"type": "QColor",
"defaultValue": "#000000",
"writable": true
},
{
"id": "90aaffe5-6a76-47d2-a14a-550f60390245",
"idName": "huePower",
"name": "power",
"type": "bool",
"defaultValue": false
"defaultValue": false,
"writable": true
},
{
"id": "90e91f64-a208-468c-a5a2-7f47e08859e2",
"idName": "hueBrightness",
"name": "brightness",
"type": "int",
"defaultValue": 0
}
],
"actionTypes": [
{
"id": "29cc299a-818b-47b2-817f-c5a6361545e4",
"idName": "hueSetColor",
"name": "Set color",
"paramTypes": [
{
"name": "color",
"type": "QColor"
}
]
},
{
"id": "7782d91e-d73a-4321-8828-da768e2f6827",
"idName": "hueSetPower",
"name": "Set power",
"paramTypes": [
{
"name": "power",
"type": "bool"
}
]
},
{
"id": "3bc95552-cba0-4222-abd5-9b668132e442",
"idName": "hueSetBrightness",
"name": "Set brightness",
"paramTypes": [
{
"name": "brightness",
"type": "int"
}
]
"minValue": 0,
"maxValue": 100,
"defaultValue": 0,
"writable": true
}
]
}

View File

@ -1,86 +0,0 @@
/*
* Copyright 2013 Christian Muehlhaeuser
*
* This program 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; version 2.
*
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Christian Muehlhaeuser <muesli@gmail.com>
*/
#include "discovery.h"
#include <QDebug>
#include <QTimer>
Discovery::Discovery(QObject *parent) :
QUdpSocket(parent),
m_timeout(new QTimer(this))
{
quint16 port = 1900;
unsigned int tries = 0;
const unsigned int maxtries = 10;
while (!bind(port++)) {
if (++tries == maxtries) {
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection);
return;
}
}
connect(this, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
m_timeout->setSingleShot(true);
connect(m_timeout, SIGNAL(timeout()), this, SLOT(onTimeout()));
}
bool Discovery::findBridges(int timeout)
{
m_timeout->stop();
m_reportedBridges.clear();
QString b("M-SEARCH * HTTP/1.1\r\n"
"HOST: 239.255.255.250:1900\r\n"
"MAN: \"ssdp:discover\"\r\n"
"MX: %1\r\n"
"ST: libhue:idl\r\n");
b.arg(timeout / 1000);
// qDebug() << "writing datagram" << b;
m_timeout->start(timeout);
if (writeDatagram(b.toUtf8(), QHostAddress("239.255.255.250"), 1900) < 0) {
return false;
}
return true;
}
void Discovery::onTimeout()
{
emit discoveryDone(m_reportedBridges);
}
void Discovery::onReadyRead()
{
while (hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
// qDebug() << "got datagram" << datagram;
if (!m_reportedBridges.contains(sender)) {
m_reportedBridges << sender;
}
}
}

View File

@ -1,50 +0,0 @@
/*
* Copyright 2013 Christian Muehlhaeuser
*
* This program 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; version 2.
*
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Christian Muehlhaeuser <muesli@gmail.com>
* Michael Zanetti <michael_zanetti@gmx.net>
*/
#ifndef DISCOVERY_H
#define DISCOVERY_H
#include <QUdpSocket>
#include <QHostAddress>
class QTimer;
class Discovery: public QUdpSocket
{
Q_OBJECT
public:
Discovery(QObject *parent);
bool findBridges(int timeout);
signals:
void error();
void discoveryDone(QList<QHostAddress> bridges);
private slots:
void onTimeout();
void onReadyRead();
private:
QList<QHostAddress> m_reportedBridges;
QTimer *m_timeout;
};
#endif

View File

@ -6,13 +6,11 @@ QT += network
SOURCES += \
devicepluginphilipshue.cpp \
discovery.cpp \
huebridgeconnection.cpp \
light.cpp
HEADERS += \
devicepluginphilipshue.h \
discovery.h \
huebridgeconnection.h \
light.h \
lightinterface.h