Merge pull request #57 from Aircoookie/development

Release of v0.8.0
This commit is contained in:
Aircoookie 2018-10-15 16:33:20 +02:00 committed by GitHub
commit 1e69cc75c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 5684 additions and 3632 deletions

View File

@ -1,30 +1,34 @@
## Welcome to my project WLED! ![WLED logo](https://raw.githubusercontent.com/Aircoookie/WLED/development/wled_logo.png)
WLED is a fast and (relatively) secure implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B) LEDs! ## Welcome to my project WLED! (v0.8.0)
### Features: (V0.7.1) A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B) LEDs!
- RGB, HSB, and brightness sliders
- All new, mobile-friendly web UI! ### Features:
- WS2812FX library integrated for over 70 special effects
- FastLED noise effects and palettes
- Customizable Mobile and desktop UI with color and effect controls
- Settings page - configuration over network - Settings page - configuration over network
- Access Point and station mode - automatic failsafe AP - Access Point and station mode - automatic failsafe AP
- Support of Blynk IoT cloud
- WS2812FX library integrated for over 50 special effects (+Custom Theater Chase)!
- Secondary color support lets you use even more effect combinations
- Alexa smart home device server (including dimming)
- Beta syncronization to Philips hue lights
- Support for RGBW strips - Support for RGBW strips
- 25 user presets! Save colors and effects and apply them easily! Supports cycling through them. - 25 user presets to save and load colors/effects easily, supports cycling through them.
- HTTP request API for simple integration
- Macro functions to automatically execute API calls - Macro functions to automatically execute API calls
- Nightlight function (gradually dims down) - Nightlight function (gradually dims down)
- Notifier function (multiple ESPs sync color via UDP broadcast) - Full OTA software updatability (HTTP + ArduinoOTA), password protectable
- Support for power pushbutton - Configurable analog clock + support for the Cronixie kit by Diamex
- Support for the Adalight serial ambilight protocol!
- Full OTA software update capability (HTTP and ArduinoOTA) ### Supported light control interfaces:
- Password protected OTA page for added security (OTA lock) - HTTP request API
- NTP and configurable analog clock function - Blynk IoT
- Support for the Cronixie Clock kit by Diamex - MQTT
- Realtime UDP Packet Control (E1.31, Hyperion, WARLS, DRGB, DRGBW) - E1.31
- Hyperion
- UDP realtime
- Alexa smart device (including dimming)
- Sync to Philips hue lights
- Adalight (PC ambilight via serial)
- Sync color of multiple WLED devices (UDP notifier)
- Simple timers/schedules (time from NTP, timezones/DST supported)
### Quick start guide and documentation: ### Quick start guide and documentation:
@ -32,16 +36,14 @@ See the [wiki](https://github.com/Aircoookie/WLED/wiki)!
### Other ### Other
Licensed under the MIT license Licensed under the MIT license
Uses libraries: Credits in About page!
ESP8266/ESP32 Arduino Core
NeoPixelBus by Makuna
[WS2812FX](https://github.com/kitesurfer1404/WS2812FX) by kitesurfer1404 (Aircoookie fork)
Time library
Timezone library by JChristensen
Alexa code based on arduino-esp8266-alexa-multiple-wemo-switch by kakopappa
Uses Linearicons by Perxis! (link in settings page) Uses Linearicons by Perxis!
Join the Discord [server](https://discord.gg/KuqP7NE) to discuss everything about WLED!
You can also send me mails to [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com).
If you insist that you just love WLED too much, you can [send me a gift](https://paypal.me/aircoookie)!

View File

@ -1,8 +1,12 @@
//this code is a modified version of https://github.com/Makuna/NeoPixelBus/issues/103 //this code is a modified version of https://github.com/Makuna/NeoPixelBus/issues/103
#ifndef NpbWrapper_h
#define NpbWrapper_h
//#define WORKAROUND_ESP32_BITBANG //#define WORKAROUND_ESP32_BITBANG
//see https://github.com/Aircoookie/WLED/issues/2 for flicker free ESP32 support //see https://github.com/Aircoookie/WLED/issues/2 for flicker free ESP32 support
#define LEDPIN 2 //strip pin. Only effective for ESP32, ESP8266 must use gpio2
//uncomment this if red and green are swapped //uncomment this if red and green are swapped
//#define SWAPRG //#define SWAPRG
@ -13,9 +17,12 @@
#else #else
#define PIXELMETHOD NeoEsp32RmtWS2813_V3Method #define PIXELMETHOD NeoEsp32RmtWS2813_V3Method
#endif #endif
#else #else //esp8266
//you may change to DMA method on pin GPIO3 here
#define PIXELMETHOD NeoEsp8266Uart800KbpsMethod #define PIXELMETHOD NeoEsp8266Uart800KbpsMethod
//#define PIXELMETHOD NeoEsp8266Dma800KbpsMethod
#endif #endif
//handle swapping Red and Green automatically //handle swapping Red and Green automatically
#ifdef SWAPRG #ifdef SWAPRG
#define PIXELFEATURE3 NeoRgbFeature #define PIXELFEATURE3 NeoRgbFeature
@ -52,7 +59,7 @@ public:
cleanup(); cleanup();
} }
void Begin(NeoPixelType type, uint16_t countPixels, uint8_t pin) void Begin(NeoPixelType type, uint16_t countPixels)
{ {
cleanup(); cleanup();
_type = type; _type = type;
@ -60,12 +67,12 @@ public:
switch (_type) { switch (_type) {
case NeoPixelType_Grb: case NeoPixelType_Grb:
_pGrb = new NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>(countPixels, pin); _pGrb = new NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>(countPixels, LEDPIN);
_pGrb->Begin(); _pGrb->Begin();
break; break;
case NeoPixelType_Grbw: case NeoPixelType_Grbw:
_pGrbw = new NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>(countPixels, pin); _pGrbw = new NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>(countPixels, LEDPIN);
_pGrbw->Begin(); _pGrbw->Begin();
break; break;
} }
@ -110,7 +117,7 @@ public:
void SetPixelColor(uint16_t indexPixel, RgbwColor color) void SetPixelColor(uint16_t indexPixel, RgbwColor color)
{ {
switch (_type) { switch (_type) {
case NeoPixelType_Grb: _pGrbw->SetPixelColor(indexPixel, color); break; case NeoPixelType_Grb: _pGrb->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B)); break;
case NeoPixelType_Grbw: _pGrbw->SetPixelColor(indexPixel, color); break; case NeoPixelType_Grbw: _pGrbw->SetPixelColor(indexPixel, color); break;
} }
} }
@ -174,3 +181,4 @@ private:
} }
} }
}; };
#endif

File diff suppressed because it is too large Load Diff

View File

