kopia lustrzana https://github.com/Aircoookie/WLED
				
				
				
			Merge branch 'master' into groupfinal
						commit
						6bc927c535
					
				|  | @ -4,14 +4,17 @@ | |||
| [platformio] | ||||
| src_dir = ./wled00 | ||||
| data_dir = ./wled00/data | ||||
| lib_extra_dirs = ./wled00/src | ||||
| ;lib_extra_dirs = ./wled00/src | ||||
| lib_dir = ./wled00/src | ||||
| ; Please uncomment one of the 5 lines below to select your board | ||||
| ; env_default = nodemcuv2 | ||||
| ; env_default = esp01 | ||||
| ; env_default = esp01_1m | ||||
| ; env_default = d1_mini | ||||
| ; env_default = esp32dev | ||||
| 
 | ||||
| ; env_default = esp8285_4CH_MagicHome | ||||
| ; env_default = esp8285_4CH_H801 | ||||
| ; env_default = esp8285_5CH_H801 | ||||
| 
 | ||||
| [common] | ||||
| framework = arduino | ||||
|  | @ -38,6 +41,8 @@ lib_deps_external = | |||
|   IRremoteESP8266@2.5.5 | ||||
|   #Time@1.5 | ||||
|   #Timezone@1.2.1 | ||||
|   #For use SSD1306 0.91" OLED display uncomment following | ||||
|   #U8g2@~2.27.2 | ||||
| 
 | ||||
| [common:esp8266] | ||||
| # ------------------------------------------------------------------------------ | ||||
|  | @ -77,7 +82,7 @@ build_flags = | |||
|   -D WLED_DISABLE_BLYNK | ||||
|   -D WLED_DISABLE_CRONIXIE | ||||
|   ; -D WLED_DISABLE_HUESYNC | ||||
|   -D WLED_DISABLE_INFRARED | ||||
|   ; -D WLED_DISABLE_INFRARED | ||||
| 
 | ||||
| [common:esp8266_512k] | ||||
| platform = espressif8266@1.8.0 | ||||
|  | @ -89,15 +94,15 @@ build_flags = | |||
|   ; -D WLED_DISABLE_ALEXA | ||||
|   -D WLED_DISABLE_BLYNK | ||||
|   -D WLED_DISABLE_CRONIXIE | ||||
|   ; -D WLED_DISABLE_HUESYNC | ||||
|   -D WLED_DISABLE_INFRARED | ||||
|   -D WLED_DISABLE_HUESYNC | ||||
|   ; -D WLED_DISABLE_INFRARED | ||||
| 
 | ||||
| [common:esp32] | ||||
| platform = espressif32@1.11.1 | ||||
| build_flags = | ||||
|   -D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH | ||||
|   -D ARDUINO_ARCH_ESP32 | ||||
|   -D WLED_DISABLE_INFRARED | ||||
|   -D WLED_DISABLE_INFRARED  | ||||
| 
 | ||||
| # see: http://docs.platformio.org/en/latest/platforms/espressif8266.html | ||||
| [env:nodemcuv2] | ||||
|  | @ -147,6 +152,7 @@ framework = ${common.framework} | |||
| build_flags = | ||||
|   ${common.build_flags} | ||||
|   ${common:esp8266_512k.build_flags} | ||||
|   -D WLED_DISABLE_INFRARED | ||||
| lib_deps = | ||||
|   ${common.lib_deps_external} | ||||
| 
 | ||||
|  | @ -165,3 +171,49 @@ lib_deps = | |||
| lib_ignore = | ||||
|   IRremoteESP8266 | ||||
|   ESPAsyncUDP | ||||
| 
 | ||||
| [env:esp8285_4CH_MagicHome] | ||||
| board = esp8285 | ||||
| platform = ${common:esp8266_1M.platform} | ||||
| monitor_speed = ${common.monitor_speed} | ||||
| upload_speed = ${common.upload_speed} | ||||
| framework = ${common.framework} | ||||
| build_flags = | ||||
|   ${common.build_flags} | ||||
|   ${common:esp8266_1M.build_flags} | ||||
|   -D WLED_DISABLE_HUESYNC | ||||
|   -D WLED_ENABLE_ANALOG_LEDS | ||||
| lib_deps = | ||||
|   ${common.lib_deps_external} | ||||
| 
 | ||||
| [env:esp8285_4CH_H801] | ||||
| board = esp8285 | ||||
| platform = ${common:esp8266_1M.platform} | ||||
| monitor_speed = ${common.monitor_speed} | ||||
| upload_speed = ${common.upload_speed} | ||||
| framework = ${common.framework} | ||||
| build_flags = | ||||
|   ${common.build_flags} | ||||
|   ${common:esp8266_1M.build_flags} | ||||
|   -D WLED_DISABLE_HUESYNC | ||||
|   -D WLED_ENABLE_ANALOG_LEDS | ||||
|   -D WLED_USE_H801 | ||||
| lib_deps = | ||||
|   ${common.lib_deps_external} | ||||
| 
 | ||||
| [env:esp8285_5CH_H801] | ||||
| board = esp8285 | ||||
| platform = ${common:esp8266_1M.platform} | ||||
| monitor_speed = ${common.monitor_speed} | ||||
| upload_speed = ${common.upload_speed} | ||||
| framework = ${common.framework} | ||||
| build_flags = | ||||
|   ${common.build_flags} | ||||
|   ${common:esp8266_1M.build_flags} | ||||
|   -D WLED_DISABLE_HUESYNC | ||||
|   -D WLED_ENABLE_ANALOG_LEDS | ||||
|   -D WLED_USE_H801 | ||||
|   -D WLED_ENABLE_5CH_LEDS  | ||||
| lib_deps = | ||||
|   ${common.lib_deps_external} | ||||
|    | ||||
|  |  | |||
|  | @ -10,13 +10,14 @@ | |||
| A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812, APA102) LEDs! | ||||
| 
 | ||||
| ### Features: | ||||
| - WS2812FX library integrated for 80 special effects    | ||||
| - WS2812FX library integrated for almost 90 special effects   | ||||
| - FastLED noise effects and palettes   | ||||
| - Customizable Mobile and desktop UI with color and effect controls   | ||||
| - Modern UI with color, effect and segment controls   | ||||
| - Segments to set different effects and colors to parts of the LEDs   | ||||
| - Settings page - configuration over network   | ||||
| - Access Point and station mode - automatic failsafe AP   | ||||
| - Support for RGBW strips   | ||||
| - 25 user presets to save and load colors/effects easily, supports cycling through them.   | ||||
| - 16 user presets to save and load colors/effects easily, supports cycling through them.   | ||||
| - Macro functions to automatically execute API calls   | ||||
| - Nightlight function (gradually dims down)   | ||||
| - Full OTA software updatability (HTTP + ArduinoOTA), password protectable   | ||||
|  |  | |||
|  | @ -4,5 +4,5 @@ This code uses Aircookie's WLED software. It has a premade file for user modific | |||
| 
 | ||||
| To install: | ||||
| 
 | ||||
| Add the enties in the WLED00 file to the top of the same file from Aircoookies WLED. | ||||
| Add the entries in the WLED00 file to the top of the same file from Aircoookies WLED. | ||||
| Replace the WLED06_usermod.ino file in Aircoookies WLED folder. | ||||
|  |  | |||
|  | @ -0,0 +1,45 @@ | |||
| //Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
 | ||||
| 
 | ||||
| long lastTime = 0; | ||||
| int delayMs = 10; | ||||
| const int pinA = D6; //data
 | ||||
| const int pinB = D7; //clk
 | ||||
| int oldA = LOW; | ||||
| 
 | ||||
| //gets called once at boot. Do all initialization that doesn't depend on network here
 | ||||
| void userSetup() { | ||||
|   pinMode(pinA, INPUT_PULLUP); | ||||
|   pinMode(pinB, INPUT_PULLUP); | ||||
| } | ||||
| 
 | ||||
| //gets called every time WiFi is (re-)connected. Initialize own network interfaces here
 | ||||
| void userConnected() { | ||||
| } | ||||
| 
 | ||||
| //loop. You can use "if (WLED_CONNECTED)" to check for successful connection
 | ||||
| void userLoop() { | ||||
|   if (millis()-lastTime > delayMs) { | ||||
|     int A = digitalRead(pinA); | ||||
|     int B = digitalRead(pinB); | ||||
| 
 | ||||
|     if (oldA == LOW && A == HIGH) { | ||||
|       if (oldB == HIGH) { | ||||
|       // bri += 10;
 | ||||
|       // if (bri > 250) bri = 10;
 | ||||
|       effectCurrent += 1; | ||||
|       if (effectCurrent >= MODE_COUNT) effectCurrent = 0; | ||||
|     } | ||||
|     else { | ||||
|       // bri -= 10;
 | ||||
|       // if (bri < 10) bri = 250;
 | ||||
|       effectCurrent -= 1; | ||||
|       if (effectCurrent < 0) effectCurrent = (MODE_COUNT-1); | ||||
|     } | ||||
|     oldA = A; | ||||
| 
 | ||||
|     //call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
 | ||||
|     // 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
 | ||||
|     colorUpdated(6); | ||||
|     lastTime = millis(); | ||||
|   } | ||||
| } | ||||
|  | @ -1,12 +1,18 @@ | |||
| #include <U8x8lib.h> // from https://github.com/olikraus/u8g2/ | ||||
| 
 | ||||
| //The SCL and SDA pins are defined here. 
 | ||||
| //Lolin32 boards use SCL=5 SDA=4 
 | ||||
| #define U8X8_PIN_SCL 5 | ||||
| #define U8X8_PIN_SDA 4 | ||||
| 
 | ||||
| 
 | ||||
| // If display does not work or looks corrupted check the
 | ||||
| // constructor reference:
 | ||||
| // https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
 | ||||
| // or check the gallery:
 | ||||
| // https://github.com/olikraus/u8g2/wiki/gallery
 | ||||
| U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, 5, | ||||
|                                           4); // Pins are Reset, SCL, SDA
 | ||||
| U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, | ||||
|                                           U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
 | ||||
| 
 | ||||
| // gets called once at boot. Do all initialization that doesn't depend on
 | ||||
| // network here
 | ||||
|  | @ -63,7 +69,11 @@ void userLoop() { | |||
|   needRedraw = false; | ||||
| 
 | ||||
|   // Update last known values.
 | ||||
|   #if defined(ESP8266) | ||||
|   knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID(); | ||||
|   #else | ||||
|   knownSsid = WiFi.SSID(); | ||||
|   #endif | ||||
|   knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP(); | ||||
|   knownBrightness = bri; | ||||
|   knownMode = strip.getMode(); | ||||
|  | @ -74,9 +84,9 @@ void userLoop() { | |||
| 
 | ||||
|   // First row with Wifi name
 | ||||
|   u8x8.setCursor(1, 0); | ||||
|   u8x8.print(ssid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0)); | ||||
|   u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0)); | ||||
|   // Print `~` char to indicate that SSID is longer, than owr dicplay
 | ||||
|   if (ssid.length() > u8x8.getCols()) | ||||
|   if (knownSsid.length() > u8x8.getCols()) | ||||
|     u8x8.print("~"); | ||||
| 
 | ||||
|   // Second row with IP or Psssword
 | ||||
