From 2c4b8a4a3b5acd42834584b8043e1d24cf79993d Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Tue, 20 Mar 2018 16:28:18 +0100 Subject: [PATCH] v5.12.0h - Add HSBColor and Channel commands 5.12.0h * Add PWM status to command State if PWM enabled (#2203) * Add command HSBColor Hue,Sat,Bri (#1642, #2203) * Add command Channel 0..100 to control dimmer value for individual color channels (#2111, #2203) --- sonoff/_releasenotes.ino | 3 ++ sonoff/i18n.h | 5 +++- sonoff/sonoff.ino | 30 ++++++++++++++------ sonoff/support.ino | 2 +- sonoff/xdrv_01_light.ino | 59 ++++++++++++++++++++++++++++++++++++++-- 5 files changed, 86 insertions(+), 13 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 7dd12439a..41334f0a6 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,6 +1,9 @@ /* 5.12.0h * Add support for Software Serial bridge using commands SerialDelimiter, SBaudrate and SSerialSend. Supports 8N1 and text only (#2190) * Add support for Hardware Serial bridge using commands SerialDelimiter, Baudrate and SerialSend. Supports 8N1 and text only (#2182) + * Add PWM status to command State if PWM enabled (#2203) + * Add command HSBColor Hue,Sat,Bri (#1642, #2203) + * Add command Channel 0..100 to control dimmer value for individual color channels (#2111, #2203) * * 5.12.0f * Add compile time support for WS2812 BRG and RBG led configurations to be defined in user_config.h (#1690) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index ce785243d..71a795297 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -63,6 +63,7 @@ #define D_JSON_GATEWAY "Gateway" #define D_JSON_HEAPSIZE "Heap" #define D_JSON_HIGH "High" +#define D_JSON_HSBCOLOR "HSBColor" #define D_JSON_HUMIDITY "Humidity" #define D_JSON_I2CSCAN_DEVICES_FOUND_AT "Device(s) found at" #define D_JSON_I2CSCAN_UNKNOWN_ERROR_AT "Unknown error at" @@ -247,9 +248,11 @@ #define D_CMND_EXCEPTION "Exception" // Commands xdrv_01_light.ino +#define D_CMND_CHANNEL "Channel" #define D_CMND_COLOR "Color" #define D_CMND_COLORTEMPERATURE "CT" #define D_CMND_DIMMER "Dimmer" +#define D_CMND_HSBCOLOR "HSBColor" #define D_CMND_LED "Led" #define D_CMND_LEDTABLE "LedTable" #define D_CMND_FADE "Fade" @@ -483,4 +486,4 @@ const char S_INFORMATION[] PROGMEM = D_INFORMATION; const char S_RESTART[] PROGMEM = D_RESTART; #endif // USE_WEBSERVER -#endif // _I18N_H_ \ No newline at end of file +#endif // _I18N_H_ diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 941ec36c6..695cf1c0b 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -737,15 +737,9 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) Settings.pwm_value[index -1] = payload; analogWrite(pin[GPIO_PWM1 + index -1], bitRead(pwm_inverted, index -1) ? Settings.pwm_range - payload : payload); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_PWM "\":{")); - bool first = true; - for (byte i = 0; i < MAX_PWMS; i++) { - if (pin[GPIO_PWM1 + i] < 99) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_PWM "%d\":%d"), mqtt_data, first ? "" : ",", i+1, Settings.pwm_value[i]); - first = false; - } - } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}}"),mqtt_data); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); + MqttShowPWMState(); // Render the PWM status to MQTT + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } else if (CMND_PWMFREQUENCY == command_code) { if ((1 == payload) || ((payload >= 100) && (payload <= 4000))) { @@ -1327,6 +1321,19 @@ void PublishStatus(uint8_t payload) } +void MqttShowPWMState() +{ + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_PWM "\":{"), mqtt_data); + bool first = true; + for (byte i = 0; i < MAX_PWMS; i++) { + if (pin[GPIO_PWM1 + i] < 99) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_PWM "%d\":%d"), mqtt_data, first ? "" : ",", i+1, Settings.pwm_value[i]); + first = false; + } + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); +} + void MqttShowState() { char stemp1[33]; @@ -1345,6 +1352,11 @@ void MqttShowState() } } + if (pwm_present) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + MqttShowPWMState(); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_RSSI "\":%d,\"" D_JSON_APMAC_ADDRESS "\":\"%s\"}}"), mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.BSSIDstr().c_str()); } diff --git a/sonoff/support.ino b/sonoff/support.ino index 4689ae707..6a1293ccf 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -223,7 +223,7 @@ char* Unescape(char* buffer, uint16_t* size) case 'f': che = '\f'; break; // 0C Formfeed case 'n': che = '\n'; break; // 0A Linefeed (Newline) case 'r': che = '\r'; break; // 0D Carriage return -// case 's': che = ' '; break; // 20 Space + case 's': che = ' '; break; // 20 Space case 't': che = '\t'; break; // 09 Horizontal tab case 'v': che = '\v'; break; // 0B Vertical tab // case '?': che = '\?'; break; // 3F Question mark diff --git a/sonoff/xdrv_01_light.ino b/sonoff/xdrv_01_light.ino index f5f6184c7..61a599c86 100644 --- a/sonoff/xdrv_01_light.ino +++ b/sonoff/xdrv_01_light.ino @@ -55,10 +55,12 @@ enum LightCommands { CMND_COLOR, CMND_COLORTEMPERATURE, CMND_DIMMER, CMND_LED, CMND_LEDTABLE, CMND_FADE, - CMND_PIXELS, CMND_ROTATION, CMND_SCHEME, CMND_SPEED, CMND_WAKEUP, CMND_WAKEUPDURATION, CMND_WIDTH, CMND_UNDOCA }; + CMND_PIXELS, CMND_ROTATION, CMND_SCHEME, CMND_SPEED, CMND_WAKEUP, CMND_WAKEUPDURATION, + CMND_WIDTH, CMND_CHANNEL, CMND_HSBCOLOR, CMND_UNDOCA }; const char kLightCommands[] PROGMEM = D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_LED "|" D_CMND_LEDTABLE "|" D_CMND_FADE "|" - D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" D_CMND_WIDTH "|UNDOCA" ; + D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" + D_CMND_WIDTH "|" D_CMND_CHANNEL "|" D_CMND_HSBCOLOR "|UNDOCA" ; struct LRgbColor { uint8_t R, G, B; @@ -535,6 +537,8 @@ void LightState(uint8_t append) { char scolor[25]; char scommand[33]; + float hsb[3]; + int16_t h,s,b; if (append) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); @@ -546,6 +550,15 @@ void LightState(uint8_t append) mqtt_data, scommand, GetStateText(light_power), Settings.light_dimmer); if (light_subtype > LST_SINGLE) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLOR "\":\"%s\""), mqtt_data, LightGetColor(0, scolor)); + + // Add status for HSB + LightGetHsb(&hsb[0],&hsb[1],&hsb[2]); + // Scale these percentages up to the numbers expected byt he client + h = round(hsb[0] * 360); + s = round(hsb[1] * 100); + b = round(hsb[2] * 100); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_HSBCOLOR "\":\"%d,%d,%d\""), mqtt_data, h,s,b); + } if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLORTEMPERATURE "\":%d"), mqtt_data, LightGetColorTemp()); @@ -1053,6 +1066,48 @@ boolean LightCommand() snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor); } } + else if ((CMND_CHANNEL == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= light_subtype ) ) { + // Set "Channel" directly - this allows Color and Direct PWM control to coexist + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + uint8_t level = XdrvMailbox.payload; + light_current_color[XdrvMailbox.index-1] = round(level * 2.55); + LightSetColor(); + coldim = true; + } + snprintf_P(scolor, 25, PSTR("%d"), round(light_current_color[XdrvMailbox.index -1] / 2.55)); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor); + } + else if ((CMND_HSBCOLOR == command_code) && ( light_subtype >= LST_RGB)) { + // Implement method to "direct set" color by HSB (HSB is passed comma separated, 0360) ? (HSB[0] % 360) : HSB[0] ) /360.0, + ( (HSB[1]>100) ? (HSB[1] % 100) : HSB[1] ) /100.0, + ( (HSB[2]>100) ? (HSB[2] % 100) : HSB[2] ) /100.0, + 0); + } else { + LightState(0); + } + } #ifdef USE_WS2812 // *********************************************************************** else if ((CMND_LED == command_code) && (LT_WS2812 == light_type) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= Settings.light_pixels)) { if (XdrvMailbox.data_len > 0) {