@ -2,18 +2,17 @@
/* /*
WS2812FX.h - Library for WS2812 LED effects. WS2812FX.h - Library for WS2812 LED effects.
Harm Aldick - 2016 Harm Aldick - 2016
www.aldick.org www.aldick.org
FEATURES FEATURES
* A lot of blinken modes and counting * A lot of blinken modes and counting
* WS2812FX can be used as drop-in replacement for Adafruit Neopixel Library * WS2812FX can be used as drop-in replacement for Adafruit NeoPixel Library
NOTES NOTES
* Uses the Adafruit Neopixel library. Get it here: * Uses the Adafruit NeoPixel library. Get it here:
https://github.com/adafruit/Adafruit_NeoPixel https://github.com/adafruit/Adafruit_NeoPixel
LICENSE LICENSE
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2016 Harm Aldick Copyright (c) 2016 Harm Aldick
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
@ -29,27 +28,61 @@
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
Heavily modified to work with WLED - differs from Github WS2812FX CHANGELOG
2016-05-28 Initial beta release
2016-06-03 Code cleanup, minor improvements, new modes
2016-06-04 2 new fx, fixed setColor (now also resets _mode_color)
2017-02-02 added external trigger functionality (e.g. for sound-to-light)
Modified for WLED
*/ */
#ifndef WS2812FX_h #ifndef WS2812FX_h
#define WS2812FX_h #define WS2812FX_h
#include "Arduino.h"
#include "NpbWrapper.h" #include "NpbWrapper.h"
#define DEFAULT_BRIGHTNESS 50 #define DEFAULT_BRIGHTNESS (uint8_t)50
#define DEFAULT_MODE 0 #define DEFAULT_MODE (uint8_t)0
#define DEFAULT_SPEED 150 #define DEFAULT_SPEED (uint16_t)1000
#define DEFAULT_COLOR 0xFFAA00 #define DEFAULT_COLOR (uint32_t)0xFF0000
#define SPEED_MIN 0 #define min(a,b) ((a)<(b)?(a):(b))
#define SPEED_MAX 255 #define max(a,b) ((a)>(b)?(a):(b))
#define BRIGHTNESS_MIN 0 /* each segment uses 38 bytes of SRAM memory, so if you're application fails because of
#define BRIGHTNESS_MAX 255 insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
#define MAX_NUM_SEGMENTS 10
#define NUM_COLORS 3 /* number of colors per segment */
#define SEGMENT _segments[_segment_index]
#define SEGMENT_RUNTIME _segment_runtimes[_segment_index]
#define SEGMENT_LENGTH (SEGMENT.stop - SEGMENT.start + 1)
#define SPEED_FORMULA_L 5 + (50*(255 - SEGMENT.speed))/SEGMENT_LENGTH
#define RESET_RUNTIME memset(_segment_runtimes, 0, sizeof(_segment_runtimes))
#define MODE_COUNT 58 // some common colors
#define RED (uint32_t)0xFF0000
#define GREEN (uint32_t)0x00FF00
#define BLUE (uint32_t)0x0000FF
#define WHITE (uint32_t)0xFFFFFF
#define BLACK (uint32_t)0x000000
#define YELLOW (uint32_t)0xFFFF00
#define CYAN (uint32_t)0x00FFFF
#define MAGENTA (uint32_t)0xFF00FF
#define PURPLE (uint32_t)0x400080
#define ORANGE (uint32_t)0xFF3000
#define PINK (uint32_t)0xFF1493
#define ULTRAWHITE (uint32_t)0xFFFFFFFF
// options
// bit 8: reverse animation
// bits 5-7: fade rate (0-7)
// bit 4: gamma correction
// bits 1-3: TBD
#define NO_OPTIONS (uint8_t)0x00
#define REVERSE (uint8_t)0x80
#define IS_REVERSE ((SEGMENT.options & REVERSE) == REVERSE)
#define MODE_COUNT 74
#define FX_MODE_STATIC 0 #define FX_MODE_STATIC 0
#define FX_MODE_BLINK 1 #define FX_MODE_BLINK 1
@ -57,7 +90,7 @@
#define FX_MODE_COLOR_WIPE 3 #define FX_MODE_COLOR_WIPE 3
#define FX_MODE_COLOR_WIPE_RANDOM 4 #define FX_MODE_COLOR_WIPE_RANDOM 4
#define FX_MODE_RANDOM_COLOR 5 #define FX_MODE_RANDOM_COLOR 5
#define FX_MODE_EASTER 6 #define FX_MODE_COLOR_SWEEP 6
#define FX_MODE_DYNAMIC 7 #define FX_MODE_DYNAMIC 7
#define FX_MODE_RAINBOW 8 #define FX_MODE_RAINBOW 8
#define FX_MODE_RAINBOW_CYCLE 9 #define FX_MODE_RAINBOW_CYCLE 9
@ -104,193 +137,237 @@
#define FX_MODE_DUAL_COLOR_WIPE_OUT_OUT 50 #define FX_MODE_DUAL_COLOR_WIPE_OUT_OUT 50
#define FX_MODE_DUAL_COLOR_WIPE_OUT_IN 51 #define FX_MODE_DUAL_COLOR_WIPE_OUT_IN 51
#define FX_MODE_CIRCUS_COMBUSTUS 52 #define FX_MODE_CIRCUS_COMBUSTUS 52
#define FX_MODE_CUSTOM_CHASE 53 #define FX_MODE_HALLOWEEN 53
#define FX_MODE_CC_ON_RAINBOW 54 #define FX_MODE_TRICOLOR_CHASE 54
#define FX_MODE_CC_ON_RAINBOW_CYCLE 55 #define FX_MODE_TRICOLOR_WIPE 55
#define FX_MODE_CC_BLINK 56 #define FX_MODE_TRICOLOR_FADE 56
#define FX_MODE_CC_RANDOM 57 #define FX_MODE_LIGHTNING 57
#define FX_MODE_ICU 58
#define FX_MODE_MULTI_COMET 59
#define FX_MODE_DUAL_LARSON_SCANNER 60
#define FX_MODE_RANDOM_CHASE 61
#define FX_MODE_OSCILLATE 62
//Modes that use FastLED -->
#define FX_MODE_PRIDE_2015 63
#define FX_MODE_JUGGLE 64
#define FX_MODE_PALETTE 65
#define FX_MODE_FIRE_2012 66
#define FX_MODE_COLORWAVES 67
#define FX_MODE_BPM 68
#define FX_MODE_FILLNOISE8 69
#define FX_MODE_NOISE16_1 70
#define FX_MODE_NOISE16_2 71
#define FX_MODE_NOISE16_3 72
#define FX_MODE_NOISE16_4 73
class WS2812FX { class WS2812FX {
typedef void (WS2812FX::*mode_ptr)(void); typedef uint16_t (WS2812FX::*mode_ptr)(void);
// segment parameters
public: public:
WS2812FX(){ typedef struct Segment { // 21 bytes
uint16_t start;
uint16_t stop;
uint8_t speed;
uint8_t intensity;
uint8_t palette;
uint8_t mode;
uint8_t options;
uint32_t colors[NUM_COLORS];
} segment;
_mode[FX_MODE_STATIC] = &WS2812FX::mode_static; // segment runtime parameters
_mode[FX_MODE_BLINK] = &WS2812FX::mode_blink; typedef struct Segment_runtime { // 17 bytes
_mode[FX_MODE_BREATH] = &WS2812FX::mode_breath; unsigned long next_time;
_mode[FX_MODE_COLOR_WIPE] = &WS2812FX::mode_color_wipe; uint32_t counter_mode_step;
_mode[FX_MODE_COLOR_WIPE_RANDOM] = &WS2812FX::mode_color_wipe_random; uint32_t counter_mode_call;
_mode[FX_MODE_RANDOM_COLOR] = &WS2812FX::mode_random_color; uint16_t aux_param;
_mode[FX_MODE_EASTER] = &WS2812FX::mode_easter; uint16_t aux_param2;
_mode[FX_MODE_DYNAMIC] = &WS2812FX::mode_dynamic; uint8_t trans_act;
_mode[FX_MODE_RAINBOW] = &WS2812FX::mode_rainbow; } segment_runtime;
_mode[FX_MODE_RAINBOW_CYCLE] = &WS2812FX::mode_rainbow_cycle;
_mode[FX_MODE_SCAN] = &WS2812FX::mode_scan; WS2812FX() {
_mode[FX_MODE_DUAL_SCAN] = &WS2812FX::mode_dual_scan; _mode[FX_MODE_STATIC] = &WS2812FX::mode_static;
_mode[FX_MODE_FADE] = &WS2812FX::mode_fade; _mode[FX_MODE_BLINK] = &WS2812FX::mode_blink;
_mode[FX_MODE_THEATER_CHASE] = &WS2812FX::mode_theater_chase; _mode[FX_MODE_COLOR_WIPE] = &WS2812FX::mode_color_wipe;
_mode[FX_MODE_THEATER_CHASE_RAINBOW] = &WS2812FX::mode_theater_chase_rainbow; _mode[FX_MODE_COLOR_WIPE_RANDOM] = &WS2812FX::mode_color_wipe_random;
_mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_running_lights; _mode[FX_MODE_RANDOM_COLOR] = &WS2812FX::mode_random_color;
_mode[FX_MODE_TWINKLE] = &WS2812FX::mode_twinkle; _mode[FX_MODE_COLOR_SWEEP] = &WS2812FX::mode_color_sweep;
_mode[FX_MODE_TWINKLE_RANDOM] = &WS2812FX::mode_twinkle_random; _mode[FX_MODE_DYNAMIC] = &WS2812FX::mode_dynamic;
_mode[FX_MODE_TWINKLE_FADE] = &WS2812FX::mode_twinkle_fade; _mode[FX_MODE_RAINBOW] = &WS2812FX::mode_rainbow;
_mode[FX_MODE_TWINKLE_FADE_RANDOM] = &WS2812FX::mode_twinkle_fade_random; _mode[FX_MODE_RAINBOW_CYCLE] = &WS2812FX::mode_rainbow_cycle;
_mode[FX_MODE_SPARKLE] = &WS2812FX::mode_sparkle; _mode[FX_MODE_SCAN] = &WS2812FX::mode_scan;
_mode[FX_MODE_FLASH_SPARKLE] = &WS2812FX::mode_flash_sparkle; _mode[FX_MODE_DUAL_SCAN] = &WS2812FX::mode_dual_scan;
_mode[FX_MODE_HYPER_SPARKLE] = &WS2812FX::mode_hyper_sparkle; _mode[FX_MODE_FADE] = &WS2812FX::mode_fade;
_mode[FX_MODE_STROBE] = &WS2812FX::mode_strobe; _mode[FX_MODE_THEATER_CHASE] = &WS2812FX::mode_theater_chase;
_mode[FX_MODE_STROBE_RAINBOW] = &WS2812FX::mode_strobe_rainbow; _mode[FX_MODE_THEATER_CHASE_RAINBOW] = &WS2812FX::mode_theater_chase_rainbow;
_mode[FX_MODE_MULTI_STROBE] = &WS2812FX::mode_multi_strobe; _mode[FX_MODE_TWINKLE] = &WS2812FX::mode_twinkle;
_mode[FX_MODE_BLINK_RAINBOW] = &WS2812FX::mode_blink_rainbow; _mode[FX_MODE_TWINKLE_RANDOM] = &WS2812FX::mode_twinkle_random;
_mode[FX_MODE_ANDROID] = &WS2812FX::mode_android; _mode[FX_MODE_TWINKLE_FADE] = &WS2812FX::mode_twinkle_fade;
_mode[FX_MODE_CHASE_COLOR] = &WS2812FX::mode_chase_color; _mode[FX_MODE_TWINKLE_FADE_RANDOM] = &WS2812FX::mode_twinkle_fade_random;
_mode[FX_MODE_CHASE_RANDOM] = &WS2812FX::mode_chase_random; _mode[FX_MODE_SPARKLE] = &WS2812FX::mode_sparkle;
_mode[FX_MODE_CHASE_RAINBOW] = &WS2812FX::mode_chase_rainbow; _mode[FX_MODE_FLASH_SPARKLE] = &WS2812FX::mode_flash_sparkle;
_mode[FX_MODE_CHASE_FLASH] = &WS2812FX::mode_chase_flash; _mode[FX_MODE_HYPER_SPARKLE] = &WS2812FX::mode_hyper_sparkle;
_mode[FX_MODE_CHASE_FLASH_RANDOM] = &WS2812FX::mode_chase_flash_random; _mode[FX_MODE_STROBE] = &WS2812FX::mode_strobe;
_mode[FX_MODE_CHASE_RAINBOW_WHITE] = &WS2812FX::mode_chase_rainbow_white; _mode[FX_MODE_STROBE_RAINBOW] = &WS2812FX::mode_strobe_rainbow;
_mode[FX_MODE_COLORFUL] = &WS2812FX::mode_colorful; _mode[FX_MODE_MULTI_STROBE] = &WS2812FX::mode_multi_strobe;
_mode[FX_MODE_TRAFFIC_LIGHT] = &WS2812FX::mode_traffic_light; _mode[FX_MODE_BLINK_RAINBOW] = &WS2812FX::mode_blink_rainbow;
_mode[FX_MODE_COLOR_SWEEP_RANDOM] = &WS2812FX::mode_color_sweep_random; _mode[FX_MODE_ANDROID] = &WS2812FX::mode_android;
_mode[FX_MODE_RUNNING_COLOR] = &WS2812FX::mode_running_color; _mode[FX_MODE_CHASE_COLOR] = &WS2812FX::mode_chase_color;
_mode[FX_MODE_RUNNING_RED_BLUE] = &WS2812FX::mode_running_red_blue; _mode[FX_MODE_CHASE_RANDOM] = &WS2812FX::mode_chase_random;
_mode[FX_MODE_RUNNING_RANDOM] = &WS2812FX::mode_running_random; _mode[FX_MODE_CHASE_RAINBOW] = &WS2812FX::mode_chase_rainbow;
_mode[FX_MODE_LARSON_SCANNER] = &WS2812FX::mode_larson_scanner; _mode[FX_MODE_CHASE_FLASH] = &WS2812FX::mode_chase_flash;
_mode[FX_MODE_COMET] = &WS2812FX::mode_comet; _mode[FX_MODE_CHASE_FLASH_RANDOM] = &WS2812FX::mode_chase_flash_random;
_mode[FX_MODE_FIREWORKS] = &WS2812FX::mode_fireworks; _mode[FX_MODE_CHASE_RAINBOW_WHITE] = &WS2812FX::mode_chase_rainbow_white;
_mode[FX_MODE_FIREWORKS_RANDOM] = &WS2812FX::mode_fireworks_random; _mode[FX_MODE_COLORFUL] = &WS2812FX::mode_colorful;
_mode[FX_MODE_MERRY_CHRISTMAS] = &WS2812FX::mode_merry_christmas; _mode[FX_MODE_TRAFFIC_LIGHT] = &WS2812FX::mode_traffic_light;
_mode[FX_MODE_FIRE_FLICKER] = &WS2812FX::mode_fire_flicker; _mode[FX_MODE_COLOR_SWEEP_RANDOM] = &WS2812FX::mode_color_sweep_random;
_mode[FX_MODE_GRADIENT] = &WS2812FX::mode_gradient; _mode[FX_MODE_RUNNING_COLOR] = &WS2812FX::mode_running_color;
_mode[FX_MODE_LOADING] = &WS2812FX::mode_loading; _mode[FX_MODE_RUNNING_RED_BLUE] = &WS2812FX::mode_running_red_blue;
_mode[FX_MODE_RUNNING_RANDOM] = &WS2812FX::mode_running_random;
_mode[FX_MODE_LARSON_SCANNER] = &WS2812FX::mode_larson_scanner;
_mode[FX_MODE_COMET] = &WS2812FX::mode_comet;
_mode[FX_MODE_FIREWORKS] = &WS2812FX::mode_fireworks;
_mode[FX_MODE_FIREWORKS_RANDOM] = &WS2812FX::mode_fireworks_random;
_mode[FX_MODE_MERRY_CHRISTMAS] = &WS2812FX::mode_merry_christmas;
_mode[FX_MODE_FIRE_FLICKER] = &WS2812FX::mode_fire_flicker;
_mode[FX_MODE_GRADIENT] = &WS2812FX::mode_gradient;
_mode[FX_MODE_LOADING] = &WS2812FX::mode_loading;
_mode[FX_MODE_DUAL_COLOR_WIPE_IN_OUT] = &WS2812FX::mode_dual_color_wipe_in_out; _mode[FX_MODE_DUAL_COLOR_WIPE_IN_OUT] = &WS2812FX::mode_dual_color_wipe_in_out;
_mode[FX_MODE_DUAL_COLOR_WIPE_IN_IN] = &WS2812FX::mode_dual_color_wipe_in_in; _mode[FX_MODE_DUAL_COLOR_WIPE_IN_IN] = &WS2812FX::mode_dual_color_wipe_in_in;
_mode[FX_MODE_DUAL_COLOR_WIPE_OUT_OUT] = &WS2812FX::mode_dual_color_wipe_out_out; _mode[FX_MODE_DUAL_COLOR_WIPE_OUT_OUT] = &WS2812FX::mode_dual_color_wipe_out_out;
_mode[FX_MODE_DUAL_COLOR_WIPE_OUT_IN] = &WS2812FX::mode_dual_color_wipe_out_in; _mode[FX_MODE_DUAL_COLOR_WIPE_OUT_IN] = &WS2812FX::mode_dual_color_wipe_out_in;
_mode[FX_MODE_CIRCUS_COMBUSTUS] = &WS2812FX::mode_circus_combustus; _mode[FX_MODE_CIRCUS_COMBUSTUS] = &WS2812FX::mode_circus_combustus;
_mode[FX_MODE_CUSTOM_CHASE] = &WS2812FX::mode_cc_standard; _mode[FX_MODE_HALLOWEEN] = &WS2812FX::mode_halloween;
_mode[FX_MODE_CC_ON_RAINBOW] = &WS2812FX::mode_cc_rainbow; _mode[FX_MODE_TRICOLOR_CHASE] = &WS2812FX::mode_tricolor_chase;
_mode[FX_MODE_CC_ON_RAINBOW_CYCLE] = &WS2812FX::mode_cc_cycle; _mode[FX_MODE_TRICOLOR_WIPE] = &WS2812FX::mode_tricolor_wipe;
_mode[FX_MODE_CC_BLINK] = &WS2812FX::mode_cc_blink; _mode[FX_MODE_TRICOLOR_FADE] = &WS2812FX::mode_tricolor_fade;
_mode[FX_MODE_CC_RANDOM] = &WS2812FX::mode_cc_random; _mode[FX_MODE_BREATH] = &WS2812FX::mode_breath;
_mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_running_lights;
_mode[FX_MODE_LIGHTNING] = &WS2812FX::mode_lightning;
_mode[FX_MODE_ICU] = &WS2812FX::mode_icu;
_mode[FX_MODE_MULTI_COMET] = &WS2812FX::mode_multi_comet;
_mode[FX_MODE_DUAL_LARSON_SCANNER] = &WS2812FX::mode_dual_larson_scanner;
_mode[FX_MODE_RANDOM_CHASE] = &WS2812FX::mode_random_chase;
_mode[FX_MODE_OSCILLATE] = &WS2812FX::mode_oscillate;
_mode[FX_MODE_FIRE_2012] = &WS2812FX::mode_fire_2012;
_mode[FX_MODE_PRIDE_2015] = &WS2812FX::mode_pride_2015;
_mode[FX_MODE_BPM] = &WS2812FX::mode_bpm;
_mode[FX_MODE_JUGGLE] = &WS2812FX::mode_juggle;
_mode[FX_MODE_PALETTE] = &WS2812FX::mode_palette;
_mode[FX_MODE_COLORWAVES] = &WS2812FX::mode_colorwaves;
_mode[FX_MODE_FILLNOISE8] = &WS2812FX::mode_fillnoise8;
_mode[FX_MODE_NOISE16_1] = &WS2812FX::mode_noise16_1;
_mode[FX_MODE_NOISE16_2] = &WS2812FX::mode_noise16_2;
_mode[FX_MODE_NOISE16_3] = &WS2812FX::mode_noise16_3;
_mode[FX_MODE_NOISE16_4] = &WS2812FX::mode_noise16_4;
_mode_index = DEFAULT_MODE;
_speed = DEFAULT_SPEED;
_brightness = DEFAULT_BRIGHTNESS; _brightness = DEFAULT_BRIGHTNESS;
_running = false; _running = false;
_led_count = 255; _num_segments = 1;
_mode_last_call_time = 0; _segments[0].mode = DEFAULT_MODE;
_mode_delay = 0; _segments[0].colors[0] = DEFAULT_COLOR;
_color = DEFAULT_COLOR; _segments[0].start = 0;
_mode_color = DEFAULT_COLOR; _segments[0].speed = DEFAULT_SPEED;
_color_sec = 0;
_mode_var1 = 0;
_cc_fs = true;
_cc_fe = false;
_cc_is = 0;
_cc_i1 = 0;
_cc_i2 = 254;
_cc_num1 = 5;
_cc_num2 = 5;
_ccStep = 1;
_counter_mode_call = 0;
_counter_mode_step = 0;
_counter_ccStep = 0;
_fastStandard = false;
_reverseMode = false; _reverseMode = false;
_skipFirstMode = false; _skipFirstMode = false;
paletteFade = 0;
paletteBlend = 0;
_locked = NULL; _locked = NULL;
_cronixieDigits = new byte[6]; _cronixieDigits = new byte[6];
bus = new NeoPixelWrapper(); bus = new NeoPixelWrapper();
RESET_RUNTIME;
} }
void void
show(void), init(bool supportWhite, uint16_t countPixels, bool skipFirst),
setPixelColor(uint16_t i, byte r, byte g, byte b),
setPixelColor(uint16_t i, byte r, byte g, byte b, byte w),
init(bool supportWhite, uint16_t countPixels, uint8_t pin, bool skipFirst),
service(void), service(void),
start(void), clear(void),
stop(void), strip_off(void),
setMode(byte m), fade_out(uint8_t r),
setCustomChase(byte i1, uint16_t i2, byte is, byte np, byte ns, byte stp, bool fs, bool fe), setMode(uint8_t m),
setCCIndex1(byte i1), setSpeed(uint8_t s),
setCCIndex2(uint16_t i2), setIntensity(uint8_t i),
setCCStart(byte is), setPalette(uint8_t p),
setCCNum1(byte np), setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
setCCNum2(byte ns), setSecondaryColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
setCCStep(byte stp),
setCCFS(bool fs),
setCCFE(bool fe),
setSpeed(byte s),
setIntensity(byte in),
increaseSpeed(byte s),
decreaseSpeed(byte s),
setColor(byte r, byte g, byte b),
setColor(byte r, byte g, byte b, byte w),
setColor(uint32_t c), setColor(uint32_t c),
setSecondaryColor(byte r, byte g, byte b),
setSecondaryColor(byte r, byte g, byte b, byte w),
setSecondaryColor(uint32_t c), setSecondaryColor(uint32_t c),
setBrightness(byte b), setBrightness(uint8_t b),
increaseBrightness(byte s),
decreaseBrightness(byte s),
setReverseMode(bool b), setReverseMode(bool b),
driverModeCronixie(bool b), driverModeCronixie(bool b),
setCronixieDigits(byte* d), setCronixieDigits(byte* d),
setCronixieBacklight(bool b), setCronixieBacklight(bool b),
setIndividual(int i), setIndividual(uint16_t i, uint32_t col),
setIndividual(int i, uint32_t col), setRange(uint16_t i, uint16_t i2, uint32_t col),
setRange(int i, int i2), lock(uint16_t i),
setRange(int i, int i2, uint32_t col), lockRange(uint16_t i, uint16_t i2),
lock(int i), unlock(uint16_t i),
lockRange(int i, int i2), unlockRange(uint16_t i, uint16_t i2),
lockAll(void),
unlock(int i),
unlockRange(int i, int i2),
unlockAll(void), unlockAll(void),
setFastUpdateMode(bool b), setTransitionMode(bool t),
trigger(void), trigger(void),
setFade(int sp); setNumSegments(uint8_t n),
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint8_t speed, uint8_t intensity, bool reverse),
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint8_t speed, uint8_t intensity, bool reverse),
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint8_t speed, uint8_t intensity, uint8_t options),
resetSegments(),
setPixelColor(uint16_t n, uint32_t c),
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
show(void);
bool uint8_t
isRunning(void), paletteFade,
isLocked(int i); paletteBlend,
getBrightness(void),
byte
get_random_wheel_index(byte),
getMode(void), getMode(void),
getSpeed(void), getSpeed(void),
getIntensity(void), getNumSegments(void),
getBrightness(void), get_random_wheel_index(uint8_t);
getModeCount(void);
uint32_t uint32_t
color_wheel(byte), color_wheel(uint8_t),
color_blend(uint32_t,uint32_t,uint8_t),
getPixelColor(uint16_t),
getColor(void); getColor(void);
double double
getPowerEstimate(uint16_t leds, uint32_t c, byte b), getPowerEstimate(uint16_t leds, uint32_t c, byte b),
getSafePowerMultiplier(double safeMilliAmps, uint16_t leds, uint32_t c, byte b); getSafePowerMultiplier(double safeMilliAmps, uint16_t leds, uint32_t c, byte b);
private: WS2812FX::Segment
NeoPixelWrapper *bus; getSegment(void);
void WS2812FX::Segment_runtime
begin(bool supportWhite, uint16_t countPixels, uint8_t pin, bool skipFirst), getSegmentRuntime(void);
clear(void),
setPixelColor(uint16_t i, uint32_t c), WS2812FX::Segment*
setPixelColorRaw(uint16_t i, byte r, byte g, byte b, byte w), getSegments(void);
dofade(void),
strip_off(void), // mode helper functions
strip_off_respectLock(void), uint16_t
blink(uint32_t, uint32_t, bool strobe),
color_wipe(uint32_t, uint32_t, bool),
theater_chase(uint32_t, uint32_t),
twinkle(uint32_t),
twinkle_fade(uint32_t),
chase(uint32_t, uint32_t, uint32_t),
running(uint32_t, uint32_t),
fireworks(uint32_t),
tricolor_chase(uint32_t, uint32_t, uint32_t);
// builtin modes
uint16_t
mode_static(void), mode_static(void),
mode_blink(void), mode_blink(void),
mode_blink_rainbow(void),
mode_strobe(void),
mode_strobe_rainbow(void),
mode_color_wipe(void), mode_color_wipe(void),
mode_color_sweep(void),
mode_color_wipe_random(void), mode_color_wipe_random(void),
mode_color_sweep_random(void),
mode_random_color(void), mode_random_color(void),
mode_easter(void),
mode_dynamic(void), mode_dynamic(void),
mode_breath(void), mode_breath(void),
mode_fade(void), mode_fade(void),
@ -308,10 +385,7 @@ class WS2812FX {
mode_sparkle(void), mode_sparkle(void),
mode_flash_sparkle(void), mode_flash_sparkle(void),
mode_hyper_sparkle(void), mode_hyper_sparkle(void),
mode_strobe(void),
mode_strobe_rainbow(void),
mode_multi_strobe(void), mode_multi_strobe(void),
mode_blink_rainbow(void),
mode_android(void), mode_android(void),
mode_chase_color(void), mode_chase_color(void),
mode_chase_random(void), mode_chase_random(void),
@ -320,9 +394,7 @@ class WS2812FX {
mode_chase_flash_random(void), mode_chase_flash_random(void),
mode_chase_rainbow_white(void), mode_chase_rainbow_white(void),
mode_colorful(void), mode_colorful(void),
mode_colorful_internal(uint32_t*),
mode_traffic_light(void), mode_traffic_light(void),
mode_color_sweep_random(void),
mode_running_color(void), mode_running_color(void),
mode_running_red_blue(void), mode_running_red_blue(void),
mode_running_random(void), mode_running_random(void),
@ -331,6 +403,7 @@ class WS2812FX {
mode_fireworks(void), mode_fireworks(void),
mode_fireworks_random(void), mode_fireworks_random(void),
mode_merry_christmas(void), mode_merry_christmas(void),
mode_halloween(void),
mode_fire_flicker(void), mode_fire_flicker(void),
mode_gradient(void), mode_gradient(void),
mode_loading(void), mode_loading(void),
@ -339,67 +412,65 @@ class WS2812FX {
mode_dual_color_wipe_out_out(void), mode_dual_color_wipe_out_out(void),
mode_dual_color_wipe_out_in(void), mode_dual_color_wipe_out_in(void),
mode_circus_combustus(void), mode_circus_combustus(void),
mode_cc_core(void), mode_bicolor_chase(void),
mode_cc_standard(void), mode_tricolor_chase(void),
mode_cc_rainbow(void), mode_tricolor_wipe(void),
mode_cc_cycle(void), mode_tricolor_fade(void),
mode_cc_blink(void), mode_icu(void),
mode_cc_random(void); mode_multi_comet(void),
mode_dual_larson_scanner(void),
mode_random_chase(void),
mode_oscillate(void),
mode_fire_2012(void),
mode_pride_2015(void),
mode_bpm(void),
mode_juggle(void),
mode_palette(void),
mode_colorwaves(void),
mode_fillnoise8(void),
mode_noise16_1(void),
mode_noise16_2(void),
mode_noise16_3(void),
mode_noise16_4(void),
mode_lightning(void);
bool private:
_triggered, NeoPixelWrapper *bus;
_rgbwMode,
_skipFirstMode, uint16_t _length;
_fastStandard, uint16_t _rand16seed;
_reverseMode, uint8_t _brightness;
_cronixieMode,
_cronixieBacklightEnabled,
_cc_fs,
_cc_fe,
_running;
bool* void handle_palette(void);
_locked;
byte
_mode_index,
_speed,
_intensity,
_cc_i1,
_cc_is,
_cc_num1,
_cc_num2,
_ccStep,
_brightness;
byte*
_cronixieDigits;
uint16_t
minval(uint16_t v, uint16_t w),
maxval(uint16_t v, uint16_t w),
_cc_i2,
_led_count;
uint32_t
getPixelColor(uint16_t i),
_color,
_color_sec,
_counter_mode_call,
_counter_mode_step,
_counter_ccStep,
_mode_var1,
_mode_color,
_mode_delay;
double double
_cronixieSecMultiplier; _cronixieSecMultiplier;
unsigned long boolean
_mode_last_call_time; _running,
_rgbwMode,
_reverseMode,
_cronixieMode,
_cronixieBacklightEnabled,
_skipFirstMode,
_triggered;
mode_ptr byte* _locked;
_mode[MODE_COUNT]; byte* _cronixieDigits;
mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element
uint32_t _lastPaletteChange = 0;
uint8_t _segment_index = 0;
uint8_t _segment_index_palette_last = 99;
uint8_t _num_segments = 1;
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 20 bytes per element
// start, stop, speed, intensity, mode, options, color[]
{ 0, 7, DEFAULT_SPEED, 128, FX_MODE_STATIC, NO_OPTIONS, {DEFAULT_COLOR}}
};
segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 17 bytes per element
}; };
#endif #endif

View File

@ -2,7 +2,7 @@
<html> <html>
<head><meta charset="utf-8"><meta name="theme-color" content="#fff"> <head><meta charset="utf-8"><meta name="theme-color" content="#fff">
<link rel='shortcut icon' type='image/x-icon' href='/favicon.ico'/> <link rel='shortcut icon' type='image/x-icon' href='/favicon.ico'/>
<title>WLED 0.7.1</title> <title>WLED 0.8.0</title>
<script> <script>
var d=document; var d=document;
var w=window.getComputedStyle(d.querySelector("html")); var w=window.getComputedStyle(d.querySelector("html"));
@ -58,6 +58,7 @@
uwv = false; uwv = false;
} }
Cf.TX.selectedIndex = this.responseXML.getElementsByTagName('fx')[0].childNodes[0].nodeValue; Cf.TX.selectedIndex = this.responseXML.getElementsByTagName('fx')[0].childNodes[0].nodeValue;
Cf.FP.selectedIndex = this.responseXML.getElementsByTagName('fp')[0].childNodes[0].nodeValue;
d.Cf.SX.value = this.responseXML.getElementsByTagName('sx')[0].childNodes[0].nodeValue; d.Cf.SX.value = this.responseXML.getElementsByTagName('sx')[0].childNodes[0].nodeValue;
d.Cf.IX.value = this.responseXML.getElementsByTagName('ix')[0].childNodes[0].nodeValue; d.Cf.IX.value = this.responseXML.getElementsByTagName('ix')[0].childNodes[0].nodeValue;
nla = (this.responseXML.getElementsByTagName('nl')[0].innerHTML)!=0?true:false; nla = (this.responseXML.getElementsByTagName('nl')[0].innerHTML)!=0?true:false;
@ -120,16 +121,9 @@
d.Cf.SB.value=b; d.Cf.SB.value=b;
GC(); GC();
} }
function GetCC() function GP()
{ {
resp+="&CP="; resp+= "&FP=" + Cf.FP.selectedIndex;
resp+=d.Cf.PF.value;
resp+="&CS=";
resp+=d.Cf.SF.value;
resp+="&CM=";
resp+=d.Cf.HF.value;
resp+=(d.Cf.SC.checked)?"&CF=1":"&CF=0";
resp+=(d.Cf.EC.checked)?"&CE=1":"&CE=0";
GIO(); GIO();
} }
function CV(v) function CV(v)
@ -178,8 +172,8 @@
case 3: gId("path1").style.fill = aC; gId("path2").style.fill = aC; case 3: gId("path1").style.fill = aC; gId("path2").style.fill = aC;
} }
tgb.style.fill=(Cf.SA.value>0)?aC:dC; tgb.style.fill=(Cf.SA.value>0)?aC:dC;
ccX.style.display=(Cf.TX.selectedIndex>52)?"block":"none"; fpX.style.display=(Cf.TX.selectedIndex>64)?"block":"none";
fof.style.fill=(Cf.TX.selectedIndex>52)?aC:dC; fof.style.fill=(Cf.TX.selectedIndex>64)?aC:dC;
fmr.style.fill=(Cf.TX.selectedIndex<1)?aC:dC; fmr.style.fill=(Cf.TX.selectedIndex<1)?aC:dC;
} }
function TgT() function TgT()
@ -198,10 +192,10 @@
function SwFX(s) function SwFX(s)
{ {
var n=Cf.TX.selectedIndex+s; var n=Cf.TX.selectedIndex+s;
if (n==-1||n==58) return; if (n==-1||n==74) return;
Cf.TX.selectedIndex =n; Cf.TX.selectedIndex =n;
if (n < 0) Cf.TX.selectedIndex = 0; if (n < 0) Cf.TX.selectedIndex = 0;
if (n > 57) Cf.TX.selectedIndex = 53; if (n > 73) Cf.TX.selectedIndex = 65;
GX(); GX();
} }
function TgHSB() function TgHSB()
@ -598,7 +592,7 @@
<option value="3">Wipe (3)</option> <option value="3">Wipe (3)</option>
<option value="4">Wipe Random (4)</option> <option value="4">Wipe Random (4)</option>
<option value="5">Color R (5)</option> <option value="5">Color R (5)</option>
<option value="6">Easter (6)</option> <option value="6">Sweep (6)</option>
<option value="7">Dynamic (7)</option> <option value="7">Dynamic (7)</option>
<option value="8">Colorloop (8)</option> <option value="8">Colorloop (8)</option>
<option value="9">Rainbow (9)</option> <option value="9">Rainbow (9)</option>
@ -645,11 +639,27 @@
<option value="50">Wipe OO (50)</option> <option value="50">Wipe OO (50)</option>
<option value="51">Wipe OI (51)</option> <option value="51">Wipe OI (51)</option>
<option value="52">Circus (52)</option> <option value="52">Circus (52)</option>
<option value="53">Custom Chase (53)</option> <option value="53">Halloween (53)</option>
<option value="54">CC Colorloop (54)</option> <option value="54">Tricolor Chase (54)</option>
<option value="55">CC Rainbow (55)</option> <option value="55">Tricolor Wipe (55)</option>
<option value="56">CC Blink (56)</option> <option value="56">Tricolor Fade (56)</option>
<option value="57">CC Random (57)</option> <option value="57">Lighting (57)</option>
<option value="58">ICU (58)</option>
<option value="59">Multi Comet (59)</option>
<option value="60">Scanner x2 (60)</option>
<option value="61">Random Chase (61)</option>
<option value="62">Oscillate (62)</option>
<option value="63">Pride 2015 (63)</option>
<option value="64">Juggle (64)</option>
<option value="65">Palette (65)</option>
<option value="66">Fire 2012 (66)</option>
<option value="67">Colorwaves (67)</option>
<option value="68">BPM (68)</option>
<option value="69">Fill Noise 8 (69)</option>
<option value="70">Noise 16 1 (70)</option>
<option value="71">Noise 16 2 (71)</option>
<option value="72">Noise 16 3 (72)</option>
<option value="73">Noise 16 4 (73)</option>
</select><br><br> </select><br><br>
Set secondary color to Set secondary color to
<button type="button" onclick="CS(0)">White</button> <button type="button" onclick="CS(0)">White</button>
@ -658,12 +668,55 @@
<button type="button" onclick="CS(3)">Primary</button> <button type="button" onclick="CS(3)">Primary</button>
<button type="button" onclick="CS(4)">Swap P/S</button> <button type="button" onclick="CS(4)">Swap P/S</button>
or <button type="button" onclick="CS(5)">Set Primary to Random</button> or <button type="button" onclick="CS(5)">Set Primary to Random</button>
<div id="ccX"> <div id="fpX">
<br>Custom Theater Chase<br> <br>FastLED Palette<br><br>
using <input id="ccP" name="PF" type="number" value="2" min="0" max="255" step="1" onchange="GetCC()"> primary and <select name="FP" onchange="GP()">
<input id="ccS" name ="SF" type="number" value="4" min="0" max="255" step="1" onchange="GetCC()"> secondary color LEDs,<br> <option value="0" selected>Default</option>
doing <input id="ccH" name="HF" type="number" value="1" min="0" max="255" step="1" onchange="GetCC()"> steps per tick, <option value="1">Random Cycle</option>
from <input type="checkbox" onchange="GetCC()" name="SC"> start and <input type="checkbox" onchange="GetCC()" name="EC"> end. <option value="2">Primary Color Only</option>
<option value="3">Based on Primary</option>
<option value="4">Set Colors Only</option>
<option value="5">Based on Set Colors</option>
<option value="6">Party</option>
<option value="7">Cloud</option>
<option value="8">Lava</option>
<option value="9">Ocean</option>
<option value="10">Forest</option>
<option value="11">Rainbow</option>
<option value="12">Rainbow Stripe</option>
<option value="13">Sunset</option>
<option value="14">Rivendell</option>
<option value="15">Breeze</option>
<option value="16">Red & Blue</option>
<option value="17">Yellowout</option>
<option value="18">Analogous</option>
<option value="19">Splash</option>
<option value="20">Pastel</option>
<option value="21">Sunset2</option>
<option value="22">Beech</option>
<option value="23">Vintage</option>
<option value="24">Departure</option>
<option value="25">Landscape</option>
<option value="26">Beach</option>
<option value="27">Sherbet</option>
<option value="28">Hult</option>
<option value="29">Hult64</option>
<option value="30">Drywet</option>
<option value="31">Jul</option>
<option value="32">Grintage</option>
<option value="33">Rewhi</option>
<option value="34">Tertiary</option>
<option value="35">Fire</option>
<option value="36">Icefire</option>
<option value="37">Cyane</option>
<option value="38">Light Pink</option>
<option value="39">Autumn</option>
<option value="40">Magenta</option>
<option value="41">Magred</option>
<option value="42">Yelmag</option>
<option value="43">Yelblu</option>
<option value="44">Orange & Teal</option>
</select>
</div> </div>
<div id="slX" class="sl"> <div id="slX" class="sl">
<input type="range" title="Effect Speed" class="sds" name="SX" value="0" min="0" max="255" step="1" onchange="GX()"></div> <input type="range" title="Effect Speed" class="sds" name="SX" value="0" min="0" max="255" step="1" onchange="GX()"></div>

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,14 @@
/* /*
* Settings html * Settings html
*/ */
//common CSS of settings pages
const char PAGE_settingsCss[] PROGMEM = R"=====( const char PAGE_settingsCss[] PROGMEM = R"=====(
body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol);color:var(--tCol);line-height:200%;margin:0;background-attachment:fixed}hr{border-color:var(--dCol);filter:drop-shadow(-5px -5px 5px var(--sCol))}button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:20px;margin:8px;margin-top:12px}.helpB{text-align:left;position:absolute;width:60px}input{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.5ch solid var(--bCol);filter:drop-shadow(-5px -5px 5px var(--sCol))}input[type=number]{width:3em}select{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:0.5ch solid var(--bCol);filter:drop-shadow( -5px -5px 5px var(--sCol) );}</style> body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol);color:var(--tCol);line-height:200%;margin:0;background-attachment:fixed}hr{border-color:var(--dCol);filter:drop-shadow(-5px -5px 5px var(--sCol))}button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:20px;margin:8px;margin-top:12px}.helpB{text-align:left;position:absolute;width:60px}input{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.5ch solid var(--bCol);filter:drop-shadow(-5px -5px 5px var(--sCol))}input[type=number]{width:3em}select{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:0.5ch solid var(--bCol);filter:drop-shadow( -5px -5px 5px var(--sCol) );}</style>
)====="; )=====";
//settings menu
const char PAGE_settings0[] PROGMEM = R"=====( const char PAGE_settings0[] PROGMEM = R"=====(
<!DOCTYPE html> <!DOCTYPE html>
<html><head><title>WLED Settings</title> <html><head><title>WLED Settings</title>
@ -26,11 +30,14 @@ body{text-align:center;background:var(--cCol);height:100%;margin:0;background-at
</html> </html>
)====="; )=====";
//wifi settings
const char PAGE_settings_wifi0[] PROGMEM = R"=====( const char PAGE_settings_wifi0[] PROGMEM = R"=====(
<!DOCTYPE html> <!DOCTYPE html>
<html><head> <html><head>
<title>WiFi Settings</title><script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#wifi-settings");}function B(){window.history.back();}function GetV(){var d = document; <title>WiFi Settings</title><script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#wifi-settings");}function B(){window.history.back();}function GetV(){var d = document;
)====="; )=====";
const char PAGE_settings_wifi1[] PROGMEM = R"=====( const char PAGE_settings_wifi1[] PROGMEM = R"=====(
</head> </head>
<body onload="GetV()"> <body onload="GetV()">
@ -72,11 +79,14 @@ AP IP: <span class="sip"> Not active </span><hr>
</html> </html>
)====="; )=====";
//LED settings
const char PAGE_settings_leds0[] PROGMEM = R"=====( const char PAGE_settings_leds0[] PROGMEM = R"=====(
<!DOCTYPE html> <!DOCTYPE html>
<html><head> <html><head>
<title>LED Settings</title><script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#led-settings");}function B(){window.history.back();}function GetV(){var d = document; <title>LED Settings</title><script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#led-settings");}function B(){window.history.back();}function GetV(){var d = document;
)====="; )=====";
const char PAGE_settings_leds1[] PROGMEM = R"=====( const char PAGE_settings_leds1[] PROGMEM = R"=====(
</head> </head>
<body onload="GetV()"> <body onload="GetV()">
@ -86,7 +96,10 @@ const char PAGE_settings_leds1[] PROGMEM = R"=====(
<h2>LED setup</h2> <h2>LED setup</h2>
LED count: <input name="LC" type="number" min="1" max="1200" required><br> LED count: <input name="LC" type="number" min="1" max="1200" required><br>
LEDs are 4-channel type (RGBW): <input type="checkbox" name="EW"><br> LEDs are 4-channel type (RGBW): <input type="checkbox" name="EW"><br>
<br>
Apply preset <input name="BP" type="number" min="0" max="25" required> at boot (0 uses defaults)<br> Apply preset <input name="BP" type="number" min="0" max="25" required> at boot (0 uses defaults)<br>
Turn on after power up/reset: <input type="checkbox" name="BO"><br>
<br>
Default RGB color: Default RGB color:
<input name="CR" type="number" min="0" max="255" required> <input name="CR" type="number" min="0" max="255" required>
<input name="CG" type="number" min="0" max="255" required> <input name="CG" type="number" min="0" max="255" required>
@ -97,6 +110,7 @@ Default brightness: <input name="CA" type="number" min="0" max="255" required> (
Default effect ID: <input name="FX" type="number" min="0" max="57" required><br> Default effect ID: <input name="FX" type="number" min="0" max="57" required><br>
Default effect speed: <input name="SX" type="number" min="0" max="255" required><br> Default effect speed: <input name="SX" type="number" min="0" max="255" required><br>
Default effect intensity: <input name="IX" type="number" min="0" max="255" required><br> Default effect intensity: <input name="IX" type="number" min="0" max="255" required><br>
Default effect palette: <input name="FP" type="number" min="0" max="255" required><br>
Default secondary RGB(W):<br> Default secondary RGB(W):<br>
<input name="SR" type="number" min="0" max="255" required> <input name="SR" type="number" min="0" max="255" required>
<input name="SG" type="number" min="0" max="255" required> <input name="SG" type="number" min="0" max="255" required>
@ -104,20 +118,27 @@ Default secondary RGB(W):<br>
<input name="SW" type="number" min="0" max="255" required><br> <input name="SW" type="number" min="0" max="255" required><br>
Ignore and use current color, brightness and effects: <input type="checkbox" name="IS"><br> Ignore and use current color, brightness and effects: <input type="checkbox" name="IS"><br>
Save current preset cycle configuration as boot default: <input type="checkbox" name="PC"><br> Save current preset cycle configuration as boot default: <input type="checkbox" name="PC"><br>
Turn on after power up/reset: <input type="checkbox" name="BO"><br> <br>
Use Gamma correction for brightness: <input type="checkbox" name="GB"><br> Use Gamma correction for color: <input type="checkbox" name="GC"> (strongly recommended)<br>
Use Gamma correction for color: <input type="checkbox" name="GC"><br> Use Gamma correction for brightness: <input type="checkbox" name="GB"> (not recommended)<br>
Brightness factor: <input name="BF" type="number" min="0" max="255" required> % Brightness factor: <input name="BF" type="number" min="0" max="255" required> %
<h3>Transitions</h3> <h3>Transitions</h3>
Fade: <input type="checkbox" name="TF"><br> Crossfade: <input type="checkbox" name="TF"><br>
Sweep: <input type="checkbox" name="TS"> Invert direction: <input type="checkbox" name="TI"><br>
Transition Time: <input name="TD" maxlength="5" size="2"> ms<br> Transition Time: <input name="TD" maxlength="5" size="2"> ms<br>
Enable transition for secondary color: <input type="checkbox" name="T2"><br> Enable transition for secondary color: <input type="checkbox" name="T2"><br>
Enable Palette transitions: <input type="checkbox" name="PF">
<h3>Timed light</h3> <h3>Timed light</h3>
Default Duration: <input name="TL" type="number" min="1" max="255" required> min<br> Default Duration: <input name="TL" type="number" min="1" max="255" required> min<br>
Default Target brightness: <input name="TB" type="number" min="0" max="255" required><br> Default Target brightness: <input name="TB" type="number" min="0" max="255" required><br>
Fade down: <input type="checkbox" name="TW"><br> Fade down: <input type="checkbox" name="TW"><br>
<h3>Advanced</h3> <h3>Advanced</h3>
Palette blending:
<select name="PB">
<option value="0">Linear (wrap if moving)</option>
<option value="1">Linear (always wrap)</option>
<option value="2">Linear (never wrap)</option>
<option value="3">None (not recommended)</option>
</select><br>
Reverse LED order (rotate 180): <input type="checkbox" name="RV"><br> Reverse LED order (rotate 180): <input type="checkbox" name="RV"><br>
Init LEDs after WiFi: <input type="checkbox" name="EI"><br> Init LEDs after WiFi: <input type="checkbox" name="EI"><br>
Skip first LED: <input type="checkbox" name="SL"><hr> Skip first LED: <input type="checkbox" name="SL"><hr>
@ -127,12 +148,15 @@ Skip first LED: <input type="checkbox" name="SL"><hr>
</html> </html>
)====="; )=====";
//User Interface settings
const char PAGE_settings_ui0[] PROGMEM = R"=====( const char PAGE_settings_ui0[] PROGMEM = R"=====(
<!DOCTYPE html> <!DOCTYPE html>
<html><head> <html><head>
<title>UI Settings</title><script> <title>UI Settings</title><script>
function gId(s){return document.getElementById(s);}function S(){GetV();Ct();}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#user-interface-settings");}function B(){window.history.back();}function Ct(){if (gId("co").selected){gId("cth").style.display="block";}else{gId("cth").style.display="none";}}function GetV(){var d = document; function gId(s){return document.getElementById(s);}function S(){GetV();Ct();}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#user-interface-settings");}function B(){window.history.back();}function Ct(){if (gId("co").selected){gId("cth").style.display="block";}else{gId("cth").style.display="none";}}function GetV(){var d = document;
)====="; )=====";
const char PAGE_settings_ui1[] PROGMEM = R"=====( const char PAGE_settings_ui1[] PROGMEM = R"=====(
</head> </head>
<body onload="S()"> <body onload="S()">
@ -184,11 +208,14 @@ Make sure the font you use is installed on your system!<br>
</html> </html>
)====="; )=====";
//sync settings
const char PAGE_settings_sync0[] PROGMEM = R"=====( const char PAGE_settings_sync0[] PROGMEM = R"=====(
<!DOCTYPE html> <!DOCTYPE html>
<html><head><title>Sync Settings</title> <html><head><title>Sync Settings</title>
<script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#sync-settings");}function B(){window.open("/settings","_self");}function GetV(){var d = document; <script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#sync-settings");}function B(){window.open("/settings","_self");}function GetV(){var d = document;
)====="; )=====";
const char PAGE_settings_sync1[] PROGMEM = R"=====( const char PAGE_settings_sync1[] PROGMEM = R"=====(
</head> </head>
<body onload="GetV()"> <body onload="GetV()">
@ -223,6 +250,11 @@ Alexa invocation name: <input name="AI" maxlength="32">
<h3>Blynk</h3> <h3>Blynk</h3>
Device Auth token: <input name="BK" maxlength="33"><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> <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>
Broker: <input name="MS" maxlength="32"><br>
Device Topic: <input name="MD" maxlength="32"><br>
Group Topic: <input name="MG" maxlength="32"><br>
<i>Reboot required to apply changes. </i><a href="https://github.com/Aircoookie/WLED/wiki/MQTT" target="_blank">MQTT info</a>
<h3>Philips Hue</h3> <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> <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> 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>
@ -241,11 +273,14 @@ Hue status: <span class="hms"> Internal ESP Error! </span><hr>
</html> </html>
)====="; )=====";
//time and macro settings
const char PAGE_settings_time0[] PROGMEM = R"=====( const char PAGE_settings_time0[] PROGMEM = R"=====(
<!DOCTYPE html> <!DOCTYPE html>
<html><head><title>Time Settings</title> <html><head><title>Time Settings</title>
<script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#time-settings");}function B(){window.open("/settings","_self");}function S(){GetV();Cs();}function gId(s){return document.getElementById(s);}function Cs(){gId("cac").style.display="none";gId("coc").style.display="block";gId("ccc").style.display="none";if (gId("ca").selected){gId("cac").style.display="block";}if (gId("cc").selected){gId("coc").style.display="none";gId("ccc").style.display="block";}if (gId("cn").selected){gId("coc").style.display="none";}}function GetV(){var d = document; <script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#time-settings");}function B(){window.open("/settings","_self");}function S(){GetV();Cs();}function gId(s){return document.getElementById(s);}function Cs(){gId("cac").style.display="none";gId("coc").style.display="block";gId("ccc").style.display="none";if (gId("ca").selected){gId("cac").style.display="block";}if (gId("cc").selected){gId("coc").style.display="none";gId("ccc").style.display="block";}if (gId("cn").selected){gId("coc").style.display="none";}}function GetV(){var d = document;
)====="; )=====";
const char PAGE_settings_time1[] PROGMEM = R"=====( const char PAGE_settings_time1[] PROGMEM = R"=====(
</head> </head>
<body onload="S()"> <body onload="S()">
@ -278,10 +313,9 @@ Current local time is <span class="times">unknown</span>.
Clock Overlay: Clock Overlay:
<select name="OL" onchange="Cs()"> <select name="OL" onchange="Cs()">
<option value="0" id="cn" selected>None</option> <option value="0" id="cn" selected>None</option>
<option value="1">Static color</option> <option value="1" id="ca">Analog Clock</option>
<option value="2" id="ca">Analog Clock</option> <option value="2">Single Digit Clock</option>
<option value="3">Single Digit Clock</option> <option value="3" id="cc">Cronixie Clock</option>
<option value="4" id="cc">Cronixie Clock</option>
</select><br> </select><br>
<div id="coc"> <div id="coc">
First LED: <input name="O1" type="number" min="0" max="255" required> Last LED: <input name="O2" type="number" min="0" max="255" required><br> First LED: <input name="O1" type="number" min="0" max="255" required> Last LED: <input name="O2" type="number" min="0" max="255" required><br>
@ -316,24 +350,43 @@ Define API macros here:<br>
15: <input name="M15" maxlength="64"><br> 15: <input name="M15" maxlength="64"><br>
16: <input name="M16" maxlength="64"><br><br> 16: <input name="M16" maxlength="64"><br><br>
<i>Use 0 for the default action instead of a macro</i><br> <i>Use 0 for the default action instead of a macro</i><br>
Time controlled macros coming soon!<br>
Boot Macro: <input name="MB" type="number" min="0" max="16" required><br> Boot Macro: <input name="MB" type="number" min="0" max="16" required><br>
Alexa On/Off Macros: <input name="A0" type="number" min="0" max="16" required> <input name="A1" type="number" min="0" max="16" required><br> Alexa On/Off Macros: <input name="A0" type="number" min="0" max="16" required> <input name="A1" type="number" min="0" max="16" required><br>
Button Macro: <input name="MP" type="number" min="0" max="16" required> Long Press: <input name="ML" type="number" min="0" max="16" required><br> Button Macro: <input name="MP" type="number" min="0" max="16" required> Long Press: <input name="ML" type="number" min="0" max="16" required><br>
Countdown-Over Macro: <input name="MC" type="number" min="0" max="16" required><br> Countdown-Over Macro: <input name="MC" type="number" min="0" max="16" required><br>
Timed-Light-Over Macro: <input name="MN" type="number" min="0" max="16" required><hr> Timed-Light-Over Macro: <input name="MN" type="number" min="0" max="16" required><br>
Time-Controlled Macros (Hours/Minutes &gt; Macro):<br>
<input name="H0" type="number" min="0" max="24"> <input name="N0" type="number" min="0" max="59">
&gt; <input name="T0" type="number" min="0" max="16"><br>
<input name="H1" type="number" min="0" max="24"> <input name="N1" type="number" min="0" max="59">
&gt; <input name="T1" type="number" min="0" max="16"><br>
<input name="H2" type="number" min="0" max="24"> <input name="N2" type="number" min="0" max="59">
&gt; <input name="T2" type="number" min="0" max="16"><br>
<input name="H3" type="number" min="0" max="24"> <input name="N3" type="number" min="0" max="59">
&gt; <input name="T3" type="number" min="0" max="16"><br>
<input name="H4" type="number" min="0" max="24"> <input name="N4" type="number" min="0" max="59">
&gt; <input name="T4" type="number" min="0" max="16"><br>
<input name="H5" type="number" min="0" max="24"> <input name="N5" type="number" min="0" max="59">
&gt; <input name="T5" type="number" min="0" max="16"><br>
<input name="H6" type="number" min="0" max="24"> <input name="N6" type="number" min="0" max="59">
&gt; <input name="T6" type="number" min="0" max="16"><br>
<input name="H7" type="number" min="0" max="24"> <input name="N7" type="number" min="0" max="59">
&gt; <input name="T7" type="number" min="0" max="16"><hr>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button> <button type="button" onclick="B()">Back</button><button type="submit">Save</button>
</form> </form>
</body> </body>
</html> </html>
)====="; )=====";
//security settings and about
const char PAGE_settings_sec0[] PROGMEM = R"=====( const char PAGE_settings_sec0[] PROGMEM = R"=====(
<!DOCTYPE html> <!DOCTYPE html>
<html><head> <html><head>
<title>Misc Settings</title> <title>Misc Settings</title>
<script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#security-settings");}function B(){window.open("/settings","_self");}function U(){window.open("/update","_self");}function GetV(){var d = document; <script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#security-settings");}function B(){window.open("/settings","_self");}function U(){window.open("/update","_self");}function GetV(){var d = document;
)====="; )=====";
const char PAGE_settings_sec1[] PROGMEM = R"=====( const char PAGE_settings_sec1[] PROGMEM = R"=====(
</head> </head>
<body onload="GetV()"> <body onload="GetV()">
@ -358,7 +411,7 @@ HTTP traffic is unencrypted. An attacker in the same network can intercept form
<button type="button" onclick="U()">Manual OTA Update</button><br> <button type="button" onclick="U()">Manual OTA Update</button><br>
Enable ArduinoOTA: <input type="checkbox" name="AO"><br> Enable ArduinoOTA: <input type="checkbox" name="AO"><br>
<h3>About</h3> <h3>About</h3>
<a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.7.1<br><br> <a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.8.0<br><br>
<b>Contributors:</b><br> <b>Contributors:</b><br>
StormPie <i>(Mobile HTML UI)</i><br><br> StormPie <i>(Mobile HTML UI)</i><br><br>
Thank you so much!<br><br> Thank you so much!<br><br>
@ -366,11 +419,14 @@ Thank you so much!<br><br>
<i>Licensed under the MIT license</i><br><br> <i>Licensed under the MIT license</i><br><br>
<b>Uses libraries:</b><br> <b>Uses libraries:</b><br>
<i>ESP8266/ESP32 Arduino Core</i><br> <i>ESP8266/ESP32 Arduino Core</i><br>
<i><a href="https://github.com/svenihoney/NeoPixelBus" target="_blank">NeoPixelBus</a> by Makuna (svenihoney fork)</i><br>
<i><a href="https://github.com/FastLED/FastLED/" target="_blank">FastLED</a> library</i><br>
<i>(ESP32) <a href="https://github.com/bbx10/WebServer_tng" target="_blank">WebServer_tng</a> by bbx10</i><br> <i>(ESP32) <a href="https://github.com/bbx10/WebServer_tng" target="_blank">WebServer_tng</a> by bbx10</i><br>
<i><a href="https://github.com/kitesurfer1404/WS2812FX" target="_blank">WS2812FX</a> by kitesurfer1404 (modified)</i><br> <i><a href="https://github.com/kitesurfer1404/WS2812FX" target="_blank">WS2812FX</a> by kitesurfer1404 (modified)</i><br>
<i><a href="https://github.com/JChristensen/Timezone" target="_blank">Timezone</a> library by JChristensen</i><br> <i><a href="https://github.com/JChristensen/Timezone" target="_blank">Timezone</a> library by JChristensen</i><br>
<i><a href="https://github.com/blynkkk/blynk-library" target="_blank">Blynk</a> library (compacted)</i><br> <i><a href="https://github.com/blynkkk/blynk-library" target="_blank">Blynk</a> library (compacted)</i><br>
<i><a href="https://github.com/forkineye/E131" target="_blank">E1.31</a> library by forkineye (modified)</i><br> <i><a href="https://github.com/forkineye/E131" target="_blank">E1.31</a> library by forkineye (modified)</i><br>
<i><a href="https://github.com/knolleary/pubsubclient" target="_blank">PubSubClient</a> by knolleary (modified)</i><br>
<i><a href="https://github.com/Aircoookie/Espalexa" target="_blank">Espalexa</a> by Aircoookie (modified)</i><br><br> <i><a href="https://github.com/Aircoookie/Espalexa" target="_blank">Espalexa</a> by Aircoookie (modified)</i><br><br>
<i>UI icons by <a href="https://linearicons.com" target="_blank">Linearicons</a> created by <a href="https://perxis.com" target="_blank">Perxis</a>! (CC-BY-SA 4.0)</i> <br><br> <i>UI icons by <a href="https://linearicons.com" target="_blank">Linearicons</a> created by <a href="https://perxis.com" target="_blank">Perxis</a>! (CC-BY-SA 4.0)</i> <br><br>
Server message: <span class="msg"> Response error! </span><hr> Server message: <span class="msg"> Response error! </span><hr>

View File

@ -1,27 +1,36 @@
//USER HTML /*
* Various pages
*/
//USER HTML HERE (/u subpage)
const char PAGE_usermod[] PROGMEM = R"=====( const char PAGE_usermod[] PROGMEM = R"=====(
<html><body>There is no usermod installed or it doesn't specify a custom web page.</body></html> <html><body>There is no usermod installed or it doesn't specify a custom web page.</body></html>
)====="; )=====";
/*
* Various
*/ //server message
const char PAGE_msg0[] PROGMEM = R"=====( const char PAGE_msg0[] PROGMEM = R"=====(
<!DOCTYPE html> <!DOCTYPE html>
<html><head> <html><head>
<title>WLED Message</title> <title>WLED Message</title>
<script>function B(){window.history.back()};function RS(){window.location = "/settings";}function RP(){top.location.href="/";}</script> <script>function B(){window.history.back()};function RS(){window.location = "/settings";}function RP(){top.location.href="/";}</script>
)====="; )=====";
const char PAGE_msg1[] PROGMEM = R"=====( const char PAGE_msg1[] PROGMEM = R"=====(
button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:20px;margin:8px;margin-top:12px}body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol);color:var(--tCol);line-height:200%;margin:0;background-attachment:fixed}</style> button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:20px;margin:8px;margin-top:12px}body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol);color:var(--tCol);line-height:200%;margin:0;background-attachment:fixed}</style>
</head> </head>
<body> <body>
)====="; )=====";
//new user welcome page
#ifndef WLED_FLASH_512K_MODE
const char PAGE_welcome0[] PROGMEM = R"=====( const char PAGE_welcome0[] PROGMEM = R"=====(
<!DOCTYPE html> <!DOCTYPE html>
<html><head> <html><head>
<title>WLED Welcome!</title> <title>WLED Welcome!</title>
)====="; )=====";
const char PAGE_welcome1[] PROGMEM = R"=====( const char PAGE_welcome1[] PROGMEM = R"=====(
body{font-family:var(--cFn),sans-serif;text-align:center;background:linear-gradient(var(--bCol),black);height:100%;margin:0;background-repeat:no-repeat;background-attachment: fixed;color: var(--tCol);}svg {fill: var(--dCol);} body{font-family:var(--cFn),sans-serif;text-align:center;background:linear-gradient(var(--bCol),black);height:100%;margin:0;background-repeat:no-repeat;background-attachment: fixed;color: var(--tCol);}svg {fill: var(--dCol);}
</style></head> </style></head>
@ -41,6 +50,11 @@ Connect the module to your local WiFi <a href="/settings/wifi">here</a>!<br><br>
<i>Just trying this out in AP mode?</i> <a href="/sliders">Here are the controls.</a><br> <i>Just trying this out in AP mode?</i> <a href="/sliders">Here are the controls.</a><br>
</body></html> </body></html>
)====="; )=====";
#else
const char PAGE_welcome0[] PROGMEM = "";
const char PAGE_welcome1[] PROGMEM = "";
#endif
/* /*
* SPIFFS editor html * SPIFFS editor html
@ -54,6 +68,8 @@ eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a
#else #else
const char PAGE_edit[] PROGMEM = R"=====(SPIFFS disabled)====="; const char PAGE_edit[] PROGMEM = R"=====(SPIFFS disabled)=====";
#endif #endif
/* /*
* favicon * favicon
*/ */

