From f5a8174783bab0029751accb5c40250f211195b2 Mon Sep 17 00:00:00 2001 From: Tim Niggemann Date: Tue, 15 Jul 2014 08:51:07 +0200 Subject: [PATCH 01/12] Implemented color triangle calculations. Former-commit-id: dbde6635077a82ace5f4ed1fdf89458a28e7bf05 --- libsrc/leddevice/LedDevicePhilipsHue.cpp | 145 +++++++++++++++++++---- libsrc/leddevice/LedDevicePhilipsHue.h | 27 ++++- 2 files changed, 143 insertions(+), 29 deletions(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index f8a9698a..b2525033 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -10,6 +10,8 @@ #include #include +#include + LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output) : host(output.c_str()), username("newdeveloper") { http = new QHttp(host); @@ -24,18 +26,21 @@ LedDevicePhilipsHue::~LedDevicePhilipsHue() { int LedDevicePhilipsHue::write(const std::vector & ledValues) { // Save light states if not done before. - if (!statesSaved()) { - saveStates(ledValues.size()); - switchOn(ledValues.size()); + if (!areStatesSaved()) { + saveStates((unsigned int) ledValues.size()); + switchOn((unsigned int) ledValues.size()); } // Iterate through colors and set light states. unsigned int lightId = 1; for (const ColorRgb& color : ledValues) { - float x, y, b; + // Find triangle. + CGTriangle triangle = triangles.at(lightId - 1); // Scale colors from [0, 255] to [0, 1] and convert to xy space. - rgbToXYBrightness(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, x, y, b); + CGPoint xy; + float b; + rgbToXYBrightness(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, triangle, xy, b); // Send adjust color command in JSON format. - put(getStateRoute(lightId), QString("{\"xy\": [%1, %2]}").arg(x).arg(y)); + put(getStateRoute(lightId), QString("{\"xy\": [%1, %2]}").arg(xy.x).arg(xy.y)); // Send brightness color command in JSON format. put(getStateRoute(lightId), QString("{\"bri\": %1}").arg(qRound(b * 255.0f))); // Next light id. @@ -48,7 +53,7 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { int LedDevicePhilipsHue::switchOff() { timer.stop(); // If light states have been saved before, ... - if (statesSaved()) { + if (areStatesSaved()) { // ... restore them. restoreStates(); } @@ -93,6 +98,27 @@ QString LedDevicePhilipsHue::getRoute(unsigned int lightId) { return QString("lights/%1").arg(lightId); } +CGTriangle LedDevicePhilipsHue::getTriangle(QString modelId) { + const std::set HUE_BULBS_MODEL_IDS = { "LCT001", "LCT002", "LCT003" }; + const std::set LIVING_COLORS_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC011", "LLC012", + "LLC013", "LST001" }; + CGTriangle triangle; + if (HUE_BULBS_MODEL_IDS.find(modelId) != HUE_BULBS_MODEL_IDS.end()) { + triangle.red = {0.675f, 0.322f}; + triangle.green = {0.4091f, 0.518f}; + triangle.blue = {0.167f, 0.04f}; + } else if (LIVING_COLORS_MODEL_IDS.find(modelId) != LIVING_COLORS_MODEL_IDS.end()) { + triangle.red = {0.703f, 0.296f}; + triangle.green = {0.214f, 0.709f}; + triangle.blue = {0.139f, 0.081f}; + } else { + triangle.red = {1.0f, 0.0f}; + triangle.green = {0.0f, 1.0f}; + triangle.blue = {0.0f, 0.0f}; + } + return triangle; +} + void LedDevicePhilipsHue::saveStates(unsigned int nLights) { // Clear saved light states. states.clear(); @@ -116,8 +142,12 @@ void LedDevicePhilipsHue::saveStates(unsigned int nLights) { state["xy"] = json["state"]["xy"]; state["bri"] = json["state"]["bri"]; } + // Save id. + ids.push_back(QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", "")); // Save state object. states.push_back(QString(writer.write(state).c_str()).trimmed()); + // Determine triangle. + triangles.push_back(getTriangle(ids.back())); } } @@ -137,27 +167,94 @@ void LedDevicePhilipsHue::restoreStates() { states.clear(); } -bool LedDevicePhilipsHue::statesSaved() { +bool LedDevicePhilipsHue::areStatesSaved() { return !states.empty(); } -void LedDevicePhilipsHue::rgbToXYBrightness(float red, float green, float blue, float& x, float& y, float& brightness) { - // Apply gamma correction. - red = (red > 0.04045f) ? qPow((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f); - green = (green > 0.04045f) ? qPow((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f); - blue = (blue > 0.04045f) ? qPow((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f); - // Convert to XYZ space. - float X = red * 0.649926f + green * 0.103455f + blue * 0.197109f; - float Y = red * 0.234327f + green * 0.743075f + blue * 0.022598f; - float Z = red * 0.0000000f + green * 0.053077f + blue * 1.035763f; - // Convert to x,y space. - x = X / (X + Y + Z); - y = Y / (X + Y + Z); - if (isnan(x)) { - x = 0.0f; +float LedDevicePhilipsHue::crossProduct(CGPoint p1, CGPoint p2) { + return p1.x * p2.y - p1.y * p2.x; +} + +bool LedDevicePhilipsHue::isPointInLampsReach(CGTriangle triangle, CGPoint p) { + CGPoint v1 = { triangle.green.x - triangle.red.x, triangle.green.y - triangle.red.y }; + CGPoint v2 = { triangle.blue.x - triangle.red.x, triangle.blue.y - triangle.red.y }; + CGPoint q = { p.x - triangle.red.x, p.y - triangle.red.y }; + float s = crossProduct(q, v2) / crossProduct(v1, v2); + float t = crossProduct(v1, q) / crossProduct(v1, v2); + if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) { + return true; + } else { + return false; } - if (isnan(y)) { - y = 0.0f; +} + +CGPoint LedDevicePhilipsHue::getClosestPointToPoint(CGPoint A, CGPoint B, CGPoint P) { + CGPoint AP = { P.x - A.x, P.y - A.y }; + CGPoint AB = { B.x - A.x, B.y - A.y }; + float ab2 = AB.x * AB.x + AB.y * AB.y; + float ap_ab = AP.x * AB.x + AP.y * AB.y; + float t = ap_ab / ab2; + if (t < 0.0f) { + t = 0.0f; + } else if (t > 1.0f) { + t = 1.0f; + } + return {A.x + AB.x * t, A.y + AB.y * t}; +} + +float LedDevicePhilipsHue::getDistanceBetweenTwoPoints(CGPoint one, CGPoint two) { + // Horizontal difference. + float dx = one.x - two.x; + // Vertical difference. + float dy = one.y - two.y; + float dist = sqrt(dx * dx + dy * dy); + return dist; +} + +void LedDevicePhilipsHue::rgbToXYBrightness(float red, float green, float blue, CGTriangle triangle, CGPoint& xyPoint, + float& brightness) { + // Apply gamma correction. + float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f); + float g = (green > 0.04045f) ? powf((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f); + float b = (blue > 0.04045f) ? powf((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f); + // Convert to XYZ space. + float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; + float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; + float Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f; + // Convert to x,y space. + float cx = X / (X + Y + Z + 0.0000001f); + float cy = Y / (X + Y + Z + 0.0000001f); + if (isnan(cx)) { + cx = 0.0f; + } + if (isnan(cy)) { + cy = 0.0f; + } + xyPoint.x = cx; + xyPoint.y = cy; + // Check if the given XY value is within the colourreach of our lamps. + if (!isPointInLampsReach(triangle, xyPoint)) { + // It seems the colour is out of reach let's find the closes colour we can produce with our lamp and send this XY value out. + CGPoint pAB = getClosestPointToPoint(triangle.red, triangle.green, xyPoint); + CGPoint pAC = getClosestPointToPoint(triangle.blue, triangle.red, xyPoint); + CGPoint pBC = getClosestPointToPoint(triangle.green, triangle.blue, xyPoint); + // Get the distances per point and see which point is closer to our Point. + float dAB = getDistanceBetweenTwoPoints(xyPoint, pAB); + float dAC = getDistanceBetweenTwoPoints(xyPoint, pAC); + float dBC = getDistanceBetweenTwoPoints(xyPoint, pBC); + float lowest = dAB; + CGPoint closestPoint = pAB; + if (dAC < lowest) { + lowest = dAC; + closestPoint = pAC; + } + if (dBC < lowest) { + lowest = dBC; + closestPoint = pBC; + } + // Change the xy value to a value which is within the reach of the lamp. + xyPoint.x = closestPoint.x; + xyPoint.y = closestPoint.y; } // Brightness is simply Y in the XYZ space. brightness = Y; diff --git a/libsrc/leddevice/LedDevicePhilipsHue.h b/libsrc/leddevice/LedDevicePhilipsHue.h index 84e7bd35..cc988e97 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.h +++ b/libsrc/leddevice/LedDevicePhilipsHue.h @@ -12,6 +12,15 @@ // Leddevice includes #include +struct CGPoint { + float x; + float y; +}; + +struct CGTriangle { + CGPoint red, green, blue; +}; + /** * Implementation for the Philips Hue system. * @@ -56,6 +65,10 @@ private slots: private: /// Array to save the light states. std::vector states; + /// Array to save model ids. + std::vector ids; + /// Color triangles. + std::vector triangles; /// Ip address of the bridge QString host; /// User name for the API ("newdeveloper") @@ -114,7 +127,7 @@ private: /// /// @return true if light states have been saved. /// - bool statesSaved(); + bool areStatesSaved(); /// /// Converts an RGB color to the Hue xy color space and brightness @@ -126,12 +139,16 @@ private: /// /// @param blue the blue component in [0, 1] /// - /// @param x converted x component - /// - /// @param y converted y component + /// @param xyPoint converted xy component /// /// @param brightness converted brightness component /// - void rgbToXYBrightness(float red, float green, float blue, float& x, float& y, float& brightness); + void rgbToXYBrightness(float red, float green, float blue, CGTriangle triangle, CGPoint& xyPoint, float& brightness); + + CGTriangle getTriangle(QString modelId); + float crossProduct(CGPoint p1, CGPoint p2); + bool isPointInLampsReach(CGTriangle triangle, CGPoint p); + CGPoint getClosestPointToPoint(CGPoint a, CGPoint b, CGPoint p); + float getDistanceBetweenTwoPoints(CGPoint one, CGPoint two); }; From 9269b0a1e3c54b3c20f90f2be1b138c3b64715d3 Mon Sep 17 00:00:00 2001 From: Tim Niggemann Date: Tue, 15 Jul 2014 08:54:40 +0200 Subject: [PATCH 02/12] Removed saving of model ids. Save the corresponding color triangles instead for speedup. Former-commit-id: 72e6031234e12a488a5425e80e73dc8b03ec364f --- libsrc/leddevice/LedDevicePhilipsHue.cpp | 7 ++++--- libsrc/leddevice/LedDevicePhilipsHue.h | 2 -- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index b2525033..5c12b667 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -122,6 +122,7 @@ CGTriangle LedDevicePhilipsHue::getTriangle(QString modelId) { void LedDevicePhilipsHue::saveStates(unsigned int nLights) { // Clear saved light states. states.clear(); + triangles.clear(); // Use json parser to parse reponse. Json::Reader reader; Json::FastWriter writer; @@ -142,12 +143,11 @@ void LedDevicePhilipsHue::saveStates(unsigned int nLights) { state["xy"] = json["state"]["xy"]; state["bri"] = json["state"]["bri"]; } - // Save id. - ids.push_back(QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", "")); // Save state object. states.push_back(QString(writer.write(state).c_str()).trimmed()); // Determine triangle. - triangles.push_back(getTriangle(ids.back())); + QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", ""); + triangles.push_back(getTriangle(modelId)); } } @@ -165,6 +165,7 @@ void LedDevicePhilipsHue::restoreStates() { } // Clear saved light states. states.clear(); + triangles.clear(); } bool LedDevicePhilipsHue::areStatesSaved() { diff --git a/libsrc/leddevice/LedDevicePhilipsHue.h b/libsrc/leddevice/LedDevicePhilipsHue.h index cc988e97..81781db1 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.h +++ b/libsrc/leddevice/LedDevicePhilipsHue.h @@ -65,8 +65,6 @@ private slots: private: /// Array to save the light states. std::vector states; - /// Array to save model ids. - std::vector ids; /// Color triangles. std::vector triangles; /// Ip address of the bridge From 67970fce08d60e3bdf10d4126c3c0a43d18a318b Mon Sep 17 00:00:00 2001 From: Tim Niggemann Date: Tue, 15 Jul 2014 09:55:58 +0200 Subject: [PATCH 03/12] Created HueLamp class holding the color space as well as the original state and current color. Former-commit-id: 129c34f6008a68bca6cafb63eb0c0ad6a37f5179 --- libsrc/leddevice/LedDevicePhilipsHue.cpp | 169 ++++++++++++----------- libsrc/leddevice/LedDevicePhilipsHue.h | 37 +++-- 2 files changed, 114 insertions(+), 92 deletions(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index 5c12b667..a678480d 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -31,18 +31,22 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { switchOn((unsigned int) ledValues.size()); } // Iterate through colors and set light states. - unsigned int lightId = 1; + unsigned int lightId = 0; for (const ColorRgb& color : ledValues) { - // Find triangle. - CGTriangle triangle = triangles.at(lightId - 1); + // Get lamp. + HueLamp& lamp = lamps.at(lightId); // Scale colors from [0, 255] to [0, 1] and convert to xy space. - CGPoint xy; - float b; - rgbToXYBrightness(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, triangle, xy, b); - // Send adjust color command in JSON format. - put(getStateRoute(lightId), QString("{\"xy\": [%1, %2]}").arg(xy.x).arg(xy.y)); - // Send brightness color command in JSON format. - put(getStateRoute(lightId), QString("{\"bri\": %1}").arg(qRound(b * 255.0f))); + ColorPoint xy; + rgbToXYBrightness(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, lamp, xy); + // Write color if color has been changed. + if (xy != lamp.color) { + // Send adjust color command in JSON format. + put(getStateRoute(lightId), QString("{\"xy\": [%1, %2]}").arg(xy.x).arg(xy.y)); + // Send brightness color command in JSON format. + put(getStateRoute(lightId), QString("{\"bri\": %1}").arg(qRound(xy.bri * 255.0f))); + // Remember written color. + lamp.color = xy; + } // Next light id. lightId++; } @@ -98,31 +102,9 @@ QString LedDevicePhilipsHue::getRoute(unsigned int lightId) { return QString("lights/%1").arg(lightId); } -CGTriangle LedDevicePhilipsHue::getTriangle(QString modelId) { - const std::set HUE_BULBS_MODEL_IDS = { "LCT001", "LCT002", "LCT003" }; - const std::set LIVING_COLORS_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC011", "LLC012", - "LLC013", "LST001" }; - CGTriangle triangle; - if (HUE_BULBS_MODEL_IDS.find(modelId) != HUE_BULBS_MODEL_IDS.end()) { - triangle.red = {0.675f, 0.322f}; - triangle.green = {0.4091f, 0.518f}; - triangle.blue = {0.167f, 0.04f}; - } else if (LIVING_COLORS_MODEL_IDS.find(modelId) != LIVING_COLORS_MODEL_IDS.end()) { - triangle.red = {0.703f, 0.296f}; - triangle.green = {0.214f, 0.709f}; - triangle.blue = {0.139f, 0.081f}; - } else { - triangle.red = {1.0f, 0.0f}; - triangle.green = {0.0f, 1.0f}; - triangle.blue = {0.0f, 0.0f}; - } - return triangle; -} - void LedDevicePhilipsHue::saveStates(unsigned int nLights) { - // Clear saved light states. - states.clear(); - triangles.clear(); + // Clear saved lamps. + lamps.clear(); // Use json parser to parse reponse. Json::Reader reader; Json::FastWriter writer; @@ -136,50 +118,48 @@ void LedDevicePhilipsHue::saveStates(unsigned int nLights) { // Error occured, break loop. break; } - // Save state object values which are subject to change. + // Get state object values which are subject to change. Json::Value state(Json::objectValue); state["on"] = json["state"]["on"]; if (json["state"]["on"] == true) { state["xy"] = json["state"]["xy"]; state["bri"] = json["state"]["bri"]; } - // Save state object. - states.push_back(QString(writer.write(state).c_str()).trimmed()); - // Determine triangle. + // Determine the model id. QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", ""); - triangles.push_back(getTriangle(modelId)); + QString originalState = QString(writer.write(state).c_str()).trimmed(); + // Save state object. + lamps.push_back(HueLamp(i + 1, originalState, modelId)); } } void LedDevicePhilipsHue::switchOn(unsigned int nLights) { - for (unsigned int i = 0; i < nLights; i++) { - put(getStateRoute(i + 1), "{\"on\": true}"); + for (HueLamp lamp : lamps) { + put(getStateRoute(lamp.id), "{\"on\": true}"); } } void LedDevicePhilipsHue::restoreStates() { - unsigned int lightId = 1; - for (QString state : states) { - put(getStateRoute(lightId), state); - lightId++; + for (HueLamp lamp : lamps) { + put(getStateRoute(lamp.id), lamp.originalState); } // Clear saved light states. - states.clear(); - triangles.clear(); + lamps.clear(); } bool LedDevicePhilipsHue::areStatesSaved() { - return !states.empty(); + return !lamps.empty(); } -float LedDevicePhilipsHue::crossProduct(CGPoint p1, CGPoint p2) { +float LedDevicePhilipsHue::crossProduct(ColorPoint p1, ColorPoint p2) { return p1.x * p2.y - p1.y * p2.x; } -bool LedDevicePhilipsHue::isPointInLampsReach(CGTriangle triangle, CGPoint p) { - CGPoint v1 = { triangle.green.x - triangle.red.x, triangle.green.y - triangle.red.y }; - CGPoint v2 = { triangle.blue.x - triangle.red.x, triangle.blue.y - triangle.red.y }; - CGPoint q = { p.x - triangle.red.x, p.y - triangle.red.y }; +bool LedDevicePhilipsHue::isPointInLampsReach(HueLamp lamp, ColorPoint p) { + ColorTriangle& triangle = lamp.colorSpace; + ColorPoint v1 = { triangle.green.x - triangle.red.x, triangle.green.y - triangle.red.y }; + ColorPoint v2 = { triangle.blue.x - triangle.red.x, triangle.blue.y - triangle.red.y }; + ColorPoint q = { p.x - triangle.red.x, p.y - triangle.red.y }; float s = crossProduct(q, v2) / crossProduct(v1, v2); float t = crossProduct(v1, q) / crossProduct(v1, v2); if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) { @@ -189,9 +169,9 @@ bool LedDevicePhilipsHue::isPointInLampsReach(CGTriangle triangle, CGPoint p) { } } -CGPoint LedDevicePhilipsHue::getClosestPointToPoint(CGPoint A, CGPoint B, CGPoint P) { - CGPoint AP = { P.x - A.x, P.y - A.y }; - CGPoint AB = { B.x - A.x, B.y - A.y }; +ColorPoint LedDevicePhilipsHue::getClosestPointToPoint(ColorPoint a, ColorPoint b, ColorPoint p) { + ColorPoint AP = { p.x - a.x, p.y - a.y }; + ColorPoint AB = { b.x - a.x, b.y - a.y }; float ab2 = AB.x * AB.x + AB.y * AB.y; float ap_ab = AP.x * AB.x + AP.y * AB.y; float t = ap_ab / ab2; @@ -200,20 +180,19 @@ CGPoint LedDevicePhilipsHue::getClosestPointToPoint(CGPoint A, CGPoint B, CGPoin } else if (t > 1.0f) { t = 1.0f; } - return {A.x + AB.x * t, A.y + AB.y * t}; + return {a.x + AB.x * t, a.y + AB.y * t}; } -float LedDevicePhilipsHue::getDistanceBetweenTwoPoints(CGPoint one, CGPoint two) { +float LedDevicePhilipsHue::getDistanceBetweenTwoPoints(ColorPoint p1, ColorPoint p2) { // Horizontal difference. - float dx = one.x - two.x; + float dx = p1.x - p2.x; // Vertical difference. - float dy = one.y - two.y; - float dist = sqrt(dx * dx + dy * dy); - return dist; + float dy = p1.y - p2.y; + // Absolute value. + return sqrt(dx * dx + dy * dy); } -void LedDevicePhilipsHue::rgbToXYBrightness(float red, float green, float blue, CGTriangle triangle, CGPoint& xyPoint, - float& brightness) { +void LedDevicePhilipsHue::rgbToXYBrightness(float red, float green, float blue, HueLamp lamp, ColorPoint& xy) { // Apply gamma correction. float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f); float g = (green > 0.04045f) ? powf((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f); @@ -231,20 +210,20 @@ void LedDevicePhilipsHue::rgbToXYBrightness(float red, float green, float blue, if (isnan(cy)) { cy = 0.0f; } - xyPoint.x = cx; - xyPoint.y = cy; - // Check if the given XY value is within the colourreach of our lamps. - if (!isPointInLampsReach(triangle, xyPoint)) { - // It seems the colour is out of reach let's find the closes colour we can produce with our lamp and send this XY value out. - CGPoint pAB = getClosestPointToPoint(triangle.red, triangle.green, xyPoint); - CGPoint pAC = getClosestPointToPoint(triangle.blue, triangle.red, xyPoint); - CGPoint pBC = getClosestPointToPoint(triangle.green, triangle.blue, xyPoint); + xy.x = cx; + xy.y = cy; + // Check if the given XY value is within the color reach of our lamps. + if (!isPointInLampsReach(lamp, xy)) { + // It seems the color is out of reach let's find the closes colour we can produce with our lamp and send this XY value out. + ColorPoint pAB = getClosestPointToPoint(lamp.colorSpace.red, lamp.colorSpace.green, xy); + ColorPoint pAC = getClosestPointToPoint(lamp.colorSpace.blue, lamp.colorSpace.red, xy); + ColorPoint pBC = getClosestPointToPoint(lamp.colorSpace.green, lamp.colorSpace.blue, xy); // Get the distances per point and see which point is closer to our Point. - float dAB = getDistanceBetweenTwoPoints(xyPoint, pAB); - float dAC = getDistanceBetweenTwoPoints(xyPoint, pAC); - float dBC = getDistanceBetweenTwoPoints(xyPoint, pBC); + float dAB = getDistanceBetweenTwoPoints(xy, pAB); + float dAC = getDistanceBetweenTwoPoints(xy, pAC); + float dBC = getDistanceBetweenTwoPoints(xy, pBC); float lowest = dAB; - CGPoint closestPoint = pAB; + ColorPoint closestPoint = pAB; if (dAC < lowest) { lowest = dAC; closestPoint = pAC; @@ -254,9 +233,41 @@ void LedDevicePhilipsHue::rgbToXYBrightness(float red, float green, float blue, closestPoint = pBC; } // Change the xy value to a value which is within the reach of the lamp. - xyPoint.x = closestPoint.x; - xyPoint.y = closestPoint.y; + xy.x = closestPoint.x; + xy.y = closestPoint.y; } // Brightness is simply Y in the XYZ space. - brightness = Y; + xy.bri = Y; +} + +HueLamp::HueLamp(unsigned int id, QString originalState, QString modelId) : + id(id), originalState(originalState) { + /// Hue system model ids. + const std::set HUE_BULBS_MODEL_IDS = { "LCT001", "LCT002", "LCT003" }; + const std::set LIVING_COLORS_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC011", "LLC012", + "LLC013", "LST001" }; + /// Find id in the sets and set the appropiate color space. + if (HUE_BULBS_MODEL_IDS.find(modelId) != HUE_BULBS_MODEL_IDS.end()) { + colorSpace.red = {0.675f, 0.322f}; + colorSpace.green = {0.4091f, 0.518f}; + colorSpace.blue = {0.167f, 0.04f}; + } else if (LIVING_COLORS_MODEL_IDS.find(modelId) != LIVING_COLORS_MODEL_IDS.end()) { + colorSpace.red = {0.703f, 0.296f}; + colorSpace.green = {0.214f, 0.709f}; + colorSpace.blue = {0.139f, 0.081f}; + } else { + colorSpace.red = {1.0f, 0.0f}; + colorSpace.green = {0.0f, 1.0f}; + colorSpace.blue = {0.0f, 0.0f}; + } + /// Initialize color with black + color = {0.0f, 0.0f, 0.0f}; +} + +bool operator ==(ColorPoint p1, ColorPoint p2) { + return (p1.x == p2.x) && (p1.y == p2.y) && (p1.bri == p2.bri); +} + +bool operator !=(ColorPoint p1, ColorPoint p2) { + return !(p1 == p2); } diff --git a/libsrc/leddevice/LedDevicePhilipsHue.h b/libsrc/leddevice/LedDevicePhilipsHue.h index 81781db1..219cce85 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.h +++ b/libsrc/leddevice/LedDevicePhilipsHue.h @@ -12,13 +12,27 @@ // Leddevice includes #include -struct CGPoint { +struct ColorPoint { float x; float y; + float bri; }; -struct CGTriangle { - CGPoint red, green, blue; +bool operator==(ColorPoint p1, ColorPoint p2); +bool operator!=(ColorPoint p1, ColorPoint p2); + +struct ColorTriangle { + ColorPoint red, green, blue; +}; + +class HueLamp { +public: + unsigned int id; + ColorPoint color; + ColorTriangle colorSpace; + QString originalState; + + HueLamp(unsigned int id, QString originalState, QString modelId); }; /** @@ -63,10 +77,8 @@ private slots: void restoreStates(); private: - /// Array to save the light states. - std::vector states; - /// Color triangles. - std::vector triangles; + /// Array to save the lamps. + std::vector lamps; /// Ip address of the bridge QString host; /// User name for the API ("newdeveloper") @@ -141,12 +153,11 @@ private: /// /// @param brightness converted brightness component /// - void rgbToXYBrightness(float red, float green, float blue, CGTriangle triangle, CGPoint& xyPoint, float& brightness); + void rgbToXYBrightness(float red, float green, float blue, HueLamp lamp, ColorPoint& xy); - CGTriangle getTriangle(QString modelId); - float crossProduct(CGPoint p1, CGPoint p2); - bool isPointInLampsReach(CGTriangle triangle, CGPoint p); - CGPoint getClosestPointToPoint(CGPoint a, CGPoint b, CGPoint p); - float getDistanceBetweenTwoPoints(CGPoint one, CGPoint two); + float crossProduct(ColorPoint p1, ColorPoint p2); + bool isPointInLampsReach(HueLamp lamp, ColorPoint p); + ColorPoint getClosestPointToPoint(ColorPoint a, ColorPoint b, ColorPoint p); + float getDistanceBetweenTwoPoints(ColorPoint one, ColorPoint two); }; From 4af2b11d8fa846c19344685e93175d406574db5e Mon Sep 17 00:00:00 2001 From: Tim Niggemann Date: Tue, 15 Jul 2014 09:58:29 +0200 Subject: [PATCH 04/12] Get the light id from the lamp object. Former-commit-id: dc7aa992386c2511261614a2a8fe3ccf15d9a591 --- libsrc/leddevice/LedDevicePhilipsHue.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index a678480d..a78c7fca 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -41,9 +41,9 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { // Write color if color has been changed. if (xy != lamp.color) { // Send adjust color command in JSON format. - put(getStateRoute(lightId), QString("{\"xy\": [%1, %2]}").arg(xy.x).arg(xy.y)); + put(getStateRoute(lamp.id), QString("{\"xy\": [%1, %2]}").arg(xy.x).arg(xy.y)); // Send brightness color command in JSON format. - put(getStateRoute(lightId), QString("{\"bri\": %1}").arg(qRound(xy.bri * 255.0f))); + put(getStateRoute(lamp.id), QString("{\"bri\": %1}").arg(qRound(xy.bri * 255.0f))); // Remember written color. lamp.color = xy; } From d2542142be8d37c3d290bd5b41e351206448dc36 Mon Sep 17 00:00:00 2001 From: Tim Niggemann Date: Tue, 15 Jul 2014 09:59:01 +0200 Subject: [PATCH 05/12] Get the light id from the lamp object. Former-commit-id: 7120af8551c185979c94b2a186f09c883784a882 --- libsrc/leddevice/LedDevicePhilipsHue.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index a78c7fca..94b6bdab 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -31,10 +31,10 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { switchOn((unsigned int) ledValues.size()); } // Iterate through colors and set light states. - unsigned int lightId = 0; + unsigned int idx = 0; for (const ColorRgb& color : ledValues) { // Get lamp. - HueLamp& lamp = lamps.at(lightId); + HueLamp& lamp = lamps.at(idx); // Scale colors from [0, 255] to [0, 1] and convert to xy space. ColorPoint xy; rgbToXYBrightness(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, lamp, xy); @@ -48,7 +48,7 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { lamp.color = xy; } // Next light id. - lightId++; + idx++; } timer.start(); return 0; From 7e049273a84afcf808e510c4847e0e79c1fa16c2 Mon Sep 17 00:00:00 2001 From: Tim Niggemann Date: Tue, 15 Jul 2014 12:06:26 +0200 Subject: [PATCH 06/12] Comments. Former-commit-id: bb4573afa8072bf03a3ae7c1b8ece721c7ea91ff --- libsrc/leddevice/LedDevicePhilipsHue.cpp | 18 ++++---- libsrc/leddevice/LedDevicePhilipsHue.h | 59 ++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 13 deletions(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index 94b6bdab..fcb6b2a8 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -36,8 +36,7 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { // Get lamp. HueLamp& lamp = lamps.at(idx); // Scale colors from [0, 255] to [0, 1] and convert to xy space. - ColorPoint xy; - rgbToXYBrightness(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, lamp, xy); + ColorPoint xy = rgbToXYBrightness(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, lamp); // Write color if color has been changed. if (xy != lamp.color) { // Send adjust color command in JSON format. @@ -192,7 +191,7 @@ float LedDevicePhilipsHue::getDistanceBetweenTwoPoints(ColorPoint p1, ColorPoint return sqrt(dx * dx + dy * dy); } -void LedDevicePhilipsHue::rgbToXYBrightness(float red, float green, float blue, HueLamp lamp, ColorPoint& xy) { +ColorPoint LedDevicePhilipsHue::rgbToXYBrightness(float red, float green, float blue, HueLamp lamp) { // Apply gamma correction. float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f); float g = (green > 0.04045f) ? powf((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f); @@ -202,16 +201,15 @@ void LedDevicePhilipsHue::rgbToXYBrightness(float red, float green, float blue, float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; float Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f; // Convert to x,y space. - float cx = X / (X + Y + Z + 0.0000001f); - float cy = Y / (X + Y + Z + 0.0000001f); + float cx = X / (X + Y + Z); + float cy = Y / (X + Y + Z); if (isnan(cx)) { cx = 0.0f; } if (isnan(cy)) { cy = 0.0f; } - xy.x = cx; - xy.y = cy; + ColorPoint xy = {cx, cy}; // Check if the given XY value is within the color reach of our lamps. if (!isPointInLampsReach(lamp, xy)) { // It seems the color is out of reach let's find the closes colour we can produce with our lamp and send this XY value out. @@ -242,11 +240,11 @@ void LedDevicePhilipsHue::rgbToXYBrightness(float red, float green, float blue, HueLamp::HueLamp(unsigned int id, QString originalState, QString modelId) : id(id), originalState(originalState) { - /// Hue system model ids. + // Hue system model ids. const std::set HUE_BULBS_MODEL_IDS = { "LCT001", "LCT002", "LCT003" }; const std::set LIVING_COLORS_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC011", "LLC012", "LLC013", "LST001" }; - /// Find id in the sets and set the appropiate color space. + // Find id in the sets and set the appropiate color space. if (HUE_BULBS_MODEL_IDS.find(modelId) != HUE_BULBS_MODEL_IDS.end()) { colorSpace.red = {0.675f, 0.322f}; colorSpace.green = {0.4091f, 0.518f}; @@ -260,7 +258,7 @@ HueLamp::HueLamp(unsigned int id, QString originalState, QString modelId) : colorSpace.green = {0.0f, 1.0f}; colorSpace.blue = {0.0f, 0.0f}; } - /// Initialize color with black + // Initialize color with black color = {0.0f, 0.0f, 0.0f}; } diff --git a/libsrc/leddevice/LedDevicePhilipsHue.h b/libsrc/leddevice/LedDevicePhilipsHue.h index 219cce85..59d86594 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.h +++ b/libsrc/leddevice/LedDevicePhilipsHue.h @@ -12,6 +12,9 @@ // Leddevice includes #include +/** + * A color point in the color space of the hue system. + */ struct ColorPoint { float x; float y; @@ -21,10 +24,16 @@ struct ColorPoint { bool operator==(ColorPoint p1, ColorPoint p2); bool operator!=(ColorPoint p1, ColorPoint p2); +/** + * Color triangle to define an available color space for the hue lamps. + */ struct ColorTriangle { ColorPoint red, green, blue; }; +/** + * Simple class to hold the id, the latest color, the color space and the original state. + */ class HueLamp { public: unsigned int id; @@ -32,6 +41,15 @@ public: ColorTriangle colorSpace; QString originalState; + /// + /// Constructs the lamp. + /// + /// @param id the light id + /// + /// @param originalState the json string of the original state + /// + /// @param modelId the model id of the hue lamp which is used to determine the color space + /// HueLamp(unsigned int id, QString originalState, QString modelId); }; @@ -149,15 +167,50 @@ private: /// /// @param blue the blue component in [0, 1] /// - /// @param xyPoint converted xy component + /// @param lamp the hue lamp instance used for color space checks. /// - /// @param brightness converted brightness component + /// @return color point /// - void rgbToXYBrightness(float red, float green, float blue, HueLamp lamp, ColorPoint& xy); + ColorPoint rgbToXYBrightness(float red, float green, float blue, HueLamp lamp); + /// + /// @param p1 point one + /// + /// @param p2 point tow + /// + /// @return the cross product between p1 and p2 + /// float crossProduct(ColorPoint p1, ColorPoint p2); + + + /// + /// @param lamp the hue lamp instance + /// + /// @param p the color point to check + /// + /// @return true if the color point is covered by the lamp color space + /// bool isPointInLampsReach(HueLamp lamp, ColorPoint p); + + + /// + /// @param a reference point one + /// + /// @param b reference point two + /// + /// @param p the point to which the closest point is to be found + /// + /// @return the closest color point of p to a and b + /// ColorPoint getClosestPointToPoint(ColorPoint a, ColorPoint b, ColorPoint p); + + /// + /// @param p1 point one + /// + /// @param p2 point tow + /// + /// @return the distance between the two points + /// float getDistanceBetweenTwoPoints(ColorPoint one, ColorPoint two); }; From fcb2ff66671fcb9b8a800e62a7da13ef608ed012 Mon Sep 17 00:00:00 2001 From: Tim Niggemann Date: Tue, 15 Jul 2014 12:08:27 +0200 Subject: [PATCH 07/12] Renamed method parameters. Former-commit-id: e10705dd6d93f5c1398a213583bbe349833d2648 --- libsrc/leddevice/LedDevicePhilipsHue.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.h b/libsrc/leddevice/LedDevicePhilipsHue.h index 59d86594..d60c2b32 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.h +++ b/libsrc/leddevice/LedDevicePhilipsHue.h @@ -158,7 +158,7 @@ private: bool areStatesSaved(); /// - /// Converts an RGB color to the Hue xy color space and brightness + /// Converts an RGB color to the Hue xy color space and brightness. /// https://github.com/PhilipsHue/PhilipsHueSDK-iOS-OSX/blob/master/ApplicationDesignNotes/RGB%20to%20xy%20Color%20conversion.md /// /// @param red the red component in [0, 1] @@ -211,6 +211,6 @@ private: /// /// @return the distance between the two points /// - float getDistanceBetweenTwoPoints(ColorPoint one, ColorPoint two); + float getDistanceBetweenTwoPoints(ColorPoint p1, ColorPoint p2); }; From b055578759bb7a1f81f08b94c7a6cf8fca90aa31 Mon Sep 17 00:00:00 2001 From: Tim Niggemann Date: Wed, 16 Jul 2014 11:49:34 +0200 Subject: [PATCH 08/12] Added config switch for turing off the lamps if the color black is written. Former-commit-id: bb4f4bc74c035c10a8dc678a11052ea276ea0149 --- libsrc/leddevice/LedDeviceFactory.cpp | 3 ++- libsrc/leddevice/LedDevicePhilipsHue.cpp | 23 ++++++++++++++++------- libsrc/leddevice/LedDevicePhilipsHue.h | 7 ++++++- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 76eb0137..5a1bd123 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -164,7 +164,8 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) else if (type == "philipshue") { const std::string output = deviceConfig["output"].asString(); - device = new LedDevicePhilipsHue(output); + const bool switchOffOnBlack = deviceConfig.get("switch_off_on_black", false).asBool(); + device = new LedDevicePhilipsHue(output, switchOffOnBlack); } else if (type == "test") { diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index fcb6b2a8..beda2d71 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -12,8 +12,10 @@ #include -LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output) : - host(output.c_str()), username("newdeveloper") { +const ColorPoint LedDevicePhilipsHue::BLACK = {0.0f, 0.0f, 0.0f}; + +LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, bool switchOffOnBlack) : + host(output.c_str()), username("newdeveloper"), switchOffOnBlack(switchOffOnBlack) { http = new QHttp(host); timer.setInterval(3000); timer.setSingleShot(true); @@ -37,12 +39,19 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { HueLamp& lamp = lamps.at(idx); // Scale colors from [0, 255] to [0, 1] and convert to xy space. ColorPoint xy = rgbToXYBrightness(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, lamp); + // Switch lamp off if switchOffOnBlack is enabled and the lamp is currently on. + if (switchOffOnBlack && xy == BLACK && lamp.color != BLACK) { + put(getStateRoute(lamp.id), QString("{\"on\": false}")); + } // Write color if color has been changed. - if (xy != lamp.color) { - // Send adjust color command in JSON format. - put(getStateRoute(lamp.id), QString("{\"xy\": [%1, %2]}").arg(xy.x).arg(xy.y)); - // Send brightness color command in JSON format. - put(getStateRoute(lamp.id), QString("{\"bri\": %1}").arg(qRound(xy.bri * 255.0f))); + else if (xy != lamp.color) { + // Switch on if the lamp has been previously switched off. + if (switchOffOnBlack && lamp.color == BLACK) { + put(getStateRoute(lamp.id), QString("{\"on\": true}")); + } + // Send adjust color and brightness command in JSON format. + put(getStateRoute(lamp.id), QString("{\"xy\": [%1, %2], \"bri\": %1}").arg(xy.x).arg(xy.y) + .arg(qRound(xy.bri * 255.0f))); // Remember written color. lamp.color = xy; } diff --git a/libsrc/leddevice/LedDevicePhilipsHue.h b/libsrc/leddevice/LedDevicePhilipsHue.h index d60c2b32..ecbecf3a 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.h +++ b/libsrc/leddevice/LedDevicePhilipsHue.h @@ -71,7 +71,9 @@ public: /// /// @param output the ip address of the bridge /// - LedDevicePhilipsHue(const std::string& output); + /// @param switchOffOnBlack kill lights for black + /// + LedDevicePhilipsHue(const std::string& output, bool switchOffOnBlack); /// /// Destructor of this device @@ -95,6 +97,7 @@ private slots: void restoreStates(); private: + const static ColorPoint BLACK; /// Array to save the lamps. std::vector lamps; /// Ip address of the bridge @@ -105,6 +108,8 @@ private: QHttp* http; /// Use timer to reset lights when we got into "GRABBINGMODE_OFF". QTimer timer; + /// + bool switchOffOnBlack; /// /// Sends a HTTP GET request (blocking). From f76b5ffbd885b9190f7f637e40cf88f1cca5717e Mon Sep 17 00:00:00 2001 From: Tim Niggemann Date: Wed, 16 Jul 2014 16:21:11 +0200 Subject: [PATCH 09/12] Added author tag, added missing return statement. Former-commit-id: 4d0a29a8ba3d33de6f86b90a4eaf2f0de12ea59a --- libsrc/leddevice/LedDevicePhilipsHue.cpp | 16 ++++++++-------- libsrc/leddevice/LedDevicePhilipsHue.h | 4 +--- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index beda2d71..3e960509 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -12,7 +12,7 @@ #include -const ColorPoint LedDevicePhilipsHue::BLACK = {0.0f, 0.0f, 0.0f}; +const ColorPoint LedDevicePhilipsHue::BLACK = { 0.0f, 0.0f, 0.0f }; LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, bool switchOffOnBlack) : host(output.c_str()), username("newdeveloper"), switchOffOnBlack(switchOffOnBlack) { @@ -42,7 +42,7 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { // Switch lamp off if switchOffOnBlack is enabled and the lamp is currently on. if (switchOffOnBlack && xy == BLACK && lamp.color != BLACK) { put(getStateRoute(lamp.id), QString("{\"on\": false}")); - } + } // Write color if color has been changed. else if (xy != lamp.color) { // Switch on if the lamp has been previously switched off. @@ -50,8 +50,8 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { put(getStateRoute(lamp.id), QString("{\"on\": true}")); } // Send adjust color and brightness command in JSON format. - put(getStateRoute(lamp.id), QString("{\"xy\": [%1, %2], \"bri\": %1}").arg(xy.x).arg(xy.y) - .arg(qRound(xy.bri * 255.0f))); + put(getStateRoute(lamp.id), + QString("{\"xy\": [%1, %2], \"bri\": %1}").arg(xy.x).arg(xy.y).arg(qRound(xy.bri * 255.0f))); // Remember written color. lamp.color = xy; } @@ -218,10 +218,11 @@ ColorPoint LedDevicePhilipsHue::rgbToXYBrightness(float red, float green, float if (isnan(cy)) { cy = 0.0f; } - ColorPoint xy = {cx, cy}; + // Brightness is simply Y in the XYZ space. + ColorPoint xy = { cx, cy, Y }; // Check if the given XY value is within the color reach of our lamps. if (!isPointInLampsReach(lamp, xy)) { - // It seems the color is out of reach let's find the closes colour we can produce with our lamp and send this XY value out. + // It seems the color is out of reach let's find the closes color we can produce with our lamp and send this XY value out. ColorPoint pAB = getClosestPointToPoint(lamp.colorSpace.red, lamp.colorSpace.green, xy); ColorPoint pAC = getClosestPointToPoint(lamp.colorSpace.blue, lamp.colorSpace.red, xy); ColorPoint pBC = getClosestPointToPoint(lamp.colorSpace.green, lamp.colorSpace.blue, xy); @@ -243,8 +244,7 @@ ColorPoint LedDevicePhilipsHue::rgbToXYBrightness(float red, float green, float xy.x = closestPoint.x; xy.y = closestPoint.y; } - // Brightness is simply Y in the XYZ space. - xy.bri = Y; + return xy; } HueLamp::HueLamp(unsigned int id, QString originalState, QString modelId) : diff --git a/libsrc/leddevice/LedDevicePhilipsHue.h b/libsrc/leddevice/LedDevicePhilipsHue.h index ecbecf3a..c3503705 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.h +++ b/libsrc/leddevice/LedDevicePhilipsHue.h @@ -61,7 +61,7 @@ public: * Framegrabber must be limited to 10 Hz / numer of lights to avoid rate limitation by the hue bridge. * Create a new API user name "newdeveloper" on the bridge (http://developers.meethue.com/gettingstarted.html) * - * @author ntim (github) + * @author ntim (github), bimsarck (github) */ class LedDevicePhilipsHue: public QObject, public LedDevice { Q_OBJECT @@ -187,7 +187,6 @@ private: /// float crossProduct(ColorPoint p1, ColorPoint p2); - /// /// @param lamp the hue lamp instance /// @@ -197,7 +196,6 @@ private: /// bool isPointInLampsReach(HueLamp lamp, ColorPoint p); - /// /// @param a reference point one /// From f0d2c15aeb7d077ede26cf684128c38a88cf10cf Mon Sep 17 00:00:00 2001 From: Tim Niggemann Date: Wed, 16 Jul 2014 16:45:45 +0200 Subject: [PATCH 10/12] Fixed QString string formatting, added safety check in case the connection to the bridge might be lost. Former-commit-id: fb1f5fd21cd3873fc1b92d763c682e75f345ab42 --- libsrc/leddevice/LedDevicePhilipsHue.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index 3e960509..df2385ef 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -32,6 +32,11 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { saveStates((unsigned int) ledValues.size()); switchOn((unsigned int) ledValues.size()); } + // If there are less states saved than colors given, then maybe something went wrong before. + if (lamps.size() != ledValues.size()) { + restoreStates(); + return 0; + } // Iterate through colors and set light states. unsigned int idx = 0; for (const ColorRgb& color : ledValues) { @@ -51,7 +56,7 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { } // Send adjust color and brightness command in JSON format. put(getStateRoute(lamp.id), - QString("{\"xy\": [%1, %2], \"bri\": %1}").arg(xy.x).arg(xy.y).arg(qRound(xy.bri * 255.0f))); + QString("{\"xy\": [%1, %2], \"bri\": %3}").arg(xy.x).arg(xy.y).arg(qRound(xy.bri * 255.0f))); // Remember written color. lamp.color = xy; } From dbd7a86665705276e91072e17297716b79ad0f47 Mon Sep 17 00:00:00 2001 From: Tim Niggemann Date: Wed, 16 Jul 2014 20:22:37 +0200 Subject: [PATCH 11/12] Moved color logic to lamp class. Former-commit-id: f450eebc8c9d0f29dc053f2115dac6576a5fa591 --- libsrc/leddevice/LedDeviceFactory.cpp | 2 +- libsrc/leddevice/LedDevicePhilipsHue.cpp | 278 ++++++++++++----------- libsrc/leddevice/LedDevicePhilipsHue.h | 129 ++++++----- 3 files changed, 208 insertions(+), 201 deletions(-) diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 5a1bd123..34178421 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -164,7 +164,7 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) else if (type == "philipshue") { const std::string output = deviceConfig["output"].asString(); - const bool switchOffOnBlack = deviceConfig.get("switch_off_on_black", false).asBool(); + const bool switchOffOnBlack = deviceConfig.get("switchOffOnBlack", true).asBool(); device = new LedDevicePhilipsHue(output, switchOffOnBlack); } else if (type == "test") diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index df2385ef..0a47a24c 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -12,7 +12,125 @@ #include -const ColorPoint LedDevicePhilipsHue::BLACK = { 0.0f, 0.0f, 0.0f }; +bool operator ==(CiColor p1, CiColor p2) { + return (p1.x == p2.x) && (p1.y == p2.y) && (p1.bri == p2.bri); +} + +bool operator !=(CiColor p1, CiColor p2) { + return !(p1 == p2); +} + +PhilipsHueLamp::PhilipsHueLamp(unsigned int id, QString originalState, QString modelId) : + id(id), originalState(originalState) { + // Hue system model ids. + const std::set HUE_BULBS_MODEL_IDS = { "LCT001", "LCT002", "LCT003" }; + const std::set LIVING_COLORS_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC011", "LLC012", + "LLC013", "LST001" }; + // Find id in the sets and set the appropiate color space. + if (HUE_BULBS_MODEL_IDS.find(modelId) != HUE_BULBS_MODEL_IDS.end()) { + colorSpace.red = {0.675f, 0.322f}; + colorSpace.green = {0.4091f, 0.518f}; + colorSpace.blue = {0.167f, 0.04f}; + } else if (LIVING_COLORS_MODEL_IDS.find(modelId) != LIVING_COLORS_MODEL_IDS.end()) { + colorSpace.red = {0.703f, 0.296f}; + colorSpace.green = {0.214f, 0.709f}; + colorSpace.blue = {0.139f, 0.081f}; + } else { + colorSpace.red = {1.0f, 0.0f}; + colorSpace.green = {0.0f, 1.0f}; + colorSpace.blue = {0.0f, 0.0f}; + } + // Initialize black color. + black = rgbToCiColor(0.0f, 0.0f, 0.0f); + // Initialize color with black + color = {black.x, black.y, black.bri}; +} + +float PhilipsHueLamp::crossProduct(CiColor p1, CiColor p2) { + return p1.x * p2.y - p1.y * p2.x; +} + +bool PhilipsHueLamp::isPointInLampsReach(CiColor p) { + CiColor v1 = { colorSpace.green.x - colorSpace.red.x, colorSpace.green.y - colorSpace.red.y }; + CiColor v2 = { colorSpace.blue.x - colorSpace.red.x, colorSpace.blue.y - colorSpace.red.y }; + CiColor q = { p.x - colorSpace.red.x, p.y - colorSpace.red.y }; + float s = crossProduct(q, v2) / crossProduct(v1, v2); + float t = crossProduct(v1, q) / crossProduct(v1, v2); + if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) { + return true; + } + return false; +} + +CiColor PhilipsHueLamp::getClosestPointToPoint(CiColor a, CiColor b, CiColor p) { + CiColor AP = { p.x - a.x, p.y - a.y }; + CiColor AB = { b.x - a.x, b.y - a.y }; + float ab2 = AB.x * AB.x + AB.y * AB.y; + float ap_ab = AP.x * AB.x + AP.y * AB.y; + float t = ap_ab / ab2; + if (t < 0.0f) { + t = 0.0f; + } else if (t > 1.0f) { + t = 1.0f; + } + return {a.x + AB.x * t, a.y + AB.y * t}; +} + +float PhilipsHueLamp::getDistanceBetweenTwoPoints(CiColor p1, CiColor p2) { + // Horizontal difference. + float dx = p1.x - p2.x; + // Vertical difference. + float dy = p1.y - p2.y; + // Absolute value. + return sqrt(dx * dx + dy * dy); +} + +CiColor PhilipsHueLamp::rgbToCiColor(float red, float green, float blue) { + // Apply gamma correction. + float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f); + float g = (green > 0.04045f) ? powf((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f); + float b = (blue > 0.04045f) ? powf((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f); + // Convert to XYZ space. + float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; + float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; + float Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f; + // Convert to x,y space. + float cx = X / (X + Y + Z); + float cy = Y / (X + Y + Z); + if (isnan(cx)) { + cx = 0.0f; + } + if (isnan(cy)) { + cy = 0.0f; + } + // Brightness is simply Y in the XYZ space. + CiColor xy = { cx, cy, Y }; + // Check if the given XY value is within the color reach of our lamps. + if (!isPointInLampsReach(xy)) { + // It seems the color is out of reach let's find the closes color we can produce with our lamp and send this XY value out. + CiColor pAB = getClosestPointToPoint(colorSpace.red, colorSpace.green, xy); + CiColor pAC = getClosestPointToPoint(colorSpace.blue, colorSpace.red, xy); + CiColor pBC = getClosestPointToPoint(colorSpace.green, colorSpace.blue, xy); + // Get the distances per point and see which point is closer to our Point. + float dAB = getDistanceBetweenTwoPoints(xy, pAB); + float dAC = getDistanceBetweenTwoPoints(xy, pAC); + float dBC = getDistanceBetweenTwoPoints(xy, pBC); + float lowest = dAB; + CiColor closestPoint = pAB; + if (dAC < lowest) { + lowest = dAC; + closestPoint = pAC; + } + if (dBC < lowest) { + lowest = dBC; + closestPoint = pBC; + } + // Change the xy value to a value which is within the reach of the lamp. + xy.x = closestPoint.x; + xy.y = closestPoint.y; + } + return xy; +} LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, bool switchOffOnBlack) : host(output.c_str()), username("newdeveloper"), switchOffOnBlack(switchOffOnBlack) { @@ -41,25 +159,35 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { unsigned int idx = 0; for (const ColorRgb& color : ledValues) { // Get lamp. - HueLamp& lamp = lamps.at(idx); + PhilipsHueLamp& lamp = lamps.at(idx); // Scale colors from [0, 255] to [0, 1] and convert to xy space. - ColorPoint xy = rgbToXYBrightness(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, lamp); - // Switch lamp off if switchOffOnBlack is enabled and the lamp is currently on. - if (switchOffOnBlack && xy == BLACK && lamp.color != BLACK) { - put(getStateRoute(lamp.id), QString("{\"on\": false}")); - } + CiColor xy = lamp.rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f); // Write color if color has been changed. - else if (xy != lamp.color) { + if (xy != lamp.color) { // Switch on if the lamp has been previously switched off. - if (switchOffOnBlack && lamp.color == BLACK) { - put(getStateRoute(lamp.id), QString("{\"on\": true}")); + if (switchOffOnBlack && lamp.color == lamp.black) { + } // Send adjust color and brightness command in JSON format. put(getStateRoute(lamp.id), QString("{\"xy\": [%1, %2], \"bri\": %3}").arg(xy.x).arg(xy.y).arg(qRound(xy.bri * 255.0f))); - // Remember written color. - lamp.color = xy; + } + // Switch lamp off if switchOffOnBlack is enabled and the lamp is currently on. + if (switchOffOnBlack) { + // From black to a color. + if (lamp.color == lamp.black && xy != lamp.black) { + put(getStateRoute(lamp.id), QString("{\"on\": true}")); + std::cout << "switchon" << std::endl; + } + // From a color to black. + else if (lamp.color != lamp.black && xy == lamp.black) { + put(getStateRoute(lamp.id), QString("{\"on\": false}")); + std::cout << "switchoff" << std::endl; + } + } + // Remember last color. + lamp.color = xy; // Next light id. idx++; } @@ -142,18 +270,18 @@ void LedDevicePhilipsHue::saveStates(unsigned int nLights) { QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", ""); QString originalState = QString(writer.write(state).c_str()).trimmed(); // Save state object. - lamps.push_back(HueLamp(i + 1, originalState, modelId)); + lamps.push_back(PhilipsHueLamp(i + 1, originalState, modelId)); } } void LedDevicePhilipsHue::switchOn(unsigned int nLights) { - for (HueLamp lamp : lamps) { + for (PhilipsHueLamp lamp : lamps) { put(getStateRoute(lamp.id), "{\"on\": true}"); } } void LedDevicePhilipsHue::restoreStates() { - for (HueLamp lamp : lamps) { + for (PhilipsHueLamp lamp : lamps) { put(getStateRoute(lamp.id), lamp.originalState); } // Clear saved light states. @@ -163,123 +291,3 @@ void LedDevicePhilipsHue::restoreStates() { bool LedDevicePhilipsHue::areStatesSaved() { return !lamps.empty(); } - -float LedDevicePhilipsHue::crossProduct(ColorPoint p1, ColorPoint p2) { - return p1.x * p2.y - p1.y * p2.x; -} - -bool LedDevicePhilipsHue::isPointInLampsReach(HueLamp lamp, ColorPoint p) { - ColorTriangle& triangle = lamp.colorSpace; - ColorPoint v1 = { triangle.green.x - triangle.red.x, triangle.green.y - triangle.red.y }; - ColorPoint v2 = { triangle.blue.x - triangle.red.x, triangle.blue.y - triangle.red.y }; - ColorPoint q = { p.x - triangle.red.x, p.y - triangle.red.y }; - float s = crossProduct(q, v2) / crossProduct(v1, v2); - float t = crossProduct(v1, q) / crossProduct(v1, v2); - if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) { - return true; - } else { - return false; - } -} - -ColorPoint LedDevicePhilipsHue::getClosestPointToPoint(ColorPoint a, ColorPoint b, ColorPoint p) { - ColorPoint AP = { p.x - a.x, p.y - a.y }; - ColorPoint AB = { b.x - a.x, b.y - a.y }; - float ab2 = AB.x * AB.x + AB.y * AB.y; - float ap_ab = AP.x * AB.x + AP.y * AB.y; - float t = ap_ab / ab2; - if (t < 0.0f) { - t = 0.0f; - } else if (t > 1.0f) { - t = 1.0f; - } - return {a.x + AB.x * t, a.y + AB.y * t}; -} - -float LedDevicePhilipsHue::getDistanceBetweenTwoPoints(ColorPoint p1, ColorPoint p2) { - // Horizontal difference. - float dx = p1.x - p2.x; - // Vertical difference. - float dy = p1.y - p2.y; - // Absolute value. - return sqrt(dx * dx + dy * dy); -} - -ColorPoint LedDevicePhilipsHue::rgbToXYBrightness(float red, float green, float blue, HueLamp lamp) { - // Apply gamma correction. - float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f); - float g = (green > 0.04045f) ? powf((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f); - float b = (blue > 0.04045f) ? powf((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f); - // Convert to XYZ space. - float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; - float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; - float Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f; - // Convert to x,y space. - float cx = X / (X + Y + Z); - float cy = Y / (X + Y + Z); - if (isnan(cx)) { - cx = 0.0f; - } - if (isnan(cy)) { - cy = 0.0f; - } - // Brightness is simply Y in the XYZ space. - ColorPoint xy = { cx, cy, Y }; - // Check if the given XY value is within the color reach of our lamps. - if (!isPointInLampsReach(lamp, xy)) { - // It seems the color is out of reach let's find the closes color we can produce with our lamp and send this XY value out. - ColorPoint pAB = getClosestPointToPoint(lamp.colorSpace.red, lamp.colorSpace.green, xy); - ColorPoint pAC = getClosestPointToPoint(lamp.colorSpace.blue, lamp.colorSpace.red, xy); - ColorPoint pBC = getClosestPointToPoint(lamp.colorSpace.green, lamp.colorSpace.blue, xy); - // Get the distances per point and see which point is closer to our Point. - float dAB = getDistanceBetweenTwoPoints(xy, pAB); - float dAC = getDistanceBetweenTwoPoints(xy, pAC); - float dBC = getDistanceBetweenTwoPoints(xy, pBC); - float lowest = dAB; - ColorPoint closestPoint = pAB; - if (dAC < lowest) { - lowest = dAC; - closestPoint = pAC; - } - if (dBC < lowest) { - lowest = dBC; - closestPoint = pBC; - } - // Change the xy value to a value which is within the reach of the lamp. - xy.x = closestPoint.x; - xy.y = closestPoint.y; - } - return xy; -} - -HueLamp::HueLamp(unsigned int id, QString originalState, QString modelId) : - id(id), originalState(originalState) { - // Hue system model ids. - const std::set HUE_BULBS_MODEL_IDS = { "LCT001", "LCT002", "LCT003" }; - const std::set LIVING_COLORS_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC011", "LLC012", - "LLC013", "LST001" }; - // Find id in the sets and set the appropiate color space. - if (HUE_BULBS_MODEL_IDS.find(modelId) != HUE_BULBS_MODEL_IDS.end()) { - colorSpace.red = {0.675f, 0.322f}; - colorSpace.green = {0.4091f, 0.518f}; - colorSpace.blue = {0.167f, 0.04f}; - } else if (LIVING_COLORS_MODEL_IDS.find(modelId) != LIVING_COLORS_MODEL_IDS.end()) { - colorSpace.red = {0.703f, 0.296f}; - colorSpace.green = {0.214f, 0.709f}; - colorSpace.blue = {0.139f, 0.081f}; - } else { - colorSpace.red = {1.0f, 0.0f}; - colorSpace.green = {0.0f, 1.0f}; - colorSpace.blue = {0.0f, 0.0f}; - } - // Initialize color with black - color = {0.0f, 0.0f, 0.0f}; -} - -bool operator ==(ColorPoint p1, ColorPoint p2) { - return (p1.x == p2.x) && (p1.y == p2.y) && (p1.bri == p2.bri); -} - -bool operator !=(ColorPoint p1, ColorPoint p2) { - return !(p1 == p2); -} diff --git a/libsrc/leddevice/LedDevicePhilipsHue.h b/libsrc/leddevice/LedDevicePhilipsHue.h index c3503705..085defb0 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.h +++ b/libsrc/leddevice/LedDevicePhilipsHue.h @@ -15,30 +15,34 @@ /** * A color point in the color space of the hue system. */ -struct ColorPoint { +struct CiColor { + /// X component. float x; + /// Y component. float y; + /// The brightness. float bri; }; -bool operator==(ColorPoint p1, ColorPoint p2); -bool operator!=(ColorPoint p1, ColorPoint p2); +bool operator==(CiColor p1, CiColor p2); +bool operator!=(CiColor p1, CiColor p2); /** * Color triangle to define an available color space for the hue lamps. */ -struct ColorTriangle { - ColorPoint red, green, blue; +struct CiColorTriangle { + CiColor red, green, blue; }; /** * Simple class to hold the id, the latest color, the color space and the original state. */ -class HueLamp { +class PhilipsHueLamp { public: unsigned int id; - ColorPoint color; - ColorTriangle colorSpace; + CiColor black; + CiColor color; + CiColorTriangle colorSpace; QString originalState; /// @@ -50,7 +54,57 @@ public: /// /// @param modelId the model id of the hue lamp which is used to determine the color space /// - HueLamp(unsigned int id, QString originalState, QString modelId); + PhilipsHueLamp(unsigned int id, QString originalState, QString modelId); + + /// + /// Converts an RGB color to the Hue xy color space and brightness. + /// https://github.com/PhilipsHue/PhilipsHueSDK-iOS-OSX/blob/master/ApplicationDesignNotes/RGB%20to%20xy%20Color%20conversion.md + /// + /// @param red the red component in [0, 1] + /// + /// @param green the green component in [0, 1] + /// + /// @param blue the blue component in [0, 1] + /// + /// @return color point + /// + CiColor rgbToCiColor(float red, float green, float blue); + + /// + /// @param p the color point to check + /// + /// @return true if the color point is covered by the lamp color space + /// + bool isPointInLampsReach(CiColor p); + + /// + /// @param p1 point one + /// + /// @param p2 point tow + /// + /// @return the cross product between p1 and p2 + /// + float crossProduct(CiColor p1, CiColor p2); + + /// + /// @param a reference point one + /// + /// @param b reference point two + /// + /// @param p the point to which the closest point is to be found + /// + /// @return the closest color point of p to a and b + /// + CiColor getClosestPointToPoint(CiColor a, CiColor b, CiColor p); + + /// + /// @param p1 point one + /// + /// @param p2 point tow + /// + /// @return the distance between the two points + /// + float getDistanceBetweenTwoPoints(CiColor p1, CiColor p2); }; /** @@ -97,9 +151,8 @@ private slots: void restoreStates(); private: - const static ColorPoint BLACK; /// Array to save the lamps. - std::vector lamps; + std::vector lamps; /// Ip address of the bridge QString host; /// User name for the API ("newdeveloper") @@ -162,58 +215,4 @@ private: /// bool areStatesSaved(); - /// - /// Converts an RGB color to the Hue xy color space and brightness. - /// https://github.com/PhilipsHue/PhilipsHueSDK-iOS-OSX/blob/master/ApplicationDesignNotes/RGB%20to%20xy%20Color%20conversion.md - /// - /// @param red the red component in [0, 1] - /// - /// @param green the green component in [0, 1] - /// - /// @param blue the blue component in [0, 1] - /// - /// @param lamp the hue lamp instance used for color space checks. - /// - /// @return color point - /// - ColorPoint rgbToXYBrightness(float red, float green, float blue, HueLamp lamp); - - /// - /// @param p1 point one - /// - /// @param p2 point tow - /// - /// @return the cross product between p1 and p2 - /// - float crossProduct(ColorPoint p1, ColorPoint p2); - - /// - /// @param lamp the hue lamp instance - /// - /// @param p the color point to check - /// - /// @return true if the color point is covered by the lamp color space - /// - bool isPointInLampsReach(HueLamp lamp, ColorPoint p); - - /// - /// @param a reference point one - /// - /// @param b reference point two - /// - /// @param p the point to which the closest point is to be found - /// - /// @return the closest color point of p to a and b - /// - ColorPoint getClosestPointToPoint(ColorPoint a, ColorPoint b, ColorPoint p); - - /// - /// @param p1 point one - /// - /// @param p2 point tow - /// - /// @return the distance between the two points - /// - float getDistanceBetweenTwoPoints(ColorPoint p1, ColorPoint p2); - }; From dc2e173f040e23d80529c11e743e43d20bd89b99 Mon Sep 17 00:00:00 2001 From: ntim Date: Wed, 16 Jul 2014 20:46:59 +0200 Subject: [PATCH 12/12] Remove couts. Former-commit-id: fdc93ea33644313277bd4b01c14e4a63396c077f --- libsrc/leddevice/LedDevicePhilipsHue.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index 0a47a24c..35607871 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -178,12 +178,10 @@ int LedDevicePhilipsHue::write(const std::vector & ledValues) { // From black to a color. if (lamp.color == lamp.black && xy != lamp.black) { put(getStateRoute(lamp.id), QString("{\"on\": true}")); - std::cout << "switchon" << std::endl; } // From a color to black. else if (lamp.color != lamp.black && xy == lamp.black) { put(getStateRoute(lamp.id), QString("{\"on\": false}")); - std::cout << "switchoff" << std::endl; } } // Remember last color.