"
"
{ha} Module
{h}
";
const char HTTP_SCRIPT_CONSOL[] PROGMEM =
"var sn=0;" // Scroll position
@@ -415,7 +419,7 @@ void handleRoot()
if (HTTP_MANAGER == _httpflag) {
handleWifi0();
} else {
- char stemp[10], line[100];
+ char stemp[10], line[160];
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), F("Main menu"));
page.replace(F(""), F(""));
@@ -423,7 +427,12 @@ void handleRoot()
page += F("
");
if (Maxdevice) {
if (sfl_flg) {
- snprintf_P(line, sizeof(line), PSTR("
"),
+ if ((2 == sfl_flg) || (5 == sfl_flg)) {
+ snprintf_P(line, sizeof(line), PSTR("
ColdWarm
"),
+ sl_getColorTemp());
+ page += line;
+ }
+ snprintf_P(line, sizeof(line), PSTR("
DarkBright
"),
sysCfg.led_dimmer[0]);
page += line;
}
@@ -474,6 +483,10 @@ void handleAjax2()
snprintf_P(svalue, sizeof(svalue), PSTR("dimmer %s"), webServer->arg("d").c_str());
do_cmnd(svalue);
}
+ if (strlen(webServer->arg("t").c_str())) {
+ snprintf_P(svalue, sizeof(svalue), PSTR("ct %s"), webServer->arg("t").c_str());
+ do_cmnd(svalue);
+ }
if (strlen(webServer->arg("k").c_str())) {
snprintf_P(svalue, sizeof(svalue), PSTR("rfkey%s"), webServer->arg("k").c_str());
do_cmnd(svalue);
diff --git a/sonoff/xdrv_ir_send.ino b/sonoff/xdrv_ir_send.ino
index a1998f605..e25b44176 100644
--- a/sonoff/xdrv_ir_send.ino
+++ b/sonoff/xdrv_ir_send.ino
@@ -261,7 +261,7 @@ boolean ir_hvac_mitsubishi(const char *HVAC_Mode,const char *HVAC_FanMode, boole
mode = (p - HVACMODE +1) << 3; // HOT = 0x08, DRY = 0x10, COOL = 0x18, AUTO = 0x20
mitsubir->setMode(mode);
- mitsubir->setPower(~HVAC_Power);
+ mitsubir->setPower(HVAC_Power);
if (HVAC_FanMode == NULL) {
p = (char*)FANSPEED; // default FAN_SPEED_AUTO
diff --git a/sonoff/xdrv_snfled.ino b/sonoff/xdrv_snfled.ino
index 9f5acdf0c..dba0e6167 100644
--- a/sonoff/xdrv_snfled.ino
+++ b/sonoff/xdrv_snfled.ino
@@ -18,7 +18,14 @@
*/
/*********************************************************************************************\
- * Sonoff Led and BN-SZ01
+ * Sonoff B1, AiLight, Sonoff Led and BN-SZ01
+ *
+ * sfl_flg Module Color ColorTemp
+ * 1 Sonoff BN-SZ W no
+ * 2 Sonoff Led CW yes
+ * 3 not used
+ * 4 AiLight RGBW no
+ * 5 Sonoff B1 RGBCW yes
\*********************************************************************************************/
uint8_t ledTable[] = {
@@ -39,9 +46,9 @@ uint8_t ledTable[] = {
184,186,189,191,193,195,197,199,201,204,206,208,210,212,215,217,
219,221,224,226,228,231,233,235,238,240,243,245,248,250,253,255 };
-uint8_t sl_dcolor[2];
-uint8_t sl_tcolor[2];
-uint8_t sl_lcolor[2];
+uint8_t sl_dcolor[5];
+uint8_t sl_tcolor[5];
+uint8_t sl_lcolor[5];
uint8_t sl_power;
uint8_t sl_any;
@@ -49,54 +56,211 @@ uint8_t sl_wakeupActive = 0;
uint8_t sl_wakeupDimmer = 0;
uint16_t sl_wakeupCntr = 0;
-/********************************************************************************************/
+/*********************************************************************************************\
+ * Sonoff B1 and AiLight inspired by OpenLight https://github.com/icamgo/noduino-sdk
+\*********************************************************************************************/
-void sl_setDim(uint8_t myDimmer)
-{
- if ((1 == sfl_flg) && (100 == myDimmer)) {
- myDimmer = 99; // BN-SZ01 starts flickering at dimmer = 100
- }
- float newDim = 100 / (float)myDimmer;
- float fmyCld = (float)sysCfg.led_color[0] / newDim;
- sl_dcolor[0] = (uint8_t)fmyCld;
- float fmyWrm = (float)sysCfg.led_color[1] / newDim;
- sl_dcolor[1] = (uint8_t)fmyWrm;
+extern "C" {
+ void os_delay_us(unsigned int);
}
+uint8_t sl_pdi;
+uint8_t sl_pdcki;
+
+void sl_di_pulse(uint8_t times)
+{
+ for (uint8_t i = 0; i < times; i++) {
+ digitalWrite(sl_pdi, HIGH);
+ digitalWrite(sl_pdi, LOW);
+ }
+}
+
+void sl_dcki_pulse(uint8_t times)
+{
+ for (uint8_t i = 0; i < times; i++) {
+ digitalWrite(sl_pdcki, HIGH);
+ digitalWrite(sl_pdcki, LOW);
+ }
+}
+
+void sl_my92x1_write(uint8_t data)
+{
+ for (uint8_t i = 0; i < 4; i++) { // Send 8bit Data
+ digitalWrite(sl_pdcki, LOW);
+ digitalWrite(sl_pdi, (data & 0x80));
+ digitalWrite(sl_pdcki, HIGH);
+ data = data << 1;
+ digitalWrite(sl_pdi, (data & 0x80));
+ digitalWrite(sl_pdcki, LOW);
+ digitalWrite(sl_pdi, LOW);
+ data = data << 1;
+ }
+}
+
+void sl_my92x1_init()
+{
+ uint8_t chips = sfl_flg -3; // 1 (AiLight) or 2 (Sonoff B1)
+
+ sl_dcki_pulse(chips * 32); // Clear all duty register
+ os_delay_us(12); // TStop > 12us.
+ // Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12
+ // pulse's rising edge convert to command mode.
+ sl_di_pulse(12);
+ os_delay_us(12); // Delay >12us, begin send CMD data
+ for (uint8_t n = 0; n < chips; n++) { // Send CMD data
+ sl_my92x1_write(0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM
+ }
+ os_delay_us(12); // TStart > 12us. Delay 12 us.
+ // Send 16 DI pulse, at 14 pulse's falling edge store CMD data, and
+ // at 16 pulse's falling edge convert to duty mode.
+ sl_di_pulse(16);
+ os_delay_us(12); // TStop > 12us.
+}
+
+void sl_my92x1_duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c)
+{
+ uint8_t channels[2] = { 4, 6 };
+
+ uint8_t didx = sfl_flg -4; // 0 or 1
+
+ uint8_t duty[2][6] = {{ duty_r, duty_g, duty_b, duty_w, 0, 0 }, // Definition for RGBW channels
+ { duty_w, duty_c, 0, duty_g, duty_r, duty_b }}; // Definition for RGBWC channels
+
+ os_delay_us(12); // TStop > 12us.
+ for (uint8_t channel = 0; channel < channels[didx]; channel++) {
+ sl_my92x1_write(duty[didx][channel]); // Send 8bit Data
+ }
+ os_delay_us(12); // TStart > 12us. Ready for send DI pulse.
+ sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data.
+ os_delay_us(12); // TStop > 12us.
+}
+
+/********************************************************************************************/
+
void sl_init(void)
{
- sysCfg.pwmvalue[0] = 0; // We use dimmer / led_color
- if (2 == sfl_flg) {
- sysCfg.pwmvalue[1] = 0; // We use led_color
+ pin[GPIO_WS2812] = 99; // I do not allow both Sonoff Led AND WS2812 led
+ if (sfl_flg < 4) {
+ if (!my_module.gp.io[4]) {
+ pinMode(4, OUTPUT); // Stop floating outputs
+ digitalWrite(4, LOW);
+ }
+ if (!my_module.gp.io[5]) {
+ pinMode(5, OUTPUT); // Stop floating outputs
+ digitalWrite(5, LOW);
+ }
+ if (!my_module.gp.io[14]) {
+ pinMode(14, OUTPUT); // Stop floating outputs
+ digitalWrite(14, LOW);
+ }
+ sysCfg.pwmvalue[0] = 0; // We use dimmer / led_color
+ if (2 == sfl_flg) {
+ sysCfg.pwmvalue[1] = 0; // We use led_color
+ }
+ } else {
+ sl_pdi = pin[GPIO_DI];
+ sl_pdcki = pin[GPIO_DCKI];
+
+ pinMode(sl_pdi, OUTPUT);
+ pinMode(sl_pdcki, OUTPUT);
+ digitalWrite(sl_pdi, LOW);
+ digitalWrite(sl_pdcki, LOW);
+
+ sl_my92x1_init();
}
+
sl_power = 0;
sl_any = 0;
sl_wakeupActive = 0;
}
-void sl_setColor(char* colstr)
+void sl_setColorTemp(uint16_t ct)
{
- uint8_t my_color[2];
- char *p;
-
- uint16_t temp = strtol(colstr, &p, 16);
- my_color[1] = temp & 0xFF; // Warm
- temp >>= 8;
- my_color[0] = temp & 0xFF; // Cold
- if (temp < my_color[1]) {
- temp = my_color[1];
+/* Color Temperature (https://developers.meethue.com/documentation/core-concepts)
+ *
+ * ct = 153 = 2000K = Warm = CCWW = 00FF
+ * ct = 500 = 6500K = Cold = CCWW = FF00
+ */
+ uint16_t my_ct = ct - 153;
+ if (my_ct > 347) {
+ my_ct = 347;
}
- float mDim = (float)temp / 2.55;
+ uint16_t icold = (100 * (347 - my_ct)) / 136;
+ uint16_t iwarm = (100 * my_ct) / 136;
+ if (5 == sfl_flg) {
+ sysCfg.led_color[0] = 0;
+ sysCfg.led_color[1] = 0;
+ sysCfg.led_color[2] = 0;
+ sysCfg.led_color[3] = (uint8_t)icold;
+ sysCfg.led_color[4] = (uint8_t)iwarm;
+ } else {
+ sysCfg.led_color[0] = (uint8_t)icold;
+ sysCfg.led_color[1] = (uint8_t)iwarm;
+ }
+}
+
+uint16_t sl_getColorTemp()
+{
+ uint8_t ct_idx = 0;
+ if (5 == sfl_flg) {
+ ct_idx = 3;
+ }
+ uint16_t my_ct = sysCfg.led_color[ct_idx +1];
+ if (my_ct > 0) {
+ return ((my_ct * 136) / 100) + 154;
+ } else {
+ my_ct = sysCfg.led_color[ct_idx];
+ return 499 - ((my_ct * 136) / 100);
+ }
+}
+
+void sl_setDim(uint8_t myDimmer)
+{
+ float temp;
+
+ if ((1 == sfl_flg) && (100 == myDimmer)) {
+ myDimmer = 99; // BN-SZ01 starts flickering at dimmer = 100
+ }
+ float newDim = 100 / (float)myDimmer;
+ for (byte i = 0; i < sfl_flg; i++) {
+ temp = (float)sysCfg.led_color[i] / newDim;
+ sl_dcolor[i] = (uint8_t)temp;
+ }
+}
+
+void sl_setColor()
+{
+ uint8_t highest = 0;
+ float temp;
+
+ for (byte i = 0; i < sfl_flg; i++) {
+ if (highest < sl_dcolor[i]) {
+ highest = sl_dcolor[i];
+ }
+ }
+ float mDim = (float)highest / 2.55;
sysCfg.led_dimmer[0] = (uint8_t)mDim;
float newDim = 100 / mDim;
- float fmyCold = (float)my_color[0] * newDim;
- float fmyWarm = (float)my_color[1] * newDim;
- sysCfg.led_color[0] = (uint8_t)fmyCold;
- sysCfg.led_color[1] = (uint8_t)fmyWarm;
+ for (byte i = 0; i < sfl_flg; i++) {
+ temp = (float)sl_dcolor[i] * newDim;
+ sysCfg.led_color[i] = (uint8_t)temp;
+ }
+}
+
+char* sl_getColor(char* scolor)
+{
+ sl_setDim(sysCfg.led_dimmer[0]);
+ scolor[0] = '\0';
+ for (byte i = 0; i < sfl_flg; i++) {
+ snprintf_P(scolor, 11, PSTR("%s%02X"), scolor, sl_dcolor[i]);
+ }
+ return scolor;
}
void sl_prepPower(char *svalue, uint16_t ssvalue)
{
+ char scolor[11];
+
// do_cmnd_power(index, (sysCfg.led_dimmer[0]>0));
if (sysCfg.led_dimmer[0] && !(power&1)) {
do_cmnd_power(1, 7); // No publishPowerState
@@ -107,12 +271,9 @@ void sl_prepPower(char *svalue, uint16_t ssvalue)
#ifdef USE_DOMOTICZ
mqtt_publishDomoticzPowerState(1);
#endif // USE_DOMOTICZ
- sl_setDim(sysCfg.led_dimmer[0]);
- if (2 == sfl_flg) {
- uint16_t color = (uint16_t)sl_dcolor[0] << 8;
- color += (uint16_t)sl_dcolor[1];
- snprintf_P(svalue, ssvalue, PSTR("{\"POWER\":\"%s\", \"Dimmer\":%d, \"Color\":\"%04X\"}"),
- getStateText(power &1), sysCfg.led_dimmer[0], color);
+ if (sfl_flg > 1) {
+ snprintf_P(svalue, ssvalue, PSTR("{\"POWER\":\"%s\", \"Dimmer\":%d, \"Color\":\"%s\"}"),
+ getStateText(power &1), sysCfg.led_dimmer[0], sl_getColor(scolor));
} else {
snprintf_P(svalue, ssvalue, PSTR("{\"POWER\":\"%s\", \"Dimmer\":%d}"),
getStateText(power &1), sysCfg.led_dimmer[0]);
@@ -133,40 +294,38 @@ void sl_animate()
// {"Wakeup":"Done"}
char svalue[32]; // was MESSZ
uint8_t fadeValue;
+ uint8_t cur_col[5];
if (0 == sl_power) { // Power Off
- sl_tcolor[0] = 0;
- sl_tcolor[1] = 0;
+ for (byte i = 0; i < sfl_flg; i++) {
+ sl_tcolor[i] = 0;
+ }
}
else {
if (!sl_wakeupActive) { // Power On
sl_setDim(sysCfg.led_dimmer[0]);
if (0 == sysCfg.led_fade) {
- sl_tcolor[0] = sl_dcolor[0];
- sl_tcolor[1] = sl_dcolor[1];
- } else {
- if (sl_tcolor[0] != sl_dcolor[0]) {
- if (sl_tcolor[0] < sl_dcolor[0]) {
- sl_tcolor[0] += ((sl_dcolor[0] - sl_tcolor[0]) >> sysCfg.led_speed) +1;
- }
- if (sl_tcolor[0] > sl_dcolor[0]) {
- sl_tcolor[0] -= ((sl_tcolor[0] - sl_dcolor[0]) >> sysCfg.led_speed) +1;
- }
+ for (byte i = 0; i < sfl_flg; i++) {
+ sl_tcolor[i] = sl_dcolor[i];
}
- if ((2 == sfl_flg) && (sl_tcolor[1] != sl_dcolor[1])) {
- if (sl_tcolor[1] < sl_dcolor[1]) {
- sl_tcolor[1] += ((sl_dcolor[1] - sl_tcolor[1]) >> sysCfg.led_speed) +1;
- }
- if (sl_tcolor[1] > sl_dcolor[1]) {
- sl_tcolor[1] -= ((sl_tcolor[1] - sl_dcolor[1]) >> sysCfg.led_speed) +1;
+ } else {
+ for (byte i = 0; i < sfl_flg; i++) {
+ if (sl_tcolor[i] != sl_dcolor[i]) {
+ if (sl_tcolor[i] < sl_dcolor[i]) {
+ sl_tcolor[i] += ((sl_dcolor[i] - sl_tcolor[i]) >> sysCfg.led_speed) +1;
+ }
+ if (sl_tcolor[i] > sl_dcolor[i]) {
+ sl_tcolor[i] -= ((sl_tcolor[i] - sl_dcolor[i]) >> sysCfg.led_speed) +1;
+ }
}
}
}
} else { // Power On using wake up duration
if (2 == sl_wakeupActive) {
sl_wakeupActive = 1;
- sl_tcolor[0] = 0;
- sl_tcolor[1] = 0;
+ for (byte i = 0; i < sfl_flg; i++) {
+ sl_tcolor[i] = 0;
+ }
sl_wakeupCntr = 0;
sl_wakeupDimmer = 0;
}
@@ -176,8 +335,9 @@ void sl_animate()
sl_wakeupDimmer++;
if (sl_wakeupDimmer <= sysCfg.led_dimmer[0]) {
sl_setDim(sl_wakeupDimmer);
- sl_tcolor[0] = sl_dcolor[0];
- sl_tcolor[1] = sl_dcolor[1];
+ for (byte i = 0; i < sfl_flg; i++) {
+ sl_tcolor[i] = sl_dcolor[i];
+ }
} else {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Wakeup\":\"Done\"}"));
mqtt_publish_topic_P(2, PSTR("WAKEUP"), svalue);
@@ -186,15 +346,25 @@ void sl_animate()
}
}
}
- if ((sl_lcolor[0] != sl_tcolor[0]) || (sl_lcolor[1] != sl_tcolor[1]) || sl_any) {
+ for (byte i = 0; i < sfl_flg; i++) {
+ if (sl_lcolor[i] != sl_tcolor[i]) {
+ sl_any = 1;
+ }
+ }
+ if (sl_any) {
sl_any = 0;
- sl_lcolor[0] = sl_tcolor[0];
- sl_lcolor[1] = sl_tcolor[1];
for (byte i = 0; i < sfl_flg; i++) {
- if (pin[GPIO_PWM1 +i] < 99) {
- analogWrite(pin[GPIO_PWM1 +i], ((sysCfg.led_table) ? ledTable[sl_lcolor[i]] : sl_lcolor[i]) * (PWM_RANGE / 255));
+ sl_lcolor[i] = sl_tcolor[i];
+ cur_col[i] = (sysCfg.led_table) ? ledTable[sl_lcolor[i]] : sl_lcolor[i];
+ if (sfl_flg < 4) {
+ if (pin[GPIO_PWM1 +i] < 99) {
+ analogWrite(pin[GPIO_PWM1 +i], cur_col[i] * (PWM_RANGE / 255));
+ }
}
}
+ if (sfl_flg > 3) {
+ sl_my92x1_duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]);
+ }
}
}
@@ -202,28 +372,99 @@ void sl_animate()
* Hue support
\*********************************************************************************************/
+void sl_rgb2hsb(float *hue, float *sat, float *bri)
+{
+ RgbColor dcolor;
+
+ sl_setDim(sysCfg.led_dimmer[0]);
+ dcolor.R = sl_dcolor[0];
+ dcolor.G = sl_dcolor[1];
+ dcolor.B = sl_dcolor[2];
+ HsbColor hsb = HsbColor(dcolor);
+ *hue = hsb.H;
+ *sat = hsb.S;
+ *bri = hsb.B;
+}
+
+/********************************************************************************************/
+
void sl_replaceHSB(String *response)
{
- response->replace("{h}", "0");
- response->replace("{s}", "0");
- response->replace("{b}", String((uint8_t)(2.54f * (float)sysCfg.led_dimmer[0])));
+ float hue;
+ float sat;
+ float bri;
+
+ if (sfl_flg > 2) {
+ sl_rgb2hsb(&hue, &sat, &bri);
+ response->replace("{h}", String((uint16_t)(65535.0f * hue)));
+ response->replace("{s}", String((uint8_t)(254.0f * sat)));
+ response->replace("{b}", String((uint8_t)(254.0f * bri)));
+ } else {
+ response->replace("{h}", "0");
+ response->replace("{s}", "0");
+// response->replace("{b}", String((uint8_t)(2.54f * (float)sysCfg.led_dimmer[0])));
+ response->replace("{b}", String((uint8_t)(0.01f * (float)sysCfg.led_dimmer[0])));
+ }
}
void sl_getHSB(float *hue, float *sat, float *bri)
{
- *hue = 0;
- *sat = 0;
- *bri = (2.54f * (float)sysCfg.led_dimmer[0]);
+ if (sfl_flg > 2) {
+ sl_rgb2hsb(hue, sat, bri);
+ } else {
+ *hue = 0;
+ *sat = 0;
+// *bri = (2.54f * (float)sysCfg.led_dimmer[0]);
+ *bri = (0.01f * (float)sysCfg.led_dimmer[0]);
+ }
}
-void sl_setHSB(float hue, float sat, float bri)
+void sl_setHSB(float hue, float sat, float bri, uint16_t ct)
{
char svalue[MESSZ];
+ HsbColor hsb;
- uint8_t tmp = (uint8_t)(bri * 100);
- sysCfg.led_dimmer[0] = tmp;
- sl_prepPower(svalue, sizeof(svalue));
- mqtt_publish_topic_P(5, "DIMMER", svalue);
+/*
+ char log[LOGSZ];
+ char stemp1[10];
+ char stemp2[10];
+ char stemp3[10];
+ dtostrf(hue, 1, 3, stemp1);
+ dtostrf(sat, 1, 3, stemp2);
+ dtostrf(bri, 1, 3, stemp3);
+ snprintf_P(log, sizeof(log), PSTR("HUE: Set Hue %s, Sat %s, Bri %s, Ct %d"), stemp1, stemp2, stemp3, ct);
+ addLog(LOG_LEVEL_DEBUG, log);
+*/
+
+ if (sfl_flg > 2) {
+ if ((5 == sfl_flg) && (ct > 0)) {
+ sl_setColorTemp(ct);
+ } else {
+ hsb.H = hue;
+ hsb.S = sat;
+ hsb.B = bri;
+ RgbColor tmp = RgbColor(hsb);
+ sl_dcolor[0] = tmp.R;
+ sl_dcolor[1] = tmp.G;
+ sl_dcolor[2] = tmp.B;
+ sl_setColor();
+ }
+ sl_prepPower(svalue, sizeof(svalue));
+ mqtt_publish_topic_P(5, "COLOR", svalue);
+ } else {
+ uint8_t tmp = (uint8_t)(bri * 100);
+ sysCfg.led_dimmer[0] = tmp;
+ if (2 == sfl_flg) {
+ if (ct > 0) {
+ sl_setColorTemp(ct);
+ }
+ sl_prepPower(svalue, sizeof(svalue));
+ mqtt_publish_topic_P(5, "COLOR", svalue);
+ } else {
+ sl_prepPower(svalue, sizeof(svalue));
+ mqtt_publish_topic_P(5, "DIMMER", svalue);
+ }
+ }
}
/*********************************************************************************************\
@@ -234,18 +475,27 @@ boolean sl_command(char *type, uint16_t index, char *dataBufUc, uint16_t data_le
{
boolean serviced = true;
boolean coldim = false;
+ char scolor[11];
+ char *p;
- if ((2 == sfl_flg) && !strcmp_P(type,PSTR("COLOR"))) {
- uint8_t my_color[2];
- char *p;
- if (4 == data_len) {
- sl_setColor(dataBufUc);
+ if ((sfl_flg > 1) && !strcmp_P(type,PSTR("COLOR"))) {
+ if ((2 * sfl_flg) == data_len) {
+ for (byte i = 0; i < sfl_flg; i++) {
+ strlcpy(scolor, dataBufUc + (i *2), 3);
+ sl_dcolor[i] = (uint8_t)strtol(scolor, &p, 16);
+ }
+ sl_setColor();
coldim = true;
} else {
- sl_setDim(sysCfg.led_dimmer[0]);
- uint16_t color = (uint16_t)sl_dcolor[0] << 8;
- color += (uint16_t)sl_dcolor[1];
- snprintf_P(svalue, ssvalue, PSTR("{\"Color\":\"%04X\"}"), color);
+ snprintf_P(svalue, ssvalue, PSTR("{\"Color\":\"%s\"}"), sl_getColor(scolor));
+ }
+ }
+ else if (!strcmp_P(type,PSTR("CT")) && ((2 == sfl_flg) || (5 == sfl_flg))) { // ColorTemp
+ if ((payload >= 153) && (payload <= 500)) { // https://developers.meethue.com/documentation/core-concepts
+ sl_setColorTemp(payload);
+ coldim = true;
+ } else {
+ snprintf_P(svalue, ssvalue, PSTR("{\"CT\":%d}"), sl_getColorTemp());
}
}
else if (!strcmp_P(type,PSTR("DIMMER"))) {
diff --git a/sonoff/xdrv_wemohue.ino b/sonoff/xdrv_wemohue.ino
index 08bcba878..ac522167d 100644
--- a/sonoff/xdrv_wemohue.ino
+++ b/sonoff/xdrv_wemohue.ino
@@ -533,6 +533,7 @@ void hue_lights(String *path)
float bri = 0;
float hue = 0;
float sat = 0;
+ uint16_t ct = 0;
bool resp = false;
bool on = false;
bool change = false;
@@ -636,9 +637,20 @@ void hue_lights(String *path)
response.replace("{res}", String(tmp));
change = true;
}
+ if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm)
+ ct = hue_json["ct"];
+ if (resp) {
+ response += ",";
+ }
+ response += FPSTR(HUE_LIGHT_RESPONSE_JSON);
+ response.replace("{id}", String(device));
+ response.replace("{cmd}", "ct");
+ response.replace("{res}", String(ct));
+ change = true;
+ }
if (change) {
if (sfl_flg) {
- sl_setHSB(hue, sat, bri);
+ sl_setHSB(hue, sat, bri, ct);
#ifdef USE_WS2812
}
else if (pin[GPIO_WS2812] < 99) {
@@ -655,6 +667,9 @@ void hue_lights(String *path)
else {
response = FPSTR(HUE_ERROR_JSON);
}
+
+//addLog(LOG_LEVEL_DEBUG_MORE, response.c_str());
+
webServer->send(200, FPSTR(HDR_CTYPE_JSON), response);
}
else if(path->indexOf("/lights/") >= 0) { // Got /lights/ID
@@ -678,6 +693,9 @@ void hue_lights(String *path)
void hue_groups(String *path)
{
+/*
+ * http://sonoff/api/username/groups?1={"name":"Woonkamer","lights":[],"type":"Room","class":"Living room"})
+ */
String response = "{}";
if (path->endsWith("/0")) {
@@ -721,7 +739,7 @@ void handle_hue_api(String *path)
else if (path->endsWith("/")) hue_auth(path); // New HUE App setup
else if (path->endsWith("/config")) hue_config(path);
else if (path->indexOf("/lights") >= 0) hue_lights(path);
- else if (path->indexOf("/groups") >= 0) hue_groups(path);
+ else if (path->indexOf("/groups") >= 0) hue_groups(path);
else if (path->endsWith("/schedules")) hue_todo(path);
else if (path->endsWith("/sensors")) hue_todo(path);
else if (path->endsWith("/scenes")) hue_todo(path);
diff --git a/sonoff/xdrv_ws2812.ino b/sonoff/xdrv_ws2812.ino
index 93a6e5fe4..92fe3e349 100644
--- a/sonoff/xdrv_ws2812.ino
+++ b/sonoff/xdrv_ws2812.ino
@@ -22,7 +22,7 @@
* WS2812 Leds using NeopixelBus library
\*********************************************************************************************/
-#include
+//#include // Global defined as also used by Sonoff Led
#ifdef USE_WS2812_DMA
#if (USE_WS2812_CTYPE == 1)
@@ -145,37 +145,6 @@ void ws2812_setColor(uint16_t led, char* colstr)
}
}
-void ws2812_replaceHSB(String *response)
-{
- ws2812_setDim(sysCfg.ws_dimmer);
- HsbColor hsb = HsbColor(dcolor);
- response->replace("{h}", String((uint16_t)(65535.0f * hsb.H)));
- response->replace("{s}", String((uint8_t)(254.0f * hsb.S)));
- response->replace("{b}", String((uint8_t)(254.0f * hsb.B)));
-}
-
-void ws2812_getHSB(float *hue, float *sat, float *bri)
-{
- ws2812_setDim(sysCfg.ws_dimmer);
- HsbColor hsb = HsbColor(dcolor);
- *hue = hsb.H;
- *sat = hsb.S;
- *bri = hsb.B;
-}
-
-void ws2812_setHSB(float hue, float sat, float bri)
-{
- char rgb[7];
-
- HsbColor hsb;
- hsb.H = hue;
- hsb.S = sat;
- hsb.B = bri;
- RgbColor tmp = RgbColor(hsb);
- sprintf(rgb,"%02X%02X%02X", tmp.R, tmp.G, tmp.B);
- ws2812_setColor(0,rgb);
-}
-
void ws2812_getColor(uint16_t led, char* svalue, uint16_t ssvalue)
{
RgbColor mcolor;
@@ -504,6 +473,41 @@ void ws2812_init(uint8_t powerbit)
ws2812_pixels();
}
+/*********************************************************************************************\
+ * Hue support
+\*********************************************************************************************/
+
+void ws2812_replaceHSB(String *response)
+{
+ ws2812_setDim(sysCfg.ws_dimmer);
+ HsbColor hsb = HsbColor(dcolor);
+ response->replace("{h}", String((uint16_t)(65535.0f * hsb.H)));
+ response->replace("{s}", String((uint8_t)(254.0f * hsb.S)));
+ response->replace("{b}", String((uint8_t)(254.0f * hsb.B)));
+}
+
+void ws2812_getHSB(float *hue, float *sat, float *bri)
+{
+ ws2812_setDim(sysCfg.ws_dimmer);
+ HsbColor hsb = HsbColor(dcolor);
+ *hue = hsb.H;
+ *sat = hsb.S;
+ *bri = hsb.B;
+}
+
+void ws2812_setHSB(float hue, float sat, float bri)
+{
+ char rgb[7];
+
+ HsbColor hsb;
+ hsb.H = hue;
+ hsb.S = sat;
+ hsb.B = bri;
+ RgbColor tmp = RgbColor(hsb);
+ sprintf(rgb,"%02X%02X%02X", tmp.R, tmp.G, tmp.B);
+ ws2812_setColor(0,rgb);
+}
+
/*********************************************************************************************\
* Commands
\*********************************************************************************************/
diff --git a/sonoff/xsns_hlw8012.ino b/sonoff/xsns_hlw8012.ino
index a23f9a430..471b79d18 100644
--- a/sonoff/xsns_hlw8012.ino
+++ b/sonoff/xsns_hlw8012.ino
@@ -1,7 +1,7 @@
/*
xsns_hlw8012.ino - sonoff pow HLW8012 energy sensor support for Sonoff-Tasmota
- Copyright (C) 2017 Heiko Krupp and Theo Arends
+ Copyright (C) 2017 Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -173,8 +173,11 @@ void hlw_savestate()
sysCfg.hlw_kWhtotal = rtcMem.hlw_kWhtotal;
}
-boolean hlw_readEnergy(byte option, float &et, float &ed, uint16_t &e, uint16_t &w, float &u, float &i, float &c)
+void hlw_readEnergy(byte option, float &et, float &ed, uint16_t &e, uint16_t &w, float &u, float &i, float &c)
{
+/* option 0 = do not calculate period energy usage
+ * option 1 = calculate period energy usage
+ */
unsigned long cur_kWhtoday = hlw_kWhtoday;
unsigned long hlw_len;
unsigned long hlw_temp;
@@ -189,60 +192,51 @@ boolean hlw_readEnergy(byte option, float &et, float &ed, uint16_t &e, uint16_t
//addLog(LOG_LEVEL_DEBUG, log);
et = (float)(rtcMem.hlw_kWhtotal + (cur_kWhtoday / 1000)) / 100000;
-
+ ed = 0;
if (cur_kWhtoday) {
ed = (float)cur_kWhtoday / 100000000;
- } else {
- ed = 0;
}
-
+ e = 0;
if (option) {
if (!hlw_lasttime) {
hlw_period = sysCfg.tele_period;
} else {
hlw_period = rtc_loctime() - hlw_lasttime;
}
- hlw_lasttime = rtc_loctime();
- hlw_interval = 3600 / hlw_period;
- if (hlw_Ecntr) {
- hlw_len = hlw_period * 1000000 / hlw_Ecntr;
- hlw_Ecntr = 0;
- hlw_temp = ((HLW_PREF * sysCfg.hlw_pcal) / hlw_len) / hlw_interval;
- e = hlw_temp / 10;
- } else {
- e = 0;
+ if (hlw_period) {
+ hlw_lasttime = rtc_loctime();
+ hlw_interval = 3600 / hlw_period;
+ if (hlw_Ecntr) {
+ hlw_len = hlw_period * 1000000 / hlw_Ecntr;
+ hlw_Ecntr = 0;
+ hlw_temp = ((HLW_PREF * sysCfg.hlw_pcal) / hlw_len) / hlw_interval;
+ e = hlw_temp / 10;
+ }
}
}
-
+ w = 0;
if (hlw_cf_plen) {
hlw_w = (HLW_PREF * sysCfg.hlw_pcal) / hlw_cf_plen;
w = hlw_w / 10;
- } else {
- w = 0;
}
+ u = 0;
if (hlw_cf1u_plen && (w || (power &1))) {
hlw_u = (HLW_UREF * sysCfg.hlw_ucal) / hlw_cf1u_plen;
u = (float)hlw_u / 10;
- } else {
- u = 0;
}
+ i = 0;
if (hlw_cf1i_plen && w) {
hlw_i = (HLW_IREF * sysCfg.hlw_ical) / hlw_cf1i_plen;
i = (float)hlw_i / 1000;
- } else {
- i = 0;
}
+ c = 0;
if (hlw_i && hlw_u && hlw_w && w) {
hlw_temp = (hlw_w * 100) / ((hlw_u * hlw_i) / 1000);
if (hlw_temp > 100) {
hlw_temp = 100;
}
c = (float)hlw_temp / 100;
- } else {
- c = 0;
}
-
- return true;
}
void hlw_init()
@@ -366,7 +360,7 @@ void hlw_margin_chk()
if (jsonflg) {
snprintf_P(svalue, sizeof(svalue), PSTR("%s}"), svalue);
mqtt_publish_topic_P(2, PSTR("MARGINS"), svalue);
- hlw_mqttPresent();
+ hlw_mqttPresent(0);
}
}
@@ -381,7 +375,7 @@ void hlw_margin_chk()
if (!hlw_mplh_counter) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"MaxPowerReached\":\"%d%s\"}"), pw, (sysCfg.flag.value_units) ? " W" : "");
mqtt_publish_topic_P(1, PSTR("WARNING"), svalue);
- hlw_mqttPresent();
+ hlw_mqttPresent(0);
do_cmnd_power(1, 0);
if (!hlw_mplr_counter) {
hlw_mplr_counter = sysCfg.param[P_MAX_POWER_RETRY] +1;
@@ -408,7 +402,7 @@ void hlw_margin_chk()
} else {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"MaxPowerReachedRetry\":\"%s\"}"), getStateText(0));
mqtt_publish_topic_P(1, PSTR("WARNING"), svalue);
- hlw_mqttPresent();
+ hlw_mqttPresent(0);
}
}
}
@@ -429,7 +423,7 @@ void hlw_margin_chk()
dtostrf(ped, 1, 3, svalue);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"MaxEnergyReached\":\"%s%s\"}"), svalue, (sysCfg.flag.value_units) ? " kWh" : "");
mqtt_publish_topic_P(1, PSTR("WARNING"), svalue);
- hlw_mqttPresent();
+ hlw_mqttPresent(0);
do_cmnd_power(1, 0);
}
}
@@ -616,6 +610,9 @@ boolean hlw_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len
void hlw_mqttStat(byte option, char* svalue, uint16_t ssvalue)
{
+/* option 0 = do not show period energy usage
+ * option 1 = show period energy usage
+ */
char stemp0[10];
char stemp1[10];
char stemp2[10];
@@ -642,18 +639,23 @@ void hlw_mqttStat(byte option, char* svalue, uint16_t ssvalue)
snprintf_P(svalue, ssvalue, PSTR("%s\"Total\":%s, \"Yesterday\":%s, \"Today\":%s%s, \"Power\":%d, \"Factor\":%s, \"Voltage\":%s, \"Current\":%s}"),
svalue, stemp4, stemp0, stemp1, (option) ? speriod : "", pw, stemp2, stemp5, stemp3);
#ifdef USE_DOMOTICZ
- dtostrf(pet * 1000, 1, 1, stemp1);
- domoticz_sensor4(pw, stemp1);
+ if (option) { // Only send if telemetry
+ dtostrf(pet * 1000, 1, 1, stemp1);
+ domoticz_sensor4(pw, stemp1);
+ }
#endif // USE_DOMOTICZ
}
-void hlw_mqttPresent()
+void hlw_mqttPresent(byte option)
{
+/* option 0 = do not show period energy usage
+ * option 1 = show period energy usage
+ */
// {"Time":"2017-03-04T13:37:24", "Total":0.013, "Yesterday":0.013, "Today":0.000, "Period":0, "Power":0, "Factor":0.00, "Voltage":0, "Current":0.000}
char svalue[200]; // was MESSZ
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Time\":\"%s\", "), getDateTime().c_str());
- hlw_mqttStat(1, svalue, sizeof(svalue));
+ hlw_mqttStat(option, svalue, sizeof(svalue));
mqtt_publish_topic_P(2, PSTR("ENERGY"), svalue);
}
@@ -693,7 +695,6 @@ String hlw_webPresent()
uint16_t pw;
hlw_readEnergy(0, pet, ped, pe, pw, pu, pi, pc);
-
dtostrf(pu, 1, sysCfg.flag.voltage_resolution, stemp6);
dtostrf(pi, 1, 3, stemp);
dtostrf(pc, 1, 2, stemp2);