555
wled00/palettes.h Normal file
View File

@ -0,0 +1,555 @@
/*
* Color palettes for FastLED effects (65-73).
*/
// From ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb
// Unfortunaltely, these are stored in RAM!
// Gradient palette "ib_jul01_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ing/xmas/tn/ib_jul01.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 16 bytes of program space.
#ifndef PalettesWLED_h
#define PalettesWLED_h
DEFINE_GRADIENT_PALETTE( ib_jul01_gp ) {
0, 194, 1, 1,
94, 1, 29, 18,
132, 57,131, 28,
255, 113, 1, 1};
// Gradient palette "es_vintage_57_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/vintage/tn/es_vintage_57.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_vintage_57_gp ) {
0, 2, 1, 1,
53, 18, 1, 0,
104, 69, 29, 1,
153, 167,135, 10,
255, 46, 56, 4};
// Gradient palette "es_vintage_01_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/vintage/tn/es_vintage_01.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 32 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_vintage_01_gp ) {
0, 4, 1, 1,
51, 16, 0, 1,
76, 97,104, 3,
101, 255,131, 19,
127, 67, 9, 4,
153, 16, 0, 1,
229, 4, 1, 1,
255, 4, 1, 1};
// Gradient palette "es_rivendell_15_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/rivendell/tn/es_rivendell_15.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_rivendell_15_gp ) {
0, 1, 14, 5,
101, 16, 36, 14,
165, 56, 68, 30,
242, 150,156, 99,
255, 150,156, 99};
// Gradient palette "rgi_15_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ds/rgi/tn/rgi_15.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 36 bytes of program space.
// Edited to be brighter
DEFINE_GRADIENT_PALETTE( rgi_15_gp ) {
0, 4, 1, 70,
31, 55, 1, 30,
63, 255, 4, 7,
95, 59, 2, 29,
127, 11, 3, 50,
159, 39, 8, 60,
191, 112, 19, 40,
223, 78, 11, 39,
255, 29, 8, 59};
// Gradient palette "retro2_16_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ma/retro2/tn/retro2_16.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 8 bytes of program space.
DEFINE_GRADIENT_PALETTE( retro2_16_gp ) {
0, 188,135, 1,
255, 46, 7, 1};
// Gradient palette "Analogous_1_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/red/tn/Analogous_1.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( Analogous_1_gp ) {
0, 3, 0,255,
63, 23, 0,255,
127, 67, 0,255,
191, 142, 0, 45,
255, 255, 0, 0};
// Gradient palette "es_pinksplash_08_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/pink_splash/tn/es_pinksplash_08.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_pinksplash_08_gp ) {
0, 126, 11,255,
127, 197, 1, 22,
175, 210,157,172,
221, 157, 3,112,
255, 157, 3,112};
// Gradient palette "es_ocean_breeze_036_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/ocean_breeze/tn/es_ocean_breeze_036.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 16 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_ocean_breeze_036_gp ) {
0, 1, 6, 7,
89, 1, 99,111,
153, 144,209,255,
255, 0, 73, 82};
// Gradient palette "departure_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/mjf/tn/departure.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 88 bytes of program space.
DEFINE_GRADIENT_PALETTE( departure_gp ) {
0, 8, 3, 0,
42, 23, 7, 0,
63, 75, 38, 6,
84, 169, 99, 38,
106, 213,169,119,
116, 255,255,255,
138, 135,255,138,
148, 22,255, 24,
170, 0,255, 0,
191, 0,136, 0,
212, 0, 55, 0,
255, 0, 55, 0};
// Gradient palette "es_landscape_64_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/landscape/tn/es_landscape_64.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 36 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_landscape_64_gp ) {
0, 0, 0, 0,
37, 2, 25, 1,
76, 15,115, 5,
127, 79,213, 1,
128, 126,211, 47,
130, 188,209,247,
153, 144,182,205,
204, 59,117,250,
255, 1, 37,192};
// Gradient palette "es_landscape_33_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/landscape/tn/es_landscape_33.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 24 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_landscape_33_gp ) {
0, 1, 5, 0,
19, 32, 23, 1,
38, 161, 55, 1,
63, 229,144, 1,
66, 39,142, 74,
255, 1, 4, 1};
// Gradient palette "rainbowsherbet_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ma/icecream/tn/rainbowsherbet.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 28 bytes of program space.
DEFINE_GRADIENT_PALETTE( rainbowsherbet_gp ) {
0, 255, 33, 4,
43, 255, 68, 25,
86, 255, 7, 25,
127, 255, 82,103,
170, 255,255,242,
209, 42,255, 22,
255, 87,255, 65};
// Gradient palette "gr65_hult_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/hult/tn/gr65_hult.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 24 bytes of program space.
DEFINE_GRADIENT_PALETTE( gr65_hult_gp ) {
0, 247,176,247,
48, 255,136,255,
89, 220, 29,226,
160, 7, 82,178,
216, 1,124,109,
255, 1,124,109};
// Gradient palette "gr64_hult_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/hult/tn/gr64_hult.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 32 bytes of program space.
DEFINE_GRADIENT_PALETTE( gr64_hult_gp ) {
0, 1,124,109,
66, 1, 93, 79,
104, 52, 65, 1,
130, 115,127, 1,
150, 52, 65, 1,
201, 1, 86, 72,
239, 0, 55, 45,
255, 0, 55, 45};
// Gradient palette "GMT_drywet_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/gmt/tn/GMT_drywet.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 28 bytes of program space.
DEFINE_GRADIENT_PALETTE( GMT_drywet_gp ) {
0, 47, 30, 2,
42, 213,147, 24,
84, 103,219, 52,
127, 3,219,207,
170, 1, 48,214,
212, 1, 1,111,
255, 1, 7, 33};
// Gradient palette "ib15_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ing/general/tn/ib15.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 24 bytes of program space.
DEFINE_GRADIENT_PALETTE( ib15_gp ) {
0, 113, 91,147,
72, 157, 88, 78,
89, 208, 85, 33,
107, 255, 29, 11,
141, 137, 31, 39,
255, 59, 33, 89};
// Gradient palette "Tertiary_01_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/vermillion/tn/Tertiary_01.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( Tertiary_01_gp ) {
0, 0, 1,255,
63, 3, 68, 45,
127, 23,255, 0,
191, 100, 68, 1,
255, 255, 1, 4};
// Gradient palette "lava_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/neota/elem/tn/lava.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 52 bytes of program space.
DEFINE_GRADIENT_PALETTE( lava_gp ) {
0, 0, 0, 0,
46, 18, 0, 0,
96, 113, 0, 0,
108, 142, 3, 1,
119, 175, 17, 1,
146, 213, 44, 2,
174, 255, 82, 4,
188, 255,115, 4,
202, 255,156, 4,
218, 255,203, 4,
234, 255,255, 4,
244, 255,255, 71,
255, 255,255,255};
// Gradient palette "fierce_ice_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/neota/elem/tn/fierce-ice.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 28 bytes of program space.
DEFINE_GRADIENT_PALETTE( fierce_ice_gp ) {
0, 0, 0, 0,
59, 0, 9, 45,
119, 0, 38,255,
149, 3,100,255,
180, 23,199,255,
217, 100,235,255,
255, 255,255,255};
// Gradient palette "Colorfull_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Colorfull.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 44 bytes of program space.
DEFINE_GRADIENT_PALETTE( Colorfull_gp ) {
0, 10, 85, 5,
25, 29,109, 18,
60, 59,138, 42,
93, 83, 99, 52,
106, 110, 66, 64,
109, 123, 49, 65,
113, 139, 35, 66,
116, 192,117, 98,
124, 255,255,137,
168, 100,180,155,
255, 22,121,174};
// Gradient palette "Pink_Purple_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Pink_Purple.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 44 bytes of program space.
DEFINE_GRADIENT_PALETTE( Pink_Purple_gp ) {
0, 19, 2, 39,
25, 26, 4, 45,
51, 33, 6, 52,
76, 68, 62,125,
102, 118,187,240,
109, 163,215,247,
114, 217,244,255,
122, 159,149,221,
149, 113, 78,188,
183, 128, 57,155,
255, 146, 40,123};
// Gradient palette "Sunset_Real_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Sunset_Real.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 28 bytes of program space.
DEFINE_GRADIENT_PALETTE( Sunset_Real_gp ) {
0, 120, 0, 0,
22, 179, 22, 0,
51, 255,104, 0,
85, 167, 22, 18,
135, 100, 0,103,
198, 16, 0,130,
255, 0, 0,160};
// Gradient palette "Sunset_Yellow_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Sunset_Yellow.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 44 bytes of program space.
DEFINE_GRADIENT_PALETTE( Sunset_Yellow_gp ) {
0, 10, 62,123,
36, 56,130,103,
87, 153,225, 85,
100, 199,217, 68,
107, 255,207, 54,
115, 247,152, 57,
120, 239,107, 61,
128, 247,152, 57,
180, 255,207, 54,
223, 255,227, 48,
255, 255,248, 42};
// Gradient palette "Beech_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Beech.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 60 bytes of program space.
DEFINE_GRADIENT_PALETTE( Beech_gp ) {
0, 255,252,214,
12, 255,252,214,
22, 255,252,214,
26, 190,191,115,
28, 137,141, 52,
28, 112,255,205,
50, 51,246,214,
71, 17,235,226,
93, 2,193,199,
120, 0,156,174,
133, 1,101,115,
136, 1, 59, 71,
136, 7,131,170,
208, 1, 90,151,
255, 0, 56,133};
// Gradient palette "Another_Sunset_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Another_Sunset.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 32 bytes of program space.
DEFINE_GRADIENT_PALETTE( Another_Sunset_gp ) {
0, 110, 49, 11,
29, 55, 34, 10,
68, 22, 22, 9,
68, 239,124, 8,
97, 220,156, 27,
124, 203,193, 61,
178, 33, 53, 56,
255, 0, 1, 52};
// Gradient palette "es_autumn_19_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/autumn/tn/es_autumn_19.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 52 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_autumn_19_gp ) {
0, 26, 1, 1,
51, 67, 4, 1,
84, 118, 14, 1,
104, 137,152, 52,
112, 113, 65, 1,
122, 133,149, 59,
124, 137,152, 52,
135, 113, 65, 1,
142, 139,154, 46,
163, 113, 13, 1,
204, 55, 3, 1,
249, 17, 1, 1,
255, 17, 1, 1};
// Gradient palette "BlacK_Blue_Magenta_White_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/BlacK_Blue_Magenta_White.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 28 bytes of program space.
DEFINE_GRADIENT_PALETTE( BlacK_Blue_Magenta_White_gp ) {
0, 0, 0, 0,
42, 0, 0, 45,
84, 0, 0,255,
127, 42, 0,255,
170, 255, 0,255,
212, 255, 55,255,
255, 255,255,255};
// Gradient palette "BlacK_Magenta_Red_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/BlacK_Magenta_Red.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( BlacK_Magenta_Red_gp ) {
0, 0, 0, 0,
63, 42, 0, 45,
127, 255, 0,255,
191, 255, 0, 45,
255, 255, 0, 0};
// Gradient palette "BlacK_Red_Magenta_Yellow_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/BlacK_Red_Magenta_Yellow.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 28 bytes of program space.
DEFINE_GRADIENT_PALETTE( BlacK_Red_Magenta_Yellow_gp ) {
0, 0, 0, 0,
42, 42, 0, 0,
84, 255, 0, 0,
127, 255, 0, 45,
170, 255, 0,255,
212, 255, 55, 45,
255, 255,255, 0};
// Gradient palette "Blue_Cyan_Yellow_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/Blue_Cyan_Yellow.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( Blue_Cyan_Yellow_gp ) {
0, 0, 0,255,
63, 0, 55,255,
127, 0,255,255,
191, 42,255, 45,
255, 255,255, 0};
//Custom palette by Aircoookie
DEFINE_GRADIENT_PALETTE( Orange_Teal_gp ) {
0, 0,150, 92,
55, 0,150, 92,
200, 255, 72, 0,
255, 255, 72, 0};
// Single array of defined cpt-city color palettes.
// This will let us programmatically choose one based on
// a number, rather than having to activate each explicitly
// by name every time.
// Since it is const, this array could also be moved
// into PROGMEM to save SRAM, but for simplicity of illustration
// we'll keep it in a regular SRAM array.
//
// This list of color palettes acts as a "playlist"; you can
// add or delete, or re-arrange as you wish.
const TProgmemRGBGradientPalettePtr gGradientPalettes[] = {
Sunset_Real_gp, //13-00 Sunset
es_rivendell_15_gp, //14-01 Rivendell
es_ocean_breeze_036_gp, //15-02 Breeze
rgi_15_gp, //16-03 Red & Blue
retro2_16_gp, //17-04 Yellowout
Analogous_1_gp, //18-05 Analogous
es_pinksplash_08_gp, //19-06 Splash
Sunset_Yellow_gp, //20-07 Pastel
Another_Sunset_gp, //21-08 Sunset2
Beech_gp, //22-09 Beech
es_vintage_01_gp, //23-10 Vintage
departure_gp, //24-11 Departure
es_landscape_64_gp, //25-12 Landscape
es_landscape_33_gp, //26-13 Beach
rainbowsherbet_gp, //27-14 Sherbet
gr65_hult_gp, //28-15 Hult
gr64_hult_gp, //29-16 Hult64
GMT_drywet_gp, //30-17 Drywet
ib_jul01_gp, //31-18 Jul
es_vintage_57_gp, //32-19 Grintage
ib15_gp, //33-20 Rewhi
Tertiary_01_gp, //34-21 Tertiary
lava_gp, //35-22 Fire
fierce_ice_gp, //36-23 Icefire
Colorfull_gp, //37-24 Cyane
Pink_Purple_gp, //38-25 Light Pink
es_autumn_19_gp, //39-26 Autumn
BlacK_Blue_Magenta_White_gp, //40-27 Magenta
BlacK_Magenta_Red_gp, //41-28 Magred
BlacK_Red_Magenta_Yellow_gp, //42-29 Yelmag
Blue_Cyan_Yellow_gp, //43-30 Yelblu
Orange_Teal_gp //44-31 Orange & Teal
};
// Count of how many cpt-city gradients are defined:
const uint8_t gGradientPaletteCount =
sizeof( gGradientPalettes) / sizeof( TProgmemRGBGradientPalettePtr );
#endif

View File

@ -0,0 +1,20 @@
Copyright (c) 2008-2015 Nicholas O'Leary
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,601 @@
/*
PubSubClient.cpp - A simple client for MQTT.
Nick O'Leary
http://knolleary.net
*/
#include "PubSubClient.h"
#include "Arduino.h"
PubSubClient::PubSubClient() {
this->_state = MQTT_DISCONNECTED;
this->_client = NULL;
this->stream = NULL;
setCallback(NULL);
}
PubSubClient::PubSubClient(Client& client) {
this->_state = MQTT_DISCONNECTED;
setClient(client);
this->stream = NULL;
}
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) {
this->_state = MQTT_DISCONNECTED;
setServer(addr, port);
setClient(client);
this->stream = NULL;
}
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) {
this->_state = MQTT_DISCONNECTED;
setServer(addr,port);
setClient(client);
setStream(stream);
}
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
this->_state = MQTT_DISCONNECTED;
setServer(addr, port);
setCallback(callback);
setClient(client);
this->stream = NULL;
}
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
this->_state = MQTT_DISCONNECTED;
setServer(addr,port);
setCallback(callback);
setClient(client);
setStream(stream);
}
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) {
this->_state = MQTT_DISCONNECTED;
setServer(ip, port);
setClient(client);
this->stream = NULL;
}
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream) {
this->_state = MQTT_DISCONNECTED;
setServer(ip,port);
setClient(client);
setStream(stream);
}
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
this->_state = MQTT_DISCONNECTED;
setServer(ip, port);
setCallback(callback);
setClient(client);
this->stream = NULL;
}
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
this->_state = MQTT_DISCONNECTED;
setServer(ip,port);
setCallback(callback);
setClient(client);
setStream(stream);
}
PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) {
this->_state = MQTT_DISCONNECTED;
setServer(domain,port);
setClient(client);
this->stream = NULL;
}
PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream) {
this->_state = MQTT_DISCONNECTED;
setServer(domain,port);
setClient(client);
setStream(stream);
}
PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
this->_state = MQTT_DISCONNECTED;
setServer(domain,port);
setCallback(callback);
setClient(client);
this->stream = NULL;
}
PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
this->_state = MQTT_DISCONNECTED;
setServer(domain,port);
setCallback(callback);
setClient(client);
setStream(stream);
}
boolean PubSubClient::connect(const char *id) {
return connect(id,NULL,NULL,0,0,0,0);
}
boolean PubSubClient::connect(const char *id, const char *user, const char *pass) {
return connect(id,user,pass,0,0,0,0);
}
boolean PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) {
return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage);
}
boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) {
if (!connected()) {
int result = 0;
if (domain != NULL) {
result = _client->connect(this->domain, this->port);
} else {
result = _client->connect(this->ip, this->port);
}
if (result == 1) {
nextMsgId = 1;
// Leave room in the buffer for header and variable length field
uint16_t length = 5;
unsigned int j;
#if MQTT_VERSION == MQTT_VERSION_3_1
uint8_t d[9] = {0x00,0x06,'M','Q','I','s','d','p', MQTT_VERSION};
#define MQTT_HEADER_VERSION_LENGTH 9
#elif MQTT_VERSION == MQTT_VERSION_3_1_1
uint8_t d[7] = {0x00,0x04,'M','Q','T','T',MQTT_VERSION};
#define MQTT_HEADER_VERSION_LENGTH 7
#endif
for (j = 0;j<MQTT_HEADER_VERSION_LENGTH;j++) {
buffer[length++] = d[j];
}
uint8_t v;
if (willTopic) {
v = 0x06|(willQos<<3)|(willRetain<<5);
} else {
v = 0x02;
}
if(user != NULL) {
v = v|0x80;
if(pass != NULL) {
v = v|(0x80>>1);
}
}
buffer[length++] = v;
buffer[length++] = ((MQTT_KEEPALIVE) >> 8);
buffer[length++] = ((MQTT_KEEPALIVE) & 0xFF);
length = writeString(id,buffer,length);
if (willTopic) {
length = writeString(willTopic,buffer,length);
length = writeString(willMessage,buffer,length);
}
if(user != NULL) {
length = writeString(user,buffer,length);
if(pass != NULL) {
length = writeString(pass,buffer,length);
}
}
write(MQTTCONNECT,buffer,length-5);
lastInActivity = lastOutActivity = millis();
while (!_client->available()) {
unsigned long t = millis();
if (t-lastInActivity >= ((int32_t) MQTT_SOCKET_TIMEOUT*1000UL)) {
_state = MQTT_CONNECTION_TIMEOUT;
_client->stop();
return false;
}
}
uint8_t llen;
uint16_t len = readPacket(&llen);
if (len == 4) {
if (buffer[3] == 0) {
lastInActivity = millis();
pingOutstanding = false;
_state = MQTT_CONNECTED;
return true;
} else {
_state = buffer[3];
}
}
_client->stop();
} else {
_state = MQTT_CONNECT_FAILED;
}
return false;
}
return true;
}
// reads a byte into result
boolean PubSubClient::readByte(uint8_t * result) {
uint32_t previousMillis = millis();
while(!_client->available()) {
uint32_t currentMillis = millis();
if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)){
return false;
}
}
*result = _client->read();
return true;
}
// reads a byte into result[*index] and increments index
boolean PubSubClient::readByte(uint8_t * result, uint16_t * index){
uint16_t current_index = *index;
uint8_t * write_address = &(result[current_index]);
if(readByte(write_address)){
*index = current_index + 1;
return true;
}
return false;
}
uint16_t PubSubClient::readPacket(uint8_t* lengthLength) {
uint16_t len = 0;
if(!readByte(buffer, &len)) return 0;
bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH;
uint32_t multiplier = 1;
uint16_t length = 0;
uint8_t digit = 0;
uint16_t skip = 0;
uint8_t start = 0;
do {
if (len == 6) {
// Invalid remaining length encoding - kill the connection
_state = MQTT_DISCONNECTED;
_client->stop();
return 0;
}
if(!readByte(&digit)) return 0;
buffer[len++] = digit;
length += (digit & 127) * multiplier;
multiplier *= 128;
} while ((digit & 128) != 0);
*lengthLength = len-1;
if (isPublish) {
// Read in topic length to calculate bytes to skip over for Stream writing
if(!readByte(buffer, &len)) return 0;
if(!readByte(buffer, &len)) return 0;
skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2];
start = 2;
if (buffer[0]&MQTTQOS1) {
// skip message id
skip += 2;
}
}
for (uint16_t i = start;i<length;i++) {
if(!readByte(&digit)) return 0;
if (this->stream) {
if (isPublish && len-*lengthLength-2>skip) {
this->stream->write(digit);
}
}
if (len < MQTT_MAX_PACKET_SIZE) {
buffer[len] = digit;
}
len++;
}
if (!this->stream && len > MQTT_MAX_PACKET_SIZE) {
len = 0; // This will cause the packet to be ignored.
}
return len;
}
boolean PubSubClient::loop() {
if (connected()) {
unsigned long t = millis();
if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) {
if (pingOutstanding) {
this->_state = MQTT_CONNECTION_TIMEOUT;
_client->stop();
return false;
} else {
buffer[0] = MQTTPINGREQ;
buffer[1] = 0;
_client->write(buffer,2);
lastOutActivity = t;
lastInActivity = t;
pingOutstanding = true;
}
}
if (_client->available()) {
uint8_t llen;
uint16_t len = readPacket(&llen);
uint16_t msgId = 0;
uint8_t *payload;
if (len > 0) {
lastInActivity = t;
uint8_t type = buffer[0]&0xF0;
if (type == MQTTPUBLISH) {
if (callback) {
uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; /* topic length in bytes */
memmove(buffer+llen+2,buffer+llen+3,tl); /* move topic inside buffer 1 byte to front */
buffer[llen+2+tl] = 0; /* end the topic as a 'C' string with \x00 */
char *topic = (char*) buffer+llen+2;
// make sure payload can be interpreted as 'C' string
buffer[(len < MQTT_MAX_PACKET_SIZE) ? len : MQTT_MAX_PACKET_SIZE -1] = 0;
// msgId only present for QOS>0
if ((buffer[0]&0x06) == MQTTQOS1) {
msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1];
payload = buffer+llen+3+tl+2;
callback(topic,payload,len-llen-3-tl-2);
buffer[0] = MQTTPUBACK;
buffer[1] = 2;
buffer[2] = (msgId >> 8);
buffer[3] = (msgId & 0xFF);
_client->write(buffer,4);
lastOutActivity = t;
} else {
payload = buffer+llen+3+tl;
callback(topic,payload,len-llen-3-tl);
}
}
} else if (type == MQTTPINGREQ) {
buffer[0] = MQTTPINGRESP;
buffer[1] = 0;
_client->write(buffer,2);
} else if (type == MQTTPINGRESP) {
pingOutstanding = false;
}
} else if (!connected()) {
// readPacket has closed the connection
return false;
}
}
return true;
}
return false;
}
boolean PubSubClient::publish(const char* topic, const char* payload) {
return publish(topic,(const uint8_t*)payload,strlen(payload),false);
}
boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained) {
return publish(topic,(const uint8_t*)payload,strlen(payload),retained);
}
boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength) {
return publish(topic, payload, plength, false);
}
boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) {
if (connected()) {
if (MQTT_MAX_PACKET_SIZE < 5 + 2+strlen(topic) + plength) {
// Too long
return false;
}
// Leave room in the buffer for header and variable length field
uint16_t length = 5;
length = writeString(topic,buffer,length);
uint16_t i;
for (i=0;i<plength;i++) {
buffer[length++] = payload[i];
}
uint8_t header = MQTTPUBLISH;
if (retained) {
header |= 1;
}
return write(header,buffer,length-5);
}
return false;
}
boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) {
uint8_t llen = 0;
uint8_t digit;
unsigned int rc = 0;
uint16_t tlen;
unsigned int pos = 0;
unsigned int i;
uint8_t header;
unsigned int len;
if (!connected()) {
return false;
}
tlen = strlen(topic);
header = MQTTPUBLISH;
if (retained) {
header |= 1;
}
buffer[pos++] = header;
len = plength + 2 + tlen;
do {
digit = len % 128;
len = len / 128;
if (len > 0) {
digit |= 0x80;
}
buffer[pos++] = digit;
llen++;
} while(len>0);
pos = writeString(topic,buffer,pos);
rc += _client->write(buffer,pos);
for (i=0;i<plength;i++) {
rc += _client->write((char)pgm_read_byte_near(payload + i));
}
lastOutActivity = millis();
return rc == tlen + 4 + plength;
}
boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) {
uint8_t lenBuf[4];
uint8_t llen = 0;
uint8_t digit;
uint8_t pos = 0;
uint16_t rc;
uint16_t len = length;
do {
digit = len % 128;
len = len / 128;
if (len > 0) {
digit |= 0x80;
}
lenBuf[pos++] = digit;
llen++;
} while(len>0);
buf[4-llen] = header;
for (int i=0;i<llen;i++) {
buf[5-llen+i] = lenBuf[i];
}
#ifdef MQTT_MAX_TRANSFER_SIZE
uint8_t* writeBuf = buf+(4-llen);
uint16_t bytesRemaining = length+1+llen; //Match the length type
uint8_t bytesToWrite;
boolean result = true;
while((bytesRemaining > 0) && result) {
bytesToWrite = (bytesRemaining > MQTT_MAX_TRANSFER_SIZE)?MQTT_MAX_TRANSFER_SIZE:bytesRemaining;
rc = _client->write(writeBuf,bytesToWrite);
result = (rc == bytesToWrite);
bytesRemaining -= rc;
writeBuf += rc;
}
return result;
#else
rc = _client->write(buf+(4-llen),length+1+llen);
lastOutActivity = millis();
return (rc == 1+llen+length);
#endif
}
boolean PubSubClient::subscribe(const char* topic) {
return subscribe(topic, 0);
}
boolean PubSubClient::subscribe(const char* topic, uint8_t qos) {
if (qos > 1) {
return false;
}
if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) {
// Too long
return false;
}
if (connected()) {
// Leave room in the buffer for header and variable length field
uint16_t length = 5;
nextMsgId++;
if (nextMsgId == 0) {
nextMsgId = 1;
}
buffer[length++] = (nextMsgId >> 8);
buffer[length++] = (nextMsgId & 0xFF);
length = writeString((char*)topic, buffer,length);
buffer[length++] = qos;
return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-5);
}
return false;
}
boolean PubSubClient::unsubscribe(const char* topic) {
if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) {
// Too long
return false;
}
if (connected()) {
uint16_t length = 5;
nextMsgId++;
if (nextMsgId == 0) {
nextMsgId = 1;
}
buffer[length++] = (nextMsgId >> 8);
buffer[length++] = (nextMsgId & 0xFF);
length = writeString(topic, buffer,length);
return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-5);
}
return false;
}
void PubSubClient::disconnect() {
buffer[0] = MQTTDISCONNECT;
buffer[1] = 0;
_client->write(buffer,2);
_state = MQTT_DISCONNECTED;
_client->stop();
lastInActivity = lastOutActivity = millis();
}
uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t pos) {
const char* idp = string;
uint16_t i = 0;
pos += 2;
while (*idp) {
buf[pos++] = *idp++;
i++;
}
buf[pos-i-2] = (i >> 8);
buf[pos-i-1] = (i & 0xFF);
return pos;
}
boolean PubSubClient::connected() {
boolean rc;
if (_client == NULL ) {
rc = false;
} else {
rc = (int)_client->connected();
if (!rc) {
if (this->_state == MQTT_CONNECTED) {
this->_state = MQTT_CONNECTION_LOST;
_client->flush();
_client->stop();
}
}
}
return rc;
}
PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) {
IPAddress addr(ip[0],ip[1],ip[2],ip[3]);
return setServer(addr,port);
}
PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) {
this->ip = ip;
this->port = port;
this->domain = NULL;
return *this;
}
PubSubClient& PubSubClient::setServer(const char * domain, uint16_t port) {
this->domain = domain;
this->port = port;
return *this;
}
PubSubClient& PubSubClient::setCallback(MQTT_CALLBACK_SIGNATURE) {
this->callback = callback;
return *this;
}
PubSubClient& PubSubClient::setClient(Client& client){
this->_client = &client;
return *this;
}
PubSubClient& PubSubClient::setStream(Stream& stream){
this->stream = &stream;
return *this;
}
int PubSubClient::state() {
return this->_state;
}

View File

