Merge branch 'sonoff-b1' into development

This commit is contained in:
arendst 2017-08-16 17:20:47 +02:00
commit e1895cbeba
8 changed files with 470 additions and 146 deletions

View File

@ -1,6 +1,14 @@
/* 5.5.2b /* 5.5.2h
* Fix Sonoff Pow intermittent exception 0 * Fix Sonoff Pow intermittent exception 0
* Change Sonoff Pow sending Domoticz telemetry data only * Change Sonoff Pow sending Domoticz telemetry data only
* Add Sonoff B1 RGBCW led support with command Color RRGGBBCCWW (#676)
* Add command CT 152..500 to Sonoff Led and Sonoff B1 to control Color Temperature
* Add Cold-Warm slider to web page for Sonoff Led and Sonoff B1
* Add CT parameter to Hue
* Add Ai-Thinker RGBW led (AiLight) (experimental)
* Add NeoPixelBus library to Sonoff Led for Hue support (saves 1k code space)
* Add user configurable GPIO4 and GPIO5 to module Sonoff Bridge
* Fix Mitsubishi HVAC IR power controll (#740)
* *
* 5.5.2 20170808 * 5.5.2 20170808
* Extent max number of WS2812 pixels from 256 to 512 (#667) * Extent max number of WS2812 pixels from 256 to 512 (#667)

View File

@ -25,7 +25,7 @@
- Select IDE Tools - Flash Size: "1M (no SPIFFS)" - Select IDE Tools - Flash Size: "1M (no SPIFFS)"
====================================================*/ ====================================================*/
#define VERSION 0x05050202 // 5.5.2b #define VERSION 0x05050208 // 5.5.2h
enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL};
enum week_t {Last, First, Second, Third, Fourth}; enum week_t {Last, First, Second, Third, Fourth};
@ -172,6 +172,7 @@ enum opt_t {P_HOLD_TIME, P_MAX_POWER_RETRY, P_MAX_PARAM8}; // Index in sysCf
#include <ESP8266httpUpdate.h> // Ota #include <ESP8266httpUpdate.h> // Ota
#include <StreamString.h> // Webserver, Updater #include <StreamString.h> // Webserver, Updater
#include <ArduinoJson.h> // WemoHue, IRremote, Domoticz #include <ArduinoJson.h> // WemoHue, IRremote, Domoticz
#include <NeoPixelBus.h> // Ws2812, Sonoff Led hue support
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
#include <ESP8266WebServer.h> // WifiManager, Webserver #include <ESP8266WebServer.h> // WifiManager, Webserver
#include <DNSServer.h> // WifiManager #include <DNSServer.h> // WifiManager
@ -303,7 +304,7 @@ uint8_t hlw_flg = 0; // Power monitor configured
uint8_t i2c_flg = 0; // I2C configured uint8_t i2c_flg = 0; // I2C configured
uint8_t spi_flg = 0; // SPI configured uint8_t spi_flg = 0; // SPI configured
uint8_t pwm_flg = 0; // PWM configured uint8_t pwm_flg = 0; // PWM configured
uint8_t sfl_flg = 0; // Sonoff Led flag (0 = No led, 1 = BN-SZ01, 2 = Sonoff Led) uint8_t sfl_flg = 0; // Sonoff Led flag (0 = No led, 1 = BN-SZ01, 2 = Sonoff Led, 5 = Sonoff B1)
uint8_t pwm_idxoffset = 0; // Allowed PWM command offset (change for Sonoff Led) uint8_t pwm_idxoffset = 0; // Allowed PWM command offset (change for Sonoff Led)
boolean mDNSbegun = false; boolean mDNSbegun = false;
@ -2318,7 +2319,7 @@ void stateloop()
button_handler(); button_handler();
switch_handler(); switch_handler();
if (sfl_flg) { // Sonoff BN-SZ01 or Sonoff Led if (sfl_flg) { // Sonoff B1, AiLight, Sonoff led or BN-SZ01
sl_animate(); sl_animate();
} }
@ -2627,12 +2628,18 @@ void GPIO_init()
Maxdevice = 0; Maxdevice = 0;
Baudrate = 19200; Baudrate = 19200;
} }
else if (SONOFF_BN == sysCfg.module) { else if (SONOFF_BN == sysCfg.module) { // Single color led (White)
sfl_flg = 1; sfl_flg = 1;
} }
else if (SONOFF_LED == sysCfg.module) { else if (SONOFF_LED == sysCfg.module) { // Dual color led (White warm and cold)
sfl_flg = 2; sfl_flg = 2;
} }
else if (AILIGHT == sysCfg.module) { // RGBW led
sfl_flg = 4;
}
else if (SONOFF_B1 == sysCfg.module) { // RGBWC led
sfl_flg = 5;
}
else { else {
Maxdevice = 0; Maxdevice = 0;
for (byte i = 0; i < 4; i++) { for (byte i = 0; i < 4; i++) {
@ -2660,20 +2667,9 @@ void GPIO_init()
} }
} }
if (sfl_flg) { // Sonoff Led or BN-SZ01 if (sfl_flg) { // Sonoff B1, AiLight, Sonoff Led or BN-SZ01
pwm_idxoffset = sfl_flg; // 1 for BN-SZ01, 2 for Sonoff Led if (sfl_flg < 4) {
pin[GPIO_WS2812] = 99; // I do not allow both Sonoff Led AND WS2812 led pwm_idxoffset = sfl_flg; // 1 for BN-SZ01, 2 for Sonoff Led
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);
} }
sl_init(); sl_init();
} }

