diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 1ad9bb410..9b04c9236 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,6 +1,7 @@ /* 5.12.0e * Add a second TLS fingerprint to allow switching keys in TLS mode (#2033, #2102) * Add HTML language header in local language (#2123) + * Add commands Color6 RRGGBB for Clock marker color and Rotation pixels for Clock rotation (#2092) * * 5.12.0d * Add support for optional MQTT drivers to be selected in user_config.h (#1992) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index e0e115b50..6b724fce9 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -250,6 +250,7 @@ #define D_CMND_LEDTABLE "LedTable" #define D_CMND_FADE "Fade" #define D_CMND_PIXELS "Pixels" +#define D_CMND_ROTATION "Rotation" #define D_CMND_SCHEME "Scheme" #define D_CMND_SPEED "Speed" #define D_CMND_WAKEUP "Wakeup" diff --git a/sonoff/settings.h b/sonoff/settings.h index a3049dbca..3cdedb488 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -116,11 +116,9 @@ struct SYSCFG { byte syslog_level; // 1AA uint8_t webserver; // 1AB byte weblog_level; // 1AC - -// char mqtt_fingerprint[60]; // 1AD uint8_t mqtt_fingerprint[2][20]; // 1AD - byte free_1D5[20]; // 1D5 + byte free_1D5[20]; // 1D5 Free since 5.12.0e char mqtt_host[33]; // 1E9 uint16_t mqtt_port; // 20A @@ -186,7 +184,7 @@ struct SYSCFG { uint16_t blinktime; // 39A uint16_t blinkcount; // 39C - uint16_t ws_pixels; // 39E Not used since 5.8.0 + uint16_t light_rotation; // 39E uint8_t ws_red; // 3A0 Not used since 5.8.0 uint8_t ws_green; // 3A1 Not used since 5.8.0 uint8_t ws_blue; // 3A2 Not used since 5.8.0 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index b0d6c444e..72bbcf5fc 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -579,6 +579,7 @@ void SettingsDefaultSet2() // 5.8.0 Settings.light_pixels = WS2812_LEDS; +// Settings.light_rotation = 0; // 5.8.1 // Settings.altitude = 0; @@ -597,7 +598,6 @@ void SettingsDefaultSet2() void SettingsDefaultSet_3_2_4() { - Settings.ws_pixels = WS2812_LEDS; Settings.ws_red = 255; Settings.ws_green = 0; Settings.ws_blue = 0; @@ -625,6 +625,7 @@ void SettingsDefaultSet_3_9_3() } Settings.light_pixels = WS2812_LEDS; + Settings.light_rotation = 0; for (byte i = 0; i < MAX_PWMS; i++) { Settings.light_color[i] = 255; } @@ -835,7 +836,7 @@ void SettingsDelta() } } if (!Settings.light_pixels && cfg_wsflg) { - Settings.light_pixels = Settings.ws_pixels; + Settings.light_pixels = WS2812_LEDS; Settings.light_color[0] = Settings.ws_red; Settings.light_color[1] = Settings.ws_green; Settings.light_color[2] = Settings.ws_blue; @@ -887,6 +888,7 @@ void SettingsDelta() Settings.flag.not_power_linked = 0; } if (Settings.version < 0x050C0005) { + Settings.light_rotation = 0; char fingerprint[60]; memcpy(fingerprint, Settings.mqtt_fingerprint, sizeof(fingerprint)); char *p = fingerprint; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index cfa72ffe6..df588119c 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -138,8 +138,8 @@ enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_MAX_PARAM8}; enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_MAX_SENSORS}; -enum Ws2812ClockIndex {WS_SECOND, WS_MINUTE, WS_HOUR}; -enum Ws2812Color {WS_RED, WS_GREEN, WS_BLUE}; +enum Ws2812ClockIndex { WS_SECOND, WS_MINUTE, WS_HOUR, WS_MARKER }; +enum Ws2812Color { WS_RED, WS_GREEN, WS_BLUE }; enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, LT_NU8, LT_NU9, LT_NU10, LT_WS2812, LT_RGBW, LT_RGBWC}; enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC}; enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; diff --git a/sonoff/xdrv_01_light.ino b/sonoff/xdrv_01_light.ino index 432788878..6bcf20bea 100644 --- a/sonoff/xdrv_01_light.ino +++ b/sonoff/xdrv_01_light.ino @@ -55,10 +55,10 @@ enum LightCommands { CMND_COLOR, CMND_COLORTEMPERATURE, CMND_DIMMER, CMND_LED, CMND_LEDTABLE, CMND_FADE, - CMND_PIXELS, 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_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_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 "|UNDOCA" ; struct LRgbColor { uint8_t R, G, B; @@ -1018,7 +1018,7 @@ boolean LightCommand() char option = (1 == XdrvMailbox.data_len) ? XdrvMailbox.data[0] : '\0'; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kLightCommands); - if ((CMND_COLOR == command_code) && (light_subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { + if ((CMND_COLOR == command_code) && (light_subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { if (XdrvMailbox.data_len > 0) { valid_entry = LightColorEntry(XdrvMailbox.data, XdrvMailbox.data_len); if (valid_entry) { @@ -1031,7 +1031,7 @@ boolean LightCommand() } Settings.light_scheme = 0; coldim = true; - } else { // Color3, 4 and 5 + } else { // Color3, 4, 5 and 6 for (byte i = 0; i < LST_RGB; i++) { Settings.ws_color[XdrvMailbox.index -3][i] = light_entry_color[i]; } @@ -1065,11 +1065,18 @@ boolean LightCommand() else if ((CMND_PIXELS == command_code) && (LT_WS2812 == light_type)) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= WS2812_MAX_LEDS)) { Settings.light_pixels = XdrvMailbox.payload; + Settings.light_rotation = 0; Ws2812Clear(); light_update = 1; } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_pixels); } + else if ((CMND_ROTATION == command_code) && (LT_WS2812 == light_type)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < Settings.light_pixels)) { + Settings.light_rotation = XdrvMailbox.payload; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_rotation); + } else if ((CMND_WIDTH == command_code) && (LT_WS2812 == light_type) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { if (1 == XdrvMailbox.index) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 4)) { diff --git a/sonoff/xplg_ws2812.ino b/sonoff/xplg_ws2812.ino index d8d085085..42aafb8f3 100644 --- a/sonoff/xplg_ws2812.ino +++ b/sonoff/xplg_ws2812.ino @@ -114,9 +114,7 @@ void Ws2812StripShow() int mod(int a, int b) { int ret = a % b; - if (ret < 0) { - ret += b; - } + if (ret < 0) ret += b; return ret; } @@ -142,13 +140,15 @@ void Ws2812UpdatePixelColor(int position, struct WsColor hand_color, float offse void Ws2812UpdateHand(int position, uint8_t index) { - if (Settings.flag.ws_clock_reverse) { - position = Settings.light_pixels -position; - } + position = (position + Settings.light_rotation) % Settings.light_pixels; + + if (Settings.flag.ws_clock_reverse) position = Settings.light_pixels -position; WsColor hand_color = { Settings.ws_color[index][WS_RED], Settings.ws_color[index][WS_GREEN], Settings.ws_color[index][WS_BLUE] }; Ws2812UpdatePixelColor(position, hand_color, 1); - uint8_t range = ((Settings.ws_width[index] -1) / 2) +1; + + uint8_t range = 1; + if (index < WS_MARKER) range = ((Settings.ws_width[index] -1) / 2) +1; for (uint8_t h = 1; h < range; h++) { float offset = (float)(range - h) / (float)range; Ws2812UpdatePixelColor(position -h, hand_color, offset); @@ -160,9 +160,15 @@ void Ws2812Clock() { strip->ClearTo(0); // Reset strip int clksize = 60000 / (int)Settings.light_pixels; + Ws2812UpdateHand((RtcTime.second * 1000) / clksize, WS_SECOND); Ws2812UpdateHand((RtcTime.minute * 1000) / clksize, WS_MINUTE); Ws2812UpdateHand(((RtcTime.hour % 12) * (5000 / clksize)) + ((RtcTime.minute * 1000) / (12 * clksize)), WS_HOUR); + if (Settings.ws_color[WS_MARKER][WS_RED] + Settings.ws_color[WS_MARKER][WS_GREEN] + Settings.ws_color[WS_MARKER][WS_BLUE]) { + for (byte i = 0; i < 12; i++) { + Ws2812UpdateHand((i * 5000) / clksize, WS_MARKER); + } + } Ws2812StripShow(); } @@ -207,9 +213,7 @@ void Ws2812Gradient(uint8_t schemenr) #endif ColorScheme scheme = kSchemes[schemenr]; - if (scheme.count < 2) { - return; - } + if (scheme.count < 2) return; uint8_t repeat = kRepeat[Settings.light_width]; // number of scheme.count per ledcount uint16_t range = (uint16_t)ceil((float)Settings.light_pixels / (float)repeat); @@ -260,9 +264,7 @@ void Ws2812Bars(uint8_t schemenr) ColorScheme scheme = kSchemes[schemenr]; uint16_t maxSize = Settings.light_pixels / scheme.count; - if (kWidth[Settings.light_width] > maxSize) { - maxSize = 0; - } + if (kWidth[Settings.light_width] > maxSize) maxSize = 0; uint16_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); uint8_t offset = speed > 0 ? strip_timer_counter / speed : 0; @@ -280,9 +282,7 @@ void Ws2812Bars(uint8_t schemenr) } uint8_t colorIndex = offset % scheme.count; for (i = 0; i < Settings.light_pixels; i++) { - if (maxSize) { - colorIndex = ((i + offset) % (scheme.count * kWidth[Settings.light_width])) / kWidth[Settings.light_width]; - } + if (maxSize) colorIndex = ((i + offset) % (scheme.count * kWidth[Settings.light_width])) / kWidth[Settings.light_width]; c.R = mcolor[colorIndex].red; c.G = mcolor[colorIndex].green; c.B = mcolor[colorIndex].blue;