@ -0,0 +1,144 @@
/*
PubSubClient.h - A simple client for MQTT.
Nick O'Leary
http://knolleary.net
*/
#ifndef PubSubClient_h
#define PubSubClient_h
#include <Arduino.h>
#include "IPAddress.h"
#include "Client.h"
#include "Stream.h"
#define MQTT_VERSION_3_1 3
#define MQTT_VERSION_3_1_1 4
// MQTT_VERSION : Pick the version
//#define MQTT_VERSION MQTT_VERSION_3_1
#ifndef MQTT_VERSION
#define MQTT_VERSION MQTT_VERSION_3_1_1
#endif
// MQTT_MAX_PACKET_SIZE : Maximum packet size
#ifndef MQTT_MAX_PACKET_SIZE
#define MQTT_MAX_PACKET_SIZE 128
#endif
// MQTT_KEEPALIVE : keepAlive interval in Seconds
#ifndef MQTT_KEEPALIVE
#define MQTT_KEEPALIVE 60
#endif
// MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds
#ifndef MQTT_SOCKET_TIMEOUT
#define MQTT_SOCKET_TIMEOUT 62
#endif
// MQTT_MAX_TRANSFER_SIZE : limit how much data is passed to the network client
// in each write call. Needed for the Arduino Wifi Shield. Leave undefined to
// pass the entire MQTT packet in each write call.
//#define MQTT_MAX_TRANSFER_SIZE 80
// Possible values for client.state()
#define MQTT_CONNECTION_TIMEOUT -4
#define MQTT_CONNECTION_LOST -3
#define MQTT_CONNECT_FAILED -2
#define MQTT_DISCONNECTED -1
#define MQTT_CONNECTED 0
#define MQTT_CONNECT_BAD_PROTOCOL 1
#define MQTT_CONNECT_BAD_CLIENT_ID 2
#define MQTT_CONNECT_UNAVAILABLE 3
#define MQTT_CONNECT_BAD_CREDENTIALS 4
#define MQTT_CONNECT_UNAUTHORIZED 5
#define MQTTCONNECT 1 << 4 // Client request to connect to Server
#define MQTTCONNACK 2 << 4 // Connect Acknowledgment
#define MQTTPUBLISH 3 << 4 // Publish message
#define MQTTPUBACK 4 << 4 // Publish Acknowledgment
#define MQTTPUBREC 5 << 4 // Publish Received (assured delivery part 1)
#define MQTTPUBREL 6 << 4 // Publish Release (assured delivery part 2)
#define MQTTPUBCOMP 7 << 4 // Publish Complete (assured delivery part 3)
#define MQTTSUBSCRIBE 8 << 4 // Client Subscribe request
#define MQTTSUBACK 9 << 4 // Subscribe Acknowledgment
#define MQTTUNSUBSCRIBE 10 << 4 // Client Unsubscribe request
#define MQTTUNSUBACK 11 << 4 // Unsubscribe Acknowledgment
#define MQTTPINGREQ 12 << 4 // PING Request
#define MQTTPINGRESP 13 << 4 // PING Response
#define MQTTDISCONNECT 14 << 4 // Client is Disconnecting
#define MQTTReserved 15 << 4 // Reserved
#define MQTTQOS0 (0 << 1)
#define MQTTQOS1 (1 << 1)
#define MQTTQOS2 (2 << 1)
#ifdef ESP8266
#include <functional>
#define MQTT_CALLBACK_SIGNATURE std::function<void(char*, uint8_t*, unsigned int)> callback
#else
#define MQTT_CALLBACK_SIGNATURE void (*callback)(char*, uint8_t*, unsigned int)
#endif
class PubSubClient {
private:
Client* _client;
uint8_t buffer[MQTT_MAX_PACKET_SIZE];
uint16_t nextMsgId;
unsigned long lastOutActivity;
unsigned long lastInActivity;
bool pingOutstanding;
MQTT_CALLBACK_SIGNATURE;
uint16_t readPacket(uint8_t*);
boolean readByte(uint8_t * result);
boolean readByte(uint8_t * result, uint16_t * index);
boolean write(uint8_t header, uint8_t* buf, uint16_t length);
uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos);
IPAddress ip;
const char* domain;
uint16_t port;
Stream* stream;
int _state;
public:
PubSubClient();
PubSubClient(Client& client);
PubSubClient(IPAddress, uint16_t, Client& client);
PubSubClient(IPAddress, uint16_t, Client& client, Stream&);
PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client);
PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&);
PubSubClient(uint8_t *, uint16_t, Client& client);
PubSubClient(uint8_t *, uint16_t, Client& client, Stream&);
PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client);
PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&);
PubSubClient(const char*, uint16_t, Client& client);
PubSubClient(const char*, uint16_t, Client& client, Stream&);
PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client);
PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&);
PubSubClient& setServer(IPAddress ip, uint16_t port);
PubSubClient& setServer(uint8_t * ip, uint16_t port);
PubSubClient& setServer(const char * domain, uint16_t port);
PubSubClient& setCallback(MQTT_CALLBACK_SIGNATURE);
PubSubClient& setClient(Client& client);
PubSubClient& setStream(Stream& stream);
boolean connect(const char* id);
boolean connect(const char* id, const char* user, const char* pass);
boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage);
boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage);
void disconnect();
boolean publish(const char* topic, const char* payload);
boolean publish(const char* topic, const char* payload, boolean retained);
boolean publish(const char* topic, const uint8_t * payload, unsigned int plength);
boolean publish(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained);
boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained);
boolean subscribe(const char* topic);
boolean subscribe(const char* topic, uint8_t qos);
boolean unsubscribe(const char* topic);
boolean loop();
boolean connected();
int state();
};
#endif

View File

