mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-30 06:06:36 +00:00
Merge pull request #5667 from s-hadinger/development
Support for color and colortone in Philips Hue emulation via Alexa
This commit is contained in:
commit
934cde4a94
@ -11,6 +11,7 @@
|
|||||||
* Add all temperature, humidity and pressure for global access
|
* Add all temperature, humidity and pressure for global access
|
||||||
* Add Shelly 2.5 overtemp functionality
|
* Add Shelly 2.5 overtemp functionality
|
||||||
* Fix Shelly 2.5 I2C address priority issue when VEML6070 code is present by disabling VEML6070 for Shelly 2.5 (#5592)
|
* Fix Shelly 2.5 I2C address priority issue when VEML6070 code is present by disabling VEML6070 for Shelly 2.5 (#5592)
|
||||||
|
* Support for color and colortone for Philips Hue emulation via Alexa (#5600 #4809)
|
||||||
*
|
*
|
||||||
* 6.5.0.7 20190410
|
* 6.5.0.7 20190410
|
||||||
* Add command LedMask to assign which relay has access to power LED (#5602, #5612)
|
* Add command LedMask to assign which relay has access to power LED (#5602, #5612)
|
||||||
|
@ -599,6 +599,11 @@ void LightSetColorTemp(uint16_t ct)
|
|||||||
* ct = 153 = 2000K = Warm = CCWW = 00FF
|
* ct = 153 = 2000K = Warm = CCWW = 00FF
|
||||||
* ct = 500 = 6500K = Cold = CCWW = FF00
|
* ct = 500 = 6500K = Cold = CCWW = FF00
|
||||||
*/
|
*/
|
||||||
|
// don't set CT if not supported
|
||||||
|
if ((LST_COLDWARM != light_subtype) && (LST_RGBWC != light_subtype)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t my_ct = ct - 153;
|
uint16_t my_ct = ct - 153;
|
||||||
if (my_ct > 347) {
|
if (my_ct > 347) {
|
||||||
my_ct = 347;
|
my_ct = 347;
|
||||||
@ -626,17 +631,29 @@ void LightSetColorTemp(uint16_t ct)
|
|||||||
|
|
||||||
uint16_t LightGetColorTemp(void)
|
uint16_t LightGetColorTemp(void)
|
||||||
{
|
{
|
||||||
|
// don't calculate CT for unsupported devices
|
||||||
|
if ((LST_COLDWARM != light_subtype) && (LST_RGBWC != light_subtype)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ct = 0;
|
||||||
uint8_t ct_idx = 0;
|
uint8_t ct_idx = 0;
|
||||||
if (LST_RGBWC == light_subtype) {
|
if (LST_RGBWC == light_subtype) {
|
||||||
ct_idx = 3;
|
ct_idx = 3;
|
||||||
}
|
}
|
||||||
uint16_t my_ct = Settings.light_color[ct_idx +1];
|
uint16_t my_ct = Settings.light_color[ct_idx +1];
|
||||||
if (my_ct > 0) {
|
if (my_ct > 0) {
|
||||||
return ((my_ct * 136) / 100) + 154;
|
ct = ((my_ct * 136) / 100) + 154;
|
||||||
} else {
|
} else {
|
||||||
my_ct = Settings.light_color[ct_idx];
|
my_ct = Settings.light_color[ct_idx];
|
||||||
return 499 - ((my_ct * 136) / 100);
|
if (my_ct > 0) {
|
||||||
|
ct = 499 - ((my_ct * 136) / 100);
|
||||||
|
} else {
|
||||||
|
ct = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ct;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightSetDimmer(uint8_t myDimmer)
|
void LightSetDimmer(uint8_t myDimmer)
|
||||||
@ -655,12 +672,12 @@ void LightSetDimmer(uint8_t myDimmer)
|
|||||||
if (LT_PWM1 == light_type) {
|
if (LT_PWM1 == light_type) {
|
||||||
Settings.light_color[0] = 255; // One PWM channel only supports Dimmer but needs max color
|
Settings.light_color[0] = 255; // One PWM channel only supports Dimmer but needs max color
|
||||||
}
|
}
|
||||||
float dimmer = 100 / (float)myDimmer;
|
float dimmer = 100.0f / (float)myDimmer;
|
||||||
for (uint8_t i = 0; i < light_subtype; i++) {
|
for (uint8_t i = 0; i < light_subtype; i++) {
|
||||||
if (Settings.flag.light_signal) {
|
if (Settings.flag.light_signal) {
|
||||||
temp = (float)light_signal_color[i] / dimmer;
|
temp = (float)light_signal_color[i] / dimmer + 0.5f;
|
||||||
} else {
|
} else {
|
||||||
temp = (float)Settings.light_color[i] / dimmer;
|
temp = (float)Settings.light_color[i] / dimmer + 0.5f;
|
||||||
}
|
}
|
||||||
light_current_color[i] = (uint8_t)temp;
|
light_current_color[i] = (uint8_t)temp;
|
||||||
}
|
}
|
||||||
@ -675,11 +692,11 @@ void LightSetColor(void)
|
|||||||
highest = light_current_color[i];
|
highest = light_current_color[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float mDim = (float)highest / 2.55;
|
float mDim = (float)highest / 2.55f;
|
||||||
Settings.light_dimmer = (uint8_t)mDim;
|
Settings.light_dimmer = (uint8_t)(mDim + 0.5f);
|
||||||
float dimmer = 100 / mDim;
|
float dimmer = 100 / mDim;
|
||||||
for (uint8_t i = 0; i < light_subtype; i++) {
|
for (uint8_t i = 0; i < light_subtype; i++) {
|
||||||
float temp = (float)light_current_color[i] * dimmer;
|
float temp = (float)light_current_color[i] * dimmer + 0.5f;
|
||||||
Settings.light_color[i] = (uint8_t)temp;
|
Settings.light_color[i] = (uint8_t)temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -845,7 +862,7 @@ void LightWheel(uint8_t wheel_pos)
|
|||||||
light_entry_color[4] = 0;
|
light_entry_color[4] = 0;
|
||||||
float dimmer = 100 / (float)Settings.light_dimmer;
|
float dimmer = 100 / (float)Settings.light_dimmer;
|
||||||
for (uint8_t i = 0; i < LST_RGB; i++) {
|
for (uint8_t i = 0; i < LST_RGB; i++) {
|
||||||
float temp = (float)light_entry_color[i] / dimmer;
|
float temp = (float)light_entry_color[i] / dimmer + 0.5f;
|
||||||
light_entry_color[i] = (uint8_t)temp;
|
light_entry_color[i] = (uint8_t)temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -872,6 +889,7 @@ void LightRandomColor(void)
|
|||||||
light_wheel = random(255);
|
light_wheel = random(255);
|
||||||
LightWheel(light_wheel);
|
LightWheel(light_wheel);
|
||||||
memcpy(light_current_color, light_entry_color, sizeof(light_current_color));
|
memcpy(light_current_color, light_entry_color, sizeof(light_current_color));
|
||||||
|
LightSetColor();
|
||||||
}
|
}
|
||||||
LightFade();
|
LightFade();
|
||||||
}
|
}
|
||||||
@ -1048,103 +1066,118 @@ void LightAnimate(void)
|
|||||||
* Hue support
|
* Hue support
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
float light_hue = 0.0;
|
float light_hue = 0.0f;
|
||||||
float light_saturation = 0.0;
|
float light_saturation = 0.0f;
|
||||||
float light_brightness = 0.0;
|
float light_brightness = 0.0f;
|
||||||
|
|
||||||
void LightRgbToHsb(void)
|
void LightRgbToHsb(bool from_settings = false)
|
||||||
{
|
{
|
||||||
LightSetDimmer(Settings.light_dimmer);
|
// We get a previse Hue and Sat from the Settings parameter with full brightness
|
||||||
|
// and apply the Dimmer value for Brightness
|
||||||
|
// 'from_settings' default to actual RGB color for retro-compatibility
|
||||||
|
|
||||||
// convert colors to float between (0.0 - 1.0)
|
// convert colors to float between (0.0 - 1.0)
|
||||||
float r = light_current_color[0] / 255.0f;
|
float r, g, b;
|
||||||
float g = light_current_color[1] / 255.0f;
|
if (from_settings) {
|
||||||
float b = light_current_color[2] / 255.0f;
|
r = Settings.light_color[0] / 255.0f;
|
||||||
|
g = Settings.light_color[1] / 255.0f;
|
||||||
|
b = Settings.light_color[2] / 255.0f;
|
||||||
|
} else {
|
||||||
|
r = light_current_color[0] / 255.0f;
|
||||||
|
g = light_current_color[1] / 255.0f;
|
||||||
|
b = light_current_color[2] / 255.0f;
|
||||||
|
}
|
||||||
|
|
||||||
float max = (r > g && r > b) ? r : (g > b) ? g : b;
|
float max = (r > g && r > b) ? r : (g > b) ? g : b;
|
||||||
float min = (r < g && r < b) ? r : (g < b) ? g : b;
|
float min = (r < g && r < b) ? r : (g < b) ? g : b;
|
||||||
|
|
||||||
float d = max - min;
|
float d = max - min;
|
||||||
|
|
||||||
light_hue = 0.0;
|
float hue = 0.0f;
|
||||||
light_brightness = max;
|
float brightness;
|
||||||
light_saturation = (0.0f == light_brightness) ? 0 : (d / light_brightness);
|
if (from_settings) {
|
||||||
|
brightness = max * Settings.light_dimmer / 100.0f;
|
||||||
|
} else {
|
||||||
|
brightness = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
float saturation = (0.0f == max) ? 0 : 1.0f - min / max;
|
||||||
|
|
||||||
if (d != 0.0f)
|
if (d != 0.0f)
|
||||||
{
|
{
|
||||||
if (r == max) {
|
if (r == max) {
|
||||||
light_hue = (g - b) / d + (g < b ? 6.0f : 0.0f);
|
hue = (g - b) / d + (g < b ? 6.0f : 0.0f);
|
||||||
} else if (g == max) {
|
} else if (g == max) {
|
||||||
light_hue = (b - r) / d + 2.0f;
|
hue = (b - r) / d + 2.0f;
|
||||||
} else {
|
} else {
|
||||||
light_hue = (r - g) / d + 4.0f;
|
hue = (r - g) / d + 4.0f;
|
||||||
}
|
}
|
||||||
light_hue /= 6.0f;
|
hue /= 6.0f;
|
||||||
}
|
}
|
||||||
|
light_hue = hue;
|
||||||
|
light_saturation = saturation;
|
||||||
|
light_brightness = brightness;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightHsbToRgb(void)
|
void LightHsToRgb(void)
|
||||||
{
|
{
|
||||||
float r;
|
float r = 1.0f; // default to white
|
||||||
float g;
|
float g = 1.0f;
|
||||||
float b;
|
float b = 1.0f;
|
||||||
|
|
||||||
float h = light_hue;
|
float h = light_hue;
|
||||||
float s = light_saturation;
|
float s = light_saturation;
|
||||||
float v = light_brightness;
|
// brightness is set to 100%, and controlled via Dimmer
|
||||||
|
|
||||||
if (0.0f == light_saturation) {
|
if (0.0f < light_saturation) {
|
||||||
r = g = b = v; // Achromatic or black
|
|
||||||
} else {
|
|
||||||
if (h < 0.0f) {
|
if (h < 0.0f) {
|
||||||
h += 1.0f;
|
h += 1.0f;
|
||||||
}
|
} else if (h >= 1.0f) {
|
||||||
else if (h >= 1.0f) {
|
|
||||||
h -= 1.0f;
|
h -= 1.0f;
|
||||||
}
|
}
|
||||||
h *= 6.0f;
|
h *= 6.0f;
|
||||||
int i = (int)h;
|
int i = (int)h;
|
||||||
float f = h - i;
|
float f = h - i;
|
||||||
float q = v * (1.0f - s * f);
|
float q = 1.0f - s * f;
|
||||||
float p = v * (1.0f - s);
|
float p = 1.0f - s;
|
||||||
float t = v * (1.0f - s * (1.0f - f));
|
float t = 1.0f - s * (1.0f - f);
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
r = v;
|
//r = 1.0f;
|
||||||
g = t;
|
g = t;
|
||||||
b = p;
|
b = p;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
r = q;
|
r = q;
|
||||||
g = v;
|
//g = 1.0f;
|
||||||
b = p;
|
b = p;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
r = p;
|
r = p;
|
||||||
g = v;
|
//g = 1.0f;
|
||||||
b = t;
|
b = t;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
r = p;
|
r = p;
|
||||||
g = q;
|
g = q;
|
||||||
b = v;
|
//b = 1.0f;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
r = t;
|
r = t;
|
||||||
g = p;
|
g = p;
|
||||||
b = v;
|
//b = 1.0f;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
r = v;
|
//r = 1.0f;
|
||||||
g = p;
|
g = p;
|
||||||
b = q;
|
b = q;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
light_current_color[0] = (uint8_t)(r * 255.0f);
|
light_current_color[0] = (uint8_t)(r * 255.0f + 0.5f);
|
||||||
light_current_color[1] = (uint8_t)(g * 255.0f);
|
light_current_color[1] = (uint8_t)(g * 255.0f + 0.5f);
|
||||||
light_current_color[2] = (uint8_t)(b * 255.0f);
|
light_current_color[2] = (uint8_t)(b * 255.0f + 0.5f);
|
||||||
if(light_ct_rgb_linked){
|
if(light_ct_rgb_linked){
|
||||||
light_current_color[3] = 0;
|
light_current_color[3] = 0;
|
||||||
light_current_color[4] = 0;
|
light_current_color[4] = 0;
|
||||||
@ -1156,14 +1189,17 @@ void LightHsbToRgb(void)
|
|||||||
void LightGetHsb(float *hue, float *sat, float *bri, bool gotct)
|
void LightGetHsb(float *hue, float *sat, float *bri, bool gotct)
|
||||||
{
|
{
|
||||||
if (light_subtype > LST_COLDWARM && !gotct) {
|
if (light_subtype > LST_COLDWARM && !gotct) {
|
||||||
LightRgbToHsb();
|
LightRgbToHsb(true);
|
||||||
*hue = light_hue;
|
*hue = light_hue;
|
||||||
*sat = light_saturation;
|
*sat = light_saturation;
|
||||||
*bri = light_brightness;
|
*bri = light_brightness;
|
||||||
} else {
|
} else {
|
||||||
*hue = 0;
|
*hue = light_hue = 0.0f;
|
||||||
*sat = 0;
|
*sat = light_saturation = 0.0f;
|
||||||
*bri = (0.01f * (float)Settings.light_dimmer);
|
float brightness = (float)Settings.light_dimmer / 100.0f;
|
||||||
|
if ((light_brightness - brightness > 0.01f) || (brightness - light_brightness > 0.01f))
|
||||||
|
light_brightness = brightness;
|
||||||
|
*bri = light_brightness;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1171,25 +1207,31 @@ 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) && (gotct)) {
|
if ((LST_RGBWC == light_subtype) && (gotct)) {
|
||||||
uint8_t tmp = (uint8_t)(bri * 100);
|
light_brightness = bri;
|
||||||
Settings.light_dimmer = tmp;
|
Settings.light_dimmer = (uint8_t)(bri * 100.0f +0.5f);
|
||||||
if (ct > 0) {
|
if (ct > 0) {
|
||||||
|
light_hue = 0.0f;
|
||||||
|
light_saturation = 0.0f;
|
||||||
LightSetColorTemp(ct);
|
LightSetColorTemp(ct);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
light_hue = hue;
|
light_hue = hue;
|
||||||
light_saturation = sat;
|
light_saturation = sat;
|
||||||
light_brightness = bri;
|
light_brightness = bri;
|
||||||
LightHsbToRgb();
|
LightHsToRgb();
|
||||||
LightSetColor();
|
LightSetColor();
|
||||||
|
Settings.light_dimmer = (uint8_t)(bri * 100.0f + 0.5f);
|
||||||
|
LightSetDimmer(Settings.light_dimmer);
|
||||||
}
|
}
|
||||||
LightPreparePower();
|
LightPreparePower();
|
||||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_COLOR));
|
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_COLOR));
|
||||||
} else {
|
} else {
|
||||||
uint8_t tmp = (uint8_t)(bri * 100);
|
light_brightness = bri;
|
||||||
Settings.light_dimmer = tmp;
|
Settings.light_dimmer = (uint8_t)(bri * 100.0f +0.5f);
|
||||||
if (LST_COLDWARM == light_subtype) {
|
if (LST_COLDWARM == light_subtype) {
|
||||||
if (ct > 0) {
|
if (ct > 0) {
|
||||||
|
light_hue = 0.0f;
|
||||||
|
light_saturation = 0.0f;
|
||||||
LightSetColorTemp(ct);
|
LightSetColorTemp(ct);
|
||||||
}
|
}
|
||||||
LightPreparePower();
|
LightPreparePower();
|
||||||
|
@ -466,16 +466,11 @@ const char HUE_DESCRIPTION_XML[] PROGMEM =
|
|||||||
"</device>"
|
"</device>"
|
||||||
"</root>\r\n"
|
"</root>\r\n"
|
||||||
"\r\n";
|
"\r\n";
|
||||||
const char HUE_LIGHTS_STATUS_JSON[] PROGMEM =
|
const char HUE_LIGHTS_STATUS_JSON1[] PROGMEM =
|
||||||
"{\"on\":{state},"
|
"{\"on\":{state},"
|
||||||
"\"bri\":{b},"
|
"{light_status}"
|
||||||
"\"hue\":{h},"
|
|
||||||
"\"sat\":{s},"
|
|
||||||
"\"xy\":[0.5, 0.5],"
|
|
||||||
"\"ct\":{t},"
|
|
||||||
"\"alert\":\"none\","
|
"\"alert\":\"none\","
|
||||||
"\"effect\":\"none\","
|
"\"effect\":\"none\","
|
||||||
"\"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\","
|
||||||
@ -570,24 +565,105 @@ void HueConfig(String *path)
|
|||||||
|
|
||||||
bool g_gotct = false;
|
bool g_gotct = false;
|
||||||
|
|
||||||
|
#define FORCE_RANGE(x, min, max) x < min ? min : (x > max ? max : x)
|
||||||
|
|
||||||
|
void RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y)
|
||||||
|
{
|
||||||
|
float x = 0.31271f;
|
||||||
|
float y = 0.32902f;
|
||||||
|
|
||||||
|
if (i_r + i_b + i_g > 0) {
|
||||||
|
float r = (float)i_r / 255.0f;
|
||||||
|
float g = (float)i_g / 255.0f;
|
||||||
|
float b = (float)i_b / 255.0f;
|
||||||
|
// https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d
|
||||||
|
r = (r > 0.04045f) ? pow((r + 0.055f) / (1.0f + 0.055f), 2.4f) : (r / 12.92f);
|
||||||
|
g = (g > 0.04045f) ? pow((g + 0.055f) / (1.0f + 0.055f), 2.4f) : (g / 12.92f);
|
||||||
|
b = (b > 0.04045f) ? pow((b + 0.055f) / (1.0f + 0.055f), 2.4f) : (b / 12.92f);
|
||||||
|
|
||||||
|
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.000000f + g * 0.053077f + b * 1.035763f;
|
||||||
|
|
||||||
|
x = X / (X + Y + Z);
|
||||||
|
y = Y / (X + Y + Z);
|
||||||
|
}
|
||||||
|
if (r_x) *r_x = x;
|
||||||
|
if (r_y) *r_y = y;
|
||||||
|
//*bri = Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// store previously set values from the Alexa app
|
||||||
|
uint16_t prev_hue = 0;
|
||||||
|
uint8_t prev_sat = 0;
|
||||||
|
uint8_t prev_bri = 254;
|
||||||
|
uint16_t prev_ct = 254;
|
||||||
|
|
||||||
void HueLightStatus1(uint8_t device, String *response)
|
void HueLightStatus1(uint8_t device, String *response)
|
||||||
{
|
{
|
||||||
float hue = 0;
|
uint16_t ct = 0;
|
||||||
float sat = 0;
|
// default xy color to white D65, https://en.wikipedia.org/wiki/Illuminant_D65
|
||||||
float bri = 254;
|
String light_status = "";
|
||||||
uint16_t ct = 500;
|
uint16_t hue = 0;
|
||||||
|
uint8_t sat = 0;
|
||||||
|
uint8_t bri = 254;
|
||||||
|
|
||||||
|
// force ct mode for LST_COLDWARM
|
||||||
|
if (LST_COLDWARM == light_subtype) {
|
||||||
|
g_gotct = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (light_type) {
|
if (light_type) {
|
||||||
LightGetHsb(&hue, &sat, &bri, g_gotct);
|
float hhue, hsat, hbri;
|
||||||
|
LightGetHsb(&hhue, &hsat, &hbri, g_gotct);
|
||||||
|
|
||||||
|
bri = 254.0f * hbri + 0.5f;
|
||||||
|
if (bri > 254) bri = 254; // Philips Hue bri is between 1 and 254
|
||||||
|
if (bri < 1) bri = 1;
|
||||||
|
if ((bri > prev_bri ? bri - prev_bri : prev_bri - bri) < 2)
|
||||||
|
bri = prev_bri;
|
||||||
|
|
||||||
|
sat = 254.0f * hsat + 0.5f; // 0..254
|
||||||
|
if (sat > 254) sat = 254; // Philips Hue only accepts 254 as max hue
|
||||||
|
if ((sat > prev_sat ? sat - prev_sat : prev_sat - sat) < 2)
|
||||||
|
sat = prev_sat;
|
||||||
|
|
||||||
|
hue = 65535.0f * hhue + 0.5f; // 0..65535
|
||||||
|
if ((hue > prev_hue ? hue - prev_hue : prev_hue - hue) < 700)
|
||||||
|
hue = prev_hue;
|
||||||
|
|
||||||
ct = LightGetColorTemp();
|
ct = LightGetColorTemp();
|
||||||
|
if (ct < 100) ct = 284;
|
||||||
|
if ((ct > prev_ct ? ct - prev_ct : prev_ct - ct) < 5)
|
||||||
|
ct = prev_ct;
|
||||||
|
|
||||||
|
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("HueLightStatus1 HSB (%d, %d, %d) Prev_HSB (%d, %d, %d)"),
|
||||||
|
// hue, sat, bri, prev_hue, prev_sat, prev_bri);
|
||||||
}
|
}
|
||||||
*response += FPSTR(HUE_LIGHTS_STATUS_JSON);
|
|
||||||
|
*response += FPSTR(HUE_LIGHTS_STATUS_JSON1);
|
||||||
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)));
|
if (LST_SINGLE <= light_subtype) {
|
||||||
response->replace("{s}", String((uint8_t)(254.0f * sat)));
|
light_status += "\"bri\":" + String(bri) + ",";
|
||||||
response->replace("{b}", String((uint8_t)(254.0f * bri)));
|
}
|
||||||
response->replace("{t}", String(ct));
|
if (LST_COLDWARM <= light_subtype) {
|
||||||
response->replace("{m}", g_gotct?"ct":"hs");
|
light_status += "\"colormode\":\"" + String(g_gotct ? "ct" : "hs") + "\",";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (LST_RGB <= light_subtype) { // colors
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
RgbToXy(Settings.light_color[0], Settings.light_color[1], Settings.light_color[2], &x, &y);
|
||||||
|
light_status += "\"xy\":[" + String(x) + ", " + String(y) + "],";
|
||||||
|
light_status += "\"hue\":" + String(hue) + ",";
|
||||||
|
light_status += "\"sat\":" + String(sat) + ",";
|
||||||
|
}
|
||||||
|
if (LST_COLDWARM == light_subtype || LST_RGBWC == light_subtype) { // white temp
|
||||||
|
// ct = 0 is non valid, so we put 284 as default value (medium white)
|
||||||
|
light_status += "\"ct\":" + String(ct) + ",";
|
||||||
|
}
|
||||||
|
response->replace("{light_status}", light_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HueLightStatus2(uint8_t device, String *response)
|
void HueLightStatus2(uint8_t device, String *response)
|
||||||
@ -698,6 +774,7 @@ void HueLights(String *path)
|
|||||||
|
|
||||||
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.
|
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"];
|
||||||
|
prev_bri = tmp; // store command value
|
||||||
tmp = tmax(tmp, 1);
|
tmp = tmax(tmp, 1);
|
||||||
tmp = tmin(tmp, 254);
|
tmp = tmin(tmp, 254);
|
||||||
bri = (float)tmp / 254.0f;
|
bri = (float)tmp / 254.0f;
|
||||||
@ -713,6 +790,7 @@ void HueLights(String *path)
|
|||||||
}
|
}
|
||||||
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.
|
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"];
|
||||||
|
prev_hue = tmp; // store command value
|
||||||
hue = (float)tmp / 65535.0f;
|
hue = (float)tmp / 65535.0f;
|
||||||
if (resp) {
|
if (resp) {
|
||||||
response += ",";
|
response += ",";
|
||||||
@ -727,6 +805,7 @@ void HueLights(String *path)
|
|||||||
}
|
}
|
||||||
if (hue_json.containsKey("sat")) { // Saturation of the light. 254 is the most saturated (colored) and 0 is the least saturated (white).
|
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"];
|
||||||
|
prev_sat = tmp; // store command value
|
||||||
tmp = tmax(tmp, 0);
|
tmp = tmax(tmp, 0);
|
||||||
tmp = tmin(tmp, 254);
|
tmp = tmin(tmp, 254);
|
||||||
sat = (float)tmp / 254.0f;
|
sat = (float)tmp / 254.0f;
|
||||||
@ -743,6 +822,7 @@ void HueLights(String *path)
|
|||||||
}
|
}
|
||||||
if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm)
|
if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm)
|
||||||
ct = hue_json["ct"];
|
ct = hue_json["ct"];
|
||||||
|
prev_ct = ct; // store commande value
|
||||||
if (resp) {
|
if (resp) {
|
||||||
response += ",";
|
response += ",";
|
||||||
}
|
}
|
||||||
@ -760,6 +840,7 @@ void HueLights(String *path)
|
|||||||
change = false;
|
change = false;
|
||||||
}
|
}
|
||||||
response += "]";
|
response += "]";
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str());
|
||||||
if (2 == response.length()) {
|
if (2 == response.length()) {
|
||||||
response = FPSTR(HUE_ERROR_JSON);
|
response = FPSTR(HUE_ERROR_JSON);
|
||||||
}
|
}
|
||||||
@ -777,6 +858,7 @@ void HueLights(String *path)
|
|||||||
response += F("{\"state\":");
|
response += F("{\"state\":");
|
||||||
HueLightStatus1(device, &response);
|
HueLightStatus1(device, &response);
|
||||||
HueLightStatus2(device, &response);
|
HueLightStatus2(device, &response);
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " LightResult (%s)"), response.c_str());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
response = "{}";
|
response = "{}";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user