mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Merge branch 'ntim-support_for_philips_hue'
Former-commit-id: 20e15c8247d4cb8274719fd1b1705348bf2c54af
This commit is contained in:
commit
2790ed8eb9
@ -196,7 +196,11 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig)
|
|||||||
const std::string username = deviceConfig.get("username", "newdeveloper").asString();
|
const std::string username = deviceConfig.get("username", "newdeveloper").asString();
|
||||||
const bool switchOffOnBlack = deviceConfig.get("switchOffOnBlack", true).asBool();
|
const bool switchOffOnBlack = deviceConfig.get("switchOffOnBlack", true).asBool();
|
||||||
const int transitiontime = deviceConfig.get("transitiontime", 1).asInt();
|
const int transitiontime = deviceConfig.get("transitiontime", 1).asInt();
|
||||||
device = new LedDevicePhilipsHue(output, username, switchOffOnBlack, transitiontime);
|
std::vector<unsigned int> lightIds;
|
||||||
|
for (Json::Value::ArrayIndex i = 0; i < deviceConfig["lightIds"].size(); i++) {
|
||||||
|
lightIds.push_back(deviceConfig["lightIds"][i].asInt());
|
||||||
|
}
|
||||||
|
device = new LedDevicePhilipsHue(output, username, switchOffOnBlack, transitiontime, lightIds);
|
||||||
}
|
}
|
||||||
else if (type == "test")
|
else if (type == "test")
|
||||||
{
|
{
|
||||||
|
@ -20,21 +20,23 @@ bool operator !=(CiColor p1, CiColor p2) {
|
|||||||
return !(p1 == p2);
|
return !(p1 == p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
PhilipsHueLamp::PhilipsHueLamp(unsigned int id, QString originalState, QString modelId) :
|
PhilipsHueLight::PhilipsHueLight(unsigned int id, QString originalState, QString modelId) :
|
||||||
id(id), originalState(originalState) {
|
id(id), originalState(originalState) {
|
||||||
// Hue system model ids.
|
// Hue system model ids (http://www.developers.meethue.com/documentation/supported-lights).
|
||||||
const std::set<QString> HUE_BULBS_MODEL_IDS = { "LCT001", "LCT002", "LCT003" };
|
// Light strips, color iris, ...
|
||||||
const std::set<QString> LIVING_COLORS_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC011", "LLC012",
|
const std::set<QString> GAMUT_A_MODEL_IDS = { "LLC001", "LLC005", "LLC006", "LLC007", "LLC010", "LLC011", "LLC012",
|
||||||
"LLC013", "LST001" };
|
"LLC013", "LST001" };
|
||||||
|
// Hue bulbs, spots, ...
|
||||||
|
const std::set<QString> GAMUT_B_MODEL_IDS = { "LCT001", "LCT002", "LCT003", "LLM001" };
|
||||||
// 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()) {
|
if (GAMUT_A_MODEL_IDS.find(modelId) != GAMUT_A_MODEL_IDS.end()) {
|
||||||
|
colorSpace.red = {0.703f, 0.296f};
|
||||||
|
colorSpace.green = {0.2151f, 0.7106f};
|
||||||
|
colorSpace.blue = {0.138f, 0.08f};
|
||||||
|
} else if (GAMUT_B_MODEL_IDS.find(modelId) != GAMUT_B_MODEL_IDS.end()) {
|
||||||
colorSpace.red = {0.675f, 0.322f};
|
colorSpace.red = {0.675f, 0.322f};
|
||||||
colorSpace.green = {0.4091f, 0.518f};
|
colorSpace.green = {0.4091f, 0.518f};
|
||||||
colorSpace.blue = {0.167f, 0.04f};
|
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 {
|
} else {
|
||||||
colorSpace.red = {1.0f, 0.0f};
|
colorSpace.red = {1.0f, 0.0f};
|
||||||
colorSpace.green = {0.0f, 1.0f};
|
colorSpace.green = {0.0f, 1.0f};
|
||||||
@ -46,11 +48,11 @@ PhilipsHueLamp::PhilipsHueLamp(unsigned int id, QString originalState, QString m
|
|||||||
color = {black.x, black.y, black.bri};
|
color = {black.x, black.y, black.bri};
|
||||||
}
|
}
|
||||||
|
|
||||||
float PhilipsHueLamp::crossProduct(CiColor p1, CiColor p2) {
|
float PhilipsHueLight::crossProduct(CiColor p1, CiColor p2) {
|
||||||
return p1.x * p2.y - p1.y * p2.x;
|
return p1.x * p2.y - p1.y * p2.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhilipsHueLamp::isPointInLampsReach(CiColor p) {
|
bool PhilipsHueLight::isPointInLampsReach(CiColor p) {
|
||||||
CiColor v1 = { colorSpace.green.x - colorSpace.red.x, colorSpace.green.y - colorSpace.red.y };
|
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 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 };
|
CiColor q = { p.x - colorSpace.red.x, p.y - colorSpace.red.y };
|
||||||
@ -62,7 +64,7 @@ bool PhilipsHueLamp::isPointInLampsReach(CiColor p) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CiColor PhilipsHueLamp::getClosestPointToPoint(CiColor a, CiColor b, CiColor p) {
|
CiColor PhilipsHueLight::getClosestPointToPoint(CiColor a, CiColor b, CiColor p) {
|
||||||
CiColor AP = { p.x - a.x, p.y - a.y };
|
CiColor AP = { p.x - a.x, p.y - a.y };
|
||||||
CiColor AB = { b.x - a.x, b.y - a.y };
|
CiColor AB = { b.x - a.x, b.y - a.y };
|
||||||
float ab2 = AB.x * AB.x + AB.y * AB.y;
|
float ab2 = AB.x * AB.x + AB.y * AB.y;
|
||||||
@ -76,7 +78,7 @@ CiColor PhilipsHueLamp::getClosestPointToPoint(CiColor a, CiColor b, CiColor p)
|
|||||||
return {a.x + AB.x * t, a.y + AB.y * t};
|
return {a.x + AB.x * t, a.y + AB.y * t};
|
||||||
}
|
}
|
||||||
|
|
||||||
float PhilipsHueLamp::getDistanceBetweenTwoPoints(CiColor p1, CiColor p2) {
|
float PhilipsHueLight::getDistanceBetweenTwoPoints(CiColor p1, CiColor p2) {
|
||||||
// Horizontal difference.
|
// Horizontal difference.
|
||||||
float dx = p1.x - p2.x;
|
float dx = p1.x - p2.x;
|
||||||
// Vertical difference.
|
// Vertical difference.
|
||||||
@ -85,7 +87,7 @@ float PhilipsHueLamp::getDistanceBetweenTwoPoints(CiColor p1, CiColor p2) {
|
|||||||
return sqrt(dx * dx + dy * dy);
|
return sqrt(dx * dx + dy * dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
CiColor PhilipsHueLamp::rgbToCiColor(float red, float green, float blue) {
|
CiColor PhilipsHueLight::rgbToCiColor(float red, float green, float blue) {
|
||||||
// Apply gamma correction.
|
// Apply gamma correction.
|
||||||
float r = (red > 0.04045f) ? powf((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f);
|
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 g = (green > 0.04045f) ? powf((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f);
|
||||||
@ -133,9 +135,9 @@ CiColor PhilipsHueLamp::rgbToCiColor(float red, float green, float blue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::string& username, bool switchOffOnBlack,
|
LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::string& username, bool switchOffOnBlack,
|
||||||
int transitiontime) :
|
int transitiontime, std::vector<unsigned int> lightIds) :
|
||||||
host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime(
|
host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime(
|
||||||
transitiontime) {
|
transitiontime), lightIds(lightIds) {
|
||||||
http = new QHttp(host);
|
http = new QHttp(host);
|
||||||
timer.setInterval(3000);
|
timer.setInterval(3000);
|
||||||
timer.setSingleShot(true);
|
timer.setSingleShot(true);
|
||||||
@ -153,7 +155,7 @@ int LedDevicePhilipsHue::write(const std::vector<ColorRgb> & ledValues) {
|
|||||||
switchOn((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 there are less states saved than colors given, then maybe something went wrong before.
|
||||||
if (lamps.size() != ledValues.size()) {
|
if (lights.size() != ledValues.size()) {
|
||||||
restoreStates();
|
restoreStates();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -161,7 +163,7 @@ int LedDevicePhilipsHue::write(const std::vector<ColorRgb> & ledValues) {
|
|||||||
unsigned int idx = 0;
|
unsigned int idx = 0;
|
||||||
for (const ColorRgb& color : ledValues) {
|
for (const ColorRgb& color : ledValues) {
|
||||||
// Get lamp.
|
// Get lamp.
|
||||||
PhilipsHueLamp& lamp = lamps.at(idx);
|
PhilipsHueLight& lamp = lights.at(idx);
|
||||||
// Scale colors from [0, 255] to [0, 1] and convert to xy space.
|
// Scale colors from [0, 255] to [0, 1] and convert to xy space.
|
||||||
CiColor xy = lamp.rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f);
|
CiColor xy = lamp.rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f);
|
||||||
// Write color if color has been changed.
|
// Write color if color has been changed.
|
||||||
@ -247,14 +249,21 @@ QString LedDevicePhilipsHue::getRoute(unsigned int lightId) {
|
|||||||
|
|
||||||
void LedDevicePhilipsHue::saveStates(unsigned int nLights) {
|
void LedDevicePhilipsHue::saveStates(unsigned int nLights) {
|
||||||
// Clear saved lamps.
|
// Clear saved lamps.
|
||||||
lamps.clear();
|
lights.clear();
|
||||||
// Use json parser to parse reponse.
|
// Use json parser to parse reponse.
|
||||||
Json::Reader reader;
|
Json::Reader reader;
|
||||||
Json::FastWriter writer;
|
Json::FastWriter writer;
|
||||||
|
// Create light ids if none supplied by the user.
|
||||||
|
if (lightIds.size() != nLights) {
|
||||||
|
lightIds.clear();
|
||||||
|
for (unsigned int i = 0; i < nLights; i++) {
|
||||||
|
lightIds.push_back(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Iterate lights.
|
// Iterate lights.
|
||||||
for (unsigned int i = 0; i < nLights; i++) {
|
for (unsigned int i = 0; i < nLights; i++) {
|
||||||
// Read the response.
|
// Read the response.
|
||||||
QByteArray response = get(getRoute(i + 1));
|
QByteArray response = get(getRoute(lightIds.at(i)));
|
||||||
// Parse JSON.
|
// Parse JSON.
|
||||||
Json::Value json;
|
Json::Value json;
|
||||||
if (!reader.parse(QString(response).toStdString(), json)) {
|
if (!reader.parse(QString(response).toStdString(), json)) {
|
||||||
@ -272,24 +281,24 @@ void LedDevicePhilipsHue::saveStates(unsigned int nLights) {
|
|||||||
QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", "");
|
QString modelId = QString(writer.write(json["modelid"]).c_str()).trimmed().replace("\"", "");
|
||||||
QString originalState = QString(writer.write(state).c_str()).trimmed();
|
QString originalState = QString(writer.write(state).c_str()).trimmed();
|
||||||
// Save state object.
|
// Save state object.
|
||||||
lamps.push_back(PhilipsHueLamp(i + 1, originalState, modelId));
|
lights.push_back(PhilipsHueLight(lightIds.at(i), originalState, modelId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedDevicePhilipsHue::switchOn(unsigned int nLights) {
|
void LedDevicePhilipsHue::switchOn(unsigned int nLights) {
|
||||||
for (PhilipsHueLamp lamp : lamps) {
|
for (PhilipsHueLight light : lights) {
|
||||||
put(getStateRoute(lamp.id), "{\"on\": true}");
|
put(getStateRoute(light.id), "{\"on\": true}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedDevicePhilipsHue::restoreStates() {
|
void LedDevicePhilipsHue::restoreStates() {
|
||||||
for (PhilipsHueLamp lamp : lamps) {
|
for (PhilipsHueLight light : lights) {
|
||||||
put(getStateRoute(lamp.id), lamp.originalState);
|
put(getStateRoute(light.id), light.originalState);
|
||||||
}
|
}
|
||||||
// Clear saved light states.
|
// Clear saved light states.
|
||||||
lamps.clear();
|
lights.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LedDevicePhilipsHue::areStatesSaved() {
|
bool LedDevicePhilipsHue::areStatesSaved() {
|
||||||
return !lamps.empty();
|
return !lights.empty();
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ struct CiColorTriangle {
|
|||||||
/**
|
/**
|
||||||
* Simple class to hold the id, the latest color, the color space and the original state.
|
* Simple class to hold the id, the latest color, the color space and the original state.
|
||||||
*/
|
*/
|
||||||
class PhilipsHueLamp {
|
class PhilipsHueLight {
|
||||||
public:
|
public:
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
CiColor black;
|
CiColor black;
|
||||||
@ -46,7 +46,7 @@ public:
|
|||||||
QString originalState;
|
QString originalState;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Constructs the lamp.
|
/// Constructs the light.
|
||||||
///
|
///
|
||||||
/// @param id the light id
|
/// @param id the light id
|
||||||
///
|
///
|
||||||
@ -54,7 +54,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// @param modelId the model id of the hue lamp which is used to determine the color space
|
/// @param modelId the model id of the hue lamp which is used to determine the color space
|
||||||
///
|
///
|
||||||
PhilipsHueLamp(unsigned int id, QString originalState, QString modelId);
|
PhilipsHueLight(unsigned int id, QString originalState, QString modelId);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Converts an RGB color to the Hue xy color space and brightness.
|
/// Converts an RGB color to the Hue xy color space and brightness.
|
||||||
@ -131,8 +131,10 @@ public:
|
|||||||
///
|
///
|
||||||
/// @param transitiontime the time duration a light change takes in multiples of 100 ms (default: 400 ms).
|
/// @param transitiontime the time duration a light change takes in multiples of 100 ms (default: 400 ms).
|
||||||
///
|
///
|
||||||
|
/// @param lightIds light ids of the lights to control if not starting at one in ascending order.
|
||||||
|
///
|
||||||
LedDevicePhilipsHue(const std::string& output, const std::string& username = "newdeveloper", bool switchOffOnBlack =
|
LedDevicePhilipsHue(const std::string& output, const std::string& username = "newdeveloper", bool switchOffOnBlack =
|
||||||
false, int transitiontime = 1);
|
false, int transitiontime = 1, std::vector<unsigned int> lightIds = {});
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Destructor of this device
|
/// Destructor of this device
|
||||||
@ -157,7 +159,7 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
/// Array to save the lamps.
|
/// Array to save the lamps.
|
||||||
std::vector<PhilipsHueLamp> lamps;
|
std::vector<PhilipsHueLight> lights;
|
||||||
/// Ip address of the bridge
|
/// Ip address of the bridge
|
||||||
QString host;
|
QString host;
|
||||||
/// User name for the API ("newdeveloper")
|
/// User name for the API ("newdeveloper")
|
||||||
@ -171,6 +173,8 @@ private:
|
|||||||
/// Transition time in multiples of 100 ms.
|
/// Transition time in multiples of 100 ms.
|
||||||
/// The default of the Hue lights will be 400 ms, but we want to have it snapier
|
/// The default of the Hue lights will be 400 ms, but we want to have it snapier
|
||||||
int transitiontime;
|
int transitiontime;
|
||||||
|
/// Array of the light ids.
|
||||||
|
std::vector<unsigned int> lightIds;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Sends a HTTP GET request (blocking).
|
/// Sends a HTTP GET request (blocking).
|
||||||
|
Loading…
Reference in New Issue
Block a user