@ -1,16 +1,19 @@
/* /*
* Main sketch * Main sketch, global variable declarations
*/ */
/* /*
* @title WLED project sketch * @title WLED project sketch
* @version 0.7.1 * @version 0.8.0
* @author Christian Schwinne * @author Christian Schwinne
*/ */
//ESP8266-01 got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.3.0 and the setting 512K(64K SPIFFS). //ESP8266-01 got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.3.0 and the setting 512K(64K SPIFFS).
//Uncomment the following line to disable some features (currently Mobile UI) to compile for ESP8266-01 //Uncomment the following line to disable some features (currently Mobile UI, welcome page and single digit + cronixie overlays) to compile for ESP8266-01
//#define WLED_FLASH_512K_MODE //#define WLED_FLASH_512K_MODE
//CURRENTLY NOT WORKING
//library inclusions
#include <Arduino.h> #include <Arduino.h>
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
#include <WiFi.h> #include <WiFi.h>
@ -23,6 +26,7 @@
#include <ESP8266WebServer.h> #include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h> #include <ESP8266HTTPClient.h>
#endif #endif
#include <EEPROM.h> #include <EEPROM.h>
#include <ArduinoOTA.h> #include <ArduinoOTA.h>
#include <WiFiUDP.h> #include <WiFiUDP.h>
@ -31,155 +35,246 @@
#include "src/dependencies/time/Time.h" #include "src/dependencies/time/Time.h"
#include "src/dependencies/time/TimeLib.h" #include "src/dependencies/time/TimeLib.h"
#include "src/dependencies/timezone/Timezone.h" #include "src/dependencies/timezone/Timezone.h"
#include "src/dependencies/blynk/BlynkSimpleEsp.h"
#include "src/dependencies/e131/E131.h"
#include "src/dependencies/pubsubclient/PubSubClient.h"
#include "htmls00.h" #include "htmls00.h"
#include "htmls01.h" #include "htmls01.h"
#include "htmls02.h" #include "htmls02.h"
#include "WS2812FX.h" #include "WS2812FX.h"
#include "src/dependencies/blynk/BlynkSimpleEsp.h"
#include "src/dependencies/e131/E131.h"
//version in format yymmddb (b = daily build)
#define VERSION 1808311
char versionString[] = "0.7.1";
//AP and OTA default passwords (change them!) //version code in format yymmddb (b = daily build)
#define VERSION 1810151
char versionString[] = "0.8.0";
//AP and OTA default passwords (for maximum change them!)
char apPass[65] = "wled1234"; char apPass[65] = "wled1234";
char otaPass[33] = "wledota"; char otaPass[33] = "wledota";
//spiffs FS only useful for debug (only ESP8266)
//#define USEFS
//to toggle usb serial debug (un)comment following line(s) //to toggle usb serial debug (un)comment following line(s)
//#define DEBUG //#define DEBUG
//Hardware-settings (only changeble via code)
#define PIN 2 //strip pin. Only change for ESP32
byte buttonPin = 0; //needs pull-up
byte auxPin = 15; //use e.g. for external relay
byte auxDefaultState = 0; //0: input 1: high 2: low
byte auxTriggeredState = 0; //0: input 1: high 2: low
//Default CONFIG //spiffs FS only useful for debug (only ESP8266)
char serverDescription[33] = "WLED Light"; //#define USEFS
byte currentTheme = 0;
byte uiConfiguration = 0; //0: auto 1: classic 2: mobile
//Hardware CONFIG (only changeble HERE, not at runtime)
//LED strip pin changeable in NpbWrapper.h. Only change for ESP32
byte buttonPin = 0; //needs pull-up
byte auxPin = 15; //debug feature, use e.g. for external relay with API call AX=
byte auxDefaultState = 0; //0: input 1: high 2: low
byte auxTriggeredState = 0; //0: input 1: high 2: low
char ntpServerName[] = "0.wled.pool.ntp.org"; //NTP server to use
//WiFi CONFIG (all these can be changed via web UI, no need to set them here)
char clientSSID[33] = "Your_Network"; char clientSSID[33] = "Your_Network";
char clientPass[65] = ""; char clientPass[65] = "";
char cmDNS[33] = "led"; char cmDNS[33] = "led"; //mDNS address (x.local), only for Apple and Windows, if Bonjour installed
uint16_t ledCount = 10; //lowered to prevent accidental overcurrent char apSSID[65] = ""; //AP off by default (unless setup)
char apSSID[65] = ""; //AP off by default (unless setup) byte apChannel = 1; //2.4GHz WiFi AP channel (1-13)
byte apChannel = 1; byte apHide = 0; //hidden AP SSID
byte apHide = 0; byte apWaitTimeSecs = 32; //time to wait for connection before opening AP
byte apWaitTimeSecs = 32; bool recoveryAPDisabled = false; //never open AP (not recommended)
bool recoveryAPDisabled = false; IPAddress staticIP(0, 0, 0, 0); //static IP of ESP
IPAddress staticIP(0, 0, 0, 0); IPAddress staticGateway(0, 0, 0, 0); //gateway (router) IP
IPAddress staticGateway(0, 0, 0, 0); IPAddress staticSubnet(255, 255, 255, 0); //most common subnet in home networks
IPAddress staticSubnet(255, 255, 255, 0); IPAddress staticDNS(8, 8, 8, 8); //only for NTP, google DNS server
IPAddress staticDNS(8, 8, 8, 8); //only for NTP
bool useHSB = true, useHSBDefault = true, useRGBW = false, autoRGBtoRGBW = false;
bool turnOnAtBoot = true; //LED CONFIG
bool initLedsLast = false, skipFirstLed = false; uint16_t ledCount = 10; //lowered to prevent accidental overcurrent
byte bootPreset = 0; bool useRGBW = false; //SK6812 strips can contain an extra White channel
byte colS[]{255, 159, 0}; bool autoRGBtoRGBW = false; //if RGBW enabled, calculate White channel from RGB
byte colSecS[]{0, 0, 0}; bool turnOnAtBoot = true; //turn on LEDs at power-up
byte whiteS = 0; byte bootPreset = 0; //save preset to load after power-up
byte whiteSecS = 0;
byte briS = 127; byte colS[]{255, 159, 0}; //default RGB color
byte nightlightTargetBri = 0; byte colSecS[]{0, 0, 0}; //default RGB secondary color
bool fadeTransition = true; byte whiteS = 0; //default White channel
bool sweepTransition = false, sweepDirection = true; byte whiteSecS = 0; //default secondary White channel
bool disableSecTransition = true; byte briS = 127; //default brightness
uint16_t transitionDelay = 1200, transitionDelayDefault = transitionDelay; byte effectDefault = 0;
bool reverseMode = false;
bool otaLock = false, wifiLock = false;
bool aOtaEnabled = true;
bool buttonEnabled = true;
bool notifyDirect = true, notifyButton = true, notifyDirectDefault = true, alexaNotify = false, macroNotify = false, notifyTwice = false;
bool receiveNotifications = true, receiveNotificationBrightness = true, receiveNotificationColor = true, receiveNotificationEffects = true;
byte briMultiplier = 100;
byte nightlightDelayMins = 60;
bool nightlightFade = true;
uint16_t udpPort = 21324, udpRgbPort = 19446;
byte effectDefault = 0;
byte effectSpeedDefault = 75; byte effectSpeedDefault = 75;
byte effectIntensityDefault = 128; byte effectIntensityDefault = 128; //intensity is supported on some effects as an additional parameter (e.g. for blink you can change the duty cycle)
//NTP stuff byte effectPaletteDefault = 0; //palette is supported on the FastLED effects, otherwise it has no effect
bool ntpEnabled = false;
char ntpServerName[] = "0.wled.pool.ntp.org";
//custom chase
byte ccNumPrimary = 2;
byte ccNumSecondary = 4;
byte ccIndex1 = 0;
uint16_t ccIndex2 = ledCount -1;
bool ccFromStart = true, ccFromEnd = false;
byte ccStep = 1;
byte ccStart = 0;
//alexa bool useGammaCorrectionBri = false; //gamma correct brightness (not recommended)
bool alexaEnabled = true; bool useGammaCorrectionRGB = true; //gamma correct colors (strongly recommended)
char alexaInvocationName[33] = "Light";
byte macroBoot = 0, macroNl = 0; byte nightlightTargetBri = 0; //brightness after nightlight is over
byte nightlightDelayMins = 60;
bool nightlightFade = true; //if enabled, light will gradually dim towards the target bri. Otherwise, it will instantly set after delay over
bool fadeTransition = true; //enable crossfading color transition
bool enableSecTransition = true; //also enable transition for secondary color
uint16_t transitionDelay = 900; //default crossfade duration in ms
bool reverseMode = false; //flip entire LED strip (reverses all effect directions)
bool initLedsLast = false; //turn on LEDs only after WiFi connected/AP open
bool skipFirstLed = false; //ignore first LED in strip (useful if you need the LED as signal repeater)
byte briMultiplier = 100; //% of brightness to set (to limit power, if you set it to 50 and set bri to 255, actual brightness will be 127)
//User Interface CONFIG
char serverDescription[33] = "WLED Light"; //Name of module
byte currentTheme = 0; //UI theme index for settings and classic UI
byte uiConfiguration = 0; //0: automatic (depends on user-agent) 1: classic UI 2: mobile UI
bool useHSB = true; //classic UI: use HSB sliders instead of RGB by default
char cssFont[33] = "Verdana"; //font to use in classic UI
bool useHSBDefault = useHSB;
//Sync CONFIG
bool buttonEnabled = true;
uint16_t udpPort = 21324; //WLED notifier default port
uint16_t udpRgbPort = 19446; //Hyperion port
bool receiveNotificationBrightness = true; //apply brightness from incoming notifications
bool receiveNotificationColor = true; //apply color
bool receiveNotificationEffects = true; //apply effects setup
bool notifyDirect = true; //send notification if change via UI or HTTP API
bool notifyButton = true;
bool notifyAlexa = false; //send notification if updated via Alexa
bool notifyMacro = false; //send notification for macro
bool notifyHue = true; //send notification if Hue light changes
bool notifyTwice = false; //notifications use UDP: enable if devices don't sync reliably
bool alexaEnabled = true; //enable device discovery by Amazon Echo
char alexaInvocationName[33] = "Light"; //speech control name of device. Choose something voice-to-text can understand
char blynkApiKey[36] = ""; //Auth token for Blynk server. If empty, no connection will be made
uint16_t realtimeTimeoutMs = 2500; //ms timeout of realtime mode before returning to normal mode
int arlsOffset = 0; //realtime LED offset
bool receiveDirect = true; //receive UDP realtime
bool enableRealtimeUI = false; //web UI accessible during realtime mode (works on ESP32, lags out ESP8266)
bool arlsDisableGammaCorrection = true; //activate if gamma correction is handled by the source
bool arlsForceMaxBri = false; //enable to force max brightness if source has very dark colors that would be black
bool e131Enabled = true; //settings for E1.31 (sACN) protocol
uint16_t e131Universe = 1;
bool e131Multicast = 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)
bool huePollingEnabled = false; //poll hue bridge for light state
uint16_t huePollIntervalMs = 2500; //low values (< 1sec) may cause lag but offer quicker response
char hueApiKey[47] = "api"; //key token will be obtained from bridge
byte huePollLightId = 1; //ID of hue lamp to sync to. Find the ID in the hue app ("about" section)
IPAddress hueIP = (0,0,0,0); //IP address of the bridge
bool hueApplyOnOff = true;
bool hueApplyBri = true;
bool hueApplyColor = true;
//Time CONFIG
bool ntpEnabled = false; //get internet time. Only required if you use clock overlays or time-activated macros
bool useAMPM = false; //12h/24h clock format
byte currentTimezone = 0; //Timezone ID. Refer to timezones array in wled10_ntp.ino
int utcOffsetSecs = 0; //Seconds to offset from UTC before timzone calculation
byte overlayDefault = 0; //0: no overlay 1: analog clock 2: single-digit clocl 3: cronixie
byte overlayMin = 0, overlayMax = ledCount-1; //boundaries of overlay mode
byte analogClock12pixel = 0; //The pixel in your strip where "midnight" would be
bool analogClockSecondsTrail = false; //Display seconds as trail of LEDs instead of a single pixel
bool analogClock5MinuteMarks = false; //Light pixels at every 5-minute position
char cronixieDisplay[7] = "HHMMSS"; //Cronixie Display mask. See wled13_cronixie.ino
bool cronixieBacklight = true; //Allow digits to be back-illuminated
bool countdownMode = false; //Clock will count down towards date
byte countdownYear = 19, countdownMonth = 1; //Countdown target date, year is last two digits
byte countdownDay = 1, countdownHour = 0;
byte countdownMin = 0, countdownSec = 0;
byte macroBoot = 0; //macro loaded after startup
byte macroNl = 0; //after nightlight delay over
byte macroCountdown = 0;
byte macroAlexaOn = 0, macroAlexaOff = 0; byte macroAlexaOn = 0, macroAlexaOff = 0;
byte macroButton = 0, macroCountdown = 0, macroLongPress = 0; byte macroButton = 0, macroLongPress = 0;
unsigned long countdownTime = 1514764800L;
//hue //Security CONFIG
bool huePollingEnabled = false, hueAttempt = false; bool otaLock = false; //prevents OTA firmware updates without password. ALWAYS enable if system exposed to any public networks
uint16_t huePollIntervalMs = 2500; bool wifiLock = false; //prevents access to WiFi settings when OTA lock is enabled
char hueApiKey[65] = "api"; bool aOtaEnabled = true; //ArduinoOTA allows easy updates directly from the IDE. Careful, it does not auto-disable when OTA lock is on
byte huePollLightId = 1;
IPAddress hueIP = (0,0,0,0);
bool notifyHue = true;
bool hueApplyOnOff = true, hueApplyBri = true, hueApplyColor = true;
uint16_t userVar0 = 0, userVar1 = 0; uint16_t userVar0 = 0, userVar1 = 0;
//Internal vars
byte col[]{0, 0, 0};
byte colOld[]{0, 0, 0}; //internal global variable declarations
byte colT[]{0, 0, 0}; //color
byte colIT[]{0, 0, 0}; byte col[]{255, 159, 0}; //target RGB color
byte colOld[]{0, 0, 0}; //color before transition
byte colT[]{0, 0, 0}; //current color
byte colIT[]{0, 0, 0}; //color that was last sent to LEDs
byte colSec[]{0, 0, 0}; byte colSec[]{0, 0, 0};
byte colSecT[]{0, 0, 0}; byte colSecT[]{0, 0, 0};
byte colSecOld[]{0, 0, 0}; byte colSecOld[]{0, 0, 0};
byte colSecIT[]{0, 0, 0}; byte colSecIT[]{0, 0, 0};
byte white = 0, whiteOld, whiteT, whiteIT; byte white = whiteS, whiteOld, whiteT, whiteIT;
byte whiteSec = 0, whiteSecOld, whiteSecT, whiteSecIT; byte whiteSec = whiteSecS, whiteSecOld, whiteSecT, whiteSecIT;
byte lastRandomIndex = 0;
byte lastRandomIndex = 0; //used to save last random color so the new one is not the same
//transitions
bool transitionActive = false;
uint16_t transitionDelayDefault = transitionDelay;
uint16_t transitionDelayTemp = transitionDelay; uint16_t transitionDelayTemp = transitionDelay;
unsigned long transitionStartTime; unsigned long transitionStartTime;
unsigned long nightlightStartTime; float tperLast = 0; //crossfade transition progress, 0.0f - 1.0f
float tperLast = 0;
byte bri = 0; //nightlight
byte briOld = 0;
byte briT = 0;
byte briIT = 0;
byte briLast = 127;
bool transitionActive = false;
bool buttonPressedBefore = false;
unsigned long buttonPressedTime = 0;
unsigned long notificationSentTime = 0;
byte notificationSentCallMode = 0;
bool notificationTwoRequired = false;
bool nightlightActive = false; bool nightlightActive = false;
bool nightlightActiveOld = false; bool nightlightActiveOld = false;
uint32_t nightlightDelayMs = 10; uint32_t nightlightDelayMs = 10;
byte briNlT = 0; unsigned long nightlightStartTime;
byte effectCurrent = 0; byte briNlT = 0; //current nightlight brightness
byte effectSpeed = 75;
byte effectIntensity = 128; //brightness
bool onlyAP = false; byte bri = briS;
byte briOld = 0;
byte briT = 0;
byte briIT = 0;
byte briLast = 127; //brightness before turned off. Used for toggle function
//button
bool buttonPressedBefore = false;
unsigned long buttonPressedTime = 0;
//notifications
bool notifyDirectDefault = notifyDirect;
bool receiveNotifications = true;
unsigned long notificationSentTime = 0;
byte notificationSentCallMode = 0;
bool notificationTwoRequired = false;
//effects
byte effectCurrent = effectDefault;
byte effectSpeed = effectSpeedDefault;
byte effectIntensity = effectIntensityDefault;
byte effectPalette = effectPaletteDefault;
//network
bool onlyAP = false; //only Access Point active, no connection to home network
bool udpConnected = false, udpRgbConnected = false; bool udpConnected = false, udpRgbConnected = false;
char cssCol[9][5]={"","","","","",""};
char cssFont[33]="Verdana"; //ui style
char cssCol[6][9]={"","","","","",""};
String cssColorString=""; String cssColorString="";
//NTP stuff bool showWelcomePage = false;
bool ntpConnected = false;
byte currentTimezone = 0;
time_t local = 0;
int utcOffsetSecs = 0;
//hue //hue
char hueError[25] = "Inactive"; char hueError[25] = "Inactive";
@ -187,25 +282,12 @@ uint16_t hueFailCount = 0;
float hueXLast=0, hueYLast=0; float hueXLast=0, hueYLast=0;
uint16_t hueHueLast=0, hueCtLast=0; uint16_t hueHueLast=0, hueCtLast=0;
byte hueSatLast=0, hueBriLast=0; byte hueSatLast=0, hueBriLast=0;
long hueLastRequestSent = 0; unsigned long hueLastRequestSent = 0;
uint32_t huePollIntervalMsTemp = huePollIntervalMs; unsigned long huePollIntervalMsTemp = huePollIntervalMs;
bool hueAttempt = false;
//blynk //overlays
char blynkApiKey[36] = ""; byte overlayCurrent = overlayDefault;
bool blynkEnabled = false;
//e1.31
bool e131Enabled = true;
byte e131Universe = 1;
bool e131Multicast = false;
//overlay stuff
byte overlayDefault = 0;
byte overlayCurrent = 0;
byte overlayMin = 0, overlayMax = ledCount-1;
byte analogClock12pixel = 0;
bool analogClockSecondsTrail = false;
bool analogClock5MinuteMarks = false;
byte overlaySpeed = 200; byte overlaySpeed = 200;
unsigned long overlayRefreshMs = 200; unsigned long overlayRefreshMs = 200;
unsigned long overlayRefreshedTime; unsigned long overlayRefreshedTime;
@ -213,40 +295,54 @@ int overlayArr[6];
uint16_t overlayDur[6]; uint16_t overlayDur[6];
uint16_t overlayPauseDur[6]; uint16_t overlayPauseDur[6];
int nixieClockI = -1; int nixieClockI = -1;
bool nixiePause; bool nixiePause = false;
byte countdownYear=19, countdownMonth=1, countdownDay=1, countdownHour=0, countdownMin=0, countdownSec=0; //year is actual year -2000
bool countdownOverTriggered = true;
//cronixie //cronixie
char cronixieDisplay[] = "HHMMSS";
byte dP[]{0,0,0,0,0,0}; byte dP[]{0,0,0,0,0,0};
bool useAMPM = false;
bool cronixieBacklight = true;
bool countdownMode = false;
bool cronixieInit = false; bool cronixieInit = false;
//countdown
unsigned long countdownTime = 1514764800L;
bool countdownOverTriggered = true;
//timer
byte lastTimerMinute = 0;
byte timerHours[] = {0,0,0,0,0,0,0,0};
byte timerMinutes[] = {0,0,0,0,0,0,0,0};
byte timerMacro[] = {0,0,0,0,0,0,0,0};
byte timerWeekday[] = {255,255,255,255,255,255,255,255}; //weekdays to activate on
//bit pattern of arr elem: 0b11111111: sat,fri,thu,wed,tue,mon,sun,validity
//blynk
bool blynkEnabled = false;
//preset cycling
bool presetCyclingEnabled = false; bool presetCyclingEnabled = false;
byte presetCycleMin = 1, presetCycleMax = 5; byte presetCycleMin = 1, presetCycleMax = 5;
uint16_t presetCycleTime = 1250; uint16_t presetCycleTime = 1250;
unsigned long presetCycledTime = 0; byte presetCycCurr = presetCycleMin; unsigned long presetCycledTime = 0; byte presetCycCurr = presetCycleMin;
bool presetApplyBri = true, presetApplyCol = true, presetApplyFx = true; bool presetApplyBri = true, presetApplyCol = true, presetApplyFx = true;
bool saveCurrPresetCycConf = false; bool saveCurrPresetCycConf = false;
uint16_t arlsTimeoutMillis = 2500;
bool arlsTimeout = false; //realtime
bool receiveDirect = true, enableRealtimeUI = false; bool realtimeActive = false;
bool arlsDisableGammaCorrection = true, arlsForceMaxBri = false;
IPAddress realtimeIP = (0,0,0,0); IPAddress realtimeIP = (0,0,0,0);
unsigned long arlsTimeoutTime = 0; unsigned long realtimeTimeout = 0;
//mqtt
bool mqttInit = false;
long lastMQTTReconnectAttempt = 0;
long lastInterfaceUpdate = 0;
byte interfaceUpdateCallMode = 0;
uint32_t mqttFailedConAttempts = 0;
//auxiliary debug pin
byte auxTime = 0; byte auxTime = 0;
unsigned long auxStartTime = 0; unsigned long auxStartTime = 0;
bool auxActive = false, auxActiveBefore = false; bool auxActive = false, auxActiveBefore = false;
bool showWelcomePage = false;
bool useGammaCorrectionBri = false;
bool useGammaCorrectionRGB = true;
int arlsOffset = 0;
//alexa udp //alexa udp
WiFiUDP UDP; WiFiUDP alexaUDP;
IPAddress ipMulti(239, 255, 255, 250); IPAddress ipMulti(239, 255, 255, 250);
unsigned int portMulti = 1900; unsigned int portMulti = 1900;
String escapedMac; String escapedMac;
@ -255,50 +351,61 @@ String escapedMac;
DNSServer dnsServer; DNSServer dnsServer;
bool dnsActive = false; bool dnsActive = false;
//network time
bool ntpConnected = false;
time_t local = 0;
unsigned long ntpLastSyncTime = 999000000L;
unsigned long ntpPacketSentTime = 999000000L;
IPAddress ntpServerIP;
unsigned int ntpLocalPort = 2390;
#define NTP_PACKET_SIZE 48
//string temp buffer //string temp buffer
#define OMAX 1750 #define OMAX 1750
char obuf[OMAX]; char obuf[OMAX];
uint16_t olen = 0; uint16_t olen = 0;
//server library objects
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
WebServer server(80); WebServer server(80);
#else #else
ESP8266WebServer server(80); ESP8266WebServer server(80);
#endif #endif
E131 e131; HTTPClient* hueClient = NULL;
HTTPClient hueClient; WiFiClient* mqttTCPClient = NULL;
PubSubClient* mqtt = NULL;
ESP8266HTTPUpdateServer httpUpdater; ESP8266HTTPUpdateServer httpUpdater;
//udp interface objects
WiFiUDP notifierUdp, rgbUdp; WiFiUDP notifierUdp, rgbUdp;
WiFiUDP ntpUdp; WiFiUDP ntpUdp;
IPAddress ntpServerIP; E131* e131;
unsigned int ntpLocalPort = 2390;
#define NTP_PACKET_SIZE 48
unsigned long ntpLastSyncTime = 999000000L;
unsigned long ntpPacketSentTime = 999000000L;
//led fx library object
WS2812FX strip = WS2812FX(); WS2812FX strip = WS2812FX();
//debug macros
#ifdef DEBUG #ifdef DEBUG
#define DEBUG_PRINT(x) Serial.print (x) #define DEBUG_PRINT(x) Serial.print (x)
#define DEBUG_PRINTLN(x) Serial.println (x) #define DEBUG_PRINTLN(x) Serial.println (x)
#define DEBUG_PRINTF(x) Serial.printf (x) #define DEBUG_PRINTF(x) Serial.printf (x)
unsigned long debugTime = 0;
int lastWifiState = 3;
unsigned long wifiStateChangedTime = 0;
#else #else
#define DEBUG_PRINT(x) #define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x) #define DEBUG_PRINTLN(x)
#define DEBUG_PRINTF(x) #define DEBUG_PRINTF(x)
#endif #endif
//filesystem
#ifdef USEFS #ifdef USEFS
#include <FS.h>; #include <FS.h>;
File fsUploadFile; File fsUploadFile;
#endif #endif
#ifdef DEBUG //gamma 2.4 lookup table used for color correction
long debugTime = 0;
int lastWifiState = 3;
long wifiStateChangedTime = 0;
#endif
const byte gamma8[] = { const byte gamma8[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
@ -319,8 +426,11 @@ const byte gamma8[] = {
String txd = "Please disable OTA Lock in security settings!"; String txd = "Please disable OTA Lock in security settings!";
//function prototypes
void serveMessage(int,String,String,int=255); void serveMessage(int,String,String,int=255);
//turns all LEDs off and restarts ESP
void reset() void reset()
{ {
briT = 0; briT = 0;
@ -329,7 +439,9 @@ void reset()
ESP.restart(); ESP.restart();
} }
bool oappend(char* txt) //append new c string to temp buffer efficiently
//append new c string to temp buffer efficiently
bool oappend(char* txt)
{ {
uint16_t len = strlen(txt); uint16_t len = strlen(txt);
if (olen + len >= OMAX) return false; //buffer full if (olen + len >= OMAX) return false; //buffer full
@ -338,39 +450,57 @@ bool oappend(char* txt) //append new c string to temp buffer efficiently
return true; return true;
} }
bool oappendi(int i) //append new number to temp buffer efficiently
//append new number to temp buffer efficiently
bool oappendi(int i)
{ {
char s[11]; char s[11];
sprintf(s,"%ld", i); sprintf(s,"%ld", i);
return oappend(s); return oappend(s);
} }
//boot starts here
void setup() { void setup() {
wledInit(); wledInit();
} }
//main program loop
void loop() { void loop() {
server.handleClient(); server.handleClient();
handleSerial(); handleSerial();
handleNotifications(); handleNotifications();
handleTransitions(); handleTransitions();
userLoop(); userLoop();
yield(); yield();
handleButton(); handleButton();
handleNetworkTime(); handleNetworkTime();
if (aOtaEnabled) ArduinoOTA.handle(); if (!onlyAP)
handleAlexa(); {
handleAlexa();
handleMQTT();
}
handleOverlays(); handleOverlays();
if (!arlsTimeout) //block stuff if WARLS/Adalight is enabled
yield();
if (!realtimeActive) //block stuff if WARLS/Adalight is enabled
{ {
if (dnsActive) dnsServer.processNextRequest(); if (dnsActive) dnsServer.processNextRequest();
handleHue(); if (aOtaEnabled) ArduinoOTA.handle();
handleNightlight(); handleNightlight();
handleBlynk(); if (!onlyAP) {
handleHue();
handleBlynk();
}
if (briT) strip.service(); //do not update strip if off, prevents flicker on ESP32 if (briT) strip.service(); //do not update strip if off, prevents flicker on ESP32
} }
//DEBUG //DEBUG serial logging
#ifdef DEBUG #ifdef DEBUG
if (millis() - debugTime > 5000) if (millis() - debugTime > 5000)
{ {
@ -384,7 +514,7 @@ void loop() {
wifiStateChangedTime = millis(); wifiStateChangedTime = millis();
} }
lastWifiState = WiFi.status(); lastWifiState = WiFi.status();
DEBUG_PRINT("Wifi state: "); DEBUG_PRINTLN(wifiStateChangedTime); DEBUG_PRINT("State time: "); DEBUG_PRINTLN(wifiStateChangedTime);
DEBUG_PRINT("NTP last sync: "); DEBUG_PRINTLN(ntpLastSyncTime); DEBUG_PRINT("NTP last sync: "); DEBUG_PRINTLN(ntpLastSyncTime);
DEBUG_PRINT("Client IP: "); DEBUG_PRINTLN(WiFi.localIP()); DEBUG_PRINT("Client IP: "); DEBUG_PRINTLN(WiFi.localIP());
debugTime = millis(); debugTime = millis();

View File

@ -6,7 +6,7 @@
#define EEPSIZE 3072 #define EEPSIZE 3072
//eeprom Version code, enables default settings instead of 0 init on update //eeprom Version code, enables default settings instead of 0 init on update
#define EEPVER 7 #define EEPVER 9
//0 -> old version, default //0 -> old version, default
//1 -> 0.4p 1711272 and up //1 -> 0.4p 1711272 and up
//2 -> 0.4p 1711302 and up //2 -> 0.4p 1711302 and up
@ -15,6 +15,8 @@
//5 -> 0.5.1 and up //5 -> 0.5.1 and up
//6 -> 0.6.0 and up //6 -> 0.6.0 and up
//7 -> 0.7.1 and up //7 -> 0.7.1 and up
//8 -> 0.8.0-a and up
//9 -> 0.8.0
/* /*
* Erase all configuration data * Erase all configuration data
@ -28,6 +30,25 @@ void clearEEPROM()
EEPROM.commit(); EEPROM.commit();
} }
void writeStringToEEPROM(uint16_t pos, char* str, uint16_t len)
{
for (int i = 0; i < len; ++i)
{
EEPROM.write(pos + i, str[i]);
if (str[i] == 0) return;
}
}
void readStringFromEEPROM(uint16_t pos, char* str, uint16_t len)
{
for (int i = 0; i < len; ++i)
{
str[i] = EEPROM.read(pos + i);
if (str[i] == 0) return;
}
str[len] = 0; //make sure every string is properly terminated. str must be at least len +1 big.
}
/* /*
* Write configuration to flash * Write configuration to flash
*/ */
@ -39,26 +60,12 @@ void saveSettingsToEEPROM()
EEPROM.write(233, 233); EEPROM.write(233, 233);
} }
for (int i = 0; i < 32; ++i) writeStringToEEPROM( 0, clientSSID, 32);
{ writeStringToEEPROM( 32, clientPass, 64);
EEPROM.write(i, clientSSID[i]); writeStringToEEPROM( 96, cmDNS, 32);
} writeStringToEEPROM(128, apSSID, 32);
for (int i = 32; i < 96; ++i) writeStringToEEPROM(160, apPass, 64);
{
EEPROM.write(i, clientPass[i-32]);
}
for (int i = 96; i < 128; ++i)
{
EEPROM.write(i, cmDNS[i-96]);
}
for (int i = 128; i < 160; ++i)
{
EEPROM.write(i, apSSID[i-128]);
}
for (int i = 160; i < 224; ++i)
{
EEPROM.write(i, apPass[i-160]);
}
EEPROM.write(224, nightlightDelayMins); EEPROM.write(224, nightlightDelayMins);
EEPROM.write(225, nightlightFade); EEPROM.write(225, nightlightFade);
EEPROM.write(226, notifyDirectDefault); EEPROM.write(226, notifyDirectDefault);
@ -69,96 +76,92 @@ void saveSettingsToEEPROM()
EEPROM.write(231, notifyTwice); EEPROM.write(231, notifyTwice);
EEPROM.write(232, buttonEnabled); EEPROM.write(232, buttonEnabled);
//233 reserved for first boot flag //233 reserved for first boot flag
for (int i = 0; i<4; i++) //ip addresses for (int i = 0; i<4; i++) //ip addresses
{ {
EEPROM.write(234+i, staticIP[i]); EEPROM.write(234+i, staticIP[i]);
EEPROM.write(238+i, staticGateway[i]); EEPROM.write(238+i, staticGateway[i]);
EEPROM.write(242+i, staticSubnet[i]); EEPROM.write(242+i, staticSubnet[i]);
} }
EEPROM.write(246, colS[0]); EEPROM.write(246, colS[0]);
EEPROM.write(247, colS[1]); EEPROM.write(247, colS[1]);
EEPROM.write(248, colS[2]); EEPROM.write(248, colS[2]);
EEPROM.write(249, briS); EEPROM.write(249, briS);
EEPROM.write(250, receiveNotificationBrightness); EEPROM.write(250, receiveNotificationBrightness);
EEPROM.write(251, fadeTransition); EEPROM.write(251, fadeTransition);
EEPROM.write(252, reverseMode); EEPROM.write(252, reverseMode);
EEPROM.write(253, (transitionDelayDefault >> 0) & 0xFF); EEPROM.write(253, (transitionDelayDefault >> 0) & 0xFF);
EEPROM.write(254, (transitionDelayDefault >> 8) & 0xFF); EEPROM.write(254, (transitionDelayDefault >> 8) & 0xFF);
EEPROM.write(255, briMultiplier); EEPROM.write(255, briMultiplier);
//255,250,231,230,226 notifier bytes //255,250,231,230,226 notifier bytes
for (int i = 256; i < 288; ++i) writeStringToEEPROM(256, otaPass, 32);
{
EEPROM.write(i, otaPass[i-256]);
}
EEPROM.write(288, nightlightTargetBri); EEPROM.write(288, nightlightTargetBri);
EEPROM.write(289, otaLock); EEPROM.write(289, otaLock);
EEPROM.write(290, (udpPort >> 0) & 0xFF); EEPROM.write(290, (udpPort >> 0) & 0xFF);
EEPROM.write(291, (udpPort >> 8) & 0xFF); EEPROM.write(291, (udpPort >> 8) & 0xFF);
for (int i = 292; i < 324; ++i) writeStringToEEPROM(292, serverDescription, 32);
{
EEPROM.write(i, serverDescription[i-292]);
}
EEPROM.write(324, effectDefault); EEPROM.write(324, effectDefault);
EEPROM.write(325, effectSpeedDefault); EEPROM.write(325, effectSpeedDefault);
EEPROM.write(326, effectIntensityDefault); EEPROM.write(326, effectIntensityDefault);
EEPROM.write(327, ntpEnabled); EEPROM.write(327, ntpEnabled);
EEPROM.write(328, currentTimezone); EEPROM.write(328, currentTimezone);
EEPROM.write(329, useAMPM); EEPROM.write(329, useAMPM);
EEPROM.write(330, useGammaCorrectionBri); EEPROM.write(330, useGammaCorrectionBri);
EEPROM.write(331, useGammaCorrectionRGB); EEPROM.write(331, useGammaCorrectionRGB);
EEPROM.write(332, overlayDefault); EEPROM.write(332, overlayDefault);
EEPROM.write(333, alexaEnabled); EEPROM.write(333, alexaEnabled);
for (int i = 334; i < 366; ++i) writeStringToEEPROM(334, alexaInvocationName, 32);
{ EEPROM.write(366, notifyAlexa);
EEPROM.write(i, alexaInvocationName[i-334]);
}
EEPROM.write(366, alexaNotify);
EEPROM.write(367, (arlsOffset>=0)); EEPROM.write(367, (arlsOffset>=0));
EEPROM.write(368, abs(arlsOffset)); EEPROM.write(368, abs(arlsOffset));
EEPROM.write(369, turnOnAtBoot); EEPROM.write(369, turnOnAtBoot);
EEPROM.write(370, useHSBDefault); EEPROM.write(370, useHSBDefault);
EEPROM.write(371, whiteS); EEPROM.write(371, whiteS);
EEPROM.write(372, useRGBW); EEPROM.write(372, useRGBW);
EEPROM.write(373, sweepTransition); EEPROM.write(373, effectPaletteDefault);
EEPROM.write(374, sweepDirection); EEPROM.write(374, strip.paletteFade);
EEPROM.write(375, apWaitTimeSecs); EEPROM.write(375, apWaitTimeSecs);
EEPROM.write(376, recoveryAPDisabled); EEPROM.write(376, recoveryAPDisabled);
EEPROM.write(377, EEPVER); //eeprom was updated to latest EEPROM.write(377, EEPVER); //eeprom was updated to latest
EEPROM.write(378, colSecS[0]); EEPROM.write(378, colSecS[0]);
EEPROM.write(379, colSecS[1]); EEPROM.write(379, colSecS[1]);
EEPROM.write(380, colSecS[2]); EEPROM.write(380, colSecS[2]);
EEPROM.write(381, whiteSecS); EEPROM.write(381, whiteSecS);
EEPROM.write(382, ccIndex1); EEPROM.write(382, strip.paletteBlend);
EEPROM.write(383, ccIndex2);
EEPROM.write(384, ccNumPrimary);
EEPROM.write(385, ccNumSecondary);
EEPROM.write(386, ccFromStart);
EEPROM.write(387, ccFromEnd);
EEPROM.write(388, ccStep);
EEPROM.write(389, bootPreset); EEPROM.write(389, bootPreset);
EEPROM.write(390, aOtaEnabled); EEPROM.write(390, aOtaEnabled);
EEPROM.write(391, receiveNotificationColor); EEPROM.write(391, receiveNotificationColor);
EEPROM.write(392, receiveNotificationEffects); EEPROM.write(392, receiveNotificationEffects);
EEPROM.write(393, wifiLock); EEPROM.write(393, wifiLock);
EEPROM.write(394, (abs(utcOffsetSecs) >> 0) & 0xFF); EEPROM.write(394, (abs(utcOffsetSecs) >> 0) & 0xFF);
EEPROM.write(395, (abs(utcOffsetSecs) >> 8) & 0xFF); EEPROM.write(395, (abs(utcOffsetSecs) >> 8) & 0xFF);
EEPROM.write(396, (utcOffsetSecs<0)); //is negative EEPROM.write(396, (utcOffsetSecs<0)); //is negative
EEPROM.write(397, initLedsLast); EEPROM.write(397, initLedsLast);
EEPROM.write(398, (ledCount >> 8) & 0xFF); EEPROM.write(398, (ledCount >> 8) & 0xFF);
EEPROM.write(399, disableSecTransition); EEPROM.write(399, !enableSecTransition);
//favorite setting (preset) memory (25 slots/ each 20byte)
//400 - 899 reserved
for (int k=0;k<6;k++){ for (int k=0;k<6;k++){
int in = 900+k*8; int in = 900+k*8;
for (int i=in; i < in+8; ++i) writeStringToEEPROM(in, cssCol[k], 8);
{ }
EEPROM.write(i, cssCol[i-in][k]);
}}
EEPROM.write(948,currentTheme); EEPROM.write(948,currentTheme);
for (int i = 950; i < 982; ++i) writeStringToEEPROM(950, cssFont, 32);
{
EEPROM.write(i, cssFont[i-950]);
}
EEPROM.write(2048, huePollingEnabled); EEPROM.write(2048, huePollingEnabled);
//EEPROM.write(2049, hueUpdatingEnabled); //EEPROM.write(2049, hueUpdatingEnabled);
@ -166,10 +169,7 @@ void saveSettingsToEEPROM()
{ {
EEPROM.write(i, hueIP[i-2050]); EEPROM.write(i, hueIP[i-2050]);
} }
for (int i = 2054; i < 2100; ++i) writeStringToEEPROM(2054, hueApiKey, 46);
{
EEPROM.write(i, hueApiKey[i-2054]);
}
EEPROM.write(2100, (huePollIntervalMs >> 0) & 0xFF); EEPROM.write(2100, (huePollIntervalMs >> 0) & 0xFF);
EEPROM.write(2101, (huePollIntervalMs >> 8) & 0xFF); EEPROM.write(2101, (huePollIntervalMs >> 8) & 0xFF);
EEPROM.write(2102, notifyHue); EEPROM.write(2102, notifyHue);
@ -183,6 +183,7 @@ void saveSettingsToEEPROM()
EEPROM.write(2152, analogClock12pixel); EEPROM.write(2152, analogClock12pixel);
EEPROM.write(2153, analogClock5MinuteMarks); EEPROM.write(2153, analogClock5MinuteMarks);
EEPROM.write(2154, analogClockSecondsTrail); EEPROM.write(2154, analogClockSecondsTrail);
EEPROM.write(2155, countdownMode); EEPROM.write(2155, countdownMode);
EEPROM.write(2156, countdownYear); EEPROM.write(2156, countdownYear);
EEPROM.write(2157, countdownMonth); EEPROM.write(2157, countdownMonth);
@ -192,10 +193,7 @@ void saveSettingsToEEPROM()
EEPROM.write(2161, countdownSec); EEPROM.write(2161, countdownSec);
setCountdown(); setCountdown();
for (int i = 2165; i < 2171; ++i) writeStringToEEPROM(2165, cronixieDisplay, 6);
{
EEPROM.write(i, cronixieDisplay[i-2165]);
}
EEPROM.write(2171, cronixieBacklight); EEPROM.write(2171, cronixieBacklight);
setCronixie(); setCronixie();
@ -210,34 +208,43 @@ void saveSettingsToEEPROM()
EEPROM.write(2190, (e131Universe >> 0) & 0xFF); EEPROM.write(2190, (e131Universe >> 0) & 0xFF);
EEPROM.write(2191, (e131Universe >> 8) & 0xFF); EEPROM.write(2191, (e131Universe >> 8) & 0xFF);
EEPROM.write(2192, e131Multicast); EEPROM.write(2192, e131Multicast);
EEPROM.write(2193, (arlsTimeoutMillis >> 0) & 0xFF); EEPROM.write(2193, (realtimeTimeoutMs >> 0) & 0xFF);
EEPROM.write(2194, (arlsTimeoutMillis >> 8) & 0xFF); EEPROM.write(2194, (realtimeTimeoutMs >> 8) & 0xFF);
EEPROM.write(2195, arlsForceMaxBri); EEPROM.write(2195, arlsForceMaxBri);
EEPROM.write(2196, arlsDisableGammaCorrection); EEPROM.write(2196, arlsDisableGammaCorrection);
EEPROM.write(2200,!receiveDirect); EEPROM.write(2200, !receiveDirect);
EEPROM.write(2201,enableRealtimeUI); EEPROM.write(2201, enableRealtimeUI);
EEPROM.write(2202,uiConfiguration); EEPROM.write(2202, uiConfiguration);
EEPROM.write(2203,autoRGBtoRGBW); EEPROM.write(2203, autoRGBtoRGBW);
EEPROM.write(2204,skipFirstLed); EEPROM.write(2204, skipFirstLed);
if (saveCurrPresetCycConf) if (saveCurrPresetCycConf)
{ {
EEPROM.write(2205,presetCyclingEnabled); EEPROM.write(2205, presetCyclingEnabled);
EEPROM.write(2206,(presetCycleTime >> 0) & 0xFF); EEPROM.write(2206, (presetCycleTime >> 0) & 0xFF);
EEPROM.write(2207,(presetCycleTime >> 8) & 0xFF); EEPROM.write(2207, (presetCycleTime >> 8) & 0xFF);
EEPROM.write(2208,presetCycleMin); EEPROM.write(2208, presetCycleMin);
EEPROM.write(2209,presetCycleMax); EEPROM.write(2209, presetCycleMax);
EEPROM.write(2210,presetApplyBri); EEPROM.write(2210, presetApplyBri);
EEPROM.write(2211,presetApplyCol); EEPROM.write(2211, presetApplyCol);
EEPROM.write(2212,presetApplyFx); EEPROM.write(2212, presetApplyFx);
saveCurrPresetCycConf = false; saveCurrPresetCycConf = false;
} }
for (int i = 2220; i < 2255; ++i) writeStringToEEPROM(2220, blynkApiKey, 35);
for (int i = 0; i < 8; ++i)
{ {
EEPROM.write(i, blynkApiKey[i-2220]); EEPROM.write(2260 + i, timerHours[i] );
EEPROM.write(2270 + i, timerMinutes[i]);
EEPROM.write(2280 + i, timerWeekday[i]);
EEPROM.write(2290 + i, timerMacro[i] );
} }
writeStringToEEPROM(2300, mqttServer, 32);
writeStringToEEPROM(2333, mqttDeviceTopic, 32);
writeStringToEEPROM(2366, mqttGroupTopic, 32);
EEPROM.commit(); EEPROM.commit();
} }
@ -254,47 +261,28 @@ void loadSettingsFromEEPROM(bool first)
} }
int lastEEPROMversion = EEPROM.read(377); //last EEPROM version before update int lastEEPROMversion = EEPROM.read(377); //last EEPROM version before update
for (int i = 0; i < 32; ++i)
{
clientSSID[i] = EEPROM.read(i);
if (clientSSID[i] == 0) break;
}
for (int i = 32; i < 96; ++i) readStringFromEEPROM( 0, clientSSID, 32);
{ readStringFromEEPROM( 32, clientPass, 64);
clientPass[i-32] = EEPROM.read(i); readStringFromEEPROM( 96, cmDNS, 32);
if (clientPass[i-32] == 0) break; readStringFromEEPROM(128, apSSID, 32);
} readStringFromEEPROM(160, apPass, 64);
for (int i = 96; i < 128; ++i)
{
cmDNS[i-96] = EEPROM.read(i);
if (cmDNS[i-96] == 0) break;
}
for (int i = 128; i < 160; ++i)
{
apSSID[i-128] = EEPROM.read(i);
if (apSSID[i-128] == 0) break;
}
for (int i = 160; i < 224; ++i)
{
apPass[i-160] = EEPROM.read(i);
if (apPass[i-160] == 0) break;
}
nightlightDelayMins = EEPROM.read(224); nightlightDelayMins = EEPROM.read(224);
nightlightFade = EEPROM.read(225); nightlightFade = EEPROM.read(225);
notifyDirectDefault = EEPROM.read(226); notifyDirectDefault = EEPROM.read(226);
notifyDirect = notifyDirectDefault; notifyDirect = notifyDirectDefault;
apChannel = EEPROM.read(227); apChannel = EEPROM.read(227);
if (apChannel > 13 || apChannel < 1) apChannel = 1; if (apChannel > 13 || apChannel < 1) apChannel = 1;
apHide = EEPROM.read(228); apHide = EEPROM.read(228);
if (apHide > 1) apHide = 1; if (apHide > 1) apHide = 1;
ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10; ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10;
notifyButton = EEPROM.read(230); notifyButton = EEPROM.read(230);
notifyTwice = EEPROM.read(231); notifyTwice = EEPROM.read(231);
buttonEnabled = EEPROM.read(232); buttonEnabled = EEPROM.read(232);
staticIP[0] = EEPROM.read(234); staticIP[0] = EEPROM.read(234);
staticIP[1] = EEPROM.read(235); staticIP[1] = EEPROM.read(235);
staticIP[2] = EEPROM.read(236); staticIP[2] = EEPROM.read(236);
@ -307,6 +295,7 @@ void loadSettingsFromEEPROM(bool first)
staticSubnet[1] = EEPROM.read(243); staticSubnet[1] = EEPROM.read(243);
staticSubnet[2] = EEPROM.read(244); staticSubnet[2] = EEPROM.read(244);
staticSubnet[3] = EEPROM.read(245); staticSubnet[3] = EEPROM.read(245);
colS[0] = EEPROM.read(246); col[0] = colS[0]; colS[0] = EEPROM.read(246); col[0] = colS[0];
colS[1] = EEPROM.read(247); col[1] = colS[1]; colS[1] = EEPROM.read(247); col[1] = colS[1];
colS[2] = EEPROM.read(248); col[2] = colS[2]; colS[2] = EEPROM.read(248); col[2] = colS[2];
@ -322,20 +311,14 @@ void loadSettingsFromEEPROM(bool first)
transitionDelay = transitionDelayDefault; transitionDelay = transitionDelayDefault;
briMultiplier = EEPROM.read(255); briMultiplier = EEPROM.read(255);
for (int i = 256; i < 288; ++i) readStringFromEEPROM(256, otaPass, 32);
{
otaPass[i-256] = EEPROM.read(i);
if (otaPass[i-256] == 0) break;
}
nightlightTargetBri = EEPROM.read(288); nightlightTargetBri = EEPROM.read(288);
otaLock = EEPROM.read(289); otaLock = EEPROM.read(289);
udpPort = ((EEPROM.read(290) << 0) & 0xFF) + ((EEPROM.read(291) << 8) & 0xFF00); udpPort = ((EEPROM.read(290) << 0) & 0xFF) + ((EEPROM.read(291) << 8) & 0xFF00);
for (int i = 292; i < 324; ++i) readStringFromEEPROM(292, serverDescription, 32);
{
serverDescription[i-292] = EEPROM.read(i);
if (serverDescription[i-292] == 0) break;
}
effectDefault = EEPROM.read(324); effectCurrent = effectDefault; effectDefault = EEPROM.read(324); effectCurrent = effectDefault;
effectSpeedDefault = EEPROM.read(325); effectSpeed = effectSpeedDefault; effectSpeedDefault = EEPROM.read(325); effectSpeed = effectSpeedDefault;
ntpEnabled = EEPROM.read(327); ntpEnabled = EEPROM.read(327);
@ -344,22 +327,22 @@ void loadSettingsFromEEPROM(bool first)
useGammaCorrectionBri = EEPROM.read(330); useGammaCorrectionBri = EEPROM.read(330);
useGammaCorrectionRGB = EEPROM.read(331); useGammaCorrectionRGB = EEPROM.read(331);
overlayDefault = EEPROM.read(332); overlayDefault = EEPROM.read(332);
if (lastEEPROMversion < 8 && overlayDefault > 0) overlayDefault--; //overlay mode 1 (solid) was removed
alexaEnabled = EEPROM.read(333); alexaEnabled = EEPROM.read(333);
for (int i = 334; i < 366; ++i) readStringFromEEPROM(334, alexaInvocationName, 32);
{
alexaInvocationName[i-334] = EEPROM.read(i); notifyAlexa = EEPROM.read(366);
if (alexaInvocationName[i-334] == 0) break;
}
alexaNotify = EEPROM.read(366);
arlsOffset = EEPROM.read(368); arlsOffset = EEPROM.read(368);
if (!EEPROM.read(367)) arlsOffset = -arlsOffset; if (!EEPROM.read(367)) arlsOffset = -arlsOffset;
turnOnAtBoot = EEPROM.read(369); turnOnAtBoot = EEPROM.read(369);
useHSBDefault = EEPROM.read(370); useHSBDefault = EEPROM.read(370);
whiteS = EEPROM.read(371); white = whiteS; whiteS = EEPROM.read(371); white = whiteS;
useRGBW = EEPROM.read(372); useRGBW = EEPROM.read(372);
sweepTransition = EEPROM.read(373); effectPaletteDefault = EEPROM.read(373); effectPalette = effectPaletteDefault;
sweepDirection = EEPROM.read(374); //374 - strip.paletteFade
if (lastEEPROMversion > 0) { if (lastEEPROMversion > 0) {
apWaitTimeSecs = EEPROM.read(375); apWaitTimeSecs = EEPROM.read(375);
recoveryAPDisabled = EEPROM.read(376); recoveryAPDisabled = EEPROM.read(376);
@ -369,15 +352,7 @@ void loadSettingsFromEEPROM(bool first)
colSecS[0] = EEPROM.read(378); colSec[0] = colSecS[0]; colSecS[0] = EEPROM.read(378); colSec[0] = colSecS[0];
colSecS[1] = EEPROM.read(379); colSec[1] = colSecS[1]; colSecS[1] = EEPROM.read(379); colSec[1] = colSecS[1];
colSecS[2] = EEPROM.read(380); colSec[2] = colSecS[2]; colSecS[2] = EEPROM.read(380); colSec[2] = colSecS[2];
whiteSecS = EEPROM.read(381); whiteSec = whiteSecS; whiteSecS = EEPROM.read(381); whiteSec = whiteSecS;
ccIndex1 = EEPROM.read(382);
ccIndex2 = EEPROM.read(383);
ccNumPrimary = EEPROM.read(384);
ccNumSecondary = EEPROM.read(385);
ccFromStart = EEPROM.read(386);
ccFromEnd = EEPROM.read(387);
ccStep = EEPROM.read(388);
strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd);
} }
if (lastEEPROMversion > 3) { if (lastEEPROMversion > 3) {
effectIntensityDefault = EEPROM.read(326); effectIntensity = effectIntensityDefault; effectIntensityDefault = EEPROM.read(326); effectIntensity = effectIntensityDefault;
@ -385,11 +360,7 @@ void loadSettingsFromEEPROM(bool first)
receiveNotificationColor = EEPROM.read(391); receiveNotificationColor = EEPROM.read(391);
receiveNotificationEffects = EEPROM.read(392); receiveNotificationEffects = EEPROM.read(392);
for (int i = 950; i < 982; ++i) readStringFromEEPROM(950, cssFont, 32);
{
cssFont[i-950] = EEPROM.read(i);
if (cssFont[i-950] == 0) break;
}
} else //keep receiving notification behavior from pre0.5.0 after update } else //keep receiving notification behavior from pre0.5.0 after update
{ {
receiveNotificationColor = receiveNotificationBrightness; receiveNotificationColor = receiveNotificationBrightness;
@ -404,11 +375,8 @@ void loadSettingsFromEEPROM(bool first)
hueIP[i-2050] = EEPROM.read(i); hueIP[i-2050] = EEPROM.read(i);
} }
for (int i = 2054; i < 2100; ++i) readStringFromEEPROM(2054, hueApiKey, 46);
{
hueApiKey[i-2054] = EEPROM.read(i);
if (hueApiKey[i-2054] == 0) break;
}
huePollIntervalMs = ((EEPROM.read(2100) << 0) & 0xFF) + ((EEPROM.read(2101) << 8) & 0xFF00); huePollIntervalMs = ((EEPROM.read(2100) << 0) & 0xFF) + ((EEPROM.read(2101) << 8) & 0xFF00);
notifyHue = EEPROM.read(2102); notifyHue = EEPROM.read(2102);
hueApplyOnOff = EEPROM.read(2103); hueApplyOnOff = EEPROM.read(2103);
@ -431,10 +399,7 @@ void loadSettingsFromEEPROM(bool first)
countdownSec = EEPROM.read(2161); countdownSec = EEPROM.read(2161);
setCountdown(); setCountdown();
for (int i = 2165; i < 2171; ++i) readStringFromEEPROM(2165, cronixieDisplay, 6);
{
cronixieDisplay[i-2165] = EEPROM.read(i);
}
cronixieBacklight = EEPROM.read(2171); cronixieBacklight = EEPROM.read(2171);
macroBoot = EEPROM.read(2175); macroBoot = EEPROM.read(2175);
@ -450,10 +415,32 @@ void loadSettingsFromEEPROM(bool first)
{ {
e131Universe = ((EEPROM.read(2190) << 0) & 0xFF) + ((EEPROM.read(2191) << 8) & 0xFF00); e131Universe = ((EEPROM.read(2190) << 0) & 0xFF) + ((EEPROM.read(2191) << 8) & 0xFF00);
e131Multicast = EEPROM.read(2192); e131Multicast = EEPROM.read(2192);
arlsTimeoutMillis = ((EEPROM.read(2193) << 0) & 0xFF) + ((EEPROM.read(2194) << 8) & 0xFF00); realtimeTimeoutMs = ((EEPROM.read(2193) << 0) & 0xFF) + ((EEPROM.read(2194) << 8) & 0xFF00);
arlsForceMaxBri = EEPROM.read(2195); arlsForceMaxBri = EEPROM.read(2195);
arlsDisableGammaCorrection = EEPROM.read(2196); arlsDisableGammaCorrection = EEPROM.read(2196);
} }
if (lastEEPROMversion > 7)
{
strip.paletteFade = EEPROM.read(374);
strip.paletteBlend = EEPROM.read(382);
for (int i = 0; i < 8; ++i)
{
timerHours[i] = EEPROM.read(2260 + i);
timerMinutes[i] = EEPROM.read(2270 + i);
timerWeekday[i] = EEPROM.read(2280 + i);
if (timerWeekday[i] == 0) timerWeekday[i] = 255;
timerMacro[i] = EEPROM.read(2290 + i);
}
}
if (lastEEPROMversion > 8)
{
readStringFromEEPROM(2300, mqttServer, 32);
readStringFromEEPROM(2333, mqttDeviceTopic, 32);
readStringFromEEPROM(2366, mqttGroupTopic, 32);
}
receiveDirect = !EEPROM.read(2200); receiveDirect = !EEPROM.read(2200);
enableRealtimeUI = EEPROM.read(2201); enableRealtimeUI = EEPROM.read(2201);
@ -477,19 +464,13 @@ void loadSettingsFromEEPROM(bool first)
presetApplyCol = EEPROM.read(2211); presetApplyCol = EEPROM.read(2211);
presetApplyFx = EEPROM.read(2212); presetApplyFx = EEPROM.read(2212);
} }
for (int i = 2220; i < 2255; ++i)
{
blynkApiKey[i-2220] = EEPROM.read(i);
if (blynkApiKey[i-2220] == 0) break;
}
bootPreset = EEPROM.read(389); bootPreset = EEPROM.read(389);
wifiLock = EEPROM.read(393); wifiLock = EEPROM.read(393);
utcOffsetSecs = ((EEPROM.read(394) << 0) & 0xFF) + ((EEPROM.read(395) << 8) & 0xFF00); utcOffsetSecs = ((EEPROM.read(394) << 0) & 0xFF) + ((EEPROM.read(395) << 8) & 0xFF00);
if (EEPROM.read(396)) utcOffsetSecs = -utcOffsetSecs; //negative if (EEPROM.read(396)) utcOffsetSecs = -utcOffsetSecs; //negative
initLedsLast = EEPROM.read(397); initLedsLast = EEPROM.read(397);
disableSecTransition = EEPROM.read(399); enableSecTransition = !EEPROM.read(399);
//favorite setting (preset) memory (25 slots/ each 20byte) //favorite setting (preset) memory (25 slots/ each 20byte)
//400 - 899 reserved //400 - 899 reserved
@ -497,15 +478,14 @@ void loadSettingsFromEEPROM(bool first)
currentTheme = EEPROM.read(948); currentTheme = EEPROM.read(948);
for (int k=0;k<6;k++){ for (int k=0;k<6;k++){
int in=900+k*8; int in=900+k*8;
for (int i=in; i < in+8; ++i) readStringFromEEPROM(in, cssCol[k], 8);
{ }
if (EEPROM.read(i) == 0) break;
cssCol[i-in][k] =EEPROM.read(i);
}}
//custom macro memory (16 slots/ each 64byte) //custom macro memory (16 slots/ each 64byte)
//1024-2047 reserved //1024-2047 reserved
readStringFromEEPROM(2220, blynkApiKey, 35);
//user MOD memory //user MOD memory
//2944 - 3071 reserved //2944 - 3071 reserved
@ -514,12 +494,13 @@ void loadSettingsFromEEPROM(bool first)
strip.setMode(effectCurrent); strip.setMode(effectCurrent);
strip.setSpeed(effectSpeed); strip.setSpeed(effectSpeed);
strip.setIntensity(effectIntensity); strip.setIntensity(effectIntensity);
strip.setPalette(effectPalette);
overlayCurrent = overlayDefault; overlayCurrent = overlayDefault;
} }
//PRESET PROTOCOL 20 bytes //PRESET PROTOCOL 20 bytes
//0: preset purpose byte 0:invalid 1:valid preset 1.0 //0: preset purpose byte 0:invalid 1:valid preset 1.0
//1:a 2:r 3:g 4:b 5:w 6:er 7:eg 8:eb 9:ew 10:fx 11:sx | custom chase 12:numP 13:numS 14:(0:fs 1:both 2:fe) 15:step 16:ix 17-19:Zeros //1:a 2:r 3:g 4:b 5:w 6:er 7:eg 8:eb 9:ew 10:fx 11:sx | custom chase 12:numP 13:numS 14:(0:fs 1:both 2:fe) 15:step 16:ix 17: fp 18-19:Zeros
void applyPreset(byte index, bool loadBri, bool loadCol, bool loadFX) void applyPreset(byte index, bool loadBri, bool loadCol, bool loadFX)
{ {
@ -545,15 +526,11 @@ void applyPreset(byte index, bool loadBri, bool loadCol, bool loadFX)
effectCurrent = EEPROM.read(i+10); effectCurrent = EEPROM.read(i+10);
effectSpeed = EEPROM.read(i+11); effectSpeed = EEPROM.read(i+11);
effectIntensity = EEPROM.read(i+16); effectIntensity = EEPROM.read(i+16);
ccNumPrimary = EEPROM.read(i+12); effectPalette = EEPROM.read(i+17);
ccNumSecondary = EEPROM.read(i+13);
ccFromEnd = EEPROM.read(i+14);
ccFromStart = (EEPROM.read(i+14)<2);
ccStep = EEPROM.read(i+15);
strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd);
if (lastfx != effectCurrent) strip.setMode(effectCurrent); if (lastfx != effectCurrent) strip.setMode(effectCurrent);
strip.setSpeed(effectSpeed); strip.setSpeed(effectSpeed);
strip.setIntensity(effectIntensity); strip.setIntensity(effectIntensity);
strip.setPalette(effectPalette);
} }
} }
@ -574,14 +551,9 @@ void savePreset(byte index)
EEPROM.write(i+9, whiteSec); EEPROM.write(i+9, whiteSec);
EEPROM.write(i+10, effectCurrent); EEPROM.write(i+10, effectCurrent);
EEPROM.write(i+11, effectSpeed); EEPROM.write(i+11, effectSpeed);
EEPROM.write(i+12, ccNumPrimary);
EEPROM.write(i+13, ccNumSecondary);
byte m = 1;
if (!ccFromStart) m = 2;
if (!ccFromEnd) m = 0;
EEPROM.write(i+14, m);
EEPROM.write(i+15, ccStep);
EEPROM.write(i+16, effectIntensity); EEPROM.write(i+16, effectIntensity);
EEPROM.write(i+17, effectPalette);
EEPROM.commit(); EEPROM.commit();
} }
@ -606,7 +578,7 @@ void applyMacro(byte index)
String mc="win&"; String mc="win&";
mc += loadMacro(index+1); mc += loadMacro(index+1);
mc += "&IN"; //internal, no XML response mc += "&IN"; //internal, no XML response
if (!macroNotify) mc += "&NN"; if (!notifyMacro) mc += "&NN";
String forbidden = "&M="; //dont apply if called by the macro itself to prevent loop String forbidden = "&M="; //dont apply if called by the macro itself to prevent loop
/* /*
* NOTE: loop is still possible if you call a different macro from a macro, which then calls the first macro again. * NOTE: loop is still possible if you call a different macro from a macro, which then calls the first macro again.

View File

@ -2,7 +2,7 @@
* Sending XML status files to client * Sending XML status files to client
*/ */
void XML_response() void XML_response(bool isHTTP)
{ {
olen = 0; olen = 0;
oappend("<?xml version = \"1.0\" ?><vs><ac>"); oappend("<?xml version = \"1.0\" ?><vs><ac>");
@ -39,7 +39,9 @@ void XML_response()
oappendi(effectSpeed); oappendi(effectSpeed);
oappend("</sx><ix>"); oappend("</sx><ix>");
oappendi(effectIntensity); oappendi(effectIntensity);
oappend("</ix><wv>"); oappend("</ix><fp>");
oappendi(effectPalette);
oappend("</fp><wv>");
if (useRGBW && !autoRGBtoRGBW) { if (useRGBW && !autoRGBtoRGBW) {
oappendi(white); oappendi(white);
} else { } else {
@ -50,7 +52,7 @@ void XML_response()
oappend("</md><ds>"); oappend("</md><ds>");
oappend(serverDescription); oappend(serverDescription);
oappend("</ds></vs>"); oappend("</ds></vs>");
server.send(200, "text/xml", obuf); if (isHTTP) server.send(200, "text/xml", obuf);
} }
void sappend(char stype, char* key, int val) //append a setting to string buffer void sappend(char stype, char* key, int val) //append a setting to string buffer
@ -185,17 +187,18 @@ void getSettingsJS(byte subPage) //get values for settings form in javascript
sappend('v',"FX",effectDefault); sappend('v',"FX",effectDefault);
sappend('v',"SX",effectSpeedDefault); sappend('v',"SX",effectSpeedDefault);
sappend('v',"IX",effectIntensityDefault); sappend('v',"IX",effectIntensityDefault);
sappend('v',"FP",effectPaletteDefault);
sappend('c',"GB",useGammaCorrectionBri); sappend('c',"GB",useGammaCorrectionBri);
sappend('c',"GC",useGammaCorrectionRGB); sappend('c',"GC",useGammaCorrectionRGB);
sappend('c',"TF",fadeTransition); sappend('c',"TF",fadeTransition);
sappend('c',"TS",sweepTransition);
sappend('c',"TI",!sweepDirection);
sappend('v',"TD",transitionDelay); sappend('v',"TD",transitionDelay);
sappend('c',"T2",!disableSecTransition); sappend('c',"PF",strip.paletteFade);
sappend('c',"T2",enableSecTransition);
sappend('v',"BF",briMultiplier); sappend('v',"BF",briMultiplier);
sappend('v',"TB",nightlightTargetBri); sappend('v',"TB",nightlightTargetBri);
sappend('v',"TL",nightlightDelayMins); sappend('v',"TL",nightlightDelayMins);
sappend('c',"TW",nightlightFade); sappend('c',"TW",nightlightFade);
sappend('i',"PB",strip.paletteBlend);
sappend('c',"RV",reverseMode); sappend('c',"RV",reverseMode);
sappend('c',"EI",initLedsLast); sappend('c',"EI",initLedsLast);
sappend('c',"SL",skipFirstLed); sappend('c',"SL",skipFirstLed);
@ -230,15 +233,18 @@ void getSettingsJS(byte subPage) //get values for settings form in javascript
sappend('c',"RD",receiveDirect); sappend('c',"RD",receiveDirect);
sappend('c',"EM",e131Multicast); sappend('c',"EM",e131Multicast);
sappend('v',"EU",e131Universe); sappend('v',"EU",e131Universe);
sappend('v',"ET",arlsTimeoutMillis); sappend('v',"ET",realtimeTimeoutMs);
sappend('c',"FB",arlsForceMaxBri); sappend('c',"FB",arlsForceMaxBri);
sappend('c',"RG",arlsDisableGammaCorrection); sappend('c',"RG",arlsDisableGammaCorrection);
sappend('v',"WO",arlsOffset); sappend('v',"WO",arlsOffset);
sappend('c',"RU",enableRealtimeUI); sappend('c',"RU",enableRealtimeUI);
sappend('c',"AL",alexaEnabled); sappend('c',"AL",alexaEnabled);
sappends('s',"AI",alexaInvocationName); sappends('s',"AI",alexaInvocationName);
sappend('c',"SA",alexaNotify); sappend('c',"SA",notifyAlexa);
sappends('s',"BK",(char*)((blynkEnabled)?"Hidden":"")); sappends('s',"BK",(char*)((blynkEnabled)?"Hidden":""));
sappends('s',"MS",mqttServer);
sappends('s',"MD",mqttDeviceTopic);
sappends('s',"MG",mqttGroupTopic);
sappend('v',"H0",hueIP[0]); sappend('v',"H0",hueIP[0]);
sappend('v',"H1",hueIP[1]); sappend('v',"H1",hueIP[1]);
sappend('v',"H2",hueIP[2]); sappend('v',"H2",hueIP[2]);
@ -289,6 +295,15 @@ void getSettingsJS(byte subPage) //get values for settings form in javascript
sappend('v',"ML",macroLongPress); sappend('v',"ML",macroLongPress);
sappend('v',"MC",macroCountdown); sappend('v',"MC",macroCountdown);
sappend('v',"MN",macroNl); sappend('v',"MN",macroNl);
k[2] = 0; //Time macros
for (int i = 0; i<8; i++)
{
k[1] = 48+i; //ascii 0,1,2,3
k[0] = 'H'; sappend('v',k,timerHours[i]);
k[0] = 'N'; sappend('v',k,timerMinutes[i]);
k[0] = 'T'; sappend('v',k,timerMacro[i]);
}
} }
if (subPage == 6) if (subPage == 6)