|  | @ -85,7 +95,7 @@ void userLoop() { | |||
|   if (apActive && bri == 0) | ||||
|     u8x8.print(apPass); | ||||
|   else | ||||
|     u8x8.print(ip); | ||||
|     u8x8.print(knownIp); | ||||
| 
 | ||||
|   // Third row with mode name
 | ||||
|   u8x8.setCursor(2, 2); | ||||
|  |  | |||
							
								
								
									
										1031
									
								
								wled00/FX.cpp
								
								
								
								
							
							
						
						
									
										1031
									
								
								wled00/FX.cpp
								
								
								
								
							
										
											
												Plik diff jest za duży
												Load Diff
											
										
									
								
							
							
								
								
									
										105
									
								
								wled00/FX.h
								
								
								
								
							
							
						
						
									
										105
									
								
								wled00/FX.h
								
								
								
								
							|  | @ -42,12 +42,19 @@ | |||
| 
 | ||||
| /* Not used in all effects yet */ | ||||
| #define WLED_FPS         42 | ||||
| #define FRAMETIME        1000/WLED_FPS | ||||
| #define FRAMETIME        (1000/WLED_FPS) | ||||
| 
 | ||||
| /* each segment uses 41 bytes of SRAM memory, so if you're application fails because of
 | ||||
| /* each segment uses 52 bytes of SRAM memory, so if you're application fails because of
 | ||||
|   insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ | ||||
| #define MAX_NUM_SEGMENTS 10 | ||||
| 
 | ||||
| /* How much data bytes all segments combined may allocate */ | ||||
| #ifdef ESP8266 | ||||
| #define MAX_SEGMENT_DATA 2048 | ||||
| #else | ||||
| #define MAX_SEGMENT_DATA 8192 | ||||
| #endif | ||||
| 
 | ||||
| #define NUM_COLORS       3 /* number of colors per segment */ | ||||
| #define SEGMENT          _segments[_segment_index] | ||||
| #define SEGCOLOR(x)      gamma32(_segments[_segment_index].colors[x]) | ||||
|  | @ -84,7 +91,7 @@ | |||
| #define IS_REVERSE      ((SEGMENT.options & REVERSE )     == REVERSE     ) | ||||
| #define IS_SELECTED     ((SEGMENT.options & SELECTED)     == SELECTED    ) | ||||
| 
 | ||||
| #define MODE_COUNT  87 | ||||
| #define MODE_COUNT  96 | ||||
| 
 | ||||
| #define FX_MODE_STATIC                   0 | ||||
| #define FX_MODE_BLINK                    1 | ||||
|  | @ -173,10 +180,22 @@ | |||
| #define FX_MODE_TRI_STATIC_PATTERN      84 | ||||
| #define FX_MODE_SPOTS                   85 | ||||
| #define FX_MODE_SPOTS_FADE              86 | ||||
| #define FX_MODE_GLITTER                 87 | ||||
| #define FX_MODE_CANDLE                  88 | ||||
| #define FX_MODE_STARBURST               89 | ||||
| #define FX_MODE_EXPLODING_FIREWORKS     90 | ||||
| #define FX_MODE_BOUNCINGBALLS           91 | ||||
| #define FX_MODE_SINELON                 92 | ||||
| #define FX_MODE_SINELON_DUAL            93 | ||||
| #define FX_MODE_SINELON_RAINBOW         94 | ||||
| #define FX_MODE_POPCORN                 95 | ||||
| 
 | ||||
| 
 | ||||
| class WS2812FX { | ||||
|   typedef uint16_t (WS2812FX::*mode_ptr)(void); | ||||
| 
 | ||||
|   // pre show callback
 | ||||
|   typedef void (*show_callback) (void); | ||||
|    | ||||
|   // segment parameters
 | ||||
|   public: | ||||
|  | @ -223,13 +242,33 @@ class WS2812FX { | |||
|     } segment; | ||||
| 
 | ||||
|   // segment runtime parameters
 | ||||
|     typedef struct Segment_runtime { // 16 bytes
 | ||||
|     typedef struct Segment_runtime { // 28 bytes
 | ||||
|       unsigned long next_time; | ||||
|       uint32_t step; | ||||
|       uint32_t call; | ||||
|       uint16_t aux0; | ||||
|       uint16_t aux1; | ||||
|       void reset(){next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;}; | ||||
|       byte* data = nullptr; | ||||
|       bool allocateData(uint16_t len){ | ||||
|         if (data && _dataLen == len) return true; //already allocated
 | ||||
|         deallocateData(); | ||||
|         if (WS2812FX::_usedSegmentData + len > MAX_SEGMENT_DATA) return false; //not enough memory
 | ||||
|         data = new (std::nothrow) byte[len]; | ||||
|         if (!data) return false; //allocation failed
 | ||||
|         WS2812FX::_usedSegmentData += len; | ||||
|         _dataLen = len; | ||||
|         memset(data, 0, len); | ||||
|         return true; | ||||
|       } | ||||
|       void deallocateData(){ | ||||
|         delete[] data; | ||||
|         data = nullptr; | ||||
|         WS2812FX::_usedSegmentData -= _dataLen; | ||||
|         _dataLen = 0; | ||||
|       } | ||||
|       void reset(){next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; deallocateData();} | ||||
|       private: | ||||
|         uint16_t _dataLen = 0; | ||||
|     } segment_runtime; | ||||
| 
 | ||||
|     WS2812FX() { | ||||
|  | @ -321,6 +360,15 @@ class WS2812FX { | |||
|       _mode[FX_MODE_TRI_STATIC_PATTERN]      = &WS2812FX::mode_tri_static_pattern; | ||||
|       _mode[FX_MODE_SPOTS]                   = &WS2812FX::mode_spots; | ||||
|       _mode[FX_MODE_SPOTS_FADE]              = &WS2812FX::mode_spots_fade; | ||||
|       _mode[FX_MODE_GLITTER]                 = &WS2812FX::mode_glitter; | ||||
|       _mode[FX_MODE_CANDLE]                  = &WS2812FX::mode_candle; | ||||
|       _mode[FX_MODE_STARBURST]               = &WS2812FX::mode_starburst; | ||||
|       _mode[FX_MODE_EXPLODING_FIREWORKS]     = &WS2812FX::mode_exploding_fireworks; | ||||
|       _mode[FX_MODE_BOUNCINGBALLS]           = &WS2812FX::mode_bouncing_balls; | ||||
|       _mode[FX_MODE_SINELON]                 = &WS2812FX::mode_sinelon; | ||||
|       _mode[FX_MODE_SINELON_DUAL]            = &WS2812FX::mode_sinelon_dual; | ||||
|       _mode[FX_MODE_SINELON_RAINBOW]         = &WS2812FX::mode_sinelon_rainbow; | ||||
|       _mode[FX_MODE_POPCORN]                 = &WS2812FX::mode_popcorn; | ||||
| 
 | ||||
|       _brightness = DEFAULT_BRIGHTNESS; | ||||
|       currentPalette = CRGBPalette16(CRGB::Black); | ||||
|  | @ -328,8 +376,6 @@ class WS2812FX { | |||
|       ablMilliampsMax = 850; | ||||
|       currentMilliamps = 0; | ||||
|       timebase = 0; | ||||
|       _locked = nullptr; | ||||
|       _modeUsesLock = false; | ||||
|       bus = new NeoPixelWrapper(); | ||||
|       resetSegments(); | ||||
|     } | ||||
|  | @ -346,13 +392,8 @@ class WS2812FX { | |||
|       driverModeCronixie(bool b), | ||||
|       setCronixieDigits(byte* d), | ||||
|       setCronixieBacklight(bool b), | ||||
|       setIndividual(uint16_t i, uint32_t col), | ||||
|       setRange(uint16_t i, uint16_t i2, uint32_t col), | ||||
|       lock(uint16_t i), | ||||
|       lockRange(uint16_t i, uint16_t i2), | ||||
|       unlock(uint16_t i), | ||||
|       unlockRange(uint16_t i, uint16_t i2), | ||||
|       unlockAll(void), | ||||
|       setShowCallback(show_callback cb), | ||||
|       setTransitionMode(bool t), | ||||
|       trigger(void), | ||||
|       setSegment(uint8_t n, uint16_t start, uint16_t length, uint8_t group, uint8_t spacing), | ||||
|  | @ -502,7 +543,17 @@ class WS2812FX { | |||
|       mode_static_pattern(void), | ||||
| 	    mode_tri_static_pattern(void), | ||||
|       mode_spots(void), | ||||
|       mode_spots_fade(void); | ||||
|       mode_spots_fade(void), | ||||
|       mode_glitter(void), | ||||
|       mode_candle(void), | ||||
|       mode_starburst(void), | ||||
|       mode_exploding_fireworks(void), | ||||
|       mode_bouncing_balls(void), | ||||
|       mode_sinelon(void), | ||||
|       mode_sinelon_dual(void), | ||||
|       mode_sinelon_rainbow(void), | ||||
|       mode_popcorn(void); | ||||
|        | ||||
| 
 | ||||
|   private: | ||||
|     NeoPixelWrapper *bus; | ||||
|  | @ -516,24 +567,24 @@ class WS2812FX { | |||
|     uint16_t _length; | ||||
|     uint16_t _rand16seed; | ||||
|     uint8_t _brightness; | ||||
|     static uint16_t _usedSegmentData; | ||||
| 
 | ||||
|     void handle_palette(void); | ||||
|     void fill(uint32_t); | ||||
|     bool modeUsesLock(uint8_t); | ||||
| 
 | ||||
|     bool | ||||
|       _modeUsesLock, | ||||
|       _rgbwMode, | ||||
|       _cronixieMode, | ||||
|       _cronixieBacklightEnabled, | ||||
|       _skipFirstMode, | ||||
|       _triggered; | ||||
| 
 | ||||
|     byte* _locked; | ||||
|     byte _cronixieDigits[6]; | ||||
| 
 | ||||
|     mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element
 | ||||
| 
 | ||||
|     show_callback _callback = nullptr; | ||||
| 
 | ||||
|     // mode helper functions
 | ||||
|     uint16_t | ||||
|       blink(uint32_t, uint32_t, bool strobe, bool), | ||||
|  | @ -541,6 +592,8 @@ class WS2812FX { | |||
|       scan(bool), | ||||
|       theater_chase(uint32_t, uint32_t, bool), | ||||
|       running_base(bool), | ||||
|       larson_scanner(bool), | ||||
|       sinelon_base(bool,bool), | ||||
|       dissolve(uint32_t), | ||||
|       chase(uint32_t, uint32_t, uint32_t, bool), | ||||
|       gradient_base(bool), | ||||
|  | @ -561,8 +614,10 @@ class WS2812FX { | |||
|       // start, stop, length, speed, intensity, palette, mode, options, group, spacing, opacity (unused), color[]
 | ||||
|       { 0, 7, 7, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}} | ||||
|     }; | ||||
|     segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 16 bytes per element
 | ||||
| 
 | ||||
|     segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element
 | ||||
|     friend class Segment_runtime; | ||||
|    | ||||
|     uint16_t realPixelIndex(uint16_t i); | ||||
| }; | ||||
| 
 | ||||
|  | @ -570,14 +625,15 @@ class WS2812FX { | |||
| //10 names per line
 | ||||
| const char JSON_mode_names[] PROGMEM = R"=====([ | ||||
| "Solid","Blink","Breathe","Wipe","Wipe Random","Random Colors","Sweep","Dynamic","Colorloop","Rainbow", | ||||
| "Scan","Dual Scan","Fade","Theater","Theater Rainbow","Running","Saw","Twinkle","Dissolve","Dissolve Rnd", | ||||
| "Sparkle","Dark Sparkle","Sparkle+","Strobe","Strobe Rainbow","Mega Strobe","Blink Rainbow","Android","Chase","Chase Random", | ||||
| "Scan","Scan Dual","Fade","Theater","Theater Rainbow","Running","Saw","Twinkle","Dissolve","Dissolve Rnd", | ||||
| "Sparkle","Sparkle Dark","Sparkle+","Strobe","Strobe Rainbow","Strobe Mega","Blink Rainbow","Android","Chase","Chase Random", | ||||
| "Chase Rainbow","Chase Flash","Chase Flash Rnd","Rainbow Runner","Colorful","Traffic Light","Sweep Random","Running 2","Red & Blue","Stream", | ||||
| "Scanner","Lighthouse","Fireworks","Rain","Merry Christmas","Fire Flicker","Gradient","Loading","Police","Police All", | ||||
| "Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", | ||||
| "Dual Scanner","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", | ||||
| "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Smooth Meteor","Railway","Ripple", | ||||
| "Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade" | ||||
| "Scanner Dual","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", | ||||
| "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple", | ||||
| "Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst", | ||||
| "Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn" | ||||
| ])====="; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -586,7 +642,8 @@ const char JSON_palette_names[] PROGMEM = R"=====([ | |||
| "Forest","Rainbow","Rainbow Bands","Sunset","Rivendell","Breeze","Red & Blue","Yellowout","Analogous","Splash", | ||||
| "Pastel","Sunset 2","Beech","Vintage","Departure","Landscape","Beach","Sherbet","Hult","Hult 64", | ||||
| "Drywet","Jul","Grintage","Rewhi","Tertiary","Fire","Icefire","Cyane","Light Pink","Autumn", | ||||
| "Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night","Orangery","C9","Sakura" | ||||
| "Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night","Orangery","C9","Sakura", | ||||
| "Aurora" | ||||
| ])====="; | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ | |||
| 
 | ||||
| void WS2812FX::init(bool supportWhite, uint16_t countPixels, uint8_t group, uint8_t spacing, bool skipFirst) | ||||
| { | ||||
|   if (supportWhite == _rgbwMode && countPixels == _length && _locked != NULL && group == _group && spacing == _spacing) return; | ||||
|   if (supportWhite == _rgbwMode && countPixels == _length && disableNLeds == _disableNLeds) return; | ||||
|   RESET_RUNTIME; | ||||
|   _rgbwMode = supportWhite; | ||||
|   _skipFirstMode = skipFirst; | ||||
|  | @ -46,16 +46,13 @@ void WS2812FX::init(bool supportWhite, uint16_t countPixels, uint8_t group, uint | |||
| 
 | ||||
|   bus->Begin((NeoPixelType)ty, lengthRaw); | ||||
|    | ||||
|   delete[] _locked; | ||||
|   _locked = new byte[_length]; | ||||
|    | ||||
|   _segments[0].start = 0; | ||||
| 
 | ||||
|   _segments[0].group = _group; | ||||
|   _segments[0].spacing = _spacing; | ||||
|   _segments[0].stop = getUsableCount(); | ||||
|   _segments[0].rawLength = _length; | ||||
|    | ||||
|   unlockAll(); | ||||
| 
 | ||||
|   setBrightness(_brightness); | ||||
| } | ||||
| 
 | ||||
|  | @ -91,14 +88,6 @@ void WS2812FX::service() { | |||
|   _triggered = false; | ||||
| } | ||||
| 
 | ||||
| bool WS2812FX::modeUsesLock(uint8_t m) | ||||
| { | ||||
|   if (m == FX_MODE_FIRE_2012 || m == FX_MODE_COLORTWINKLE  || | ||||
|       m == FX_MODE_METEOR    || m == FX_MODE_METEOR_SMOOTH ||  | ||||
|       m == FX_MODE_RIPPLE    || m == FX_MODE_DYNAMIC ) return true; | ||||
|   return false; | ||||
| } | ||||
| 
 | ||||
| void WS2812FX::setPixelColor(uint16_t n, uint32_t c) { | ||||
|   uint8_t w = (c >> 24); | ||||
|   uint8_t r = (c >> 16); | ||||
|  | @ -124,10 +113,10 @@ uint16_t WS2812FX::realPixelIndex(uint16_t i) { | |||
| 
 | ||||
| void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) | ||||
| { | ||||
|   if (_locked[i] && !_modeUsesLock) return; | ||||
| 
 | ||||
|   RgbwColor color; | ||||
|   color.W = w; | ||||
| 
 | ||||
|   switch (colorOrder) //0 = Grb, default
 | ||||
|   { | ||||
|     case 0: color.G = g; color.R = r; color.B = b; break; // 0 = GRB
 | ||||
|  | @ -218,6 +207,8 @@ void WS2812FX::setCronixieDigits(byte d[]) | |||
|                               //you can set it to 0 if the ESP is powered by USB and the LEDs by external
 | ||||
| 
 | ||||
| void WS2812FX::show(void) { | ||||
|   if (_callback) _callback(); | ||||
|    | ||||
|   //power limit calculation
 | ||||
|   //each LED can draw up 195075 "power units" (approx. 53mA)
 | ||||
|   //one PU is the power it takes to have 1 channel 1 step brighter per brightness step
 | ||||
|  | @ -283,7 +274,6 @@ void WS2812FX::trigger() { | |||
| void WS2812FX::setMode(uint8_t segid, uint8_t m) { | ||||
|   if (segid >= MAX_NUM_SEGMENTS) return; | ||||
|     | ||||
|   bool anyUsedLock = _modeUsesLock, anyUseLock = false; | ||||
|   if (m >= MODE_COUNT) m = MODE_COUNT - 1; | ||||
| 
 | ||||
|   if (_segments[segid].mode != m)  | ||||
|  | @ -291,13 +281,6 @@ void WS2812FX::setMode(uint8_t segid, uint8_t m) { | |||
|     _segment_runtimes[segid].reset(); | ||||
|     _segments[segid].mode = m; | ||||
|   } | ||||
| 
 | ||||
|   for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) | ||||
|   { | ||||
|     if (modeUsesLock(_segments[i].mode)) anyUseLock = true; | ||||
|   } | ||||
|   if (anyUsedLock && !anyUseLock) unlockAll(); | ||||
|   _modeUsesLock = anyUseLock; | ||||
| } | ||||
| 
 | ||||
| uint8_t WS2812FX::getModeCount() | ||||
|  | @ -457,13 +440,9 @@ uint32_t WS2812FX::getLastShow(void) { | |||
| void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t length, uint8_t group, uint8_t spacing) { | ||||
|   if (n >= MAX_NUM_SEGMENTS) return; | ||||
|   Segment& seg = _segments[n]; | ||||
| 
 | ||||
|   if (seg.start == start && seg.rawLength == length && seg.group == group && seg.spacing == spacing) return; | ||||
|   if (seg.isActive() && modeUsesLock(seg.mode)) | ||||
|   { | ||||
|     _modeUsesLock = false; | ||||
|     unlockRange(seg.start, seg.stop); | ||||
|     _modeUsesLock = true; | ||||
|   } | ||||
| 
 | ||||
|   _segment_index = n; fill(0); //turn old segment range off
 | ||||
| 
 | ||||
|   seg.rawLength = min(_length - start, length); | ||||
|  | @ -482,7 +461,7 @@ void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t length, uint8_t gr | |||
| 
 | ||||
| void WS2812FX::resetSegments() { | ||||
|   memset(_segments, 0, sizeof(_segments)); | ||||
|   memset(_segment_runtimes, 0, sizeof(_segment_runtimes)); | ||||
|   //memset(_segment_runtimes, 0, sizeof(_segment_runtimes));
 | ||||
|   _segment_index = 0; | ||||
|   _segments[0].mode = DEFAULT_MODE; | ||||
|   _segments[0].colors[0] = DEFAULT_COLOR; | ||||
|  | @ -491,65 +470,32 @@ void WS2812FX::resetSegments() { | |||
|   _segments[0].stop = getUsableCount(); | ||||
|   _segments[0].rawLength = _length; | ||||
|   _segments[0].setOption(0, 1); //select
 | ||||
| 
 | ||||
|   _segments[0].group = _group; | ||||
|   _segments[0].spacing = _spacing; | ||||
| } | ||||
| 
 | ||||
| void WS2812FX::setIndividual(uint16_t i, uint32_t col) | ||||
| { | ||||
|   if (modeUsesLock(SEGMENT.mode)) return; | ||||
|   if (i >= 0 && i < _length) | ||||
|   for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++) | ||||
|   { | ||||
|     _locked[i] = false; | ||||
|     setPixelColor(i, col); | ||||
|     _locked[i] = true; | ||||
|     _segments[i].colors[0] = color_wheel(i*51); | ||||
|     _segment_runtimes[i].reset(); | ||||
|   } | ||||
|   _segment_runtimes[0].reset(); | ||||
| } | ||||
| 
 | ||||
| void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) | ||||
| { | ||||
|   if (i2 >= i) | ||||
|   { | ||||
|     for (uint16_t x = i; x <= i2; x++) setIndividual(x,col); | ||||
|     for (uint16_t x = i; x <= i2; x++) setPixelColor(x, col); | ||||
|   } else | ||||
|   { | ||||
|     for (uint16_t x = i2; x <= i; x++) setIndividual(x,col); | ||||
|     for (uint16_t x = i2; x <= i; x++) setPixelColor(x, col); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void WS2812FX::lock(uint16_t i) | ||||
| void WS2812FX::setShowCallback(show_callback cb) | ||||
| { | ||||
|   if (_modeUsesLock) return; | ||||
|   if (i < _length) _locked[i] = true; | ||||
| } | ||||
| 
 | ||||
| void WS2812FX::lockRange(uint16_t i, uint16_t i2) | ||||
| { | ||||
|   if (_modeUsesLock) return; | ||||
|   for (uint16_t x = i; x < i2; x++) | ||||
|   { | ||||
|     if (x < _length) _locked[i] = true; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void WS2812FX::unlock(uint16_t i) | ||||
| { | ||||
|   if (_modeUsesLock) return; | ||||
|   if (i < _length) _locked[i] = false; | ||||
| } | ||||
| 
 | ||||
| void WS2812FX::unlockRange(uint16_t i, uint16_t i2) | ||||
| { | ||||
|   if (_modeUsesLock) return; | ||||
|   for (uint16_t x = i; x < i2; x++) | ||||
|   { | ||||
|     if (x < _length) _locked[x] = false; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void WS2812FX::unlockAll() | ||||
| { | ||||
|   for (int i=0; i < _length; i++) _locked[i] = false; | ||||
|   _callback = cb; | ||||
| } | ||||
| 
 | ||||
| void WS2812FX::setTransitionMode(bool t) | ||||
|  | @ -723,7 +669,8 @@ void WS2812FX::handle_palette(void) | |||
|   _segment_index_palette_last = _segment_index; | ||||
| 
 | ||||
|   byte paletteIndex = SEGMENT.palette; | ||||
|   if ((SEGMENT.mode >= FX_MODE_METEOR) && SEGMENT.palette == 0) paletteIndex = 4; | ||||
|   if (SEGMENT.mode == FX_MODE_GLITTER && paletteIndex == 0) paletteIndex = 11; | ||||
|   if (SEGMENT.mode >= FX_MODE_METEOR && paletteIndex == 0) paletteIndex = 4; | ||||
|    | ||||
|   switch (paletteIndex) | ||||
|   { | ||||
|  | @ -737,6 +684,7 @@ void WS2812FX::handle_palette(void) | |||
|         case FX_MODE_NOISE16_2  : targetPalette = gGradientPalettes[30]; break;//Blue cyan yellow
 | ||||
|         case FX_MODE_NOISE16_3  : targetPalette = gGradientPalettes[22]; break;//heat palette
 | ||||
|         case FX_MODE_NOISE16_4  : targetPalette = gGradientPalettes[13]; break;//landscape 33
 | ||||
|         //case FX_MODE_GLITTER    : targetPalette = RainbowColors_p;       break;
 | ||||
|          | ||||
|         default: targetPalette = PartyColors_p; break;//palette, bpm
 | ||||
|       } | ||||
|  | @ -775,7 +723,8 @@ void WS2812FX::handle_palette(void) | |||
|     case 5: {//based on primary + secondary
 | ||||
|       CRGB prim = col_to_crgb(SEGCOLOR(0)); | ||||
|       CRGB sec  = col_to_crgb(SEGCOLOR(1)); | ||||
|       targetPalette = CRGBPalette16(sec,prim,CRGB::White); break;} | ||||
|       CRGB ter  = col_to_crgb(SEGCOLOR(2)); | ||||
|       targetPalette = CRGBPalette16(ter,sec,prim); break;} | ||||
|     case 6: //Party colors
 | ||||
|       targetPalette = PartyColors_p; break; | ||||
|     case 7: //Cloud colors
 | ||||
|  | @ -867,3 +816,5 @@ uint32_t WS2812FX::gamma32(uint32_t color) | |||
|   b = gammaT[b]; | ||||
|   return ((w << 24) | (r << 16) | (g << 8) | (b)); | ||||
| } | ||||
| 
 | ||||
| uint16_t WS2812FX::_usedSegmentData = 0; | ||||
|  |  | |||
|  | @ -5,12 +5,18 @@ | |||
| //PIN CONFIGURATION
 | ||||
| #define LEDPIN 2     //strip pin. Any for ESP32, gpio2 or 3 is recommended for ESP8266 (gpio2/3 are labeled D4/RX on NodeMCU and Wemos)
 | ||||
| //#define USE_APA102 // Uncomment for using APA102 LEDs.
 | ||||
| #define BTNPIN 0     //button pin. Needs to have pullup (gpio0 recommended)
 | ||||
| #define IR_PIN 4     //infrared pin (-1 to disable)
 | ||||
| #define RLYPIN 12    //pin for relay, will be set HIGH if LEDs are on (-1 to disable). Also usable for standby leds, triggers,...
 | ||||
| #define AUXPIN -1    //debug auxiliary output pin (-1 to disable)
 | ||||
| //#define WLED_USE_ANALOG_LEDS //Uncomment for using "dumb" PWM controlled LEDs (see pins below, default R: gpio5, G: 12, B: 15, W: 13)
 | ||||
| //#define WLED_USE_H801 //H801 controller. Please uncomment #define WLED_USE_ANALOG_LEDS as well
 | ||||
| //#define WLED_USE_5CH  //5 Channel H801 for cold and warm white
 | ||||
| 
 | ||||
| #define RLYMDE 1     //mode for relay, 0: LOW if LEDs are on 1: HIGH if LEDs are on
 | ||||
| #define BTNPIN  0  //button pin. Needs to have pullup (gpio0 recommended)
 | ||||
| #define IR_PIN  4  //infrared pin (-1 to disable)  MagicHome: 4, H801 Wifi: 0
 | ||||
| #define RLYPIN 12  //pin for relay, will be set HIGH if LEDs are on (-1 to disable). Also usable for standby leds, triggers,...
 | ||||
| #define AUXPIN -1  //debug auxiliary output pin (-1 to disable)
 | ||||
| 
 | ||||
| #define RLYMDE 1  //mode for relay, 0: LOW if LEDs are on 1: HIGH if LEDs are on
 | ||||
| 
 | ||||
| //END CONFIGURATION
 | ||||
| 
 | ||||
| #ifdef USE_APA102 | ||||
|  #define CLKPIN 0 | ||||
|  | @ -20,6 +26,27 @@ | |||
|  #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifdef WLED_USE_ANALOG_LEDS | ||||
|   //PWM pins - PINs 15,13,12,14 (W2 = 04)are used with H801 Wifi LED Controller
 | ||||
|   #ifdef WLED_USE_H801 | ||||
|     #define RPIN 15   //R pin for analog LED strip   
 | ||||
|     #define GPIN 13   //G pin for analog LED strip
 | ||||
|     #define BPIN 12   //B pin for analog LED strip
 | ||||
|     #define WPIN 14   //W pin for analog LED strip (W1: 14, W2: 04)
 | ||||
|     #define W2PIN 04  //W2 pin for analog LED strip
 | ||||
|     #undef BTNPIN | ||||
|     #undef IR_PIN | ||||
|     #define IR_PIN  0 //infrared pin (-1 to disable)  MagicHome: 4, H801 Wifi: 0
 | ||||
|   #else | ||||
|   //PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller
 | ||||
|     #define RPIN 5   //R pin for analog LED strip   
 | ||||
|     #define GPIN 12   //G pin for analog LED strip
 | ||||
|     #define BPIN 15   //B pin for analog LED strip
 | ||||
|     #define WPIN 13   //W pin for analog LED strip (W1: 14, W2: 04)
 | ||||
|   #endif | ||||
|   #undef RLYPIN | ||||
|   #define RLYPIN -1 //disable as pin 12 is used by analog LEDs
 | ||||
| #endif | ||||
| 
 | ||||
| //automatically uses the right driver method for each platform
 | ||||
| #ifdef ARDUINO_ARCH_ESP32 | ||||
|  | @ -103,41 +130,94 @@ public: | |||
|         _pGrbw = new NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>(countPixels, LEDPIN); | ||||
|       #endif | ||||
|         _pGrbw->Begin(); | ||||
|        | ||||
|       #ifdef WLED_USE_ANALOG_LEDS | ||||
|         pinMode(WPIN, OUTPUT);  | ||||
|         #ifdef WLED_USE_5CH_LEDS | ||||
|           pinMode(W2PIN, OUTPUT); | ||||
|         #endif | ||||
|       #endif | ||||
|          | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
|     #ifdef WLED_USE_ANALOG_LEDS    | ||||
|       //init PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller
 | ||||
|       pinMode(RPIN, OUTPUT); | ||||
|       pinMode(GPIN, OUTPUT); | ||||
|       pinMode(BPIN, OUTPUT);    | ||||
|       analogWriteRange(255);  //same range as one RGB channel
 | ||||
|       analogWriteFreq(880);   //PWM frequency proven as good for LEDs
 | ||||
|     #endif | ||||
|   } | ||||
| 
 | ||||
| #ifdef WLED_USE_ANALOG_LEDS       | ||||
|     void SetRgbwPwm(uint8_t r, uint8_t g, uint8_t b, uint8_t w, uint8_t w2=0) | ||||
|     { | ||||
|       analogWrite(RPIN, r); | ||||
|       analogWrite(GPIN, g); | ||||
|       analogWrite(BPIN, b); | ||||
|       switch (_type) { | ||||
|         case NeoPixelType_Grb:                                                  break; | ||||
|         #ifdef WLED_USE_5CH_LEDS | ||||
|           case NeoPixelType_Grbw: analogWrite(WPIN, w); analogWrite(W2PIN, w2); break; | ||||
|         #else | ||||
|           case NeoPixelType_Grbw: analogWrite(WPIN, w);                         break; | ||||
|         #endif | ||||
|       } | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|   void Show() | ||||
|   { | ||||
|     byte b; | ||||
|     switch (_type) | ||||
|     { | ||||
|       case NeoPixelType_Grb:  _pGrb->Show();   break; | ||||
|       case NeoPixelType_Grbw: _pGrbw->Show();  break; | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   bool CanShow() const | ||||
|   { | ||||
|     switch (_type) { | ||||
|       case NeoPixelType_Grb:  _pGrb->CanShow();  break; | ||||
|       case NeoPixelType_Grbw: _pGrbw->CanShow(); break; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   void SetPixelColor(uint16_t indexPixel, RgbColor color) | ||||
|   { | ||||
|     switch (_type) { | ||||
|       case NeoPixelType_Grb: _pGrb->SetPixelColor(indexPixel, color);   break; | ||||
|       case NeoPixelType_Grbw:_pGrbw->SetPixelColor(indexPixel, color);  break; | ||||
|       case NeoPixelType_Grb:  _pGrb->Show();  break; | ||||
|       case NeoPixelType_Grbw: _pGrbw->Show(); break; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   void SetPixelColor(uint16_t indexPixel, RgbwColor color) | ||||
|   { | ||||
|     switch (_type) { | ||||
|       case NeoPixelType_Grb:  _pGrb->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B));   break; | ||||
|       case NeoPixelType_Grbw: _pGrbw->SetPixelColor(indexPixel, color);   break; | ||||
|       case NeoPixelType_Grb: { | ||||
|         _pGrb->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B)); | ||||
|         #ifdef WLED_USE_ANALOG_LEDS | ||||
|           if (indexPixel != 0) return; //set analog LEDs from first pixel
 | ||||
|           byte b = _pGrb->GetBrightness(); | ||||
|           SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, 0); | ||||
|         #endif | ||||
|       } | ||||
|       break; | ||||
|       case NeoPixelType_Grbw: { | ||||
|         _pGrbw->SetPixelColor(indexPixel, color); | ||||
|         #ifdef WLED_USE_ANALOG_LEDS       | ||||
|           if (indexPixel != 0) return; //set analog LEDs from first pixel
 | ||||
|           byte b = _pGrbw->GetBrightness(); | ||||
|           // check color values for Warm / Cold white mix (for RGBW)  // EsplanexaDevice.cpp
 | ||||
|           #ifdef WLED_USE_5CH_LEDS | ||||
|             if        (color.R == 255 & color.G == 255 && color.B == 255 && color.W == 255) {   | ||||
|               SetRgbwPwm(0, 0, 0,                  0, color.W * b / 255); | ||||
|             } else if (color.R == 127 & color.G == 127 && color.B == 127 && color.W == 255) {   | ||||
|               SetRgbwPwm(0, 0, 0, color.W * b / 512, colorW.W * b / 255); | ||||
|             } else if (color.R ==   0 & color.G ==   0 && color.B ==   0 && color.W == 255) {   | ||||
|               SetRgbwPwm(0, 0, 0, color.W * b / 255,                  0); | ||||
|             } else if (color.R == 130 & color.G ==  90 && color.B ==   0 && color.W == 255) {   | ||||
|               SetRgbwPwm(0, 0, 0, color.W * b / 255, color.W * b / 512); | ||||
|             } else if (color.R == 255 & color.G == 153 && color.B ==   0 && color.W == 255) {   | ||||
|               SetRgbwPwm(0, 0, 0, color.W * b / 255,                  0); | ||||
|             } else {  // not only white colors
 | ||||
|               SetRgbwPwm(color.R * b / 255, colorW.G * b / 255, colorW.B * b / 255, color.W * b / 255); | ||||
|             } | ||||
|           #else | ||||
|             SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255); | ||||
|           #endif          | ||||
|         #endif | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
|      | ||||
|   } | ||||
| 
 | ||||
|   void SetBrightness(byte b) | ||||
|  | @ -148,15 +228,6 @@ public: | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   RgbColor GetPixelColor(uint16_t indexPixel) const | ||||
|   { | ||||
|     switch (_type) { | ||||
|       case NeoPixelType_Grb:  return _pGrb->GetPixelColor(indexPixel);     break; | ||||
|       case NeoPixelType_Grbw: /*doesn't support it so we don't return it*/ break; | ||||
|     } | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   // NOTE:  Due to feature differences, some support RGBW but the method name
 | ||||
|   // here needs to be unique, thus GetPixeColorRgbw
 | ||||
|   RgbwColor GetPixelColorRgbw(uint16_t indexPixel) const | ||||
|  | @ -168,21 +239,6 @@ public: | |||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   void ClearTo(RgbColor color) | ||||
|   { | ||||
|     switch (_type) { | ||||
|       case NeoPixelType_Grb: _pGrb->ClearTo(color);   break; | ||||
|       case NeoPixelType_Grbw:_pGrbw->ClearTo(color);  break; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   void ClearTo(RgbwColor color) | ||||
|   { | ||||
|     switch (_type) { | ||||
|       case NeoPixelType_Grb:    break; | ||||
|       case NeoPixelType_Grbw:_pGrbw->ClearTo(color);  break; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   NeoPixelType _type; | ||||
|  |  | |||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -23,16 +23,19 @@ | |||
|   <script> | ||||
|     update(); | ||||
|      | ||||
|     var tmout = null; | ||||
|     function update() | ||||
|     { | ||||
|       if (document.hidden) { | ||||
|         setTimeout(update, 250); | ||||
|         clearTimeout(tmout); | ||||
|         tmout = setTimeout(update, 250); | ||||
|         return; | ||||
|       } | ||||
|       fetch('/json/live') | ||||
|       .then(res => { | ||||
|         if (!res.ok) { | ||||
|           setTimeout(update, 2500); | ||||
|           clearTimeout(tmout); | ||||
|           tmout = setTimeout(update, 2500); | ||||
|         } | ||||
|         return res.json(); | ||||
|       }) | ||||
|  | @ -47,10 +50,12 @@ | |||
|         } | ||||
|         str += ")"; | ||||
|         document.getElementById("canv").style.background = str; | ||||
|         setTimeout(update, 40); | ||||
|         clearTimeout(tmout); | ||||
|         tmout = setTimeout(update, 40); | ||||
|       }) | ||||
|       .catch(function (error) { | ||||
|         setTimeout(update, 2500); | ||||
|         clearTimeout(tmout); | ||||
|         tmout = setTimeout(update, 2500); | ||||
|       }) | ||||
| 
 | ||||
|     } | ||||
|  |  | |||
|  | @ -88,7 +88,7 @@ | |||
| 		<button type="button" onclick="U()">Manual OTA Update</button><br> | ||||
| 		Enable ArduinoOTA: <input type="checkbox" name="AO"><br> | ||||
| 		<h3>About</h3> | ||||
| 		<a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.8.4<br><br> | ||||
| 		<a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.9.0<br><br> | ||||
| 		<a href="https://github.com/Aircoookie/WLED/wiki/Contributors-&-About" target="_blank">Contributors, dependencies and special thanks</a><br> | ||||
| 		A huge thank you to everyone who helped me create WLED!<br><br> | ||||
| 		(c) 2016-2019 Christian Schwinne <br> | ||||
|  |  | |||
|  | @ -103,6 +103,30 @@ | |||
| 		Device Auth token: <input name="BK" maxlength="33"><br> | ||||
| 		<i>Clear the token field to disable. </i><a href="https://github.com/Aircoookie/WLED/wiki/Blynk" target="_blank">Setup info</a> | ||||
| 		<h3>MQTT</h3> | ||||
|     Enable MQTT: <input type="checkbox" name="MQ"><br> | ||||
| 		Broker: <input name="MS" maxlength="32"><br> | ||||
| 	唉敳湲浡㩥㰠湩異⁴慮敭∽免呔单剅•慭汸湥瑧㵨㌢∲㰾牢ਾऀऀ慐獳潷摲›椼灮瑵琠灹㵥瀢獡睳牯≤椠灮瑵渠浡㵥䴢呑偔十≓洠硡敬杮桴∽㈳㸢戼㹲 | ||||
| 	䌉楬湥⁴䑉›椼灮瑵渠浡㵥䴢呑䍔䑉•慭汸湥瑧㵨㌢∲㰾牢ਾऀऀ䐀攀瘀椀挀攀 吀漀瀀椀挀㨀 㰀椀渀瀀甀琀 渀愀洀攀㴀∀䴀䐀∀ 洀愀砀氀攀渀最琀栀㴀∀㌀㈀∀㸀㰀戀爀㸀ഀऀऀ䜀爀漀甀瀀 吀漀瀀椀挀㨀 㰀椀渀瀀甀琀 渀愀洀攀㴀∀䴀䜀∀ 洀愀砀氀攀渀最琀栀㴀∀㌀㈀∀㸀㰀戀爀㸀ഀऀऀ㰀愀 栀爀攀昀㴀∀栀琀琀瀀猀㨀⼀⼀最椀琀栀甀戀⸀挀漀洀⼀䄀椀爀挀漀漀漀欀椀攀⼀圀䰀䔀䐀⼀眀椀欀椀⼀䴀儀吀吀∀ 琀愀爀最攀琀㴀∀开戀氀愀渀欀∀㸀䴀儀吀吀 椀渀昀漀㰀⼀愀㸀ഀऀऀ㰀栀㌀㸀倀栀椀氀椀瀀猀 䠀甀攀㰀⼀栀㌀㸀ഀऀऀ㰀椀㸀夀漀甀 挀愀渀 昀椀渀搀 琀栀攀 戀爀椀搀最攀 䤀倀 愀渀搀 琀栀攀 氀椀最栀琀 渀甀洀戀攀爀 椀渀 琀栀攀 ✀䄀戀漀甀琀✀ 猀攀挀琀椀漀渀 漀昀 琀栀攀 栀甀攀 愀瀀瀀⸀㰀⼀椀㸀㰀戀爀㸀ഀऀऀ倀漀氀氀 䠀甀攀 氀椀最栀琀 㰀椀渀瀀甀琀 渀愀洀攀㴀∀䠀䰀∀ 琀礀瀀攀㴀∀渀甀洀戀攀爀∀ 洀椀渀㴀∀∀ 洀愀砀㴀∀㤀㤀∀ 爀攀焀甀椀爀攀搀㸀 攀瘀攀爀礀 㰀椀渀瀀甀琀 渀愀洀攀㴀∀䠀䤀∀ 琀礀瀀攀㴀∀渀甀洀戀攀爀∀ 洀椀渀㴀∀  ∀ 洀愀砀㴀∀㘀㔀   ∀ 爀攀焀甀椀爀攀搀㸀 洀猀㨀 㰀椀渀瀀甀琀 琀礀瀀攀㴀∀挀栀攀挀欀戀漀砀∀ 渀愀洀攀㴀∀䠀倀∀㸀㰀戀爀㸀ഀऀऀ吀栀攀渀Ⰰ 爀攀挀攀椀瘀攀 㰀椀渀瀀甀琀 琀礀瀀攀㴀∀挀栀攀挀欀戀漀砀∀ 渀愀洀攀㴀∀䠀伀∀㸀 伀渀⼀伀昀昀Ⰰ 㰀椀渀瀀甀琀 琀礀瀀攀㴀∀挀栀攀挀欀戀漀砀∀ 渀愀洀攀㴀∀䠀䈀∀㸀 䈀爀椀最栀琀渀攀猀猀Ⰰ 愀渀搀 㰀椀渀瀀甀琀 琀礀瀀攀㴀∀挀栀攀挀欀戀漀砀∀ 渀愀洀攀㴀∀䠀䌀∀㸀 䌀漀氀漀爀㰀戀爀㸀ഀऀऀ䠀甀攀 䈀爀椀搀最攀 䤀倀㨀㰀戀爀㸀ഀऀऀ㰀椀渀瀀甀琀 渀愀洀攀㴀∀䠀 ∀ 琀礀瀀攀㴀∀渀甀洀戀攀爀∀ 洀椀渀㴀∀ ∀ 洀愀砀㴀∀㈀㔀㔀∀ 爀攀焀甀椀爀攀搀㸀 ⸀ഀऀऀ㰀椀渀瀀甀琀 渀愀洀攀㴀∀䠀∀ 琀礀瀀攀㴀∀渀甀洀戀攀爀∀ 洀椀渀㴀∀ ∀ 洀愀砀㴀∀㈀㔀㔀∀ 爀攀焀甀椀爀攀搀㸀 ⸀ഀऀऀ㰀椀渀瀀甀琀 渀愀洀攀㴀∀䠀㈀∀ 琀礀瀀攀㴀∀渀甀洀戀攀爀∀ 洀椀渀㴀∀ ∀ 洀愀砀㴀∀㈀㔀㔀∀ 爀攀焀甀椀爀攀搀㸀 ⸀ഀऀऀ㰀椀渀瀀甀琀 渀愀洀攀㴀∀䠀㌀∀ 琀礀瀀攀㴀∀渀甀洀戀攀爀∀ 洀椀渀㴀∀ ∀ 洀愀砀㴀∀㈀㔀㔀∀ 爀攀焀甀椀爀攀搀㸀㰀戀爀㸀ഀऀऀ㰀戀㸀倀爀攀猀猀 琀栀攀 瀀甀猀栀氀椀渀欀 戀甀琀琀漀渀 漀渀 琀栀攀 戀爀椀搀最攀Ⰰ 愀昀琀攀爀 琀栀愀琀 猀愀瘀攀 琀栀椀猀 瀀愀最攀℀㰀⼀戀㸀㰀戀爀㸀ഀऀऀ⠀眀栀攀渀 昀椀爀猀琀 挀漀渀渀攀挀琀椀渀最⤀㰀戀爀㸀ഀऀऀ㰀℀ⴀⴀ唀瀀搀愀琀攀 䠀甀攀 最爀漀甀瀀 㰀椀渀瀀甀琀 渀愀洀攀㴀∀䠀唀䔀䜀刀∀ 琀礀瀀攀㴀∀渀甀洀戀攀爀∀ 洀椀渀㴀∀ ∀ 洀愀砀㴀∀㤀㤀∀ 爀攀焀甀椀爀攀搀㸀 㰀戀爀㸀ഀऀऀ匀攀渀搀 㰀椀渀瀀甀琀 琀礀瀀攀㴀∀挀栀攀挀欀戀漀砀∀ 渀愀洀攀㴀∀䠀唀䔀䤀伀∀㸀 伀渀⼀伀昀昀Ⰰ 㰀椀渀瀀甀琀 琀礀瀀攀㴀∀挀栀攀挀欀戀漀砀∀ 渀愀洀攀㴀∀䠀唀䔀䈀刀∀㸀 䈀爀椀最栀琀渀攀猀猀Ⰰ 愀渀搀 㰀椀渀瀀甀琀 琀礀瀀攀㴀∀挀栀攀挀欀戀漀砀∀ 渀愀洀攀㴀∀䠀唀䔀䌀䰀∀㸀 䌀漀氀漀爀㰀戀爀㸀ⴀⴀ㸀ഀऀऀ㰀℀ⴀⴀ䄀昀琀攀爀 搀攀瘀椀挀攀 挀漀氀漀爀 甀瀀搀愀琀攀Ⰰ 椀最渀漀爀攀 䠀甀攀 甀瀀搀愀琀攀猀 昀漀爀 㰀椀渀瀀甀琀 渀愀洀攀㴀∀䠀唀䔀䰀䤀∀ 琀礀瀀攀㴀∀渀甀洀戀攀爀∀ 洀椀渀㴀∀ ∀ 洀愀砀㴀∀㈀㔀㔀∀ 爀攀焀甀椀爀攀搀㸀 洀椀渀甀琀攀猀㰀戀爀㸀ⴀⴀ㸀ഀऀऀ䠀甀攀 猀琀愀琀甀猀㨀 㰀猀瀀愀渀 挀氀愀猀猀㴀∀栀洀猀∀㸀 䤀渀琀攀爀渀愀氀 䔀匀倀 䔀爀爀漀爀℀ 㰀⼀猀瀀愀渀㸀㰀栀爀㸀ഀऀऀ㰀戀甀琀琀漀渀 琀礀瀀攀㴀∀戀甀琀琀漀渀∀ 漀渀挀氀椀挀欀㴀∀䈀⠀⤀∀㸀䈀愀挀欀㰀⼀戀甀琀琀漀渀㸀㰀戀甀琀琀漀渀 琀礀瀀攀㴀∀猀甀戀洀椀琀∀㸀匀愀瘀攀㰀⼀戀甀琀琀漀渀㸀ഀऀ㰀⼀昀漀爀洀㸀ഀ㰀⼀戀漀搀礀㸀ഀ㰀⼀栀琀洀氀㸀 | ||||
| 		Username: <input name="MQTTUSER" maxlength="32"><br> | ||||
| 		Password: <input type="password" input name="MQTTPASS" maxlength="32"><br> | ||||
| 		Client ID: <input name="MQTTCID" maxlength="32"><br> | ||||
| 		Device Topic: <input name="MD" maxlength="32"><br> | ||||
| 		Group Topic: <input name="MG" maxlength="32"><br> | ||||
| 		<a href="https://github.com/Aircoookie/WLED/wiki/MQTT" target="_blank">MQTT info</a> | ||||
| 		<h3>Philips Hue</h3> | ||||
| 		<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br> | ||||
| 		Poll Hue light <input name="HL" type="number" min="1" max="99" required> every <input name="HI" type="number" min="100" max="65000" required> ms: <input type="checkbox" name="HP"><br> | ||||
| 		Then, receive <input type="checkbox" name="HO"> On/Off, <input type="checkbox" name="HB"> Brightness, and <input type="checkbox" name="HC"> Color<br> | ||||
| 		Hue Bridge IP:<br> | ||||
| 		<input name="H0" type="number" min="0" max="255" required> . | ||||
| 		<input name="H1" type="number" min="0" max="255" required> . | ||||
| 		<input name="H2" type="number" min="0" max="255" required> . | ||||
| 		<input name="H3" type="number" min="0" max="255" required><br> | ||||
| 		<b>Press the pushlink button on the bridge, after that save this page!</b><br> | ||||
| 		(when first connecting)<br> | ||||
| 		<!--Update Hue group <input name="HUEGR" type="number" min="0" max="99" required> <br> | ||||
| 		Send <input type="checkbox" name="HUEIO"> On/Off, <input type="checkbox" name="HUEBR"> Brightness, and <input type="checkbox" name="HUECL"> Color<br>--> | ||||
| 		<!--After device color update, ignore Hue updates for <input name="HUELI" type="number" min="0" max="255" required> minutes<br>--> | ||||
| 		Hue status: <span class="hms"> Internal ESP Error! </span><hr> | ||||
| 		<button type="button" onclick="B()">Back</button><button type="submit">Save</button> | ||||
| 	</form> | ||||
| </body> | ||||
| </html> | ||||
|  | @ -98,7 +98,8 @@ | |||
| 		<div class="helpB"><button type="button" onclick="H()">?</button></div> | ||||
| 		<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr> | ||||
| 		<h2>Web Setup</h2> | ||||
| 		Server description: <input name="DS" maxlength="32"><br><br> | ||||
| 		Server description: <input name="DS" maxlength="32"><br> | ||||
|     Sync button toggles both send and receive: <input type="checkbox" name="ST"><br><br> | ||||
| 		<hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button> | ||||
| 	</form> | ||||
| </body> | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ const char PAGE_msg[] PROGMEM = R"=====(<!DOCTYPE html> | |||
| const char PAGE_update[] PROGMEM = R"=====(<!DOCTYPE html> | ||||
| <html><head><meta content='width=device-width' name='viewport'><title>WLED Update</title><script>function B(){window.history.back()}</script> | ||||
| <style>.bt{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}input[type=file]{font-size:16px}body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%}</style></head> | ||||
| <body><h2>WLED Software Update</h2>Installed version: 0.9.0-dev<br>Download the latest binary: <a href="https://github.com/Aircoookie/WLED/releases"><img src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square"></a><br><form method='POST' action='/update' enctype='multipart/form-data'><input type='file' class="bt" name='update' required><br><input type='submit' class="bt" value='Update!'></form><button type="button" class="bt" onclick="B()">Back</button></body></html>)====="; | ||||
| <body><h2>WLED Software Update</h2>Installed version: 0.9.0-b1<br>Download the latest binary: <a href="https://github.com/Aircoookie/WLED/releases"><img src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square"></a><br><form method='POST' action='/update' enctype='multipart/form-data'><input type='file' class="bt" name='update' required><br><input type='submit' class="bt" value='Update!'></form><button type="button" class="bt" onclick="B()">Back</button></body></html>)====="; | ||||
| 
 | ||||
| 
 | ||||
| //new user welcome page
 | ||||
|  | @ -36,14 +36,50 @@ const char PAGE_liveview[] PROGMEM = R"=====(<!DOCTYPE html> | |||
| <meta charset=utf-8> | ||||
| <meta name=theme-color content=#222222> | ||||
| <title>WLED Live Preview</title> | ||||
| <style>body{margin:0}#canv{background:black;filter:brightness(175%);width:100%;height:100%;position:absolute}</style> | ||||
| </head> | ||||
| <body><div id=canv /> | ||||
| <script>update();function update() | ||||
| {if(document.hidden){setTimeout(update,250);return;} | ||||
| fetch('/json/live').then(res=>{if(!res.ok){setTimeout(update,2500);} | ||||
| return res.json();}).then(json=>{var str="linear-gradient(90deg,";var len=json.leds.length;for(i=0;i<len;i++){var leddata=json.leds[i];if(leddata.length>6)leddata=leddata.substring(2);str+="#"+leddata;if(i<len-1)str+=","} | ||||
| str+=")";document.getElementById("canv").style.background=str;setTimeout(update,40);}).catch(function(error){setTimeout(update,2500);})}</script> | ||||
| <style> | ||||
| body {margin: 0;} | ||||
| #canv {background: black;filter: brightness(175%);width: 100%;height: 100%;position: absolute;} | ||||
| </style></head> | ||||
| <body> | ||||
| <div id="canv" /> | ||||
| <script> | ||||
| update(); | ||||
| var tmout = null; | ||||
| function update() | ||||
| { | ||||
| if (document.hidden) { | ||||
| clearTimeout(tmout); | ||||
| tmout = setTimeout(update, 250); | ||||
| return; | ||||
| } | ||||
| fetch('/json/live') | ||||
| .then(res => { | ||||
| if (!res.ok) { | ||||
| clearTimeout(tmout); | ||||
| tmout = setTimeout(update, 2500); | ||||
| } | ||||
| return res.json(); | ||||
| }) | ||||
| .then(json => { | ||||
| var str = "linear-gradient(90deg,"; | ||||
| var len = json.leds.length; | ||||
| for (i = 0; i < len; i++) { | ||||
| var leddata = json.leds[i]; | ||||
| if (leddata.length > 6) leddata = leddata.substring(2); | ||||
| str += "#" + leddata; | ||||
| if (i < len -1) str += "," | ||||
| } | ||||
| str += ")"; | ||||
| document.getElementById("canv").style.background = str; | ||||
| clearTimeout(tmout); | ||||
| tmout = setTimeout(update, 40); | ||||
| }) | ||||
| .catch(function (error) { | ||||
| clearTimeout(tmout); | ||||
| tmout = setTimeout(update, 2500); | ||||
| }) | ||||
| } | ||||
| </script> | ||||
| </body></html>)====="; | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -121,7 +121,7 @@ Color order: | |||
| <select name=CO> | ||||
| <option value=0>GRB</option> | ||||
| <option value=1>RGB</option> | ||||
| <option value=2 disabled>BRG</option> | ||||
| <option value=2>BRG</option> | ||||
| <option value=3>RBG</option> | ||||
| </select> | ||||
| <h3>Defaults</h3> | ||||
|  | @ -168,7 +168,8 @@ function gId(s){return document.getElementById(s);}function S(){GetV();Ct();}fun | |||
| <div class="helpB"><button type="button" onclick="H()">?</button></div> | ||||
| <button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr> | ||||
| <h2>Web Setup</h2> | ||||
| Server description: <input name="DS" maxlength="32"><br><br> | ||||
| Server description: <input name="DS" maxlength="32"><br> | ||||
| Sync button toggles both send and receive: <input type="checkbox" name="ST"><br><br> | ||||
| <hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button> | ||||
| </form> | ||||
| </body> | ||||
|  | @ -219,6 +220,7 @@ For best results, only use one of these services at a time.<br> | |||
| Device Auth token: <input name="BK" maxlength="33"><br> | ||||
| <i>Clear the token field to disable. </i><a href="https://github.com/Aircoookie/WLED/wiki/Blynk" target="_blank">Setup info</a> | ||||
| <h3>MQTT</h3> | ||||
| Enable MQTT: <input type="checkbox" name="MQ"><br> | ||||
| Broker: <input name="MS" maxlength="32"> | ||||
| Port: <input name="MQPORT" type="number" min="1" max="65535" required><br> | ||||
| <b>The MQTT credentials are sent over an unsecured connection.<br> | ||||
|  | @ -280,6 +282,7 @@ Time zone: | |||
| <option value="12">NZST/NZDT</option> | ||||
| <option value="13">North Korea</option> | ||||
| <option value="14">IST (India)</option> | ||||
| <option value="15">CA-Saskatchewan</option> | ||||
| </select><br> | ||||
| UTC offset: <input name="UO" type="number" min="-65500" max="65500" required> seconds (max. 18 hours)<br> | ||||
| Current local time is <span class="times">unknown</span>. | ||||
|  | @ -288,7 +291,7 @@ Clock Overlay: | |||
| <select name="OL" onchange="Cs()"> | ||||
| <option value="0" id="cn" selected>None</option> | ||||
| <option value="1" id="ca">Analog Clock</option> | ||||
| <option value="2">Single Digit Clock</option> | ||||
| <option value="2" disabled>-</option> | ||||
| <option value="3" id="cc">Cronixie Clock</option> | ||||
| </select><br> | ||||
| <div id="coc"> | ||||
|  | @ -366,10 +369,10 @@ HTTP traffic is unencrypted. An attacker in the same network can intercept form | |||
| <button type="button" onclick="U()">Manual OTA Update</button><br> | ||||
| Enable ArduinoOTA: <input type="checkbox" name="AO"><br> | ||||
| <h3>About</h3> | ||||
| <a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.9.0-dev<br><br> | ||||
| <a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.9.0-b2<br><br> | ||||
| <a href="https://github.com/Aircoookie/WLED/wiki/Contributors-&-About" target="_blank">Contributors, dependencies and special thanks</a><br> | ||||
| A huge thank you to everyone who helped me create WLED!<br><br> | ||||
| (c) 2016-2019 Christian Schwinne <br> | ||||
| (c) 2016-2020 Christian Schwinne <br> | ||||
| <i>Licensed under the MIT license</i><br><br> | ||||
| Server message: <span class="msg"> Response error! </span><hr> | ||||
| <button type="button" onclick="B()">Back</button><button type="submit">Save & Reboot</button> | ||||
|  |  | |||
							
								
								
									
										2902
									
								
								wled00/html_ui.h
								
								
								
								
							
							
						
						
									
										2902
									
								
								wled00/html_ui.h
								
								
								
								
							
										
											
												Plik diff jest za duży
												Load Diff
											
										
									
								
							|  | @ -564,6 +564,14 @@ DEFINE_GRADIENT_PALETTE( Sakura_gp ) { | |||
|   130, 223, 45, 72, | ||||
|   195, 255, 82,103, | ||||
|   255, 223, 13, 17}; | ||||
| 
 | ||||
| DEFINE_GRADIENT_PALETTE( Aurora_gp ) { | ||||
|     0,   1,  5, 45, //deep blue
 | ||||
|    64,   0,200, 23, | ||||
|   128,   0,255,  0, //green
 | ||||
|   170,   0,243, 45, | ||||
|   200,   0,135,  7, | ||||
|   255,   1,  5, 45};//deep blue
 | ||||
|    | ||||
| 
 | ||||
| // Single array of defined cpt-city color palettes.
 | ||||
|  | @ -614,6 +622,7 @@ const TProgmemRGBGradientPalettePtr gGradientPalettes[] = { | |||
|   Orangery_gp,                  //47-34 Orangery
 | ||||
|   C9_gp,                        //48-35 C9
 | ||||
|   Sakura_gp,                    //49-36 Sakura
 | ||||
|   Aurora_gp,                    //50-37 Aurora
 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -110,8 +110,8 @@ uint32_t EspalexaDevice::getKelvin() | |||
| uint32_t EspalexaDevice::getRGB() | ||||
| { | ||||
|   if (_rgb != 0) return _rgb; //color has not changed
 | ||||
|   uint8_t rgb[3]; | ||||
|   float r, g, b; | ||||
|   byte rgb[4]{0, 0, 0, 0};  | ||||
|   float r, g, b, w; | ||||
|    | ||||
|   if (_mode == EspalexaColorMode::none) return 0; | ||||
| 
 | ||||
|  | @ -122,6 +122,15 @@ uint32_t EspalexaDevice::getRGB() | |||
|     float temp = 10000/ _ct; //kelvins = 1,000,000/mired (and that /100)
 | ||||
|     float r, g, b; | ||||
| 
 | ||||
| // Cold white to warm white receiving from Alexa: _ct = 199, 234, 284, 350, 383 (from cold white to warm white)
 | ||||
|     switch (_ct) { | ||||
|       case 199: rgb[0]=255,rgb[1]=255,rgb[2]=255;rgb[3]=255;break; | ||||
|       case 234: rgb[0]=127,rgb[1]=127,rgb[2]=127;rgb[3]=255;break; | ||||
|       case 284: rgb[0]=0,rgb[1]=0,rgb[2]=0;rgb[3]=255;break; | ||||
|       case 350: rgb[0]=130,rgb[1]=90,rgb[2]=0;rgb[3]=255;break; | ||||
|       case 383: rgb[0]=255,rgb[1]=153,rgb[2]=0;rgb[3]=255;break; | ||||
|       default: { | ||||
|   | ||||
|     if( temp <= 66 ){  | ||||
|       r = 255;  | ||||
|       g = temp; | ||||
|  | @ -143,6 +152,9 @@ uint32_t EspalexaDevice::getRGB() | |||
|     rgb[0] = (byte)constrain(r,0.1,255.1); | ||||
|     rgb[1] = (byte)constrain(g,0.1,255.1); | ||||
|     rgb[2] = (byte)constrain(b,0.1,255.1); | ||||
| 
 | ||||
|     } | ||||
|     } | ||||
|   } else if (_mode == EspalexaColorMode::hs) | ||||
|   { | ||||
|     float h = ((float)_hue)/65535.0; | ||||
|  | @ -216,7 +228,7 @@ uint32_t EspalexaDevice::getRGB() | |||
|     rgb[1] = 255.0*g; | ||||
|     rgb[2] = 255.0*b; | ||||
|   } | ||||
|   _rgb = ((rgb[0] << 16) | (rgb[1] << 8) | (rgb[2])); | ||||
|   _rgb = ((rgb[3] << 24) | (rgb[0] << 16) | (rgb[1] << 8) | (rgb[2]));  //white value is only >0 if Alexa did provide a CT value, RGB colors will not be touched.
 | ||||
|   return _rgb; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ | |||
| #include "ArduinoJson-v6.h" | ||||
| #include <Print.h> | ||||
| 
 | ||||
| #define DYNAMYC_JSON_DOCUMENT_SIZE 8192 | ||||
| #define DYNAMIC_JSON_DOCUMENT_SIZE 8192 | ||||
| 
 | ||||
| constexpr const char* JSON_MIMETYPE = "application/json"; | ||||
| 
 | ||||
|  | @ -60,7 +60,7 @@ class AsyncJsonResponse: public AsyncAbstractResponse { | |||
| 
 | ||||
|   public:     | ||||
| 
 | ||||
|     AsyncJsonResponse(size_t maxJsonBufferSize = DYNAMYC_JSON_DOCUMENT_SIZE, bool isArray=false) : _jsonBuffer(maxJsonBufferSize), _isValid{false} { | ||||
|     AsyncJsonResponse(size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE, bool isArray=false) : _jsonBuffer(maxJsonBufferSize), _isValid{false} { | ||||
|       _code = 200; | ||||
|       _contentType = JSON_MIMETYPE; | ||||
|       if(isArray) | ||||
|  | @ -90,7 +90,7 @@ class AsyncJsonResponse: public AsyncAbstractResponse { | |||
|     } | ||||
| }; | ||||
| 
 | ||||
| typedef std::function<void(AsyncWebServerRequest *request, JsonObject json)> ArJsonRequestHandlerFunction; | ||||
| typedef std::function<void(AsyncWebServerRequest *request)> ArJsonRequestHandlerFunction; | ||||
| 
 | ||||
| class AsyncCallbackJsonWebHandler: public AsyncWebHandler { | ||||
| private: | ||||
|  | @ -103,7 +103,7 @@ protected: | |||
|   int _maxContentLength; | ||||
| public: | ||||
| 
 | ||||
|   AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize=DYNAMYC_JSON_DOCUMENT_SIZE)  | ||||
|   AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize=DYNAMIC_JSON_DOCUMENT_SIZE)  | ||||
|   : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), maxJsonBufferSize(maxJsonBufferSize), _maxContentLength(16384) {} | ||||
|    | ||||
|   void setMethod(WebRequestMethodComposite method){ _method = method; } | ||||
|  | @ -127,15 +127,8 @@ public: | |||
|   virtual void handleRequest(AsyncWebServerRequest *request) override final { | ||||
|     if(_onRequest) { | ||||
|       if (request->_tempObject != NULL) { | ||||
| 
 | ||||
|         DynamicJsonDocument jsonBuffer(this->maxJsonBufferSize); | ||||
|         DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject)); | ||||
|         if(!error) { | ||||
|           JsonObject json = jsonBuffer.as<JsonObject>(); | ||||
| 
 | ||||
|           _onRequest(request, json); | ||||
|           return; | ||||
|         } | ||||
|         _onRequest(request); | ||||
|         return; | ||||
|       } | ||||
|       request->send(_contentLength > _maxContentLength ? 413 : 400); | ||||
|     } else { | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
|  */ | ||||
| /*
 | ||||
|  * @title WLED project sketch | ||||
|  * @version 0.9.0-dev | ||||
|  * @version 0.9.0-b2 | ||||
|  * @author Christian Schwinne | ||||
|  */ | ||||
| 
 | ||||
|  | @ -14,15 +14,16 @@ | |||
| //Uncomment some of the following lines to disable features to compile for ESP8266-01 (max flash size 434kB):
 | ||||
| 
 | ||||
| //You are required to disable over-the-air updates:
 | ||||
| //#define WLED_DISABLE_OTA
 | ||||
| //#define WLED_DISABLE_OTA         //saves 14kb
 | ||||
| 
 | ||||
| //You need to choose some of these features to disable:
 | ||||
| //#define WLED_DISABLE_ALEXA
 | ||||
| //#define WLED_DISABLE_BLYNK
 | ||||
| //#define WLED_DISABLE_CRONIXIE
 | ||||
| //#define WLED_DISABLE_HUESYNC
 | ||||
| //#define WLED_DISABLE_INFRARED    //there is no pin left for this on ESP8266-01
 | ||||
| #define WLED_ENABLE_ADALIGHT       //only saves about 500b
 | ||||
| //#define WLED_DISABLE_ALEXA       //saves 11kb
 | ||||
| //#define WLED_DISABLE_BLYNK       //saves 6kb
 | ||||
| //#define WLED_DISABLE_CRONIXIE    //saves 3kb
 | ||||
| //#define WLED_DISABLE_HUESYNC     //saves 4kb
 | ||||
| //#define WLED_DISABLE_INFRARED    //there is no pin left for this on ESP8266-01, saves 25kb (!)
 | ||||
| #define WLED_ENABLE_MQTT           //saves 12kb
 | ||||
| #define WLED_ENABLE_ADALIGHT       //saves 500b only
 | ||||
| 
 | ||||
| #define WLED_DISABLE_FILESYSTEM    //SPIFFS is not used by any WLED feature yet
 | ||||
| //#define WLED_ENABLE_FS_SERVING   //Enable sending html file from SPIFFS before serving progmem version
 | ||||
|  | @ -31,7 +32,6 @@ | |||
| //to toggle usb serial debug (un)comment the following line
 | ||||
| //#define WLED_DEBUG
 | ||||
| 
 | ||||
| 
 | ||||
| //library inclusions
 | ||||
| #include <Arduino.h> | ||||
| #ifdef ESP8266 | ||||
|  | @ -84,6 +84,7 @@ | |||
| #endif | ||||
| 
 | ||||
| #ifdef ARDUINO_ARCH_ESP32 | ||||
|   #undef WLED_USE_ANALOG_LEDS  // Solid RGBW not implemented for ESP32 yet
 | ||||
|  /*#ifndef WLED_DISABLE_INFRARED
 | ||||
|   #include <IRremote.h> | ||||
|  #endif*/ //there are issues with ESP32 infrared, so it is disabled for now
 | ||||
|  | @ -97,8 +98,8 @@ | |||
| 
 | ||||
| 
 | ||||
| //version code in format yymmddb (b = daily build)
 | ||||
| #define VERSION 1912051 | ||||
| char versionString[] = "0.9.0-dev"; | ||||
| #define VERSION 2001051 | ||||
| char versionString[] = "0.9.0-b2"; | ||||
| 
 | ||||
| 
 | ||||
| //AP and OTA default passwords (for maximum change them!)
 | ||||
|  | @ -147,7 +148,6 @@ bool fadeTransition = true;                   //enable crossfading color transit | |||
| bool enableSecTransition = true;              //also enable transition for secondary color
 | ||||
| uint16_t transitionDelay = 750;               //default crossfade duration in ms
 | ||||
| 
 | ||||
| //bool strip.reverseMode  = false;            //flip entire LED strip (reverses all effect directions) --> edit in WS2812FX.h
 | ||||
| bool skipFirstLed = false;                    //ignore first LED in strip (useful if you need the LED as signal repeater)
 | ||||
| uint8_t spacing = 0;                          //disables N LEDs between active nodes. (Useful for spacing out lights for more traditional christmas light look)
 | ||||
| uint8_t group = 1;                            //Group LEDs into one logical LED
 | ||||
|  | @ -156,6 +156,7 @@ byte briMultiplier =  100;                    //% of brightness to set (to limit | |||
| 
 | ||||
| //User Interface CONFIG
 | ||||
| char serverDescription[33] = "WLED";          //Name of module
 | ||||
| bool syncToggleReceive = false;               //UIs which only have a single button for sync should toggle send+receive if this is true, only send otherwise
 | ||||
| 
 | ||||
| 
 | ||||
| //Sync CONFIG
 | ||||
|  | @ -189,6 +190,7 @@ bool arlsForceMaxBri = false;                 //enable to force max brightness i | |||
| uint16_t e131Universe = 1;                    //settings for E1.31 (sACN) protocol
 | ||||
| bool e131Multicast = false; | ||||
| 
 | ||||
| bool mqttEnabled = false; | ||||
| char mqttDeviceTopic[33] = "";                //main MQTT topic (individual per device, default is wled/mac)
 | ||||
| char mqttGroupTopic[33] = "wled/all";         //second MQTT topic (for example to group devices)
 | ||||
| char mqttServer[33] = "";                     //both domains and IPs should work (no SSL)
 | ||||
|  | @ -329,11 +331,6 @@ byte overlayCurrent = overlayDefault; | |||
| byte overlaySpeed = 200; | ||||
| unsigned long overlayRefreshMs = 200; | ||||
| unsigned long overlayRefreshedTime; | ||||
| int overlayArr[6]; | ||||
| uint16_t overlayDur[6]; | ||||
| uint16_t overlayPauseDur[6]; | ||||
| int nixieClockI = -1; | ||||
| bool nixiePause = false; | ||||
| 
 | ||||
| //cronixie
 | ||||
| byte dP[]{0,0,0,0,0,0}; | ||||
|  | @ -428,6 +425,7 @@ AsyncMqttClient* mqtt = NULL; | |||
| void colorFromUint32(uint32_t,bool=false); | ||||
| void serveMessage(AsyncWebServerRequest*,uint16_t,String,String,byte); | ||||
| void handleE131Packet(e131_packet_t*, IPAddress); | ||||
| void handleOverlayDraw(); | ||||
| 
 | ||||
| #define E131_MAX_UNIVERSE_COUNT 9 | ||||
| 
 | ||||
|  | @ -483,7 +481,7 @@ void reset() | |||
| 
 | ||||
| 
 | ||||
| //append new c string to temp buffer efficiently
 | ||||
| bool oappend(char* txt) | ||||
| bool oappend(const char* txt) | ||||
| { | ||||
|   uint16_t len = strlen(txt); | ||||
|   if (olen + len >= OMAX) return false; //buffer full
 | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
| #define EEPSIZE 2560 | ||||
| 
 | ||||
| //eeprom Version code, enables default settings instead of 0 init on update
 | ||||
| #define EEPVER 13 | ||||
| #define EEPVER 14 | ||||
| //0 -> old version, default
 | ||||
| //1 -> 0.4p 1711272 and up
 | ||||
| //2 -> 0.4p 1711302 and up
 | ||||
|  | @ -20,7 +20,8 @@ | |||
| //10-> 0.8.2
 | ||||
| //11-> 0.8.5-dev #mqttauth @TimothyBrown
 | ||||
| //12-> 0.8.7-dev
 | ||||
| //13-> 0.9.0
 | ||||
| //13-> 0.9.0-dev
 | ||||
| //14-> 0.9.0-b1
 | ||||
| 
 | ||||
| void commit() | ||||
| { | ||||
|  | @ -152,7 +153,7 @@ void saveSettingsToEEPROM() | |||
|   EEPROM.write(394, abs(utcOffsetSecs) & 0xFF); | ||||
|   EEPROM.write(395, (abs(utcOffsetSecs) >> 8) & 0xFF); | ||||
|   EEPROM.write(396, (utcOffsetSecs<0)); //is negative
 | ||||
|   //397 was initLedsLast
 | ||||
|   EEPROM.write(397, syncToggleReceive); | ||||
|   EEPROM.write(398, (ledCount >> 8) & 0xFF); | ||||
|   EEPROM.write(399, !enableSecTransition); | ||||
| 
 | ||||
|  | @ -242,6 +243,7 @@ void saveSettingsToEEPROM() | |||
|     EEPROM.write(2290 + i, timerMacro[i]  ); | ||||
|   } | ||||
| 
 | ||||
|   EEPROM.write(2299, mqttEnabled); | ||||
|   writeStringToEEPROM(2300, mqttServer, 32); | ||||
|   writeStringToEEPROM(2333, mqttDeviceTopic, 32); | ||||
|   writeStringToEEPROM(2366, mqttGroupTopic, 32); | ||||
|  | @ -463,6 +465,14 @@ void loadSettingsFromEEPROM(bool first) | |||
|   { | ||||
|     readStringFromEEPROM(990, ntpServerName, 32); | ||||
|   } | ||||
|   if (lastEEPROMversion > 13) | ||||
|   { | ||||
|     mqttEnabled = EEPROM.read(2299); | ||||
|     syncToggleReceive = EEPROM.read(397); | ||||
|   } else { | ||||
|     mqttEnabled = true; | ||||
|     syncToggleReceive = false; | ||||
|   } | ||||
| 
 | ||||
|   receiveDirect = !EEPROM.read(2200); | ||||
|   notifyMacro = EEPROM.read(2201); | ||||
|  | @ -497,6 +507,7 @@ void loadSettingsFromEEPROM(bool first) | |||
|   //1024-2047 reserved
 | ||||
| 
 | ||||
|   readStringFromEEPROM(2220, blynkApiKey, 35); | ||||
|   if (strlen(blynkApiKey) < 25) blynkApiKey[0] = 0; | ||||
| 
 | ||||
|   //user MOD memory
 | ||||
|   //2944 - 3071 reserved
 | ||||
|  | @ -552,6 +563,7 @@ bool applyPreset(byte index, bool loadBri = true, bool loadCol = true, bool load | |||
|         col[j] = EEPROM.read(i+j+2); | ||||
|         colSec[j] = EEPROM.read(i+j+6); | ||||
|       } | ||||
|       strip.setColor(2, EEPROM.read(i+12), EEPROM.read(i+13), EEPROM.read(i+14), EEPROM.read(i+15)); //tertiary color
 | ||||
|     } | ||||
|     if (loadFX) | ||||
|     { | ||||
|  | @ -589,6 +601,12 @@ void savePreset(byte index) | |||
|     } | ||||
|     EEPROM.write(i+10, effectCurrent); | ||||
|     EEPROM.write(i+11, effectSpeed); | ||||
| 
 | ||||
|     uint32_t colTer = strip.getSegment(strip.getMainSegmentId()).colors[2]; | ||||
|     EEPROM.write(i+12, (colTer >> 16) & 0xFF); | ||||
|     EEPROM.write(i+13, (colTer >>  8) & 0xFF); | ||||
|     EEPROM.write(i+14, (colTer >>  0) & 0xFF); | ||||
|     EEPROM.write(i+15, (colTer >> 24) & 0xFF); | ||||
|    | ||||
|     EEPROM.write(i+16, effectIntensity); | ||||
|     EEPROM.write(i+17, effectPalette); | ||||
|  |  | |||
|  | @ -82,7 +82,7 @@ char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr) | |||
| } | ||||
| 
 | ||||
| //append a numeric setting to string buffer
 | ||||
| void sappend(char stype, char* key, int val) | ||||
| void sappend(char stype, const char* key, int val) | ||||
| { | ||||
|   char ds[] = "d.Sf."; | ||||
| 
 | ||||
|  | @ -113,7 +113,7 @@ void sappend(char stype, char* key, int val) | |||
| } | ||||
| 
 | ||||
| //append a string setting to buffer
 | ||||
| void sappends(char stype, char* key, char* val) | ||||
| void sappends(char stype, const char* key, char* val) | ||||
| { | ||||
|   switch(stype) | ||||
|   { | ||||
|  | @ -244,6 +244,7 @@ void getSettingsJS(byte subPage, char* dest) | |||
|   if (subPage == 3) | ||||
|   { | ||||
|     sappends('s',"DS",serverDescription); | ||||
|     sappend('c',"ST",syncToggleReceive); | ||||
|   } | ||||
| 
 | ||||
|   if (subPage == 4) | ||||
|  | @ -270,6 +271,9 @@ void getSettingsJS(byte subPage, char* dest) | |||
|     sappends('s',"AI",alexaInvocationName); | ||||
|     sappend('c',"SA",notifyAlexa); | ||||
|     sappends('s',"BK",(char*)((blynkEnabled)?"Hidden":"")); | ||||
| 
 | ||||
|     #ifdef WLED_ENABLE_MQTT | ||||
|     sappend('c',"MQ",mqttEnabled); | ||||
|     sappends('s',"MS",mqttServer); | ||||
|     sappend('v',"MQPORT",mqttPort); | ||||
|     sappends('s',"MQUSER",mqttUser); | ||||
|  | @ -282,6 +286,11 @@ void getSettingsJS(byte subPage, char* dest) | |||
|     sappends('s',"MQCID",mqttClientID); | ||||
|     sappends('s',"MD",mqttDeviceTopic); | ||||
|     sappends('s',"MG",mqttGroupTopic); | ||||
|     #endif | ||||
| 
 | ||||
|     #ifdef WLED_DISABLE_HUESYNC | ||||
|     sappends('m',"(\"hms\")[0]","Unsupported in build"); | ||||
|     #else | ||||
|     sappend('v',"H0",hueIP[0]); | ||||
|     sappend('v',"H1",hueIP[1]); | ||||
|     sappend('v',"H2",hueIP[2]); | ||||
|  | @ -293,6 +302,7 @@ void getSettingsJS(byte subPage, char* dest) | |||
|     sappend('c',"HB",hueApplyBri); | ||||
|     sappend('c',"HC",hueApplyColor); | ||||
|     sappends('m',"(\"hms\")[0]",hueError); | ||||
|     #endif | ||||
|   } | ||||
| 
 | ||||
|   if (subPage == 5) | ||||
|  |  | |||
|  | @ -14,6 +14,16 @@ void _setRandomColor(bool _sec,bool fromButton=false) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| bool isAsterisksOnly(const char* str, byte maxLen) | ||||
| { | ||||
|   for (byte i = 0; i < maxLen; i++) { | ||||
|     if (str[i] == 0) break; | ||||
|     if (str[i] != '*') return false; | ||||
|   } | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| //called upon POST settings form submit
 | ||||
| void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) | ||||
| { | ||||
|  | @ -24,7 +34,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) | |||
|   if (subPage == 1) | ||||
|   { | ||||
|     strlcpy(clientSSID,request->arg("CS").c_str(), 33); | ||||
|     if (request->arg("CP").charAt(0) != '*') strlcpy(clientPass, request->arg("CP").c_str(), 65); | ||||
| 
 | ||||
|     if (!isAsterisksOnly(request->arg("CP").c_str(), 65)) strlcpy(clientPass, request->arg("CP").c_str(), 65); | ||||
| 
 | ||||
|     strlcpy(cmDNS, request->arg("CM").c_str(), 33); | ||||
| 
 | ||||
|  | @ -32,7 +43,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) | |||
|     strlcpy(apSSID, request->arg("AS").c_str(), 33); | ||||
|     apHide = request->hasArg("AH"); | ||||
|     int passlen = request->arg("AP").length(); | ||||
|     if (passlen == 0 || (passlen > 7 && request->arg("AP").charAt(0) != '*')) strlcpy(apPass, request->arg("AP").c_str(), 65); | ||||
|     if (passlen == 0 || (passlen > 7 && !isAsterisksOnly(request->arg("AP").c_str(), 65))) strlcpy(apPass, request->arg("AP").c_str(), 65); | ||||
|     int t = request->arg("AC").toInt(); if (t > 0 && t < 14) apChannel = t; | ||||
| 
 | ||||
|     char k[3]; k[2] = 0; | ||||
|  | @ -103,6 +114,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) | |||
|   if (subPage == 3) | ||||
|   { | ||||
|     strlcpy(serverDescription, request->arg("DS").c_str(), 33); | ||||
|     syncToggleReceive = request->hasArg("ST"); | ||||
|   } | ||||
| 
 | ||||
|   //SYNC
 | ||||
|  | @ -142,15 +154,19 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) | |||
|       strlcpy(blynkApiKey, request->arg("BK").c_str(), 36); initBlynk(blynkApiKey); | ||||
|     } | ||||
| 
 | ||||
|     #ifdef WLED_ENABLE_MQTT | ||||
|     mqttEnabled = request->hasArg("MQ"); | ||||
|     strlcpy(mqttServer, request->arg("MS").c_str(), 33); | ||||
|     t = request->arg("MQPORT").toInt(); | ||||
|     if (t > 0) mqttPort = t; | ||||
|     strlcpy(mqttUser, request->arg("MQUSER").c_str(), 41); | ||||
|     if (request->arg("MQPASS").charAt(0) != '*') strlcpy(mqttPass, request->arg("MQPASS").c_str(), 41); | ||||
|     if (!isAsterisksOnly(request->arg("MQPASS").c_str(), 41)) strlcpy(mqttPass, request->arg("MQPASS").c_str(), 41); | ||||
|     strlcpy(mqttClientID, request->arg("MQCID").c_str(), 41); | ||||
|     strlcpy(mqttDeviceTopic, request->arg("MD").c_str(), 33); | ||||
|     strlcpy(mqttGroupTopic, request->arg("MG").c_str(), 33); | ||||
|     #endif | ||||
| 
 | ||||
|     #ifndef WLED_DISABLE_HUESYNC | ||||
|     for (int i=0;i<4;i++){ | ||||
|       String a = "H"+String(i); | ||||
|       hueIP[i] = request->arg(a).toInt(); | ||||
|  | @ -168,6 +184,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) | |||
|     huePollingEnabled = request->hasArg("HP"); | ||||
|     hueStoreAllowed = true; | ||||
|     reconnectHue(); | ||||
|     #endif | ||||
|   } | ||||
| 
 | ||||
|   //TIME
 | ||||
|  | @ -184,7 +201,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) | |||
| 
 | ||||
|     if (request->hasArg("OL")){ | ||||
|       overlayDefault = request->arg("OL").toInt(); | ||||
|       if (overlayCurrent != overlayDefault) strip.unlockAll(); | ||||
|       overlayCurrent = overlayDefault; | ||||
|     } | ||||
| 
 | ||||
|  | @ -443,29 +459,6 @@ bool handleSet(AsyncWebServerRequest *request, const String& req) | |||
|   pos = req.indexOf("OL="); | ||||
|   if (pos > 0) { | ||||
|     overlayCurrent = getNumVal(&req, pos); | ||||
|     strip.unlockAll(); | ||||
|   } | ||||
| 
 | ||||
|   //(un)lock pixel (ranges)
 | ||||
|   pos = req.indexOf("&L="); | ||||
|   if (pos > 0) { | ||||
|     uint16_t index = getNumVal(&req, pos); | ||||
|     pos = req.indexOf("L2="); | ||||
|     bool unlock = req.indexOf("UL") > 0; | ||||
|     if (pos > 0) { | ||||
|       uint16_t index2 = getNumVal(&req, pos); | ||||
|       if (unlock) { | ||||
|         strip.unlockRange(index, index2); | ||||
|       } else { | ||||
|         strip.lockRange(index, index2); | ||||
|       } | ||||
|     } else { | ||||
|       if (unlock) { | ||||
|         strip.unlock(index); | ||||
|       } else { | ||||
|         strip.lock(index); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   //apply macro
 | ||||
|  | @ -606,6 +599,10 @@ bool handleSet(AsyncWebServerRequest *request, const String& req) | |||
| 
 | ||||
|   //cronixie
 | ||||
|   #ifndef WLED_DISABLE_CRONIXIE | ||||
|   //mode, 1 countdown
 | ||||
|   pos = req.indexOf("NM="); | ||||
|   if (pos > 0) countdownMode = (req.charAt(pos+3) != '0'); | ||||
|    | ||||
|   pos = req.indexOf("NX="); //sets digits to code
 | ||||
|   if (pos > 0) { | ||||
|     strlcpy(cronixieDisplay, req.substring(pos + 3, pos + 9).c_str(), 6); | ||||
|  | @ -620,9 +617,6 @@ bool handleSet(AsyncWebServerRequest *request, const String& req) | |||
|     overlayRefreshedTime = 0; | ||||
|   } | ||||
|   #endif | ||||
|   //mode, 1 countdown
 | ||||
|   pos = req.indexOf("NM="); | ||||
|   if (pos > 0) countdownMode = (req.charAt(pos+3) != '0'); | ||||
| 
 | ||||
|   pos = req.indexOf("U0="); //user var 0
 | ||||
|   if (pos > 0) { | ||||
|  |  | |||
|  | @ -97,6 +97,7 @@ void wledInit() | |||
| void beginStrip() | ||||
| { | ||||
|   // Initialize NeoPixel Strip and button
 | ||||
|   strip.setShowCallback(handleOverlayDraw); | ||||
| 
 | ||||
| #ifdef BTNPIN | ||||
|   pinMode(BTNPIN, INPUT_PULLUP); | ||||
|  | @ -141,7 +142,10 @@ void initAP(bool resetAP=false){ | |||
|     if (udpPort > 0 && udpPort != ntpLocalPort) | ||||
|     { | ||||
|       udpConnected = notifierUdp.begin(udpPort); | ||||
|       if (udpConnected && udpRgbPort != udpPort) udpRgbConnected = rgbUdp.begin(udpRgbPort); | ||||
|     } | ||||
|     if (udpRgbPort > 0 && udpRgbPort != ntpLocalPort && udpRgbPort != udpPort) | ||||
|     { | ||||
|       udpRgbConnected = rgbUdp.begin(udpRgbPort); | ||||
|     } | ||||
| 
 | ||||
|     dnsServer.setErrorReplyCode(DNSReplyCode::NoError); | ||||
|  | @ -232,7 +236,7 @@ void initInterfaces() { | |||
|   if (ntpEnabled) ntpConnected = ntpUdp.begin(ntpLocalPort); | ||||
| 
 | ||||
|   initBlynk(blynkApiKey); | ||||
|   Serial.println(e131.begin((e131Multicast) ? E131_MULTICAST : E131_UNICAST , e131Universe, E131_MAX_UNIVERSE_COUNT)); | ||||
|   e131.begin((e131Multicast) ? E131_MULTICAST : E131_UNICAST , e131Universe, E131_MAX_UNIVERSE_COUNT); | ||||
|   reconnectHue(); | ||||
|   initMqtt(); | ||||
|   interfacesInited = true; | ||||
|  | @ -240,11 +244,25 @@ void initInterfaces() { | |||
| } | ||||
| 
 | ||||
| byte stacO = 0; | ||||
| uint32_t lastHeap; | ||||
| unsigned long heapTime = 0; | ||||
| 
 | ||||
| void handleConnection() { | ||||
|   //TODO: reconnect if heap <8000
 | ||||
|   if (millis() < 2000 && (!WLED_WIFI_CONFIGURED || apBehavior == 2)) return; | ||||
|   if (lastReconnectAttempt == 0) initConnection(); | ||||
| 
 | ||||
|   //reconnect WiFi to clear stale allocations if heap gets too low
 | ||||
|   if (millis() - heapTime > 5000) | ||||
|   { | ||||
|     uint32_t heap = ESP.getFreeHeap(); | ||||
|     if (heap < 9000 && lastHeap < 9000) { | ||||
|       DEBUG_PRINT("Heap too low! "); | ||||
|       DEBUG_PRINTLN(heap); | ||||
|       forceReconnect = true; | ||||
|     } | ||||
|     lastHeap = heap; | ||||
|     heapTime = millis(); | ||||
|   } | ||||
|    | ||||
|   byte stac = 0; | ||||
|   if (apActive) { | ||||
|  |  | |||
|  | @ -38,7 +38,7 @@ void notify(byte callMode, bool followUp=false) | |||
|   //0: old 1: supports white 2: supports secondary color
 | ||||
|   //3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
 | ||||
|   //6: supports timebase syncing, 29 byte packet 7: supports tertiary color 
 | ||||
|   udpOut[11] = 6;  | ||||
|   udpOut[11] = 7;  | ||||
|   udpOut[12] = colSec[0]; | ||||
|   udpOut[13] = colSec[1]; | ||||
|   udpOut[14] = colSec[2]; | ||||
|  | @ -47,10 +47,12 @@ void notify(byte callMode, bool followUp=false) | |||
|   udpOut[17] = (transitionDelay >> 0) & 0xFF; | ||||
|   udpOut[18] = (transitionDelay >> 8) & 0xFF; | ||||
|   udpOut[19] = effectPalette; | ||||
|   /*udpOut[20] = colTer[0];
 | ||||
|   udpOut[21] = colTer[1]; | ||||
|   udpOut[22] = colTer[2]; | ||||
|   udpOut[23] = colTer[3];*/ | ||||
|   uint32_t colTer = strip.getSegment(strip.getMainSegmentId()).colors[2]; | ||||
|   udpOut[20] = (colTer >> 16) & 0xFF; | ||||
|   udpOut[21] = (colTer >>  8) & 0xFF; | ||||
|   udpOut[22] = (colTer >>  0) & 0xFF; | ||||
|   udpOut[23] = (colTer >> 24) & 0xFF; | ||||
|    | ||||
|   udpOut[24] = followUp; | ||||
|   uint32_t t = millis() + strip.timebase; | ||||
|   udpOut[25] = (t >> 24) & 0xFF; | ||||
|  | @ -77,7 +79,6 @@ void arlsLock(uint32_t timeoutMs) | |||
|     { | ||||
|       strip.setPixelColor(i,0,0,0,0); | ||||
|     } | ||||
|     strip.unlockAll(); | ||||
|     realtimeActive = true; | ||||
|   } | ||||
|   realtimeTimeout = millis() + timeoutMs; | ||||
|  | @ -120,13 +121,11 @@ void handleNotifications() | |||
|   { | ||||
|     e131NewData = false; | ||||
|     strip.show(); | ||||
|     Serial.println("Show"); | ||||
|   } | ||||
| 
 | ||||
|   //unlock strip when realtime UDP times out
 | ||||
|   if (realtimeActive && millis() > realtimeTimeout) | ||||
|   { | ||||
|     //strip.unlockAll();
 | ||||
|     strip.setBrightness(bri); | ||||
|     realtimeActive = false; | ||||
|     //strip.setMode(effectCurrent);
 | ||||
|  | @ -180,7 +179,7 @@ void handleNotifications() | |||
|         col[0] = udpIn[3]; | ||||
|         col[1] = udpIn[4]; | ||||
|         col[2] = udpIn[5]; | ||||
|         if (udpIn[11] > 0) //check if sending modules white val is inteded
 | ||||
|         if (udpIn[11] > 0) //sending module's white val is intended
 | ||||
|         { | ||||
|           col[3] = udpIn[10]; | ||||
|           if (udpIn[11] > 1) | ||||
|  | @ -193,17 +192,14 @@ void handleNotifications() | |||
|           if (udpIn[11] > 5) | ||||
|           { | ||||
|             uint32_t t = (udpIn[25] << 24) | (udpIn[26] << 16) | (udpIn[27] << 8) | (udpIn[28]); | ||||
|             t -= 2; | ||||
|             t += 2; | ||||
|             t -= millis(); | ||||
|             strip.timebase = t; | ||||
|           } | ||||
|           /*if (udpIn[11] > 6)
 | ||||
|           if (udpIn[11] > 6) | ||||
|           { | ||||
|             colTer[0] = udpIn[20]; | ||||
|             colTer[1] = udpIn[21]; | ||||
|             colTer[2] = udpIn[22]; | ||||
|             colSec[3] = udpIn[23]; | ||||
|           }*/ | ||||
|             strip.setColor(2, udpIn[20], udpIn[21], udpIn[22], udpIn[23]); //tertiary color
 | ||||
|           } | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,6 +12,13 @@ void setValuesFromMainSeg() | |||
|   effectPalette = seg.palette; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void resetTimebase() | ||||
| { | ||||
|   strip.timebase = 0 - millis(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void toggleOnOff() | ||||
| { | ||||
|   if (bri == 0) | ||||
|  | @ -81,7 +88,7 @@ void colorUpdated(int callMode) | |||
| { | ||||
|   //call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
 | ||||
|   //                     6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
 | ||||
|   if (callMode != 1 && callMode != 5) strip.applyToAllSelected = true; //if not from JSON api, which directly sets segments
 | ||||
|   if (callMode != 0 && callMode != 1 && callMode != 5) strip.applyToAllSelected = true; //if not from JSON api, which directly sets segments
 | ||||
|    | ||||
|   bool fxChanged = strip.setEffectConfig(effectCurrent, effectSpeed, effectIntensity, effectPalette); | ||||
|   if (!colorChanged()) | ||||
|  | @ -113,6 +120,7 @@ void colorUpdated(int callMode) | |||
|     colIT[i] = col[i]; | ||||
|     colSecIT[i] = colSec[i]; | ||||
|   } | ||||
|   if (briT == 0 && callMode != 3) resetTimebase();  | ||||
|   briIT = bri; | ||||
|   if (bri > 0) briLast = bri; | ||||
|    | ||||
|  |  | |||
|  | @ -25,6 +25,8 @@ TimeChangeRule CDT = {Second, Sun, Mar, 2, -300 };    //Daylight time = UTC - 5 | |||
| TimeChangeRule CST = {First, Sun, Nov, 2, -360 };     //Standard time = UTC - 6 hours
 | ||||
| Timezone tzUSCentral(CDT, CST); | ||||
| 
 | ||||
| Timezone tzCASaskatchewan(CST, CST); //Central without DST
 | ||||
| 
 | ||||
| TimeChangeRule MDT = {Second, Sun, Mar, 2, -360 };    //Daylight time = UTC - 6 hours
 | ||||
| TimeChangeRule MST = {First, Sun, Nov, 2, -420 };     //Standard time = UTC - 7 hours
 | ||||
| Timezone tzUSMountain(MDT, MST); | ||||
|  | @ -55,7 +57,7 @@ Timezone tzNK(NKST, NKST); | |||
| TimeChangeRule IST = {Last, Sun, Mar, 1, 330};     // India Standard Time = UTC + 5.5 hours
 | ||||
| Timezone tzIndia(IST, IST); | ||||
| 
 | ||||
| Timezone* timezones[] = {&tzUTC, &tzUK, &tzEUCentral, &tzEUEastern, &tzUSEastern, &tzUSCentral, &tzUSMountain, &tzUSArizona, &tzUSPacific, &tzChina, &tzJapan, &tzAUEastern, &tzNZ, &tzNK, &tzIndia};   | ||||
| Timezone* timezones[] = {&tzUTC, &tzUK, &tzEUCentral, &tzEUEastern, &tzUSEastern, &tzUSCentral, &tzUSMountain, &tzUSArizona, &tzUSPacific, &tzChina, &tzJapan, &tzAUEastern, &tzNZ, &tzNK, &tzIndia, &tzCASaskatchewan};   | ||||
| 
 | ||||
| void handleNetworkTime() | ||||
| { | ||||
|  | @ -161,13 +163,16 @@ void setCountdown() | |||
| //returns true if countdown just over
 | ||||
| bool checkCountdown() | ||||
| { | ||||
|   long diff = countdownTime - now(); | ||||
|   local = abs(diff); | ||||
|   if (diff <0 && !countdownOverTriggered) | ||||
|   { | ||||
|     if (macroCountdown != 0) applyMacro(macroCountdown); | ||||
|     countdownOverTriggered = true; | ||||
|     return true; | ||||
|   unsigned long n = now(); | ||||
|   local = countdownTime - n; | ||||
|   if (n > countdownTime) { | ||||
|     local = n - countdownTime; | ||||
|     if (!countdownOverTriggered) | ||||
|     { | ||||
|       if (macroCountdown != 0) applyMacro(macroCountdown); | ||||
|       countdownOverTriggered = true; | ||||
|       return true; | ||||
|     } | ||||
|   } | ||||
|   return false; | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| /*
 | ||||
|  * Used to draw clock overlays over the strip | ||||
|  */ | ||||
|   | ||||
| void initCronixie() | ||||
| { | ||||
|   if (overlayCurrent == 3 && !cronixieInit) | ||||
|  | @ -17,107 +18,6 @@ void initCronixie() | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| void _nixieDisplay(int num[], uint16_t dur[], uint16_t pausedur[], byte cnt) | ||||
| { | ||||
|   strip.setRange(overlayMin, overlayMax, 0); | ||||
|   if (num[nixieClockI] >= 0 && !nixiePause) | ||||
|   { | ||||
|     strip.setIndividual(num[nixieClockI],((uint32_t)colT[3] << 24)| ((uint32_t)colT[0] << 16) | ((uint32_t)colT[1] << 8) | colT[2]); | ||||
|     strip.unlock(num[nixieClockI]); | ||||
|   } | ||||
|   if (!nixiePause) | ||||
|   { | ||||
|     overlayRefreshMs = dur[nixieClockI]; | ||||
|   } else | ||||
|   { | ||||
|     overlayRefreshMs = pausedur[nixieClockI]; | ||||
|   } | ||||
|   if (pausedur[nixieClockI] > 0 && !nixiePause) | ||||
|   { | ||||
|     nixiePause = true; | ||||
|   } else { | ||||
|     if (nixieClockI < cnt -1) | ||||
|     { | ||||
|       nixieClockI++; | ||||
|     } else | ||||
|     { | ||||
|       nixieClockI = -1; | ||||
|     } | ||||
|     nixiePause = false; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void _nixieNumber(int number, int dur)  | ||||
| { | ||||
|   if (nixieClockI < 0) | ||||
|   { | ||||
|     DEBUG_PRINT(number); | ||||
|     int digitCnt = -1; | ||||
|     int digits[4]; | ||||
|     digits[3] = number/1000; | ||||
|     digits[2] = (number/100)%10; | ||||
|     digits[1] = (number/10)%10; | ||||
|     digits[0] = number%10; | ||||
|     if (number > 999) //four digits
 | ||||
|     { | ||||
|       digitCnt = 4; | ||||
|     } else if (number > 99) //three digits
 | ||||
|     { | ||||
|       digitCnt = 3; | ||||
|     } else if (number > 9) //two digits
 | ||||
|     { | ||||
|       digitCnt = 2; | ||||
|     } else { //single digit
 | ||||
|       digitCnt = 1; | ||||
|     } | ||||
|     DEBUG_PRINT(" "); | ||||
|     for (int i = 0; i < digitCnt; i++) | ||||
|     { | ||||
|       DEBUG_PRINT(digits[i]); | ||||
|       overlayArr[digitCnt-1-i] = digits[i]; | ||||
|       overlayDur[digitCnt-1-i] = ((dur/4)*3)/digitCnt; | ||||
|       overlayPauseDur[digitCnt-1-i] = 0; | ||||
|     } | ||||
|     DEBUG_PRINTLN(" "); | ||||
|     for (int i = 1; i < digitCnt; i++) | ||||
|     { | ||||
|       if (overlayArr[i] == overlayArr[i-1]) | ||||
|       { | ||||
|         overlayPauseDur[i-1] = dur/12; | ||||
|         overlayDur[i-1] = overlayDur[i-1]-dur/12; | ||||
|       } | ||||
|     } | ||||
|     for (int i = digitCnt; i < 6; i++) | ||||
|     { | ||||
|       overlayArr[i] = -1; | ||||
|       overlayDur[i] = 0; | ||||
|       overlayPauseDur[i] = 0; | ||||
|     } | ||||
|     overlayPauseDur[5] = dur/4; | ||||
|     for (int i = 0; i < 6; i++) | ||||
|     { | ||||
|       if (overlayArr[i] != -1) | ||||
|       { | ||||
|         overlayArr[i] = overlayArr[i] + overlayMin; | ||||
|       } | ||||
|     } | ||||
|     for (int i = 0; i <6; i++) | ||||
|     { | ||||
|       DEBUG_PRINT(overlayArr[i]); | ||||
|       DEBUG_PRINT(" "); | ||||
|       DEBUG_PRINT(overlayDur[i]); | ||||
|       DEBUG_PRINT(" "); | ||||
|       DEBUG_PRINT(overlayPauseDur[i]); | ||||
|       DEBUG_PRINT(" "); | ||||
|     } | ||||
|     DEBUG_PRINTLN(" "); | ||||
|     nixieClockI = 0; | ||||
|   } else { | ||||
|     _nixieDisplay(overlayArr, overlayDur, overlayPauseDur, 6); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void handleOverlays() | ||||
| { | ||||
|   if (millis() - overlayRefreshedTime > overlayRefreshMs) | ||||
|  | @ -125,22 +25,16 @@ void handleOverlays() | |||
|     initCronixie(); | ||||
|     updateLocalTime(); | ||||
|     checkTimers(); | ||||
|     switch (overlayCurrent) | ||||
|     { | ||||
|       case 0: break;//no overlay
 | ||||
|       case 1: _overlayAnalogClock(); break;//2 analog clock
 | ||||
|       case 2: _overlayNixieClock(); break;//nixie 1-digit
 | ||||
|       case 3: _overlayCronixie();//Diamex cronixie clock kit
 | ||||
|     } | ||||
|     if (!countdownMode || overlayCurrent < 2) checkCountdown(); //countdown macro activation must work
 | ||||
|     checkCountdown(); | ||||
|     if (overlayCurrent == 3) _overlayCronixie();//Diamex cronixie clock kit
 | ||||
|     overlayRefreshedTime = millis(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void _overlayAnalogClock() | ||||
| { | ||||
|   int overlaySize = overlayMax - overlayMin +1; | ||||
|   strip.unlockAll(); | ||||
|   if (countdownMode) | ||||
|   { | ||||
|     _overlayAnalogCountdown(); return; | ||||
|  | @ -173,115 +67,19 @@ void _overlayAnalogClock() | |||
|     { | ||||
|       pix = analogClock12pixel + round((overlaySize / 12.0) *i); | ||||
|       if (pix > overlayMax) pix -= overlaySize; | ||||
|       strip.setIndividual(pix, 0x00FFAA); | ||||
|       strip.setPixelColor(pix, 0x00FFAA); | ||||
|     } | ||||
|   } | ||||
|   if (!analogClockSecondsTrail) strip.setIndividual(secondPixel, 0xFF0000); | ||||
|   strip.setIndividual(minutePixel, 0x00FF00); | ||||
|   strip.setIndividual(hourPixel, 0x0000FF); | ||||
|   if (!analogClockSecondsTrail) strip.setPixelColor(secondPixel, 0xFF0000); | ||||
|   strip.setPixelColor(minutePixel, 0x00FF00); | ||||
|   strip.setPixelColor(hourPixel, 0x0000FF); | ||||
|   overlayRefreshMs = 998; | ||||
| } | ||||
| 
 | ||||
| void _overlayNixieClock() | ||||
| { | ||||
|   #ifdef WLED_DISABLE_CRONIXIE | ||||
|   if (countdownMode) checkCountdown(); | ||||
|   #else | ||||
|    | ||||
|   if (countdownMode) | ||||
|   { | ||||
|     _overlayNixieCountdown(); return; | ||||
|   } | ||||
|   if (nixieClockI < 0) | ||||
|   { | ||||
|       overlayArr[0] = hour(local); | ||||
|       if (useAMPM) overlayArr[0] = overlayArr[0]%12; | ||||
|       overlayArr[1] = -1; | ||||
|       if (overlayArr[0] > 9) | ||||
|       { | ||||
|         overlayArr[1] = overlayArr[0]%10; | ||||
|         overlayArr[0] = overlayArr[0]/10; | ||||
|       } | ||||
|       overlayArr[2] = minute(local); | ||||
|       overlayArr[3] = overlayArr[2]%10; | ||||
|       overlayArr[2] = overlayArr[2]/10; | ||||
|       overlayArr[4] = -1; | ||||
|       overlayArr[5] = -1; | ||||
|       if (analogClockSecondsTrail) | ||||
|       { | ||||
|         overlayArr[4] = second(local); | ||||
|         overlayArr[5] = overlayArr[4]%10; | ||||
|         overlayArr[4] = overlayArr[4]/10; | ||||
|       } | ||||
|       for (int i = 0; i < 6; i++) | ||||
|       { | ||||
|         if (overlayArr[i] != -1) | ||||
|         { | ||||
|           overlayArr[i] = overlayArr[i] + overlayMin; | ||||
|         } | ||||
|       } | ||||
|       overlayDur[0] = 12 + 12*(255 - overlaySpeed); | ||||
|       if (overlayArr[1] == overlayArr[0]) | ||||
|       { | ||||
|         overlayPauseDur[0] = 3 + 3*(255 - overlaySpeed); | ||||
|       } else | ||||
|       { | ||||
|         overlayPauseDur[0] = 0; | ||||
|       } | ||||
|       if (overlayArr[1] == -1) | ||||
|       { | ||||
|         overlayDur[1] = 0; | ||||
|       } else | ||||
|       { | ||||
|         overlayDur[1] = 12 + 12*(255 - overlaySpeed); | ||||
|       } | ||||
|       overlayPauseDur[1] = 9 + 9*(255 - overlaySpeed); | ||||
| 
 | ||||
|       overlayDur[2] = 12 + 12*(255 - overlaySpeed); | ||||
|       if (overlayArr[2] == overlayArr[3]) | ||||
|       { | ||||
|         overlayPauseDur[2] = 3 + 3*(255 - overlaySpeed); | ||||
|       } else | ||||
|       { | ||||
|         overlayPauseDur[2] = 0; | ||||
|       } | ||||
|       overlayDur[3] = 12 + 12*(255 - overlaySpeed); | ||||
|       overlayPauseDur[3] = 9 + 9*(255 - overlaySpeed); | ||||
|        | ||||
|       if (overlayArr[4] == -1) | ||||
|       { | ||||
|         overlayDur[4] = 0; | ||||
|         overlayPauseDur[4] = 0; | ||||
|         overlayDur[5] = 0; | ||||
|       } else | ||||
|       { | ||||
|         overlayDur[4] = 12 + 12*(255 - overlaySpeed); | ||||
|         if (overlayArr[5] == overlayArr[4]) | ||||
|         { | ||||
|           overlayPauseDur[4] = 3 + 3*(255 - overlaySpeed); | ||||
|         } else | ||||
|         { | ||||
|           overlayPauseDur[4] = 0; | ||||
|         } | ||||
|         overlayDur[5] = 12 + 12*(255 - overlaySpeed); | ||||
|       } | ||||
|       overlayPauseDur[5] = 22 + 22*(255 - overlaySpeed); | ||||
|        | ||||
|       nixieClockI = 0;    | ||||
|   } else | ||||
|   { | ||||
|     _nixieDisplay(overlayArr, overlayDur, overlayPauseDur, 6); | ||||
|   } | ||||
|   #endif | ||||
| } | ||||
| 
 | ||||
| void _overlayAnalogCountdown() | ||||
| { | ||||
|   strip.unlockAll(); | ||||
|   if (now() >= countdownTime) | ||||
|   { | ||||
|     checkCountdown(); | ||||
|   } else | ||||
|   if (now() < countdownTime) | ||||
|   { | ||||
|     long diff = countdownTime - now(); | ||||
|     double pval = 60; | ||||
|  | @ -321,31 +119,7 @@ void _overlayAnalogCountdown() | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| void _overlayNixieCountdown() | ||||
| { | ||||
|   if (now() >= countdownTime) | ||||
|   { | ||||
|     if (checkCountdown()) | ||||
|     { | ||||
|       _nixieNumber(2019, 2019); | ||||
|     } | ||||
|   } else | ||||
|   { | ||||
|     long diff = countdownTime - now(); | ||||
|     if (diff > 86313600L) //display in years if more than 999 days
 | ||||
|     { | ||||
|       diff = diff/31557600L; | ||||
|     } else if (diff > 3596400) //display in days if more than 999 hours
 | ||||
|     { | ||||
|       diff = diff/86400; | ||||
|     } else if (diff > 59940) //display in hours if more than 999 minutes
 | ||||
|     { | ||||
|       diff = diff/1440; | ||||
|     } else if (diff > 999) //display in minutes if more than 999 seconds
 | ||||
|     { | ||||
|       diff = diff/60; | ||||
|     } | ||||
|     _nixieNumber(diff, 800); | ||||
|   } | ||||
|   overlayRefreshMs = 998; | ||||
| void handleOverlayDraw() { | ||||
|   if (overlayCurrent != 1) return; //only analog clock
 | ||||
|   _overlayAnalogClock(); | ||||
| } | ||||
|  |  | |||
|  | @ -62,10 +62,11 @@ void onAlexaChange(EspalexaDevice* dev) | |||
|   } else //color
 | ||||
|   { | ||||
|     uint32_t color = espalexaDevice->getRGB(); | ||||
|     col[3] = ((color >> 24) & 0xFF);  // white color from Alexa is "pure white only" 
 | ||||
|     col[0] = ((color >> 16) & 0xFF); | ||||
|     col[1] = ((color >>  8) & 0xFF); | ||||
|     col[2] = (color & 0xFF); | ||||
|     if (useRGBW) colorRGBtoRGBW(col); | ||||
|     if (useRGBW && col[3] == 0) colorRGBtoRGBW(col);  // do not touch white value if EspalexaDevice.cpp did set the white channel
 | ||||
|     colorUpdated(10); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -145,9 +145,7 @@ void setCronixie() | |||
| 
 | ||||
| void _overlayCronixie() | ||||
| { | ||||
|   if (countdownMode) checkCountdown(); | ||||
|   #ifndef WLED_DISABLE_CRONIXIE | ||||
|    | ||||
|   byte h = hour(local); | ||||
|   byte h0 = h; | ||||
|   byte m = minute(local); | ||||
|  |  | |||
|  | @ -165,6 +165,6 @@ void colorRGBtoRGBW(byte* rgb) //rgb to rgbw (http://codewelt.com/rgbw) | |||
|   float low = minf(rgb[0],minf(rgb[1],rgb[2])); | ||||
|   float high = maxf(rgb[0],maxf(rgb[1],rgb[2])); | ||||
|   if (high < 0.1f) return; | ||||
|   float sat = 255.0f * ((high - low) / high); | ||||
|   float sat = 100.0f * ((high - low) / high);;   // maximum saturation is 100  (corrected from 255)
 | ||||
|   rgb[3] = (byte)((255.0f - sat) / 255.0f * (rgb[0] + rgb[1] + rgb[2]) / 3); | ||||
| } | ||||
|  |  | |||
|  | @ -2,6 +2,8 @@ | |||
|  * MQTT communication protocol for home automation | ||||
|  */ | ||||
| 
 | ||||
| #ifdef WLED_ENABLE_MQTT | ||||
| 
 | ||||
| void parseMQTTBriPayload(char* payload) | ||||
| { | ||||
|   if      (strstr(payload, "ON") || strstr(payload, "on") || strstr(payload, "true")) {bri = briLast; colorUpdated(1);} | ||||
|  | @ -104,7 +106,7 @@ void publishMqtt() | |||
| bool initMqtt() | ||||
| { | ||||
|   lastMqttReconnectAttempt = millis(); | ||||
|   if (mqttServer[0] == 0 || !WLED_CONNECTED) return false; | ||||
|   if (!mqttEnabled || mqttServer[0] == 0 || !WLED_CONNECTED) return false; | ||||
| 
 | ||||
|   if (mqtt == nullptr) { | ||||
|     mqtt = new AsyncMqttClient(); | ||||
|  | @ -130,3 +132,8 @@ bool initMqtt() | |||
|   mqtt->connect(); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| bool initMqtt(){return false;} | ||||
| void publishMqtt(){} | ||||
| #endif | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ void initServer() | |||
|    | ||||
|   server.on("/settings/wifi", HTTP_POST, [](AsyncWebServerRequest *request){ | ||||
|     if (!(wifiLock && otaLock)) handleSettingsSet(request, 1); | ||||
|     serveMessage(request, 200,"WiFi settings saved.","Reconnecting now...",129); | ||||
|     serveMessage(request, 200,"WiFi settings saved.","Please connect to the new IP (if changed)",129); | ||||
|     forceReconnect = true; | ||||
|   }); | ||||
| 
 | ||||
|  | @ -79,7 +79,7 @@ void initServer() | |||
| 
 | ||||
|   server.on("/settings/ui", HTTP_POST, [](AsyncWebServerRequest *request){ | ||||
|     handleSettingsSet(request, 3); | ||||
|     serveMessage(request, 200,"UI settings saved.","Reloading to apply theme...",122); | ||||
|     serveMessage(request, 200,"UI settings saved.","Redirecting...",1); | ||||
|   }); | ||||
| 
 | ||||
|   server.on("/settings/sync", HTTP_POST, [](AsyncWebServerRequest *request){ | ||||
|  | @ -94,7 +94,7 @@ void initServer() | |||
| 
 | ||||
|   server.on("/settings/sec", HTTP_POST, [](AsyncWebServerRequest *request){ | ||||
|     handleSettingsSet(request, 6); | ||||
|     if (!doReboot) serveMessage(request, 200,"Security settings saved.","Rebooting now, please wait ~10 seconds...",129); | ||||
|     if (!doReboot) serveMessage(request, 200,"Security settings saved.","Rebooting, please wait ~10 seconds...",129); | ||||
|     doReboot = true; | ||||
|   }); | ||||
| 
 | ||||
|  | @ -102,9 +102,20 @@ void initServer() | |||
|     serveJson(request); | ||||
|   }); | ||||
| 
 | ||||
|   AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/json", [](AsyncWebServerRequest *request, JsonObject root) { | ||||
|     if (root.isNull()){request->send(500, "application/json", "{\"error\":\"Parsing failed\"}"); return;} | ||||
|     if (deserializeState(root)) { serveJson(request); return; } //if JSON contains "v" (verbose response)
 | ||||
|   AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/json", [](AsyncWebServerRequest *request) { | ||||
|     bool verboseResponse = false; | ||||
|     { //scope JsonDocument so it releases its buffer
 | ||||
|       DynamicJsonDocument jsonBuffer(8192); | ||||
|       DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject)); | ||||
|       JsonObject root = jsonBuffer.as<JsonObject>(); | ||||
|       if (error || root.isNull()) { | ||||
|         request->send(400, "application/json", "{\"error\":10}"); return; | ||||
|       } | ||||
|       verboseResponse = deserializeState(root); | ||||
|     } | ||||
|     if (verboseResponse) { //if JSON contains "v"
 | ||||
|       serveJson(request); return;  | ||||
|     }  | ||||
|     request->send(200, "application/json", "{\"success\":true}"); | ||||
|   }); | ||||
|   server.addHandler(handler); | ||||
|  |  | |||
|  | @ -86,8 +86,8 @@ bool deserializeState(JsonObject root) | |||
|   int ps = root["ps"] | -1; | ||||
|   if (ps >= 0) applyPreset(ps); | ||||
|    | ||||
|   int cy = root["pl"] | -1; | ||||
|   presetCyclingEnabled = (cy >= 0); | ||||
|   int cy = root["pl"] | -2; | ||||
|   if (cy > -2) presetCyclingEnabled = (cy >= 0); | ||||
|   JsonObject ccnf = root["ccnf"]; | ||||
|   presetCycleMin = ccnf["min"] | presetCycleMin; | ||||
|   presetCycleMax = ccnf["max"] | presetCycleMax; | ||||
|  | @ -121,15 +121,23 @@ bool deserializeState(JsonObject root) | |||
|   if (segVar.is<JsonObject>()) | ||||
|   { | ||||
|     int id = segVar["id"] | -1; | ||||
|      | ||||
|     if (id < 0) { //set all selected segments
 | ||||
|       bool didSet = false; | ||||
|       byte lowestActive = 99; | ||||
|       for (byte s = 0; s < strip.getMaxSegments(); s++) | ||||
|       { | ||||
|         WS2812FX::Segment sg = strip.getSegment(s); | ||||
|         if (sg.isActive() && sg.isSelected()) | ||||
|         if (sg.isActive()) | ||||
|         { | ||||
|           deserializeSegment(segVar, s); | ||||
|           if (lowestActive == 99) lowestActive = s; | ||||
|           if (sg.isSelected()) { | ||||
|             deserializeSegment(segVar, s); | ||||
|             didSet = true; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       if (!didSet && lowestActive < strip.getMaxSegments()) deserializeSegment(segVar, lowestActive); | ||||
|     } else { //set only the segment with the specified ID
 | ||||
|       deserializeSegment(segVar, it); | ||||
|     } | ||||
|  | @ -142,7 +150,6 @@ bool deserializeState(JsonObject root) | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   //fromJson = true;
 | ||||
|   colorUpdated(noNotification ? 5:1); | ||||
| 
 | ||||
|   ps = root["psave"] | -1; | ||||
|  | @ -236,9 +243,11 @@ void serializeInfo(JsonObject root) | |||
|   leds_pin.add(LEDPIN); | ||||
|    | ||||
|   leds["pwr"] = strip.currentMilliamps; | ||||
|   leds["maxpwr"] = strip.ablMilliampsMax; | ||||
|   leds["maxpwr"] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0; | ||||
|   leds["maxseg"] = strip.getMaxSegments(); | ||||
|   leds["seglock"] = false; //will be used in the future to prevent modifications to segment config
 | ||||
| 
 | ||||
|   root["str"] = syncToggleReceive; | ||||
|    | ||||
|   root["name"] = serverDescription; | ||||
|   root["udpport"] = udpPort; | ||||
|  | @ -295,7 +304,7 @@ void serializeInfo(JsonObject root) | |||
|    | ||||
|   root["brand"] = "WLED"; | ||||
|   root["product"] = "DIY light"; | ||||
|   root["btype"] = "dev"; | ||||
|   root["btype"] = "src"; | ||||
|   root["mac"] = escapedMac; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Aircoookie
						Aircoookie