Fix setting and getting color temperature for Philips Hue emulation

- Improve setting and getting color temperature for Philips Hue emulation
- Clamp Philips Hue API values
- Turn off white LEDs when setting hue+saturation
This commit is contained in:
Erik 2018-09-08 08:49:08 +02:00
parent f517755303
commit b5d7f75647
2 changed files with 41 additions and 18 deletions

View File

@ -557,8 +557,8 @@ void LightState(uint8_t append)
if (light_subtype > LST_SINGLE) { if (light_subtype > LST_SINGLE) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLOR "\":\"%s\""), mqtt_data, LightGetColor(0, scolor)); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLOR "\":\"%s\""), mqtt_data, LightGetColor(0, scolor));
// Add status for HSB // Add status for HSB
LightGetHsb(&hsb[0],&hsb[1],&hsb[2]); LightGetHsb(&hsb[0],&hsb[1],&hsb[2], false);
// Scale these percentages up to the numbers expected byt he client // Scale these percentages up to the numbers expected by the client
h = round(hsb[0] * 360); h = round(hsb[0] * 360);
s = round(hsb[1] * 100); s = round(hsb[1] * 100);
b = round(hsb[2] * 100); b = round(hsb[2] * 100);
@ -911,13 +911,15 @@ void LightHsbToRgb()
light_current_color[0] = (uint8_t)(r * 255.0f); light_current_color[0] = (uint8_t)(r * 255.0f);
light_current_color[1] = (uint8_t)(g * 255.0f); light_current_color[1] = (uint8_t)(g * 255.0f);
light_current_color[2] = (uint8_t)(b * 255.0f); light_current_color[2] = (uint8_t)(b * 255.0f);
light_current_color[3] = 0;
light_current_color[4] = 0;
} }
/********************************************************************************************/ /********************************************************************************************/
void LightGetHsb(float *hue, float *sat, float *bri) void LightGetHsb(float *hue, float *sat, float *bri, bool gotct)
{ {
if (light_subtype > LST_COLDWARM) { if (light_subtype > LST_COLDWARM && !gotct) {
LightRgbToHsb(); LightRgbToHsb();
*hue = light_hue; *hue = light_hue;
*sat = light_saturation; *sat = light_saturation;
@ -925,16 +927,19 @@ void LightGetHsb(float *hue, float *sat, float *bri)
} else { } else {
*hue = 0; *hue = 0;
*sat = 0; *sat = 0;
// *bri = (2.54f * (float)Settings.light_dimmer);
*bri = (0.01f * (float)Settings.light_dimmer); *bri = (0.01f * (float)Settings.light_dimmer);
} }
} }
void LightSetHsb(float hue, float sat, float bri, uint16_t ct) void LightSetHsb(float hue, float sat, float bri, uint16_t ct, bool gotct)
{ {
if (light_subtype > LST_COLDWARM) { if (light_subtype > LST_COLDWARM) {
if ((LST_RGBWC == light_subtype) && (ct > 0)) { if ((LST_RGBWC == light_subtype) && (gotct)) {
uint8_t tmp = (uint8_t)(bri * 100);
Settings.light_dimmer = tmp;
if (ct > 0) {
LightSetColorTemp(ct); LightSetColorTemp(ct);
}
} else { } else {
light_hue = hue; light_hue = hue;
light_saturation = sat; light_saturation = sat;
@ -1114,7 +1119,7 @@ boolean LightCommand()
} else { // Command with only 1 parameter, Hue (0<H<360), Saturation (0<S<100) OR Brightness (0<B<100) } else { // Command with only 1 parameter, Hue (0<H<360), Saturation (0<S<100) OR Brightness (0<B<100)
float hsb[3]; float hsb[3];
LightGetHsb(&hsb[0],&hsb[1],&hsb[2]); LightGetHsb(&hsb[0],&hsb[1],&hsb[2], false);
HSB[0] = round(hsb[0] * 360); HSB[0] = round(hsb[0] * 360);
HSB[1] = round(hsb[1] * 100); HSB[1] = round(hsb[1] * 100);
HSB[2] = round(hsb[2] * 100); HSB[2] = round(hsb[2] * 100);
@ -1130,7 +1135,8 @@ boolean LightCommand()
LightSetHsb(( (HSB[0]>360) ? (HSB[0] % 360) : HSB[0] ) /360.0, LightSetHsb(( (HSB[0]>360) ? (HSB[0] % 360) : HSB[0] ) /360.0,
( (HSB[1]>100) ? (HSB[1] % 100) : HSB[1] ) /100.0, ( (HSB[1]>100) ? (HSB[1] % 100) : HSB[1] ) /100.0,
( (HSB[2]>100) ? (HSB[2] % 100) : HSB[2] ) /100.0, ( (HSB[2]>100) ? (HSB[2] % 100) : HSB[2] ) /100.0,
0); 0,
false);
} }
} else { } else {
LightState(0); LightState(0);

View File

@ -17,6 +17,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#if defined(USE_WEBSERVER) && defined(USE_EMULATION) #if defined(USE_WEBSERVER) && defined(USE_EMULATION)
/*********************************************************************************************\ /*********************************************************************************************\
* Belkin WeMo and Philips Hue bridge emulation * Belkin WeMo and Philips Hue bridge emulation
@ -462,10 +465,10 @@ const char HUE_LIGHTS_STATUS_JSON[] PROGMEM =
"\"hue\":{h}," "\"hue\":{h},"
"\"sat\":{s}," "\"sat\":{s},"
"\"xy\":[0.5, 0.5]," "\"xy\":[0.5, 0.5],"
"\"ct\":500," "\"ct\":{t},"
"\"alert\":\"none\"," "\"alert\":\"none\","
"\"effect\":\"none\"," "\"effect\":\"none\","
"\"colormode\":\"hs\"," "\"colormode\":\"{m}\","
"\"reachable\":true}"; "\"reachable\":true}";
const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM =
",\"type\":\"Extended color light\"," ",\"type\":\"Extended color light\","
@ -559,20 +562,26 @@ void HueConfig(String *path)
WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response);
} }
bool g_gotct = false;
void HueLightStatus1(byte device, String *response) void HueLightStatus1(byte device, String *response)
{ {
float hue = 0; float hue = 0;
float sat = 0; float sat = 0;
float bri = 0; float bri = 0;
uint16_t ct = 500;
if (light_type) { if (light_type) {
LightGetHsb(&hue, &sat, &bri); LightGetHsb(&hue, &sat, &bri, g_gotct);
ct = LightGetColorTemp();
} }
*response += FPSTR(HUE_LIGHTS_STATUS_JSON); *response += FPSTR(HUE_LIGHTS_STATUS_JSON);
response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false"); response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false");
response->replace("{h}", String((uint16_t)(65535.0f * hue))); response->replace("{h}", String((uint16_t)(65535.0f * hue)));
response->replace("{s}", String((uint8_t)(254.0f * sat))); response->replace("{s}", String((uint8_t)(254.0f * sat)));
response->replace("{b}", String((uint8_t)(254.0f * bri))); response->replace("{b}", String((uint8_t)(254.0f * bri)));
response->replace("{t}", String(ct));
response->replace("{m}", g_gotct?"ct":"hs");
} }
void HueLightStatus2(byte device, String *response) void HueLightStatus2(byte device, String *response)
@ -678,11 +687,13 @@ void HueLights(String *path)
} }
if (light_type) { if (light_type) {
LightGetHsb(&hue, &sat, &bri); LightGetHsb(&hue, &sat, &bri, g_gotct);
} }
if (hue_json.containsKey("bri")) { if (hue_json.containsKey("bri")) { // Brightness is a scale from 1 (the minimum the light is capable of) to 254 (the maximum). Note: a brightness of 1 is not off.
tmp = hue_json["bri"]; tmp = hue_json["bri"];
tmp = max(tmp, 1);
tmp = min(tmp, 254);
bri = (float)tmp / 254.0f; bri = (float)tmp / 254.0f;
if (resp) { if (resp) {
response += ","; response += ",";
@ -694,7 +705,7 @@ void HueLights(String *path)
resp = true; resp = true;
change = true; change = true;
} }
if (hue_json.containsKey("hue")) { if (hue_json.containsKey("hue")) { // The hue value is a wrapping value between 0 and 65535. Both 0 and 65535 are red, 25500 is green and 46920 is blue.
tmp = hue_json["hue"]; tmp = hue_json["hue"];
hue = (float)tmp / 65535.0f; hue = (float)tmp / 65535.0f;
if (resp) { if (resp) {
@ -704,11 +715,14 @@ void HueLights(String *path)
response.replace("{id", String(device)); response.replace("{id", String(device));
response.replace("{cm", "hue"); response.replace("{cm", "hue");
response.replace("{re", String(tmp)); response.replace("{re", String(tmp));
g_gotct = false;
resp = true; resp = true;
change = true; change = true;
} }
if (hue_json.containsKey("sat")) { if (hue_json.containsKey("sat")) { // Saturation of the light. 254 is the most saturated (colored) and 0 is the least saturated (white).
tmp = hue_json["sat"]; tmp = hue_json["sat"];
tmp = max(tmp, 0);
tmp = min(tmp, 254);
sat = (float)tmp / 254.0f; sat = (float)tmp / 254.0f;
if (resp) { if (resp) {
response += ","; response += ",";
@ -717,6 +731,8 @@ void HueLights(String *path)
response.replace("{id", String(device)); response.replace("{id", String(device));
response.replace("{cm", "sat"); response.replace("{cm", "sat");
response.replace("{re", String(tmp)); response.replace("{re", String(tmp));
g_gotct = false;
resp = true;
change = true; change = true;
} }
if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm) if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm)
@ -728,11 +744,12 @@ void HueLights(String *path)
response.replace("{id", String(device)); response.replace("{id", String(device));
response.replace("{cm", "ct"); response.replace("{cm", "ct");
response.replace("{re", String(ct)); response.replace("{re", String(ct));
g_gotct = true;
change = true; change = true;
} }
if (change) { if (change) {
if (light_type) { if (light_type) {
LightSetHsb(hue, sat, bri, ct); LightSetHsb(hue, sat, bri, ct, g_gotct);
} }
change = false; change = false;
} }