View File

@ -13,6 +13,8 @@ void _setRandomColor(bool _sec,bool fromButton=false)
if (fromButton) colorUpdated(2); if (fromButton) colorUpdated(2);
} }
//called upon POST settings form submit
void handleSettingsSet(byte subPage) void handleSettingsSet(byte subPage)
{ {
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec //0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec
@ -21,60 +23,42 @@ void handleSettingsSet(byte subPage)
//WIFI SETTINGS //WIFI SETTINGS
if (subPage == 1) if (subPage == 1)
{ {
if (server.hasArg("CS")) strcpy(clientSSID,server.arg("CS").c_str()); strcpy(clientSSID,server.arg("CS").c_str());
if (server.hasArg("CP")) if (server.arg("CP").charAt(0) != '*') strcpy(clientPass, server.arg("CP").c_str());
{
if (!server.arg("CP").indexOf('*') == 0) strcpy(cmDNS, server.arg("CM").c_str());
{
strcpy(clientPass,server.arg("CP").c_str()); int t = server.arg("AT").toInt(); if (t > 9 && t <= 255) apWaitTimeSecs = t;
} strcpy(apSSID, server.arg("AS").c_str());
}
if (server.hasArg("CM")) strcpy(cmDNS,server.arg("CM").c_str());
if (server.hasArg("AT"))
{
int i = server.arg("AT").toInt();
if (i >= 0 && i <= 255) apWaitTimeSecs = i;
}
if (server.hasArg("AS")) strcpy(apSSID,server.arg("AS").c_str());
apHide = server.hasArg("AH"); apHide = server.hasArg("AH");
if (server.hasArg("AP")) if (server.arg("AP").charAt(0) != '*') strcpy(apPass, server.arg("AP").c_str());
{ t = server.arg("AC").toInt(); if (t > 0 && t < 14) apChannel = t;
if (server.arg("AP").charAt(0) != '*') strcpy(apPass,server.arg("AP").c_str());
} char k[3]; k[2] = 0;
if (server.hasArg("AC"))
{
int chan = server.arg("AC").toInt();
if (chan > 0 && chan < 14) apChannel = chan;
}
char k[3]; k[2] = 0; int j = 0;
for (int i = 0; i<4; i++) for (int i = 0; i<4; i++)
{ {
k[1] = i+48; k[1] = i+48;//ascii 0,1,2,3
k[0] = 'I'; //static IP k[0] = 'I'; //static IP
if (server.hasArg(k)) j = server.arg(k).toInt(); staticIP[i] = server.arg(k).toInt();
if (j >= 0 && j <= 255) staticIP[i] = j;
k[0] = 'G'; //gateway k[0] = 'G'; //gateway
if (server.hasArg(k)) j = server.arg(k).toInt(); staticGateway[i] = server.arg(k).toInt();
if (j >= 0 && j <= 255) staticGateway[i] = j;
k[0] = 'S'; //subnet k[0] = 'S'; //subnet
if (server.hasArg(k)) j = server.arg(k).toInt(); staticSubnet[i] = server.arg(k).toInt();
if (j >= 0 && j <= 255) staticSubnet[i] = j;
} }
} }
//LED SETTINGS //LED SETTINGS
if (subPage == 2) if (subPage == 2)
{ {
if (server.hasArg("LC")) int t = server.arg("LC").toInt();
{ if (t > 0 && t <= 1200) ledCount = t;
int i = server.arg("LC").toInt(); //RMT eats up too much RAM
if (i > 0 && i <= 1200) ledCount = i; #ifdef ARDUINO_ARCH_ESP32
//RMT eats up too much RAM if (ledCount > 600) ledCount = 600;
#ifdef ARDUINO_ARCH_ESP32 #endif
if (ledCount > 600) ledCount = 600;
#endif
}
ccIndex2 = ledCount -1;
useRGBW = server.hasArg("EW"); useRGBW = server.hasArg("EW");
autoRGBtoRGBW = server.hasArg("AW"); autoRGBtoRGBW = server.hasArg("AW");
if (server.hasArg("IS")) //ignore settings and save current brightness, colors and fx as default if (server.hasArg("IS")) //ignore settings and save current brightness, colors and fx as default
@ -82,128 +66,76 @@ void handleSettingsSet(byte subPage)
colS[0] = col[0]; colS[0] = col[0];
colS[1] = col[1]; colS[1] = col[1];
colS[2] = col[2]; colS[2] = col[2];
if (useRGBW) whiteS = white; colSecS[0] = colSec[0];
colSecS[1] = colSec[1];
colSecS[2] = colSec[2];
whiteS = white;
whiteSecS = whiteSec;
briS = bri; briS = bri;
effectDefault = effectCurrent; effectDefault = effectCurrent;
effectSpeedDefault = effectSpeed; effectSpeedDefault = effectSpeed;
effectIntensityDefault = effectIntensity;
effectPaletteDefault = effectPalette;
} else { } else {
if (server.hasArg("CR")) colS[0] = server.arg("CR").toInt();
{ colS[1] = server.arg("CG").toInt();
int i = server.arg("CR").toInt(); colS[2] = server.arg("CB").toInt();
if (i >= 0 && i <= 255) colS[0] = i; colSecS[0] = server.arg("SR").toInt();
} colSecS[1] = server.arg("SG").toInt();
if (server.hasArg("CG")) colSecS[2] = server.arg("SB").toInt();
{ whiteS = server.arg("CW").toInt();
int i = server.arg("CG").toInt(); whiteSecS = server.arg("SW").toInt();
if (i >= 0 && i <= 255) colS[1] = i; briS = server.arg("CA").toInt();
} effectDefault = server.arg("FX").toInt();
if (server.hasArg("CB")) effectSpeedDefault = server.arg("SX").toInt();
{ effectIntensityDefault = server.arg("IX").toInt();
int i = server.arg("CB").toInt(); effectPaletteDefault = server.arg("FP").toInt();
if (i >= 0 && i <= 255) colS[2] = i;
}
if (server.hasArg("SR"))
{
int i = server.arg("SR").toInt();
if (i >= 0 && i <= 255) colSecS[0] = i;
}
if (server.hasArg("SG"))
{
int i = server.arg("SG").toInt();
if (i >= 0 && i <= 255) colSecS[1] = i;
}
if (server.hasArg("SB"))
{
int i = server.arg("SB").toInt();
if (i >= 0 && i <= 255) colSecS[2] = i;
}
if (server.hasArg("SW"))
{
int i = server.arg("SW").toInt();
if (i >= 0 && i <= 255) whiteSecS = i;
}
if (server.hasArg("CW"))
{
int i = server.arg("CW").toInt();
if (i >= 0 && i <= 255) whiteS = i;
}
if (server.hasArg("CA"))
{
int i = server.arg("CA").toInt();
if (i >= 0 && i <= 255) briS = i;
}
if (server.hasArg("FX"))
{
int i = server.arg("FX").toInt();
if (i >= 0 && i <= 255) effectDefault = i;
}
if (server.hasArg("SX"))
{
int i = server.arg("SX").toInt();
if (i >= 0 && i <= 255) effectSpeedDefault = i;
}
if (server.hasArg("IX"))
{
int i = server.arg("IX").toInt();
if (i >= 0 && i <= 255) effectIntensityDefault = i;
}
} }
saveCurrPresetCycConf = server.hasArg("PC"); saveCurrPresetCycConf = server.hasArg("PC");
turnOnAtBoot = server.hasArg("BO"); turnOnAtBoot = server.hasArg("BO");
if (server.hasArg("BP")) t = server.arg("BP").toInt();
{ if (t <= 25) bootPreset = t;
int i = server.arg("BP").toInt();
if (i >= 0 && i <= 25) bootPreset = i;
}
useGammaCorrectionBri = server.hasArg("GB"); useGammaCorrectionBri = server.hasArg("GB");
useGammaCorrectionRGB = server.hasArg("GC"); useGammaCorrectionRGB = server.hasArg("GC");
fadeTransition = server.hasArg("TF"); fadeTransition = server.hasArg("TF");
sweepTransition = server.hasArg("TS"); t = server.arg("TD").toInt();
sweepDirection = !server.hasArg("TI"); if (t > 0) transitionDelay = t;
if (server.hasArg("TD")) transitionDelayDefault = t;
{ strip.paletteFade = server.hasArg("PF");
int i = server.arg("TD").toInt(); enableSecTransition = server.hasArg("T2");
if (i > 0){
transitionDelay = i; nightlightTargetBri = server.arg("TB").toInt();
} t = server.arg("TL").toInt();
} if (t > 0) nightlightDelayMins = t;
disableSecTransition = !server.hasArg("T2");
if (server.hasArg("TB"))
{
nightlightTargetBri = server.arg("TB").toInt();
}
if (server.hasArg("TL"))
{
int i = server.arg("TL").toInt();
if (i > 0) nightlightDelayMins = i;
}
nightlightFade = server.hasArg("TW"); nightlightFade = server.hasArg("TW");
reverseMode = server.hasArg("RV");
t = server.arg("PB").toInt();
if (t >= 0 && t < 4) strip.paletteBlend = t;
initLedsLast = server.hasArg("EI"); initLedsLast = server.hasArg("EI");
reverseMode = server.hasArg("RV");
strip.setReverseMode(reverseMode); strip.setReverseMode(reverseMode);
skipFirstLed = server.hasArg("SL"); skipFirstLed = server.hasArg("SL");
if (server.hasArg("BF")) t = server.arg("BF").toInt();
{ if (t > 0) briMultiplier = t;
int i = server.arg("BF").toInt();
if (i > 0) briMultiplier = i;
}
} }
//UI //UI
if (subPage == 3) if (subPage == 3)
{ {
if (server.hasArg("UI")) uiConfiguration = server.arg("UI").toInt(); int t = server.arg("UI").toInt();
if (server.hasArg("DS")) strcpy(serverDescription,server.arg("DS").c_str()); if (t >= 0 && t < 3) uiConfiguration = t;
strcpy(serverDescription, server.arg("DS").c_str());
useHSBDefault = server.hasArg("MD"); useHSBDefault = server.hasArg("MD");
useHSB = useHSBDefault; useHSB = useHSBDefault;
if (server.hasArg("TH")) currentTheme = server.arg("TH").toInt(); currentTheme = server.arg("TH").toInt();
char k[3]; k[0]='C'; k[2]=0; char k[3]; k[0]='C'; k[2]=0;
for(int i=0;i<6;i++) for(int i=0;i<6;i++)
{ {
k[1] = i+48; k[1] = i+48;
if (server.hasArg(k)) strcpy(cssCol[i],server.arg(k).c_str()); strcpy(cssCol[i],server.arg(k).c_str());
} }
if (server.hasArg("CF")) strcpy(cssFont,server.arg("CF").c_str()); strcpy(cssFont,server.arg("CF").c_str());
buildCssColorString(); buildCssColorString();
} }
@ -211,10 +143,8 @@ void handleSettingsSet(byte subPage)
if (subPage == 4) if (subPage == 4)
{ {
buttonEnabled = server.hasArg("BT"); buttonEnabled = server.hasArg("BT");
if (server.hasArg("UP")) int t = server.arg("UP").toInt();
{ if (t > 0) udpPort = t;
udpPort = server.arg("UP").toInt();
}
receiveNotificationBrightness = server.hasArg("RB"); receiveNotificationBrightness = server.hasArg("RB");
receiveNotificationColor = server.hasArg("RC"); receiveNotificationColor = server.hasArg("RC");
receiveNotificationEffects = server.hasArg("RX"); receiveNotificationEffects = server.hasArg("RX");
@ -223,45 +153,41 @@ void handleSettingsSet(byte subPage)
notifyDirect = notifyDirectDefault; notifyDirect = notifyDirectDefault;
notifyButton = server.hasArg("SB"); notifyButton = server.hasArg("SB");
notifyTwice = server.hasArg("S2"); notifyTwice = server.hasArg("S2");
receiveDirect = server.hasArg("RD"); receiveDirect = server.hasArg("RD");
if (server.hasArg("EU")) e131Multicast = server.hasArg("EM");
{ t = server.arg("EU").toInt();
int i = server.arg("EU").toInt(); if (t > 0 && t <= 63999) e131Universe = t;
if (i > 0 && i <= 63999) arlsTimeoutMillis = i; t = server.arg("ET").toInt();
} if (t > 99 && t <= 65000) realtimeTimeoutMs = t;
if (server.hasArg("ET"))
{
int i = server.arg("ET").toInt();
if (i > 99 && i <= 65000) arlsTimeoutMillis = i;
}
arlsForceMaxBri = server.hasArg("FB"); arlsForceMaxBri = server.hasArg("FB");
arlsDisableGammaCorrection = server.hasArg("RG"); arlsDisableGammaCorrection = server.hasArg("RG");
if (server.hasArg("WO")) t = server.arg("WO").toInt();
{ if (t >= -255 && t <= 255) arlsOffset = t;
int i = server.arg("WO").toInt();
if (i >= -255 && i <= 255) arlsOffset = i;
}
enableRealtimeUI = server.hasArg("RU"); enableRealtimeUI = server.hasArg("RU");
alexaEnabled = server.hasArg("AL"); alexaEnabled = server.hasArg("AL");
if (server.hasArg("AI")) strcpy(alexaInvocationName,server.arg("AI").c_str()); strcpy(alexaInvocationName, server.arg("AI").c_str());
alexaNotify = server.hasArg("SA"); notifyAlexa = server.hasArg("SA");
if (server.hasArg("BK") && !server.arg("BK").equals("Hidden")) {strcpy(blynkApiKey,server.arg("BK").c_str()); initBlynk(blynkApiKey);} if (server.hasArg("BK") && !server.arg("BK").equals("Hidden")) {strcpy(blynkApiKey,server.arg("BK").c_str()); initBlynk(blynkApiKey);}
strcpy(mqttServer, server.arg("MS").c_str());
strcpy(mqttDeviceTopic, server.arg("MD").c_str());
strcpy(mqttGroupTopic, server.arg("MG").c_str());
notifyHue = server.hasArg("SH"); notifyHue = server.hasArg("SH");
for (int i=0;i<4;i++){ for (int i=0;i<4;i++){
String a = "H"+String(i); String a = "H"+String(i);
if (server.hasArg(a)) hueIP[i] = server.arg(a).toInt();
hueIP[i] = server.arg(a).toInt();
}
if (server.hasArg("HL"))
{
int i = server.arg("HL").toInt();
if (i > 0) huePollLightId = i;
}
if (server.hasArg("HI"))
{
int i = server.arg("HI").toInt();
if (i > 50) huePollIntervalMs = i;
} }
t = server.arg("HL").toInt();
if (t > 0) huePollLightId = t;
t = server.arg("HI").toInt();
if (t > 50) huePollIntervalMs = t;
hueApplyOnOff = server.hasArg("HO"); hueApplyOnOff = server.hasArg("HO");
hueApplyBri = server.hasArg("HB"); hueApplyBri = server.hasArg("HB");
hueApplyColor = server.hasArg("HC"); hueApplyColor = server.hasArg("HC");
@ -281,54 +207,70 @@ void handleSettingsSet(byte subPage)
{ {
ntpEnabled = server.hasArg("NT"); ntpEnabled = server.hasArg("NT");
useAMPM = !server.hasArg("CF"); useAMPM = !server.hasArg("CF");
if (server.hasArg("TZ")) currentTimezone = server.arg("TZ").toInt(); currentTimezone = server.arg("TZ").toInt();
if (server.hasArg("UO")) utcOffsetSecs = server.arg("UO").toInt(); utcOffsetSecs = server.arg("UO").toInt();
if (ntpEnabled && WiFi.status() == WL_CONNECTED && !ntpConnected) ntpConnected = ntpUdp.begin(ntpLocalPort); //start if not already connected if (ntpEnabled && WiFi.status() == WL_CONNECTED && !ntpConnected) ntpConnected = ntpUdp.begin(ntpLocalPort); //start if not already connected
if (server.hasArg("OL")){ if (server.hasArg("OL")){
overlayDefault = server.arg("OL").toInt(); overlayDefault = server.arg("OL").toInt();
overlayCurrent = overlayDefault; overlayCurrent = overlayDefault;
strip.unlockAll();
} }
if (server.hasArg("O1")) overlayMin = server.arg("O1").toInt();
if (server.hasArg("O2")) overlayMax = server.arg("O2").toInt(); overlayMin = server.arg("O1").toInt();
if (server.hasArg("OM")) analogClock12pixel = server.arg("OM").toInt(); overlayMax = server.arg("O2").toInt();
analogClock12pixel = server.arg("OM").toInt();
analogClock5MinuteMarks = server.hasArg("O5"); analogClock5MinuteMarks = server.hasArg("O5");
analogClockSecondsTrail = server.hasArg("OS"); analogClockSecondsTrail = server.hasArg("OS");
if (server.hasArg("CX")) strcpy(cronixieDisplay,server.arg("CX").c_str()); strcpy(cronixieDisplay,server.arg("CX").c_str());
bool cbOld = cronixieBacklight; bool cbOld = cronixieBacklight;
cronixieBacklight = server.hasArg("CB"); cronixieBacklight = server.hasArg("CB");
if (cbOld != cronixieBacklight && overlayCurrent == 4) if (cbOld != cronixieBacklight && overlayCurrent == 3)
{ {
strip.setCronixieBacklight(cronixieBacklight); overlayRefreshedTime = 0; strip.setCronixieBacklight(cronixieBacklight); overlayRefreshedTime = 0;
} }
countdownMode = server.hasArg("CE"); countdownMode = server.hasArg("CE");
if (server.hasArg("CY")) countdownYear = server.arg("CY").toInt(); countdownYear = server.arg("CY").toInt();
if (server.hasArg("CI")) countdownMonth = server.arg("CI").toInt(); countdownMonth = server.arg("CI").toInt();
if (server.hasArg("CD")) countdownDay = server.arg("CD").toInt(); countdownDay = server.arg("CD").toInt();
if (server.hasArg("CH")) countdownHour = server.arg("CH").toInt(); countdownHour = server.arg("CH").toInt();
if (server.hasArg("CM")) countdownMin = server.arg("CM").toInt(); countdownMin = server.arg("CM").toInt();
if (server.hasArg("CS")) countdownSec = server.arg("CS").toInt(); countdownSec = server.arg("CS").toInt();
for (int i=1;i<17;i++) for (int i=1;i<17;i++)
{ {
String a = "M"+String(i); String a = "M"+String(i);
if (server.hasArg(a)) saveMacro(i,server.arg(a),false); if (server.hasArg(a)) saveMacro(i,server.arg(a),false);
} }
if (server.hasArg("MB")) macroBoot = server.arg("MB").toInt();
if (server.hasArg("A0")) macroAlexaOn = server.arg("A0").toInt(); macroBoot = server.arg("MB").toInt();
if (server.hasArg("A1")) macroAlexaOff = server.arg("A1").toInt(); macroAlexaOn = server.arg("A0").toInt();
if (server.hasArg("MP")) macroButton = server.arg("MP").toInt(); macroAlexaOff = server.arg("A1").toInt();
if (server.hasArg("ML")) macroLongPress = server.arg("ML").toInt(); macroButton = server.arg("MP").toInt();
if (server.hasArg("MC")) macroCountdown = server.arg("MC").toInt(); macroLongPress = server.arg("ML").toInt();
if (server.hasArg("MN")) macroNl = server.arg("MN").toInt(); macroCountdown = server.arg("MC").toInt();
macroNl = server.arg("MN").toInt();
char k[3]; k[2] = 0;
for (int i = 0; i<8; i++)
{
k[1] = i+48;//ascii 0,1,2,3
k[0] = 'H'; //timer hours
timerHours[i] = server.arg(k).toInt();
k[0] = 'N'; //minutes
timerMinutes[i] = server.arg(k).toInt();
k[0] = 'T'; //macros
timerMacro[i] = server.arg(k).toInt();
}
} }
//SECURITY //SECURITY
if (subPage == 6) if (subPage == 6)
{ {
if (server.hasArg("RS")) if (server.hasArg("RS")) //complete factory reset
{ {
clearEEPROM(); clearEEPROM();
serveMessage(200, "All Settings erased.", "Connect to WLED-AP to setup again...",255); serveMessage(200, "All Settings erased.", "Connect to WLED-AP to setup again...",255);
@ -357,15 +299,14 @@ void handleSettingsSet(byte subPage)
} }
} }
saveSettingsToEEPROM(); saveSettingsToEEPROM();
if (subPage == 2) strip.init(useRGBW,ledCount,PIN,skipFirstLed); if (subPage == 2) strip.init(useRGBW,ledCount,skipFirstLed);
} }
bool handleSet(String req) bool handleSet(String req)
{ {
bool effectUpdated = false; bool effectUpdated = false;
if (!(req.indexOf("win") >= 0)) { if (!(req.indexOf("win") >= 0)) return false;
return false;
}
int pos = 0; int pos = 0;
DEBUG_PRINT("API req: "); DEBUG_PRINT("API req: ");
DEBUG_PRINTLN(req); DEBUG_PRINTLN(req);
@ -383,7 +324,7 @@ bool handleSet(String req)
} }
pos = req.indexOf("IN"); pos = req.indexOf("IN");
if (pos < 1) XML_response(); if (pos < 1) XML_response(true);
return true; return true;
//if you save a macro in one request, other commands in that request are ignored due to unwanted behavior otherwise //if you save a macro in one request, other commands in that request are ignored due to unwanted behavior otherwise
} }
@ -448,6 +389,16 @@ bool handleSet(String req)
whiteSec = req.substring(pos + 3).toInt(); whiteSec = req.substring(pos + 3).toInt();
} }
//set color from HEX or 32bit DEC
pos = req.indexOf("CL=");
if (pos > 0) {
colorFromDecOrHexString(col, &white, (char*)req.substring(pos + 3).c_str());
}
pos = req.indexOf("C2=");
if (pos > 0) {
colorFromDecOrHexString(colSec, &whiteSec, (char*)req.substring(pos + 3).c_str());
}
//set 2nd to white //set 2nd to white
pos = req.indexOf("SW"); pos = req.indexOf("SW");
if (pos > 0) { if (pos > 0) {
@ -462,6 +413,7 @@ bool handleSet(String req)
colSec[2] = 255; colSec[2] = 255;
} }
} }
//set 2nd to black //set 2nd to black
pos = req.indexOf("SB"); pos = req.indexOf("SB");
if (pos > 0) { if (pos > 0) {
@ -470,6 +422,7 @@ bool handleSet(String req)
colSec[1] = 0; colSec[1] = 0;
colSec[2] = 0; colSec[2] = 0;
} }
//set to random hue SR=0->1st SR=1->2nd //set to random hue SR=0->1st SR=1->2nd
pos = req.indexOf("SR"); pos = req.indexOf("SR");
if (pos > 0) { if (pos > 0) {
@ -528,6 +481,16 @@ bool handleSet(String req)
effectUpdated = true; effectUpdated = true;
} }
} }
//set effect palette (only for FastLED effects)
pos = req.indexOf("FP=");
if (pos > 0) {
if (effectPalette != req.substring(pos + 3).toInt())
{
effectPalette = req.substring(pos + 3).toInt();
strip.setPalette(effectPalette);
effectUpdated = true;
}
}
//set hue polling light: 0 -off //set hue polling light: 0 -off
pos = req.indexOf("HP="); pos = req.indexOf("HP=");
@ -553,19 +516,6 @@ bool handleSet(String req)
overlayCurrent = req.substring(pos + 3).toInt(); overlayCurrent = req.substring(pos + 3).toInt();
strip.unlockAll(); strip.unlockAll();
} }
//set individual pixel (range) to current color
pos = req.indexOf("&I=");
if (pos > 0){
int index = req.substring(pos + 3).toInt();
pos = req.indexOf("I2=");
if (pos > 0){
int index2 = req.substring(pos + 3).toInt();
strip.setRange(index, index2);
} else
{
strip.setIndividual(index);
}
}
//(un)lock pixel (ranges) //(un)lock pixel (ranges)
pos = req.indexOf("&L="); pos = req.indexOf("&L=");
if (pos > 0){ if (pos > 0){
@ -591,6 +541,7 @@ bool handleSet(String req)
} }
} }
} }
//apply macro //apply macro
pos = req.indexOf("&M="); pos = req.indexOf("&M=");
if (pos > 0) { if (pos > 0) {
@ -605,6 +556,7 @@ bool handleSet(String req)
notifyDirect = false; notifyDirect = false;
} }
} }
//toggle receive UDP direct notifications //toggle receive UDP direct notifications
if (req.indexOf("RN=") > 0) if (req.indexOf("RN=") > 0)
{ {
@ -614,6 +566,7 @@ bool handleSet(String req)
receiveNotifications = false; receiveNotifications = false;
} }
} }
//toggle nightlight mode //toggle nightlight mode
bool aNlDef = false; bool aNlDef = false;
if (req.indexOf("&ND") > 0) aNlDef = true; if (req.indexOf("&ND") > 0) aNlDef = true;
@ -634,12 +587,14 @@ bool handleSet(String req)
nightlightActive = true; nightlightActive = true;
nightlightStartTime = millis(); nightlightStartTime = millis();
} }
//set nightlight target brightness //set nightlight target brightness
pos = req.indexOf("NT="); pos = req.indexOf("NT=");
if (pos > 0) { if (pos > 0) {
nightlightTargetBri = req.substring(pos + 3).toInt(); nightlightTargetBri = req.substring(pos + 3).toInt();
nightlightActiveOld = false; //re-init nightlightActiveOld = false; //re-init
} }
//toggle nightlight fade //toggle nightlight fade
if (req.indexOf("NF=") > 0) if (req.indexOf("NF=") > 0)
{ {
@ -651,6 +606,7 @@ bool handleSet(String req)
} }
nightlightActiveOld = false; //re-init nightlightActiveOld = false; //re-init
} }
//toggle general purpose output //toggle general purpose output
pos = req.indexOf("AX="); pos = req.indexOf("AX=");
if (pos > 0) { if (pos > 0) {
@ -662,9 +618,11 @@ bool handleSet(String req)
if (pos > 0) { if (pos > 0) {
transitionDelay = req.substring(pos + 3).toInt(); transitionDelay = req.substring(pos + 3).toInt();
} }
//main toggle on/off //main toggle on/off
pos = req.indexOf("&T="); pos = req.indexOf("&T=");
if (pos > 0) { if (pos > 0) {
nightlightActive = false; //always disable nightlight when toggling
switch (req.substring(pos + 3).toInt()) switch (req.substring(pos + 3).toInt())
{ {
case 0: if (bri != 0){briLast = bri; bri = 0;} break; //off case 0: if (bri != 0){briLast = bri; bri = 0;} break; //off
@ -679,6 +637,7 @@ bool handleSet(String req)
} }
} }
} }
//deactivate nightlight if target brightness is reached //deactivate nightlight if target brightness is reached
if (bri == nightlightTargetBri) nightlightActive = false; if (bri == nightlightTargetBri) nightlightActive = false;
//set time (unix timestamp) //set time (unix timestamp)
@ -686,6 +645,7 @@ bool handleSet(String req)
if (pos > 0) { if (pos > 0) {
setTime(req.substring(pos+3).toInt()); setTime(req.substring(pos+3).toInt());
} }
//set countdown goal (unix timestamp) //set countdown goal (unix timestamp)
pos = req.indexOf("CT="); pos = req.indexOf("CT=");
if (pos > 0) { if (pos > 0) {
@ -693,19 +653,6 @@ bool handleSet(String req)
if (countdownTime - now() > 0) countdownOverTriggered = false; if (countdownTime - now() > 0) countdownOverTriggered = false;
} }
//set custom chase data
bool _cc_updated = false;
pos = req.indexOf("C0="); if (pos > 0) {ccStart = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("C1="); if (pos > 0) {ccIndex1 = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("C2="); if (pos > 0) {ccIndex2 = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CP="); if (pos > 0) {ccNumPrimary = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CS="); if (pos > 0) {ccNumSecondary = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CM="); if (pos > 0) {ccStep = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CF="); if (pos > 0) {ccFromStart = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CE="); if (pos > 0) {ccFromEnd = (req.substring(pos + 3).toInt()); _cc_updated = true;}
if (ccIndex2 == 255) ccIndex2 = ledCount-1;
if (_cc_updated) strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd);
//set presets //set presets
pos = req.indexOf("P1="); //sets first preset for cycle pos = req.indexOf("P1="); //sets first preset for cycle
if (pos > 0) presetCycleMin = req.substring(pos + 3).toInt(); if (pos > 0) presetCycleMin = req.substring(pos + 3).toInt();
@ -773,7 +720,7 @@ bool handleSet(String req)
{ {
cronixieBacklight = false; cronixieBacklight = false;
} }
if (overlayCurrent == 4) strip.setCronixieBacklight(cronixieBacklight); if (overlayCurrent == 3) strip.setCronixieBacklight(cronixieBacklight);
overlayRefreshedTime = 0; overlayRefreshedTime = 0;
} }
pos = req.indexOf("U0="); //user var 0 pos = req.indexOf("U0="); //user var 0
@ -788,7 +735,7 @@ bool handleSet(String req)
//internal call, does not send XML response //internal call, does not send XML response
pos = req.indexOf("IN"); pos = req.indexOf("IN");
if (pos < 1) XML_response(); if (pos < 1) XML_response(true);
//do not send UDP notifications this time //do not send UDP notifications this time
pos = req.indexOf("NN"); pos = req.indexOf("NN");
if (pos > 0) if (pos > 0)

