diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e12f18640..882d09787 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -7,6 +7,8 @@ * Add define USE_SONOFF_RF to enable/disable Sonoff Rf support (#6648) * Add incremental beeps to Ifan03 remote control fan speed buttons (#6636) * Add rule support after every command execution like Fanspeed#Data=2 (#6636) + * Fix handling of ligth channels when pwm_multichannel (Option68) is enabled + * Add WebUI for multiple, independent PWM channels * * 6.6.0.17 20191009 * Add command SetOption34 0..255 to set backlog delay. Default value is 200 (mSeconds) (#6562) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 474ce1289..936b46c28 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -153,39 +153,17 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = #endif // USE_SCRIPT_WEB_DISPLAY #ifdef USE_JAVASCRIPT_ES6 - "lb=p=>la('&d='+p);" // Dark - Bright &d related to lb(value) and WebGetArg("d", tmp, sizeof(tmp)); - "lc=p=>la('&t='+p);" // Cold - Warm &t related to lc(value) and WebGetArg("t", tmp, sizeof(tmp)); + "lb=(v,p)=>la(`&${v}=${p}`);" + "lc=(v,i,p)=>la(`&${v}${i}=${p}`);" #else - "function lb(p){" - "la('&d='+p);" // &d related to WebGetArg("d", tmp, sizeof(tmp)); + "function lb(v,p){" + "la('&'+v+'='+p);" "}" - "function lc(p){" - "la('&t='+p);" // &t related to WebGetArg("t", tmp, sizeof(tmp)); + "function lc(v,i,p){" + "la('&'+v+i+'='+p);" "}" #endif // USE_JAVASCRIPT_ES6 -#ifdef USE_SHUTTER -#ifdef USE_JAVASCRIPT_ES6 - "ld1=p=>la('&u1='+p);" - "ld2=p=>la('&u2='+p);" - "ld3=p=>la('&u3='+p);" - "ld4=p=>la('&u4='+p);" -#else - "function ld1(p){" - "la('&u1='+p);" - "}" - "function ld2(p){" - "la('&u2='+p);" - "}" - "function ld3(p){" - "la('&u3='+p);" - "}" - "function ld4(p){" - "la('&u4='+p);" - "}" -#endif // USE_JAVASCRIPT_ES6 -#endif // USE_SHUTTER - "wl(la);"; const char HTTP_SCRIPT_WIFI[] PROGMEM = @@ -395,16 +373,11 @@ const char HTTP_HEAD_STYLE3[] PROGMEM = "

%s

"; const char HTTP_MSG_SLIDER1[] PROGMEM = - "
" D_COLDLIGHT "" D_WARMLIGHT "
" - "
"; + "
%s%s
" + "
"; const char HTTP_MSG_SLIDER2[] PROGMEM = - "
" D_DARKLIGHT "" D_BRIGHTLIGHT "
" - "
"; -#ifdef USE_SHUTTER -const char HTTP_MSG_SLIDER3[] PROGMEM = - "
" D_CLOSE "" D_OPEN "
" - "
"; -#endif // USE_SHUTTER + "
%s%s
" + "
"; const char HTTP_MSG_RSTRT[] PROGMEM = "
" D_DEVICE_WILL_RESTART "

"; @@ -1012,16 +985,31 @@ void HandleRoot(void) if (devices_present) { #ifdef USE_LIGHT if (light_type) { - if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { - WSContentSend_P(HTTP_MSG_SLIDER1, LightGetColorTemp()); - } - WSContentSend_P(HTTP_MSG_SLIDER2, Settings.light_dimmer); + if (!Settings.flag3.pwm_multi_channels) { + if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { + // Cold - Warm &t related to lb("t", value) and WebGetArg("t", tmp, sizeof(tmp)); + WSContentSend_P(HTTP_MSG_SLIDER1, F(D_COLDLIGHT), F(D_WARMLIGHT), + 153, 500, LightGetColorTemp(), 't'); + } + // Dark - Bright &d related to lb("d", value) and WebGetArg("d", tmp, sizeof(tmp)); + WSContentSend_P(HTTP_MSG_SLIDER1, F(D_DARKLIGHT), F(D_BRIGHTLIGHT), + 1, 100, Settings.light_dimmer, 'd'); + } else { // Settings.flag3.pwm_multi_channels + uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + for (uint32_t i = 0; i < pwm_channels; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("c%d"), i); + WSContentSend_P(HTTP_MSG_SLIDER2, stemp, FPSTR("100%"), + 1, 100, + changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), 'd', i+1); + } + } // Settings.flag3.pwm_multi_channels } #endif #ifdef USE_SHUTTER if (Settings.flag3.shutter_mode) { for (uint32_t i = 0; i < shutters_present; i++) { - WSContentSend_P(HTTP_MSG_SLIDER3, Settings.shutter_position[i], i+1); + WSContentSend_P(HTTP_MSG_SLIDER2, F(D_CLOSE), F(D_OPEN), + 0, 100, Settings.shutter_position[i], 'u', i+1); } } #endif // USE_SHUTTER @@ -1097,6 +1085,7 @@ bool HandleRootStatusRefresh(void) char tmp[8]; // WebGetArg numbers only char svalue[32]; // Command and number parameter + char webindex[5]; // WebGetArg name WebGetArg("o", tmp, sizeof(tmp)); // 1 - 16 Device number for button Toggle or Fanspeed if (strlen(tmp)) { @@ -1122,13 +1111,21 @@ bool HandleRootStatusRefresh(void) snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } + uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + for (uint32_t j = 1; j <= pwm_channels; j++) { + snprintf_P(webindex, sizeof(webindex), PSTR("d%d"), j); + WebGetArg(webindex, tmp, sizeof(tmp)); // 0 - 100 percent + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_CHANNEL "%d %s"), j, tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + } WebGetArg("t", tmp, sizeof(tmp)); // 153 - 500 Color temperature if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } #ifdef USE_SHUTTER - char webindex[5]; // WebGetArg name for (uint32_t j = 1; j <= shutters_present; j++) { snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j); WebGetArg(webindex, tmp, sizeof(tmp)); // 0 - 100 percent diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 2fafd2e6c..603e95f30 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -420,6 +420,14 @@ class LightStateClass { getActualRGBCW(&channels[0], &channels[1], &channels[2], &channels[3], &channels[4]); } + void getChannelsRaw(uint8_t *channels) { + channels[0] = _r; + channels[1] = _g; + channels[2] = _b; + channels[3] = _wc; + channels[4] = _ww; + } + void getHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { if (hue) { *hue = _hue; } if (sat) { *sat = _sat; } @@ -602,6 +610,16 @@ class LightStateClass { #endif } + // set all 5 channels at once, don't modify the values in ANY way + // Channels are: R G B CW WW + void setChannelsRaw(uint8_t *channels) { + _r = channels[0]; + _g = channels[1]; + _b = channels[2]; + _wc = channels[3]; + _ww = channels[4]; +} + // set all 5 channels at once. // Channels are: R G B CW WW // Brightness is automatically recalculated to adjust channels to the desired values @@ -838,10 +856,13 @@ public: AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings light_type/sub (%d %d)", light_type, Light.subtype); #endif - // first try setting CW, if zero, it select RGB mode - _state->setCW(Settings.light_color[3], Settings.light_color[4], true); - _state->setRGB(Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); - if (!_pwm_multi_channels) { + if (_pwm_multi_channels) { + _state->setChannelsRaw(Settings.light_color); + } else { + // first try setting CW, if zero, it select RGB mode + _state->setCW(Settings.light_color[3], Settings.light_color[4], true); + _state->setRGB(Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); + // only if non-multi channel // We apply dimmer in priority to RGB uint8_t bri = _state->DimmerToBri(Settings.light_dimmer); @@ -893,16 +914,13 @@ public: // calculate the levels for each channel void calcLevels() { uint8_t r,g,b,c,w,briRGB,briCT; - _state->getActualRGBCW(&r,&g,&b,&c,&w); if (_pwm_multi_channels) { // if PWM multi channel, no more transformation required - Light.current_color[0] = r; - Light.current_color[1] = g; - Light.current_color[2] = b; - Light.current_color[3] = c; - Light.current_color[4] = w; + _state->getChannelsRaw(Light.current_color); return; } + + _state->getActualRGBCW(&r,&g,&b,&c,&w); briRGB = _state->getBriRGB(); briCT = _state->getBriCT(); @@ -948,9 +966,7 @@ public: void saveSettings() { if (Light.pwm_multi_channels) { // simply save each channel - _state->getActualRGBCW(&Settings.light_color[0], &Settings.light_color[1], - &Settings.light_color[2], &Settings.light_color[3], - &Settings.light_color[4]); + _state->getChannelsRaw(Settings.light_color); Settings.light_dimmer = 100; // arbitrary value, unused in this mode } else { uint8_t cm = _state->getColorMode(); @@ -980,13 +996,16 @@ public: // Channels are: R G B CW WW // Brightness is automatically recalculated to adjust channels to the desired values void changeChannels(uint8_t *channels) { - if (LST_COLDWARM == Light.subtype) { + if (Light.pwm_multi_channels) { + _state->setChannelsRaw(channels); + } else if (LST_COLDWARM == Light.subtype) { // remap channels 0-1 to 3-4 if cold/warm uint8_t remapped_channels[5] = {0,0,0,channels[0],channels[1]}; _state->setChannels(remapped_channels); } else { _state->setChannels(channels); } + saveSettings(); calcLevels(); }