View File

@ -117,6 +117,8 @@ enum fpins_t {
GPIO_HLW_CF1, // HLW8012 CF1 voltage / current (Sonoff Pow) GPIO_HLW_CF1, // HLW8012 CF1 voltage / current (Sonoff Pow)
GPIO_HLW_CF, // HLW8012 CF power (Sonoff Pow) GPIO_HLW_CF, // HLW8012 CF power (Sonoff Pow)
GPIO_ADC0, // ADC GPIO_ADC0, // ADC
GPIO_DI, // my92x1 PWM input
GPIO_DCKI, // my92x1 CLK input
GPIO_USER, // User configurable GPIO_USER, // User configurable
GPIO_MAX }; GPIO_MAX };
@ -149,6 +151,8 @@ enum module_t {
SONOFF_4CHPRO, SONOFF_4CHPRO,
HUAFAN_SS, HUAFAN_SS,
SONOFF_BRIDGE, SONOFF_BRIDGE,
SONOFF_B1,
AILIGHT,
MAXMODULE }; MAXMODULE };
/********************************************************************************************/ /********************************************************************************************/
@ -482,13 +486,44 @@ const mytmplt modules[MAXMODULE] PROGMEM = {
GPIO_TXD, // GPIO01 RF bridge control GPIO_TXD, // GPIO01 RF bridge control
GPIO_USER, // GPIO02 Optional sensor GPIO_USER, // GPIO02 Optional sensor
GPIO_RXD, // GPIO03 RF bridge control GPIO_RXD, // GPIO03 RF bridge control
0, 0, GPIO_USER, // GPIO04 Optional sensor
GPIO_USER, // GPIO05 Optional sensor
0, 0, 0, // Flash connection 0, 0, 0, // Flash connection
0, 0, 0, 0,
0, // Flash connection 0, // Flash connection
0, 0,
GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off)
0, 0, 0, 0 0, 0, 0, 0
},
{ "Sonoff B1", // Sonoff B1 (ESP8285 - my9231)
GPIO_KEY1, // GPIO00 Pad
GPIO_USER, // GPIO01 Serial RXD and Optional sensor pad
GPIO_USER, // GPIO02 Optional sensor SDA pad
GPIO_USER, // GPIO03 Serial TXD and Optional sensor pad
0, 0,
0, 0, 0, // Flash connection
0, 0,
0, // Flash connection
GPIO_DI, // GPIO12 my9231 DI
0,
GPIO_DCKI, // GPIO14 my9231 DCKI
0, 0, 0
},
{ "AiLight", // Ai-Thinker RGBW led (ESP8266 - my9291)
GPIO_KEY1, // GPIO00 Pad
GPIO_USER, // GPIO01 Serial RXD and Optional sensor pad
GPIO_USER, // GPIO02 Optional sensor SDA pad
GPIO_USER, // GPIO03 Serial TXD and Optional sensor pad
0, 0,
0, 0, 0, // Flash connection
0, 0,
0, // Flash connection
0,
GPIO_DI, // GPIO13 my9291 DI
0,
GPIO_DCKI, // GPIO15 my9291 DCKI
0, 0
} }
}; };

View File