View File

@ -7,12 +7,8 @@ void handleSerial()
{ {
if (Serial.find("Ada")) if (Serial.find("Ada"))
{ {
if (!arlsTimeout){ if (!realtimeActive && bri == 0) strip.setBrightness(briLast);
if (bri == 0) strip.setBrightness(briLast); arlsLock(realtimeTimeoutMs);
strip.setRange(0, ledCount-1, 0);
strip.setMode(0);
}
arlsLock(arlsTimeoutMillis);
delay(1); delay(1);
byte hi = Serial.read(); byte hi = Serial.read();
byte ledc = Serial.read(); byte ledc = Serial.read();

View File

@ -5,13 +5,12 @@
void wledInit() void wledInit()
{ {
EEPROM.begin(EEPSIZE); EEPROM.begin(EEPSIZE);
showWelcomePage = (EEPROM.read(233) != 233);
ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10; ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10;
//RMT eats up too much RAM //RMT eats up too much RAM
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
if (ledCount > 600) ledCount = 600; if (ledCount > 600) ledCount = 600;
#endif #endif
if (!EEPROM.read(397)) strip.init(EEPROM.read(372),ledCount,PIN,EEPROM.read(2204)); //quick init if (!EEPROM.read(397)) strip.init(EEPROM.read(372),ledCount,EEPROM.read(2204)); //quick init
Serial.begin(115200); Serial.begin(115200);
Serial.setTimeout(50); Serial.setTimeout(50);
@ -27,6 +26,7 @@ void wledInit()
DEBUG_PRINT(clientSSID); DEBUG_PRINT(clientSSID);
buildCssColorString(); buildCssColorString();
userBeginPreConnection(); userBeginPreConnection();
if (strcmp(clientSSID,"Your_Network") == 0) showWelcomePage = true;
initCon(); initCon();
@ -49,220 +49,73 @@ void wledInit()
if (ntpEnabled && WiFi.status() == WL_CONNECTED) if (ntpEnabled && WiFi.status() == WL_CONNECTED)
ntpConnected = ntpUdp.begin(ntpLocalPort); ntpConnected = ntpUdp.begin(ntpLocalPort);
//start captive portal //start captive portal if AP active
if (onlyAP || strlen(apSSID) > 0) if (onlyAP || strlen(apSSID) > 0)
{ {
dnsServer.setErrorReplyCode(DNSReplyCode::NoError); dnsServer.setErrorReplyCode(DNSReplyCode::ServerFailure);
dnsServer.start(53, "*", WiFi.softAPIP()); dnsServer.start(53, "wled.me", WiFi.softAPIP());
dnsActive = true; dnsActive = true;
} }
if (!initLedsLast) strip.service();
//SERVER INIT
//settings page
server.on("/settings", HTTP_GET, [](){
serveSettings(0);
});
server.on("/settings/wifi", HTTP_GET, [](){
if (!(wifiLock && otaLock))
{
serveSettings(1);
}else{
serveMessage(500, "Access Denied", txd, 254);
}
});
server.on("/settings/leds", HTTP_GET, [](){
serveSettings(2);
});
server.on("/settings/ui", HTTP_GET, [](){
serveSettings(3);
});
server.on("/settings/sync", HTTP_GET, [](){
serveSettings(4);
});
server.on("/settings/time", HTTP_GET, [](){
serveSettings(5);
});
server.on("/settings/sec", HTTP_GET, [](){
serveSettings(6);
});
server.on("/favicon.ico", HTTP_GET, [](){
if(!handleFileRead("/favicon.ico"))
{
server.send_P(200, "image/x-icon", favicon, 156);
}
});
server.on("/", HTTP_GET, [](){
serveIndexOrWelcome();
});
server.on("/generate_204", HTTP_GET, [](){ prepareIds(); //UUID from MAC (for Alexa and MQTT)
serveIndexOrWelcome(); if (mqttDeviceTopic[0] == 0)
});
server.on("/fwlink", HTTP_GET, [](){
serveIndexOrWelcome();
});
server.on("/sliders", HTTP_GET, serveIndex);
server.on("/welcome", HTTP_GET, [](){
serveSettings(255);
});
server.on("/reset", HTTP_GET, [](){
serveMessage(200,"Rebooting now...","(takes ~20 seconds, wait for auto-redirect)",79);
reset();
});
server.on("/settings/wifi", HTTP_POST, [](){
if (!(wifiLock && otaLock)) handleSettingsSet(1);
serveMessage(200,"WiFi settings saved.","Rebooting now... (takes ~20 seconds, wait for auto-redirect)",139);
reset();
});
server.on("/settings/leds", HTTP_POST, [](){
handleSettingsSet(2);
serveMessage(200,"LED settings saved.","Redirecting...",1);
});
server.on("/settings/ui", HTTP_POST, [](){
handleSettingsSet(3);
serveMessage(200,"UI settings saved.","Reloading to apply theme...",122);
});
server.on("/settings/sync", HTTP_POST, [](){
handleSettingsSet(4);
if (hueAttempt)
{
serveMessage(200,"Hue setup result",hueError,253);
} else {
serveMessage(200,"Sync settings saved.","Redirecting...",1);
}
hueAttempt = false;
});
server.on("/settings/time", HTTP_POST, [](){
handleSettingsSet(5);
serveMessage(200,"Time settings saved.","Redirecting...",1);
});
server.on("/settings/sec", HTTP_POST, [](){
handleSettingsSet(6);
serveMessage(200,"Security settings saved.","Rebooting now... (takes ~20 seconds, wait for auto-redirect)",139);
reset();
});
server.on("/version", HTTP_GET, [](){
server.send(200, "text/plain", (String)VERSION);
});
server.on("/uptime", HTTP_GET, [](){
server.send(200, "text/plain", (String)millis());
});
server.on("/freeheap", HTTP_GET, [](){
server.send(200, "text/plain", (String)ESP.getFreeHeap());
});
server.on("/power", HTTP_GET, [](){
String val = (String)(int)strip.getPowerEstimate(ledCount,strip.getColor(),strip.getBrightness());
val += "mA currently";
serveMessage(200,val,"This is just an estimate (does not take into account several factors like effects and wire resistance). It is NOT an accurate measurement!",254);
});
server.on("/u", HTTP_GET, [](){
server.setContentLength(strlen_P(PAGE_usermod));
server.send(200, "text/html", "");
server.sendContent_P(PAGE_usermod);
});
server.on("/teapot", HTTP_GET, [](){
serveMessage(418, "418. I'm a teapot.","(Tangible Embedded Advanced Project Of Twinkling)",254);
});
server.on("/build", HTTP_GET, [](){
getBuildInfo();
server.send(200, "text/plain", obuf);
});
//if OTA is allowed
if (!otaLock){
server.on("/edit", HTTP_GET, [](){
if(!handleFileRead("/edit.htm")) server.send(200, "text/html", PAGE_edit);
});
#ifdef USEFS
server.on("/edit", HTTP_PUT, handleFileCreate);
server.on("/edit", HTTP_DELETE, handleFileDelete);
server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); }, handleFileUpload);
server.on("/list", HTTP_GET, handleFileList);
#endif
//init ota page
httpUpdater.setup(&server);
} else
{ {
server.on("/edit", HTTP_GET, [](){ strcpy(mqttDeviceTopic, "wled/");
serveMessage(500, "Access Denied", txd, 254); strcat(mqttDeviceTopic, escapedMac.c_str());
});
server.on("/update", HTTP_GET, [](){
serveMessage(500, "Access Denied", txd, 254);
});
server.on("/list", HTTP_GET, [](){
serveMessage(500, "Access Denied", txd, 254);
});
} }
//called when the url is not defined here, ajax-in; get-settings
server.onNotFound([](){
DEBUG_PRINTLN("Not-Found HTTP call:");
DEBUG_PRINTLN("URI: " + server.uri());
DEBUG_PRINTLN("Body: " + server.arg(0));
if(!handleSet(server.uri())){
if(!handleAlexaApiCall(server.uri(),server.arg(0)))
server.send(404, "text/plain", "Not Found");
}
});
#ifndef ARDUINO_ARCH_ESP32 //smartInit, we only init some resources when connected
const char * headerkeys[] = {"User-Agent"}; if (!onlyAP && WiFi.status() == WL_CONNECTED)
server.collectHeaders(headerkeys,sizeof(headerkeys)/sizeof(char*)); {
#else mqttTCPClient = new WiFiClient();
String ua = "User-Agent"; mqtt = new PubSubClient(*mqttTCPClient);
server.collectHeaders(ua); mqttInit = initMQTT();
#endif }
if (!initLedsLast) strip.service();
//HTTP server page init
initServer();
if (!initLedsLast) strip.service(); if (!initLedsLast) strip.service();
//init Alexa hue emulation //init Alexa hue emulation
if (alexaEnabled) alexaInit(); if (alexaEnabled && !onlyAP) alexaInit();
server.begin(); server.begin();
DEBUG_PRINTLN("HTTP server started"); DEBUG_PRINTLN("HTTP server started");
//init ArduinoOTA //init ArduinoOTA
if (aOtaEnabled) if (!onlyAP) {
{ if (aOtaEnabled)
ArduinoOTA.onStart([]() { {
#ifndef ARDUINO_ARCH_ESP32 ArduinoOTA.onStart([]() {
wifi_set_sleep_type(NONE_SLEEP_T); #ifndef ARDUINO_ARCH_ESP32
#endif wifi_set_sleep_type(NONE_SLEEP_T);
DEBUG_PRINTLN("Start ArduinoOTA"); #endif
}); DEBUG_PRINTLN("Start ArduinoOTA");
if (strlen(cmDNS) > 0) ArduinoOTA.setHostname(cmDNS); });
ArduinoOTA.begin(); if (strlen(cmDNS) > 0) ArduinoOTA.setHostname(cmDNS);
} ArduinoOTA.begin();
}
if (!initLedsLast) strip.service();
// Set up mDNS responder:
if (strlen(cmDNS) > 0 && !onlyAP)
{
MDNS.begin(cmDNS);
DEBUG_PRINTLN("mDNS responder started");
// Add service to MDNS
MDNS.addService("http", "tcp", 80);
}
initBlynk(blynkApiKey);
initE131(); if (!initLedsLast) strip.service();
// Set up mDNS responder:
if (strlen(cmDNS) > 0 && !onlyAP)
{
MDNS.begin(cmDNS);
DEBUG_PRINTLN("mDNS responder started");
// Add service to MDNS
MDNS.addService("http", "tcp", 80);
}
if (!initLedsLast) strip.service();
initBlynk(blynkApiKey);
initE131();
hueClient = new HTTPClient();
} else {
e131Enabled = false;
}
if (initLedsLast) initStrip(); if (initLedsLast) initStrip();
userBegin(); userBegin();
@ -273,11 +126,10 @@ void wledInit()
void initStrip() void initStrip()
{ {
// Initialize NeoPixel Strip and button // Initialize NeoPixel Strip and button
if (initLedsLast) strip.init(useRGBW,ledCount,PIN,skipFirstLed); if (initLedsLast) strip.init(useRGBW,ledCount,skipFirstLed);
strip.setReverseMode(reverseMode); strip.setReverseMode(reverseMode);
strip.setColor(0); strip.setColor(0);
strip.setBrightness(255); strip.setBrightness(255);
strip.start();
pinMode(buttonPin, INPUT_PULLUP); pinMode(buttonPin, INPUT_PULLUP);
pinMode(4,OUTPUT); //this is only needed in special cases pinMode(4,OUTPUT); //this is only needed in special cases
@ -309,12 +161,12 @@ void initCon()
if (strlen(apSSID)>0) if (strlen(apSSID)>0)
{ {
DEBUG_PRINT("USING AP"); DEBUG_PRINT(" USING AP");
DEBUG_PRINTLN(strlen(apSSID)); DEBUG_PRINTLN(strlen(apSSID));
initAP(); initAP();
} else } else
{ {
DEBUG_PRINTLN("NO AP"); DEBUG_PRINTLN(" NO AP");
WiFi.softAPdisconnect(true); WiFi.softAPdisconnect(true);
} }
int fail_count = 0; int fail_count = 0;
@ -355,191 +207,6 @@ void initCon()
} }
} }
void buildCssColorString()
{
String cs[]={"","","","","",""};
switch (currentTheme)
{
default: cs[0]="D9B310"; cs[1]="0B3C5D"; cs[2]="1D2731"; cs[3]="328CC1"; cs[4]="000"; cs[5]="328CC1"; break; //night
case 1: cs[0]="eee"; cs[1]="ddd"; cs[2]="b9b9b9"; cs[3]="049"; cs[4]="777"; cs[5]="049"; break; //modern
case 2: cs[0]="abc"; cs[1]="fff"; cs[2]="ddd"; cs[3]="000"; cs[4]="0004"; cs[5]="000"; break; //bright
case 3: cs[0]="c09f80"; cs[1]="d7cec7"; cs[2]="76323f"; cs[3]="888"; cs[4]="3334"; cs[5]="888"; break; //wine
case 4: cs[0]="3cc47c"; cs[1]="828081"; cs[2]="d9a803"; cs[3]="1e392a"; cs[4]="000a"; cs[5]="1e392a"; break; //electric
case 5: cs[0]="57bc90"; cs[1]="a5a5af"; cs[2]="015249"; cs[3]="88c9d4"; cs[4]="0004"; cs[5]="88c9d4"; break; //mint
case 6: cs[0]="f7c331"; cs[1]="dcc7aa"; cs[2]="6b7a8f"; cs[3]="f7882f"; cs[4]="0007"; cs[5]="f7882f"; break; //amber
case 7: cs[0]="fc3"; cs[1]="124"; cs[2]="334"; cs[3]="f1d"; cs[4]="f00"; cs[5]="f1d"; break;//club
case 8: cs[0]="0ac"; cs[1]="124"; cs[2]="224"; cs[3]="003eff"; cs[4]="003eff"; cs[5]="003eff"; break;//air
case 9: cs[0]="f70"; cs[1]="421"; cs[2]="221"; cs[3]="a50"; cs[4]="f70"; cs[5]="f70"; break;//nixie
case 10: cs[0]="2d2"; cs[1]="010"; cs[2]="121"; cs[3]="060"; cs[4]="040"; cs[5]="3f3"; break; //terminal
case 11: cs[0]="867ADE"; cs[1]="4033A3"; cs[2]="483AAA"; cs[3]="483AAA"; cs[4]=""; cs[5]="867ADE"; break; //c64
case 12: cs[0]="fbe8a6"; cs[1]="d2fdff"; cs[2]="b4dfe5"; cs[3]="f4976c"; cs[4]=""; cs[5]="303c6c"; break; //c64
case 14: cs[0]="fc7"; cs[1]="49274a"; cs[2]="94618e"; cs[3]="f4decb"; cs[4]="0008"; cs[5]="f4decb"; break; //end
case 15: for (int i=0;i<6;i++)cs[i]=cssCol[i];//custom
}
cssColorString="<style>:root{--aCol:#";
cssColorString+=cs[0];
cssColorString+=";--bCol:#";
cssColorString+=cs[1];
cssColorString+=";--cCol:#";
cssColorString+=cs[2];
cssColorString+=";--dCol:#";
cssColorString+=cs[3];
cssColorString+=";--sCol:#";
cssColorString+=cs[4];
cssColorString+=";--tCol:#";
cssColorString+=cs[5];
cssColorString+=";--cFn:";
cssColorString+=cssFont;
cssColorString+=";}";
}
void serveIndexOrWelcome()
{
if (!showWelcomePage){
if(!handleFileRead("/index.htm")) {
serveIndex();
}
}else{
if(!handleFileRead("/welcome.htm")) {
serveSettings(255);
}
showWelcomePage = false;
}
}
void serveRealtimeError(bool settings)
{
String mesg = "The ";
mesg += (settings)?"settings":"WLED";
mesg += " UI is not available while receiving real-time data (";
if (realtimeIP[0] == 0)
{
mesg += "E1.31";
} else {
mesg += "UDP from ";
mesg += realtimeIP[0];
for (int i = 1; i < 4; i++)
{
mesg += ".";
mesg += realtimeIP[i];
}
}
mesg += ").";
server.send(200, "text/plain", mesg);
}
void serveIndex()
{
bool serveMobile = false;
if (uiConfiguration == 0) serveMobile = checkClientIsMobile(server.header("User-Agent"));
else if (uiConfiguration == 2) serveMobile = true;
if (!arlsTimeout || enableRealtimeUI) //do not serve while receiving realtime
{
if (serveMobile)
{
server.setContentLength(strlen_P(PAGE_indexM));
server.send(200, "text/html", "");
server.sendContent_P(PAGE_indexM);
} else
{
server.setContentLength(strlen_P(PAGE_index0) + cssColorString.length() + strlen_P(PAGE_index1) + strlen_P(PAGE_index2) + strlen_P(PAGE_index3));
server.send(200, "text/html", "");
server.sendContent_P(PAGE_index0);
server.sendContent(cssColorString);
server.sendContent_P(PAGE_index1);
server.sendContent_P(PAGE_index2);
server.sendContent_P(PAGE_index3);
}
} else {
serveRealtimeError(false);
}
}
void serveMessage(int code, String headl, String subl="", int optionType)
{
String messageBody = "<h2>";
messageBody += headl;
messageBody += "</h2>";
messageBody += subl;
switch(optionType)
{
case 255: break; //simple message
case 254: messageBody += "<br><br><button type=\"button\" onclick=\"B()\">Back</button>"; break; //back button
case 253: messageBody += "<br><br><form action=/settings><button type=submit>Back</button></form>"; //button to settings
}
if (optionType < 60) //redirect to settings after optionType seconds
{
messageBody += "<script>setTimeout(RS," + String(optionType*1000) + ")</script>";
} else if (optionType < 120) //redirect back after optionType-60 seconds
{
messageBody += "<script>setTimeout(B," + String((optionType-60)*1000) + ")</script>";
} else if (optionType < 180) //reload parent after optionType-120 seconds
{
messageBody += "<script>setTimeout(RP," + String((optionType-120)*1000) + ")</script>";
}
messageBody += "</body></html>";
server.setContentLength(strlen_P(PAGE_msg0) + cssColorString.length() + strlen_P(PAGE_msg1) + messageBody.length());
server.send(code, "text/html", "");
server.sendContent_P(PAGE_msg0);
server.sendContent(cssColorString);
server.sendContent_P(PAGE_msg1);
server.sendContent(messageBody);
}
void serveSettings(byte subPage)
{
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 255: welcomepage
if (!arlsTimeout || enableRealtimeUI) //do not serve while receiving realtime
{
int pl0, pl1;
switch (subPage)
{
case 1: pl0 = strlen_P(PAGE_settings_wifi0); pl1 = strlen_P(PAGE_settings_wifi1); break;
case 2: pl0 = strlen_P(PAGE_settings_leds0); pl1 = strlen_P(PAGE_settings_leds1); break;
case 3: pl0 = strlen_P(PAGE_settings_ui0); pl1 = strlen_P(PAGE_settings_ui1); break;
case 4: pl0 = strlen_P(PAGE_settings_sync0); pl1 = strlen_P(PAGE_settings_sync1); break;
case 5: pl0 = strlen_P(PAGE_settings_time0); pl1 = strlen_P(PAGE_settings_time1); break;
case 6: pl0 = strlen_P(PAGE_settings_sec0); pl1 = strlen_P(PAGE_settings_sec1); break;
case 255: pl0 = strlen_P(PAGE_welcome0); pl1 = strlen_P(PAGE_welcome1); break;
default: pl0 = strlen_P(PAGE_settings0); pl1 = strlen_P(PAGE_settings1);
}
getSettingsJS(subPage);
int sCssLength = (subPage >0 && subPage <7)?strlen_P(PAGE_settingsCss):0;
server.setContentLength(pl0 + cssColorString.length() + olen + sCssLength + pl1);
server.send(200, "text/html", "");
switch (subPage)
{
case 1: server.sendContent_P(PAGE_settings_wifi0); break;
case 2: server.sendContent_P(PAGE_settings_leds0); break;
case 3: server.sendContent_P(PAGE_settings_ui0); break;
case 4: server.sendContent_P(PAGE_settings_sync0); break;
case 5: server.sendContent_P(PAGE_settings_time0); break;
case 6: server.sendContent_P(PAGE_settings_sec0); break;
case 255: server.sendContent_P(PAGE_welcome0); break;
default: server.sendContent_P(PAGE_settings0);
}
server.sendContent(obuf);
server.sendContent(cssColorString);
if (subPage >0 && subPage <7) server.sendContent_P(PAGE_settingsCss);
switch (subPage)
{
case 1: server.sendContent_P(PAGE_settings_wifi1); break;
case 2: server.sendContent_P(PAGE_settings_leds1); break;
case 3: server.sendContent_P(PAGE_settings_ui1); break;
case 4: server.sendContent_P(PAGE_settings_sync1); break;
case 5: server.sendContent_P(PAGE_settings_time1); break;
case 6: server.sendContent_P(PAGE_settings_sec1); break;
case 255: server.sendContent_P(PAGE_welcome1); break;
default: server.sendContent_P(PAGE_settings1);
}
} else {
serveRealtimeError(true);
}
}
void getBuildInfo() void getBuildInfo()
{ {
@ -572,13 +239,14 @@ void getBuildInfo()
oappend("\r\n"); oappend("\r\n");
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
oappend("strip-pin: gpio"); oappend("strip-pin: gpio");
oappendi(PIN); oappendi(LEDPIN);
#else #else
oappend("strip-pin: gpio2"); oappend("strip-pin: gpio2");
#endif #endif
oappend("\r\nbuild-type: src\r\n"); oappend("\r\nbuild-type: src\r\n");
} }
bool checkClientIsMobile(String useragent) bool checkClientIsMobile(String useragent)
{ {
//to save complexity this function is not comprehensive //to save complexity this function is not comprehensive

View File

@ -31,7 +31,7 @@ void notify(byte callMode, bool followUp=false)
udpOut[8] = effectCurrent; udpOut[8] = effectCurrent;
udpOut[9] = effectSpeed; udpOut[9] = effectSpeed;
udpOut[10] = white; udpOut[10] = white;
udpOut[11] = 4; //compatibilityVersionByte: 0: old 1: supports white 2: supports secondary color 3: supports FX intensity, 24 byte packet 4: supports transitionDelay udpOut[11] = 5; //compatibilityVersionByte: 0: old 1: supports white 2: supports secondary color 3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
udpOut[12] = colSec[0]; udpOut[12] = colSec[0];
udpOut[13] = colSec[1]; udpOut[13] = colSec[1];
udpOut[14] = colSec[2]; udpOut[14] = colSec[2];
@ -39,6 +39,7 @@ void notify(byte callMode, bool followUp=false)
udpOut[16] = effectIntensity; udpOut[16] = effectIntensity;
udpOut[17] = (transitionDelay >> 0) & 0xFF; udpOut[17] = (transitionDelay >> 0) & 0xFF;
udpOut[18] = (transitionDelay >> 8) & 0xFF; udpOut[18] = (transitionDelay >> 8) & 0xFF;
udpOut[19] = effectPalette;
IPAddress broadcastIp; IPAddress broadcastIp;
broadcastIp = ~WiFi.subnetMask() | WiFi.gatewayIP(); broadcastIp = ~WiFi.subnetMask() | WiFi.gatewayIP();
@ -53,19 +54,23 @@ void notify(byte callMode, bool followUp=false)
void arlsLock(uint32_t timeoutMs) void arlsLock(uint32_t timeoutMs)
{ {
if (!arlsTimeout){ if (!realtimeActive){
strip.setRange(0, ledCount-1, 0); for (uint16_t i = 0; i < ledCount; i++)
{
strip.setPixelColor(i,0,0,0,0);
}
strip.setMode(0); strip.setMode(0);
} }
arlsTimeout = true; realtimeActive = true;
arlsTimeoutTime = millis() + timeoutMs; realtimeTimeout = millis() + timeoutMs;
if (arlsForceMaxBri) strip.setBrightness(255); if (arlsForceMaxBri) strip.setBrightness(255);
} }
void initE131(){ void initE131(){
if (WiFi.status() == WL_CONNECTED && e131Enabled) if (WiFi.status() == WL_CONNECTED && e131Enabled)
{ {
e131.begin((e131Multicast) ? E131_MULTICAST : E131_UNICAST , e131Universe); e131 = new E131();
e131->begin((e131Multicast) ? E131_MULTICAST : E131_UNICAST , e131Universe);
} else { } else {
e131Enabled = false; e131Enabled = false;
} }
@ -80,25 +85,25 @@ void handleNotifications()
//E1.31 protocol support //E1.31 protocol support
if(e131Enabled) { if(e131Enabled) {
uint16_t len = e131.parsePacket(); uint16_t len = e131->parsePacket();
if (len && e131.universe == e131Universe) { if (len && e131->universe == e131Universe) {
arlsLock(arlsTimeoutMillis); arlsLock(realtimeTimeoutMs);
if (len > ledCount) len = ledCount; if (len > ledCount) len = ledCount;
for (uint16_t i = 0; i < len; i++) { for (uint16_t i = 0; i < len; i++) {
int j = i * 3; int j = i * 3;
setRealtimePixel(i, e131.data[j], e131.data[j+1], e131.data[j+2], 0); setRealtimePixel(i, e131->data[j], e131->data[j+1], e131->data[j+2], 0);
} }
strip.show(); strip.show();
} }
} }
//unlock strip when realtime UDP times out //unlock strip when realtime UDP times out
if (arlsTimeout && millis() > arlsTimeoutTime) if (realtimeActive && millis() > realtimeTimeout)
{ {
strip.unlockAll(); strip.unlockAll();
strip.setBrightness(bri); strip.setBrightness(bri);
arlsTimeout = false; realtimeActive = false;
strip.setMode(effectCurrent); strip.setMode(effectCurrent);
realtimeIP[0] = 0; realtimeIP[0] = 0;
} }
@ -111,11 +116,12 @@ void handleNotifications()
if (!packetSize && udpRgbConnected) { if (!packetSize && udpRgbConnected) {
packetSize = rgbUdp.parsePacket(); packetSize = rgbUdp.parsePacket();
if (!receiveDirect) return; if (!receiveDirect) return;
realtimeIP = rgbUdp.remoteIP();
if (packetSize > 1026 || packetSize < 3) return; if (packetSize > 1026 || packetSize < 3) return;
realtimeIP = rgbUdp.remoteIP();
DEBUG_PRINTLN(rgbUdp.remoteIP());
byte udpIn[packetSize]; byte udpIn[packetSize];
rgbUdp.read(udpIn, packetSize); rgbUdp.read(udpIn, packetSize);
arlsLock(arlsTimeoutMillis); arlsLock(realtimeTimeoutMs);
uint16_t id = 0; uint16_t id = 0;
for (uint16_t i = 0; i < packetSize -2; i += 3) for (uint16_t i = 0; i < packetSize -2; i += 3)
{ {
@ -132,7 +138,7 @@ void handleNotifications()
{ {
byte udpIn[packetSize]; byte udpIn[packetSize];
notifierUdp.read(udpIn, packetSize); notifierUdp.read(udpIn, packetSize);
if (udpIn[0] == 0 && !arlsTimeout && receiveNotifications) //wled notifier, block if realtime packets active if (udpIn[0] == 0 && !realtimeActive && receiveNotifications) //wled notifier, block if realtime packets active
{ {
if (receiveNotificationColor) if (receiveNotificationColor)
{ {
@ -170,6 +176,11 @@ void handleNotifications()
{ {
transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00); transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00);
} }
if (udpIn[11] > 4 && udpIn[19] != effectPalette && receiveNotificationEffects)
{
effectPalette = udpIn[19];
strip.setPalette(effectPalette);
}
nightlightActive = udpIn[6]; nightlightActive = udpIn[6];
if (!nightlightActive) if (!nightlightActive)
{ {
@ -179,10 +190,11 @@ void handleNotifications()
} else if (udpIn[0] > 0 && udpIn[0] < 4 && receiveDirect) //1 warls //2 drgb //3 drgbw } else if (udpIn[0] > 0 && udpIn[0] < 4 && receiveDirect) //1 warls //2 drgb //3 drgbw
{ {
realtimeIP = notifierUdp.remoteIP(); realtimeIP = notifierUdp.remoteIP();
DEBUG_PRINTLN(notifierUdp.remoteIP());
if (packetSize > 1) { if (packetSize > 1) {
if (udpIn[1] == 0) if (udpIn[1] == 0)
{ {
arlsTimeout = false; realtimeActive = false;
} else { } else {
arlsLock(udpIn[1]*1000); arlsLock(udpIn[1]*1000);
} }
@ -218,15 +230,16 @@ void handleNotifications()
} }
} }
void setRealtimePixel(int i, byte r, byte g, byte b, byte w) void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w)
{ {
if (i + arlsOffset < ledCount && i + arlsOffset >= 0) uint16_t pix = i + arlsOffset;
if (pix < ledCount)
{ {
if (!arlsDisableGammaCorrection && useGammaCorrectionRGB) if (!arlsDisableGammaCorrection && useGammaCorrectionRGB)
{ {
strip.setPixelColor(i + arlsOffset, gamma8[r], gamma8[g], gamma8[b], gamma8[w]); strip.setPixelColor(pix, gamma8[r], gamma8[g], gamma8[b], gamma8[w]);
} else { } else {
strip.setPixelColor(i + arlsOffset, r, g, b, w); strip.setPixelColor(pix, r, g, b, w);
} }
} }
} }

View File

@ -3,7 +3,7 @@
*/ */
void setAllLeds() { void setAllLeds() {
if (!arlsTimeout || !arlsForceMaxBri) if (!realtimeActive || !arlsForceMaxBri)
{ {
double d = briT*briMultiplier; double d = briT*briMultiplier;
int val = d/100; int val = d/100;
@ -15,7 +15,7 @@ void setAllLeds() {
strip.setBrightness(val); strip.setBrightness(val);
} }
} }
if (disableSecTransition) if (!enableSecTransition)
{ {
for (byte i = 0; i<3; i++) for (byte i = 0; i<3; i++)
{ {
@ -92,12 +92,14 @@ void colorUpdated(int callMode)
whiteSecIT = whiteSec; whiteSecIT = whiteSec;
briIT = bri; briIT = bri;
if (bri > 0) briLast = bri; if (bri > 0) briLast = bri;
notify(callMode); notify(callMode);
if (fadeTransition || sweepTransition)
if (fadeTransition)
{ {
//set correct delay if not using notification delay //set correct delay if not using notification delay
if (callMode != 3) transitionDelayTemp = transitionDelay; if (callMode != 3) transitionDelayTemp = transitionDelay;
if (transitionDelayTemp == 0) {setLedsStandard();strip.trigger();return;} if (transitionDelayTemp == 0) {setLedsStandard(); strip.trigger(); return;}
if (transitionActive) if (transitionActive)
{ {
@ -112,29 +114,50 @@ void colorUpdated(int callMode)
briOld = briT; briOld = briT;
tperLast = 0; tperLast = 0;
} }
strip.setTransitionMode(true);
transitionActive = true; transitionActive = true;
transitionStartTime = millis(); transitionStartTime = millis();
strip.setFastUpdateMode(true);
} else } else
{ {
setLedsStandard(); setLedsStandard();
strip.trigger(); strip.trigger();
} }
if (callMode != 9 && callMode != 5 && callMode != 8) updateBlynk();
if (callMode == 8) return;
//only update Blynk and mqtt every 2 seconds to reduce lag
if (millis() - lastInterfaceUpdate <= 2000)
{
interfaceUpdateCallMode = callMode;
return;
}
updateInterfaces(callMode);
}
void updateInterfaces(uint8_t callMode)
{
if (callMode != 9 && callMode != 5) updateBlynk();
publishMQTT();
lastInterfaceUpdate = millis();
} }
void handleTransitions() void handleTransitions()
{ {
//handle still pending interface update
if (interfaceUpdateCallMode && millis() - lastInterfaceUpdate > 2000)
{
updateInterfaces(interfaceUpdateCallMode);
interfaceUpdateCallMode = 0; //disable
}
if (transitionActive && transitionDelayTemp > 0) if (transitionActive && transitionDelayTemp > 0)
{ {
float tper = (millis() - transitionStartTime)/(float)transitionDelayTemp; float tper = (millis() - transitionStartTime)/(float)transitionDelayTemp;
if (tper >= 1.0) if (tper >= 1.0)
{ {
strip.setTransitionMode(false);
transitionActive = false; transitionActive = false;
tperLast = 0; tperLast = 0;
if (sweepTransition) strip.unlockAll();
setLedsStandard(); setLedsStandard();
strip.setFastUpdateMode(false);
return; return;
} }
if (tper - tperLast < 0.004) if (tper - tperLast < 0.004)
@ -153,21 +176,6 @@ void handleTransitions()
whiteSecT = whiteSecOld +((whiteSec - whiteSecOld )*tper); whiteSecT = whiteSecOld +((whiteSec - whiteSecOld )*tper);
briT = briOld +((bri - briOld )*tper); briT = briOld +((bri - briOld )*tper);
} }
if (sweepTransition)
{
strip.lockAll();
if (sweepDirection)
{
strip.unlockRange(0, (int)(tper*(double)ledCount));
} else
{
strip.unlockRange(ledCount - (int)(tper*(double)ledCount), ledCount);
}
if (!fadeTransition)
{
setLedsStandard();
}
}
if (fadeTransition) setAllLeds(); if (fadeTransition) setAllLeds();
} }
} }

View File

@ -166,3 +166,21 @@ bool checkCountdown()
return false; return false;
} }
void checkTimers()
{
if (lastTimerMinute != minute(local)) //only check once a new minute begins
{
lastTimerMinute = minute(local);
for (uint8_t i = 0; i < 8; i++)
{
if (timerMacro[i] != 0
&& (timerHours[i] == hour(local) || timerHours[i] == 24) //if hour is set to 24, activate every hour
&& timerMinutes[i] == minute(local)
&& timerWeekday[i] >> weekday(local) & 0x01) //timer should activate at current day of week
{
applyMacro(timerMacro[i]);
}
}
}
}

View File

@ -3,19 +3,20 @@
*/ */
void initCronixie() void initCronixie()
{ {
if (overlayCurrent == 4 && !cronixieInit) if (overlayCurrent == 3 && !cronixieInit)
{ {
strip.driverModeCronixie(true); strip.driverModeCronixie(true);
strip.setCronixieBacklight(cronixieBacklight); strip.setCronixieBacklight(cronixieBacklight);
setCronixie(); setCronixie();
cronixieInit = true; cronixieInit = true;
} else if (cronixieInit && overlayCurrent != 4) } else if (cronixieInit && overlayCurrent != 3)
{ {
strip.driverModeCronixie(false); strip.driverModeCronixie(false);
cronixieInit = false; cronixieInit = false;
} }
} }
void _nixieDisplay(int num[], uint16_t dur[], uint16_t pausedur[], byte cnt) void _nixieDisplay(int num[], uint16_t dur[], uint16_t pausedur[], byte cnt)
{ {
strip.setRange(overlayMin, overlayMax, 0); strip.setRange(overlayMin, overlayMax, 0);
@ -116,33 +117,26 @@ void _nixieNumber(int number, int dur)
} }
} }
void handleOverlays() void handleOverlays()
{ {
if (millis() - overlayRefreshedTime > overlayRefreshMs) if (millis() - overlayRefreshedTime > overlayRefreshMs)
{ {
initCronixie(); initCronixie();
updateLocalTime(); updateLocalTime();
checkTimers();
switch (overlayCurrent) switch (overlayCurrent)
{ {
case 0: break;//no overlay case 0: break;//no overlay
case 1: _overlaySolid(); break;//solid secondary color case 1: _overlayAnalogClock(); break;//2 analog clock
case 2: _overlayAnalogClock(); break;//2 analog clock case 2: _overlayNixieClock(); break;//nixie 1-digit
case 3: _overlayNixieClock(); break;//nixie 1-digit case 3: _overlayCronixie();//Diamex cronixie clock kit
case 4: _overlayCronixie();//Diamex cronixie clock kit
} }
if (!countdownMode || overlayCurrent < 2) checkCountdown(); //countdown macro activation must work if (!countdownMode || overlayCurrent < 2) checkCountdown(); //countdown macro activation must work
overlayRefreshedTime = millis(); overlayRefreshedTime = millis();
} }
} }
void _overlaySolid()
{
strip.unlockAll();
uint32_t cls = (useGammaCorrectionRGB)? gamma8[whiteSec*16777216] + gamma8[colSec[0]]*65536 + gamma8[colSec[1]]*256 + gamma8[colSec[2]]:whiteSec*16777216 + colSec[0]*65536 + colSec[1]*256 + colSec[2];
strip.setRange(overlayMin,overlayMax,cls);
overlayRefreshMs = 1902;
}
void _overlayAnalogClock() void _overlayAnalogClock()
{ {
int overlaySize = overlayMax - overlayMin +1; int overlaySize = overlayMax - overlayMin +1;
@ -151,7 +145,6 @@ void _overlayAnalogClock()
{ {
_overlayAnalogCountdown(); return; _overlayAnalogCountdown(); return;
} }
_overlaySolid();
double hourP = ((double)(hour(local)%12))/12; double hourP = ((double)(hour(local)%12))/12;
double minuteP = ((double)minute(local))/60; double minuteP = ((double)minute(local))/60;
hourP = hourP + minuteP/12; hourP = hourP + minuteP/12;
@ -191,6 +184,10 @@ void _overlayAnalogClock()
void _overlayNixieClock() void _overlayNixieClock()
{ {
#ifdef WLED_FLASH_512K_MODE
if (countdownMode) checkCountdown();
#else
if (countdownMode) if (countdownMode)
{ {
_overlayNixieCountdown(); return; _overlayNixieCountdown(); return;
@ -275,6 +272,7 @@ void _overlayNixieClock()
{ {
_nixieDisplay(overlayArr, overlayDur, overlayPauseDur, 6); _nixieDisplay(overlayArr, overlayDur, overlayPauseDur, 6);
} }
#endif
} }
void _overlayAnalogCountdown() void _overlayAnalogCountdown()
@ -322,6 +320,7 @@ void _overlayAnalogCountdown()
overlayRefreshMs = 998; overlayRefreshMs = 998;
} }
void _overlayNixieCountdown() void _overlayNixieCountdown()
{ {
if (now() >= countdownTime) if (now() >= countdownTime)

View File

@ -10,8 +10,6 @@ void alexaInit()
{ {
if (alexaEnabled && WiFi.status() == WL_CONNECTED) if (alexaEnabled && WiFi.status() == WL_CONNECTED)
{ {
prepareIds();
udpConnected = connectUDP(); udpConnected = connectUDP();
if (udpConnected) alexaInitPages(); if (udpConnected) alexaInitPages();
@ -24,10 +22,10 @@ void handleAlexa()
{ {
if(udpConnected){ if(udpConnected){
// if theres data available, read a packet // if theres data available, read a packet
int packetSize = UDP.parsePacket(); int packetSize = alexaUDP.parsePacket();
if(packetSize>0) { if(packetSize>0) {
IPAddress remote = UDP.remoteIP(); IPAddress remote = alexaUDP.remoteIP();
int len = UDP.read(obuf, 254); int len = alexaUDP.read(obuf, 254);
if (len > 0) { if (len > 0) {
obuf[len] = 0; obuf[len] = 0;
} }
@ -47,7 +45,7 @@ void alexaOn()
{ {
if (macroAlexaOn == 0) if (macroAlexaOn == 0)
{ {
handleSet((alexaNotify)?"win&T=1&IN":"win&T=1&NN&IN"); handleSet((notifyAlexa)?"win&T=1&IN":"win&T=1&NN&IN");
} else } else
{ {
applyMacro(macroAlexaOn); applyMacro(macroAlexaOn);
@ -60,7 +58,7 @@ void alexaOff()
{ {
if (macroAlexaOff == 0) if (macroAlexaOff == 0)
{ {
handleSet((alexaNotify)?"win&T=0&IN":"win&T=0&NN&IN"); handleSet((notifyAlexa)?"win&T=0&IN":"win&T=0&NN&IN");
} else } else
{ {
applyMacro(macroAlexaOff); applyMacro(macroAlexaOff);
@ -78,7 +76,7 @@ void alexaDim(byte briL)
server.send(200, "application/json", obuf); server.send(200, "application/json", obuf);
String ct = (alexaNotify)?"win&IN&A=":"win&NN&IN&A="; String ct = (notifyAlexa)?"win&IN&A=":"win&NN&IN&A=";
if (briL < 255) if (briL < 255)
{ {
ct = ct + (briL+1); ct = ct + (briL+1);
@ -98,9 +96,9 @@ void prepareIds() {
void respondToSearch() { void respondToSearch() {
DEBUG_PRINTLN(""); DEBUG_PRINTLN("");
DEBUG_PRINT("Send resp to "); DEBUG_PRINT("Send resp to ");
DEBUG_PRINTLN(UDP.remoteIP()); DEBUG_PRINTLN(alexaUDP.remoteIP());
DEBUG_PRINT("Port : "); DEBUG_PRINT("Port : ");
DEBUG_PRINTLN(UDP.remotePort()); DEBUG_PRINTLN(alexaUDP.remotePort());
IPAddress localIP = WiFi.localIP(); IPAddress localIP = WiFi.localIP();
char s[16]; char s[16];
@ -124,13 +122,13 @@ void respondToSearch() {
oappend("::upnp:rootdevice\r\n" // _uuid::_deviceType oappend("::upnp:rootdevice\r\n" // _uuid::_deviceType
"\r\n"); "\r\n");
UDP.beginPacket(UDP.remoteIP(), UDP.remotePort()); alexaUDP.beginPacket(alexaUDP.remoteIP(), alexaUDP.remotePort());
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
UDP.write((byte*)obuf, olen); alexaUDP.write((byte*)obuf, olen);
#else #else
UDP.write(obuf); alexaUDP.write(obuf);
#endif #endif
UDP.endPacket(); alexaUDP.endPacket();
DEBUG_PRINTLN("Response sent!"); DEBUG_PRINTLN("Response sent!");
} }
@ -276,9 +274,9 @@ bool connectUDP(){
DEBUG_PRINTLN("Con UDP"); DEBUG_PRINTLN("Con UDP");
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
if(UDP.beginMulticast(ipMulti, portMulti)) if(alexaUDP.beginMulticast(ipMulti, portMulti))
#else #else
if(UDP.beginMulticast(WiFi.localIP(), ipMulti, portMulti)) if(alexaUDP.beginMulticast(WiFi.localIP(), ipMulti, portMulti))
#endif #endif
{ {
DEBUG_PRINTLN("Con success"); DEBUG_PRINTLN("Con success");

View File

@ -19,6 +19,7 @@ byte getSameCodeLength(char code, int index, char const cronixieDisplay[])
void setCronixie() void setCronixie()
{ {
#ifndef WLED_FLASH_512K_MODE
/* /*
* digit purpose index * digit purpose index
* 0-9 | 0-9 (incl. random) * 0-9 | 0-9 (incl. random)
@ -139,11 +140,14 @@ void setCronixie()
DEBUG_PRINTLN((int)dP[5]); DEBUG_PRINTLN((int)dP[5]);
_overlayCronixie(); //refresh _overlayCronixie(); //refresh
#endif
} }
void _overlayCronixie() void _overlayCronixie()
{ {
if (countdownMode) checkCountdown(); if (countdownMode) checkCountdown();
#ifndef WLED_FLASH_512K_MODE
byte h = hour(local); byte h = hour(local);
byte h0 = h; byte h0 = h;
byte m = minute(local); byte m = minute(local);
@ -208,4 +212,6 @@ void _overlayCronixie()
} }
strip.setCronixieDigits(_digitOut); strip.setCronixieDigits(_digitOut);
//strip.trigger(); //this has a drawback, no effects slower than RefreshMs. advantage: Quick update, not dependant on effect time //strip.trigger(); //this has a drawback, no effects slower than RefreshMs. advantage: Quick update, not dependant on effect time
#endif
} }

View File

@ -106,6 +106,26 @@ void colorXYtoRGB(float x, float y, byte* rgb) //coordinates to rgb (https://www
rgb[2] = 255.0*b; rgb[2] = 255.0*b;
} }
void colorFromDecOrHexString(byte* rgb, byte* wht, char* in)
{
if (in[0] == 0) return;
char first = in[0];
uint32_t c = 0;
if (first == '#' || first == 'h' || first == 'H') //is HEX encoded
{
c = strtoul(in +1, NULL, 16);
} else
{
c = strtoul(in, NULL, 10);
}
*wht = (c >> 24) & 0xFF;
rgb[0] = (c >> 16) & 0xFF;
rgb[1] = (c >> 8) & 0xFF;
rgb[2] = c & 0xFF;
}
void colorRGBtoXY(byte* rgb, float* xy) //rgb to coordinates (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy) void colorRGBtoXY(byte* rgb, float* xy) //rgb to coordinates (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy)
{ {
float X = rgb[0] * 0.664511f + rgb[1] * 0.154324f + rgb[2] * 0.162028f; float X = rgb[0] * 0.664511f + rgb[1] * 0.154324f + rgb[2] * 0.162028f;

View File

@ -4,7 +4,7 @@
void handleHue() void handleHue()
{ {
if (huePollingEnabled && WiFi.status() == WL_CONNECTED) if (huePollingEnabled && WiFi.status() == WL_CONNECTED && hueClient != NULL)
{ {
if (millis() - hueLastRequestSent > huePollIntervalMsTemp) if (millis() - hueLastRequestSent > huePollIntervalMsTemp)
{ {
@ -44,8 +44,8 @@ bool setupHue()
bool sendHuePoll(bool sAuth) bool sendHuePoll(bool sAuth)
{ {
bool st; bool st;
hueClient.setReuse(true); hueClient->setReuse(true);
hueClient.setTimeout(450); hueClient->setTimeout(450);
String hueURL = "http://"; String hueURL = "http://";
hueURL += hueIP.toString(); hueURL += hueIP.toString();
hueURL += "/api/"; hueURL += "/api/";
@ -53,12 +53,12 @@ bool sendHuePoll(bool sAuth)
hueURL += hueApiKey; hueURL += hueApiKey;
hueURL += "/lights/" + String(huePollLightId); hueURL += "/lights/" + String(huePollLightId);
} }
hueClient.begin(hueURL); hueClient->begin(hueURL);
int httpCode = (sAuth)? hueClient.POST("{\"devicetype\":\"wled#esp\"}"):hueClient.GET(); int httpCode = (sAuth)? hueClient->POST("{\"devicetype\":\"wled#esp\"}"):hueClient->GET();
//TODO this request may block operation for ages //TODO this request may block operation for ages
if (httpCode>0){ if (httpCode>0){
st = handleHueResponse(hueClient.getString(),sAuth); st = handleHueResponse(hueClient->getString(),sAuth);
} else { } else {
strcpy(hueError,"Request timed out"); strcpy(hueError,"Request timed out");
st = false; st = false;

View File

@ -20,14 +20,15 @@ void handleBlynk()
void updateBlynk() void updateBlynk()
{ {
Blynk.virtualWrite(V0,bri); if (onlyAP) return;
Blynk.virtualWrite(V0, bri);
//we need a RGB -> HSB convert here //we need a RGB -> HSB convert here
Blynk.virtualWrite(V3,bri); Blynk.virtualWrite(V3, bri? 1:0);
Blynk.virtualWrite(V4,effectCurrent); Blynk.virtualWrite(V4, effectCurrent);
Blynk.virtualWrite(V5,effectSpeed); Blynk.virtualWrite(V5, effectSpeed);
Blynk.virtualWrite(V6,effectIntensity); Blynk.virtualWrite(V6, effectIntensity);
Blynk.virtualWrite(V7,nightlightActive); Blynk.virtualWrite(V7, nightlightActive);
Blynk.virtualWrite(V8,notifyDirect); Blynk.virtualWrite(V8, notifyDirect);
} }
BLYNK_WRITE(V0) BLYNK_WRITE(V0)

136
wled00/wled17_mqtt.ino Normal file
View File

@ -0,0 +1,136 @@
/*
* MQTT communication protocol for home automation
*/
void parseMQTTBriPayload(char* payload)
{
if (strcmp(payload, "ON") == 0) {bri = briLast; colorUpdated(1);}
else if (strcmp(payload, "T" ) == 0) {handleSet("win&T=2");}
else {
uint8_t in = strtoul(payload, NULL, 10);
if (in == 0 && bri > 0) briLast = bri;
bri = in;
colorUpdated(1);
}
}
void callbackMQTT(char* topic, byte* payload, unsigned int length) {
DEBUG_PRINT("MQTT callb rec: ");
DEBUG_PRINTLN(topic);
DEBUG_PRINTLN((char*)payload);
//no need to check the topic because we only get topics we are subscribed to
if (strstr(topic, "/col"))
{
colorFromDecOrHexString(col, &white, (char*)payload);
colorUpdated(1);
} else if (strstr(topic, "/api"))
{
String apireq = "win&";
apireq += (char*)payload;
handleSet(apireq);
} else
{
parseMQTTBriPayload((char*)payload);
}
}
void publishMQTT()
{
if (mqtt == NULL) return;
if (!mqtt->connected()) return;
DEBUG_PRINTLN("Publish MQTT");
char s[10];
char subuf[38];
sprintf(s, "%ld", bri);
strcpy(subuf, mqttDeviceTopic);
strcat(subuf, "/g");
mqtt->publish(subuf, s);
sprintf(s, "#%X", white*16777216 + col[0]*65536 + col[1]*256 + col[2]);
strcpy(subuf, mqttDeviceTopic);
strcat(subuf, "/c");
mqtt->publish(subuf, s);
//if you want to use this, increase the MQTT buffer in PubSubClient.h to 350+
//it will publish the API response to MQTT
/*XML_response(false);
strcpy(subuf, mqttDeviceTopic);
strcat(subuf, "/v");
mqtt->publish(subuf, obuf);*/
}
bool reconnectMQTT()
{
if (mqtt->connect(escapedMac.c_str()))
{
//re-subscribe to required topics
char subuf[38];
strcpy(subuf, mqttDeviceTopic);
if (mqttDeviceTopic[0] != 0)
{
strcpy(subuf, mqttDeviceTopic);
mqtt->subscribe(subuf);
strcat(subuf, "/col");
mqtt->subscribe(subuf);
strcpy(subuf, mqttDeviceTopic);
strcat(subuf, "/api");
mqtt->subscribe(subuf);
}
if (mqttGroupTopic[0] != 0)
{
strcpy(subuf, mqttGroupTopic);
mqtt->subscribe(subuf);
strcat(subuf, "/col");
mqtt->subscribe(subuf);
strcpy(subuf, mqttGroupTopic);
strcat(subuf, "/api");
mqtt->subscribe(subuf);
}
}
return mqtt->connected();
}
bool initMQTT()
{
if (WiFi.status() != WL_CONNECTED) return false;
if (mqttServer[0] == 0) return false;
IPAddress mqttIP;
if (mqttIP.fromString(mqttServer)) //see if server is IP or domain
{
mqtt->setServer(mqttIP,1883);
} else {
mqtt->setServer(mqttServer,1883);
}
mqtt->setCallback(callbackMQTT);
DEBUG_PRINTLN("MQTT ready.");
return true;
}
void handleMQTT()
{
if (WiFi.status() != WL_CONNECTED || !mqttInit) return;
//every time connection is unsuccessful, the attempt interval is increased, since attempt will block program for 7 sec each time
if (!mqtt->connected() && millis() - lastMQTTReconnectAttempt > 5000 + (5000 * mqttFailedConAttempts * mqttFailedConAttempts))
{
DEBUG_PRINTLN("Attempting to connect MQTT...");
lastMQTTReconnectAttempt = millis();
if (!reconnectMQTT())
{
//still attempt reconnect about once daily
if (mqttFailedConAttempts < 120) mqttFailedConAttempts++;
return;
}
DEBUG_PRINTLN("MQTT con!");
mqttFailedConAttempts = 0;
}
mqtt->loop();
}

366
wled00/wled18_server.ino Normal file
View File

@ -0,0 +1,366 @@
/*
* Server page definitions
*/
void initServer()
{
//settings page
server.on("/settings", HTTP_GET, [](){
serveSettings(0);
});
server.on("/settings/wifi", HTTP_GET, [](){
if (!(wifiLock && otaLock))
{
serveSettings(1);
}else{
serveMessage(500, "Access Denied", txd, 254);
}
});
server.on("/settings/leds", HTTP_GET, [](){
serveSettings(2);
});
server.on("/settings/ui", HTTP_GET, [](){
serveSettings(3);
});
server.on("/settings/sync", HTTP_GET, [](){
serveSettings(4);
});
server.on("/settings/time", HTTP_GET, [](){
serveSettings(5);
});
server.on("/settings/sec", HTTP_GET, [](){
serveSettings(6);
});
server.on("/favicon.ico", HTTP_GET, [](){
if(!handleFileRead("/favicon.ico"))
{
server.send_P(200, "image/x-icon", favicon, 156);
}
});
server.on("/sliders", HTTP_GET, serveIndex);
server.on("/welcome", HTTP_GET, [](){
serveSettings(255);
});
server.on("/reset", HTTP_GET, [](){
serveMessage(200,"Rebooting now...","(takes ~20 seconds, wait for auto-redirect)",79);
reset();
});
server.on("/settings/wifi", HTTP_POST, [](){
if (!(wifiLock && otaLock)) handleSettingsSet(1);
serveMessage(200,"WiFi settings saved.","Rebooting now...",255);
reset();
});
server.on("/settings/leds", HTTP_POST, [](){
handleSettingsSet(2);
serveMessage(200,"LED settings saved.","Redirecting...",1);
});
server.on("/settings/ui", HTTP_POST, [](){
handleSettingsSet(3);
serveMessage(200,"UI settings saved.","Reloading to apply theme...",122);
});
server.on("/settings/sync", HTTP_POST, [](){
handleSettingsSet(4);
if (hueAttempt)
{
serveMessage(200,"Hue setup result",hueError,253);
} else {
serveMessage(200,"Sync settings saved.","Redirecting...",1);
}
hueAttempt = false;
});
server.on("/settings/time", HTTP_POST, [](){
handleSettingsSet(5);
serveMessage(200,"Time settings saved.","Redirecting...",1);
});
server.on("/settings/sec", HTTP_POST, [](){
handleSettingsSet(6);
serveMessage(200,"Security settings saved.","Rebooting now... (takes ~20 seconds, wait for auto-redirect)",139);
reset();
});
server.on("/version", HTTP_GET, [](){
server.send(200, "text/plain", (String)VERSION);
});
server.on("/uptime", HTTP_GET, [](){
server.send(200, "text/plain", (String)millis());
});
server.on("/freeheap", HTTP_GET, [](){
server.send(200, "text/plain", (String)ESP.getFreeHeap());
});
server.on("/power", HTTP_GET, [](){
String val = (String)(int)strip.getPowerEstimate(ledCount,strip.getColor(),strip.getBrightness());
val += "mA currently";
serveMessage(200,val,"This is just an estimate (does not take into account several factors like effects and wire resistance). It is NOT an accurate measurement!",254);
});
server.on("/u", HTTP_GET, [](){
server.setContentLength(strlen_P(PAGE_usermod));
server.send(200, "text/html", "");
server.sendContent_P(PAGE_usermod);
});
server.on("/teapot", HTTP_GET, [](){
serveMessage(418, "418. I'm a teapot.","(Tangible Embedded Advanced Project Of Twinkling)",254);
});
server.on("/build", HTTP_GET, [](){
getBuildInfo();
server.send(200, "text/plain", obuf);
});
//if OTA is allowed
if (!otaLock){
server.on("/edit", HTTP_GET, [](){
server.send(200, "text/html", PAGE_edit);
});
#ifdef USEFS
server.on("/edit", HTTP_PUT, handleFileCreate);
server.on("/edit", HTTP_DELETE, handleFileDelete);
server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); }, handleFileUpload);
server.on("/list", HTTP_GET, handleFileList);
#endif
//init ota page
httpUpdater.setup(&server);
} else
{
server.on("/edit", HTTP_GET, [](){
serveMessage(500, "Access Denied", txd, 254);
});
server.on("/update", HTTP_GET, [](){
serveMessage(500, "Access Denied", txd, 254);
});
server.on("/list", HTTP_GET, [](){
serveMessage(500, "Access Denied", txd, 254);
});
}
//this ceased working somehow
/*server.on("/", HTTP_GET, [](){
serveIndexOrWelcome();
});*/
//called when the url is not defined here, ajax-in; get-settings
server.onNotFound([](){
DEBUG_PRINTLN("Not-Found HTTP call:");
DEBUG_PRINTLN("URI: " + server.uri());
DEBUG_PRINTLN("Body: " + server.arg(0));
//workaround for subpage issue
if (server.uri().length() == 1)
{
serveIndexOrWelcome();
return;
}
if(!handleSet(server.uri())){
if(!handleAlexaApiCall(server.uri(),server.arg(0)))
server.send(404, "text/plain", "Not Found");
}
});
#ifndef ARDUINO_ARCH_ESP32
const char * headerkeys[] = {"User-Agent"};
server.collectHeaders(headerkeys,sizeof(headerkeys)/sizeof(char*));
#else
String ua = "User-Agent";
server.collectHeaders(ua);
#endif
}
void buildCssColorString()
{
String cs[]={"","","","","",""};
switch (currentTheme)
{
default: cs[0]="D9B310"; cs[1]="0B3C5D"; cs[2]="1D2731"; cs[3]="328CC1"; cs[4]="000"; cs[5]="328CC1"; break; //night
case 1: cs[0]="eee"; cs[1]="ddd"; cs[2]="b9b9b9"; cs[3]="049"; cs[4]="777"; cs[5]="049"; break; //modern
case 2: cs[0]="abc"; cs[1]="fff"; cs[2]="ddd"; cs[3]="000"; cs[4]="0004"; cs[5]="000"; break; //bright
case 3: cs[0]="c09f80"; cs[1]="d7cec7"; cs[2]="76323f"; cs[3]="888"; cs[4]="3334"; cs[5]="888"; break; //wine
case 4: cs[0]="3cc47c"; cs[1]="828081"; cs[2]="d9a803"; cs[3]="1e392a"; cs[4]="000a"; cs[5]="1e392a"; break; //electric
case 5: cs[0]="57bc90"; cs[1]="a5a5af"; cs[2]="015249"; cs[3]="88c9d4"; cs[4]="0004"; cs[5]="88c9d4"; break; //mint
case 6: cs[0]="f7c331"; cs[1]="dcc7aa"; cs[2]="6b7a8f"; cs[3]="f7882f"; cs[4]="0007"; cs[5]="f7882f"; break; //amber
case 7: cs[0]="fc3"; cs[1]="124"; cs[2]="334"; cs[3]="f1d"; cs[4]="f00"; cs[5]="f1d"; break;//club
case 8: cs[0]="0ac"; cs[1]="124"; cs[2]="224"; cs[3]="003eff"; cs[4]="003eff"; cs[5]="003eff"; break;//air
case 9: cs[0]="f70"; cs[1]="421"; cs[2]="221"; cs[3]="a50"; cs[4]="f70"; cs[5]="f70"; break;//nixie
case 10: cs[0]="2d2"; cs[1]="010"; cs[2]="121"; cs[3]="060"; cs[4]="040"; cs[5]="3f3"; break; //terminal
case 11: cs[0]="867ADE"; cs[1]="4033A3"; cs[2]="483AAA"; cs[3]="483AAA"; cs[4]=""; cs[5]="867ADE"; break; //c64
case 12: cs[0]="fbe8a6"; cs[1]="d2fdff"; cs[2]="b4dfe5"; cs[3]="f4976c"; cs[4]=""; cs[5]="303c6c"; break; //c64
case 14: cs[0]="fc7"; cs[1]="49274a"; cs[2]="94618e"; cs[3]="f4decb"; cs[4]="0008"; cs[5]="f4decb"; break; //end
case 15: for (int i=0;i<6;i++)cs[i]=cssCol[i];//custom
}
cssColorString="<style>:root{--aCol:#";
cssColorString+=cs[0];
cssColorString+=";--bCol:#";
cssColorString+=cs[1];
cssColorString+=";--cCol:#";
cssColorString+=cs[2];
cssColorString+=";--dCol:#";
cssColorString+=cs[3];
cssColorString+=";--sCol:#";
cssColorString+=cs[4];
cssColorString+=";--tCol:#";
cssColorString+=cs[5];
cssColorString+=";--cFn:";
cssColorString+=cssFont;
cssColorString+=";}";
}
void serveIndexOrWelcome()
{
if (!showWelcomePage){
serveIndex();
}else{
serveSettings(255);
}
}
void serveRealtimeError(bool settings)
{
String mesg = "The ";
mesg += (settings)?"settings":"WLED";
mesg += " UI is not available while receiving real-time data (";
if (realtimeIP[0] == 0)
{
mesg += "E1.31";
} else {
mesg += "UDP from ";
mesg += realtimeIP[0];
for (int i = 1; i < 4; i++)
{
mesg += ".";
mesg += realtimeIP[i];
}
}
mesg += ").";
server.send(200, "text/plain", mesg);
}
void serveIndex()
{
bool serveMobile = false;
if (uiConfiguration == 0) serveMobile = checkClientIsMobile(server.header("User-Agent"));
else if (uiConfiguration == 2) serveMobile = true;
if (!realtimeActive || enableRealtimeUI) //do not serve while receiving realtime
{
if (serveMobile)
{
server.setContentLength(strlen_P(PAGE_indexM));
server.send(200, "text/html", "");
server.sendContent_P(PAGE_indexM);
} else
{
server.setContentLength(strlen_P(PAGE_index0) + cssColorString.length() + strlen_P(PAGE_index1) + strlen_P(PAGE_index2) + strlen_P(PAGE_index3));
server.send(200, "text/html", "");
server.sendContent_P(PAGE_index0);
server.sendContent(cssColorString);
server.sendContent_P(PAGE_index1);
server.sendContent_P(PAGE_index2);
server.sendContent_P(PAGE_index3);
}
} else {
serveRealtimeError(false);
}
}
void serveMessage(int code, String headl, String subl="", int optionType)
{
String messageBody = "<h2>";
messageBody += headl;
messageBody += "</h2>";
messageBody += subl;
switch(optionType)
{
case 255: break; //simple message
case 254: messageBody += "<br><br><button type=\"button\" onclick=\"B()\">Back</button>"; break; //back button
case 253: messageBody += "<br><br><form action=/settings><button type=submit>Back</button></form>"; //button to settings
}
if (optionType < 60) //redirect to settings after optionType seconds
{
messageBody += "<script>setTimeout(RS," + String(optionType*1000) + ")</script>";
} else if (optionType < 120) //redirect back after optionType-60 seconds
{
messageBody += "<script>setTimeout(B," + String((optionType-60)*1000) + ")</script>";
} else if (optionType < 180) //reload parent after optionType-120 seconds
{
messageBody += "<script>setTimeout(RP," + String((optionType-120)*1000) + ")</script>";
}
messageBody += "</body></html>";
server.setContentLength(strlen_P(PAGE_msg0) + cssColorString.length() + strlen_P(PAGE_msg1) + messageBody.length());
server.send(code, "text/html", "");
server.sendContent_P(PAGE_msg0);
server.sendContent(cssColorString);
server.sendContent_P(PAGE_msg1);
server.sendContent(messageBody);
}
void serveSettings(byte subPage)
{
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 255: welcomepage
if (!realtimeActive || enableRealtimeUI) //do not serve while receiving realtime
{
#ifdef WLED_FLASH_512K_MODE //disable welcome page if not enough storage
if (subPage == 255) {serveIndex(); return;}
#endif
int pl0, pl1;
switch (subPage)
{
case 1: pl0 = strlen_P(PAGE_settings_wifi0); pl1 = strlen_P(PAGE_settings_wifi1); break;
case 2: pl0 = strlen_P(PAGE_settings_leds0); pl1 = strlen_P(PAGE_settings_leds1); break;
case 3: pl0 = strlen_P(PAGE_settings_ui0); pl1 = strlen_P(PAGE_settings_ui1); break;
case 4: pl0 = strlen_P(PAGE_settings_sync0); pl1 = strlen_P(PAGE_settings_sync1); break;
case 5: pl0 = strlen_P(PAGE_settings_time0); pl1 = strlen_P(PAGE_settings_time1); break;
case 6: pl0 = strlen_P(PAGE_settings_sec0); pl1 = strlen_P(PAGE_settings_sec1); break;
case 255: pl0 = strlen_P(PAGE_welcome0); pl1 = strlen_P(PAGE_welcome1); break;
default: pl0 = strlen_P(PAGE_settings0); pl1 = strlen_P(PAGE_settings1);
}
getSettingsJS(subPage);
int sCssLength = (subPage >0 && subPage <7)?strlen_P(PAGE_settingsCss):0;
server.setContentLength(pl0 + cssColorString.length() + olen + sCssLength + pl1);
server.send(200, "text/html", "");
switch (subPage)
{
case 1: server.sendContent_P(PAGE_settings_wifi0); break;
case 2: server.sendContent_P(PAGE_settings_leds0); break;
case 3: server.sendContent_P(PAGE_settings_ui0); break;
case 4: server.sendContent_P(PAGE_settings_sync0); break;
case 5: server.sendContent_P(PAGE_settings_time0); break;
case 6: server.sendContent_P(PAGE_settings_sec0); break;
case 255: server.sendContent_P(PAGE_welcome0); break;
default: server.sendContent_P(PAGE_settings0);
}
server.sendContent(obuf);
server.sendContent(cssColorString);
if (subPage >0 && subPage <7) server.sendContent_P(PAGE_settingsCss);
switch (subPage)
{
case 1: server.sendContent_P(PAGE_settings_wifi1); break;
case 2: server.sendContent_P(PAGE_settings_leds1); break;
case 3: server.sendContent_P(PAGE_settings_ui1); break;
case 4: server.sendContent_P(PAGE_settings_sync1); break;
case 5: server.sendContent_P(PAGE_settings_time1); break;
case 6: server.sendContent_P(PAGE_settings_sec1); break;
case 255: server.sendContent_P(PAGE_welcome1); break;
default: server.sendContent_P(PAGE_settings1);
}
} else {
serveRealtimeError(true);
}
}

BIN
wled_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB