Skip to content
This repository was archived by the owner on May 6, 2021. It is now read-only.

Commit 5b7d802

Browse files
committed
Initial commit of support for the Philips Hue system.
1 parent 515208c commit 5b7d802

File tree

4 files changed

+179
-0
lines changed

4 files changed

+179
-0
lines changed

libsrc/leddevice/CMakeLists.txt

100644100755
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ SET(Leddevice_HEADERS
2929
${CURRENT_SOURCE_DIR}/LedDeviceSedu.h
3030
${CURRENT_SOURCE_DIR}/LedDeviceTest.h
3131
${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h
32+
${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.h
3233
)
3334

3435
SET(Leddevice_SOURCES
@@ -44,6 +45,7 @@ SET(Leddevice_SOURCES
4445
${CURRENT_SOURCE_DIR}/LedDeviceSedu.cpp
4546
${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp
4647
${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp
48+
${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.cpp
4749
)
4850

4951
if(ENABLE_SPIDEV)

libsrc/leddevice/LedDeviceFactory.cpp

100644100755
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "LedDeviceSedu.h"
2929
#include "LedDeviceTest.h"
3030
#include "LedDeviceHyperionUsbasp.h"
31+
#include "LedDevicePhilipsHue.h"
3132

3233
LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig)
3334
{
@@ -159,6 +160,11 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig)
159160
deviceHyperionUsbasp->open();
160161
device = deviceHyperionUsbasp;
161162
}
163+
else if (type == "philipshue")
164+
{
165+
const std::string output = deviceConfig["output"].asString();
166+
device = new LedDevicePhilipsHue(output);
167+
}
162168
else if (type == "test")
163169
{
164170
const std::string output = deviceConfig["output"].asString();
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Local-Hyperion includes
2+
#include "LedDevicePhilipsHue.h"
3+
4+
#include <iostream>
5+
6+
#include <QtCore/qmath.h>
7+
#include <QUrl>
8+
#include <QHttpRequestHeader>
9+
#include <QThread>
10+
11+
LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output) :
12+
host(output.c_str()), username("newdeveloper") {
13+
http = new QHttp(host, 80);
14+
}
15+
16+
LedDevicePhilipsHue::~LedDevicePhilipsHue() {
17+
delete http;
18+
}
19+
20+
int LedDevicePhilipsHue::write(const std::vector<ColorRgb> & ledValues) {
21+
// Due to rate limiting (max. 30 request per seconds), discard new values if
22+
// the previous request have not been completed yet.
23+
if (http->hasPendingRequests()) {
24+
return -1;
25+
}
26+
unsigned int lightId = 1;
27+
for (const ColorRgb& color : ledValues) {
28+
float x, y, b;
29+
// Scale colors from [0, 255] to [0, 1] and convert to xy space.
30+
rgbToXYBrightness(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, x, y, b);
31+
// Send adjust color command in JSON format.
32+
put(getRoute(lightId), QString("{\"xy\": [%1, %2]}").arg(x).arg(y));
33+
// Send brightness color command in JSON format.
34+
put(getRoute(lightId), QString("{\"bri\": %1}").arg(qRound(b * 255.0f)));
35+
// Next light id.
36+
lightId++;
37+
}
38+
return 0;
39+
}
40+
41+
int LedDevicePhilipsHue::switchOff() {
42+
return 0;
43+
}
44+
45+
void LedDevicePhilipsHue::put(QString route, QString content) {
46+
QString url = QString("/api/%1/%2").arg(username).arg(route);
47+
QHttpRequestHeader header("PUT", url);
48+
header.setValue("Host", host);
49+
header.setValue("Accept-Encoding", "identity");
50+
header.setValue("Content-Length", QString("%1").arg(content.size()));
51+
http->setHost(host);
52+
http->request(header, content.toAscii());
53+
// std::cout << "LedDevicePhilipsHue::put(): " << header.toString().toUtf8().constData() << std::endl;
54+
// std::cout << "LedDevicePhilipsHue::put(): " << content.toUtf8().constData() << std::endl;
55+
}
56+
57+
QString LedDevicePhilipsHue::getRoute(unsigned int lightId) {
58+
return QString("lights/%1/state").arg(lightId);
59+
}
60+
61+
void LedDevicePhilipsHue::rgbToXYBrightness(float red, float green, float blue, float& x, float& y, float& brightness) {
62+
// Apply gamma correction.
63+
red = (red > 0.04045f) ? qPow((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f);
64+
green = (green > 0.04045f) ? qPow ((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f);
65+
blue = (blue > 0.04045f) ? qPow ((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f);
66+
// Convert to XYZ space.
67+
float X = red * 0.649926f + green * 0.103455f + blue * 0.197109f;
68+
float Y = red * 0.234327f + green * 0.743075f + blue * 0.022598f;
69+
float Z = red * 0.0000000f + green * 0.053077f + blue * 1.035763f;
70+
// Convert to x,y space.
71+
x = X / (X + Y + Z);
72+
y = Y / (X + Y + Z);
73+
if (isnan(x)) {
74+
x = 0.0f;
75+
}
76+
if (isnan(y)) {
77+
y = 0.0f;
78+
}
79+
// Brightness is simply Y in the XYZ space.
80+
brightness = Y;
81+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#pragma once
2+
3+
// STL includes
4+
#include <string>
5+
6+
// Qt includes
7+
#include <QString>
8+
#include <QHttp>
9+
10+
// Leddevice includes
11+
#include <leddevice/LedDevice.h>
12+
13+
/**
14+
* Implementation for the Philips Hue system.
15+
*
16+
* To use set the device to "philipshue".
17+
* Uses the official Philips Hue API (http://developers.meethue.com).
18+
* Framegrabber should be limited to 30 Hz / numer of lights to avoid rate limitation by the hue bridge.
19+
* Create a new API user name "newdeveloper" on the bridge (http://developers.meethue.com/gettingstarted.html)
20+
*/
21+
class LedDevicePhilipsHue : public LedDevice
22+
{
23+
public:
24+
///
25+
/// Constructs the device.
26+
///
27+
/// @param output the ip address of the bridge
28+
///
29+
LedDevicePhilipsHue(const std::string& output);
30+
31+
///
32+
/// Destructor of this device
33+
///
34+
virtual ~LedDevicePhilipsHue();
35+
36+
///
37+
/// Sends the given led-color values via put request to the hue system
38+
///
39+
/// @param ledValues The color-value per led
40+
///
41+
/// @return Zero on success else negative
42+
///
43+
virtual int write(const std::vector<ColorRgb> & ledValues);
44+
45+
/// Switch the leds off
46+
virtual int switchOff();
47+
48+
private:
49+
/// Ip address of the bridge
50+
QString host;
51+
/// User name for the API ("newdeveloper")
52+
QString username;
53+
QHttp* http;
54+
55+
///
56+
/// Sends a HTTP PUT request
57+
///
58+
/// @param route the URI of the request
59+
///
60+
/// @param content content of the request
61+
///
62+
void put(QString route, QString content);
63+
64+
///
65+
/// @param lightId the id of the hue light (starting from 1)
66+
///
67+
/// @return the URI of the light
68+
///
69+
QString getRoute(unsigned int lightId);
70+
71+
///
72+
/// Converts an RGB color to the Hue xy color space and brightness
73+
/// https://github.com/PhilipsHue/PhilipsHueSDK-iOS-OSX/blob/master/ApplicationDesignNotes/RGB%20to%20xy%20Color%20conversion.md
74+
///
75+
/// @param red the red component in [0, 1]
76+
///
77+
/// @param green the green component in [0, 1]
78+
///
79+
/// @param blue the blue component in [0, 1]
80+
///
81+
/// @param x converted x component
82+
///
83+
/// @param y converted y component
84+
///
85+
/// @param brightness converted brightness component
86+
///
87+
void rgbToXYBrightness(float red, float green, float blue,
88+
float& x, float& y, float& brightness);
89+
90+
};

0 commit comments

Comments
 (0)