@ -70,6 +70,9 @@ const char HTTP_HEAD[] PROGMEM =
"function lb(p){" "function lb(p){"
"la('?d='+p);" "la('?d='+p);"
"}" "}"
"function lc(p){"
"la('?t='+p);"
"}"
"</script>" "</script>"
"<style>" "<style>"
@ -81,12 +84,13 @@ const char HTTP_HEAD[] PROGMEM =
"td{padding:0px;}" "td{padding:0px;}"
"button{border:0;border-radius:0.3rem;background-color:#1fa3ec;color:#fff;line-height:2.4rem;font-size:1.2rem;width:100%;-webkit-transition-duration:0.4s;transition-duration:0.4s;}" "button{border:0;border-radius:0.3rem;background-color:#1fa3ec;color:#fff;line-height:2.4rem;font-size:1.2rem;width:100%;-webkit-transition-duration:0.4s;transition-duration:0.4s;}"
"button:hover{background-color:#006cba;}" "button:hover{background-color:#006cba;}"
".q{float:right;width:200px;text-align:right;}" ".p{float:left;text-align:left;}"
".q{float:right;text-align:right;}"
"</style>" "</style>"
"</head>" "</head>"
"<body>" "<body>"
"<div style='text-align:left;display:inline-block;min-width:320px;'>" "<div style='text-align:left;display:inline-block;min-width:340px;'>"
"<div style='text-align:center;'><h3>{ha} Module</h3><h2>{h}</h2></div>"; "<div style='text-align:center;'><h3>{ha} Module</h3><h2>{h}</h2></div>";
const char HTTP_SCRIPT_CONSOL[] PROGMEM = const char HTTP_SCRIPT_CONSOL[] PROGMEM =
"var sn=0;" // Scroll position "var sn=0;" // Scroll position
@ -415,7 +419,7 @@ void handleRoot()
if (HTTP_MANAGER == _httpflag) { if (HTTP_MANAGER == _httpflag) {
handleWifi0(); handleWifi0();
} else { } else {
char stemp[10], line[100]; char stemp[10], line[160];
String page = FPSTR(HTTP_HEAD); String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), F("Main menu")); page.replace(F("{v}"), F("Main menu"));
page.replace(F("<body>"), F("<body onload='la()'>")); page.replace(F("<body>"), F("<body onload='la()'>"));
@ -423,7 +427,12 @@ void handleRoot()
page += F("<div id='l1' name='l1'></div>"); page += F("<div id='l1' name='l1'></div>");
if (Maxdevice) { if (Maxdevice) {
if (sfl_flg) { if (sfl_flg) {
snprintf_P(line, sizeof(line), PSTR("<input type='range' min='1' max='100' value='%d' onchange='lb(value)'>"), if ((2 == sfl_flg) || (5 == sfl_flg)) {
snprintf_P(line, sizeof(line), PSTR("<div><span class='p'>Cold</span><span class='q'>Warm</span></div><div><input type='range' min='153' max='500' value='%d' onchange='lc(value)'></div>"),
sl_getColorTemp());
page += line;
}
snprintf_P(line, sizeof(line), PSTR("<div><span class='p'>Dark</span><span class='q'>Bright</span></div><div><input type='range' min='1' max='100' value='%d' onchange='lb(value)'></div>"),
sysCfg.led_dimmer[0]); sysCfg.led_dimmer[0]);
page += line; page += line;
} }
@ -474,6 +483,10 @@ void handleAjax2()
snprintf_P(svalue, sizeof(svalue), PSTR("dimmer %s"), webServer->arg("d").c_str()); snprintf_P(svalue, sizeof(svalue), PSTR("dimmer %s"), webServer->arg("d").c_str());
do_cmnd(svalue); 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())) { if (strlen(webServer->arg("k").c_str())) {
snprintf_P(svalue, sizeof(svalue), PSTR("rfkey%s"), webServer->arg("k").c_str()); snprintf_P(svalue, sizeof(svalue), PSTR("rfkey%s"), webServer->arg("k").c_str());
do_cmnd(svalue); do_cmnd(svalue);

View File

@ -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 mode = (p - HVACMODE +1) << 3; // HOT = 0x08, DRY = 0x10, COOL = 0x18, AUTO = 0x20
mitsubir->setMode(mode); mitsubir->setMode(mode);
mitsubir->setPower(~HVAC_Power); mitsubir->setPower(HVAC_Power);
if (HVAC_FanMode == NULL) { if (HVAC_FanMode == NULL) {
p = (char*)FANSPEED; // default FAN_SPEED_AUTO p = (char*)FANSPEED; // default FAN_SPEED_AUTO

View File

@ -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[] = { 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, 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 }; 219,221,224,226,228,231,233,235,238,240,243,245,248,250,253,255 };
uint8_t sl_dcolor[2]; uint8_t sl_dcolor[5];
uint8_t sl_tcolor[2]; uint8_t sl_tcolor[5];
uint8_t sl_lcolor[2]; uint8_t sl_lcolor[5];
uint8_t sl_power; uint8_t sl_power;
uint8_t sl_any; uint8_t sl_any;
@ -49,54 +56,211 @@ uint8_t sl_wakeupActive = 0;
uint8_t sl_wakeupDimmer = 0; uint8_t sl_wakeupDimmer = 0;
uint16_t sl_wakeupCntr = 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) extern "C" {
{ void os_delay_us(unsigned int);
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;
} }
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) void sl_init(void)
{ {
sysCfg.pwmvalue[0] = 0; // We use dimmer / led_color pin[GPIO_WS2812] = 99; // I do not allow both Sonoff Led AND WS2812 led
if (2 == sfl_flg) { if (sfl_flg < 4) {
sysCfg.pwmvalue[1] = 0; // We use led_color 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_power = 0;
sl_any = 0; sl_any = 0;
sl_wakeupActive = 0; sl_wakeupActive = 0;
} }
void sl_setColor(char* colstr) void sl_setColorTemp(uint16_t ct)
{ {
uint8_t my_color[2]; /* Color Temperature (https://developers.meethue.com/documentation/core-concepts)
char *p; *
* ct = 153 = 2000K = Warm = CCWW = 00FF
uint16_t temp = strtol(colstr, &p, 16); * ct = 500 = 6500K = Cold = CCWW = FF00
my_color[1] = temp & 0xFF; // Warm */
temp >>= 8; uint16_t my_ct = ct - 153;
my_color[0] = temp & 0xFF; // Cold if (my_ct > 347) {
if (temp < my_color[1]) { my_ct = 347;
temp = my_color[1];
} }
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; sysCfg.led_dimmer[0] = (uint8_t)mDim;
float newDim = 100 / mDim; float newDim = 100 / mDim;
float fmyCold = (float)my_color[0] * newDim; for (byte i = 0; i < sfl_flg; i++) {
float fmyWarm = (float)my_color[1] * newDim; temp = (float)sl_dcolor[i] * newDim;
sysCfg.led_color[0] = (uint8_t)fmyCold; sysCfg.led_color[i] = (uint8_t)temp;
sysCfg.led_color[1] = (uint8_t)fmyWarm; }
}
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) void sl_prepPower(char *svalue, uint16_t ssvalue)
{ {
char scolor[11];
// do_cmnd_power(index, (sysCfg.led_dimmer[0]>0)); // do_cmnd_power(index, (sysCfg.led_dimmer[0]>0));
if (sysCfg.led_dimmer[0] && !(power&1)) { if (sysCfg.led_dimmer[0] && !(power&1)) {
do_cmnd_power(1, 7); // No publishPowerState do_cmnd_power(1, 7); // No publishPowerState
@ -107,12 +271,9 @@ void sl_prepPower(char *svalue, uint16_t ssvalue)
#ifdef USE_DOMOTICZ #ifdef USE_DOMOTICZ
mqtt_publishDomoticzPowerState(1); mqtt_publishDomoticzPowerState(1);
#endif // USE_DOMOTICZ #endif // USE_DOMOTICZ
sl_setDim(sysCfg.led_dimmer[0]); if (sfl_flg > 1) {
if (2 == sfl_flg) { snprintf_P(svalue, ssvalue, PSTR("{\"POWER\":\"%s\", \"Dimmer\":%d, \"Color\":\"%s\"}"),
uint16_t color = (uint16_t)sl_dcolor[0] << 8; getStateText(power &1), sysCfg.led_dimmer[0], sl_getColor(scolor));
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);
} else { } else {
snprintf_P(svalue, ssvalue, PSTR("{\"POWER\":\"%s\", \"Dimmer\":%d}"), snprintf_P(svalue, ssvalue, PSTR("{\"POWER\":\"%s\", \"Dimmer\":%d}"),
getStateText(power &1), sysCfg.led_dimmer[0]); getStateText(power &1), sysCfg.led_dimmer[0]);
@ -133,40 +294,38 @@ void sl_animate()
// {"Wakeup":"Done"} // {"Wakeup":"Done"}
char svalue[32]; // was MESSZ char svalue[32]; // was MESSZ
uint8_t fadeValue; uint8_t fadeValue;
uint8_t cur_col[5];
if (0 == sl_power) { // Power Off if (0 == sl_power) { // Power Off
sl_tcolor[0] = 0; for (byte i = 0; i < sfl_flg; i++) {
sl_tcolor[1] = 0; sl_tcolor[i] = 0;
}
} }
else { else {
if (!sl_wakeupActive) { // Power On if (!sl_wakeupActive) { // Power On
sl_setDim(sysCfg.led_dimmer[0]); sl_setDim(sysCfg.led_dimmer[0]);
if (0 == sysCfg.led_fade) { if (0 == sysCfg.led_fade) {
sl_tcolor[0] = sl_dcolor[0]; for (byte i = 0; i < sfl_flg; i++) {
sl_tcolor[1] = sl_dcolor[1]; sl_tcolor[i] = sl_dcolor[i];
} 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;
}
} }
if ((2 == sfl_flg) && (sl_tcolor[1] != sl_dcolor[1])) { } else {
if (sl_tcolor[1] < sl_dcolor[1]) { for (byte i = 0; i < sfl_flg; i++) {
sl_tcolor[1] += ((sl_dcolor[1] - sl_tcolor[1]) >> sysCfg.led_speed) +1; if (sl_tcolor[i] != sl_dcolor[i]) {
} if (sl_tcolor[i] < sl_dcolor[i]) {
if (sl_tcolor[1] > sl_dcolor[1]) { sl_tcolor[i] += ((sl_dcolor[i] - sl_tcolor[i]) >> sysCfg.led_speed) +1;
sl_tcolor[1] -= ((sl_tcolor[1] - sl_dcolor[1]) >> 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 } else { // Power On using wake up duration
if (2 == sl_wakeupActive) { if (2 == sl_wakeupActive) {
sl_wakeupActive = 1; sl_wakeupActive = 1;
sl_tcolor[0] = 0; for (byte i = 0; i < sfl_flg; i++) {
sl_tcolor[1] = 0; sl_tcolor[i] = 0;
}
sl_wakeupCntr = 0; sl_wakeupCntr = 0;
sl_wakeupDimmer = 0; sl_wakeupDimmer = 0;
} }
@ -176,8 +335,9 @@ void sl_animate()
sl_wakeupDimmer++; sl_wakeupDimmer++;
if (sl_wakeupDimmer <= sysCfg.led_dimmer[0]) { if (sl_wakeupDimmer <= sysCfg.led_dimmer[0]) {
sl_setDim(sl_wakeupDimmer); sl_setDim(sl_wakeupDimmer);
sl_tcolor[0] = sl_dcolor[0]; for (byte i = 0; i < sfl_flg; i++) {
sl_tcolor[1] = sl_dcolor[1]; sl_tcolor[i] = sl_dcolor[i];
}
} else { } else {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Wakeup\":\"Done\"}")); snprintf_P(svalue, sizeof(svalue), PSTR("{\"Wakeup\":\"Done\"}"));
mqtt_publish_topic_P(2, PSTR("WAKEUP"), svalue); 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_any = 0;
sl_lcolor[0] = sl_tcolor[0];
sl_lcolor[1] = sl_tcolor[1];
for (byte i = 0; i < sfl_flg; i++) { for (byte i = 0; i < sfl_flg; i++) {
if (pin[GPIO_PWM1 +i] < 99) { sl_lcolor[i] = sl_tcolor[i];
analogWrite(pin[GPIO_PWM1 +i], ((sysCfg.led_table) ? ledTable[sl_lcolor[i]] : sl_lcolor[i]) * (PWM_RANGE / 255)); 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 * 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) void sl_replaceHSB(String *response)
{ {
response->replace("{h}", "0"); float hue;
response->replace("{s}", "0"); float sat;
response->replace("{b}", String((uint8_t)(2.54f * (float)sysCfg.led_dimmer[0]))); 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) void sl_getHSB(float *hue, float *sat, float *bri)
{ {
*hue = 0; if (sfl_flg > 2) {
*sat = 0; sl_rgb2hsb(hue, sat, bri);
*bri = (2.54f * (float)sysCfg.led_dimmer[0]); } 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]; char svalue[MESSZ];
HsbColor hsb;
uint8_t tmp = (uint8_t)(bri * 100); /*
sysCfg.led_dimmer[0] = tmp; char log[LOGSZ];
sl_prepPower(svalue, sizeof(svalue)); char stemp1[10];
mqtt_publish_topic_P(5, "DIMMER", svalue); 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 serviced = true;
boolean coldim = false; boolean coldim = false;
char scolor[11];
char *p;
if ((2 == sfl_flg) && !strcmp_P(type,PSTR("COLOR"))) { if ((sfl_flg > 1) && !strcmp_P(type,PSTR("COLOR"))) {
uint8_t my_color[2]; if ((2 * sfl_flg) == data_len) {
char *p; for (byte i = 0; i < sfl_flg; i++) {
if (4 == data_len) { strlcpy(scolor, dataBufUc + (i *2), 3);
sl_setColor(dataBufUc); sl_dcolor[i] = (uint8_t)strtol(scolor, &p, 16);
}
sl_setColor();
coldim = true; coldim = true;
} else { } else {
sl_setDim(sysCfg.led_dimmer[0]); snprintf_P(svalue, ssvalue, PSTR("{\"Color\":\"%s\"}"), sl_getColor(scolor));
uint16_t color = (uint16_t)sl_dcolor[0] << 8; }
color += (uint16_t)sl_dcolor[1]; }
snprintf_P(svalue, ssvalue, PSTR("{\"Color\":\"%04X\"}"), color); 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"))) { else if (!strcmp_P(type,PSTR("DIMMER"))) {

View File

@ -533,6 +533,7 @@ void hue_lights(String *path)
float bri = 0; float bri = 0;
float hue = 0; float hue = 0;
float sat = 0; float sat = 0;
uint16_t ct = 0;
bool resp = false; bool resp = false;
bool on = false; bool on = false;
bool change = false; bool change = false;
@ -636,9 +637,20 @@ void hue_lights(String *path)
response.replace("{res}", String(tmp)); response.replace("{res}", String(tmp));
change = true; 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 (change) {
if (sfl_flg) { if (sfl_flg) {
sl_setHSB(hue, sat, bri); sl_setHSB(hue, sat, bri, ct);
#ifdef USE_WS2812 #ifdef USE_WS2812
} }
else if (pin[GPIO_WS2812] < 99) { else if (pin[GPIO_WS2812] < 99) {
@ -655,6 +667,9 @@ void hue_lights(String *path)
else { else {
response = FPSTR(HUE_ERROR_JSON); response = FPSTR(HUE_ERROR_JSON);
} }
//addLog(LOG_LEVEL_DEBUG_MORE, response.c_str());
webServer->send(200, FPSTR(HDR_CTYPE_JSON), response); webServer->send(200, FPSTR(HDR_CTYPE_JSON), response);
} }
else if(path->indexOf("/lights/") >= 0) { // Got /lights/ID else if(path->indexOf("/lights/") >= 0) { // Got /lights/ID
@ -678,6 +693,9 @@ void hue_lights(String *path)
void hue_groups(String *path) void hue_groups(String *path)
{ {
/*
* http://sonoff/api/username/groups?1={"name":"Woonkamer","lights":[],"type":"Room","class":"Living room"})
*/
String response = "{}"; String response = "{}";
if (path->endsWith("/0")) { if (path->endsWith("/0")) {

View File

@ -22,7 +22,7 @@
* WS2812 Leds using NeopixelBus library * WS2812 Leds using NeopixelBus library
\*********************************************************************************************/ \*********************************************************************************************/
#include <NeoPixelBus.h> //#include <NeoPixelBus.h> // Global defined as also used by Sonoff Led
#ifdef USE_WS2812_DMA #ifdef USE_WS2812_DMA
#if (USE_WS2812_CTYPE == 1) #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) void ws2812_getColor(uint16_t led, char* svalue, uint16_t ssvalue)
{ {
RgbColor mcolor; RgbColor mcolor;
@ -504,6 +473,41 @@ void ws2812_init(uint8_t powerbit)
ws2812_pixels(); 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 * Commands
\*********************************************************************************************/ \*********************************************************************************************/