Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e4a52b0d1 | |||
| 712d5043d2 | |||
| 2a24f3567d | |||
| cac526215d | |||
| f01a340e25 | |||
| 09a1b078f6 | |||
| e07be50022 | |||
| 4c93854524 | |||
| 9a06abf549 | |||
| 0932365803 | |||
| 9bbd17f921 | |||
| 24d8dc7364 | |||
| 397239e598 | |||
| f50ae688d4 | |||
| bb0bb175fa | |||
| 02ff21e532 | |||
| 07da1bdcf3 | |||
| 3088188a26 | |||
| 06244d2717 | |||
| 2e40c5934d | |||
| 0188c8e273 | |||
| df43aba37b | |||
| a0a8fe72b5 | |||
| 95de53d045 | |||
| fb4cfe3a3e | |||
| 53178c5e33 | |||
| 7dd3c87b8c | |||
| bc783f774c | |||
| 341c469b49 | |||
| 2adc6707df | |||
| 3a1f9d2f14 | |||
| 7291cb2fe0 | |||
| 3f880f95c1 | |||
| 66103c7be9 | |||
| d1e24480e0 | |||
| d808e641ef | |||
| 8903503aef | |||
| 75b19fd09d | |||
| 8cd0a07fa0 | |||
| 0f380fe7c6 | |||
| 1ea5d12735 | |||
| a734762639 | |||
| bd442ece90 | |||
| 95475b2ddc | |||
| f080be00e5 | |||
| 3afa105ce0 | |||
| 83950c08a3 | |||
| e0694b1b5b | |||
| f0ed3c5730 | |||
| 71fd7e5b68 | |||
| e1760bdab0 | |||
| 4c88233a6f | |||
| 9f482877c3 | |||
| 0776e8f5f4 | |||
| 92b3959a6a | |||
| 3e66fc21bb | |||
| a16b525cb6 | |||
| e165274b8f | |||
| 5342ec38e1 | |||
| b0f8047f71 | |||
| a53ebf1ee5 | |||
| 3c47e312da | |||
| a2f12208b2 | |||
| c329a85a1b | |||
| 3165ed4fae |
@@ -10,3 +10,6 @@ lib/readme.txt
|
|||||||
.gcc-flags.json
|
.gcc-flags.json
|
||||||
|
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
.pio/*
|
||||||
|
|
||||||
|
*.bin
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
[submodule "Arduino/McLighting/data/McLightingUI"]
|
|
||||||
path = Arduino/McLighting/data/McLightingUI
|
|
||||||
url = https://github.com/toblum/McLightingUI
|
|
||||||
[submodule "clients/web/McLightingUI"]
|
|
||||||
path = clients/web/McLightingUI
|
|
||||||
url = https://github.com/toblum/McLightingUI
|
|
||||||
+475
-727
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,651 @@
|
|||||||
|
/*
|
||||||
|
WS2812FX.h - Library for WS2812 LED effects.
|
||||||
|
|
||||||
|
Harm Aldick - 2016
|
||||||
|
www.aldick.org
|
||||||
|
FEATURES
|
||||||
|
* A lot of blinken modes and counting
|
||||||
|
* WS2812FX can be used as drop-in replacement for Adafruit NeoPixel Library
|
||||||
|
NOTES
|
||||||
|
* Uses the Adafruit NeoPixel library. Get it here:
|
||||||
|
https://github.com/adafruit/Adafruit_NeoPixel
|
||||||
|
LICENSE
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2016 Harm Aldick
|
||||||
|
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.
|
||||||
|
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)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WS2812FX_h
|
||||||
|
#define WS2812FX_h
|
||||||
|
|
||||||
|
#define FSH(x) (__FlashStringHelper*)(x)
|
||||||
|
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
#define DEFAULT_BRIGHTNESS (uint8_t)50
|
||||||
|
#define DEFAULT_MODE (uint8_t)0
|
||||||
|
#define DEFAULT_SPEED (uint16_t)1000
|
||||||
|
#define DEFAULT_COLOR (uint32_t)0xFF0000
|
||||||
|
|
||||||
|
#if defined(ESP8266) || defined(ESP32)
|
||||||
|
//#pragma message("Compiling for ESP")
|
||||||
|
#define SPEED_MIN (uint16_t)2
|
||||||
|
#else
|
||||||
|
//#pragma message("Compiling for Arduino")
|
||||||
|
#define SPEED_MIN (uint16_t)10
|
||||||
|
#endif
|
||||||
|
#define SPEED_MAX (uint16_t)65535
|
||||||
|
|
||||||
|
#define BRIGHTNESS_MIN (uint8_t)0
|
||||||
|
#define BRIGHTNESS_MAX (uint8_t)255
|
||||||
|
|
||||||
|
/* each segment uses 36 bytes of SRAM memory, so if you're application fails because of
|
||||||
|
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
|
||||||
|
#define MAX_NUM_SEGMENTS 10
|
||||||
|
#define NUM_COLORS 3 /* number of colors per segment */
|
||||||
|
#define MAX_CUSTOM_MODES 10
|
||||||
|
#define SEGMENT _segments[_segment_index]
|
||||||
|
#define SEGMENT_RUNTIME _segment_runtimes[_segment_index]
|
||||||
|
#define SEGMENT_LENGTH (uint16_t)(SEGMENT.stop - SEGMENT.start + 1)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
#define DARK(c) (uint32_t)((c >> 4) & 0x0f0f0f0f)
|
||||||
|
|
||||||
|
// segment options
|
||||||
|
// bit 7: reverse animation
|
||||||
|
// bits 4-6: fade rate (0-7)
|
||||||
|
// bit 3: gamma correction
|
||||||
|
// bits 1-2: size
|
||||||
|
// bits 0: TBD
|
||||||
|
#define NO_OPTIONS (uint8_t)B00000000
|
||||||
|
#define REVERSE (uint8_t)B10000000
|
||||||
|
#define IS_REVERSE ((SEGMENT.options & REVERSE) == REVERSE)
|
||||||
|
#define FADE_XFAST (uint8_t)B00010000
|
||||||
|
#define FADE_FAST (uint8_t)B00100000
|
||||||
|
#define FADE_MEDIUM (uint8_t)B00110000
|
||||||
|
#define FADE_SLOW (uint8_t)B01000000
|
||||||
|
#define FADE_XSLOW (uint8_t)B01010000
|
||||||
|
#define FADE_XXSLOW (uint8_t)B01100000
|
||||||
|
#define FADE_GLACIAL (uint8_t)B01110000
|
||||||
|
#define FADE_RATE ((SEGMENT.options >> 4) & 7)
|
||||||
|
#define GAMMA (uint8_t)B00001000
|
||||||
|
#define IS_GAMMA ((SEGMENT.options & GAMMA) == GAMMA)
|
||||||
|
#define SIZE_SMALL (uint8_t)B00000000
|
||||||
|
#define SIZE_MEDIUM (uint8_t)B00000010
|
||||||
|
#define SIZE_LARGE (uint8_t)B00000100
|
||||||
|
#define SIZE_XLARGE (uint8_t)B00000110
|
||||||
|
#define SIZE_OPTION ((SEGMENT.options >> 1) & 3)
|
||||||
|
|
||||||
|
// segment runtime options (aux_param2)
|
||||||
|
#define FRAME (uint8_t)B10000000
|
||||||
|
#define SET_FRAME (SEGMENT_RUNTIME.aux_param2 |= FRAME)
|
||||||
|
#define CLR_FRAME (SEGMENT_RUNTIME.aux_param2 &= ~FRAME)
|
||||||
|
#define CYCLE (uint8_t)B01000000
|
||||||
|
#define SET_CYCLE (SEGMENT_RUNTIME.aux_param2 |= CYCLE)
|
||||||
|
#define CLR_CYCLE (SEGMENT_RUNTIME.aux_param2 &= ~CYCLE)
|
||||||
|
|
||||||
|
#define MODE_COUNT (sizeof(_names)/sizeof(_names[0]))
|
||||||
|
|
||||||
|
#define FX_MODE_STATIC 0
|
||||||
|
#define FX_MODE_BLINK 1
|
||||||
|
#define FX_MODE_BREATH 2
|
||||||
|
#define FX_MODE_COLOR_WIPE 3
|
||||||
|
#define FX_MODE_COLOR_WIPE_INV 4
|
||||||
|
#define FX_MODE_COLOR_WIPE_REV 5
|
||||||
|
#define FX_MODE_COLOR_WIPE_REV_INV 6
|
||||||
|
#define FX_MODE_COLOR_WIPE_RANDOM 7
|
||||||
|
#define FX_MODE_RANDOM_COLOR 8
|
||||||
|
#define FX_MODE_SINGLE_DYNAMIC 9
|
||||||
|
#define FX_MODE_MULTI_DYNAMIC 10
|
||||||
|
#define FX_MODE_RAINBOW 11
|
||||||
|
#define FX_MODE_RAINBOW_CYCLE 12
|
||||||
|
#define FX_MODE_SCAN 13
|
||||||
|
#define FX_MODE_DUAL_SCAN 14
|
||||||
|
#define FX_MODE_FADE 15
|
||||||
|
#define FX_MODE_THEATER_CHASE 16
|
||||||
|
#define FX_MODE_THEATER_CHASE_RAINBOW 17
|
||||||
|
#define FX_MODE_RUNNING_LIGHTS 18
|
||||||
|
#define FX_MODE_TWINKLE 19
|
||||||
|
#define FX_MODE_TWINKLE_RANDOM 20
|
||||||
|
#define FX_MODE_TWINKLE_FADE 21
|
||||||
|
#define FX_MODE_TWINKLE_FADE_RANDOM 22
|
||||||
|
#define FX_MODE_SPARKLE 23
|
||||||
|
#define FX_MODE_FLASH_SPARKLE 24
|
||||||
|
#define FX_MODE_HYPER_SPARKLE 25
|
||||||
|
#define FX_MODE_STROBE 26
|
||||||
|
#define FX_MODE_STROBE_RAINBOW 27
|
||||||
|
#define FX_MODE_MULTI_STROBE 28
|
||||||
|
#define FX_MODE_BLINK_RAINBOW 29
|
||||||
|
#define FX_MODE_CHASE_WHITE 30
|
||||||
|
#define FX_MODE_CHASE_COLOR 31
|
||||||
|
#define FX_MODE_CHASE_RANDOM 32
|
||||||
|
#define FX_MODE_CHASE_RAINBOW 33
|
||||||
|
#define FX_MODE_CHASE_FLASH 34
|
||||||
|
#define FX_MODE_CHASE_FLASH_RANDOM 35
|
||||||
|
#define FX_MODE_CHASE_RAINBOW_WHITE 36
|
||||||
|
#define FX_MODE_CHASE_BLACKOUT 37
|
||||||
|
#define FX_MODE_CHASE_BLACKOUT_RAINBOW 38
|
||||||
|
#define FX_MODE_COLOR_SWEEP_RANDOM 39
|
||||||
|
#define FX_MODE_RUNNING_COLOR 40
|
||||||
|
#define FX_MODE_RUNNING_RED_BLUE 41
|
||||||
|
#define FX_MODE_RUNNING_RANDOM 42
|
||||||
|
#define FX_MODE_LARSON_SCANNER 43
|
||||||
|
#define FX_MODE_COMET 44
|
||||||
|
#define FX_MODE_FIREWORKS 45
|
||||||
|
#define FX_MODE_FIREWORKS_RANDOM 46
|
||||||
|
#define FX_MODE_MERRY_CHRISTMAS 47
|
||||||
|
#define FX_MODE_FIRE_FLICKER 48
|
||||||
|
#define FX_MODE_FIRE_FLICKER_SOFT 49
|
||||||
|
#define FX_MODE_FIRE_FLICKER_INTENSE 50
|
||||||
|
#define FX_MODE_CIRCUS_COMBUSTUS 51
|
||||||
|
#define FX_MODE_HALLOWEEN 52
|
||||||
|
#define FX_MODE_BICOLOR_CHASE 53
|
||||||
|
#define FX_MODE_TRICOLOR_CHASE 54
|
||||||
|
#define FX_MODE_ICU 55
|
||||||
|
#define FX_MODE_CUSTOM 56 // keep this for backward compatiblity
|
||||||
|
#define FX_MODE_CUSTOM_0 56 // custom modes need to go at the end
|
||||||
|
#define FX_MODE_CUSTOM_1 57
|
||||||
|
#define FX_MODE_CUSTOM_2 58
|
||||||
|
#define FX_MODE_CUSTOM_3 59
|
||||||
|
#define FX_MODE_CUSTOM_4 60
|
||||||
|
#define FX_MODE_CUSTOM_5 61
|
||||||
|
#define FX_MODE_CUSTOM_6 62
|
||||||
|
#define FX_MODE_CUSTOM_7 63
|
||||||
|
#define FX_MODE_CUSTOM_8 64
|
||||||
|
#define FX_MODE_CUSTOM_9 65
|
||||||
|
|
||||||
|
// create GLOBAL names to allow WS2812FX to compile with sketches and other libs that store strings
|
||||||
|
// in PROGMEM (get rid of the "section type conflict with __c" errors once and for all. Amen.)
|
||||||
|
const char name_0[] PROGMEM = "Static";
|
||||||
|
const char name_1[] PROGMEM = "Blink";
|
||||||
|
const char name_2[] PROGMEM = "Breath";
|
||||||
|
const char name_3[] PROGMEM = "Color Wipe";
|
||||||
|
const char name_4[] PROGMEM = "Color Wipe Inverse";
|
||||||
|
const char name_5[] PROGMEM = "Color Wipe Reverse";
|
||||||
|
const char name_6[] PROGMEM = "Color Wipe Reverse Inverse";
|
||||||
|
const char name_7[] PROGMEM = "Color Wipe Random";
|
||||||
|
const char name_8[] PROGMEM = "Random Color";
|
||||||
|
const char name_9[] PROGMEM = "Single Dynamic";
|
||||||
|
const char name_10[] PROGMEM = "Multi Dynamic";
|
||||||
|
const char name_11[] PROGMEM = "Rainbow";
|
||||||
|
const char name_12[] PROGMEM = "Rainbow Cycle";
|
||||||
|
const char name_13[] PROGMEM = "Scan";
|
||||||
|
const char name_14[] PROGMEM = "Dual Scan";
|
||||||
|
const char name_15[] PROGMEM = "Fade";
|
||||||
|
const char name_16[] PROGMEM = "Theater Chase";
|
||||||
|
const char name_17[] PROGMEM = "Theater Chase Rainbow";
|
||||||
|
const char name_18[] PROGMEM = "Running Lights";
|
||||||
|
const char name_19[] PROGMEM = "Twinkle";
|
||||||
|
const char name_20[] PROGMEM = "Twinkle Random";
|
||||||
|
const char name_21[] PROGMEM = "Twinkle Fade";
|
||||||
|
const char name_22[] PROGMEM = "Twinkle Fade Random";
|
||||||
|
const char name_23[] PROGMEM = "Sparkle";
|
||||||
|
const char name_24[] PROGMEM = "Flash Sparkle";
|
||||||
|
const char name_25[] PROGMEM = "Hyper Sparkle";
|
||||||
|
const char name_26[] PROGMEM = "Strobe";
|
||||||
|
const char name_27[] PROGMEM = "Strobe Rainbow";
|
||||||
|
const char name_28[] PROGMEM = "Multi Strobe";
|
||||||
|
const char name_29[] PROGMEM = "Blink Rainbow";
|
||||||
|
const char name_30[] PROGMEM = "Chase White";
|
||||||
|
const char name_31[] PROGMEM = "Chase Color";
|
||||||
|
const char name_32[] PROGMEM = "Chase Random";
|
||||||
|
const char name_33[] PROGMEM = "Chase Rainbow";
|
||||||
|
const char name_34[] PROGMEM = "Chase Flash";
|
||||||
|
const char name_35[] PROGMEM = "Chase Flash Random";
|
||||||
|
const char name_36[] PROGMEM = "Chase Rainbow White";
|
||||||
|
const char name_37[] PROGMEM = "Chase Blackout";
|
||||||
|
const char name_38[] PROGMEM = "Chase Blackout Rainbow";
|
||||||
|
const char name_39[] PROGMEM = "Color Sweep Random";
|
||||||
|
const char name_40[] PROGMEM = "Running Color";
|
||||||
|
const char name_41[] PROGMEM = "Running Red Blue";
|
||||||
|
const char name_42[] PROGMEM = "Running Random";
|
||||||
|
const char name_43[] PROGMEM = "Larson Scanner";
|
||||||
|
const char name_44[] PROGMEM = "Comet";
|
||||||
|
const char name_45[] PROGMEM = "Fireworks";
|
||||||
|
const char name_46[] PROGMEM = "Fireworks Random";
|
||||||
|
const char name_47[] PROGMEM = "Merry Christmas";
|
||||||
|
const char name_48[] PROGMEM = "Fire Flicker";
|
||||||
|
const char name_49[] PROGMEM = "Fire Flicker (soft)";
|
||||||
|
const char name_50[] PROGMEM = "Fire Flicker (intense)";
|
||||||
|
const char name_51[] PROGMEM = "Circus Combustus";
|
||||||
|
const char name_52[] PROGMEM = "Halloween";
|
||||||
|
const char name_53[] PROGMEM = "Bicolor Chase";
|
||||||
|
const char name_54[] PROGMEM = "Tricolor Chase";
|
||||||
|
const char name_55[] PROGMEM = "ICU";
|
||||||
|
const char name_56[] PROGMEM = "Custom 0"; // custom modes need to go at the end
|
||||||
|
const char name_57[] PROGMEM = "Custom 1";
|
||||||
|
const char name_58[] PROGMEM = "Custom 2";
|
||||||
|
const char name_59[] PROGMEM = "Custom 3";
|
||||||
|
const char name_60[] PROGMEM = "Custom 4";
|
||||||
|
const char name_61[] PROGMEM = "Custom 5";
|
||||||
|
const char name_62[] PROGMEM = "Custom 6";
|
||||||
|
const char name_63[] PROGMEM = "Custom 7";
|
||||||
|
const char name_64[] PROGMEM = "Custom 8";
|
||||||
|
const char name_65[] PROGMEM = "Custom 9";
|
||||||
|
|
||||||
|
static const __FlashStringHelper* _names[] = {
|
||||||
|
FSH(name_0),
|
||||||
|
FSH(name_1),
|
||||||
|
FSH(name_2),
|
||||||
|
FSH(name_3),
|
||||||
|
FSH(name_4),
|
||||||
|
FSH(name_5),
|
||||||
|
FSH(name_6),
|
||||||
|
FSH(name_7),
|
||||||
|
FSH(name_8),
|
||||||
|
FSH(name_9),
|
||||||
|
FSH(name_10),
|
||||||
|
FSH(name_11),
|
||||||
|
FSH(name_12),
|
||||||
|
FSH(name_13),
|
||||||
|
FSH(name_14),
|
||||||
|
FSH(name_15),
|
||||||
|
FSH(name_16),
|
||||||
|
FSH(name_17),
|
||||||
|
FSH(name_18),
|
||||||
|
FSH(name_19),
|
||||||
|
FSH(name_20),
|
||||||
|
FSH(name_21),
|
||||||
|
FSH(name_22),
|
||||||
|
FSH(name_23),
|
||||||
|
FSH(name_24),
|
||||||
|
FSH(name_25),
|
||||||
|
FSH(name_26),
|
||||||
|
FSH(name_27),
|
||||||
|
FSH(name_28),
|
||||||
|
FSH(name_29),
|
||||||
|
FSH(name_30),
|
||||||
|
FSH(name_31),
|
||||||
|
FSH(name_32),
|
||||||
|
FSH(name_33),
|
||||||
|
FSH(name_34),
|
||||||
|
FSH(name_35),
|
||||||
|
FSH(name_36),
|
||||||
|
FSH(name_37),
|
||||||
|
FSH(name_38),
|
||||||
|
FSH(name_39),
|
||||||
|
FSH(name_40),
|
||||||
|
FSH(name_41),
|
||||||
|
FSH(name_42),
|
||||||
|
FSH(name_43),
|
||||||
|
FSH(name_44),
|
||||||
|
FSH(name_45),
|
||||||
|
FSH(name_46),
|
||||||
|
FSH(name_47),
|
||||||
|
FSH(name_48),
|
||||||
|
FSH(name_49),
|
||||||
|
FSH(name_50),
|
||||||
|
FSH(name_51),
|
||||||
|
FSH(name_52),
|
||||||
|
FSH(name_53),
|
||||||
|
FSH(name_54),
|
||||||
|
FSH(name_55),
|
||||||
|
FSH(name_56),
|
||||||
|
FSH(name_57),
|
||||||
|
FSH(name_58),
|
||||||
|
FSH(name_59),
|
||||||
|
FSH(name_60),
|
||||||
|
FSH(name_61),
|
||||||
|
FSH(name_62),
|
||||||
|
FSH(name_63),
|
||||||
|
FSH(name_64),
|
||||||
|
FSH(name_65)
|
||||||
|
};
|
||||||
|
|
||||||
|
class WS2812FX : public Adafruit_NeoPixel {
|
||||||
|
|
||||||
|
typedef uint16_t (WS2812FX::*mode_ptr)(void);
|
||||||
|
|
||||||
|
// segment parameters
|
||||||
|
public:
|
||||||
|
typedef struct Segment { // 20 bytes
|
||||||
|
uint16_t start;
|
||||||
|
uint16_t stop;
|
||||||
|
uint16_t speed;
|
||||||
|
uint8_t mode;
|
||||||
|
uint8_t options;
|
||||||
|
uint32_t colors[NUM_COLORS];
|
||||||
|
} segment;
|
||||||
|
|
||||||
|
// segment runtime parameters
|
||||||
|
typedef struct Segment_runtime { // 16 bytes
|
||||||
|
unsigned long next_time;
|
||||||
|
uint32_t counter_mode_step;
|
||||||
|
uint32_t counter_mode_call;
|
||||||
|
uint8_t aux_param; // auxilary param (usually stores a color_wheel index)
|
||||||
|
uint8_t aux_param2; // auxilary param (usually stores bitwise options)
|
||||||
|
uint16_t aux_param3; // auxilary param (usually stores a segment index)
|
||||||
|
} segment_runtime;
|
||||||
|
|
||||||
|
WS2812FX(uint16_t n, uint8_t p, neoPixelType t) : Adafruit_NeoPixel(n, p, t) {
|
||||||
|
_mode[FX_MODE_STATIC] = &WS2812FX::mode_static;
|
||||||
|
_mode[FX_MODE_BLINK] = &WS2812FX::mode_blink;
|
||||||
|
_mode[FX_MODE_COLOR_WIPE] = &WS2812FX::mode_color_wipe;
|
||||||
|
_mode[FX_MODE_COLOR_WIPE_INV] = &WS2812FX::mode_color_wipe_inv;
|
||||||
|
_mode[FX_MODE_COLOR_WIPE_REV] = &WS2812FX::mode_color_wipe_rev;
|
||||||
|
_mode[FX_MODE_COLOR_WIPE_REV_INV] = &WS2812FX::mode_color_wipe_rev_inv;
|
||||||
|
_mode[FX_MODE_COLOR_WIPE_RANDOM] = &WS2812FX::mode_color_wipe_random;
|
||||||
|
_mode[FX_MODE_RANDOM_COLOR] = &WS2812FX::mode_random_color;
|
||||||
|
_mode[FX_MODE_SINGLE_DYNAMIC] = &WS2812FX::mode_single_dynamic;
|
||||||
|
_mode[FX_MODE_MULTI_DYNAMIC] = &WS2812FX::mode_multi_dynamic;
|
||||||
|
_mode[FX_MODE_RAINBOW] = &WS2812FX::mode_rainbow;
|
||||||
|
_mode[FX_MODE_RAINBOW_CYCLE] = &WS2812FX::mode_rainbow_cycle;
|
||||||
|
_mode[FX_MODE_SCAN] = &WS2812FX::mode_scan;
|
||||||
|
_mode[FX_MODE_DUAL_SCAN] = &WS2812FX::mode_dual_scan;
|
||||||
|
_mode[FX_MODE_FADE] = &WS2812FX::mode_fade;
|
||||||
|
_mode[FX_MODE_THEATER_CHASE] = &WS2812FX::mode_theater_chase;
|
||||||
|
_mode[FX_MODE_THEATER_CHASE_RAINBOW] = &WS2812FX::mode_theater_chase_rainbow;
|
||||||
|
_mode[FX_MODE_TWINKLE] = &WS2812FX::mode_twinkle;
|
||||||
|
_mode[FX_MODE_TWINKLE_RANDOM] = &WS2812FX::mode_twinkle_random;
|
||||||
|
_mode[FX_MODE_TWINKLE_FADE] = &WS2812FX::mode_twinkle_fade;
|
||||||
|
_mode[FX_MODE_TWINKLE_FADE_RANDOM] = &WS2812FX::mode_twinkle_fade_random;
|
||||||
|
_mode[FX_MODE_SPARKLE] = &WS2812FX::mode_sparkle;
|
||||||
|
_mode[FX_MODE_FLASH_SPARKLE] = &WS2812FX::mode_flash_sparkle;
|
||||||
|
_mode[FX_MODE_HYPER_SPARKLE] = &WS2812FX::mode_hyper_sparkle;
|
||||||
|
_mode[FX_MODE_STROBE] = &WS2812FX::mode_strobe;
|
||||||
|
_mode[FX_MODE_STROBE_RAINBOW] = &WS2812FX::mode_strobe_rainbow;
|
||||||
|
_mode[FX_MODE_MULTI_STROBE] = &WS2812FX::mode_multi_strobe;
|
||||||
|
_mode[FX_MODE_BLINK_RAINBOW] = &WS2812FX::mode_blink_rainbow;
|
||||||
|
_mode[FX_MODE_CHASE_WHITE] = &WS2812FX::mode_chase_white;
|
||||||
|
_mode[FX_MODE_CHASE_COLOR] = &WS2812FX::mode_chase_color;
|
||||||
|
_mode[FX_MODE_CHASE_RANDOM] = &WS2812FX::mode_chase_random;
|
||||||
|
_mode[FX_MODE_CHASE_RAINBOW] = &WS2812FX::mode_chase_rainbow;
|
||||||
|
_mode[FX_MODE_CHASE_FLASH] = &WS2812FX::mode_chase_flash;
|
||||||
|
_mode[FX_MODE_CHASE_FLASH_RANDOM] = &WS2812FX::mode_chase_flash_random;
|
||||||
|
_mode[FX_MODE_CHASE_RAINBOW_WHITE] = &WS2812FX::mode_chase_rainbow_white;
|
||||||
|
_mode[FX_MODE_CHASE_BLACKOUT] = &WS2812FX::mode_chase_blackout;
|
||||||
|
_mode[FX_MODE_CHASE_BLACKOUT_RAINBOW] = &WS2812FX::mode_chase_blackout_rainbow;
|
||||||
|
_mode[FX_MODE_COLOR_SWEEP_RANDOM] = &WS2812FX::mode_color_sweep_random;
|
||||||
|
_mode[FX_MODE_RUNNING_COLOR] = &WS2812FX::mode_running_color;
|
||||||
|
_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_FIRE_FLICKER_SOFT] = &WS2812FX::mode_fire_flicker_soft;
|
||||||
|
_mode[FX_MODE_FIRE_FLICKER_INTENSE] = &WS2812FX::mode_fire_flicker_intense;
|
||||||
|
_mode[FX_MODE_CIRCUS_COMBUSTUS] = &WS2812FX::mode_circus_combustus;
|
||||||
|
_mode[FX_MODE_HALLOWEEN] = &WS2812FX::mode_halloween;
|
||||||
|
_mode[FX_MODE_BICOLOR_CHASE] = &WS2812FX::mode_bicolor_chase;
|
||||||
|
_mode[FX_MODE_TRICOLOR_CHASE] = &WS2812FX::mode_tricolor_chase;
|
||||||
|
// if flash memory is constrained (I'm looking at you Arduino Nano), replace modes
|
||||||
|
// that use a lot of flash with mode_static (reduces flash footprint by about 2100 bytes)
|
||||||
|
#ifdef REDUCED_MODES
|
||||||
|
_mode[FX_MODE_BREATH] = &WS2812FX::mode_static;
|
||||||
|
_mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_static;
|
||||||
|
_mode[FX_MODE_ICU] = &WS2812FX::mode_static;
|
||||||
|
#else
|
||||||
|
_mode[FX_MODE_BREATH] = &WS2812FX::mode_breath;
|
||||||
|
_mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_running_lights;
|
||||||
|
_mode[FX_MODE_ICU] = &WS2812FX::mode_icu;
|
||||||
|
#endif
|
||||||
|
_mode[FX_MODE_CUSTOM_0] = &WS2812FX::mode_custom_0;
|
||||||
|
_mode[FX_MODE_CUSTOM_1] = &WS2812FX::mode_custom_1;
|
||||||
|
_mode[FX_MODE_CUSTOM_2] = &WS2812FX::mode_custom_2;
|
||||||
|
_mode[FX_MODE_CUSTOM_3] = &WS2812FX::mode_custom_3;
|
||||||
|
_mode[FX_MODE_CUSTOM_4] = &WS2812FX::mode_custom_4;
|
||||||
|
_mode[FX_MODE_CUSTOM_5] = &WS2812FX::mode_custom_5;
|
||||||
|
_mode[FX_MODE_CUSTOM_6] = &WS2812FX::mode_custom_6;
|
||||||
|
_mode[FX_MODE_CUSTOM_7] = &WS2812FX::mode_custom_7;
|
||||||
|
_mode[FX_MODE_CUSTOM_8] = &WS2812FX::mode_custom_8;
|
||||||
|
_mode[FX_MODE_CUSTOM_9] = &WS2812FX::mode_custom_9;
|
||||||
|
|
||||||
|
brightness = DEFAULT_BRIGHTNESS + 1; // Adafruit_NeoPixel internally offsets brightness by 1
|
||||||
|
_running = false;
|
||||||
|
_num_segments = 1;
|
||||||
|
_segments[0].mode = DEFAULT_MODE;
|
||||||
|
_segments[0].colors[0] = DEFAULT_COLOR;
|
||||||
|
_segments[0].start = 0;
|
||||||
|
_segments[0].stop = n - 1;
|
||||||
|
_segments[0].speed = DEFAULT_SPEED;
|
||||||
|
resetSegmentRuntimes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
// timer(void),
|
||||||
|
init(void),
|
||||||
|
service(void),
|
||||||
|
start(void),
|
||||||
|
stop(void),
|
||||||
|
pause(void),
|
||||||
|
resume(void),
|
||||||
|
strip_off(void),
|
||||||
|
fade_out(void),
|
||||||
|
fade_out(uint32_t),
|
||||||
|
setMode(uint8_t m),
|
||||||
|
setMode(uint8_t seg, uint8_t m),
|
||||||
|
setOptions(uint8_t seg, uint8_t o),
|
||||||
|
setCustomMode(uint16_t (*p)()),
|
||||||
|
setCustomShow(void (*p)()),
|
||||||
|
setSpeed(uint16_t s),
|
||||||
|
setSpeed(uint8_t seg, uint16_t s),
|
||||||
|
increaseSpeed(uint8_t s),
|
||||||
|
decreaseSpeed(uint8_t s),
|
||||||
|
setColor(uint8_t r, uint8_t g, uint8_t b),
|
||||||
|
setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w),
|
||||||
|
setColor(uint32_t c),
|
||||||
|
setColor(uint8_t seg, uint32_t c),
|
||||||
|
setColors(uint8_t seg, uint32_t* c),
|
||||||
|
setBrightness(uint8_t b),
|
||||||
|
increaseBrightness(uint8_t s),
|
||||||
|
decreaseBrightness(uint8_t s),
|
||||||
|
setLength(uint16_t b),
|
||||||
|
increaseLength(uint16_t s),
|
||||||
|
decreaseLength(uint16_t s),
|
||||||
|
trigger(void),
|
||||||
|
setNumSegments(uint8_t n),
|
||||||
|
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, bool reverse),
|
||||||
|
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, uint8_t options),
|
||||||
|
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint16_t speed, bool reverse),
|
||||||
|
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint16_t speed, uint8_t options),
|
||||||
|
resetSegments(),
|
||||||
|
resetSegmentRuntimes(),
|
||||||
|
resetSegmentRuntime(uint8_t),
|
||||||
|
setPixelColor(uint16_t n, uint32_t c),
|
||||||
|
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b),
|
||||||
|
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w),
|
||||||
|
copyPixels(uint16_t d, uint16_t s, uint16_t c),
|
||||||
|
show(void);
|
||||||
|
|
||||||
|
boolean
|
||||||
|
isRunning(void),
|
||||||
|
isTriggered(void),
|
||||||
|
isFrame(void),
|
||||||
|
isFrame(uint8_t),
|
||||||
|
isCycle(void),
|
||||||
|
isCycle(uint8_t);
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
random8(void),
|
||||||
|
random8(uint8_t),
|
||||||
|
getMode(void),
|
||||||
|
getMode(uint8_t),
|
||||||
|
getModeCount(void),
|
||||||
|
setCustomMode(const __FlashStringHelper* name, uint16_t (*p)()),
|
||||||
|
setCustomMode(uint8_t i, const __FlashStringHelper* name, uint16_t (*p)()),
|
||||||
|
getNumSegments(void),
|
||||||
|
get_random_wheel_index(uint8_t),
|
||||||
|
getOptions(uint8_t),
|
||||||
|
getNumBytesPerPixel(void),
|
||||||
|
getSegmentIndex(void);
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
random16(void),
|
||||||
|
random16(uint16_t),
|
||||||
|
getSpeed(void),
|
||||||
|
getSpeed(uint8_t),
|
||||||
|
getLength(void),
|
||||||
|
getNumBytes(void);
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
color_wheel(uint8_t),
|
||||||
|
getColor(void),
|
||||||
|
getColor(uint8_t),
|
||||||
|
intensitySum(void);
|
||||||
|
|
||||||
|
uint32_t* getColors(uint8_t);
|
||||||
|
uint32_t* intensitySums(void);
|
||||||
|
|
||||||
|
const __FlashStringHelper* getModeName(uint8_t m);
|
||||||
|
|
||||||
|
WS2812FX::Segment* getSegment(void);
|
||||||
|
|
||||||
|
WS2812FX::Segment* getSegment(uint8_t);
|
||||||
|
|
||||||
|
WS2812FX::Segment* getSegments(void);
|
||||||
|
|
||||||
|
WS2812FX::Segment_runtime* getSegmentRuntime(void);
|
||||||
|
|
||||||
|
WS2812FX::Segment_runtime* getSegmentRuntime(uint8_t);
|
||||||
|
|
||||||
|
WS2812FX::Segment_runtime* getSegmentRuntimes(void);
|
||||||
|
|
||||||
|
// mode helper functions
|
||||||
|
uint16_t
|
||||||
|
blink(uint32_t, uint32_t, bool strobe),
|
||||||
|
color_wipe(uint32_t, uint32_t, bool),
|
||||||
|
twinkle(uint32_t, uint32_t),
|
||||||
|
twinkle_fade(uint32_t),
|
||||||
|
chase(uint32_t, uint32_t, uint32_t),
|
||||||
|
running(uint32_t, uint32_t),
|
||||||
|
fireworks(uint32_t),
|
||||||
|
fire_flicker(int),
|
||||||
|
tricolor_chase(uint32_t, uint32_t, uint32_t),
|
||||||
|
scan(uint32_t, uint32_t, bool);
|
||||||
|
uint32_t
|
||||||
|
color_blend(uint32_t, uint32_t, uint8_t);
|
||||||
|
|
||||||
|
// builtin modes
|
||||||
|
uint16_t
|
||||||
|
mode_static(void),
|
||||||
|
mode_blink(void),
|
||||||
|
mode_blink_rainbow(void),
|
||||||
|
mode_strobe(void),
|
||||||
|
mode_strobe_rainbow(void),
|
||||||
|
mode_color_wipe(void),
|
||||||
|
mode_color_wipe_inv(void),
|
||||||
|
mode_color_wipe_rev(void),
|
||||||
|
mode_color_wipe_rev_inv(void),
|
||||||
|
mode_color_wipe_random(void),
|
||||||
|
mode_color_sweep_random(void),
|
||||||
|
mode_random_color(void),
|
||||||
|
mode_single_dynamic(void),
|
||||||
|
mode_multi_dynamic(void),
|
||||||
|
mode_breath(void),
|
||||||
|
mode_fade(void),
|
||||||
|
mode_scan(void),
|
||||||
|
mode_dual_scan(void),
|
||||||
|
mode_theater_chase(void),
|
||||||
|
mode_theater_chase_rainbow(void),
|
||||||
|
mode_rainbow(void),
|
||||||
|
mode_rainbow_cycle(void),
|
||||||
|
mode_running_lights(void),
|
||||||
|
mode_twinkle(void),
|
||||||
|
mode_twinkle_random(void),
|
||||||
|
mode_twinkle_fade(void),
|
||||||
|
mode_twinkle_fade_random(void),
|
||||||
|
mode_sparkle(void),
|
||||||
|
mode_flash_sparkle(void),
|
||||||
|
mode_hyper_sparkle(void),
|
||||||
|
mode_multi_strobe(void),
|
||||||
|
mode_chase_white(void),
|
||||||
|
mode_chase_color(void),
|
||||||
|
mode_chase_random(void),
|
||||||
|
mode_chase_rainbow(void),
|
||||||
|
mode_chase_flash(void),
|
||||||
|
mode_chase_flash_random(void),
|
||||||
|
mode_chase_rainbow_white(void),
|
||||||
|
mode_chase_blackout(void),
|
||||||
|
mode_chase_blackout_rainbow(void),
|
||||||
|
mode_running_color(void),
|
||||||
|
mode_running_red_blue(void),
|
||||||
|
mode_running_random(void),
|
||||||
|
mode_larson_scanner(void),
|
||||||
|
mode_comet(void),
|
||||||
|
mode_fireworks(void),
|
||||||
|
mode_fireworks_random(void),
|
||||||
|
mode_merry_christmas(void),
|
||||||
|
mode_halloween(void),
|
||||||
|
mode_fire_flicker(void),
|
||||||
|
mode_fire_flicker_soft(void),
|
||||||
|
mode_fire_flicker_intense(void),
|
||||||
|
mode_circus_combustus(void),
|
||||||
|
mode_bicolor_chase(void),
|
||||||
|
mode_tricolor_chase(void),
|
||||||
|
mode_icu(void),
|
||||||
|
mode_custom_0(void),
|
||||||
|
mode_custom_1(void),
|
||||||
|
mode_custom_2(void),
|
||||||
|
mode_custom_3(void),
|
||||||
|
mode_custom_4(void),
|
||||||
|
mode_custom_5(void),
|
||||||
|
mode_custom_6(void),
|
||||||
|
mode_custom_7(void),
|
||||||
|
mode_custom_8(void),
|
||||||
|
mode_custom_9(void);
|
||||||
|
private:
|
||||||
|
uint16_t _rand16seed;
|
||||||
|
uint16_t (*customModes[MAX_CUSTOM_MODES])(void) {
|
||||||
|
[]{ return (uint16_t)1000; },
|
||||||
|
[]{ return (uint16_t)1000; },
|
||||||
|
[]{ return (uint16_t)1000; },
|
||||||
|
[]{ return (uint16_t)1000; },
|
||||||
|
[]{ return (uint16_t)1000; },
|
||||||
|
[]{ return (uint16_t)1000; },
|
||||||
|
[]{ return (uint16_t)1000; },
|
||||||
|
[]{ return (uint16_t)1000; },
|
||||||
|
[]{ return (uint16_t)1000; },
|
||||||
|
[]{ return (uint16_t)1000; }
|
||||||
|
};
|
||||||
|
void (*customShow)(void) = NULL;
|
||||||
|
|
||||||
|
boolean
|
||||||
|
_running,
|
||||||
|
_triggered;
|
||||||
|
|
||||||
|
mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element
|
||||||
|
|
||||||
|
uint8_t _segment_index = 0;
|
||||||
|
uint8_t _num_segments = 1;
|
||||||
|
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 20 bytes per element
|
||||||
|
// start, stop, speed, mode, options, color[]
|
||||||
|
{ 0, 7, DEFAULT_SPEED, FX_MODE_STATIC, NO_OPTIONS, {DEFAULT_COLOR}}
|
||||||
|
};
|
||||||
|
segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 16 bytes per element
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
@@ -0,0 +1,676 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>SPIFFS Editor</title>
|
||||||
|
<style type="text/css" media="screen">
|
||||||
|
.contextMenu {
|
||||||
|
z-index: 300;
|
||||||
|
position: absolute;
|
||||||
|
left: 5px;
|
||||||
|
border: 1px solid #444;
|
||||||
|
background-color: #F5F5F5;
|
||||||
|
display: none;
|
||||||
|
box-shadow: 0 0 10px rgba( 0, 0, 0, .4 );
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-weight:bold;
|
||||||
|
}
|
||||||
|
.contextMenu ul {
|
||||||
|
list-style: none;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.contextMenu li {
|
||||||
|
position: relative;
|
||||||
|
min-width: 60px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.contextMenu span {
|
||||||
|
color: #444;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
.contextMenu li:hover { background: #444; }
|
||||||
|
.contextMenu li:hover span { color: #EEE; }
|
||||||
|
|
||||||
|
.css-treeview ul, .css-treeview li {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview input {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview {
|
||||||
|
font: normal 11px Verdana, Arial, Sans-serif;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview span {
|
||||||
|
color: #00f;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview span:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview input + label + ul {
|
||||||
|
margin: 0 0 0 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview input ~ ul {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview label, .css-treeview label::before {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview input:disabled + label {
|
||||||
|
cursor: default;
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview input:checked:not(:disabled) ~ ul {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview label, .css-treeview label::before {
|
||||||
|
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAACgCAYAAAAFOewUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAApxJREFUeNrslM1u00AQgGdthyalFFOK+ClIIKQKyqUVQvTEE3DmAhLwAhU8QZoH4A2Q2gMSFace4MCtJ8SPBFwAkRuiHKpA6sRN/Lu7zG5i14kctaUqRGhGXnu9O/Pt7MzsMiklvF+9t2kWTDvyIrAsA0aKRRi1T0C/hJ4LUbt5/8rNpWVlp8RSr9J40b48fxFaTQ9+ft8EZ6MJYb0Ok+dnYGpmPgXwKIAvLx8vYXc5GdMAQJgQEkpjRTh36TS2U+DWW/D17WuYgm8pwJyY1npZsZKOxImOV1I/h4+O6vEg5GCZBpgmA6hX8wHKUHDRBXQYicQ4rlc3Tf0VMs8DHBS864F2YFspjgUYjKX/Az3gsdQd2eeBHwmdGWXHcgBGSkZXOXohcEXebRoQcAgjqediNY+AVyu3Z3sAKqfKoGMsewBeEIOPgQxxPJIjcGH6qtL/0AdADzKGnuuD+2tLK7Q8DhHHbOBW+KEzcHLuYc82MkEUekLiwuvVH+guQBQzOG4XdAb8EOcRcqQvDkY2iCLuxECJ43JobMXoutqGgDa2T7UqLKwt9KRyuxKVByqVXXqIoCCUCAqhUOioTWC7G4TQEOD0APy2/7G2Xpu1J4+lxeQ4TXBbITDpoVelRN/BVFbwu5oMMJUBhoXy5tmdRcMwymP2OLQaLjx9/vnBo6V3K6izATmSnMa0Dq7ferIohJhr1p01zrlz49rZF4OMs8JkX23vVQzYp+wbYGV/KpXKjvspl8tsIKCrMNAYFxj2GKS5ZWxg4ewKsJfaGMIY5KXqPz8LBBj6+yDvVP79+yDp/9F9oIx3OisHWwe7Oal0HxCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgwD8E/BZgAP0qhKj3rXO7AAAAAElFTkSuQmCC") no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview label, .css-treeview span, .css-treeview label::before {
|
||||||
|
display: inline-block;
|
||||||
|
height: 16px;
|
||||||
|
line-height: 16px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview label {
|
||||||
|
background-position: 18px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview label::before {
|
||||||
|
content: "";
|
||||||
|
width: 16px;
|
||||||
|
margin: 0 22px 0 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-position: 0 -32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview input:checked + label::before {
|
||||||
|
background-position: 0 -16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* webkit adjacent element selector bugfix */
|
||||||
|
@media screen and (-webkit-min-device-pixel-ratio:0)
|
||||||
|
{
|
||||||
|
.css-treeview{
|
||||||
|
-webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes webkit-adjacent-element-selector-bugfix
|
||||||
|
{
|
||||||
|
from {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploader {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
height:28px;
|
||||||
|
line-height: 24px;
|
||||||
|
padding-left: 10px;
|
||||||
|
background-color: #444;
|
||||||
|
color:#EEE;
|
||||||
|
}
|
||||||
|
#tree {
|
||||||
|
position: absolute;
|
||||||
|
top: 28px;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width:200px;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
#editor, #preview {
|
||||||
|
position: absolute;
|
||||||
|
top: 28px;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 200px;
|
||||||
|
}
|
||||||
|
#preview {
|
||||||
|
background-color: #EEE;
|
||||||
|
padding:5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function createFileUploader(element, tree, editor){
|
||||||
|
var xmlHttp;
|
||||||
|
var input = document.createElement("input");
|
||||||
|
input.type = "file";
|
||||||
|
input.multiple = false;
|
||||||
|
input.name = "data";
|
||||||
|
document.getElementById(element).appendChild(input);
|
||||||
|
var path = document.createElement("input");
|
||||||
|
path.id = "upload-path";
|
||||||
|
path.type = "text";
|
||||||
|
path.name = "path";
|
||||||
|
path.defaultValue = "/";
|
||||||
|
document.getElementById(element).appendChild(path);
|
||||||
|
var button = document.createElement("button");
|
||||||
|
button.innerHTML = 'Upload';
|
||||||
|
document.getElementById(element).appendChild(button);
|
||||||
|
var mkdir = document.createElement("button");
|
||||||
|
mkdir.innerHTML = 'MkDir';
|
||||||
|
document.getElementById(element).appendChild(mkdir);
|
||||||
|
var mkfile = document.createElement("button");
|
||||||
|
mkfile.innerHTML = 'MkFile';
|
||||||
|
document.getElementById(element).appendChild(mkfile);
|
||||||
|
var para = document.createElement("text");
|
||||||
|
para.innerHTML = " Press Ctrl-S for save, Ctrl-Z for undo, Ctrl-Shift-Z for redo";
|
||||||
|
document.getElementById(element).appendChild(para);
|
||||||
|
function httpPostProcessRequest(){
|
||||||
|
if (xmlHttp.readyState == 4){
|
||||||
|
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||||
|
else {
|
||||||
|
tree.refreshPath(path.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function createPath(p){
|
||||||
|
xmlHttp = new XMLHttpRequest();
|
||||||
|
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append("path", p);
|
||||||
|
xmlHttp.open("PUT", "/edit");
|
||||||
|
xmlHttp.send(formData);
|
||||||
|
}
|
||||||
|
|
||||||
|
mkfile.onclick = function(e){
|
||||||
|
if(path.value.indexOf(".") === -1) return;
|
||||||
|
createPath(path.value);
|
||||||
|
editor.loadUrl(path.value);
|
||||||
|
};
|
||||||
|
mkdir.onclick = function(e){
|
||||||
|
if(path.value.length < 2) return;
|
||||||
|
var dir = path.value
|
||||||
|
if(dir.indexOf(".") !== -1){
|
||||||
|
if(dir.lastIndexOf("/") === 0) return;
|
||||||
|
dir = dir.substring(0, dir.lastIndexOf("/"));
|
||||||
|
}
|
||||||
|
createPath(dir);
|
||||||
|
};
|
||||||
|
button.onclick = function(e){
|
||||||
|
if(input.files.length === 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xmlHttp = new XMLHttpRequest();
|
||||||
|
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append("data", input.files[0], path.value);
|
||||||
|
xmlHttp.open("POST", "/edit");
|
||||||
|
xmlHttp.send(formData);
|
||||||
|
}
|
||||||
|
input.onchange = function(e){
|
||||||
|
if(input.files.length === 0) return;
|
||||||
|
var filename = input.files[0].name;
|
||||||
|
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
|
||||||
|
var name = /(.*)\.[^.]+$/.exec(filename)[1];
|
||||||
|
if(typeof name !== undefined){
|
||||||
|
if(name.length > 8) name = name.substring(0, 8);
|
||||||
|
filename = name;
|
||||||
|
}
|
||||||
|
if(typeof ext !== undefined){
|
||||||
|
if(ext === "html") ext = "htm";
|
||||||
|
else if(ext === "jpeg") ext = "jpg";
|
||||||
|
filename = filename + "." + ext;
|
||||||
|
}
|
||||||
|
if(path.value === "/" || path.value.lastIndexOf("/") === 0){
|
||||||
|
path.value = "/"+filename;
|
||||||
|
} else {
|
||||||
|
path.value = path.value.substring(0, path.value.lastIndexOf("/")+1)+filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTree(element, editor){
|
||||||
|
var preview = document.getElementById("preview");
|
||||||
|
var treeRoot = document.createElement("div");
|
||||||
|
treeRoot.className = "css-treeview";
|
||||||
|
document.getElementById(element).appendChild(treeRoot);
|
||||||
|
|
||||||
|
function loadDownload(path){
|
||||||
|
document.getElementById('download-frame').src = path+"?download=true";
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadPreview(path){
|
||||||
|
document.getElementById("editor").style.display = "none";
|
||||||
|
preview.style.display = "block";
|
||||||
|
preview.innerHTML = '<img src="'+path+'" style="max-width:100%; max-height:100%; margin:auto; display:block;" />';
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillFolderMenu(el, path){
|
||||||
|
var list = document.createElement("ul");
|
||||||
|
el.appendChild(list);
|
||||||
|
var action = document.createElement("li");
|
||||||
|
list.appendChild(action);
|
||||||
|
var isChecked = document.getElementById(path).checked;
|
||||||
|
var expnd = document.createElement("li");
|
||||||
|
list.appendChild(expnd);
|
||||||
|
if(isChecked){
|
||||||
|
expnd.innerHTML = "<span>Collapse</span>";
|
||||||
|
expnd.onclick = function(e){
|
||||||
|
document.getElementById(path).checked = false;
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
var refrsh = document.createElement("li");
|
||||||
|
list.appendChild(refrsh);
|
||||||
|
refrsh.innerHTML = "<span>Refresh</span>";
|
||||||
|
refrsh.onclick = function(e){
|
||||||
|
var leaf = document.getElementById(path).parentNode;
|
||||||
|
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||||
|
httpGet(leaf, path);
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
expnd.innerHTML = "<span>Expand</span>";
|
||||||
|
expnd.onclick = function(e){
|
||||||
|
document.getElementById(path).checked = true;
|
||||||
|
var leaf = document.getElementById(path).parentNode;
|
||||||
|
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||||
|
httpGet(leaf, path);
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var upload = document.createElement("li");
|
||||||
|
list.appendChild(upload);
|
||||||
|
upload.innerHTML = "<span>Upload</span>";
|
||||||
|
upload.onclick = function(e){
|
||||||
|
var pathEl = document.getElementById("upload-path");
|
||||||
|
if(pathEl){
|
||||||
|
var subPath = pathEl.value;
|
||||||
|
if(subPath.lastIndexOf("/") < 1) pathEl.value = path+subPath;
|
||||||
|
else pathEl.value = path.substring(subPath.lastIndexOf("/"))+subPath;
|
||||||
|
}
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
var delFile = document.createElement("li");
|
||||||
|
list.appendChild(delFile);
|
||||||
|
delFile.innerHTML = "<span>Delete</span>";
|
||||||
|
delFile.onclick = function(e){
|
||||||
|
httpDelete(path);
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillFileMenu(el, path){
|
||||||
|
var list = document.createElement("ul");
|
||||||
|
el.appendChild(list);
|
||||||
|
var action = document.createElement("li");
|
||||||
|
list.appendChild(action);
|
||||||
|
if(isTextFile(path)){
|
||||||
|
action.innerHTML = "<span>Edit</span>";
|
||||||
|
action.onclick = function(e){
|
||||||
|
editor.loadUrl(path);
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
} else if(isImageFile(path)){
|
||||||
|
action.innerHTML = "<span>Preview</span>";
|
||||||
|
action.onclick = function(e){
|
||||||
|
loadPreview(path);
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var download = document.createElement("li");
|
||||||
|
list.appendChild(download);
|
||||||
|
download.innerHTML = "<span>Download</span>";
|
||||||
|
download.onclick = function(e){
|
||||||
|
loadDownload(path);
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
var delFile = document.createElement("li");
|
||||||
|
list.appendChild(delFile);
|
||||||
|
delFile.innerHTML = "<span>Delete</span>";
|
||||||
|
delFile.onclick = function(e){
|
||||||
|
httpDelete(path);
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function showContextMenu(e, path, isfile){
|
||||||
|
var divContext = document.createElement("div");
|
||||||
|
var scrollTop = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;
|
||||||
|
var scrollLeft = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft;
|
||||||
|
var left = e.clientX + scrollLeft;
|
||||||
|
var top = e.clientY + scrollTop;
|
||||||
|
divContext.className = 'contextMenu';
|
||||||
|
divContext.style.display = 'block';
|
||||||
|
divContext.style.left = left + 'px';
|
||||||
|
divContext.style.top = top + 'px';
|
||||||
|
if(isfile) fillFileMenu(divContext, path);
|
||||||
|
else fillFolderMenu(divContext, path);
|
||||||
|
document.body.appendChild(divContext);
|
||||||
|
var width = divContext.offsetWidth;
|
||||||
|
var height = divContext.offsetHeight;
|
||||||
|
divContext.onmouseout = function(e){
|
||||||
|
if(e.clientX < left || e.clientX > (left + width) || e.clientY < top || e.clientY > (top + height)){
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(divContext);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTreeLeaf(path, name, size){
|
||||||
|
var leaf = document.createElement("li");
|
||||||
|
leaf.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
|
||||||
|
var label = document.createElement("span");
|
||||||
|
label.textContent = name.toLowerCase();
|
||||||
|
leaf.appendChild(label);
|
||||||
|
leaf.onclick = function(e){
|
||||||
|
if(isTextFile(leaf.id)){
|
||||||
|
editor.loadUrl(leaf.id);
|
||||||
|
} else if(isImageFile(leaf.id)){
|
||||||
|
loadPreview(leaf.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
leaf.oncontextmenu = function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
showContextMenu(e, leaf.id, true);
|
||||||
|
};
|
||||||
|
return leaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTreeBranch(path, name, disabled){
|
||||||
|
var leaf = document.createElement("li");
|
||||||
|
var check = document.createElement("input");
|
||||||
|
check.type = "checkbox";
|
||||||
|
check.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
|
||||||
|
if(typeof disabled !== "undefined" && disabled) check.disabled = "disabled";
|
||||||
|
leaf.appendChild(check);
|
||||||
|
var label = document.createElement("label");
|
||||||
|
label.for = check.id;
|
||||||
|
label.textContent = name.toLowerCase();
|
||||||
|
leaf.appendChild(label);
|
||||||
|
check.onchange = function(e){
|
||||||
|
if(check.checked){
|
||||||
|
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||||
|
httpGet(leaf, check.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
label.onclick = function(e){
|
||||||
|
if(!check.checked){
|
||||||
|
check.checked = true;
|
||||||
|
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||||
|
httpGet(leaf, check.id);
|
||||||
|
} else {
|
||||||
|
check.checked = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
leaf.oncontextmenu = function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
showContextMenu(e, check.id, false);
|
||||||
|
}
|
||||||
|
return leaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addList(parent, path, items){
|
||||||
|
var list = document.createElement("ul");
|
||||||
|
parent.appendChild(list);
|
||||||
|
var ll = items.length;
|
||||||
|
for(var i = 0; i < ll; i++){
|
||||||
|
var item = items[i];
|
||||||
|
var itemEl;
|
||||||
|
if(item.type === "file"){
|
||||||
|
itemEl = createTreeLeaf(path, item.name, item.size);
|
||||||
|
} else {
|
||||||
|
itemEl = createTreeBranch(path, item.name);
|
||||||
|
}
|
||||||
|
list.appendChild(itemEl);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTextFile(path){
|
||||||
|
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
|
||||||
|
if(typeof ext !== undefined){
|
||||||
|
switch(ext){
|
||||||
|
case "txt":
|
||||||
|
case "htm":
|
||||||
|
case "html":
|
||||||
|
case "js":
|
||||||
|
case "json":
|
||||||
|
case "c":
|
||||||
|
case "h":
|
||||||
|
case "cpp":
|
||||||
|
case "css":
|
||||||
|
case "xml":
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isImageFile(path){
|
||||||
|
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
|
||||||
|
if(typeof ext !== undefined){
|
||||||
|
switch(ext){
|
||||||
|
case "png":
|
||||||
|
case "jpg":
|
||||||
|
case "gif":
|
||||||
|
case "ico":
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.refreshPath = function(path){
|
||||||
|
if(path.lastIndexOf('/') < 1){
|
||||||
|
path = '/';
|
||||||
|
treeRoot.removeChild(treeRoot.childNodes[0]);
|
||||||
|
httpGet(treeRoot, "/");
|
||||||
|
} else {
|
||||||
|
path = path.substring(0, path.lastIndexOf('/'));
|
||||||
|
var leaf = document.getElementById(path).parentNode;
|
||||||
|
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||||
|
httpGet(leaf, path);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function delCb(path){
|
||||||
|
return function(){
|
||||||
|
if (xmlHttp.readyState == 4){
|
||||||
|
if(xmlHttp.status != 200){
|
||||||
|
alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||||
|
} else {
|
||||||
|
if(path.lastIndexOf('/') < 1){
|
||||||
|
path = '/';
|
||||||
|
treeRoot.removeChild(treeRoot.childNodes[0]);
|
||||||
|
httpGet(treeRoot, "/");
|
||||||
|
} else {
|
||||||
|
path = path.substring(0, path.lastIndexOf('/'));
|
||||||
|
var leaf = document.getElementById(path).parentNode;
|
||||||
|
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||||
|
httpGet(leaf, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function httpDelete(filename){
|
||||||
|
xmlHttp = new XMLHttpRequest();
|
||||||
|
xmlHttp.onreadystatechange = delCb(filename);
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append("path", filename);
|
||||||
|
xmlHttp.open("DELETE", "/edit");
|
||||||
|
xmlHttp.send(formData);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCb(parent, path){
|
||||||
|
return function(){
|
||||||
|
if (xmlHttp.readyState == 4){
|
||||||
|
//clear loading
|
||||||
|
if(xmlHttp.status == 200) addList(parent, path, JSON.parse(xmlHttp.responseText));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function httpGet(parent, path){
|
||||||
|
xmlHttp = new XMLHttpRequest(parent, path);
|
||||||
|
xmlHttp.onreadystatechange = getCb(parent, path);
|
||||||
|
xmlHttp.open("GET", "/list?dir="+path, true);
|
||||||
|
xmlHttp.send(null);
|
||||||
|
//start loading
|
||||||
|
}
|
||||||
|
|
||||||
|
httpGet(treeRoot, "/");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createEditor(element, file, lang, theme, type){
|
||||||
|
function getLangFromFilename(filename){
|
||||||
|
var lang = "plain";
|
||||||
|
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
|
||||||
|
if(typeof ext !== undefined){
|
||||||
|
switch(ext){
|
||||||
|
case "txt": lang = "plain"; break;
|
||||||
|
case "htm": lang = "html"; break;
|
||||||
|
case "js": lang = "javascript"; break;
|
||||||
|
case "c": lang = "c_cpp"; break;
|
||||||
|
case "cpp": lang = "c_cpp"; break;
|
||||||
|
case "css":
|
||||||
|
case "scss":
|
||||||
|
case "php":
|
||||||
|
case "html":
|
||||||
|
case "json":
|
||||||
|
case "xml":
|
||||||
|
lang = ext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof file === "undefined") file = "/index.htm";
|
||||||
|
|
||||||
|
if(typeof lang === "undefined"){
|
||||||
|
lang = getLangFromFilename(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof theme === "undefined") theme = "textmate";
|
||||||
|
|
||||||
|
if(typeof type === "undefined"){
|
||||||
|
type = "text/"+lang;
|
||||||
|
if(lang === "c_cpp") type = "text/plain";
|
||||||
|
}
|
||||||
|
|
||||||
|
var xmlHttp = null;
|
||||||
|
var editor = ace.edit(element);
|
||||||
|
|
||||||
|
//post
|
||||||
|
function httpPostProcessRequest(){
|
||||||
|
if (xmlHttp.readyState == 4){
|
||||||
|
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function httpPost(filename, data, type){
|
||||||
|
xmlHttp = new XMLHttpRequest();
|
||||||
|
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append("data", new Blob([data], { type: type }), filename);
|
||||||
|
xmlHttp.open("POST", "/edit");
|
||||||
|
xmlHttp.send(formData);
|
||||||
|
}
|
||||||
|
//get
|
||||||
|
function httpGetProcessRequest(){
|
||||||
|
if (xmlHttp.readyState == 4){
|
||||||
|
document.getElementById("preview").style.display = "none";
|
||||||
|
document.getElementById("editor").style.display = "block";
|
||||||
|
if(xmlHttp.status == 200) editor.setValue(xmlHttp.responseText);
|
||||||
|
else editor.setValue("");
|
||||||
|
editor.clearSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function httpGet(theUrl){
|
||||||
|
xmlHttp = new XMLHttpRequest();
|
||||||
|
xmlHttp.onreadystatechange = httpGetProcessRequest;
|
||||||
|
xmlHttp.open("GET", theUrl, true);
|
||||||
|
xmlHttp.send(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
|
||||||
|
editor.setTheme("ace/theme/"+theme);
|
||||||
|
editor.$blockScrolling = Infinity;
|
||||||
|
editor.getSession().setUseSoftTabs(true);
|
||||||
|
editor.getSession().setTabSize(2);
|
||||||
|
editor.setHighlightActiveLine(true);
|
||||||
|
editor.setShowPrintMargin(false);
|
||||||
|
editor.commands.addCommand({
|
||||||
|
name: 'saveCommand',
|
||||||
|
bindKey: {win: 'Ctrl-S', mac: 'Command-S'},
|
||||||
|
exec: function(editor) {
|
||||||
|
httpPost(file, editor.getValue()+"", type);
|
||||||
|
},
|
||||||
|
readOnly: false
|
||||||
|
});
|
||||||
|
editor.commands.addCommand({
|
||||||
|
name: 'undoCommand',
|
||||||
|
bindKey: {win: 'Ctrl-Z', mac: 'Command-Z'},
|
||||||
|
exec: function(editor) {
|
||||||
|
editor.getSession().getUndoManager().undo(false);
|
||||||
|
},
|
||||||
|
readOnly: false
|
||||||
|
});
|
||||||
|
editor.commands.addCommand({
|
||||||
|
name: 'redoCommand',
|
||||||
|
bindKey: {win: 'Ctrl-Shift-Z', mac: 'Command-Shift-Z'},
|
||||||
|
exec: function(editor) {
|
||||||
|
editor.getSession().getUndoManager().redo(false);
|
||||||
|
},
|
||||||
|
readOnly: false
|
||||||
|
});
|
||||||
|
httpGet(file);
|
||||||
|
editor.loadUrl = function(filename){
|
||||||
|
file = filename;
|
||||||
|
lang = getLangFromFilename(file);
|
||||||
|
type = "text/"+lang;
|
||||||
|
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
|
||||||
|
httpGet(file);
|
||||||
|
}
|
||||||
|
return editor;
|
||||||
|
}
|
||||||
|
function onBodyLoad(){
|
||||||
|
var vars = {};
|
||||||
|
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value; });
|
||||||
|
var editor = createEditor("editor", vars.file, vars.lang, vars.theme);
|
||||||
|
var tree = createTree("tree", editor);
|
||||||
|
createFileUploader("uploader", tree, editor);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.9/ace.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
</head>
|
||||||
|
<body onload="onBodyLoad();">
|
||||||
|
<div id="uploader"></div>
|
||||||
|
<div id="tree"></div>
|
||||||
|
<div id="editor"></div>
|
||||||
|
<div id="preview" style="display:none;"></div>
|
||||||
|
<iframe id=download-frame style='display:none;'></iframe>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 34 KiB |
Binary file not shown.
+2686
-87
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
@@ -1,43 +1,71 @@
|
|||||||
;
|
#define USE_WS2812FX_DMA 0 // 0 = Used PIN is ignored & set to RX/GPIO3; 1 = Used PIN is ignored & set to TX/GPIO1; 2 = Used PIN is ignored & set to D4/GPIO2; Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX
|
||||||
#define USE_WS2812FX_DMA 0 // 0 = Used PIN is ignored & set to RX/GPIO3; 1 = Used PIN is ignored & set to D4/GPIO2; 2 = Uses PIN is ignored & set to TX/GPIO1; Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX
|
// or comment it out
|
||||||
|
#if defined(USE_WS2812FX_DMA)
|
||||||
|
#define MAXLEDS 384 // due to memory limit of esp8266 at the moment only 384 leds are supported in DMA Mode. More can crash if mqtt is used.
|
||||||
|
#else
|
||||||
|
#define MAXLEDS 4096
|
||||||
|
#endif
|
||||||
// Neopixel
|
// Neopixel
|
||||||
#define PIN 3 // PIN (15 / D8) where neopixel / WS2811 strip is attached
|
#define LED_PIN 3 // PIN (15 / D8) where neopixel / WS2811 strip is attached; is configurable, if USE_WS2812FX_DMA is not defined. Just for the start
|
||||||
#define NUMLEDS 144 // Number of leds in the strip
|
#define NUMLEDS 50 // Number of leds in the; is configurable just for the start
|
||||||
|
#define RGBORDER "GRBW" // RGBOrder; is configurable just for the start
|
||||||
|
#define FX_OPTIONS 48 // ws2812fx Options 48 = SIZE_SMALL + FADE_MEDIUM is configurable just for the start; for WS2812FX setSegment OPTIONS, see: https://github.com/kitesurfer1404/WS2812FX/blob/master/extras/WS2812FX%20Users%20Guide.md
|
||||||
|
//#define LED_TYPE_WS2811 // Uncomment, if LED type uses 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
|
||||||
#define LED_BUILTIN 2 // ESP-12F has the built in LED on GPIO2, see https://github.com/esp8266/Arduino/issues/2192
|
#define LED_BUILTIN 2 // ESP-12F has the built in LED on GPIO2, see https://github.com/esp8266/Arduino/issues/2192
|
||||||
#define RGBW // If defined, use RGBW Strips
|
char HOSTNAME[65] = "McLightingRGBW"; // Friedly hostname is configurable just for the start. Hostname should not contain spaces as this can break Home Assistant discovery if used.
|
||||||
|
|
||||||
const char HOSTNAME[] = "McLightingRGBW_01"; // Friedly hostname
|
|
||||||
|
|
||||||
#define ENABLE_OTA 1 // If defined, enable Arduino OTA code. If set to 0 enable Arduino OTA code, if set to 1 enable ESP8266HTTPUpdateServer OTA code.
|
#define ENABLE_OTA 1 // If defined, enable Arduino OTA code. If set to 0 enable Arduino OTA code, if set to 1 enable ESP8266HTTPUpdateServer OTA code.
|
||||||
#define ENABLE_MQTT 1 // If defined use MQTT OR AMQTT, if set to 0 enable MQTT client code, see: https://github.com/toblum/McLighting/wiki/MQTT-API, if set to 1, enable Async MQTT code, see: https://github.com/marvinroger/async-mqtt-client
|
#define ENABLE_MQTT 1 // If defined use MQTT OR AMQTT, if set to 0 enable MQTT client code, see: https://github.com/toblum/McLighting/wiki/MQTT-API, if set to 1, enable Async MQTT code, see: https://github.com/marvinroger/async-mqtt-client
|
||||||
//#define ENABLE_MQTT_HOSTNAME_CHIPID // Uncomment/comment to add ESPChipID to end of MQTT hostname
|
//#define ENABLE_MQTT_HOSTNAME_CHIPID // Uncomment/comment to add ESPChipID to end of MQTT hostname
|
||||||
|
//#define ENABLE_MQTT_INCLUDE_IP // uncomment/comment to add the IP-adress to the MQTT message
|
||||||
#define ENABLE_HOMEASSISTANT // If defined, enable Homeassistant integration, ENABLE_MQTT must be active
|
#define ENABLE_HOMEASSISTANT // If defined, enable Homeassistant integration, ENABLE_MQTT must be active
|
||||||
#define MQTT_HOME_ASSISTANT_SUPPORT // If defined, use AMQTT and select Tools -> IwIP Variant -> Higher Bandwidth
|
#define MQTT_HOME_ASSISTANT_SUPPORT // If defined, use AMQTT and select Tools -> IwIP Variant -> Higher Bandwidth
|
||||||
#define ENABLE_BUTTON 14 // If defined, enable button handling code, see: https://github.com/toblum/McLighting/wiki/Button-control, the value defines the input pin (14 / D5) for switching the LED strip on / off, connect this PIN to ground to trigger button.
|
//#define DISABLE_MQTT_OUT_ON_MQTT_IN // If defined, McLighting will not send back MQTT-out on MQTT-in regarding issue #67, does not change anything at the moment
|
||||||
|
|
||||||
|
//#define ENABLE_BUTTON 14 // If defined, enable button handling code, see: https://github.com/toblum/McLighting/wiki/Button-control, the value defines the input pin (14 / D5) for switching the LED strip on / off, connect this PIN to ground to trigger button.
|
||||||
//#define ENABLE_BUTTON_GY33 12 // If defined, enable button handling code for GY-33 color sensor to scan color. The value defines the input pin (12 / D6) for read color data with RGB sensor, connect this PIN to ground to trigger button.
|
//#define ENABLE_BUTTON_GY33 12 // If defined, enable button handling code for GY-33 color sensor to scan color. The value defines the input pin (12 / D6) for read color data with RGB sensor, connect this PIN to ground to trigger button.
|
||||||
//#define ENABLE_REMOTE 13 // If defined, enable Remote Control via TSOP31238. The value defines the input pin (13 / D7) for TSOP31238 Out
|
//#define POWER_SUPPLY 12 // PIN (12 / D6) If defined, enable output to control external power supply
|
||||||
|
#if defined(POWER_SUPPLY)
|
||||||
|
#define POWER_ON HIGH // Define the output state to turn on the power supply, either HIGH or LOW. Opposite will be uses for power off.
|
||||||
|
#endif
|
||||||
|
#define ENABLE_REMOTE 13 // If defined, enable Remote Control via TSOP31238. The value defines the input pin (13 / D7) for TSOP31238 Out
|
||||||
|
|
||||||
#define ENABLE_STATE_SAVE 1 // If defined, save state on reboot, if set to 0 in EEPROM, if set to 1 on SPIFFS
|
#if defined(ENABLE_BUTTON_GY33)
|
||||||
|
#define GAMMA 2.5 // Gamma correction for GY-33 sensor
|
||||||
#define ENABLE_LEGACY_ANIMATIONS // Enable Legacy Animations
|
|
||||||
#define ENABLE_E131 // E1.31 implementation You have to uncomment #define USE_WS2812FX_DMA and set it to 0
|
|
||||||
#define ENABLE_TV // Enable TV Animation
|
|
||||||
|
|
||||||
#if defined(ENABLE_E131)
|
|
||||||
#define START_UNIVERSE 1 // First DMX Universe to listen for
|
|
||||||
#define END_UNIVERSE 2 // Total number of Universes to listen for, starting at UNIVERSE
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ENABLE_STATE_SAVE // If defined, load saved state on reboot and save state on SPIFFS
|
||||||
|
|
||||||
|
#define CUSTOM_WS2812FX_ANIMATIONS // uncomment and put animations in "custom_ws2812fx_animations.h"
|
||||||
|
#define USE_HTML_MIN_GZ // uncomment for using index.htm & edit.htm from PROGMEM instead of SPIFFS
|
||||||
|
|
||||||
|
#define TRANS_COLOR_DELAY 5 // Delay for color transition
|
||||||
|
#define TRANS_DELAY 10 // Delay for brightness and speed transition
|
||||||
|
|
||||||
|
// Experimental: Enable transitions of color, brightness and speed. It does not work properly for all effects.
|
||||||
|
bool transEffectOverride = false;
|
||||||
|
uint8_t trans_cnt = 0;
|
||||||
|
int trans_cnt_max = 0;
|
||||||
|
unsigned long colorFadeDelay = 0;
|
||||||
|
unsigned long brightnessFadeDelay = 0;
|
||||||
|
unsigned long speedFadeDelay = 0;
|
||||||
|
|
||||||
|
#if defined(CUSTOM_WS2812FX_ANIMATIONS)
|
||||||
|
#define MULTICAST false
|
||||||
|
#define START_UNIVERSE 1 // First DMX Universe to listen for
|
||||||
|
uint8_t END_UNIVERSE = START_UNIVERSE; // Total number of Universes to listen for, starting at UNIVERSE
|
||||||
|
|
||||||
|
#endif
|
||||||
|
uint8_t prevsegment = 0;
|
||||||
|
|
||||||
#if defined(ENABLE_REMOTE)
|
#if defined(ENABLE_REMOTE)
|
||||||
int selected_color = 1;
|
uint8_t selected_color = 1;
|
||||||
int chng = 1;
|
|
||||||
uint64_t last_remote_cmd;
|
uint64_t last_remote_cmd;
|
||||||
enum RMT_BTN {ON_OFF, MODE_UP, MODE_DOWN, RED_UP, RED_DOWN, GREEN_UP, GREEN_DOWN, BLUE_UP, BLUE_DOWN, WHITE_UP, WHITE_DOWN, BRIGHTNESS_UP, BRIGHTNESS_DOWN, SPEED_UP, SPEED_DOWN, COL_M, COL_B, COL_X, AUTOMODE, CUST_1, CUST_2, CUST_3, CUST_4, CUST_5, REPEATCMD, BTN_CNT};
|
enum RMT_BTN {ON_OFF, MODE_UP, MODE_DOWN, RED_UP, RED_DOWN, GREEN_UP, GREEN_DOWN, BLUE_UP, BLUE_DOWN, WHITE_UP, WHITE_DOWN, BRIGHTNESS_UP, BRIGHTNESS_DOWN, SPEED_UP, SPEED_DOWN, COL_M, COL_B, COL_X, AUTOMODE, CUST_1, CUST_2, CUST_3, SEG_UP, SEG_DOWN, REPEATCMD, BTN_CNT};
|
||||||
// Change your IR Commands here. You can see them in console, after you pressed a button on the remote
|
// Change your IR Commands here. You can see them in console, after you pressed a button on the remote
|
||||||
uint64_t rmt_commands[BTN_CNT] = {0xF7C03F, 0xF7708F, 0xF7F00F, 0xF720DF, 0xF710EF, 0xF7A05F, 0xF7906F, 0xF7609F, 0xF750AF, 0xF7E01F, 0xF7D02F, 0xF730CF, 0xF7B04F, 0xF748B7, 0xF7C837, 0xF700FF, 0xF7807F, 0xF740BF, 0xF708F7, 0xF78877, 0xF728D7, 0xF7A857, 0xF76897, 0xF7E817, 0xFFFFFFFFFFFFFFFF};
|
uint64_t rmt_commands[BTN_CNT] = {0xF7C03F, 0xF7708F, 0xF7F00F, 0xF720DF, 0xF710EF, 0xF7A05F, 0xF7906F, 0xF7609F, 0xF750AF, 0xF7E01F, 0xF7D02F, 0xF730CF, 0xF7B04F, 0xF748B7, 0xF7C837, 0xF700FF, 0xF7807F, 0xF740BF, 0xF708F7, 0xF78877, 0xF728D7, 0xF7A857, 0xF76897, 0xF7E817, 0xFFFFFFFFFFFFFFFF};
|
||||||
#endif
|
#endif
|
||||||
//#define WIFIMGR_PORTAL_TIMEOUT 180
|
#define WIFIMGR_PORTAL_TIMEOUT 180
|
||||||
//#define WIFIMGR_SET_MANUAL_IP
|
//#define WIFIMGR_SET_MANUAL_IP
|
||||||
|
|
||||||
#if defined(WIFIMGR_SET_MANUAL_IP)
|
#if defined(WIFIMGR_SET_MANUAL_IP)
|
||||||
@@ -47,7 +75,19 @@ const char HOSTNAME[] = "McLightingRGBW_01"; // Friedly hostname
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MQTT_HOME_ASSISTANT_SUPPORT)
|
#if defined(MQTT_HOME_ASSISTANT_SUPPORT)
|
||||||
#define MQTT_HOME_ASSISTANT_0_84_SUPPORT // Comment if using HA version < 0.84
|
#define MQTT_HOME_ASSISTANT_0_87_SUPPORT // Comment if using HA version < 0.87
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_WS2812FX_DMA) && (USE_WS2812FX_DMA < 0 || USE_WS2812FX_DMA > 2)
|
||||||
|
#error "Definition of USE_WS2812FX_DMA is wrong!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ENABLE_MQTT) and ENABLE_MQTT < 0 and ENABLE_MQTT > 1
|
||||||
|
#error "Definition of ENABLE_MQTT is wrong!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ENABLE_MQTT) and ENABLE_MQTT < 0 and ENABLE_MQTT > 1
|
||||||
|
#error "Definition of ENABLE_MQTT is wrong!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ENABLE_HOMEASSISTANT) and !defined(ENABLE_MQTT)
|
#if defined(ENABLE_HOMEASSISTANT) and !defined(ENABLE_MQTT)
|
||||||
@@ -58,22 +98,25 @@ const char HOSTNAME[] = "McLightingRGBW_01"; // Friedly hostname
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// parameters for automatically cycling favorite patterns
|
// parameters for automatically cycling favorite patterns
|
||||||
uint32_t autoParams[][6] = { // main_color, back_color, xtra_color, speed, mode, duration (seconds)
|
uint32_t autoParams[][6] = { // main_color, back_color, xtra_color, speed, mode, duration (milliseconds)
|
||||||
{0xff000000, 0x00ff0000, 0x00000000, 200, 1, 5}, // blink red/geen for 5 seconds
|
{0x00ff0000, 0x0000ff00, 0x00000000, 200, 1, 5000}, // blink red/geen for 5 seconds
|
||||||
{0x00ff0000, 0x0000ff00, 0x00000000, 200, 3, 10}, // wipe green/blue for 10 seconds
|
{0x0000ff00, 0x000000ff, 0x00000000, 180, 3, 10000}, // wipe green/blue for 10 seconds
|
||||||
{0x0000ff00, 0xff000000, 0x00000000, 60, 14, 10}, // dual scan blue on red for 10 seconds
|
{0x000000ff, 0x00ff0000, 0x00000000, 100, 14, 10000}, // dual scan blue on red for 10 seconds
|
||||||
{0x0000ff00, 0xff000000, 0x00000000, 40, 45, 15}, // fireworks blue/red for 15 seconds
|
{0x000000ff, 0x00ff0000, 0x00000000, 100, 45, 15000}, // fireworks blue/red for 15 seconds
|
||||||
{0xff000000, 0x00ff0000, 0x0000ff00, 40, 54, 15} // tricolor chase red/green/blue for 15 seconds
|
{0x00ff0000, 0x0000ff00, 0x000000ff, 40, 54, 15000} // tricolor chase red/green/blue for 15 seconds
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(ENABLE_MQTT)
|
#if defined(ENABLE_MQTT)
|
||||||
char mqtt_buf[80];
|
char mqtt_buf[80];
|
||||||
char mqtt_intopic[strlen(HOSTNAME) + 3 + 1]; // Topic in will be: <HOSTNAME>/in
|
char mqtt_will_topic[sizeof(HOSTNAME) + 7]; // Topic 'will' will be:HOSTNAME "/status";
|
||||||
char mqtt_outtopic[strlen(HOSTNAME) + 4 + 1]; // Topic out will be: <HOSTNAME>/out
|
const char mqtt_will_payload[] = "OFFLINE";
|
||||||
|
char mqtt_intopic[sizeof(HOSTNAME) + 3]; // Topic 'in' will be: <HOSTNAME>/in
|
||||||
|
char mqtt_outtopic[sizeof(HOSTNAME) + 4]; // Topic 'out' will be: <HOSTNAME>/out
|
||||||
|
bool mqtt_lwt_boot_flag = true;
|
||||||
#if ENABLE_MQTT == 0
|
#if ENABLE_MQTT == 0
|
||||||
#define MQTT_MAX_PACKET_SIZE 2048
|
#define MQTT_MAX_PACKET_SIZE 512
|
||||||
#define MQTT_MAX_RECONNECT_TRIES 4
|
#define MQTT_MAX_RECONNECT_TRIES 4
|
||||||
int mqtt_reconnect_retries = 0;
|
uint8_t mqtt_reconnect_retries = 0;
|
||||||
uint8_t qossub = 0; // PubSubClient can sub qos 0 or 1
|
uint8_t qossub = 0; // PubSubClient can sub qos 0 or 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -83,24 +126,20 @@ uint32_t autoParams[][6] = { // main_color, back_color, xtra_color, speed, mod
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ENABLE_HOMEASSISTANT)
|
#if defined(ENABLE_HOMEASSISTANT)
|
||||||
char mqtt_ha_state_in[5 + strlen(HOSTNAME) + 12 + 1]; // Topic in will be: home/<HOSTNAME>_ha/state/in"
|
char mqtt_ha_config[20 + sizeof(HOSTNAME) + 7]; // Topic config will be: "homeassistant/light/<HOSTNAME>/config"
|
||||||
char mqtt_ha_state_out[5 + strlen(HOSTNAME) + 13 + 1]; // Topic in will be: home/<HOSTNAME>_ha/state/out"
|
char mqtt_ha_state_in[5 + sizeof(HOSTNAME) + 12]; // Topic in will be: "home/<HOSTNAME>_ha/state/in"
|
||||||
|
char mqtt_ha_state_out[5 + sizeof(HOSTNAME) + 13]; // Topic in will be: "home/<HOSTNAME>_ha/state/out"
|
||||||
const char* on_cmd = "ON";
|
const char* on_cmd = "ON";
|
||||||
const char* off_cmd = "OFF";
|
const char* off_cmd = "OFF";
|
||||||
bool new_ha_mqtt_msg = false;
|
bool new_ha_mqtt_msg = false;
|
||||||
uint16_t color_temp = 327; // min is 154 and max is 500
|
uint16_t color_temp = 327; // min is 154 and max is 500
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ENABLE_MQTT_HOSTNAME_CHIPID)
|
char mqtt_clientid[sizeof(HOSTNAME) + 9];
|
||||||
char mqtt_clientid[64];
|
char mqtt_host[65] = ""; //is configurable just for the start
|
||||||
#else
|
uint16_t mqtt_port = 1883; //is configurable just for the start
|
||||||
const char* mqtt_clientid = HOSTNAME;
|
char mqtt_user[33] = ""; //is configurable just for the start
|
||||||
#endif
|
char mqtt_pass[33] = ""; //is configurable just for the start
|
||||||
|
|
||||||
char mqtt_host[64] = "";
|
|
||||||
char mqtt_port[6] = "";
|
|
||||||
char mqtt_user[32] = "";
|
|
||||||
char mqtt_pass[32] = "";
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -109,20 +148,52 @@ uint32_t autoParams[][6] = { // main_color, back_color, xtra_color, speed, mod
|
|||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
#define DBG_OUTPUT_PORT Serial // Set debug output port
|
#define DBG_OUTPUT_PORT Serial // Set debug output port
|
||||||
|
|
||||||
|
uint8_t autoCount[10] = {}; // Global variable for storing the counter for automated playback for each segment
|
||||||
|
unsigned long autoDelay[10] = {}; // Global variable for storing the time to next auto effect for each segment
|
||||||
|
struct {
|
||||||
|
uint16_t start = 0;
|
||||||
|
uint16_t stop = NUMLEDS - 1;
|
||||||
|
uint8_t mode[10] = {}; // Global variable for storing the WS2812FX mode to set for each segment
|
||||||
|
uint8_t speed[10] = {}; // Global variable for storing the speed for effects --> smaller == slower
|
||||||
|
uint32_t colors[10][3] = {}; // 2 dim. Color array for setting colors of WS2812FX
|
||||||
|
uint8_t options = FX_OPTIONS;
|
||||||
|
} segState;
|
||||||
|
|
||||||
// List of all color modes
|
// List of all color modes
|
||||||
enum MODE {OFF, AUTO, TV, E131, CUSTOM, HOLD, SET_ALL, SET_MODE, SET_COLOR, SET_SPEED, SET_BRIGHTNESS};
|
enum MODE {OFF, HOLD, SET};
|
||||||
MODE mode = SET_MODE; // Standard mode that is active when software starts
|
MODE prevmode = HOLD; // Do not change
|
||||||
MODE prevmode = mode;
|
|
||||||
|
|
||||||
int ws2812fx_speed = 196; // Global variable for storing the delay between color changes --> smaller == faster
|
struct {
|
||||||
int brightness = 196; // Global variable for storing the brightness (255 == 100%)
|
uint8_t segment = 0; // Actual selected segment
|
||||||
|
MODE mode = SET; // Standard mode that is active when software starts
|
||||||
|
uint8_t brightness = 196; // Global variable for storing the brightness (255 == 100%)
|
||||||
|
} State;
|
||||||
|
|
||||||
int ws2812fx_mode = 0; // Helper variable to set WS2812FX modes
|
struct {
|
||||||
|
uint8_t segments = 1;
|
||||||
|
uint16_t stripSize = NUMLEDS;
|
||||||
|
char RGBOrder[5] = RGBORDER;
|
||||||
|
#if defined(USE_WS2812FX_DMA)
|
||||||
|
#if USE_WS2812FX_DMA == 0
|
||||||
|
uint8_t pin = 3;
|
||||||
|
#endif
|
||||||
|
#if USE_WS2812FX_DMA == 1
|
||||||
|
uint8_t pin = 2;
|
||||||
|
#endif
|
||||||
|
#if USE_WS2812FX_DMA == 2
|
||||||
|
uint8_t pin = 1;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
uint8_t pin = LED_PIN;
|
||||||
|
#endif
|
||||||
|
bool transEffect = false;
|
||||||
|
} Config;
|
||||||
|
|
||||||
bool shouldSaveConfig = false; // For WiFiManger custom config
|
uint8_t fx_speed = 196; // Global variable for storing the speed for effects while fading --> smaller == slower
|
||||||
|
uint8_t fx_mode = 0;
|
||||||
uint32_t hex_colors[3] = {}; // Color array for setting WS2812FX
|
uint8_t brightness_trans = 0; // Global variable for storing the brightness before change
|
||||||
struct ledstate // Data structure to store a state of a single led
|
uint32_t hexcolors_trans[3] = {}; // Color array of colors of WS2812FX before fading
|
||||||
|
struct ledstate // Data structure to store a state of a single led
|
||||||
{
|
{
|
||||||
uint8_t red;
|
uint8_t red;
|
||||||
uint8_t green;
|
uint8_t green;
|
||||||
@@ -130,24 +201,26 @@ struct ledstate // Data structure to store a state of a single le
|
|||||||
uint8_t white;
|
uint8_t white;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ledstate LEDState; // Define the datatype LEDState
|
typedef struct ledstate LEDState; // Define the datatype LEDState
|
||||||
LEDState ledstates[NUMLEDS]; // Get an array of led states to store the state of the whole strip
|
uint8_t* ledstates; // Set a pointer to get an array of led states to store the state of the whole strip
|
||||||
LEDState main_color = { 255, 0, 0, 0 }; // Store the "main color" of the strip used in single color modes
|
LEDState main_color = { 255, 0, 0, 0 }; // Store the "main color" of the strip used in single color modes
|
||||||
LEDState back_color = { 0, 0, 0, 0 }; // Store the "2nd color" of the strip used in single color modes
|
LEDState back_color = { 0, 0, 0, 0 }; // Store the "2nd color" of the strip used in single color modes
|
||||||
LEDState xtra_color = { 0, 0, 0, 0 }; // Store the "3rd color" of the strip used in single color modes
|
LEDState xtra_color = { 0, 0, 0, 0 }; // Store the "3rd color" of the strip used in single color modes
|
||||||
|
|
||||||
char last_state[67]; // Keeps the state representation before auto or off mode
|
bool updateConfig = false; // For WiFiManger custom config and config
|
||||||
bool updateState = false;
|
|
||||||
|
|
||||||
// Button handling
|
// Button handling
|
||||||
|
|
||||||
#if defined(ENABLE_BUTTON)
|
#if defined(ENABLE_BUTTON) || defined(ENABLE_BUTTON_GY33)
|
||||||
//#define BTN_MODE_SHORT "STA|mo|fxm| h| s| r1| g1| b1| w1| r2| g2| b2| w2| r3| g3| b3| w3" // Example
|
|
||||||
#define BTN_MODE_SHORT "STA| 5| 0|255|196| 0| 0| 0|255| 0| 0| 0| 0| 0| 0| 0| 0" // Static white
|
|
||||||
#define BTN_MODE_MEDIUM "STA| 5| 48|200|196|255|102| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0" // Fire flicker
|
|
||||||
#define BTN_MODE_LONG "STA| 5| 46|200|196|255|102| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0" // Fireworks random
|
|
||||||
unsigned long keyPrevMillis = 0;
|
|
||||||
const unsigned long keySampleIntervalMs = 25;
|
const unsigned long keySampleIntervalMs = 25;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ENABLE_BUTTON)
|
||||||
|
//#define BTN_MODE_SHORT "STA|mo|fxm| s| b| r1| g1| b1| w1| r2| g2| b2| w2| r3| g3| b3| w3" // Example
|
||||||
|
#define BTN_MODE_SHORT "STA| 5| 0|196|255| 0| 0| 0|255| 0| 0| 0| 0| 0| 0| 0| 0" // Static white
|
||||||
|
#define BTN_MODE_MEDIUM "STA| 5| 48|196|200|255|102| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0" // Fire flicker
|
||||||
|
#define BTN_MODE_LONG "STA| 5| 46|196|200|255|102| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0" // Fireworks random
|
||||||
|
unsigned long keyPrevMillis = 0;
|
||||||
byte longKeyPressCountMax = 80; // 80 * 25 = 2000 ms
|
byte longKeyPressCountMax = 80; // 80 * 25 = 2000 ms
|
||||||
byte mediumKeyPressCountMin = 20; // 20 * 25 = 500 ms
|
byte mediumKeyPressCountMin = 20; // 20 * 25 = 500 ms
|
||||||
byte KeyPressCount = 0;
|
byte KeyPressCount = 0;
|
||||||
@@ -156,7 +229,6 @@ bool updateState = false;
|
|||||||
|
|
||||||
#if defined(ENABLE_BUTTON_GY33)
|
#if defined(ENABLE_BUTTON_GY33)
|
||||||
unsigned long keyPrevMillis_gy33 = 0;
|
unsigned long keyPrevMillis_gy33 = 0;
|
||||||
const unsigned long keySampleIntervalMs_gy33 = 25;
|
|
||||||
byte longKeyPressCountMax_gy33 = 80; // 80 * 25 = 2000 ms
|
byte longKeyPressCountMax_gy33 = 80; // 80 * 25 = 2000 ms
|
||||||
byte mediumKeyPressCountMin_gy33 = 20; // 20 * 25 = 500 ms
|
byte mediumKeyPressCountMin_gy33 = 20; // 20 * 25 = 500 ms
|
||||||
byte KeyPressCount_gy33 = 0;
|
byte KeyPressCount_gy33 = 0;
|
||||||
|
|||||||
@@ -0,0 +1,262 @@
|
|||||||
|
#if defined(ENABLE_STATE_SAVE)
|
||||||
|
|
||||||
|
Ticker save_state;
|
||||||
|
Ticker save_seg_state;
|
||||||
|
Ticker save_conf;
|
||||||
|
|
||||||
|
bool updateState = false;
|
||||||
|
bool updateSegState = false;
|
||||||
|
|
||||||
|
void tickerSaveState(){
|
||||||
|
updateState = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tickerSaveConfig(){
|
||||||
|
updateConfig = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tickerSaveSegmentState(){
|
||||||
|
updateSegState = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write configuration to FS JSON
|
||||||
|
bool writeConfigFS(bool save){
|
||||||
|
if (save) {
|
||||||
|
//FS save
|
||||||
|
DBG_OUTPUT_PORT.println("Saving config: ");
|
||||||
|
File configFile = SPIFFS.open("/config.json", "w");
|
||||||
|
if (!configFile) {
|
||||||
|
DBG_OUTPUT_PORT.println("Failed!");
|
||||||
|
save_conf.detach();
|
||||||
|
updateConfig = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DBG_OUTPUT_PORT.println(listConfigJSON());
|
||||||
|
configFile.print(listConfigJSON());
|
||||||
|
configFile.close();
|
||||||
|
save_conf.detach();
|
||||||
|
updateConfig = false;
|
||||||
|
return true;
|
||||||
|
//end save
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.println("SaveConfig is false!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read search_str to FS
|
||||||
|
bool readConfigFS() {
|
||||||
|
//read configuration from FS JSON
|
||||||
|
if (SPIFFS.exists("/config.json")) {
|
||||||
|
//file exists, reading and loading
|
||||||
|
DBG_OUTPUT_PORT.print("Reading config file... ");
|
||||||
|
File configFile = SPIFFS.open("/config.json", "r");
|
||||||
|
if (configFile) {
|
||||||
|
DBG_OUTPUT_PORT.println("Opened!");
|
||||||
|
size_t size = configFile.size();
|
||||||
|
std::unique_ptr<char[]> buf(new char[size]);
|
||||||
|
configFile.readBytes(buf.get(), size);
|
||||||
|
configFile.close();
|
||||||
|
#if defined(ENABLE_MQTT)
|
||||||
|
const size_t bufferSize = JSON_OBJECT_SIZE(11) + 150;
|
||||||
|
#else
|
||||||
|
const size_t bufferSize = JSON_OBJECT_SIZE(7) + 100;
|
||||||
|
#endif
|
||||||
|
DynamicJsonDocument jsonBuffer(bufferSize);
|
||||||
|
DeserializationError error = deserializeJson(jsonBuffer, buf.get());
|
||||||
|
DBG_OUTPUT_PORT.print("Config: ");
|
||||||
|
if (!error) {
|
||||||
|
DBG_OUTPUT_PORT.println("Parsed!");
|
||||||
|
JsonObject root = jsonBuffer.as<JsonObject>();
|
||||||
|
serializeJson(root, DBG_OUTPUT_PORT);
|
||||||
|
DBG_OUTPUT_PORT.println("");
|
||||||
|
strcpy(HOSTNAME, root["hostname"]);
|
||||||
|
#if defined(ENABLE_MQTT)
|
||||||
|
strcpy(mqtt_host, root["mqtt_host"]);
|
||||||
|
mqtt_port = root["mqtt_port"].as<uint16_t>();
|
||||||
|
strcpy(mqtt_user, root["mqtt_user"]);
|
||||||
|
strcpy(mqtt_pass, root["mqtt_pass"]);
|
||||||
|
#endif
|
||||||
|
Config.segments = constrain(root["ws_seg"].as<uint8_t>(), 1, MAX_NUM_SEGMENTS - 1);
|
||||||
|
Config.stripSize = constrain(root["ws_cnt"].as<uint16_t>(), 1, MAXLEDS);
|
||||||
|
char _rgbOrder[5];
|
||||||
|
strcpy(_rgbOrder, root["ws_rgbo"]);
|
||||||
|
checkRGBOrder(_rgbOrder);
|
||||||
|
uint8_t temp_pin;
|
||||||
|
checkPin((uint8_t) root["ws_pin"]);
|
||||||
|
Config.transEffect = root["ws_trans"].as<bool>();
|
||||||
|
jsonBuffer.clear();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.print("Failed to load json config: ");
|
||||||
|
DBG_OUTPUT_PORT.println(error.c_str());
|
||||||
|
jsonBuffer.clear();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.println("Failed to open /config.json");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.println("Coudnt find config.json");
|
||||||
|
writeConfigFS(true);
|
||||||
|
}
|
||||||
|
//end read
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool writeStateFS(bool save){
|
||||||
|
if (save) {
|
||||||
|
//save the strip state to FS JSON
|
||||||
|
DBG_OUTPUT_PORT.print("Saving state: ");
|
||||||
|
//SPIFFS.remove("/stripstate.json") ? DBG_OUTPUT_PORT.println("removed file") : DBG_OUTPUT_PORT.println("failed removing file");
|
||||||
|
File configFile = SPIFFS.open("/stripstate.json", "w");
|
||||||
|
if (!configFile) {
|
||||||
|
DBG_OUTPUT_PORT.println("Failed!");
|
||||||
|
save_state.detach();
|
||||||
|
updateState = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DBG_OUTPUT_PORT.println(listStateJSON());
|
||||||
|
configFile.print(listStateJSON());
|
||||||
|
configFile.close();
|
||||||
|
char filename[28];
|
||||||
|
save_state.detach();
|
||||||
|
updateState = false;
|
||||||
|
return true;
|
||||||
|
//end save
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.println("SaveState is false!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readStateFS() {
|
||||||
|
//read strip state from FS JSON
|
||||||
|
if (SPIFFS.exists("/stripstate.json")) {
|
||||||
|
//file exists, reading and loading
|
||||||
|
DBG_OUTPUT_PORT.print("Reading state file... ");
|
||||||
|
File configFile = SPIFFS.open("/stripstate.json", "r");
|
||||||
|
if (configFile) {
|
||||||
|
DBG_OUTPUT_PORT.println("Opened!");
|
||||||
|
size_t size = configFile.size();
|
||||||
|
// Allocate a buffer to store contents of the file.
|
||||||
|
std::unique_ptr<char[]> buf(new char[size]);
|
||||||
|
configFile.readBytes(buf.get(), size);
|
||||||
|
configFile.close();
|
||||||
|
const size_t bufferSize = JSON_OBJECT_SIZE(3) + 50;
|
||||||
|
DynamicJsonDocument jsonBuffer(bufferSize);
|
||||||
|
DeserializationError error = deserializeJson(jsonBuffer, buf.get());
|
||||||
|
DBG_OUTPUT_PORT.print("Config: ");
|
||||||
|
if (!error) {
|
||||||
|
DBG_OUTPUT_PORT.print("Parsed");
|
||||||
|
JsonObject root = jsonBuffer.as<JsonObject>();
|
||||||
|
serializeJson(root, DBG_OUTPUT_PORT);
|
||||||
|
DBG_OUTPUT_PORT.println("");
|
||||||
|
State.segment = root["segment"];
|
||||||
|
State.mode = static_cast<MODE>(root["mode"].as<uint8_t>());
|
||||||
|
State.brightness = root["brightness"];
|
||||||
|
jsonBuffer.clear();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.print("Failed to load json config: ");
|
||||||
|
DBG_OUTPUT_PORT.println(error.c_str());
|
||||||
|
jsonBuffer.clear();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.println("Failed to open \"/stripstate.json\"");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.println("Couldn't find \"/stripstate.json\"");
|
||||||
|
writeStateFS(true);
|
||||||
|
}
|
||||||
|
//end read
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool writeSegmentStateFS(bool save, uint8_t seg){
|
||||||
|
if (save) {
|
||||||
|
//save the segment state to FS JSON
|
||||||
|
DBG_OUTPUT_PORT.print("Saving segment state: ");
|
||||||
|
char filename[28];
|
||||||
|
snprintf(filename, 28, "/stripstate_segment_%02i.json", seg);
|
||||||
|
filename[27] = 0x00;
|
||||||
|
File configFile = SPIFFS.open(filename, "w");
|
||||||
|
if (!configFile) {
|
||||||
|
DBG_OUTPUT_PORT.println("Failed!");
|
||||||
|
save_seg_state.detach();
|
||||||
|
updateSegState = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DBG_OUTPUT_PORT.println(listSegmentStateJSON(seg));
|
||||||
|
configFile.print(listSegmentStateJSON(seg));
|
||||||
|
configFile.close();
|
||||||
|
save_seg_state.detach();
|
||||||
|
updateSegState = false;
|
||||||
|
return true;
|
||||||
|
//end save
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.println("SaveSegmentState is false!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readSegmentStateFS(uint8_t _seg) {
|
||||||
|
//read strip state from FS JSON
|
||||||
|
char filename[28];
|
||||||
|
snprintf(filename, 28, "/stripstate_segment_%02i.json", _seg);
|
||||||
|
filename[27] = 0x00;
|
||||||
|
if (SPIFFS.exists(filename)) {
|
||||||
|
//file exists, reading and loading
|
||||||
|
DBG_OUTPUT_PORT.printf("Reading segmentstate file: %s\r\n", filename);
|
||||||
|
File configFile = SPIFFS.open(filename, "r");
|
||||||
|
if (configFile) {
|
||||||
|
DBG_OUTPUT_PORT.println("Opened!");
|
||||||
|
size_t size = configFile.size();
|
||||||
|
// Allocate a buffer to store contents of the file.
|
||||||
|
std::unique_ptr<char[]> buf(new char[size]);
|
||||||
|
configFile.readBytes(buf.get(), size);
|
||||||
|
configFile.close();
|
||||||
|
const size_t bufferSize = JSON_ARRAY_SIZE(12) + JSON_OBJECT_SIZE(7) + 100;
|
||||||
|
DynamicJsonDocument jsonBuffer(bufferSize);
|
||||||
|
DeserializationError error = deserializeJson(jsonBuffer, buf.get());
|
||||||
|
DBG_OUTPUT_PORT.print("Config: ");
|
||||||
|
if (!error) {
|
||||||
|
DBG_OUTPUT_PORT.print("Parsed");
|
||||||
|
JsonObject root = jsonBuffer.as<JsonObject>();
|
||||||
|
serializeJson(root, DBG_OUTPUT_PORT);
|
||||||
|
DBG_OUTPUT_PORT.println("");
|
||||||
|
segState.start = constrain(root["start"].as<uint16_t>(), 0, Config.stripSize - 1) ;
|
||||||
|
segState.stop = constrain(root["stop"].as<uint16_t>(), 0, Config.stripSize - 1);
|
||||||
|
segState.mode[_seg] = root["fx_mode"].as<uint8_t>();
|
||||||
|
segState.speed[_seg] = root["speed"].as<uint8_t>();
|
||||||
|
main_color.white = root["color"][0].as<uint8_t>();
|
||||||
|
main_color.red = root["color"][1].as<uint8_t>();
|
||||||
|
main_color.green = root["color"][2].as<uint8_t>();
|
||||||
|
main_color.blue = root["color"][3].as<uint8_t>();
|
||||||
|
back_color.white = root["color"][4].as<uint8_t>();
|
||||||
|
back_color.red = root["color"][5].as<uint8_t>();
|
||||||
|
back_color.green = root["color"][6].as<uint8_t>();
|
||||||
|
back_color.blue = root["color"][7].as<uint8_t>();
|
||||||
|
xtra_color.white = root["color"][8].as<uint8_t>();
|
||||||
|
xtra_color.red = root["color"][9].as<uint8_t>();
|
||||||
|
xtra_color.green = root["color"][10].as<uint8_t>();
|
||||||
|
xtra_color.blue = root["color"][11].as<uint8_t>();
|
||||||
|
segState.options = constrain(root["ws_fxopt"].as<uint8_t>(), 0, 255) & 0xFE;
|
||||||
|
convertColors();
|
||||||
|
jsonBuffer.clear();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.print("Failed to load json config: ");
|
||||||
|
DBG_OUTPUT_PORT.println(error.c_str());
|
||||||
|
jsonBuffer.clear();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.printf("Failed to open \"/%s\"\r\n", filename);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.printf("Couldn't find \"/%s\"", filename);
|
||||||
|
writeSegmentStateFS(true, _seg);
|
||||||
|
}
|
||||||
|
//end read
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,323 @@
|
|||||||
|
// Prototypes
|
||||||
|
bool readSegmentStateFS(uint8_t _seg);
|
||||||
|
// End Prototypes
|
||||||
|
|
||||||
|
void getACK(char *buffer) {
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "text/plain", buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call convertColors whenever main_color, back_color or xtra_color changes.
|
||||||
|
void convertColors() {
|
||||||
|
hexcolors_trans[0] = (uint32_t)(main_color.white << 24) | (main_color.red << 16) | (main_color.green << 8) | main_color.blue;
|
||||||
|
hexcolors_trans[1] = (uint32_t)(back_color.white << 24) | (back_color.red << 16) | (back_color.green << 8) | back_color.blue;
|
||||||
|
hexcolors_trans[2] = (uint32_t)(xtra_color.white << 24) | (xtra_color.red << 16) | (xtra_color.green << 8) | xtra_color.blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*uint32_t* convertColors2(uint8_t _w, uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _w2, uint8_t _r2, uint8_t _g2, uint8_t _b2, uint8_t _w3, uint8_t _r3, uint8_t _g3, uint8_t _b3) {
|
||||||
|
uint32_t _hexcolors[3] = {};
|
||||||
|
_hexcolors[0] = (uint32_t)(_w << 24) | (_r << 16) | (_g << 8) | _b;
|
||||||
|
_hexcolors[1] = (uint32_t)(_w2 << 24) | (_r2 << 16) | (_g2 << 8) | _b2;
|
||||||
|
_hexcolors[2] = (uint32_t)(_w3 << 24) | (_r3 << 16) | (_g3 << 8) | _b3;
|
||||||
|
return _hexcolors;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
uint16_t convertSpeed(uint8_t _mcl_speed) {
|
||||||
|
uint16_t _fx_speed = 0;
|
||||||
|
if (_mcl_speed < 50) {
|
||||||
|
_fx_speed = 65535 - (_mcl_speed * 1000);
|
||||||
|
} else if (_mcl_speed < 100) {
|
||||||
|
_fx_speed = 16675 - ((_mcl_speed-49) * 250);
|
||||||
|
} else if (_mcl_speed < 150) {
|
||||||
|
_fx_speed = 4075 - ((_mcl_speed-99) * 50);
|
||||||
|
} else if (_mcl_speed < 200) {
|
||||||
|
_fx_speed = 1550 - ((_mcl_speed-149) * 25);
|
||||||
|
} else {
|
||||||
|
_fx_speed = 280 - ((_mcl_speed-199) * 5);
|
||||||
|
}
|
||||||
|
_fx_speed = constrain(_fx_speed, SPEED_MIN, SPEED_MAX);
|
||||||
|
return _fx_speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*uint8_t unconvertSpeed(uint16_t _fx_speed) {
|
||||||
|
uint16_t _mcl_speed = 0;
|
||||||
|
if (_fx_speed <= 280) {
|
||||||
|
_mcl_speed = ((280 - _fx_speed)/5) + 199;
|
||||||
|
} else if (_fx_speed < 1550) {
|
||||||
|
_mcl_speed = ((1550 - _fx_speed)/25) + 149;
|
||||||
|
} else if (_fx_speed < 4075) {
|
||||||
|
_mcl_speed = ((4075 - _fx_speed)/50) + 99;
|
||||||
|
} else if (_mcl_speed < 16500) {
|
||||||
|
_mcl_speed = ((16675 - _fx_speed)/250) + 49;
|
||||||
|
} else {
|
||||||
|
_mcl_speed = ((65535 - _fx_speed)/1000);
|
||||||
|
}
|
||||||
|
return _mcl_speed;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
bool checkPin(uint8_t pin) {
|
||||||
|
#if defined(USE_WS2812FX_DMA)
|
||||||
|
#if USE_WS2812FX_DMA == 0
|
||||||
|
pin = 3;
|
||||||
|
#endif
|
||||||
|
#if USE_WS2812FX_DMA == 1
|
||||||
|
pin = 1;
|
||||||
|
#endif
|
||||||
|
#if USE_WS2812FX_DMA == 2
|
||||||
|
pin = 2;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
if (((pin >= 0 && pin <= 5) || (pin >= 12 && pin <= 16)) && (pin != Config.pin)) {
|
||||||
|
Config.pin = pin;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
neoPixelType checkRGBOrder(char rgbOrder[5]) {
|
||||||
|
for( uint8_t i=0 ; i < sizeof(rgbOrder) ; ++i ) rgbOrder[i] = toupper(rgbOrder[i]) ;
|
||||||
|
DBG_OUTPUT_PORT.printf("Checking RGB Order: %s ...", rgbOrder);
|
||||||
|
neoPixelType returnOrder = 0;
|
||||||
|
if (strcmp(rgbOrder, "GRB") == 0) {
|
||||||
|
returnOrder = NEO_GRB;
|
||||||
|
} else if (strcmp(rgbOrder, "GBR") == 0) {
|
||||||
|
returnOrder = NEO_GBR;
|
||||||
|
} else if (strcmp(rgbOrder, "RGB") == 0) {
|
||||||
|
returnOrder = NEO_RGB;
|
||||||
|
} else if (strcmp(rgbOrder, "RBG") == 0) {
|
||||||
|
returnOrder = NEO_RBG;
|
||||||
|
} else if (strcmp(rgbOrder, "BRG") == 0) {
|
||||||
|
returnOrder = NEO_BRG;
|
||||||
|
} else if (strcmp(rgbOrder, "BGR") == 0) {
|
||||||
|
returnOrder = NEO_BGR;
|
||||||
|
} else if (strcmp(rgbOrder, "WGRB") == 0) {
|
||||||
|
returnOrder = NEO_WGRB;
|
||||||
|
} else if (strcmp(rgbOrder, "WGBR") == 0) {
|
||||||
|
returnOrder = NEO_WGBR;
|
||||||
|
} else if (strcmp(rgbOrder, "WRGB") == 0) {
|
||||||
|
returnOrder = NEO_WRGB;
|
||||||
|
} else if (strcmp(rgbOrder, "WRBG") == 0) {
|
||||||
|
returnOrder = NEO_WRBG;
|
||||||
|
} else if (strcmp(rgbOrder, "WBRG") == 0) {
|
||||||
|
returnOrder = NEO_WBRG;
|
||||||
|
} else if (strcmp(rgbOrder, "WBGR") == 0) {
|
||||||
|
returnOrder = NEO_WBGR;
|
||||||
|
} else if (strcmp(rgbOrder, "GWRB") == 0) {
|
||||||
|
returnOrder = NEO_GWRB;
|
||||||
|
} else if (strcmp(rgbOrder, "GWBR") == 0) {
|
||||||
|
returnOrder = NEO_GWBR;
|
||||||
|
} else if (strcmp(rgbOrder, "RWGB") == 0) {
|
||||||
|
returnOrder = NEO_RWGB;
|
||||||
|
} else if (strcmp(rgbOrder, "RWBG") == 0) {
|
||||||
|
returnOrder = NEO_RWBG;
|
||||||
|
} else if (strcmp(rgbOrder, "BWRG") == 0) {
|
||||||
|
returnOrder = NEO_BWRG;
|
||||||
|
} else if (strcmp(rgbOrder, "BWGR") == 0) {
|
||||||
|
returnOrder = NEO_BWGR;
|
||||||
|
} else if (strcmp(rgbOrder, "GRWB") == 0) {
|
||||||
|
returnOrder = NEO_GRWB;
|
||||||
|
} else if (strcmp(rgbOrder, "GBWR") == 0) {
|
||||||
|
returnOrder = NEO_GBWR;
|
||||||
|
} else if (strcmp(rgbOrder, "RGWB") == 0) {
|
||||||
|
returnOrder = NEO_RGWB;
|
||||||
|
} else if (strcmp(rgbOrder, "RBWG") == 0) {
|
||||||
|
returnOrder = NEO_RBWG;
|
||||||
|
} else if (strcmp(rgbOrder, "BRWG") == 0){
|
||||||
|
returnOrder = NEO_BRWG;
|
||||||
|
} else if (strcmp(rgbOrder, "BGWR") == 0) {
|
||||||
|
returnOrder = NEO_GRBW;
|
||||||
|
} else if (strcmp(rgbOrder, "GRBW") == 0) {
|
||||||
|
returnOrder = NEO_GRBW;
|
||||||
|
} else if (strcmp(rgbOrder, "GBWR") == 0) {
|
||||||
|
returnOrder = NEO_GBRW;
|
||||||
|
} else if (strcmp(rgbOrder, "RGBW") == 0) {
|
||||||
|
returnOrder = NEO_RGBW;
|
||||||
|
} else if (strcmp(rgbOrder, "RBGW") == 0) {
|
||||||
|
returnOrder = NEO_RBGW;
|
||||||
|
} else if (strcmp(rgbOrder, "BRGW") == 0) {
|
||||||
|
returnOrder = NEO_BRGW;
|
||||||
|
} else if (strcmp(rgbOrder, "BGRW") == 0) {
|
||||||
|
returnOrder = NEO_BGRW;
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.print("invalid input!");
|
||||||
|
uint16_t check = checkRGBOrder(Config.RGBOrder);
|
||||||
|
if (check != 0) {
|
||||||
|
returnOrder = static_cast<neoPixelType>(check);
|
||||||
|
strcpy(rgbOrder, Config.RGBOrder);
|
||||||
|
} else {
|
||||||
|
returnOrder = static_cast<neoPixelType>(checkRGBOrder(RGBORDER));
|
||||||
|
strcpy(rgbOrder, RGBORDER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBG_OUTPUT_PORT.println("success!");
|
||||||
|
strcpy(Config.RGBOrder, rgbOrder);
|
||||||
|
return returnOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
// function to Initialize the strip
|
||||||
|
void initStrip(uint16_t _stripSize = Config.stripSize, uint8_t _num_segments = Config.segments, char _RGBOrder[5] = Config.RGBOrder, uint8_t _pin = Config.pin){
|
||||||
|
DBG_OUTPUT_PORT.println("Initializing strip!");
|
||||||
|
/*#if defined(USE_WS2812FX_DMA)
|
||||||
|
if (dma != NULL) {
|
||||||
|
delete(dma);
|
||||||
|
}
|
||||||
|
#endif*/
|
||||||
|
if (strip != NULL) {
|
||||||
|
strip->strip_off();
|
||||||
|
delay(10);
|
||||||
|
if(strip->isRunning()) strip->stop();
|
||||||
|
strip->resetSegments();
|
||||||
|
strip->resetSegmentRuntimes();
|
||||||
|
delete(strip);
|
||||||
|
Config.stripSize = _stripSize;
|
||||||
|
strcpy(Config.RGBOrder, _RGBOrder);
|
||||||
|
Config.pin = _pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ledstates != NULL) {
|
||||||
|
delete(ledstates);
|
||||||
|
}
|
||||||
|
ledstates = new uint8_t [_stripSize];
|
||||||
|
|
||||||
|
#if !defined(LED_TYPE_WS2811)
|
||||||
|
strip = new WS2812FX(_stripSize, _pin, checkRGBOrder(_RGBOrder) + NEO_KHZ800);
|
||||||
|
#else
|
||||||
|
strip = new WS2812FX(_stripSize, _pin, checkRGBOrder(_RGBOrder) + NEO_KHZ400);
|
||||||
|
#endif
|
||||||
|
// Parameter 1 = number of pixels in strip
|
||||||
|
// Parameter 2 = Arduino pin number (most are valid)
|
||||||
|
// Parameter 3 = pixel type flags, add together as needed:
|
||||||
|
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
|
||||||
|
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
|
||||||
|
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
|
||||||
|
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
|
||||||
|
|
||||||
|
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
|
||||||
|
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
|
||||||
|
// and minimize distance between Arduino and first pixel. Avoid connecting
|
||||||
|
// on a live circuit...if you must, connect GND first.
|
||||||
|
strip->init();
|
||||||
|
#if defined(USE_WS2812FX_DMA)
|
||||||
|
initDMA(_stripSize);
|
||||||
|
strip->setCustomShow(DMA_Show);
|
||||||
|
#endif
|
||||||
|
//parameters: index, start, stop, mode, color, speed, options
|
||||||
|
for (uint8_t _seg=0; _seg < Config.segments; _seg++) {
|
||||||
|
if (_seg != State.segment) { // Read actual segment last
|
||||||
|
(readSegmentStateFS(_seg)) ? DBG_OUTPUT_PORT.println("Segment state config FS read Success!") : DBG_OUTPUT_PORT.println("Segment state config FS read failure!");
|
||||||
|
memcpy(segState.colors[_seg], hexcolors_trans, sizeof(hexcolors_trans));
|
||||||
|
strip->setSegment(_seg, segState.start, segState.stop, segState.mode[_seg], segState.colors[_seg], convertSpeed(segState.speed[_seg]), segState.options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//read actual segment last to set all vars correctly
|
||||||
|
(readSegmentStateFS(State.segment)) ? DBG_OUTPUT_PORT.println("Segment state config FS read Success!") : DBG_OUTPUT_PORT.println("Segment state config FS read failure!");
|
||||||
|
memcpy(segState.colors[State.segment], hexcolors_trans, sizeof(hexcolors_trans));
|
||||||
|
strip->setSegment(State.segment, segState.start, segState.stop , segState.mode[State.segment], hexcolors_trans, convertSpeed(segState.speed[State.segment]), segState.options);
|
||||||
|
fx_speed = segState.speed[State.segment];
|
||||||
|
fx_mode = segState.mode[State.segment];
|
||||||
|
brightness_trans = State.brightness;
|
||||||
|
prevsegment = State.segment;
|
||||||
|
strip->setCustomMode(0, F("Autoplay"), handleAuto);
|
||||||
|
strip->setCustomMode(1, F("Custom WS"), handleCustomWS);
|
||||||
|
strip->setCustomMode(9, F("Segment OFF"), handleSegmentOFF);
|
||||||
|
#if defined(CUSTOM_WS2812FX_ANIMATIONS)
|
||||||
|
strip->setCustomMode(2, F("TV"), handleTV);
|
||||||
|
strip->setCustomMode(3, F("E1.31"), handleE131);
|
||||||
|
strip->setCustomMode(4, F("Fire 2012"), handleFire2012);
|
||||||
|
strip->setCustomMode(5, F("Gradient"), handleGradient);
|
||||||
|
DBG_OUTPUT_PORT.print("Number of Segments: ");
|
||||||
|
DBG_OUTPUT_PORT.println(strip->getNumSegments());
|
||||||
|
|
||||||
|
if (e131 != NULL) { delete(e131); }
|
||||||
|
e131 = new ESPAsyncE131(END_UNIVERSE - START_UNIVERSE + 1);
|
||||||
|
float universe_leds = 170.0; // a universe has only 512 (0..511) channels: 3*170 or 4*128 <= 512
|
||||||
|
if (strstr(Config.RGBOrder, "W") != NULL) {
|
||||||
|
//universe_leds = 128.0;
|
||||||
|
}
|
||||||
|
float float_enduni = _stripSize/universe_leds;
|
||||||
|
uint8_t END_UNIVERSE = _stripSize/universe_leds;
|
||||||
|
if (float_enduni > END_UNIVERSE) {
|
||||||
|
END_UNIVERSE = END_UNIVERSE +1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (e131.begin(E131_UNICAST)) // Listen via Unicast
|
||||||
|
if (e131->begin(E131_MULTICAST, START_UNIVERSE, END_UNIVERSE)) {// Listen via Multicast
|
||||||
|
DBG_OUTPUT_PORT.println(F("Listening for data..."));
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.println(F("*** e131.begin failed ***"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void getSegmentParams(uint8_t _seg) {
|
||||||
|
segState.start = strip->getSegment(_seg)->start;
|
||||||
|
segState.stop = strip->getSegment(_seg)->stop;
|
||||||
|
//segState.mode[_seg] = strip->getMode(_seg);
|
||||||
|
//segState.speed[_seg] = unconvertSpeed(strip->getSpeed(_seg));
|
||||||
|
//fx_mode = segState.mode[_seg];
|
||||||
|
//fx_speed = segState.speed[_seg];
|
||||||
|
main_color.white = ((segState.colors[_seg][0] >> 24) & 0xFF);
|
||||||
|
main_color.red = ((segState.colors[_seg][0] >> 16) & 0xFF);
|
||||||
|
main_color.green = ((segState.colors[_seg][0] >> 8) & 0xFF);
|
||||||
|
main_color.blue = ((segState.colors[_seg][0]) & 0xFF);
|
||||||
|
back_color.white = ((segState.colors[_seg][1] >> 24) & 0xFF);
|
||||||
|
back_color.red = ((segState.colors[_seg][1] >> 16) & 0xFF);
|
||||||
|
back_color.green = ((segState.colors[_seg][1] >> 8) & 0xFF);
|
||||||
|
back_color.blue = ((segState.colors[_seg][1]) & 0xFF);
|
||||||
|
xtra_color.white = ((segState.colors[_seg][2] >> 24) & 0xFF);
|
||||||
|
xtra_color.red = ((segState.colors[_seg][2] >> 16) & 0xFF);
|
||||||
|
xtra_color.green = ((segState.colors[_seg][2] >> 8) & 0xFF);
|
||||||
|
xtra_color.blue = ((segState.colors[_seg][2] >> 0) & 0xFF);
|
||||||
|
segState.options = strip->getOptions(_seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSegmentSize() {
|
||||||
|
strip->strip_off();
|
||||||
|
delay(10);
|
||||||
|
if(strip->isRunning()) strip->stop();
|
||||||
|
strip->resetSegmentRuntimes();
|
||||||
|
strip->setSegment(State.segment, segState.start, segState.stop , segState.mode[State.segment], hexcolors_trans, convertSpeed(segState.speed[State.segment]), segState.options);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t calculateColorTransitionSteps(uint8_t _seg) {
|
||||||
|
//compare all colors and calculate steps
|
||||||
|
int _trans_cnt_max = 0;
|
||||||
|
int _calculate_max[4] = {};
|
||||||
|
for (uint8_t i=0; i<3; i++){
|
||||||
|
for (uint8_t j=0; j<4; j++) {
|
||||||
|
_calculate_max[j] = ((strip->getColors(_seg)[i] >> ((3-j)*8)) & 0xFF) - ((hexcolors_trans[i] >> ((3-j)*8)) & 0xFF);
|
||||||
|
_calculate_max[j] = abs(_calculate_max[j]);
|
||||||
|
_trans_cnt_max = max(_trans_cnt_max, _calculate_max[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _trans_cnt_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t convertColorsFade(uint8_t _seg) {
|
||||||
|
if (Config.transEffect) {
|
||||||
|
if (trans_cnt > 1) {
|
||||||
|
//memcpy(segState.colors[_seg], strip->getColors(_seg), sizeof(segState.colors[_seg]));
|
||||||
|
DBG_OUTPUT_PORT.println("Color transistion aborted. Restarting...!");
|
||||||
|
trans_cnt = 1;
|
||||||
|
}
|
||||||
|
return calculateColorTransitionSteps(_seg);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t scale_wrgb(uint32_t wrgb, uint8_t level) {
|
||||||
|
uint8_t w = (uint16_t)(((wrgb >> 24) & 0xFF) * level / 255);
|
||||||
|
uint8_t r = (uint16_t)(((wrgb >> 16) & 0xFF) * level / 255);
|
||||||
|
uint8_t g = (uint16_t)(((wrgb >> 8) & 0xFF) * level / 255);
|
||||||
|
uint8_t b = (uint16_t)(((wrgb) & 0xFF) * level / 255);
|
||||||
|
return (w << 24) | (r << 16) | (g << 8) | b;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t trans(uint32_t _newcolor, uint32_t _oldcolor, uint8_t _level, uint8_t _steps) {
|
||||||
|
if (_steps == 0) { _steps = 1; };
|
||||||
|
_level = (uint16_t)(_level * 255 / _steps);
|
||||||
|
_newcolor = scale_wrgb(_newcolor, _level);
|
||||||
|
_oldcolor = scale_wrgb(_oldcolor, 255-_level);
|
||||||
|
return _newcolor + _oldcolor;
|
||||||
|
}
|
||||||
@@ -0,0 +1,468 @@
|
|||||||
|
#include <pgmspace.h>
|
||||||
|
#define edit_htm_gz_len 5563
|
||||||
|
static const char edit_htm_gz[] PROGMEM ={
|
||||||
|
0x1f, 0x8b, 0x08, 0x08, 0x79, 0x1c, 0x96, 0x5d, 0x04, 0x00, 0x65, 0x64,
|
||||||
|
0x69, 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x00, 0xed, 0x1d, 0x6b, 0x57, 0xea,
|
||||||
|
0x46, 0xf0, 0x7b, 0xcf, 0xe9, 0x7f, 0x48, 0xd3, 0x87, 0x50, 0x9e, 0xa2,
|
||||||
|
0xd7, 0x2a, 0x6a, 0x5b, 0x40, 0x40, 0x45, 0x8a, 0x08, 0x2a, 0xda, 0xd7,
|
||||||
|
0x09, 0xc9, 0x02, 0xd1, 0x90, 0xc4, 0x24, 0x08, 0x7a, 0x6b, 0x7f, 0x7b,
|
||||||
|
0x67, 0x1f, 0x79, 0x27, 0x10, 0xd4, 0x3e, 0x4f, 0xb9, 0xed, 0x25, 0xec,
|
||||||
|
0xce, 0xcc, 0xce, 0xcc, 0xce, 0xce, 0xce, 0xce, 0xee, 0xe6, 0x1e, 0x7c,
|
||||||
|
0x76, 0xd4, 0xa9, 0xf5, 0x6f, 0xce, 0xeb, 0xdc, 0xc4, 0x9a, 0x2a, 0xdf,
|
||||||
|
0x7e, 0xfa, 0xc9, 0x01, 0xfe, 0xe6, 0x14, 0x41, 0x1d, 0x1f, 0xf2, 0x48,
|
||||||
|
0xe5, 0xa1, 0x84, 0xe3, 0x0e, 0x26, 0x48, 0x90, 0xc8, 0x13, 0x3c, 0x5b,
|
||||||
|
0xb2, 0xa5, 0xa0, 0x6f, 0x7b, 0xe7, 0x27, 0x8d, 0x46, 0x8f, 0xab, 0x4b,
|
||||||
|
0xb2, 0xa5, 0x19, 0x07, 0x05, 0x52, 0x68, 0x43, 0x98, 0xd6, 0x93, 0x82,
|
||||||
|
0x38, 0xeb, 0x49, 0x47, 0x87, 0xbc, 0x85, 0x16, 0x56, 0x41, 0x34, 0x4d,
|
||||||
|
0x9e, 0x9b, 0x22, 0x49, 0x16, 0x0e, 0x79, 0x53, 0x34, 0x10, 0xa3, 0x4b,
|
||||||
|
0x3e, 0x79, 0x51, 0x53, 0x31, 0x50, 0x1b, 0xa9, 0x33, 0xee, 0x23, 0x94,
|
||||||
|
0xb2, 0xcf, 0x73, 0x4e, 0x56, 0x25, 0xb4, 0x28, 0x73, 0x5b, 0xc5, 0xe2,
|
||||||
|
0xbe, 0x5b, 0xac, 0x6b, 0xa6, 0x6c, 0xc9, 0x9a, 0x5a, 0xe6, 0x84, 0xa1,
|
||||||
|
0xa9, 0x29, 0x33, 0x0b, 0x79, 0x2a, 0x15, 0x34, 0xb2, 0xca, 0xdc, 0x07,
|
||||||
|
0x7d, 0xe1, 0x29, 0x1b, 0x6a, 0x86, 0x84, 0x8c, 0x32, 0xb7, 0xa9, 0x2f,
|
||||||
|
0x38, 0x40, 0x90, 0x25, 0xee, 0xf3, 0xed, 0xed, 0x6d, 0x2f, 0x80, 0x20,
|
||||||
|
0xde, 0x8f, 0x0d, 0x6d, 0xa6, 0x4a, 0x39, 0x51, 0x53, 0x34, 0x00, 0xfd,
|
||||||
|
0xbc, 0xf1, 0x01, 0xff, 0xf1, 0xc0, 0x48, 0xb2, 0xa9, 0x2b, 0xc2, 0x53,
|
||||||
|
0x99, 0x53, 0x35, 0x15, 0xf9, 0x88, 0x2f, 0x72, 0xe6, 0x44, 0x90, 0xb4,
|
||||||
|
0x79, 0x99, 0x2b, 0xc2, 0x9f, 0xcd, 0x22, 0xb4, 0x62, 0x8c, 0x87, 0x42,
|
||||||
|
0x8a, 0x2b, 0x66, 0xd9, 0x7f, 0xf9, 0x6d, 0x2e, 0xed, 0x41, 0x19, 0x81,
|
||||||
|
0xb8, 0x39, 0x53, 0x7e, 0x46, 0xc0, 0x52, 0xc9, 0xe6, 0xd4, 0xad, 0x19,
|
||||||
|
0x09, 0x53, 0x59, 0x81, 0x86, 0x4c, 0x41, 0x35, 0x73, 0x26, 0x32, 0xe4,
|
||||||
|
0x51, 0x10, 0x62, 0x8e, 0xe4, 0xf1, 0xc4, 0x2a, 0x0f, 0x35, 0x45, 0x72,
|
||||||
|
0xaa, 0x5e, 0x22, 0xb5, 0x39, 0x53, 0xbc, 0x0a, 0x55, 0x64, 0x13, 0x1a,
|
||||||
|
0xc6, 0x5d, 0x13, 0x12, 0xc3, 0xd2, 0x74, 0xe0, 0x3f, 0xa0, 0x48, 0x7f,
|
||||||
|
0xc9, 0x54, 0x30, 0xc6, 0xb2, 0xea, 0x2f, 0xd3, 0x05, 0x49, 0x92, 0xd5,
|
||||||
|
0x31, 0x14, 0x2e, 0x67, 0x04, 0x9a, 0xc6, 0x8c, 0x84, 0xbb, 0xd0, 0x40,
|
||||||
|
0x8a, 0x60, 0xc9, 0x8f, 0xc8, 0xdb, 0x8e, 0xac, 0xe6, 0xe6, 0xb2, 0x64,
|
||||||
|
0x4d, 0xca, 0xdc, 0x4e, 0xd1, 0xa7, 0x1e, 0x71, 0x66, 0x98, 0xd0, 0x3b,
|
||||||
|
0x80, 0x2e, 0x03, 0x65, 0x63, 0x45, 0x93, 0xa6, 0x2e, 0xa8, 0xde, 0x46,
|
||||||
|
0x69, 0xd7, 0xb2, 0xbe, 0x0f, 0xf7, 0xab, 0xac, 0x2a, 0xb2, 0x8a, 0x72,
|
||||||
|
0x43, 0x45, 0x13, 0xef, 0xa3, 0x24, 0xdc, 0xd1, 0x17, 0x2b, 0x65, 0x2c,
|
||||||
|
0x4f, 0xb4, 0x47, 0x64, 0x70, 0x1f, 0x3d, 0x16, 0xc5, 0x1a, 0x5c, 0x81,
|
||||||
|
0xc2, 0x98, 0x75, 0x78, 0xac, 0xd7, 0xeb, 0x0e, 0x8a, 0x8b, 0x68, 0x9a,
|
||||||
|
0x39, 0x0b, 0x86, 0xce, 0xa3, 0x8c, 0xe6, 0xd0, 0xb3, 0x59, 0x7f, 0x09,
|
||||||
|
0x51, 0x71, 0x88, 0xef, 0xd5, 0x5d, 0x18, 0x36, 0x0a, 0x57, 0xc8, 0xe8,
|
||||||
|
0xa6, 0x65, 0x55, 0x9f, 0x59, 0xdc, 0xc7, 0x84, 0x23, 0x52, 0xd3, 0x05,
|
||||||
|
0x51, 0xb6, 0x9e, 0xa0, 0xd1, 0xd5, 0x94, 0x3f, 0xfa, 0x0d, 0x1d, 0x33,
|
||||||
|
0x64, 0x4c, 0x05, 0x85, 0xdb, 0xc4, 0x43, 0xf7, 0x0a, 0x19, 0x92, 0xa0,
|
||||||
|
0x0a, 0x59, 0xae, 0x62, 0xc8, 0x02, 0x48, 0xdf, 0x8b, 0x1a, 0x1f, 0xb9,
|
||||||
|
0xa9, 0xf6, 0x9c, 0x9b, 0x41, 0x29, 0xd4, 0x28, 0x48, 0xb4, 0x42, 0x86,
|
||||||
|
0x0e, 0x83, 0x67, 0x78, 0x2f, 0x5b, 0x4b, 0x61, 0x3c, 0x75, 0x49, 0x75,
|
||||||
|
0x12, 0x67, 0x6c, 0xc5, 0xe2, 0x28, 0x99, 0x01, 0xc7, 0x93, 0xb5, 0x8d,
|
||||||
|
0xca, 0x25, 0x83, 0xcd, 0x27, 0x27, 0x21, 0x51, 0x33, 0x04, 0xaa, 0x76,
|
||||||
|
0xb0, 0x33, 0x64, 0x28, 0x72, 0x12, 0x46, 0x69, 0xe7, 0x65, 0xc0, 0xbd,
|
||||||
|
0x0f, 0x91, 0x02, 0xdf, 0xc4, 0x43, 0x84, 0x0d, 0x84, 0xfc, 0x29, 0x81,
|
||||||
|
0x77, 0x4a, 0x4a, 0xf1, 0x77, 0x42, 0x29, 0x34, 0xae, 0x92, 0xea, 0x8f,
|
||||||
|
0xb0, 0x93, 0x8d, 0x2a, 0x2c, 0x97, 0x87, 0x68, 0xa4, 0x19, 0x88, 0xfb,
|
||||||
|
0xf8, 0x06, 0x3d, 0x12, 0x1e, 0xcb, 0xc0, 0x93, 0x30, 0x54, 0x90, 0x64,
|
||||||
|
0x8b, 0x1f, 0x45, 0x52, 0x42, 0x23, 0x61, 0xa6, 0x58, 0x51, 0x06, 0x9c,
|
||||||
|
0xdf, 0x49, 0xda, 0x90, 0x38, 0x41, 0xe2, 0x3d, 0x92, 0xca, 0xaa, 0x66,
|
||||||
|
0xa5, 0x9c, 0x56, 0xd3, 0xf1, 0x3a, 0x22, 0x4e, 0x67, 0x35, 0xf1, 0xf5,
|
||||||
|
0x94, 0xe4, 0xf5, 0x41, 0x33, 0x43, 0x49, 0xf1, 0x92, 0x60, 0x09, 0x65,
|
||||||
|
0x79, 0x2a, 0x8c, 0x51, 0x41, 0x57, 0xc7, 0xfb, 0x43, 0xc1, 0x44, 0x3b,
|
||||||
|
0xdb, 0x59, 0xf9, 0xaa, 0xda, 0xb9, 0x98, 0x17, 0x5b, 0xcd, 0xb1, 0x56,
|
||||||
|
0x81, 0xcf, 0x0f, 0xbd, 0xcb, 0x49, 0xfd, 0x72, 0x0c, 0x4f, 0x55, 0xfc,
|
||||||
|
0xb3, 0x36, 0xae, 0x55, 0x6e, 0xf0, 0x43, 0xa3, 0x83, 0xe6, 0x97, 0xf8,
|
||||||
|
0xa1, 0x39, 0xb8, 0x68, 0x5c, 0x1f, 0x5f, 0xf4, 0x87, 0xa5, 0xdb, 0xa2,
|
||||||
|
0x54, 0x6a, 0x3c, 0xdd, 0x76, 0xab, 0xd5, 0xdb, 0xe6, 0x9e, 0x7c, 0xdb,
|
||||||
|
0xab, 0x9e, 0x0e, 0xaf, 0x1b, 0xea, 0xed, 0xd5, 0xa9, 0x72, 0x73, 0x7d,
|
||||||
|
0xf1, 0x41, 0x14, 0x15, 0xe5, 0x1c, 0x23, 0xe8, 0x8b, 0xd3, 0x8b, 0x7a,
|
||||||
|
0xe3, 0x12, 0xfd, 0x60, 0x98, 0x4a, 0x7b, 0x73, 0x56, 0x2c, 0x56, 0xba,
|
||||||
|
0xe3, 0x26, 0xb8, 0xf7, 0x27, 0x41, 0x69, 0x34, 0x3a, 0xad, 0x4c, 0x4d,
|
||||||
|
0x39, 0x39, 0x69, 0x75, 0x5b, 0x4f, 0x0f, 0x97, 0x57, 0xdd, 0xc7, 0x7e,
|
||||||
|
0xbd, 0xbe, 0x75, 0x34, 0xad, 0x4c, 0xce, 0xe6, 0x95, 0xc9, 0xe5, 0x6e,
|
||||||
|
0xf7, 0x56, 0x3b, 0xde, 0xae, 0x94, 0xba, 0xa5, 0x71, 0xbb, 0xd7, 0x10,
|
||||||
|
0x44, 0xb4, 0xdd, 0xae, 0x59, 0xa7, 0xbb, 0xbd, 0xf3, 0x6a, 0x63, 0x5e,
|
||||||
|
0xb9, 0xbf, 0x98, 0xc9, 0xc7, 0x2d, 0xbd, 0xb2, 0x63, 0x5e, 0xfc, 0x50,
|
||||||
|
0x38, 0x9b, 0x7d, 0xf3, 0xdc, 0xfc, 0x20, 0x6f, 0x6e, 0xdf, 0x8b, 0x96,
|
||||||
|
0x70, 0xf9, 0x70, 0xd1, 0x9c, 0x34, 0x07, 0xea, 0x6c, 0xaf, 0x53, 0x38,
|
||||||
|
0xb7, 0xbe, 0x69, 0x3f, 0x9b, 0x6d, 0xf9, 0x5e, 0x79, 0x6c, 0x64, 0xf6,
|
||||||
|
0xac, 0xd2, 0xfd, 0x75, 0xff, 0xe8, 0xf1, 0xe9, 0xc4, 0xa8, 0x98, 0x95,
|
||||||
|
0xa2, 0xd0, 0xba, 0xb8, 0x90, 0x37, 0xfb, 0xc5, 0x5a, 0x61, 0x72, 0xba,
|
||||||
|
0x7d, 0x76, 0x39, 0xb4, 0x3e, 0x14, 0x76, 0x8d, 0x1f, 0xf4, 0xeb, 0x2b,
|
||||||
|
0x45, 0xdf, 0xbd, 0xe8, 0x19, 0x7b, 0xa7, 0xdb, 0xc5, 0xe1, 0xf6, 0xee,
|
||||||
|
0x68, 0xd1, 0x10, 0xfa, 0xdd, 0xbd, 0xcc, 0xc8, 0xda, 0xad, 0xdf, 0xee,
|
||||||
|
0xb4, 0x4f, 0x6f, 0x86, 0xc5, 0xce, 0x7d, 0x46, 0x52, 0x6f, 0x9a, 0xfa,
|
||||||
|
0xf4, 0x7c, 0x3c, 0x98, 0xb7, 0x4e, 0x2a, 0x8f, 0x67, 0x8b, 0xdd, 0xc7,
|
||||||
|
0x9b, 0x81, 0xf8, 0xa1, 0x29, 0xb5, 0x2b, 0xdd, 0xd3, 0x71, 0xb7, 0x7e,
|
||||||
|
0xaf, 0xdf, 0x5d, 0xf4, 0x27, 0x5b, 0x3b, 0xfd, 0x5e, 0xe9, 0x32, 0x73,
|
||||||
|
0x74, 0x7d, 0x5d, 0x38, 0xda, 0xfc, 0xe6, 0x7a, 0x76, 0x33, 0x9e, 0xee,
|
||||||
|
0xea, 0xf3, 0xd3, 0xa7, 0x9b, 0x4d, 0x55, 0xbf, 0x35, 0x6f, 0x5b, 0x9d,
|
||||||
|
0xc5, 0xc9, 0xb4, 0x73, 0xb5, 0x79, 0x52, 0x98, 0x6c, 0x67, 0x3a, 0x3b,
|
||||||
|
0x8f, 0xf5, 0xf1, 0x87, 0x66, 0xed, 0xb6, 0xaa, 0x8f, 0xa7, 0x95, 0x9d,
|
||||||
|
0xc9, 0x60, 0x77, 0x7e, 0xdc, 0xba, 0x3c, 0x3e, 0xba, 0xa8, 0x0e, 0xba,
|
||||||
|
0x37, 0xb2, 0xd8, 0xdd, 0x36, 0x14, 0x71, 0xab, 0x3f, 0x2a, 0x5e, 0xb5,
|
||||||
|
0xcd, 0xdd, 0xa3, 0xe3, 0x6a, 0x6f, 0x77, 0x67, 0xbb, 0x51, 0xba, 0x69,
|
||||||
|
0x98, 0xfa, 0xdd, 0xf8, 0xf2, 0xe6, 0xae, 0x35, 0x28, 0x54, 0x9e, 0xb7,
|
||||||
|
0xc6, 0xa6, 0xd4, 0x95, 0x4a, 0x08, 0x55, 0x8f, 0xe7, 0x53, 0xa9, 0x79,
|
||||||
|
0x3d, 0x38, 0x16, 0xc7, 0xd5, 0x66, 0xef, 0xfe, 0x76, 0xd0, 0x19, 0x68,
|
||||||
|
0x13, 0xb1, 0x3e, 0x40, 0xc3, 0x0b, 0xad, 0x2b, 0x56, 0xc6, 0x77, 0x0f,
|
||||||
|
0x10, 0x88, 0xfd, 0x70, 0x93, 0xa9, 0x5c, 0x3d, 0xcd, 0xb6, 0x6e, 0xb7,
|
||||||
|
0xcc, 0x4a, 0xeb, 0x61, 0xd4, 0xd2, 0x9a, 0x6d, 0x13, 0xcd, 0xab, 0xa8,
|
||||||
|
0x7e, 0xd2, 0x39, 0x1f, 0x77, 0x17, 0x8b, 0xf3, 0xd3, 0x93, 0x3b, 0xb1,
|
||||||
|
0x79, 0xbc, 0xf3, 0x60, 0x9d, 0x15, 0x8a, 0x15, 0xa9, 0x72, 0xf4, 0xdc,
|
||||||
|
0x6a, 0xaa, 0xb3, 0xd9, 0x51, 0xa6, 0x64, 0x9d, 0xb5, 0xbe, 0xe9, 0xee,
|
||||||
|
0x1e, 0x4d, 0x8e, 0x8f, 0x87, 0x9d, 0xea, 0x75, 0xa6, 0x55, 0x7f, 0x16,
|
||||||
|
0x8f, 0xcf, 0x66, 0x37, 0xe2, 0x6e, 0xa9, 0x7d, 0x5f, 0xbf, 0x44, 0xf7,
|
||||||
|
0x67, 0xf2, 0x7c, 0xf6, 0x78, 0x75, 0x9c, 0x19, 0xcf, 0xba, 0xd5, 0xee,
|
||||||
|
0x73, 0xa7, 0xb9, 0x3d, 0x90, 0x2a, 0xc3, 0xdd, 0x7a, 0x47, 0xbc, 0x10,
|
||||||
|
0x1f, 0xba, 0x8f, 0x47, 0xf7, 0x37, 0x25, 0xb9, 0x76, 0x36, 0x5b, 0xd4,
|
||||||
|
0x6b, 0xa7, 0xdb, 0x5b, 0xa7, 0xda, 0xb0, 0x3d, 0xd0, 0x66, 0xd6, 0x43,
|
||||||
|
0x73, 0x7c, 0x24, 0x94, 0xfa, 0xdf, 0x5c, 0x3e, 0x9c, 0xb5, 0xe6, 0xd6,
|
||||||
|
0x5e, 0xeb, 0xe2, 0x69, 0xb6, 0x68, 0x5d, 0x55, 0x9f, 0x1e, 0xae, 0x06,
|
||||||
|
0x83, 0x87, 0x13, 0xad, 0x56, 0xbb, 0xac, 0x55, 0x1e, 0x26, 0x97, 0x1d,
|
||||||
|
0x59, 0xeb, 0x5f, 0xd7, 0xbe, 0x69, 0x6e, 0xf7, 0xbb, 0xf5, 0xce, 0x51,
|
||||||
|
0xb1, 0x72, 0xfe, 0x54, 0x2a, 0x7c, 0xd3, 0x2c, 0x0d, 0xf4, 0xd9, 0xe6,
|
||||||
|
0xe9, 0x76, 0x46, 0x59, 0xa0, 0xee, 0x76, 0x7f, 0x50, 0x1d, 0x9e, 0xf4,
|
||||||
|
0x8f, 0x74, 0xed, 0x0a, 0x29, 0x60, 0x19, 0xd5, 0xab, 0xc6, 0x70, 0x3e,
|
||||||
|
0xfb, 0xa0, 0xb5, 0xdb, 0xa7, 0x97, 0xd5, 0x89, 0x36, 0x78, 0xfa, 0x60,
|
||||||
|
0x4d, 0xa5, 0x0b, 0xb1, 0x3d, 0x7f, 0x9a, 0x9e, 0x97, 0x3a, 0x67, 0x5d,
|
||||||
|
0xe1, 0xec, 0x6e, 0xb1, 0x57, 0x78, 0x54, 0xab, 0xda, 0xce, 0xd5, 0x56,
|
||||||
|
0x6b, 0x47, 0x7e, 0xae, 0xf4, 0xa7, 0x3d, 0xb5, 0x2d, 0x14, 0x8f, 0x1e,
|
||||||
|
0xbe, 0x19, 0x21, 0xe3, 0x44, 0x9b, 0x9c, 0x4e, 0x8c, 0x4d, 0xbd, 0xb8,
|
||||||
|
0xf9, 0x6c, 0x28, 0xcf, 0xdb, 0x7b, 0xc6, 0x6d, 0x63, 0xbb, 0x03, 0x5d,
|
||||||
|
0x70, 0x7a, 0x3f, 0x28, 0x6d, 0x3d, 0x5e, 0x75, 0x9f, 0x6f, 0xf4, 0xcc,
|
||||||
|
0x7c, 0x78, 0xd3, 0xbc, 0x2a, 0xb4, 0xf4, 0x41, 0xeb, 0xee, 0x11, 0x06,
|
||||||
|
0xf4, 0xae, 0x65, 0x9e, 0xb4, 0x6a, 0x46, 0xfb, 0x87, 0xca, 0x4d, 0x63,
|
||||||
|
0x71, 0x57, 0x6a, 0xb6, 0x7a, 0x1f, 0x6e, 0xaf, 0x17, 0xe3, 0x6d, 0x34,
|
||||||
|
0x6f, 0x99, 0xa7, 0x23, 0xa1, 0xd9, 0x3e, 0xb9, 0xf9, 0xd0, 0x1a, 0x3c,
|
||||||
|
0x9c, 0x3f, 0xef, 0x9e, 0x55, 0xab, 0x77, 0x3b, 0x99, 0xa7, 0xa3, 0xc7,
|
||||||
|
0xab, 0xf3, 0x6f, 0xf6, 0xe0, 0x5b, 0x2f, 0xec, 0x35, 0xf6, 0xb4, 0x93,
|
||||||
|
0xc5, 0x56, 0x47, 0x36, 0x8f, 0xaf, 0xe7, 0xe8, 0x9b, 0x8e, 0xa0, 0x14,
|
||||||
|
0x8f, 0x17, 0x35, 0x18, 0x44, 0x5d, 0x18, 0x91, 0xf5, 0x93, 0x2e, 0x0c,
|
||||||
|
0xc8, 0xfa, 0x09, 0x0c, 0x4d, 0x52, 0x34, 0x81, 0xbf, 0x4e, 0x70, 0x05,
|
||||||
|
0x2d, 0xaa, 0xc3, 0xcf, 0x09, 0x85, 0x9d, 0x1f, 0xed, 0xd6, 0x0b, 0xd5,
|
||||||
|
0xdb, 0x71, 0xe5, 0xbc, 0xf8, 0x30, 0x69, 0xdd, 0x6d, 0x19, 0x83, 0xce,
|
||||||
|
0x37, 0x15, 0xfc, 0xa9, 0x2b, 0x8d, 0xfe, 0x7d, 0x6f, 0xd6, 0x9d, 0xd6,
|
||||||
|
0x6a, 0x7c, 0x1a, 0x5c, 0x73, 0xce, 0x40, 0x3a, 0x12, 0xac, 0x57, 0xba,
|
||||||
|
0x1e, 0x3c, 0x3b, 0x25, 0x76, 0x47, 0xab, 0x02, 0xad, 0x09, 0x0d, 0x6a,
|
||||||
|
0xb9, 0xcd, 0x1d, 0x5f, 0xcc, 0x47, 0x60, 0x63, 0xea, 0x60, 0x5a, 0xb4,
|
||||||
|
0x64, 0x51, 0x50, 0x72, 0x82, 0x22, 0x8f, 0x61, 0xd6, 0x9a, 0xca, 0x92,
|
||||||
|
0xa4, 0x24, 0x9d, 0x6c, 0xa2, 0x5d, 0x65, 0xce, 0x8d, 0x65, 0x36, 0x77,
|
||||||
|
0xf5, 0x45, 0x92, 0xa0, 0x25, 0x56, 0x62, 0x12, 0xe8, 0xe1, 0x28, 0x86,
|
||||||
|
0xe7, 0x3d, 0x4c, 0x93, 0xd0, 0x96, 0x89, 0x12, 0x9a, 0x78, 0xd9, 0xa4,
|
||||||
|
0x8b, 0x67, 0xdf, 0xe4, 0x72, 0x46, 0xf1, 0x4f, 0x48, 0xe5, 0xb6, 0x92,
|
||||||
|
0x4f, 0xe0, 0xf6, 0x9c, 0xc5, 0x65, 0x92, 0xcc, 0x28, 0xfe, 0x66, 0xa8,
|
||||||
|
0x2c, 0xe1, 0x66, 0x0a, 0x5f, 0x73, 0x34, 0xda, 0xe2, 0x04, 0xe9, 0x4e,
|
||||||
|
0x10, 0x41, 0x17, 0x1c, 0x04, 0x55, 0x53, 0xfc, 0x4d, 0xa3, 0x2b, 0xcd,
|
||||||
|
0xe0, 0x86, 0xb3, 0xf1, 0x48, 0x5e, 0x70, 0x5f, 0x17, 0x6c, 0xa4, 0xef,
|
||||||
|
0xc9, 0x2a, 0x91, 0xa3, 0x8b, 0x44, 0x4e, 0x50, 0x25, 0x2e, 0x65, 0xc7,
|
||||||
|
0x6c, 0x78, 0x65, 0x20, 0x01, 0xcf, 0x22, 0xca, 0xe9, 0xf2, 0x02, 0x29,
|
||||||
|
0x39, 0x12, 0xff, 0x94, 0x8b, 0x69, 0x86, 0xcb, 0x78, 0x0d, 0x8b, 0x48,
|
||||||
|
0xca, 0x83, 0x11, 0xa0, 0xa0, 0xc2, 0x5c, 0x48, 0x65, 0x60, 0x25, 0x36,
|
||||||
|
0x97, 0x39, 0xc6, 0x65, 0xce, 0xe6, 0x32, 0xc7, 0xb8, 0x94, 0xd5, 0x91,
|
||||||
|
0xac, 0xca, 0x16, 0xe2, 0x36, 0x4d, 0x5b, 0x5e, 0x57, 0x62, 0xc6, 0xbe,
|
||||||
|
0x4d, 0xfe, 0x1e, 0x3d, 0x8d, 0x0c, 0x61, 0x8a, 0xcc, 0xc4, 0xd4, 0x5d,
|
||||||
|
0x22, 0x3e, 0x7e, 0x47, 0x86, 0x36, 0x85, 0x22, 0x56, 0x1d, 0x13, 0xdf,
|
||||||
|
0x3b, 0xbc, 0xf8, 0xc0, 0x2c, 0x2d, 0x39, 0xa2, 0x4f, 0x9e, 0x90, 0x60,
|
||||||
|
0x9f, 0xcf, 0x74, 0x45, 0x13, 0x24, 0xb2, 0xb8, 0x49, 0x18, 0xf8, 0x87,
|
||||||
|
0x96, 0x94, 0x06, 0x1e, 0xc4, 0xab, 0x56, 0x99, 0x6c, 0xa8, 0x97, 0x76,
|
||||||
|
0xe3, 0xbd, 0x40, 0x69, 0xdb, 0xad, 0x73, 0x05, 0xca, 0x11, 0x5a, 0x64,
|
||||||
|
0xfd, 0x1d, 0x3d, 0x32, 0xa2, 0xd7, 0x7f, 0xb4, 0x14, 0x2f, 0xb8, 0xc2,
|
||||||
|
0xab, 0xbb, 0xcf, 0xb1, 0xfd, 0xac, 0x29, 0x70, 0x80, 0xf1, 0xa1, 0x66,
|
||||||
|
0x59, 0xda, 0x74, 0x99, 0xd0, 0xae, 0x4f, 0x28, 0x15, 0x29, 0xef, 0xa1,
|
||||||
|
0x9e, 0xc2, 0x24, 0xc3, 0xcc, 0x21, 0x92, 0x78, 0xc9, 0x72, 0x9f, 0xeb,
|
||||||
|
0x06, 0x31, 0xf2, 0xb7, 0x31, 0x6a, 0x77, 0x4e, 0x22, 0xde, 0x09, 0xa7,
|
||||||
|
0x61, 0x96, 0x5c, 0x4e, 0x96, 0x75, 0x00, 0xd1, 0x75, 0x58, 0xca, 0x0f,
|
||||||
|
0x61, 0x8a, 0x07, 0x05, 0xbc, 0x2e, 0x75, 0x93, 0x4a, 0xa2, 0x21, 0xeb,
|
||||||
|
0x96, 0x93, 0x36, 0x1a, 0xcd, 0x54, 0x11, 0x8b, 0xc8, 0x89, 0x06, 0x4c,
|
||||||
|
0x61, 0xa8, 0x21, 0x2b, 0xe8, 0x92, 0x19, 0x69, 0x8a, 0x0d, 0xb1, 0x2c,
|
||||||
|
0x87, 0x7b, 0x30, 0xcb, 0x51, 0x55, 0xa5, 0x3d, 0x6c, 0x3d, 0x0a, 0x06,
|
||||||
|
0xb7, 0x98, 0x2a, 0xc7, 0x96, 0xa5, 0xef, 0xfb, 0x4a, 0xd9, 0x72, 0xe6,
|
||||||
|
0x90, 0x93, 0x34, 0x71, 0x86, 0x69, 0xe4, 0x29, 0xf9, 0x3a, 0xa5, 0x98,
|
||||||
|
0xe2, 0x49, 0x3d, 0xef, 0xcd, 0xe7, 0x90, 0x92, 0x3c, 0x4e, 0x76, 0x01,
|
||||||
|
0x1a, 0x3f, 0x02, 0x3e, 0xf8, 0x50, 0xed, 0x14, 0xd6, 0x14, 0xb2, 0xae,
|
||||||
|
0x60, 0x88, 0x91, 0xa0, 0x98, 0x28, 0x04, 0xa0, 0x0a, 0x53, 0x5c, 0x49,
|
||||||
|
0x82, 0x74, 0x0f, 0xba, 0xcb, 0xc6, 0x18, 0x59, 0x8c, 0x87, 0xea, 0xd3,
|
||||||
|
0x89, 0x64, 0x4b, 0x98, 0xce, 0x0b, 0xba, 0x8e, 0x54, 0xa9, 0x36, 0x91,
|
||||||
|
0x15, 0x29, 0x45, 0x48, 0xa5, 0x03, 0x02, 0xe9, 0x82, 0x35, 0x59, 0x4b,
|
||||||
|
0x1e, 0x8c, 0x90, 0x97, 0x25, 0xcc, 0x0d, 0x1d, 0xf5, 0x39, 0x5c, 0xc2,
|
||||||
|
0x07, 0x20, 0x1c, 0x81, 0xf1, 0x6a, 0x34, 0x58, 0xe9, 0x88, 0x13, 0x89,
|
||||||
|
0xc9, 0xd6, 0x58, 0x57, 0x82, 0x32, 0x23, 0x40, 0x85, 0x57, 0x0b, 0x8c,
|
||||||
|
0xc9, 0x05, 0xe5, 0x1d, 0xce, 0xc0, 0x6c, 0xd5, 0x25, 0x12, 0x53, 0x00,
|
||||||
|
0x9f, 0xc8, 0xb4, 0x28, 0x2f, 0xab, 0x2a, 0x32, 0x8e, 0xfb, 0xed, 0x33,
|
||||||
|
0xc0, 0xde, 0xa0, 0xc6, 0xb4, 0xf1, 0x5a, 0xd6, 0x28, 0xc9, 0x20, 0x73,
|
||||||
|
0xd3, 0x7b, 0x49, 0x36, 0xd6, 0xe3, 0x8d, 0xa0, 0xf8, 0x59, 0x6b, 0xdf,
|
||||||
|
0x1f, 0xc9, 0xc6, 0xab, 0x39, 0x23, 0x04, 0xc3, 0x8c, 0x61, 0xc3, 0x5d,
|
||||||
|
0x97, 0x33, 0x8c, 0x13, 0x64, 0x0d, 0x0f, 0xc4, 0x37, 0xf0, 0x86, 0x49,
|
||||||
|
0x86, 0x4d, 0xd8, 0x10, 0xe2, 0x59, 0xa3, 0x16, 0xe8, 0xc1, 0x21, 0xf0,
|
||||||
|
0x3e, 0xb6, 0x78, 0x8e, 0x3b, 0x37, 0x90, 0x69, 0x72, 0x35, 0xcb, 0x50,
|
||||||
|
0x72, 0x3d, 0x0e, 0x22, 0x1b, 0xc8, 0xaf, 0x3e, 0xa2, 0x2c, 0x2d, 0xb8,
|
||||||
|
0x25, 0x05, 0xe0, 0xa3, 0x34, 0x56, 0xd0, 0x9b, 0xc8, 0x23, 0x8b, 0x15,
|
||||||
|
0x1b, 0x48, 0xd2, 0xde, 0x60, 0xa0, 0x86, 0x40, 0x39, 0x0b, 0x38, 0xad,
|
||||||
|
0x09, 0x78, 0x9e, 0x73, 0xcd, 0xb4, 0xce, 0x0d, 0x4d, 0x04, 0xc6, 0x2e,
|
||||||
|
0xd0, 0xc3, 0x0c, 0x99, 0x56, 0x2a, 0xed, 0x9b, 0xfa, 0xe5, 0x11, 0x97,
|
||||||
|
0x62, 0x5e, 0x2a, 0x0f, 0x22, 0x4b, 0x4f, 0x3d, 0x0b, 0xe4, 0xe6, 0x0e,
|
||||||
|
0x0f, 0xb9, 0x6d, 0x1b, 0xd0, 0x05, 0x75, 0x20, 0x4d, 0x00, 0x9a, 0x99,
|
||||||
|
0xdc, 0x67, 0x87, 0xd8, 0x4f, 0xa7, 0x39, 0x41, 0x41, 0x06, 0x28, 0xa9,
|
||||||
|
0x7e, 0x71, 0xd1, 0xb9, 0xf8, 0x91, 0xcf, 0xf8, 0xa1, 0x32, 0xfc, 0xcf,
|
||||||
|
0x65, 0xce, 0x2d, 0x04, 0x1d, 0xe9, 0x9a, 0x6a, 0xa2, 0x3e, 0x68, 0x94,
|
||||||
|
0xb2, 0xed, 0x7e, 0x90, 0x62, 0xda, 0xd1, 0xa0, 0xfb, 0x21, 0x0e, 0x16,
|
||||||
|
0xd0, 0x46, 0x80, 0x39, 0x39, 0x87, 0xd1, 0x98, 0x22, 0x23, 0xfc, 0x11,
|
||||||
|
0x0f, 0xed, 0x20, 0x81, 0x97, 0x15, 0xf1, 0x46, 0xd8, 0xa7, 0x53, 0x82,
|
||||||
|
0x7e, 0x51, 0x19, 0xab, 0xd0, 0xa9, 0x2a, 0xcc, 0x34, 0x83, 0xf6, 0x19,
|
||||||
|
0xfe, 0x65, 0xab, 0xcf, 0xdf, 0xa4, 0x2d, 0x95, 0xa6, 0x12, 0xe5, 0x61,
|
||||||
|
0x89, 0x91, 0x38, 0x81, 0x7d, 0x0d, 0x50, 0x61, 0x4c, 0x07, 0x50, 0x7c,
|
||||||
|
0xd7, 0xf4, 0xb0, 0x05, 0x4c, 0x8f, 0xc0, 0x27, 0xb3, 0xf6, 0x1a, 0xec,
|
||||||
|
0xa7, 0xbf, 0x25, 0x07, 0x8a, 0xf5, 0x7d, 0x8a, 0xfa, 0xbd, 0x2c, 0xa7,
|
||||||
|
0xc7, 0x30, 0x04, 0x40, 0x29, 0xfe, 0xfc, 0xb2, 0x0f, 0x20, 0x7c, 0x01,
|
||||||
|
0xcf, 0x4e, 0x7c, 0x34, 0xa0, 0x89, 0x89, 0xd9, 0xc4, 0x09, 0x48, 0x58,
|
||||||
|
0x67, 0xc1, 0xf1, 0x08, 0xe2, 0x8a, 0x8a, 0x2c, 0xde, 0x73, 0x87, 0x8e,
|
||||||
|
0x3a, 0x53, 0x28, 0x68, 0x57, 0x9e, 0x6e, 0xca, 0x93, 0x5d, 0x96, 0xce,
|
||||||
|
0x28, 0xc5, 0xe7, 0xf9, 0x34, 0xd8, 0xd6, 0x21, 0x04, 0xf4, 0x69, 0xb0,
|
||||||
|
0x7a, 0x6b, 0x66, 0xa8, 0x5e, 0xa6, 0x58, 0x9f, 0x2c, 0xeb, 0x64, 0x36,
|
||||||
|
0xd1, 0xe6, 0xb1, 0xe3, 0xbc, 0x34, 0x94, 0x18, 0xb0, 0x97, 0xa0, 0x73,
|
||||||
|
0x5b, 0x9b, 0x63, 0x05, 0xa9, 0x63, 0x98, 0xd4, 0x0e, 0xb8, 0x92, 0xcd,
|
||||||
|
0x68, 0xa8, 0xdf, 0xa8, 0x9b, 0x75, 0x71, 0x02, 0xc4, 0xa0, 0xda, 0x2f,
|
||||||
|
0xf7, 0x67, 0x44, 0x6e, 0xda, 0x68, 0x08, 0x52, 0x11, 0x4c, 0xeb, 0xc4,
|
||||||
|
0x86, 0x2e, 0x30, 0x2d, 0x15, 0x23, 0xdb, 0xe6, 0x58, 0xcb, 0x18, 0xcd,
|
||||||
|
0x9c, 0x0d, 0x4d, 0xcb, 0x80, 0xe0, 0x26, 0x05, 0x9b, 0x40, 0x51, 0x74,
|
||||||
|
0xfc, 0xca, 0x7b, 0x89, 0x51, 0x76, 0xc0, 0x5b, 0xbf, 0x84, 0xe6, 0xad,
|
||||||
|
0x64, 0xfa, 0xa3, 0x71, 0x06, 0xb6, 0x10, 0x93, 0x29, 0x90, 0x8a, 0x11,
|
||||||
|
0x90, 0x39, 0x4a, 0xa8, 0x97, 0x7f, 0xdf, 0x00, 0x24, 0x71, 0x54, 0x96,
|
||||||
|
0xf3, 0x08, 0xfd, 0x63, 0xf1, 0xe7, 0xac, 0xc7, 0x20, 0x96, 0x8e, 0xcc,
|
||||||
|
0x4e, 0xef, 0x5d, 0x86, 0x26, 0x69, 0x1d, 0xa4, 0xa7, 0x32, 0xbf, 0xb2,
|
||||||
|
0x7b, 0xe2, 0x2c, 0x1c, 0x83, 0xd2, 0x30, 0x2b, 0x20, 0x25, 0x09, 0xbe,
|
||||||
|
0x42, 0xe0, 0xe0, 0xd1, 0x01, 0xb2, 0x90, 0xfa, 0xae, 0xfc, 0x53, 0x3e,
|
||||||
|
0xf5, 0xe3, 0x2f, 0xf9, 0x9f, 0x33, 0xe9, 0xf4, 0x77, 0x5f, 0x14, 0xf2,
|
||||||
|
0x68, 0x81, 0xc4, 0x94, 0x4d, 0x2b, 0xfd, 0xe3, 0xe6, 0xcf, 0x21, 0x4c,
|
||||||
|
0x5c, 0x41, 0x50, 0xf3, 0x5f, 0xa7, 0x7f, 0xca, 0x13, 0xd4, 0x95, 0x78,
|
||||||
|
0x20, 0x10, 0x8e, 0x0f, 0xb5, 0x11, 0xc1, 0xc6, 0xa3, 0x8b, 0x6c, 0x52,
|
||||||
|
0x8c, 0x60, 0x1d, 0x27, 0x45, 0x0c, 0x32, 0x0c, 0x64, 0x4b, 0xfd, 0x2d,
|
||||||
|
0xb7, 0x9b, 0x66, 0x6d, 0x92, 0x2f, 0xff, 0x30, 0xda, 0x0d, 0xcc, 0x2a,
|
||||||
|
0x5e, 0x35, 0x84, 0xe4, 0x7e, 0x89, 0x64, 0x09, 0xab, 0x62, 0x25, 0x47,
|
||||||
|
0x00, 0x43, 0xf4, 0xcf, 0xe3, 0xcd, 0x70, 0x3e, 0x4d, 0x70, 0xe8, 0x2f,
|
||||||
|
0x3e, 0x62, 0x5e, 0xf4, 0x61, 0xdc, 0xe9, 0x68, 0xcc, 0x30, 0xc8, 0xaf,
|
||||||
|
0x31, 0x1f, 0xcb, 0xb2, 0xfb, 0x98, 0xe1, 0xc0, 0x0d, 0xc1, 0xdf, 0x80,
|
||||||
|
0xb5, 0x54, 0x04, 0xd7, 0x80, 0x69, 0x63, 0x05, 0x9e, 0xfb, 0xed, 0x37,
|
||||||
|
0x8f, 0x59, 0xc7, 0xf8, 0xaa, 0xa0, 0x84, 0x1e, 0x32, 0x84, 0x48, 0xc6,
|
||||||
|
0x66, 0xc4, 0xdf, 0x38, 0x15, 0x6e, 0x09, 0xae, 0xfb, 0xc3, 0xdf, 0x4f,
|
||||||
|
0xcb, 0x38, 0xca, 0x6c, 0xa6, 0x9d, 0xe6, 0xd6, 0xc9, 0x41, 0x04, 0x82,
|
||||||
|
0x83, 0x3e, 0x44, 0x1e, 0x76, 0xd0, 0x15, 0xb7, 0xc4, 0xb3, 0x17, 0xa4,
|
||||||
|
0x87, 0xb1, 0x51, 0x1b, 0xcf, 0x40, 0xf8, 0x40, 0xcc, 0x49, 0x02, 0x9b,
|
||||||
|
0x0b, 0x4d, 0x5b, 0xb6, 0x14, 0x94, 0xe4, 0x47, 0x2f, 0x9a, 0x8d, 0x02,
|
||||||
|
0x70, 0x20, 0xb2, 0xf9, 0x03, 0x5b, 0x02, 0x79, 0x13, 0x51, 0xaf, 0x8e,
|
||||||
|
0x23, 0x6d, 0xd2, 0xb4, 0xb9, 0x88, 0x80, 0x09, 0x4f, 0xb9, 0x47, 0xda,
|
||||||
|
0x5c, 0xc5, 0xdf, 0xc4, 0x48, 0xa8, 0x2a, 0x56, 0x35, 0xb6, 0x21, 0x31,
|
||||||
|
0x9c, 0x1c, 0x49, 0x56, 0x6d, 0xa4, 0xf3, 0xa6, 0x21, 0xb2, 0x6e, 0xcd,
|
||||||
|
0xf0, 0xdf, 0xd9, 0xb5, 0x87, 0x96, 0x31, 0xf3, 0xad, 0x6a, 0x5f, 0x96,
|
||||||
|
0xb0, 0x71, 0x4e, 0x35, 0xba, 0x06, 0x17, 0x3c, 0xed, 0x3d, 0x1e, 0x5a,
|
||||||
|
0xc7, 0x0b, 0xfe, 0x3c, 0xcb, 0x15, 0x63, 0xed, 0xe1, 0xed, 0x43, 0xdf,
|
||||||
|
0xf8, 0xb1, 0xfb, 0x34, 0x0c, 0x4a, 0x32, 0xca, 0x91, 0xb0, 0xfe, 0x25,
|
||||||
|
0xca, 0x81, 0x3c, 0x1d, 0x73, 0x20, 0xe6, 0x21, 0xbf, 0x91, 0x21, 0x72,
|
||||||
|
0x6e, 0xf0, 0x1c, 0x21, 0x76, 0xc8, 0x4f, 0x85, 0x05, 0x3b, 0x7b, 0xb0,
|
||||||
|
0x59, 0x2c, 0x7e, 0xb9, 0xcf, 0xc1, 0x6f, 0x96, 0x76, 0xa2, 0x05, 0x76,
|
||||||
|
0x9e, 0x56, 0x98, 0x59, 0xda, 0xbe, 0x93, 0xd2, 0xa6, 0xa9, 0x6c, 0x9e,
|
||||||
|
0x2b, 0x7c, 0xbb, 0x91, 0x40, 0x45, 0x60, 0xfa, 0x4a, 0x43, 0x53, 0x20,
|
||||||
|
0x4d, 0x81, 0x8f, 0x00, 0xa4, 0x70, 0x5a, 0xdd, 0xd5, 0x94, 0xc7, 0x02,
|
||||||
|
0xf1, 0xce, 0xfc, 0x32, 0xeb, 0x9b, 0x29, 0x81, 0x99, 0x09, 0x29, 0x3e,
|
||||||
|
0x93, 0xc1, 0xe8, 0xe9, 0x90, 0x33, 0x17, 0x08, 0x13, 0x4b, 0xc8, 0x2a,
|
||||||
|
0x72, 0x80, 0x2c, 0xa6, 0xe3, 0x23, 0x4c, 0x49, 0x84, 0x49, 0xcb, 0x66,
|
||||||
|
0x8d, 0xe6, 0x90, 0x97, 0x0c, 0x37, 0x22, 0x69, 0x9e, 0xe5, 0x9a, 0x23,
|
||||||
|
0xe6, 0x28, 0x5d, 0x95, 0xde, 0xc4, 0x1b, 0xa1, 0x90, 0x0e, 0x4e, 0x45,
|
||||||
|
0x8c, 0xb3, 0xb0, 0xa3, 0x27, 0xe0, 0xfe, 0x95, 0xe2, 0x01, 0xde, 0xd5,
|
||||||
|
0xf8, 0xb6, 0xa6, 0x29, 0x8a, 0xa0, 0x9b, 0xe8, 0xa0, 0x40, 0x7e, 0xf2,
|
||||||
|
0xfb, 0x11, 0x78, 0x09, 0xc2, 0x2e, 0xf8, 0x24, 0x53, 0x45, 0x38, 0x2f,
|
||||||
|
0xe4, 0x72, 0xef, 0x10, 0x18, 0x6a, 0xd2, 0x93, 0x87, 0x8a, 0x59, 0x7d,
|
||||||
|
0xaa, 0xd9, 0x8e, 0x26, 0xb5, 0xe1, 0x39, 0x56, 0xb2, 0x91, 0x76, 0xe6,
|
||||||
|
0x52, 0x1c, 0x3f, 0xf8, 0xf1, 0x0d, 0x34, 0x85, 0xf3, 0x04, 0x4c, 0x5b,
|
||||||
|
0x4a, 0x68, 0x8d, 0xe6, 0xfc, 0x76, 0x7b, 0x05, 0xaf, 0xee, 0xcc, 0xc9,
|
||||||
|
0x3a, 0xdd, 0x12, 0xd1, 0x31, 0x94, 0x48, 0x10, 0x8c, 0x96, 0x46, 0x75,
|
||||||
|
0xc0, 0x05, 0x5d, 0x52, 0xda, 0xfa, 0x8f, 0xc4, 0x4b, 0xd8, 0x01, 0x64,
|
||||||
|
0x2c, 0x21, 0x61, 0xb4, 0xd2, 0x2c, 0x61, 0xb1, 0x0e, 0x05, 0x3f, 0x68,
|
||||||
|
0x52, 0x64, 0x37, 0x60, 0x12, 0x79, 0x11, 0x0b, 0x03, 0x10, 0xde, 0x20,
|
||||||
|
0x8d, 0xdb, 0x4a, 0x13, 0xfa, 0x5e, 0xd5, 0x06, 0xa1, 0x7f, 0x2c, 0xfd,
|
||||||
|
0x9c, 0x0e, 0x12, 0x25, 0x11, 0x70, 0x13, 0x59, 0x04, 0x96, 0x39, 0x81,
|
||||||
|
0x7f, 0x56, 0xff, 0xb3, 0xf9, 0x3f, 0xe9, 0xa0, 0xa9, 0x2f, 0xe0, 0x6f,
|
||||||
|
0xe9, 0x2f, 0x1c, 0x32, 0x78, 0x56, 0xda, 0xff, 0xbf, 0xbb, 0xdf, 0xad,
|
||||||
|
0xbb, 0x83, 0xfe, 0x98, 0xa4, 0x7f, 0xdf, 0xe6, 0x90, 0x29, 0x09, 0x3f,
|
||||||
|
0x10, 0x29, 0x8b, 0xb4, 0x20, 0x92, 0x73, 0x75, 0x2c, 0x28, 0x8c, 0x94,
|
||||||
|
0xcc, 0x80, 0xec, 0xac, 0x77, 0x5d, 0x59, 0x62, 0x03, 0xde, 0xdc, 0xb6,
|
||||||
|
0x2b, 0x84, 0xdb, 0x0d, 0x94, 0x40, 0xb4, 0x37, 0x81, 0x48, 0xf7, 0x9c,
|
||||||
|
0x66, 0xd5, 0x29, 0x14, 0x0d, 0x74, 0xa3, 0x3a, 0x93, 0x41, 0x86, 0xa3,
|
||||||
|
0xf2, 0x03, 0x6e, 0x33, 0xed, 0xc3, 0xb6, 0x83, 0x2e, 0x86, 0x11, 0x24,
|
||||||
|
0x46, 0x46, 0x62, 0x14, 0x82, 0x1b, 0x76, 0xc7, 0x36, 0x96, 0x0e, 0x12,
|
||||||
|
0x75, 0xfb, 0xfb, 0x6f, 0xb3, 0xbd, 0x97, 0x70, 0xc6, 0x06, 0x29, 0x38,
|
||||||
|
0x75, 0xfc, 0x26, 0x6b, 0x63, 0x34, 0xfc, 0x50, 0xac, 0x30, 0xca, 0xde,
|
||||||
|
0x8e, 0x20, 0xd8, 0xb6, 0x9c, 0x49, 0x3e, 0x84, 0x95, 0x2c, 0x9b, 0x46,
|
||||||
|
0x47, 0x36, 0x25, 0xc5, 0x76, 0x24, 0xfe, 0x21, 0x8a, 0x5d, 0x12, 0x82,
|
||||||
|
0x12, 0xe1, 0xfe, 0x43, 0x01, 0x28, 0x89, 0xf2, 0x70, 0xda, 0x1a, 0xe4,
|
||||||
|
0x62, 0xbd, 0x10, 0xec, 0x25, 0x8a, 0x16, 0x39, 0x71, 0xc1, 0xf2, 0xc3,
|
||||||
|
0x31, 0x82, 0x30, 0x52, 0xa2, 0x0c, 0x5b, 0x44, 0xfa, 0xf3, 0x9f, 0xe8,
|
||||||
|
0xe2, 0x89, 0x1f, 0xa1, 0xda, 0x3a, 0xc1, 0x47, 0x01, 0x5f, 0xa3, 0x2e,
|
||||||
|
0xb6, 0xc0, 0x7b, 0x0f, 0x8d, 0x79, 0xd6, 0x8b, 0xff, 0x48, 0x75, 0x05,
|
||||||
|
0xad, 0x17, 0x2f, 0x88, 0xdf, 0x3c, 0x27, 0xda, 0x44, 0xfc, 0x60, 0x76,
|
||||||
|
0x69, 0xa4, 0x9f, 0x62, 0x75, 0xb6, 0xca, 0x43, 0x88, 0x89, 0xe7, 0x46,
|
||||||
|
0x6f, 0x9e, 0xe0, 0x9f, 0xe5, 0xac, 0xfe, 0x9f, 0x05, 0xfe, 0x24, 0xc5,
|
||||||
|
0xc6, 0xcd, 0x02, 0xe6, 0x44, 0x9b, 0xd7, 0xdc, 0xb6, 0x52, 0x88, 0xce,
|
||||||
|
0x03, 0x59, 0x58, 0xc8, 0x93, 0x4d, 0xd8, 0x8f, 0xe1, 0x3d, 0x95, 0x47,
|
||||||
|
0x0a, 0xbf, 0x4e, 0x52, 0x8c, 0xa0, 0xe2, 0xe3, 0x5c, 0xb0, 0xa2, 0xee,
|
||||||
|
0x6b, 0xb0, 0x6d, 0x10, 0x90, 0xc2, 0xad, 0xf9, 0x2e, 0xb6, 0xa6, 0xec,
|
||||||
|
0xd6, 0xd8, 0x0f, 0xac, 0x3d, 0x17, 0x28, 0xa6, 0xc9, 0x33, 0x38, 0xb0,
|
||||||
|
0x12, 0x6e, 0xd3, 0xad, 0xfa, 0x2e, 0xb6, 0x6a, 0x75, 0xab, 0x18, 0x2a,
|
||||||
|
0xd4, 0xac, 0x42, 0x1b, 0x44, 0x79, 0x30, 0x18, 0x00, 0x1d, 0x40, 0x4e,
|
||||||
|
0x37, 0x1e, 0x1a, 0x1f, 0xc5, 0xf1, 0x00, 0xdf, 0x50, 0xe0, 0xb0, 0x40,
|
||||||
|
0xae, 0xea, 0xfd, 0xc9, 0x45, 0x9f, 0xad, 0xc4, 0x20, 0x84, 0x12, 0x65,
|
||||||
|
0x1b, 0x24, 0x5f, 0xb5, 0x02, 0x9c, 0x89, 0x81, 0xbf, 0x80, 0xa9, 0x0d,
|
||||||
|
0x7d, 0xb1, 0x02, 0x9e, 0x0a, 0x02, 0x7f, 0xbb, 0xd0, 0x3e, 0xd3, 0x67,
|
||||||
|
0x36, 0xe5, 0x0f, 0x3d, 0x5c, 0x2a, 0xee, 0x7a, 0x28, 0x10, 0xf1, 0xba,
|
||||||
|
0xd9, 0xb2, 0x04, 0x18, 0xbe, 0xae, 0xf4, 0xb9, 0x04, 0x17, 0x2f, 0x6c,
|
||||||
|
0x9b, 0x24, 0xe1, 0xc7, 0x1d, 0x7a, 0x65, 0xd2, 0x46, 0x23, 0x13, 0x59,
|
||||||
|
0xd7, 0xb8, 0x22, 0x04, 0x4e, 0xf3, 0x81, 0x51, 0xf0, 0xc7, 0xa4, 0x26,
|
||||||
|
0x4e, 0x4f, 0x9a, 0x3a, 0xd5, 0xe0, 0x66, 0x09, 0x1c, 0x76, 0x8e, 0xf6,
|
||||||
|
0x22, 0xae, 0xae, 0x5c, 0xdb, 0x39, 0x20, 0x1d, 0x80, 0x33, 0xfc, 0x6e,
|
||||||
|
0xd9, 0xb7, 0x5c, 0x8a, 0xf6, 0x0a, 0x65, 0x3c, 0xed, 0xad, 0xbd, 0x01,
|
||||||
|
0x0c, 0xe8, 0x03, 0x5f, 0x11, 0x46, 0x20, 0xfd, 0xc2, 0x38, 0x87, 0x89,
|
||||||
|
0xfe, 0x2f, 0x9d, 0x63, 0x83, 0xaa, 0x77, 0x3f, 0x2f, 0xeb, 0x7a, 0x2c,
|
||||||
|
0x37, 0xf1, 0x7f, 0x86, 0x04, 0xba, 0x44, 0xcb, 0x92, 0x5d, 0x9f, 0x2c,
|
||||||
|
0x87, 0xef, 0xd3, 0x45, 0x44, 0xb0, 0x00, 0xb6, 0xd6, 0x54, 0x02, 0xf0,
|
||||||
|
0xf4, 0xe8, 0x53, 0x2a, 0x45, 0xc8, 0x73, 0x74, 0x8f, 0x25, 0xfd, 0x1d,
|
||||||
|
0xcf, 0x97, 0x89, 0xbd, 0x65, 0xe0, 0x57, 0x86, 0x6c, 0x79, 0x81, 0xc9,
|
||||||
|
0x9f, 0x69, 0x73, 0x64, 0xd4, 0xe0, 0x1e, 0x45, 0x2a, 0x64, 0x55, 0xf4,
|
||||||
|
0x14, 0xed, 0x92, 0xb6, 0xf1, 0x64, 0xe3, 0x6f, 0x9d, 0xa2, 0xe4, 0xb1,
|
||||||
|
0xa6, 0x6a, 0xf4, 0xe8, 0x30, 0xdb, 0xd3, 0xf2, 0xb5, 0x14, 0x66, 0xd8,
|
||||||
|
0x67, 0xe8, 0x84, 0x46, 0x18, 0x26, 0xd1, 0x04, 0xe6, 0x8f, 0xa1, 0x99,
|
||||||
|
0x2e, 0xd2, 0x2b, 0xc3, 0x5c, 0x06, 0x48, 0x1b, 0x5d, 0x11, 0x6a, 0x3a,
|
||||||
|
0xc0, 0x4b, 0x43, 0x41, 0x1b, 0x2a, 0xb1, 0xc1, 0x38, 0x42, 0x32, 0x03,
|
||||||
|
0x05, 0x15, 0xcf, 0x96, 0x8a, 0x8a, 0xf2, 0x78, 0x6b, 0x00, 0x54, 0x7c,
|
||||||
|
0x44, 0xcf, 0xa2, 0x39, 0x6a, 0x75, 0x01, 0x4c, 0x18, 0x34, 0xb0, 0x37,
|
||||||
|
0xad, 0x0b, 0x63, 0x72, 0x4a, 0x38, 0x08, 0x11, 0x35, 0x7d, 0x32, 0xb6,
|
||||||
|
0xb3, 0x24, 0x31, 0x15, 0x9e, 0x90, 0x83, 0x7b, 0xec, 0x04, 0x7e, 0x2d,
|
||||||
|
0xb3, 0xaf, 0x1a, 0x02, 0x6c, 0x26, 0xfb, 0x0c, 0xdf, 0xbe, 0x5e, 0xf4,
|
||||||
|
0x76, 0xe3, 0xc7, 0x38, 0x24, 0xb7, 0xb6, 0xd6, 0x69, 0x41, 0x8e, 0xe2,
|
||||||
|
0x38, 0xc7, 0x01, 0xc9, 0x2f, 0xb8, 0x15, 0xcb, 0x87, 0x61, 0xde, 0x61,
|
||||||
|
0x64, 0xb9, 0x9b, 0xb8, 0xce, 0x65, 0xae, 0xcf, 0x30, 0x21, 0x67, 0x2b,
|
||||||
|
0x97, 0xe7, 0xbe, 0xfa, 0xca, 0xd5, 0x09, 0x6b, 0xd7, 0xfe, 0x8d, 0xf9,
|
||||||
|
0xb3, 0x9f, 0xf9, 0xe5, 0xe3, 0x88, 0x20, 0xae, 0x3f, 0xaa, 0x49, 0x7d,
|
||||||
|
0xe4, 0xb0, 0xc6, 0x47, 0xc9, 0x0e, 0x1d, 0x3d, 0xfc, 0x15, 0xe3, 0x9e,
|
||||||
|
0xb4, 0x95, 0xe4, 0xf4, 0x01, 0x51, 0x2b, 0x85, 0x16, 0xed, 0x7d, 0x92,
|
||||||
|
0xbf, 0x21, 0x23, 0x4a, 0xda, 0x5e, 0x73, 0xd4, 0x63, 0xa9, 0x93, 0xfa,
|
||||||
|
0xb6, 0xcf, 0x56, 0x88, 0xe8, 0x54, 0xbb, 0xd9, 0xe5, 0xbf, 0x25, 0x33,
|
||||||
|
0x4c, 0x38, 0x88, 0x77, 0xa8, 0x2b, 0xf9, 0x26, 0x1b, 0x49, 0x6b, 0xe8,
|
||||||
|
0xf0, 0x9f, 0xe0, 0x39, 0x6d, 0x99, 0xb3, 0x84, 0xfb, 0xa0, 0xef, 0x7c,
|
||||||
|
0xbd, 0xeb, 0x84, 0xc3, 0xe5, 0x67, 0xb0, 0x3c, 0x4c, 0xd1, 0x5c, 0xbf,
|
||||||
|
0xb3, 0xc0, 0xb1, 0xd0, 0xd4, 0x7c, 0x7b, 0xbe, 0x8b, 0x12, 0x4d, 0x90,
|
||||||
|
0xf3, 0x52, 0xc0, 0x65, 0x90, 0x46, 0x6d, 0x63, 0x09, 0x9e, 0x5d, 0x4a,
|
||||||
|
0x91, 0xfd, 0x53, 0x00, 0x2a, 0xee, 0xc3, 0xd7, 0x01, 0x20, 0xc0, 0x77,
|
||||||
|
0x26, 0x13, 0x91, 0xd8, 0x26, 0x64, 0x6c, 0x6a, 0x3f, 0xca, 0x3f, 0xef,
|
||||||
|
0x47, 0x43, 0xd4, 0x95, 0xf0, 0xea, 0x13, 0x97, 0x33, 0x37, 0x7d, 0x68,
|
||||||
|
0x1f, 0x54, 0x0f, 0x8d, 0x02, 0x86, 0x0d, 0x2d, 0x44, 0x06, 0x5b, 0x84,
|
||||||
|
0x06, 0xf6, 0x4d, 0xec, 0x11, 0x87, 0x5d, 0x49, 0xed, 0xd4, 0xa6, 0x1c,
|
||||||
|
0x9a, 0xcf, 0x02, 0xb4, 0xc3, 0x04, 0x57, 0xec, 0x2d, 0x52, 0xc2, 0x91,
|
||||||
|
0x36, 0xb3, 0xda, 0x42, 0x82, 0x59, 0xc3, 0x8f, 0x6b, 0x1d, 0x9c, 0xc2,
|
||||||
|
0x28, 0xe4, 0xf0, 0xd3, 0x2b, 0x4f, 0x1a, 0x99, 0x73, 0xd9, 0x02, 0x05,
|
||||||
|
0x00, 0x5c, 0x84, 0x3f, 0x02, 0xb7, 0x0f, 0xc7, 0xeb, 0xe1, 0x6c, 0x73,
|
||||||
|
0x39, 0xaa, 0x8a, 0x1c, 0x46, 0x5a, 0x52, 0xa5, 0xc4, 0xd5, 0xdd, 0x99,
|
||||||
|
0xf1, 0x35, 0x9a, 0x1a, 0x57, 0x27, 0xc6, 0x36, 0x15, 0x8b, 0xa1, 0xeb,
|
||||||
|
0xb1, 0x55, 0x66, 0x2c, 0x0f, 0x8b, 0x30, 0xe3, 0xee, 0xb0, 0x27, 0x3e,
|
||||||
|
0x39, 0xe1, 0xb1, 0x62, 0x1b, 0x87, 0x7a, 0x94, 0x04, 0xbe, 0x82, 0x85,
|
||||||
|
0xa9, 0xff, 0x5c, 0x53, 0x80, 0x5b, 0xdb, 0xb1, 0x3d, 0xa7, 0xc7, 0x56,
|
||||||
|
0x8d, 0xe5, 0x51, 0x5c, 0x95, 0x2c, 0x6a, 0x7f, 0xad, 0xae, 0xad, 0x89,
|
||||||
|
0x6c, 0x7a, 0x4f, 0x8b, 0x7b, 0x66, 0x1a, 0x47, 0xe5, 0xfe, 0x5d, 0xb8,
|
||||||
|
0xe0, 0x7e, 0xd6, 0x46, 0x61, 0x83, 0x6c, 0x9e, 0x85, 0x0e, 0xb4, 0x51,
|
||||||
|
0x6a, 0x50, 0xcd, 0x5a, 0x0f, 0x1e, 0xca, 0xf2, 0x4d, 0xca, 0x76, 0xa1,
|
||||||
|
0x77, 0x62, 0x2e, 0xd2, 0x89, 0x39, 0x3c, 0x2d, 0x3b, 0xd0, 0x59, 0x12,
|
||||||
|
0xb0, 0x26, 0xd8, 0x21, 0xa7, 0xcc, 0x90, 0xaf, 0xd0, 0xa9, 0xb8, 0xb0,
|
||||||
|
0x38, 0x98, 0xe2, 0xfb, 0x6e, 0x60, 0xff, 0x09, 0x41, 0x4a, 0xfc, 0xe6,
|
||||||
|
0x75, 0xf8, 0xec, 0x5e, 0xcc, 0x19, 0x35, 0x9c, 0x4c, 0xad, 0x0d, 0x59,
|
||||||
|
0x3f, 0x87, 0x6d, 0xc7, 0xb5, 0x04, 0x5a, 0xfb, 0xaa, 0x6b, 0x10, 0xf1,
|
||||||
|
0x17, 0x21, 0xc2, 0x90, 0xdc, 0xbb, 0x5d, 0x8d, 0x08, 0xdb, 0xc1, 0xeb,
|
||||||
|
0x8c, 0x38, 0xd6, 0x94, 0xdf, 0xc9, 0xa0, 0x13, 0x9b, 0x75, 0xb4, 0x50,
|
||||||
|
0xef, 0x67, 0xe2, 0xef, 0x65, 0xe8, 0x7f, 0x9a, 0xb9, 0x27, 0x33, 0x7a,
|
||||||
|
0xc7, 0xf4, 0x03, 0x05, 0xc9, 0x9c, 0x66, 0xdc, 0x3c, 0xe4, 0xee, 0x23,
|
||||||
|
0x38, 0xe7, 0xab, 0xff, 0x9c, 0x2b, 0x30, 0x64, 0x3c, 0xba, 0x6d, 0xbc,
|
||||||
|
0xd7, 0xd1, 0x7b, 0x76, 0xf7, 0x85, 0xd1, 0x5d, 0x7a, 0xd0, 0xfe, 0xa8,
|
||||||
|
0x7e, 0x56, 0xef, 0xd7, 0xdf, 0x76, 0xd4, 0x3e, 0x42, 0x83, 0x60, 0x44,
|
||||||
|
0xb5, 0xa1, 0x13, 0xf3, 0xff, 0xc9, 0x0e, 0xa7, 0x50, 0x10, 0xc1, 0x3e,
|
||||||
|
0x0c, 0x92, 0xbf, 0x82, 0x31, 0xb0, 0xda, 0x1f, 0x1d, 0x52, 0x7f, 0x14,
|
||||||
|
0xb3, 0x36, 0x39, 0xed, 0x75, 0x7e, 0xc0, 0x06, 0x0f, 0x4b, 0xfe, 0x48,
|
||||||
|
0xd7, 0xb3, 0xd6, 0xad, 0xaa, 0xb0, 0x6e, 0x98, 0x4d, 0xfb, 0x5b, 0x5d,
|
||||||
|
0xc3, 0xbc, 0xbc, 0x68, 0x6b, 0x98, 0x1a, 0xe9, 0x91, 0x24, 0xc8, 0xc4,
|
||||||
|
0x2c, 0x9a, 0x75, 0x7a, 0xfd, 0x02, 0x47, 0xfa, 0xdf, 0xc1, 0xf5, 0x97,
|
||||||
|
0x43, 0x9e, 0x1c, 0xd4, 0xa5, 0x79, 0xb5, 0x25, 0x36, 0xa2, 0xce, 0x14,
|
||||||
|
0xb6, 0x0c, 0x70, 0x3b, 0x07, 0xf8, 0x30, 0x2c, 0xbb, 0x73, 0x42, 0xea,
|
||||||
|
0x49, 0xec, 0x13, 0xa9, 0xc9, 0x90, 0x00, 0x66, 0x7f, 0xf5, 0xd9, 0x74,
|
||||||
|
0xf2, 0x52, 0x3c, 0xe7, 0x1a, 0x32, 0x1d, 0x0b, 0x59, 0xf2, 0x4a, 0xbd,
|
||||||
|
0x2c, 0x90, 0x80, 0x42, 0xf8, 0x7a, 0xd2, 0xd9, 0xb0, 0x0e, 0x1b, 0xef,
|
||||||
|
0x19, 0x00, 0x36, 0xe0, 0xda, 0x7f, 0x83, 0x0e, 0xa1, 0x90, 0x1f, 0x70,
|
||||||
|
0xc7, 0x28, 0xa1, 0x49, 0x2e, 0xda, 0x2a, 0x82, 0xac, 0xf2, 0xef, 0x74,
|
||||||
|
0xeb, 0xe3, 0x5d, 0xa3, 0x56, 0xb2, 0x80, 0x09, 0xf2, 0xc9, 0x0d, 0x41,
|
||||||
|
0x4f, 0xf7, 0xfb, 0xb1, 0x8b, 0x17, 0x07, 0x83, 0x2e, 0x65, 0x56, 0x20,
|
||||||
|
0xdc, 0x99, 0x1e, 0xf8, 0x3b, 0xe1, 0x51, 0xa0, 0x57, 0xc5, 0x57, 0x60,
|
||||||
|
0x89, 0x1e, 0x24, 0xf1, 0x57, 0x58, 0xad, 0xac, 0x80, 0x07, 0x88, 0x75,
|
||||||
|
0x31, 0xe2, 0x97, 0x39, 0xe6, 0x92, 0x3a, 0x7d, 0xa2, 0xbf, 0x6e, 0x5d,
|
||||||
|
0xa7, 0xa9, 0x6b, 0xae, 0xaa, 0xa8, 0x30, 0xb8, 0x97, 0x13, 0x7a, 0x15,
|
||||||
|
0x7b, 0x20, 0x10, 0xcc, 0xb0, 0x27, 0x0e, 0x1b, 0x10, 0xbd, 0x55, 0xec,
|
||||||
|
0x4f, 0xd1, 0xa6, 0x59, 0x29, 0x8c, 0x31, 0x72, 0x07, 0x2f, 0x4f, 0x6e,
|
||||||
|
0xd5, 0xc4, 0x50, 0x20, 0x2d, 0x05, 0x29, 0xf8, 0x6c, 0x8d, 0x41, 0xc4,
|
||||||
|
0x0e, 0x9c, 0x74, 0x12, 0x3e, 0xc9, 0xa8, 0x0c, 0x35, 0x43, 0x8a, 0x9d,
|
||||||
|
0x5b, 0xee, 0x53, 0x18, 0xd9, 0xf1, 0x7c, 0xe2, 0xaf, 0xe5, 0x7c, 0x7a,
|
||||||
|
0x6f, 0xcc, 0x43, 0xae, 0xdb, 0x55, 0xa1, 0x4b, 0x8b, 0x09, 0xeb, 0xd8,
|
||||||
|
0x57, 0xda, 0x8f, 0x64, 0x8f, 0xf2, 0xb0, 0x3c, 0xee, 0x90, 0x77, 0xdd,
|
||||||
|
0x37, 0x76, 0x87, 0xfb, 0xbe, 0x4a, 0xb6, 0x75, 0x03, 0x75, 0xf0, 0x2a,
|
||||||
|
0x92, 0x3c, 0xfe, 0xe1, 0x5c, 0x37, 0x09, 0xc8, 0x55, 0x28, 0xe8, 0x70,
|
||||||
|
0x37, 0xef, 0x3f, 0x70, 0x71, 0xd9, 0x3b, 0x25, 0x2e, 0x11, 0xc7, 0x71,
|
||||||
|
0x86, 0x59, 0x0e, 0x5f, 0x1d, 0x24, 0xfe, 0xf9, 0x4f, 0x0a, 0xbb, 0xfe,
|
||||||
|
0x92, 0x8b, 0x8f, 0x18, 0xa5, 0xaa, 0x68, 0xc3, 0xd4, 0x8f, 0xb8, 0x00,
|
||||||
|
0x6e, 0x3e, 0x7e, 0x24, 0x12, 0x95, 0xa9, 0x3d, 0xbd, 0xa4, 0x93, 0xc5,
|
||||||
|
0x67, 0xef, 0x75, 0x11, 0xb2, 0x50, 0x80, 0xc1, 0x19, 0x1b, 0x8c, 0xbc,
|
||||||
|
0x9b, 0x2d, 0xad, 0xbe, 0xe4, 0x95, 0xe4, 0x82, 0xd1, 0xab, 0xee, 0x29,
|
||||||
|
0x39, 0x97, 0x8f, 0x92, 0xc5, 0x7e, 0x94, 0x10, 0xe8, 0x8e, 0xbe, 0x05,
|
||||||
|
0x23, 0xb5, 0xda, 0x8e, 0xe9, 0x79, 0x88, 0x10, 0x22, 0x1f, 0x5c, 0xb9,
|
||||||
|
0xd9, 0x10, 0x24, 0x28, 0xed, 0xc1, 0xe8, 0xa6, 0x21, 0xee, 0xda, 0x83,
|
||||||
|
0x82, 0x44, 0x43, 0x13, 0x74, 0x69, 0xb0, 0x33, 0xd0, 0xaf, 0x1a, 0x07,
|
||||||
|
0x09, 0x46, 0x42, 0xa8, 0xfb, 0x09, 0x81, 0xe5, 0x91, 0x21, 0xe5, 0xcb,
|
||||||
|
0x1b, 0x0e, 0x26, 0x0c, 0x08, 0x99, 0xbb, 0x0c, 0x3a, 0xdc, 0xcf, 0x0e,
|
||||||
|
0x9d, 0xc8, 0xc4, 0xee, 0x1a, 0xdc, 0xf5, 0x3d, 0x60, 0x8a, 0xe8, 0x0e,
|
||||||
|
0xab, 0xbb, 0xad, 0x49, 0xa0, 0x6d, 0x70, 0x9b, 0x85, 0x29, 0x3c, 0x31,
|
||||||
|
0xf7, 0xed, 0xa5, 0xed, 0xf6, 0x4c, 0x1f, 0x26, 0x0d, 0x06, 0x8b, 0xe7,
|
||||||
|
0x0f, 0x0c, 0x4c, 0xbe, 0x23, 0xa0, 0xbf, 0x20, 0x76, 0xd3, 0x23, 0x67,
|
||||||
|
0x7e, 0x64, 0x32, 0x8b, 0x9d, 0xd0, 0x77, 0x4c, 0x3d, 0xb9, 0xb0, 0x71,
|
||||||
|
0x1c, 0x5d, 0x9a, 0xa8, 0xa7, 0x8d, 0xac, 0x3e, 0xbc, 0xe1, 0x27, 0x45,
|
||||||
|
0x34, 0xb1, 0x1a, 0x05, 0x60, 0x7b, 0x90, 0xb1, 0x4f, 0x95, 0xa2, 0x19,
|
||||||
|
0x3f, 0x86, 0xf3, 0x21, 0x0a, 0xfc, 0x6f, 0x55, 0x44, 0xfc, 0x52, 0xde,
|
||||||
|
0x33, 0x98, 0xc3, 0x1c, 0xca, 0x61, 0xe8, 0x1e, 0x6c, 0xe3, 0x9c, 0xc3,
|
||||||
|
0xb2, 0xdf, 0x6a, 0x93, 0x4b, 0x71, 0x29, 0x67, 0xe7, 0x26, 0x68, 0x89,
|
||||||
|
0xda, 0x74, 0x0a, 0xf7, 0x42, 0xcc, 0x3c, 0x2c, 0x78, 0x6a, 0xf4, 0x39,
|
||||||
|
0x15, 0x30, 0x29, 0xec, 0x87, 0xca, 0xdc, 0x06, 0x7e, 0x25, 0x07, 0x83,
|
||||||
|
0xd8, 0xc8, 0xfa, 0x21, 0x86, 0x10, 0x29, 0xb4, 0x10, 0xbc, 0x3e, 0xee,
|
||||||
|
0xe3, 0x5c, 0x56, 0x01, 0x94, 0xbe, 0xa6, 0x63, 0x23, 0x8b, 0x5f, 0x9d,
|
||||||
|
0x26, 0xc2, 0x6f, 0x86, 0x06, 0x45, 0x2f, 0x01, 0x4c, 0x1c, 0xea, 0x96,
|
||||||
|
0xdd, 0xb5, 0x1e, 0xbb, 0x28, 0x1a, 0xca, 0x6a, 0xf8, 0x67, 0x82, 0xac,
|
||||||
|
0xa3, 0x41, 0x7b, 0xa0, 0xc1, 0xfe, 0x34, 0x4f, 0x66, 0x85, 0x90, 0xc5,
|
||||||
|
0x05, 0x1b, 0xc4, 0x86, 0xde, 0x51, 0xf1, 0x2b, 0x9c, 0x89, 0x46, 0x3c,
|
||||||
|
0xd6, 0xf7, 0x26, 0xe5, 0xe0, 0xd7, 0x93, 0xac, 0xa3, 0x9c, 0xdb, 0xb0,
|
||||||
|
0x72, 0x6e, 0x5f, 0xad, 0x9c, 0x08, 0x7b, 0xc2, 0x3f, 0x2e, 0x81, 0xa7,
|
||||||
|
0xb6, 0xa0, 0x42, 0xd6, 0xdc, 0x80, 0x02, 0xcc, 0x21, 0xb1, 0x82, 0xbf,
|
||||||
|
0x4b, 0x45, 0x06, 0x5a, 0x4f, 0x45, 0xf4, 0x35, 0x2f, 0x61, 0x45, 0xd1,
|
||||||
|
0x8a, 0x3f, 0x5b, 0x5d, 0x06, 0x7a, 0x5f, 0x75, 0x31, 0x6f, 0xea, 0xc4,
|
||||||
|
0xbc, 0xd1, 0xc7, 0x75, 0x3c, 0x29, 0xf7, 0xe8, 0x65, 0xa5, 0x1d, 0x9c,
|
||||||
|
0xdb, 0x95, 0xfb, 0xaf, 0x0c, 0xb5, 0x93, 0xc7, 0xbb, 0xef, 0xe2, 0x7e,
|
||||||
|
0xe3, 0xe5, 0x7f, 0x09, 0xae, 0xe2, 0x59, 0x1b, 0xee, 0x3a, 0x3e, 0xb4,
|
||||||
|
0x8a, 0xd7, 0xd4, 0x2a, 0x1c, 0x63, 0x3b, 0xc3, 0x67, 0xa4, 0x03, 0x57,
|
||||||
|
0xca, 0xf1, 0xff, 0x26, 0x08, 0xf5, 0xf1, 0x25, 0xfc, 0x8e, 0x22, 0x0b,
|
||||||
|
0x57, 0x80, 0x79, 0xc1, 0x81, 0x6c, 0xd0, 0xb6, 0x48, 0x36, 0xbf, 0xf3,
|
||||||
|
0x13, 0x03, 0xe1, 0xe4, 0xa3, 0xae, 0x00, 0xef, 0xa9, 0xc2, 0x8f, 0xdf,
|
||||||
|
0x7d, 0xf5, 0x73, 0x06, 0x16, 0xe2, 0x87, 0xf0, 0x95, 0x3e, 0x84, 0x87,
|
||||||
|
0xaf, 0x7e, 0xfe, 0x3a, 0x5d, 0x18, 0xcb, 0x59, 0xb7, 0x53, 0xa6, 0x59,
|
||||||
|
0x78, 0x75, 0x60, 0x96, 0xbe, 0xa3, 0x82, 0xfb, 0x48, 0xda, 0xfb, 0x11,
|
||||||
|
0x4a, 0x7e, 0x06, 0xda, 0xa4, 0x70, 0xdf, 0xee, 0xf5, 0x70, 0x54, 0xef,
|
||||||
|
0xcb, 0x3e, 0x38, 0xd1, 0x4a, 0x96, 0xd0, 0x20, 0xaf, 0x87, 0x60, 0x8f,
|
||||||
|
0x58, 0x77, 0xec, 0x91, 0x4d, 0x4c, 0xe1, 0xbb, 0xef, 0xbe, 0x7d, 0xda,
|
||||||
|
0x14, 0x8f, 0x8b, 0x78, 0xdb, 0x2b, 0x7a, 0xe0, 0xa3, 0xde, 0xbe, 0xc6,
|
||||||
|
0xcf, 0xd8, 0x13, 0x20, 0x60, 0xbc, 0x30, 0x9a, 0xad, 0xbc, 0x83, 0x02,
|
||||||
|
0x5d, 0xa9, 0xfb, 0x5f, 0xf1, 0x46, 0x2f, 0x67, 0xe3, 0xee, 0x34, 0xcb,
|
||||||
|
0x90, 0x5d, 0x93, 0xd4, 0x3b, 0x13, 0xc2, 0x19, 0x6d, 0x26, 0x8d, 0x14,
|
||||||
|
0x48, 0x20, 0x61, 0x7f, 0x50, 0x10, 0xee, 0x84, 0x05, 0xa4, 0x87, 0x86,
|
||||||
|
0x66, 0x01, 0x9b, 0xc4, 0x66, 0x7e, 0x33, 0xbf, 0x87, 0x9f, 0xf2, 0x90,
|
||||||
|
0x09, 0xf0, 0xfe, 0xb3, 0x03, 0x9e, 0x5c, 0x00, 0x1c, 0x31, 0xc0, 0x49,
|
||||||
|
0x35, 0xeb, 0x90, 0x9f, 0x59, 0xa3, 0xdc, 0x2e, 0xff, 0xad, 0xa7, 0x6d,
|
||||||
|
0xcc, 0x88, 0xf3, 0x0f, 0x1c, 0x1c, 0xe0, 0x13, 0x8c, 0x9c, 0x46, 0xef,
|
||||||
|
0xbd, 0xf3, 0x5e, 0x4b, 0xd8, 0xe7, 0x6d, 0x3e, 0xe1, 0x4c, 0x23, 0x27,
|
||||||
|
0x43, 0xad, 0x2d, 0x28, 0xa6, 0x06, 0x65, 0xc1, 0x6a, 0x2c, 0x7c, 0x74,
|
||||||
|
0x15, 0xeb, 0x9b, 0xe8, 0x4a, 0x3b, 0x5c, 0x75, 0xae, 0xa5, 0xdb, 0x17,
|
||||||
|
0xcd, 0xc9, 0xbb, 0xb4, 0x03, 0x38, 0x32, 0xb9, 0xb8, 0x8f, 0xd1, 0xfc,
|
||||||
|
0x57, 0xf9, 0x19, 0xee, 0x86, 0x0f, 0x77, 0x03, 0x70, 0x29, 0x02, 0x93,
|
||||||
|
0x1a, 0xcb, 0x0a, 0x8f, 0x07, 0x05, 0xf6, 0x6f, 0x3f, 0xfc, 0x01, 0x35,
|
||||||
|
0x65, 0x9f, 0x7f, 0x0d, 0x62, 0x00, 0x00
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,260 @@
|
|||||||
|
#include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson
|
||||||
|
|
||||||
|
#if defined(ARDUINOJSON_VERSION)
|
||||||
|
#if !(ARDUINOJSON_VERSION_MAJOR == 6 and ARDUINOJSON_VERSION_MINOR >= 8)
|
||||||
|
#error "Install ArduinoJson v6.8.x or higher"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char * listStateJSONfull() {
|
||||||
|
const size_t bufferSize = JSON_ARRAY_SIZE(12) + JSON_OBJECT_SIZE(19) + 250;
|
||||||
|
DynamicJsonDocument jsonBuffer(bufferSize);
|
||||||
|
JsonObject root = jsonBuffer.to<JsonObject>();
|
||||||
|
root["segment"] = State.segment;
|
||||||
|
root["start"] = segState.start;
|
||||||
|
root["stop"] = segState.stop;
|
||||||
|
root["mode"] = (uint8_t) State.mode;
|
||||||
|
root["fx_mode"] = segState.mode[State.segment];
|
||||||
|
root["speed"] = segState.speed[State.segment];
|
||||||
|
root["brightness"] = State.brightness;
|
||||||
|
JsonArray color = root.createNestedArray("color");
|
||||||
|
color.add(main_color.white);
|
||||||
|
color.add(main_color.red);
|
||||||
|
color.add(main_color.green);
|
||||||
|
color.add(main_color.blue);
|
||||||
|
color.add(back_color.white);
|
||||||
|
color.add(back_color.red);
|
||||||
|
color.add(back_color.green);
|
||||||
|
color.add(back_color.blue);
|
||||||
|
color.add(xtra_color.white);
|
||||||
|
color.add(xtra_color.red);
|
||||||
|
color.add(xtra_color.green);
|
||||||
|
color.add(xtra_color.blue);
|
||||||
|
root["ws_fxopt"] = segState.options;
|
||||||
|
root["hostname"] = HOSTNAME;
|
||||||
|
#if defined(ENABLE_MQTT)
|
||||||
|
root["mqtt_host"] = mqtt_host;
|
||||||
|
root["mqtt_port"] = mqtt_port;
|
||||||
|
root["mqtt_user"] = mqtt_user;
|
||||||
|
root["mqtt_pass"] = mqtt_pass;
|
||||||
|
#endif
|
||||||
|
root["ws_seg"] = Config.segments;
|
||||||
|
root["ws_cnt"] = Config.stripSize;
|
||||||
|
root["ws_rgbo"] = Config.RGBOrder;
|
||||||
|
root["ws_pin"] = Config.pin;
|
||||||
|
root["ws_trans"] = Config.transEffect;
|
||||||
|
uint16_t msg_len = measureJson(root) + 1;
|
||||||
|
char * buffer = (char *) malloc(msg_len);
|
||||||
|
serializeJson(root, buffer, msg_len);
|
||||||
|
jsonBuffer.clear();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * listStateJSON() {
|
||||||
|
const size_t bufferSize = JSON_OBJECT_SIZE(3) + 25;
|
||||||
|
DynamicJsonDocument jsonBuffer(bufferSize);
|
||||||
|
JsonObject root = jsonBuffer.to<JsonObject>();
|
||||||
|
root["segment"] = State.segment;
|
||||||
|
root["mode"] = (uint8_t) State.mode;
|
||||||
|
root["brightness"] = State.brightness;
|
||||||
|
uint16_t msg_len = measureJson(root) + 1;
|
||||||
|
char * buffer = (char *) malloc(msg_len);
|
||||||
|
serializeJson(root, buffer, msg_len);
|
||||||
|
jsonBuffer.clear();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * listSegmentStateJSON(uint8_t _seg) {
|
||||||
|
const size_t bufferSize = JSON_ARRAY_SIZE(12) + JSON_OBJECT_SIZE(6) + 100;
|
||||||
|
DynamicJsonDocument jsonBuffer(bufferSize);
|
||||||
|
JsonObject root = jsonBuffer.to<JsonObject>();
|
||||||
|
root["start"] = strip->getSegment(_seg)->start;
|
||||||
|
root["stop"] = strip->getSegment(_seg)->stop;
|
||||||
|
root["fx_mode"] = segState.mode[_seg];
|
||||||
|
root["speed"] = segState.speed[_seg];
|
||||||
|
JsonArray color = root.createNestedArray("color");
|
||||||
|
//color.add((strip->getColors(_seg)[0] >> 24) & 0xFF);
|
||||||
|
color.add((segState.colors[_seg][0] >> 24) & 0xFF);
|
||||||
|
color.add((segState.colors[_seg][0] >> 16) & 0xFF);
|
||||||
|
color.add((segState.colors[_seg][0] >> 8) & 0xFF);
|
||||||
|
color.add((segState.colors[_seg][0]) & 0xFF);
|
||||||
|
color.add((segState.colors[_seg][1] >> 24) & 0xFF);
|
||||||
|
color.add((segState.colors[_seg][1] >> 16) & 0xFF);
|
||||||
|
color.add((segState.colors[_seg][1] >> 8) & 0xFF);
|
||||||
|
color.add((segState.colors[_seg][1]) & 0xFF);
|
||||||
|
color.add((segState.colors[_seg][2] >> 24) & 0xFF);
|
||||||
|
color.add((segState.colors[_seg][2] >> 16) & 0xFF);
|
||||||
|
color.add((segState.colors[_seg][2] >> 8) & 0xFF);
|
||||||
|
color.add((segState.colors[_seg][2]) & 0xFF);
|
||||||
|
root["ws_fxopt"] = strip->getOptions(_seg);
|
||||||
|
uint16_t msg_len = measureJson(root) + 1;
|
||||||
|
char * buffer = (char *) malloc(msg_len);
|
||||||
|
serializeJson(root, buffer, msg_len);
|
||||||
|
jsonBuffer.clear();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getStateJSON() {
|
||||||
|
char * buffer = listStateJSONfull();
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send ( 200, "application/json", buffer);
|
||||||
|
free (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
char * listConfigJSON() {
|
||||||
|
#if defined(ENABLE_MQTT)
|
||||||
|
const size_t bufferSize = JSON_OBJECT_SIZE(10) + 150;
|
||||||
|
#else
|
||||||
|
const size_t bufferSize = JSON_OBJECT_SIZE(6) + 100;
|
||||||
|
#endif
|
||||||
|
DynamicJsonDocument jsonBuffer(bufferSize);
|
||||||
|
JsonObject root = jsonBuffer.to<JsonObject>();
|
||||||
|
root["hostname"] = HOSTNAME;
|
||||||
|
#if defined(ENABLE_MQTT)
|
||||||
|
root["mqtt_host"] = mqtt_host;
|
||||||
|
root["mqtt_port"] = mqtt_port;
|
||||||
|
root["mqtt_user"] = mqtt_user;
|
||||||
|
root["mqtt_pass"] = mqtt_pass;
|
||||||
|
#endif
|
||||||
|
root["ws_seg"] = Config.segments;
|
||||||
|
root["ws_cnt"] = Config.stripSize;
|
||||||
|
root["ws_rgbo"] = Config.RGBOrder;
|
||||||
|
root["ws_pin"] = Config.pin;
|
||||||
|
root["ws_trans"] = Config.transEffect;
|
||||||
|
uint16_t msg_len = measureJson(root) + 1;
|
||||||
|
char * buffer = (char *) malloc(msg_len);
|
||||||
|
serializeJson(root, buffer, msg_len);
|
||||||
|
jsonBuffer.clear();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getConfigJSON() {
|
||||||
|
char * buffer = listConfigJSON();
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send ( 200, "application/json", buffer);
|
||||||
|
free (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
char * listModesJSON() {
|
||||||
|
const size_t bufferSize = JSON_ARRAY_SIZE(strip->getModeCount() + 1) + (strip->getModeCount() + 1)*JSON_OBJECT_SIZE(2) + 2000;
|
||||||
|
DynamicJsonDocument jsonBuffer(bufferSize);
|
||||||
|
JsonArray root = jsonBuffer.to<JsonArray>();
|
||||||
|
JsonObject objectoff = root.createNestedObject();
|
||||||
|
objectoff["mode"] = "off";
|
||||||
|
objectoff["name"] = "OFF";
|
||||||
|
for (uint8_t i = 0; i < strip->getModeCount(); i++) {
|
||||||
|
JsonObject object = root.createNestedObject();
|
||||||
|
object["mode"] = i;
|
||||||
|
object["name"] = strip->getModeName(i);
|
||||||
|
}
|
||||||
|
uint16_t msg_len = measureJson(root) + 1;
|
||||||
|
char * buffer = (char *) malloc(msg_len);
|
||||||
|
serializeJson(root, buffer, msg_len);
|
||||||
|
jsonBuffer.clear();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getModesJSON() {
|
||||||
|
char * buffer = listModesJSON();
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send ( 200, "application/json", buffer);
|
||||||
|
free (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
char * listESPStateJSON() {
|
||||||
|
const size_t bufferSize = JSON_OBJECT_SIZE(31) + 1500;
|
||||||
|
DynamicJsonDocument jsonBuffer(bufferSize);
|
||||||
|
JsonObject root = jsonBuffer.to<JsonObject>();
|
||||||
|
root["HOSTNAME"] = HOSTNAME;
|
||||||
|
root["version"] = SKETCH_VERSION;
|
||||||
|
root["heap"] = ESP.getFreeHeap();
|
||||||
|
root["sketch_size"] = ESP.getSketchSize();
|
||||||
|
root["free_sketch_space"] = ESP.getFreeSketchSpace();
|
||||||
|
root["flash_chip_size"] = ESP.getFlashChipSize();
|
||||||
|
root["flash_chip_real_size"] = ESP.getFlashChipRealSize();
|
||||||
|
root["flash_chip_speed"] = ESP.getFlashChipSpeed();
|
||||||
|
root["sdk_version"] = ESP.getSdkVersion();
|
||||||
|
root["core_version"] = ESP.getCoreVersion();
|
||||||
|
root["cpu_freq"] = ESP.getCpuFreqMHz();
|
||||||
|
root["chip_id"] = ESP.getFlashChipId();
|
||||||
|
#if defined(USE_WS2812FX_DMA)
|
||||||
|
#if USE_WS2812FX_DMA == 0
|
||||||
|
root["animation_lib"] = "WS2812FX_DMA";
|
||||||
|
#endif
|
||||||
|
#if USE_WS2812FX_DMA == 1
|
||||||
|
root["animation_lib"] = "WS2812FX_UART1";
|
||||||
|
#endif
|
||||||
|
#if USE_WS2812FX_DMA == 2
|
||||||
|
root["animation_lib"] = "WS2812FX_UART2";
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
root["animation_lib"] = "WS2812FX";
|
||||||
|
#endif
|
||||||
|
root["ws2812_pin"] = Config.pin;
|
||||||
|
root["led_count"] = Config.stripSize;
|
||||||
|
root["rgb_order"] = Config.RGBOrder;
|
||||||
|
if (strstr(Config.RGBOrder, "W") != NULL) {
|
||||||
|
root["rgbw_mode"] = "ON";
|
||||||
|
} else {
|
||||||
|
root["rgbw_mode"] = "OFF";
|
||||||
|
}
|
||||||
|
#if defined(ENABLE_BUTTON)
|
||||||
|
root["button_mode"] = "ON";
|
||||||
|
root["button_pin"] = ENABLE_BUTTON;
|
||||||
|
#else
|
||||||
|
root["button_mode"] = "OFF";
|
||||||
|
#endif
|
||||||
|
#if defined(ENABLE_BUTTON_GY33)
|
||||||
|
root["button_gy33"] = "ON";
|
||||||
|
root["gy33_pin"] = ENABLE_BUTTON_GY33;
|
||||||
|
#else
|
||||||
|
root["button_gy33"] = "OFF";
|
||||||
|
#endif
|
||||||
|
#if defined(ENABLE_REMOTE)
|
||||||
|
root["ir_remote"] = "ON";
|
||||||
|
root["tsop_ir_pin"] = ENABLE_REMOTE;
|
||||||
|
#else
|
||||||
|
root["ir_remote"] = "OFF";
|
||||||
|
#endif
|
||||||
|
#if defined(ENABLE_MQTT)
|
||||||
|
#if ENABLE_MQTT == 0
|
||||||
|
root["mqtt"] = "MQTT";
|
||||||
|
#endif
|
||||||
|
#if ENABLE_MQTT == 1
|
||||||
|
root["mqtt"] = "AMQTT";
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
root["mqtt"] = "OFF";
|
||||||
|
#endif
|
||||||
|
#if defined(ENABLE_HOMEASSISTANT)
|
||||||
|
root["home_assistant"] = "ON";
|
||||||
|
#else
|
||||||
|
root["home_assistant"] = "OFF";
|
||||||
|
#endif
|
||||||
|
#if defined(ENABLE_OTA)
|
||||||
|
#if ENABLE_OTA == 0
|
||||||
|
root["ota"] = "ARDUINO";
|
||||||
|
#endif
|
||||||
|
#if ENABLE_OTA == 1
|
||||||
|
root["ota"] = "HTTP";
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
root["ota"] = "OFF";
|
||||||
|
#endif
|
||||||
|
#if defined(ENABLE_STATE_SAVE)
|
||||||
|
root["state_save"] = "SPIFFS";
|
||||||
|
#else
|
||||||
|
root["state_save"] = "OFF";
|
||||||
|
#endif
|
||||||
|
uint16_t msg_len = measureJson(root) + 1;
|
||||||
|
char * buffer = (char *) malloc(msg_len);
|
||||||
|
serializeJson(root, buffer, msg_len);
|
||||||
|
jsonBuffer.clear();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
void getESPStateJSON() {
|
||||||
|
char * buffer = listESPStateJSON();
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "application/json", buffer);
|
||||||
|
free (buffer);
|
||||||
|
}
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
// Prototypes
|
||||||
|
uint16_t convertSpeed(uint8_t _mcl_speed);
|
||||||
|
uint32_t trans(uint32_t _newcolor, uint32_t _oldcolor, uint8_t _level, uint8_t _steps);
|
||||||
|
// End Prototypes
|
||||||
|
/*
|
||||||
|
Example of adding the example: https://github.com/kitesurfer1404/WS2812FX/blob/master/examples/ws2812fx_custom_FastLED/ws2812fx_custom_FastLED.ino
|
||||||
|
as a custom effect
|
||||||
|
|
||||||
|
More info on how to create custom aniamtions for WS2812FX: https://github.com/kitesurfer1404/WS2812FX/blob/master/extras/WS2812FX%20Users%20Guide.md#custom-effects
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint16_t handleSegmentOFF(void) {
|
||||||
|
WS2812FX::Segment* _seg = strip->getSegment();
|
||||||
|
return _seg->speed/(_seg->stop - _seg->start);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
// Function for automatic cycling
|
||||||
|
// ***************************************************************************
|
||||||
|
void handleAutoPlay(uint8_t _seg) {
|
||||||
|
//WS2812FX::Segment* _seg = strip->getSegment();
|
||||||
|
if (autoDelay[_seg] <= millis()) {
|
||||||
|
uint32_t _hex_colors[3] = {};
|
||||||
|
//if (_seg ==
|
||||||
|
_hex_colors[0] = autoParams[autoCount[_seg]][0];
|
||||||
|
_hex_colors[1] = autoParams[autoCount[_seg]][1];
|
||||||
|
_hex_colors[2] = autoParams[autoCount[_seg]][2];
|
||||||
|
//}
|
||||||
|
strip->setColors(_seg, _hex_colors);
|
||||||
|
strip->setSpeed(_seg, convertSpeed((uint16_t)autoParams[autoCount[_seg]][3]));
|
||||||
|
strip->setMode(_seg, (uint8_t)autoParams[autoCount[_seg]][4]);
|
||||||
|
//strip->trigger();
|
||||||
|
autoDelay[_seg] = millis() + (unsigned long)autoParams[autoCount[_seg]][5];
|
||||||
|
DBG_OUTPUT_PORT.printf("autoTick[%d][%d]: {0x%08x, 0x%08x, 0x%08x, %d, %d, %d}\r\n", _seg, autoCount[_seg], autoParams[autoCount[_seg]][0], autoParams[autoCount[_seg]][1], autoParams[autoCount[_seg]][2], autoParams[autoCount[_seg]][3], autoParams[autoCount[_seg]][4], autoParams[autoCount[_seg]][5]);
|
||||||
|
autoCount[_seg]++;
|
||||||
|
if (autoCount[_seg] >= (sizeof(autoParams) / sizeof(autoParams[0]))) autoCount[_seg] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t handleAuto(void) {
|
||||||
|
WS2812FX::Segment* _seg = strip->getSegment();
|
||||||
|
return _seg->speed/(_seg->stop - _seg->start);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t handleCustomWS(void) {
|
||||||
|
WS2812FX::Segment* _seg = strip->getSegment();
|
||||||
|
return _seg->speed/(_seg->stop - _seg->start);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CUSTOM_WS2812FX_ANIMATIONS)
|
||||||
|
// ***************************************************************************
|
||||||
|
// TV mode to be reviewed
|
||||||
|
// ***************************************************************************
|
||||||
|
uint16_t darkTime[10] = {250,250,250,250,250,250,250,250,250,250};
|
||||||
|
uint8_t dipInterval[10] = {10,10,10,10,10,10,10,10,10,10};
|
||||||
|
unsigned long dipStartTime[10] = {};
|
||||||
|
uint8_t ledState[10] = {LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW};
|
||||||
|
unsigned long previousMillis[10]= {0,0,0,0,0,0,0,0,0,0};
|
||||||
|
uint16_t interv[10] = {2000,2000,2000,2000,2000,2000,2000,2000,2000,2000};
|
||||||
|
uint8_t twitch[10]= {50,50,50,50,50,50,50,50,50,50};
|
||||||
|
uint8_t dipCount[10] = {0,0,0,0,0,0,0,0,0,0};
|
||||||
|
bool timeToDip[10] = {false,false,false,false,false,false,false,false,false,false};
|
||||||
|
|
||||||
|
|
||||||
|
void hsb2rgbAN1(uint16_t index, uint8_t sat, uint8_t bright, uint16_t led) {
|
||||||
|
// Source: https://blog.adafruit.com/2012/03/14/constant-brightness-hsb-to-rgb-algorithm/
|
||||||
|
uint8_t temp[5], n = (index >> 8) % 3;
|
||||||
|
temp[0] = temp[3] = (uint8_t)(( (sat ^ 255) * bright) / 255);
|
||||||
|
temp[1] = temp[4] = (uint8_t)((((( (index & 255) * sat) / 255) + (sat ^ 255)) * bright) / 255);
|
||||||
|
temp[2] = (uint8_t)(((((((index & 255) ^ 255) * sat) / 255) + (sat ^ 255)) * bright) / 255);
|
||||||
|
strip->setPixelColor(led, temp[n + 2], temp[n + 1], temp[n], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t handleTV(void) {
|
||||||
|
WS2812FX::Segment* _seg = strip->getSegment();
|
||||||
|
uint8_t _seg_num = strip->getSegmentIndex();
|
||||||
|
if (timeToDip[_seg_num] == false) {
|
||||||
|
if((millis() - previousMillis[_seg_num]) > interv[_seg_num]) {
|
||||||
|
previousMillis[_seg_num] = millis();
|
||||||
|
//interv = random(750,4001);//Adjusts the interval for more/less frequent random light changes
|
||||||
|
interv[_seg_num] = random(800-(512 - (_seg->speed/64)),6001-(2731 - (_seg->speed/24)));
|
||||||
|
twitch[_seg_num] = random(40,100);// Twitch provides motion effect but can be a bit much if too high
|
||||||
|
dipCount[_seg_num]++;
|
||||||
|
}
|
||||||
|
if((millis() - previousMillis[_seg_num]) < twitch[_seg_num]) {
|
||||||
|
uint16_t led=random(_seg->start, _seg->stop);
|
||||||
|
ledState[_seg_num] = ledState[_seg_num] == LOW ? HIGH : LOW; // if the LED is off turn it on and vice-versa:
|
||||||
|
ledstates[led] = ((ledState[_seg_num]) ? 255 : 0);
|
||||||
|
for (uint16_t j=_seg->start; j<=_seg->stop; j++) {
|
||||||
|
uint16_t index = (j%3 == 0) ? 400 : random(0,767);
|
||||||
|
hsb2rgbAN1(index, 200, ledstates[j], j);
|
||||||
|
}
|
||||||
|
if (dipCount[_seg_num] > dipInterval[_seg_num]) {
|
||||||
|
timeToDip[_seg_num] = true;
|
||||||
|
dipCount[_seg_num] = 0;
|
||||||
|
dipStartTime[_seg_num] = millis();
|
||||||
|
darkTime[_seg_num] = random(50,150);
|
||||||
|
dipInterval[_seg_num] = random(5,250);// cycles of flicker
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (millis() - dipStartTime[_seg_num] < darkTime[_seg_num]) {
|
||||||
|
for (uint16_t i = _seg->start; i <= _seg->stop; i++) {
|
||||||
|
ledstates[i] = 0;
|
||||||
|
for (uint16_t j=_seg->start; j<=_seg->stop; j++) {
|
||||||
|
uint16_t index = (j%3 == 0) ? 400 : random(0,767);
|
||||||
|
hsb2rgbAN1(index, 200, ledstates[j], j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
timeToDip[_seg_num] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _seg->speed/(_seg->stop - _seg->start);
|
||||||
|
}
|
||||||
|
// ***************************************************************************
|
||||||
|
// E1.31 mode
|
||||||
|
// ***************************************************************************
|
||||||
|
uint16_t handleE131(void) {
|
||||||
|
WS2812FX::Segment* _seg = strip->getSegment();
|
||||||
|
return _seg->speed/(_seg->stop - _seg->start);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleE131Play(void) {
|
||||||
|
if (!e131->isEmpty()) {
|
||||||
|
e131_packet_t packet;
|
||||||
|
e131->pull(&packet); // Pull packet from ring buffer
|
||||||
|
|
||||||
|
uint16_t universe = htons(packet.universe);
|
||||||
|
uint8_t *data = packet.property_values + 1;
|
||||||
|
|
||||||
|
if (universe < START_UNIVERSE || universe > END_UNIVERSE) return; //async will take care about filling the buffer
|
||||||
|
|
||||||
|
// Serial.printf("Universe %u / %u Channels | Packet#: %u / Errors: %u / CH1: %u\n",
|
||||||
|
// htons(packet.universe), // The Universe for this packet
|
||||||
|
// htons(packet.property_value_count) - 1, // Start code is ignored, we're interested in dimmer data
|
||||||
|
// e131.stats.num_packets, // Packet counter
|
||||||
|
// e131.stats.packet_errors, // Packet error counter
|
||||||
|
// packet.property_values[1]); // Dimmer data for Channel 1
|
||||||
|
/* #if defined(RGBW)
|
||||||
|
uint16_t multipacketOffset = (universe - START_UNIVERSE) * 128; //if more than 128 LEDs * 4 colors = 512 channels, client will send in next higher universe
|
||||||
|
if (Config.stripSize <= multipacketOffset) return _seg->speed/(_seg->stop - _seg->start);
|
||||||
|
uint16_t len = (128 + multipacketOffset > Config.stripSize) ? (Config.stripSize - multipacketOffset) : 128;
|
||||||
|
#else*/
|
||||||
|
uint16_t multipacketOffset = (universe - START_UNIVERSE) * 170; //if more than 170 LEDs * 3 colors = 510 channels, client will send in next higher universe
|
||||||
|
if (Config.stripSize <= multipacketOffset) return;
|
||||||
|
uint16_t len = (170 + multipacketOffset > Config.stripSize) ? (Config.stripSize - multipacketOffset) : 170;
|
||||||
|
/* #endif */
|
||||||
|
for (uint8_t k = 0; k < Config.segments; k++) {
|
||||||
|
if (segState.mode[k] == FX_MODE_CUSTOM_3) {
|
||||||
|
for (uint16_t i = 0; i < len; i++){
|
||||||
|
if ((i >= strip->getSegment(k)->start) && (i <= strip->getSegment(k)->stop)) {
|
||||||
|
uint16_t j = i * 3;
|
||||||
|
/* #if defined(RGBW)
|
||||||
|
strip->setPixelColor(i + multipacketOffset, data[j], data[j + 1], data[j + 2], data[j + 3]);
|
||||||
|
#else */
|
||||||
|
strip->setPixelColor(i + multipacketOffset, data[j], data[j + 1], data[j + 2], 0);
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* paste in the Fire2012 code with a small edit at the end which uses the
|
||||||
|
* setPixelColor() function to copy the color data to the ws2812fx instance.
|
||||||
|
*/
|
||||||
|
#include <FastLED.h> //https://github.com/FastLED/FastLED
|
||||||
|
// Fire2012 by Mark Kriegsman, July 2012
|
||||||
|
// as part of "Five Elements" shown here: http://youtu.be/knWiGsmgycY
|
||||||
|
////
|
||||||
|
// This basic one-dimensional 'fire' simulation works roughly as follows:
|
||||||
|
// There's a underlying array of 'heat' cells, that model the temperature
|
||||||
|
// at each point along the line. Every cycle through the simulation,
|
||||||
|
// four steps are performed:
|
||||||
|
// 1) All cells cool down a little bit, losing heat to the air
|
||||||
|
// 2) The heat from each cell drifts 'up' and diffuses a little
|
||||||
|
// 3) Sometimes randomly new 'sparks' of heat are added at the bottom
|
||||||
|
// 4) The heat from each cell is rendered as a color into the leds array
|
||||||
|
// The heat-to-color mapping uses a black-body radiation approximation.
|
||||||
|
//
|
||||||
|
// Temperature is in arbitrary units from 0 (cold black) to 255 (white hot).
|
||||||
|
//
|
||||||
|
// This simulation scales it self a bit depending on NUM_LEDS; it should look
|
||||||
|
// "OK" on anywhere from 20 to 100 LEDs without too much tweaking.
|
||||||
|
//
|
||||||
|
// I recommend running this simulation at anywhere from 30-100 frames per second,
|
||||||
|
// meaning an interframe delay of about 10-35 milliseconds.
|
||||||
|
//
|
||||||
|
// Looks best on a high-density LED setup (60+ pixels/meter).
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// There are two main parameters you can play with to control the look and
|
||||||
|
// feel of your fire: COOLING (used in step 1 above), and SPARKING (used
|
||||||
|
// in step 3 above).
|
||||||
|
//
|
||||||
|
// COOLING: How much does the air cool as it rises?
|
||||||
|
// Less cooling = taller flames. More cooling = shorter flames.
|
||||||
|
// Default 50, suggested range 20-100
|
||||||
|
#define COOLING 70
|
||||||
|
|
||||||
|
// SPARKING: What chance (out of 255) is there that a new spark will be lit?
|
||||||
|
// Higher chance = more roaring fire. Lower chance = more flickery fire.
|
||||||
|
// Default 120, suggested range 50-200.
|
||||||
|
#define SPARKING 120
|
||||||
|
|
||||||
|
uint16_t handleFire2012(void) {
|
||||||
|
// Array of temperature readings at each simulation cell
|
||||||
|
WS2812FX::Segment* _seg = strip->getSegment();
|
||||||
|
|
||||||
|
// Step 1. Cool down every cell a little
|
||||||
|
for( uint16_t i = _seg->start; i <= _seg->stop; i++) {
|
||||||
|
ledstates[i] = qsub8(ledstates[i], random8(0, ((COOLING * 10) / (_seg->stop - _seg->start)+1) + 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2. Heat from each cell drifts 'up' and diffuses a little
|
||||||
|
for( uint16_t k= _seg->stop; k >= (_seg->start + 2); k--) {
|
||||||
|
ledstates[k] = (ledstates[k - 1] + ledstates[k - 2] + ledstates[k - 2]) / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3. Randomly ignite new 'sparks' of heat near the bottom
|
||||||
|
if( random8() < SPARKING ) {
|
||||||
|
uint8_t y = random8(7) + _seg->start;
|
||||||
|
ledstates[y] = qadd8(ledstates[y], random8(160,255) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4. Map from heat cells to LED colors
|
||||||
|
for( uint16_t j = _seg->start; j <= _seg->stop; j++) {
|
||||||
|
CRGB color = HeatColor(ledstates[j]);
|
||||||
|
uint16_t pixel;
|
||||||
|
if ((_seg->options & 128) > 0) {
|
||||||
|
pixel = _seg->stop + (_seg->start - j);
|
||||||
|
} else {
|
||||||
|
pixel = j;
|
||||||
|
}
|
||||||
|
strip->setPixelColor(pixel, color.red, color.green, color.blue, 0);
|
||||||
|
}
|
||||||
|
return _seg->speed/(_seg->stop - _seg->start);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t handleGradient(void) {
|
||||||
|
WS2812FX::Segment* _seg = strip->getSegment();
|
||||||
|
for(uint16_t j = 0; j <= (_seg->stop - _seg->start); j++) {
|
||||||
|
uint16_t pixel;
|
||||||
|
if ((_seg->options & 128) > 0) {
|
||||||
|
pixel = _seg->stop - j;
|
||||||
|
} else {
|
||||||
|
pixel = _seg->start + j;
|
||||||
|
}
|
||||||
|
uint32_t color = trans(_seg->colors[1], _seg->colors[0], j, (_seg->stop - _seg->start));
|
||||||
|
strip->setPixelColor(pixel, ((color >> 16) & 0xFF), ((color >> 8) & 0xFF), ((color >> 0) & 0xFF), ((color >> 24) & 0xFF));
|
||||||
|
}
|
||||||
|
return _seg->speed/(_seg->stop - _seg->start);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
// ***************************************************************************
|
|
||||||
// TV mode
|
|
||||||
// ***************************************************************************
|
|
||||||
|
|
||||||
int dipInterval = 10;
|
|
||||||
int darkTime = 250;
|
|
||||||
unsigned long currentDipTime;
|
|
||||||
unsigned long dipStartTime;
|
|
||||||
unsigned long currentMillis;
|
|
||||||
int ledState = LOW;
|
|
||||||
long previousMillis = 0;
|
|
||||||
int led = 5;
|
|
||||||
int interval = 2000;
|
|
||||||
int twitch = 50;
|
|
||||||
int dipCount = 0;
|
|
||||||
int analogLevel = 100;
|
|
||||||
boolean timeToDip = false;
|
|
||||||
int ledStates[NUMLEDS];
|
|
||||||
|
|
||||||
|
|
||||||
void hsb2rgbAN1(uint16_t index, uint8_t sat, uint8_t bright, uint8_t myled) {
|
|
||||||
// Source: https://blog.adafruit.com/2012/03/14/constant-brightness-hsb-to-rgb-algorithm/
|
|
||||||
uint8_t temp[5], n = (index >> 8) % 3;
|
|
||||||
temp[0] = temp[3] = (uint8_t)(( (sat ^ 255) * bright) / 255);
|
|
||||||
temp[1] = temp[4] = (uint8_t)((((( (index & 255) * sat) / 255) + (sat ^ 255)) * bright) / 255);
|
|
||||||
temp[2] = (uint8_t)(((((((index & 255) ^ 255) * sat) / 255) + (sat ^ 255)) * bright) / 255);
|
|
||||||
strip.setPixelColor(myled, temp[n + 2], temp[n + 1], temp[n], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void updateLed (int led, int brightness) {
|
|
||||||
ledStates[led] = brightness;
|
|
||||||
for (int i=0; i<NUMLEDS; i++) {
|
|
||||||
uint16_t index = (i%3 == 0) ? 400 : random(0,767);
|
|
||||||
hsb2rgbAN1(index, 200, ledStates[i], i);
|
|
||||||
}
|
|
||||||
strip.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// See: http://forum.mysensors.org/topic/85/phoneytv-for-vera-is-here/13
|
|
||||||
void handleTV() {
|
|
||||||
if (timeToDip == false) {
|
|
||||||
currentMillis = millis();
|
|
||||||
if(currentMillis-previousMillis > interval) {
|
|
||||||
previousMillis = currentMillis;
|
|
||||||
//interval = random(750,4001);//Adjusts the interval for more/less frequent random light changes
|
|
||||||
interval = random(1000-(ws2812fx_speed*2),5001-(ws2812fx_speed*8));
|
|
||||||
twitch = random(40,100);// Twitch provides motion effect but can be a bit much if too high
|
|
||||||
dipCount = dipCount++;
|
|
||||||
}
|
|
||||||
if(currentMillis-previousMillis<twitch) {
|
|
||||||
led=random(0, (strip.numPixels()-1));
|
|
||||||
analogLevel=random(50,255);// set the range of the 3 pwm leds
|
|
||||||
ledState = ledState == LOW ? HIGH: LOW; // if the LED is off turn it on and vice-versa:
|
|
||||||
updateLed(led, (ledState) ? 255 : 0);
|
|
||||||
if (dipCount > dipInterval) {
|
|
||||||
DBG_OUTPUT_PORT.println("dip");
|
|
||||||
timeToDip = true;
|
|
||||||
dipCount = 0;
|
|
||||||
dipStartTime = millis();
|
|
||||||
darkTime = random(50,150);
|
|
||||||
dipInterval = random(5,250);// cycles of flicker
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DBG_OUTPUT_PORT.println("Dip Time");
|
|
||||||
currentDipTime = millis();
|
|
||||||
if (currentDipTime - dipStartTime < darkTime) {
|
|
||||||
for (int i=3; i<strip.numPixels(); i++) {
|
|
||||||
updateLed(i, 0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
timeToDip = false;
|
|
||||||
}
|
|
||||||
strip.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+868
-1112
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,515 @@
|
|||||||
|
// ***************************************************************************
|
||||||
|
// Setup: Webserver handler
|
||||||
|
// ***************************************************************************
|
||||||
|
//list directory
|
||||||
|
server.on("/list", HTTP_GET, handleFileList);
|
||||||
|
//create file
|
||||||
|
server.on("/edit", HTTP_PUT, handleFileCreate);
|
||||||
|
//delete file
|
||||||
|
server.on("/edit", HTTP_DELETE, handleFileDelete);
|
||||||
|
//first callback is called after the request has ended with all parsed arguments
|
||||||
|
//second callback handles file uploads at that location
|
||||||
|
server.on("/edit", HTTP_POST, []() {
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "text/plain", "");
|
||||||
|
}, handleFileUpload);
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
// Setup: SPIFFS Webserver handler
|
||||||
|
// ***************************************************************************
|
||||||
|
|
||||||
|
server.on("/", HTTP_GET, [&](){
|
||||||
|
#if defined(USE_HTML_MIN_GZ)
|
||||||
|
server.sendHeader("Content-Encoding", "gzip", true);
|
||||||
|
server.send_P(200, PSTR("text/html"), index_htm_gz, index_htm_gz_len);
|
||||||
|
#else
|
||||||
|
if (!handleFileRead(server.uri()))
|
||||||
|
handleNotFound();
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/material.woff2", HTTP_GET, [&](){
|
||||||
|
#if defined(USE_HTML_MIN_GZ)
|
||||||
|
server.send_P(200, PSTR("text/plain"), material_icons_woff2, material_icons_woff2_len);
|
||||||
|
#else
|
||||||
|
if (!handleFileRead(server.uri()))
|
||||||
|
handleNotFound();
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/favicon.ico", HTTP_GET, [&](){
|
||||||
|
#if defined(USE_HTML_MIN_GZ)
|
||||||
|
server.sendHeader("Content-Encoding", "gzip", true);
|
||||||
|
server.send_P(200, PSTR("text/plain"), fav_icon, fav_icon_len);
|
||||||
|
#else
|
||||||
|
if (!handleFileRead(server.uri()))
|
||||||
|
handleNotFound();
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/apple-touch-icon.png", HTTP_GET, [&](){
|
||||||
|
#if defined(USE_HTML_MIN_GZ)
|
||||||
|
server.send_P(200, PSTR("text/plain"), apple_touch_icon_png, apple_touch_icon_png_len);
|
||||||
|
#else
|
||||||
|
if (!handleFileRead(server.uri()))
|
||||||
|
handleNotFound();
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/edit", HTTP_GET, [&](){
|
||||||
|
#if defined(USE_HTML_MIN_GZ)
|
||||||
|
server.sendHeader("Content-Encoding", "gzip", true);
|
||||||
|
server.send_P(200, PSTR("text/html"), edit_htm_gz, edit_htm_gz_len);
|
||||||
|
#else
|
||||||
|
if (!handleFileRead("/edit.htm"))
|
||||||
|
handleNotFound();
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//called when the url is not defined here
|
||||||
|
//use it to load content from SPIFFS
|
||||||
|
server.onNotFound([]() {
|
||||||
|
if (!handleFileRead(server.uri()))
|
||||||
|
handleNotFound();
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/upload", handleMinimalUpload);
|
||||||
|
|
||||||
|
server.on("/esp_status", HTTP_GET, []() { //get heap status, analog input value and all GPIO statuses in one json call
|
||||||
|
getESPStateJSON();
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/restart", []() {
|
||||||
|
DBG_OUTPUT_PORT.printf("/restart\r\n");
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "text/plain", "restarting..." );
|
||||||
|
ESP.restart();
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/reset_wlan", []() {
|
||||||
|
DBG_OUTPUT_PORT.printf("/reset_wlan\r\n");
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "text/plain", "Resetting WLAN and restarting..." );
|
||||||
|
WiFiManager wifiManager;
|
||||||
|
wifiManager.resetSettings();
|
||||||
|
ESP.restart();
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/start_config_ap", []() {
|
||||||
|
DBG_OUTPUT_PORT.printf("/start_config_ap\r\n");
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "text/plain", "Starting config AP ..." );
|
||||||
|
WiFiManager wifiManager;
|
||||||
|
wifiManager.startConfigPortal(HOSTNAME);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/format_spiffs", []() {
|
||||||
|
DBG_OUTPUT_PORT.printf("/format_spiffs\r\n");
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "text/plain", "Formatting SPIFFS ..." );
|
||||||
|
SPIFFS.format();
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/get_brightness", []() {
|
||||||
|
char str_brightness[4];
|
||||||
|
snprintf(str_brightness, sizeof(str_brightness), "%i", (int) (State.brightness / 2.55));
|
||||||
|
str_brightness[sizeof(str_brightness) - 1] = 0x00;
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "text/plain", str_brightness );
|
||||||
|
DBG_OUTPUT_PORT.printf("/get_brightness: %i\r\n", (int) (State.brightness / 2.55));
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/get_speed", []() {
|
||||||
|
char str_speed[4];
|
||||||
|
snprintf(str_speed, sizeof(str_speed), "%i", segState.speed[State.segment]);
|
||||||
|
str_speed[sizeof(str_speed) - 1] = 0x00;
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "text/plain", str_speed );
|
||||||
|
DBG_OUTPUT_PORT.printf("/get_speed: %i\r\n", segState.speed[State.segment]);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/get_switch", []() {
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "text/plain", (State.mode == OFF) ? "0" : "1" );
|
||||||
|
DBG_OUTPUT_PORT.printf("/get_switch: %s\r\n", (State.mode == OFF) ? "0" : "1");
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/get_color", []() {
|
||||||
|
char rgbcolor[7];
|
||||||
|
snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X", main_color.red, main_color.green, main_color.blue);
|
||||||
|
rgbcolor[sizeof(rgbcolor) - 1] = 0x00;
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "text/plain", rgbcolor);
|
||||||
|
DBG_OUTPUT_PORT.print("/get_color: ");
|
||||||
|
DBG_OUTPUT_PORT.println(rgbcolor);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/get_color1", []() {
|
||||||
|
char rgbcolor[9];
|
||||||
|
snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", main_color.white, main_color.red, main_color.green, main_color.blue);
|
||||||
|
rgbcolor[sizeof(rgbcolor) - 1] = 0x00;
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "text/plain", rgbcolor );
|
||||||
|
DBG_OUTPUT_PORT.print("/get_color1: ");
|
||||||
|
DBG_OUTPUT_PORT.println(rgbcolor);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/get_color2", []() {
|
||||||
|
char rgbcolor[9];
|
||||||
|
snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", back_color.white, back_color.red, back_color.green, back_color.blue);
|
||||||
|
rgbcolor[sizeof(rgbcolor) - 1] = 0x00;
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "text/plain", rgbcolor );
|
||||||
|
DBG_OUTPUT_PORT.print("/get_color2: ");
|
||||||
|
DBG_OUTPUT_PORT.println(rgbcolor);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/get_color3", []() {
|
||||||
|
char rgbcolor[9];
|
||||||
|
snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", xtra_color.white, xtra_color.red, xtra_color.green, xtra_color.blue);
|
||||||
|
rgbcolor[sizeof(rgbcolor) - 1] = 0x00;
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "text/plain", rgbcolor );
|
||||||
|
DBG_OUTPUT_PORT.print("/get_color3: ");
|
||||||
|
DBG_OUTPUT_PORT.println(rgbcolor);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/get_modes", []() {
|
||||||
|
getModesJSON();
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/status", []() {
|
||||||
|
getStateJSON();
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/config", []() {
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
// This will be used later when web-interface is ready and HTTP_GET will not be allowed to update the Strip Settings
|
||||||
|
|
||||||
|
if(server.args() == 0 and server.method() != HTTP_POST)
|
||||||
|
{
|
||||||
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.send(200, "text/plain", "Only HTTP POST method is allowed and check the number of arguments!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
// ToDo do not save if no change
|
||||||
|
bool _updateStrip = false;
|
||||||
|
bool _updateConfig = false;
|
||||||
|
bool _updateState = false;
|
||||||
|
if(server.hasArg("ws_seg")){
|
||||||
|
uint8_t _ws_seg = server.arg("ws_seg").toInt();
|
||||||
|
_ws_seg = constrain(_ws_seg, 1, MAX_NUM_SEGMENTS - 1);
|
||||||
|
if (_ws_seg != Config.segments){
|
||||||
|
Config.segments = _ws_seg;
|
||||||
|
_updateStrip = true;
|
||||||
|
if (State.segment >= Config.segments) {
|
||||||
|
State.segment = Config.segments - 1;
|
||||||
|
_updateState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(server.hasArg("ws_cnt")){
|
||||||
|
uint16_t _stripSize = server.arg("ws_cnt").toInt();
|
||||||
|
if (_stripSize > 0) {
|
||||||
|
_stripSize = constrain(_stripSize, 1, MAXLEDS);
|
||||||
|
if (_stripSize != Config.stripSize) {
|
||||||
|
Config.stripSize = _stripSize;
|
||||||
|
_updateStrip = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(server.hasArg("ws_rgbo")){
|
||||||
|
char _ws_rgbo[5];
|
||||||
|
snprintf(_ws_rgbo, sizeof(_ws_rgbo), "%s", server.arg("ws_rgbo").c_str());
|
||||||
|
_ws_rgbo[sizeof(_ws_rgbo) - 1] = 0x00;
|
||||||
|
checkRGBOrder(_ws_rgbo);
|
||||||
|
_updateStrip = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(USE_WS2812FX_DMA)
|
||||||
|
if(server.hasArg("ws_pin")){
|
||||||
|
if (checkPin(server.arg("ws_pin").toInt())) {
|
||||||
|
_updateStrip = true;
|
||||||
|
DBG_OUTPUT_PORT.print("Pin was set to: ");
|
||||||
|
DBG_OUTPUT_PORT.println(Config.pin);
|
||||||
|
} else {
|
||||||
|
DBG_OUTPUT_PORT.println("invalid input or same value!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(_updateStrip) {
|
||||||
|
initStrip();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(server.hasArg("hostname")){
|
||||||
|
char _hostname[sizeof(HOSTNAME)];
|
||||||
|
snprintf(_hostname, sizeof(_hostname), "%s", server.arg("hostname").c_str());
|
||||||
|
_hostname[sizeof(_hostname) - 1] = 0x00;
|
||||||
|
if (strcmp(HOSTNAME, _hostname) != 0) {
|
||||||
|
strcpy(HOSTNAME, _hostname);
|
||||||
|
_updateConfig = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ENABLE_MQTT)
|
||||||
|
if(server.hasArg("mqtt_host")){
|
||||||
|
char _mqtt_host[sizeof(mqtt_host)];
|
||||||
|
snprintf(_mqtt_host, sizeof(_mqtt_host), "%s", server.arg("mqtt_host").c_str());
|
||||||
|
_mqtt_host[sizeof(_mqtt_host) - 1] = 0x00;
|
||||||
|
if (strcmp(mqtt_host, _mqtt_host) != 0) {
|
||||||
|
strcpy(mqtt_host, _mqtt_host);
|
||||||
|
_updateConfig = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(server.hasArg("mqtt_port")){
|
||||||
|
uint16_t _mqtt_port = constrain(server.arg("mqtt_port").toInt(), 1, 65535);
|
||||||
|
if (_mqtt_port != mqtt_port) {
|
||||||
|
mqtt_port = _mqtt_port;
|
||||||
|
_updateConfig = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(server.hasArg("mqtt_user")){
|
||||||
|
char _mqtt_user[sizeof(mqtt_user)];
|
||||||
|
snprintf(_mqtt_user, sizeof(_mqtt_user), "%s", server.arg("mqtt_user").c_str());
|
||||||
|
_mqtt_user[sizeof(mqtt_user) - 1] = 0x00;
|
||||||
|
if (strcmp(mqtt_user, _mqtt_user) != 0) {
|
||||||
|
strcpy(mqtt_user, _mqtt_user);
|
||||||
|
_updateConfig = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(server.hasArg("mqtt_pass")){
|
||||||
|
char _mqtt_pass[sizeof(mqtt_pass)];
|
||||||
|
snprintf(_mqtt_pass, sizeof(_mqtt_pass), "%s", server.arg("mqtt_pass").c_str());
|
||||||
|
_mqtt_pass[sizeof(_mqtt_pass) - 1] = 0x00;
|
||||||
|
if (strcmp(mqtt_pass, _mqtt_pass) != 0) {
|
||||||
|
strcpy(mqtt_pass, _mqtt_pass);
|
||||||
|
_updateConfig = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_updateConfig) {
|
||||||
|
initMqtt();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(server.hasArg("trans_effect")){
|
||||||
|
Config.transEffect = server.arg("trans_effect").toInt();
|
||||||
|
_updateConfig = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ENABLE_STATE_SAVE)
|
||||||
|
if (_updateStrip || _updateConfig) {
|
||||||
|
if(save_conf.active()) save_conf.detach();
|
||||||
|
save_conf.once(3, tickerSaveConfig);
|
||||||
|
}
|
||||||
|
if (_updateState) {
|
||||||
|
if(save_state.active()) save_state.detach();
|
||||||
|
save_state.once(3, tickerSaveState);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
_updateStrip = false;
|
||||||
|
_updateConfig = false;
|
||||||
|
_updateState = false;
|
||||||
|
getConfigJSON();
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/off", []() {
|
||||||
|
if (State.mode == OFF) { State.mode = SET; } else { State.mode = OFF; };
|
||||||
|
getACK("OK");
|
||||||
|
#if defined(ENABLE_STATE_SAVE)
|
||||||
|
if(save_state.active()) save_state.detach();
|
||||||
|
save_state.once(3, tickerSaveState);
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/on", []() {
|
||||||
|
if (prevmode == OFF) {
|
||||||
|
State.mode = SET;
|
||||||
|
getACK("OK");
|
||||||
|
#if defined(ENABLE_STATE_SAVE)
|
||||||
|
if(save_state.active()) save_state.detach();
|
||||||
|
save_state.once(3, tickerSaveState);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
getACK("NOK");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/set", []() {
|
||||||
|
prevmode = HOLD;
|
||||||
|
boolean _updateState = false;
|
||||||
|
boolean _updateSegState = false;
|
||||||
|
// Segment
|
||||||
|
if ((server.arg("seg") != "") && (server.arg("seg").toInt() >= 0) && (server.arg("seg").toInt() < Config.segments)) {
|
||||||
|
uint8_t _seg = server.arg("seg").toInt();
|
||||||
|
if (prevsegment != _seg) {
|
||||||
|
prevsegment = State.segment;
|
||||||
|
State.segment = _seg;
|
||||||
|
getSegmentParams(State.segment);
|
||||||
|
//memcpy(hexcolors_trans, segState.colors[State.segment], sizeof(hexcolors_trans));
|
||||||
|
State.mode = SET;
|
||||||
|
_updateState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((server.arg("start") != "") && (server.arg("start").toInt() >= 0) && (server.arg("start").toInt() <= segState.stop)) {
|
||||||
|
uint16_t _seg_start = server.arg("start").toInt();
|
||||||
|
_seg_start = constrain(segState.start, 0, Config.stripSize -1);
|
||||||
|
if (_seg_start != segState.start) {
|
||||||
|
segState.start = _seg_start;
|
||||||
|
setSegmentSize();
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((server.arg("stop") != "") && (server.arg("stop").toInt() >= segState.start) && (server.arg("stop").toInt() <= Config.stripSize)) {
|
||||||
|
uint16_t _seg_stop = server.arg("stop").toInt();
|
||||||
|
_seg_stop = constrain(_seg_stop, segState.start, Config.stripSize - 1);
|
||||||
|
if (_seg_stop != segState.stop) {
|
||||||
|
segState.stop = _seg_stop;
|
||||||
|
setSegmentSize();
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(server.hasArg("fxopt")){
|
||||||
|
uint8_t _fx_options = ((constrain(server.arg("fxopt").toInt(), 0, 255)>>1)<<1);
|
||||||
|
if (_fx_options != segState.options) {
|
||||||
|
segState.options = _fx_options;
|
||||||
|
strip->setOptions(State.segment, segState.options);
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//color wrgb
|
||||||
|
if (server.arg("rgb") != "") {
|
||||||
|
uint32_t rgb = (uint32_t) strtoul(server.arg("rgb").c_str(), NULL, 16);
|
||||||
|
main_color.white = ((rgb >> 24) & 0xFF);
|
||||||
|
main_color.red = ((rgb >> 16) & 0xFF);
|
||||||
|
main_color.green = ((rgb >> 8) & 0xFF);
|
||||||
|
main_color.blue = ((rgb >> 0) & 0xFF);
|
||||||
|
_updateSegState = true;
|
||||||
|
} else {
|
||||||
|
if ((server.arg("r") != "") && (server.arg("r").toInt() >= 0) && (server.arg("r").toInt() <= 255)) {
|
||||||
|
main_color.red = server.arg("r").toInt();
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
if ((server.arg("g") != "") && (server.arg("g").toInt() >= 0) && (server.arg("g").toInt() <= 255)) {
|
||||||
|
main_color.green = server.arg("g").toInt();
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
if ((server.arg("b") != "") && (server.arg("b").toInt() >= 0) && (server.arg("b").toInt() <= 255)) {
|
||||||
|
main_color.blue = server.arg("b").toInt();
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
if ((server.arg("w") != "") && (server.arg("w").toInt() >= 0) && (server.arg("w").toInt() <= 255)){
|
||||||
|
main_color.white = server.arg("w").toInt();
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (server.arg("rgb2") != "") {
|
||||||
|
uint32_t rgb2 = (uint32_t) strtoul(server.arg("rgb2").c_str(), NULL, 16);
|
||||||
|
back_color.white = ((rgb2 >> 24) & 0xFF);
|
||||||
|
back_color.red = ((rgb2 >> 16) & 0xFF);
|
||||||
|
back_color.green = ((rgb2 >> 8) & 0xFF);
|
||||||
|
back_color.blue = ((rgb2 >> 0) & 0xFF);
|
||||||
|
_updateSegState = true;
|
||||||
|
} else {
|
||||||
|
if ((server.arg("r2") != "") && (server.arg("r2").toInt() >= 0) && (server.arg("r2").toInt() <= 255)) {
|
||||||
|
back_color.red = server.arg("r2").toInt();
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
if ((server.arg("g2") != "") && (server.arg("g2").toInt() >= 0) && (server.arg("g2").toInt() <= 255)) {
|
||||||
|
back_color.green = server.arg("g2").toInt();
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
if ((server.arg("b2") != "") && (server.arg("b2").toInt() >= 0) && (server.arg("b2").toInt() <= 255)) {
|
||||||
|
back_color.blue = server.arg("b2").toInt();
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
if ((server.arg("w2") != "") && (server.arg("w2").toInt() >= 0) && (server.arg("w2").toInt() <= 255)){
|
||||||
|
back_color.white = server.arg("w2").toInt();
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (server.arg("rgb3") != "") {
|
||||||
|
uint32_t rgb3 = (uint32_t) strtoul(server.arg("rgb3").c_str(), NULL, 16);
|
||||||
|
xtra_color.white = ((rgb3 >> 24) & 0xFF);
|
||||||
|
xtra_color.red = ((rgb3 >> 16) & 0xFF);
|
||||||
|
xtra_color.green = ((rgb3 >> 8) & 0xFF);
|
||||||
|
xtra_color.blue = ((rgb3 >> 0) & 0xFF);
|
||||||
|
_updateSegState = true;
|
||||||
|
} else {
|
||||||
|
if ((server.arg("r3") != "") && (server.arg("r3").toInt() >= 0) && (server.arg("r3").toInt() <= 255)) {
|
||||||
|
xtra_color.red = server.arg("r3").toInt();
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
if ((server.arg("g3") != "") && (server.arg("g3").toInt() >= 0) && (server.arg("g3").toInt() <= 255)) {
|
||||||
|
xtra_color.green = server.arg("g3").toInt();
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
if ((server.arg("b3") != "") && (server.arg("b3").toInt() >= 0) && (server.arg("b3").toInt() <= 255)) {
|
||||||
|
xtra_color.blue = server.arg("b3").toInt();
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
if ((server.arg("w3") != "") && (server.arg("w3").toInt() >= 0) && (server.arg("w3").toInt() <= 255)){
|
||||||
|
xtra_color.white = server.arg("w3").toInt();
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
main_color.red = constrain(main_color.red, 0, 255);
|
||||||
|
main_color.green = constrain(main_color.green, 0, 255);
|
||||||
|
main_color.blue = constrain(main_color.blue, 0, 255);
|
||||||
|
main_color.white = constrain(main_color.white, 0, 255);
|
||||||
|
back_color.red = constrain(back_color.red, 0, 255);
|
||||||
|
back_color.green = constrain(back_color.green, 0, 255);
|
||||||
|
back_color.blue = constrain(back_color.blue, 0, 255);
|
||||||
|
back_color.white = constrain(back_color.white, 0, 255);
|
||||||
|
xtra_color.red = constrain(xtra_color.red, 0, 255);
|
||||||
|
xtra_color.green = constrain(xtra_color.green, 0, 255);
|
||||||
|
xtra_color.blue = constrain(xtra_color.blue, 0, 255);
|
||||||
|
xtra_color.white = constrain(xtra_color.white, 0, 255);
|
||||||
|
|
||||||
|
|
||||||
|
// Speed
|
||||||
|
if ((server.arg("s") != "") && (server.arg("s").toInt() >= 0) && (server.arg("s").toInt() <= 255)) {
|
||||||
|
segState.speed[State.segment] = constrain(server.arg("s").toInt(), 0, 255);
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
//Mode
|
||||||
|
if ((server.arg("m") != "") && (server.arg("m").toInt() >= 0) && (server.arg("m").toInt() <= strip->getModeCount())) {
|
||||||
|
fx_mode = constrain(server.arg("m").toInt(), 0, strip->getModeCount() - 1);
|
||||||
|
if (fx_mode != segState.mode[State.segment]) {
|
||||||
|
_updateSegState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Brightness
|
||||||
|
if ((server.arg("c") != "") && (server.arg("c").toInt() >= 0) && (server.arg("c").toInt() <= 100)) {
|
||||||
|
State.brightness = constrain((int) server.arg("c").toInt() * 2.55, 0, 255);
|
||||||
|
} else if ((server.arg("p") != "") && (server.arg("p").toInt() >= 0) && (server.arg("p").toInt() <= 255)) {
|
||||||
|
State.brightness = constrain(server.arg("p").toInt(), 0, 255);
|
||||||
|
}
|
||||||
|
if (strip->getBrightness() != State.brightness) {
|
||||||
|
State.mode = SET;
|
||||||
|
_updateState = true;
|
||||||
|
}
|
||||||
|
//DBG_OUTPUT_PORT.printf("Get Args: %s\r\n", listStateJSONfull()); //possibly causing heap problems
|
||||||
|
getACK("OK");
|
||||||
|
|
||||||
|
#if defined(ENABLE_STATE_SAVE)
|
||||||
|
if (_updateState) {
|
||||||
|
if(save_state.active()) save_state.detach();
|
||||||
|
save_state.once(3, tickerSaveState);
|
||||||
|
}
|
||||||
|
if (_updateSegState) {
|
||||||
|
State.mode = SET;
|
||||||
|
if(save_seg_state.active()) save_seg_state.detach();
|
||||||
|
save_seg_state.once(3, tickerSaveSegmentState);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
_updateState = false;
|
||||||
|
_updateSegState = false;
|
||||||
|
});
|
||||||
@@ -70,6 +70,9 @@ bool handleFileRead(String path) {
|
|||||||
path += ".gz";
|
path += ".gz";
|
||||||
File file = SPIFFS.open(path, "r");
|
File file = SPIFFS.open(path, "r");
|
||||||
server.sendHeader("Access-Control-Allow-Origin", "*");
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||||
|
server.sendHeader("Pragma", "no-cache");
|
||||||
|
server.sendHeader("Expires", "-1");
|
||||||
size_t sent = server.streamFile(file, contentType);
|
size_t sent = server.streamFile(file, contentType);
|
||||||
file.close();
|
file.close();
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define SKETCH_VERSION "2.2.0.rgbw.3c"
|
#define SKETCH_VERSION "3.1.0"
|
||||||
|
|||||||
@@ -56,13 +56,205 @@
|
|||||||
* 23 Dec 2018 v 2.2.0
|
* 23 Dec 2018 v 2.2.0
|
||||||
* - Add E1.31 mode to getModes(), no need to change McLightingUI
|
* - Add E1.31 mode to getModes(), no need to change McLightingUI
|
||||||
*
|
*
|
||||||
* 6 Jan 2018 v 2.2.0
|
* 6 Jan 2019 v 2.2.0
|
||||||
* - fix webserver not responding when E1.31 is mode is acivated: do a webserver.loop() for every 1.31 packet
|
* - fix webserver not responding when E1.31 is mode is acivated: do a webserver.loop() for every 1.31 packet
|
||||||
* - HA E1.31 mode added
|
* - HA E1.31 mode added
|
||||||
*
|
*
|
||||||
* 15 Feb 2018 v 2.2.0 rgbw 3colors
|
* 15 Feb 2019 v 2.2.0 rgbw 3colors
|
||||||
* - Code cleanup
|
* - Code cleanup
|
||||||
* - Implemented support for back- and xtra-color
|
* - Implemented support for back- and xtra-color
|
||||||
* - Implemented IR remote control
|
* - Implemented IR remote control
|
||||||
* - Remove some string data types (to be continued)
|
* - Remove some string data types (to be continued)
|
||||||
|
*
|
||||||
|
* 08 Mar 2018 v 2.2.1 rgbw 3colors
|
||||||
|
* - checkForRequests() is not needed
|
||||||
|
* - Minor fixes related to NeoPixelBus UART methods
|
||||||
|
* - Modify platformio.ini for future bump to esp8266-arduino v2.5.0 (shamelessly stolen settings from espurna project)
|
||||||
|
* - Gzipped index.htm & edit.htm, convereted to hex format using xxd -i abcd.gz > html_gz.h
|
||||||
|
* - Pointers added for WS2812FX & NeoPixelBus
|
||||||
|
* - new "REST API": /config?ws_cnt=xxx to change length of LED strip
|
||||||
|
* - new "REST API": /config?ws_rgbo=xxx to change RGB order
|
||||||
|
* - new "REST API": /config?ws_pin=GPIO_NO to change PIN# (Allowed GPIO values: 16/5/4/0/2/14/12/13/15/3/1) if not used DMA or UART. Otherwise it is ignored
|
||||||
|
* - added HA 0.87 version support https://github.com/toblum/McLighting/issues/327
|
||||||
|
* - Added alternative way to send large messages using PubSubClient
|
||||||
|
* - Bump PIO core to 2.0.4
|
||||||
|
* - Send HA state on MQTT connect, address https://github.com/toblum/McLighting/issues/349
|
||||||
|
* - Add LWT for MQTT and AMQTT, address https://github.com/toblum/McLighting/issues/340
|
||||||
|
* - Added file for custom WS2812FX animations in custom slots
|
||||||
|
* - Rename variables to be char instead of String
|
||||||
|
* - Added LED pixel count and PIN settings to WiFiManager
|
||||||
|
* - Gamma correction to LEDs via ws_fxopts
|
||||||
|
*
|
||||||
|
* 10 Mar 2019 v 2.2.2 rgbw 3colors
|
||||||
|
* - integraded neoconfig.json into config.json
|
||||||
|
* - Add compiler flag for WS2811 strips #define LED_TYPE_WS2811
|
||||||
|
* - new "REST API": /config?hostname=xxx to change hostname
|
||||||
|
* - new "REST API": /config?mqtt_host=xxx to change mqtt hostname
|
||||||
|
* - new "REST API": /config?mqtt_port=xxx to change mqtt port
|
||||||
|
* - new "REST API": /config?mqtt_user=xxx to change mqtt username
|
||||||
|
* - new "REST API": /config?mqtt_pass=xxx to change mqtt password
|
||||||
|
* - new "REST API": /config?ws_fxopt=xxx to change ws2812fx options
|
||||||
|
* - Pointers added for PubSubClient & AMQTTCLient
|
||||||
|
* - RGBOrder is now stored human readable not as integer
|
||||||
|
* - Bugfix on Fire 2012 animation as one variable was destroyed
|
||||||
|
*
|
||||||
|
* 15 Mar 2019 v 2.2.2 rgbw 3colors
|
||||||
|
* websocket commands
|
||||||
|
* # Set Maincolor
|
||||||
|
* ## Set Back color
|
||||||
|
* ### Set xtra Color
|
||||||
|
* ? Set speed
|
||||||
|
* % Set brightness
|
||||||
|
* * Set all
|
||||||
|
* ! Set single LED
|
||||||
|
* + Set multiple LEDs
|
||||||
|
* R Set Range
|
||||||
|
* = Set named Mode (legacy)
|
||||||
|
* $ Get Status
|
||||||
|
* new from here
|
||||||
|
* C Get Config
|
||||||
|
* Ch Set hostname
|
||||||
|
* Cmh Set mqtt hostname
|
||||||
|
* Cmp Set mqtt port
|
||||||
|
* Cmu Set mqtt username
|
||||||
|
* Cmw Set mqtt password
|
||||||
|
* Csc Set Strip LED count
|
||||||
|
* Csr Set Strip RGB Order
|
||||||
|
* Csp Set Strip pin
|
||||||
|
* Cso Set Strip FX Options
|
||||||
|
* to here
|
||||||
|
* ~ Get Modes
|
||||||
|
* / Set modes
|
||||||
|
*
|
||||||
|
* 17 Mar 2019
|
||||||
|
* adressed issue: #2
|
||||||
|
* adressed issue: #3
|
||||||
|
*
|
||||||
|
* 18 Mar 2019
|
||||||
|
* adressed issue: #6 (possibly affects R[r_start][r_end][hexrgb] [...]; +[numled][hexrgb]+[numled][hexrgb]+[numled][hexrgb] !<numled><hexrgb>)
|
||||||
|
*
|
||||||
|
* 19 Mar 2019
|
||||||
|
* included custom mode in UI
|
||||||
|
* adressed issue #4
|
||||||
|
*
|
||||||
|
* Version Bump to 2.2.3 rgbw 3colors
|
||||||
|
* PubSubClient Bug fixes
|
||||||
|
* Reverted Pointers for MQTT for the moment
|
||||||
|
*
|
||||||
|
* 21 Mar 2019
|
||||||
|
* Bugfixes
|
||||||
|
* added pointer for MQTT again
|
||||||
|
* Removed some String datatype and replaced with char array
|
||||||
|
* better responsiveness in ui for sliders
|
||||||
|
*
|
||||||
|
* 26 Mar 2019
|
||||||
|
* Bugfixes
|
||||||
|
*
|
||||||
|
* 19 May 2019
|
||||||
|
* Bugfixes regarding MQTT Hostname
|
||||||
|
*
|
||||||
|
* 08 September 2019
|
||||||
|
* Version Bump to 2.2.5 rgbw 3colors
|
||||||
|
* adressed issue: #27
|
||||||
|
* adressed issue: #28 (see new REST-API documentation)
|
||||||
|
*
|
||||||
|
* 10 September 2019
|
||||||
|
* Version Bump to 2.2.6 rgbw 3colors
|
||||||
|
* adressed issue: #28 (see new REST-API documentation) again
|
||||||
|
* adressed issue: #26
|
||||||
|
* adressed issue: #31
|
||||||
|
* adressed issue: #32
|
||||||
|
*
|
||||||
|
* 15 September 2019
|
||||||
|
* Version Bump to 2.2.7.BETA1.rgbw.3colors
|
||||||
|
* adressed issue: #25 (added Custom Animation 'Gradient' with number 57)
|
||||||
|
* adressed issue: #30 (Status 'AUTO' is saved now)
|
||||||
|
* adressed issue: https://github.com/toblum/McLighting/issues/403 (Experimental Support of transitions: set transEffect = true in definitions.h)
|
||||||
|
* corrected use of DMA for Neopixelbus by Makuna (Tests for other strips than SK6812 GRBW were not made)
|
||||||
|
*
|
||||||
|
* 27 September 2019
|
||||||
|
* Version Bump to 3.0.0.ALPHA1
|
||||||
|
* removed LEGACY_ANIMATIONS
|
||||||
|
* removed old Custom Animations from beginning of list.
|
||||||
|
* added Custom Animation 'AutoPlay' with number 56
|
||||||
|
* added Custom Animation 'Custom WS' with number 57
|
||||||
|
* added Custom Animation 'TV' with number 58
|
||||||
|
* added Custom Animation 'E1.31' with number 59
|
||||||
|
* moved Custom Animation 'Fire2012' to number 60
|
||||||
|
* moved Custom Animation 'Gradients' to number 61
|
||||||
|
* REST-API changes (will be documented soon)
|
||||||
|
*
|
||||||
|
* 29 September 2019
|
||||||
|
* Version Bump to 3.0.0.BETA1
|
||||||
|
* further code changes
|
||||||
|
* bugfixes
|
||||||
|
*
|
||||||
|
* 30 September 2019
|
||||||
|
* Version Bump to 3.1.0.ALPHA1
|
||||||
|
* further code changes
|
||||||
|
* removal of saving to EEPROM
|
||||||
|
* first integration of multi segments
|
||||||
|
*
|
||||||
|
* 3 October 2019
|
||||||
|
* Version Bump to 3.1.0.ALPHA2
|
||||||
|
* further code changes
|
||||||
|
* further integration of multi segments
|
||||||
|
* integration of multi segments to GUI
|
||||||
|
*
|
||||||
|
* 5 October 2019
|
||||||
|
* Version Bump to 3.1.0.ALPHA2
|
||||||
|
* further code changes
|
||||||
|
* further integration of multi segments
|
||||||
|
* known problem: as always: AUTOPLAY (as it is not multi segment capable yet)
|
||||||
|
*
|
||||||
|
* 07 October
|
||||||
|
* Version Bump to 3.1.0.BETA1
|
||||||
|
* bugfixes
|
||||||
|
* adressed issue: #39 uncooment //#define ENABLE_MQTT_INCLUDE_IP in defninitions.h
|
||||||
|
*
|
||||||
|
* 09 October
|
||||||
|
* Version Bump to 3.1.0.BETA2
|
||||||
|
* bugfixes
|
||||||
|
* implemented https://github.com/FabLab-Luenen/McLighting/commit/589806d0fda737011426754a6d84c88535ded688
|
||||||
|
*
|
||||||
|
* 20 October
|
||||||
|
* Version Bump to 3.1.0.BETA3
|
||||||
|
* Bugfixes
|
||||||
|
* adressed issue: #39
|
||||||
|
*
|
||||||
|
* 25 October
|
||||||
|
* Version Bump to 3.1.0.BETA4
|
||||||
|
* Bugfixes
|
||||||
|
* Made GUI fully offline compatible (included material icons, etc.)
|
||||||
|
* After Timeout (#define WIFIMGR_PORTAL_TIMEOUT 180) in definitions.h Config Portal is closed and MCL is usable over own AP @192.168.4.1
|
||||||
|
* adressed issue: #48
|
||||||
|
* known problems: E1.31 is only working for one segment at the moment
|
||||||
|
*
|
||||||
|
* 26 October
|
||||||
|
* Version Bump to 3.1.0.BETA5
|
||||||
|
* adressed issue: #44
|
||||||
|
* known problems:
|
||||||
|
* Homeassistant will allways use active segment
|
||||||
|
* E1.31 is only working for one segment at the moment
|
||||||
|
*
|
||||||
|
* 09 December
|
||||||
|
* Version Bump to 3.1.0.BETA6
|
||||||
|
* bugfixes for IR remote control
|
||||||
|
* Implemented segments to IR Remote
|
||||||
|
* Power supply update
|
||||||
|
* bugfix for Button definitions as speed and brightness were interchanged
|
||||||
|
* adressed issue #59
|
||||||
|
* known problems:
|
||||||
|
* Homeassistant will allways use active segment
|
||||||
|
* E1.31 is only working for one segment at the moment
|
||||||
|
*
|
||||||
|
* 27 January 2020
|
||||||
|
* Version Bump to 3.1.0.BETA7
|
||||||
|
* small API changes
|
||||||
|
* work to solve heap problems
|
||||||
|
*
|
||||||
|
* 23 February 2020
|
||||||
|
* Version Bump to 3.1.0
|
||||||
|
* bugfixes
|
||||||
|
* E1.31 is now working for multi segments
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# McLighting v2 - The ESP8266 based multi-client lighting gadget
|
# McLighting v3 - The ESP8266 based multi-client lighting gadget
|
||||||
|
|
||||||
[](https://gitter.im/mclighting/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [](https://travis-ci.com/toblum/McLighting) [](https://opensource.org/licenses/MIT) [](https://github.com/toblum/McLighting/blob/master/Arduino/McLighting/version.h)
|
[](https://gitter.im/mclighting/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [](https://travis-ci.com/toblum/McLighting) [](https://opensource.org/licenses/MIT) [](https://github.com/FabLab-Luenen/McLighting/blob/master/Arduino/McLighting/version.h)
|
||||||
|
|
||||||
McLighting (the multi-client lighting gadget) is a very cheap internet-controllable lighting solution based on the famous ESP8266 microcontroller and WS2811/2812 led strips. It features among other things a web-interface, a REST-API and a websocket connector.
|
McLighting (the multi-client lighting gadget) is a very cheap internet-controllable lighting solution based on the famous ESP8266 microcontroller and WS2811/2812 led strips. It features among other things a web-interface, a REST-API and a websocket connector.
|
||||||
|
|
||||||
@@ -33,17 +33,23 @@ again in out wiki: [Software installation](../../wiki/Software-installation)
|
|||||||
|
|
||||||
This project uses libraries and code by different authors:
|
This project uses libraries and code by different authors:
|
||||||
|
|
||||||
- [WiFiManager](https://github.com/tzapu/WiFiManager) by tzapu (tested with version 0.12.0)
|
- [WiFiManager](https://github.com/tzapu/WiFiManager) by tzapu (tested with version 0.15.0)
|
||||||
|
|
||||||
- [WS2812FX](https://github.com/kitesurfer1404/WS2812FX) by kitesurfer1404 (tested with version downloaded 2017-02-05)
|
- [WS2812FX](https://github.com/kitesurfer1404/WS2812FX) by kitesurfer1404 (tested with version 1.2.1)
|
||||||
|
|
||||||
- [WebSockets](https://github.com/Links2004/arduinoWebSockets) by Links2004 (tested with version 2.0.6)
|
- [WebSockets](https://github.com/Links2004/arduinoWebSockets) by Links2004 (tested with version 2.1.4)
|
||||||
|
|
||||||
- [Adafruit NeoPixel](https://github.com/adafruit/Adafruit_NeoPixel) by adafruit (tested with 1.1.2)
|
- [Adafruit NeoPixel](https://github.com/adafruit/Adafruit_NeoPixel) by adafruit (tested with 1.2.5)
|
||||||
|
|
||||||
- Optional: [PubSubClient](https://github.com/knolleary/pubsubclient/) by knolleary (tested with 2.6.0)
|
- Optional: [PubSubClient](https://github.com/knolleary/pubsubclient/) by knolleary (tested with 2.7.0)
|
||||||
_Only when you have activated MQTT in definitions.h._
|
_Only when you have activated MQTT in definitions.h._
|
||||||
|
|
||||||
|
- Optional: [Brzo I2C](https://github.com/pasko-zh/brzo_i2c/) by pazko-zh (tested with 1.3.3)
|
||||||
|
_Only when you have activated GY33 in definitions.h._
|
||||||
|
|
||||||
|
- Optional: [FastLed](https://github.com/FastLED/FastLED/) by FastLED (tested with 1.3.3)
|
||||||
|
_Only when you have activated custom animations (Fire2012) in definitions.h._
|
||||||
|
|
||||||
The sketch also uses the following built-in library:
|
The sketch also uses the following built-in library:
|
||||||
- Ticker by [@igrr](https://github.com/igrr)
|
- Ticker by [@igrr](https://github.com/igrr)
|
||||||
|
|
||||||
@@ -60,20 +66,29 @@ I hope I didn't miss any sources and mentioned every author. In case I forgot so
|
|||||||
|
|
||||||
|
|
||||||
## Todos
|
## Todos
|
||||||
- [ ] Support multiple strips and control them separately or together [Issue](https://github.com/toblum/McLighting/issues/118)
|
- [ ] Redesign of Code and bump to V3
|
||||||
- [ ] Make number of pixels, MQTT and PIN configurable via front end [Issue](https://github.com/toblum/McLighting/issues/93) and [Issue](https://github.com/toblum/McLighting/issues/93)
|
|
||||||
- [ ] Bundle webpages instead of SPIFFS [Issue](https://github.com/toblum/McLighting/issues/93)
|
|
||||||
- [ ] Remove old / wrong EEPROM settings completely [Issue]
|
|
||||||
- [ ] Customer profile to define segments of (in)active areas on the strip [Issue](https://github.com/toblum/McLighting/issues/37)
|
- [ ] Customer profile to define segments of (in)active areas on the strip [Issue](https://github.com/toblum/McLighting/issues/37)
|
||||||
- [ ] Additional clients
|
- [ ] Additional clients
|
||||||
- [ ] If no wifi, at least enable button mode.
|
- [x] If no wifi, at least enable button mode.
|
||||||
- [ ] Also enable McLighting in Wifi AP mode.
|
- [x] Also enable McLighting in Wifi AP mode.
|
||||||
- [ ] IR remote support [issue](https://github.com/toblum/McLightingUI/issues/3)
|
- [ ] Search a non-blocking alternative for wifiManager
|
||||||
- [ ] Multiple buttons/GPIO Inputs. [Issue](https://github.com/toblum/McLighting/issues/119)
|
- [ ] Multiple buttons/GPIO Inputs. [Issue](https://github.com/toblum/McLighting/issues/119)
|
||||||
- [ ] Music visualizer / Bring back ArtNet [Issue](https://github.com/toblum/McLighting/issues/111)
|
- [ ] Music visualizer / Bring back ArtNet [Issue](https://github.com/toblum/McLighting/issues/111)
|
||||||
- [ ] Display version and parameters (Number of LEDs, definition settings, ..) in the web UI [Issue](https://github.com/toblum/McLighting/issues/150)
|
- [ ] Display version and parameters (Number of LEDs, definition settings, ..) in the web UI [Issue](https://github.com/toblum/McLighting/issues/150)
|
||||||
|
- [x] Remove old / wrong EEPROM settings completely [Issue] EEPROM saving discarded
|
||||||
|
- [x] Support multiple strips and control them separately or together [Issue](https://github.com/toblum/McLighting/issues/118)
|
||||||
|
- [x] Support for up to ten segments
|
||||||
|
- [x] Removal of LEGACY_ANIMATIONS
|
||||||
|
- [x] Include ws2812fx library to code due to modifications in library
|
||||||
|
- [x] Add TV, E1.31 and AUTO to CUSTOM_WS2812FX_ANIMATIONS
|
||||||
|
- [x] Save status: Added saving of status 'AUTO'. [Issue](https://github.com/FabLab-Luenen/McLighting/issues/30)
|
||||||
|
- [x] EXPERIMENTAL: Added transition feature on changing values of color brightness and speed. ATTENTION! Does not work properly for all WS2812fx effects. Can be set via UI or REST-API.
|
||||||
|
- [x] Added Custom Animation 'Gradient': [Issue](https://github.com/FabLab-Luenen/McLighting/issues/25)
|
||||||
|
- [x] Make number of pixels, MQTT and PIN configurable via front end [Issue](https://github.com/toblum/McLighting/issues/93) and [Issue](https://github.com/toblum/McLighting/issues/101)
|
||||||
|
- [x] Bundle webpages instead of SPIFFS [Issue](https://github.com/toblum/McLighting/issues/93)
|
||||||
|
- [x] IR remote support [issue](https://github.com/toblum/McLightingUI/issues/3)
|
||||||
- [x] MQTT support
|
- [x] MQTT support
|
||||||
- [x] Save favourite effects? [Issue](https://github.com/toblum/McLighting/issues/35)(https://github.com/toblum/McLighting/issues/101)
|
- [x] Save favourite effects? [Issue](https://github.com/toblum/McLighting/issues/35)
|
||||||
- [x] OTA update [Issue](https://github.com/toblum/McLighting/issues/92)
|
- [x] OTA update [Issue](https://github.com/toblum/McLighting/issues/92)
|
||||||
- [x] Fix issue with websockets connection problems
|
- [x] Fix issue with websockets connection problems
|
||||||
- [x] Switch to the [NeoPixelBus library](https://github.com/Makuna/NeoPixelBus/wiki)
|
- [x] Switch to the [NeoPixelBus library](https://github.com/Makuna/NeoPixelBus/wiki)
|
||||||
|
|||||||
@@ -64,10 +64,16 @@ light:
|
|||||||
- "Bicolor Chase"
|
- "Bicolor Chase"
|
||||||
- "Tricolor Chase"
|
- "Tricolor Chase"
|
||||||
- "ICU"
|
- "ICU"
|
||||||
- "E131"
|
- "AutoPlay"
|
||||||
|
- "Custom WS"
|
||||||
|
- "TV"
|
||||||
|
- "E1.31"
|
||||||
|
- "Fire(2012)"
|
||||||
|
- "Gradient"
|
||||||
brightness: true
|
brightness: true
|
||||||
color_temp: true
|
color_temp: true
|
||||||
rgb: true
|
rgb: true
|
||||||
|
white_value: true
|
||||||
optimistic: false
|
optimistic: false
|
||||||
qos: 0
|
qos: 0
|
||||||
retain: true
|
retain: true
|
||||||
|
|||||||
@@ -16,18 +16,18 @@
|
|||||||
|
|
||||||
"switch": {
|
"switch": {
|
||||||
"status": "http://<ESP_HOST>/get_switch",
|
"status": "http://<ESP_HOST>/get_switch",
|
||||||
"powerOn": "http://<ESP_HOST>/all?r=255&g=255&b=255",
|
"powerOn": "http://<ESP_HOST>/on",
|
||||||
"powerOff": "http://<ESP_HOST>/off"
|
"powerOff": "http://<ESP_HOST>/off"
|
||||||
},
|
},
|
||||||
|
|
||||||
"brightness": {
|
"brightness": {
|
||||||
"status": "http://<ESP_HOST>/get_brightness",
|
"status": "http://<ESP_HOST>/get_brightness",
|
||||||
"url": "http://<ESP_HOST>/set_brightness?c=%s"
|
"url": "http://<ESP_HOST>/set?c=%s"
|
||||||
},
|
},
|
||||||
|
|
||||||
"color": {
|
"color": {
|
||||||
"status": "http://<ESP_HOST>/get_color",
|
"status": "http://<ESP_HOST>/get_color",
|
||||||
"url": "http://<ESP_HOST>/all?rgb=%s",
|
"url": "http://<ESP_HOST>/set?m=0?rgb=00%s",
|
||||||
"brightness": true
|
"brightness": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,491 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!--Import Google Icon Font-->
|
|
||||||
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
||||||
<!--Import materialize.css-->
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css" media="screen,projection" />
|
|
||||||
|
|
||||||
<!--Let browser know website is optimized for mobile-->
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
|
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
|
||||||
<title>McLighting (RGBW) v2</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<nav class="blue light-blueXXX lighten-1XXX" role="navigation" id="mc-nav">
|
|
||||||
<div class="nav-wrapper container">
|
|
||||||
<a id="logo-container" href="#" class="brand-logo">McLighting (RGBW) v2</a>
|
|
||||||
|
|
||||||
<ul class="right hide-on-med-and-down">
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane1">Wheel</a></li>
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane2">Modes</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul id="nav-mobile" class="side-nav">
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane1">Wheel</a></li>
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane2">Modes</a></li>
|
|
||||||
</ul>
|
|
||||||
<a href="#" data-activates="nav-mobile" class="button-collapse"><i class="material-icons">menu</i></a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div class="container mc_pane" id="pane0">
|
|
||||||
<div class="section">
|
|
||||||
<div class="row" id="mc-wsloader">
|
|
||||||
<div class="col">
|
|
||||||
<div class="preloader-wrapper active">
|
|
||||||
<div class="spinner-layer spinner-blue-only">
|
|
||||||
<div class="circle-clipper left">
|
|
||||||
<div class="circle"></div>
|
|
||||||
</div>
|
|
||||||
<div class="gap-patch">
|
|
||||||
<div class="circle"></div>
|
|
||||||
</div>
|
|
||||||
<div class="circle-clipper right">
|
|
||||||
<div class="circle"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row hide" id="mc-wserror">
|
|
||||||
<div class="col">
|
|
||||||
<div>Error on websocket connect.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container mc_pane hide" id="pane1">
|
|
||||||
<div class="section">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col s12 m6">
|
|
||||||
<div style="height: 330px; width: 330px;">
|
|
||||||
<canvas id="myCanvas" width="330" height="330" style="-webkit-user-select: none;-webkit-tap-highlight-color: rgba(0,0,0,0);-moz-user-select:none;"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col s12 m6">
|
|
||||||
<div class="card-panel" id="status">
|
|
||||||
<div id="status_pos">pick a color</div>
|
|
||||||
<div id="status_color"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col s12 m6">
|
|
||||||
<div class="right switch">Auto:<br>
|
|
||||||
<label>Off
|
|
||||||
<input id="autoSwitch" type="checkbox"><span class="lever"></span>On
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container mc_pane hide" id="pane2">
|
|
||||||
<div class="section">
|
|
||||||
<div class="row">
|
|
||||||
<form class="col s12">
|
|
||||||
<div class="row">
|
|
||||||
<div class="input-field col s12 l4">
|
|
||||||
<label for="txt_red">Red</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_red" min="0" max="255" class="update_colors" /></p>
|
|
||||||
</div>
|
|
||||||
<div class="input-field col s12 l4">
|
|
||||||
<label for="txt_green">Green</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_green" min="0" max="255" class="update_colors" /></p>
|
|
||||||
</div>
|
|
||||||
<div class="input-field col s12 l4">
|
|
||||||
<label for="txt_blue">Blue</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_blue" min="0" max="255" class="update_colors" /></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="input-field col s12">
|
|
||||||
<label for="txt_white">White</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_white" min="0" max="255" class="update_colors" /></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="input-field col s12">
|
|
||||||
<label for="txt_delay">Speed</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_delay" min="0" max="255" value="196" class="update_delay" /></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="input-field col s12">
|
|
||||||
<label for="txt_delay">Brightness</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_brightness" min="0" max="255" value="196" class="update_brightness" /></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div id="modes">
|
|
||||||
<div class="input-field col s12">
|
|
||||||
Loading animations...
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<footer class="page-footer blue">
|
|
||||||
<div class="footer-copyright">
|
|
||||||
<div class="container">© 2017
|
|
||||||
<a class="grey-text text-lighten-4 right" href="https://github.com/toblum/McLighting">Project home</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<style type="text/css">
|
|
||||||
.btn_grid {
|
|
||||||
margin: 7px 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<!--Import jQuery before materialize.js-->
|
|
||||||
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
|
|
||||||
<script type="text/javascript">(function($){
|
|
||||||
$(function(){
|
|
||||||
|
|
||||||
// Settings
|
|
||||||
var host = window.location.hostname;
|
|
||||||
//host = "esp8266_02.local";
|
|
||||||
|
|
||||||
var ws_url = 'ws://' + host + ':81';
|
|
||||||
var connection;
|
|
||||||
var ws_waiting = 0;
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// Side navigation
|
|
||||||
// ******************************************************************
|
|
||||||
$('.button-collapse').sideNav();
|
|
||||||
|
|
||||||
// Navlinks
|
|
||||||
$('#mc-nav').on('click', '.mc-navlink', function(){
|
|
||||||
console.log("Navigate to pane: ", $(this).data("pane"));
|
|
||||||
showPane($(this).data("pane"));
|
|
||||||
});
|
|
||||||
|
|
||||||
function showPane(pane) {
|
|
||||||
$('.mc_pane').addClass('hide');
|
|
||||||
$('#' + pane).removeClass('hide');
|
|
||||||
$('.button-collapse').sideNav('hide');
|
|
||||||
|
|
||||||
//if (pane == "pane2") {
|
|
||||||
// setMainColor();
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// init()
|
|
||||||
// ******************************************************************
|
|
||||||
function init() {
|
|
||||||
console.log("Connection websockets to:", ws_url);
|
|
||||||
connection = new WebSocket(ws_url, ['arduino']);
|
|
||||||
var mode = 0;
|
|
||||||
var ws2812fx_mode = 0;
|
|
||||||
$.getJSON("http://" + host + "/status", function(data) {
|
|
||||||
console.log("status", data);
|
|
||||||
mode = data.mode;
|
|
||||||
if (mode == "1") {
|
|
||||||
// set autoswitch $("#autoSwitch").val('checked');
|
|
||||||
}
|
|
||||||
ws2812fx_mode = data.ws2812fx_mode;
|
|
||||||
$("#rng_delay").val(data.speed);
|
|
||||||
$("#rng_brightness").val(data.brightness);
|
|
||||||
$("#rng_white").val(data.color[0]);
|
|
||||||
$("#rng_red").val(data.color[1]);
|
|
||||||
$("#rng_green").val(data.color[2]);
|
|
||||||
$("#rng_blue").val(data.color[3]);
|
|
||||||
var statusColor = "#" + componentToHex(data.color[1]) + componentToHex(data.color[2]) + componentToHex(data.color[3]);
|
|
||||||
$('#status').css("backgroundColor", statusColor);
|
|
||||||
$('#status_color').text(statusColor + "- R=" + data.color[1] + ", G=" + data.color[2] + ", B=" + data.color[3]);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Load modes async
|
|
||||||
// List of all color modes
|
|
||||||
// enum MODE {OFF, AUTO, TV, E131, SET_MODE, HOLD, CUSTOM, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW};
|
|
||||||
$.getJSON("http://" + host + "/get_modes", function(data) {
|
|
||||||
console.log("modes", data);
|
|
||||||
var modes_html = "";
|
|
||||||
data.forEach(function(current_mode){
|
|
||||||
if (current_mode.mode !== undefined) {
|
|
||||||
modes_html += '<div class="col s12 m6 l6 btn_grid">';
|
|
||||||
if ((mode == "5" && current_mode.mode == ws2812fx_mode) || (mode == "0" && current_mode.mode == "off") || (mode == "2" && current_mode.mode == "tv") || (mode == "3" && current_mode.mode == "e131")){
|
|
||||||
modes_html += '<a class="btn waves-effect waves-light btn_mode red" name="action" data-mode="' + current_mode.mode + '">(' + current_mode.mode +') '+ current_mode.name;
|
|
||||||
} else {
|
|
||||||
modes_html += '<a class="btn waves-effect waves-light btn_mode blue" name="action" data-mode="' + current_mode.mode + '">(' + current_mode.mode +') '+ current_mode.name;
|
|
||||||
}
|
|
||||||
modes_html += '<i class="material-icons right">send</i>';
|
|
||||||
modes_html += '</a>';
|
|
||||||
modes_html += '</div>';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#modes').html(modes_html);
|
|
||||||
});
|
|
||||||
// When the connection is open, send some data to the server
|
|
||||||
connection.onopen = function () {
|
|
||||||
//connection.send('Ping'); // Send the message 'Ping' to the server
|
|
||||||
console.log('WebSocket Open');
|
|
||||||
showPane('pane1');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Log errors
|
|
||||||
connection.onerror = function (error) {
|
|
||||||
console.log('WebSocket Error ' + error);
|
|
||||||
$('#mc-wsloader').addClass('hide');
|
|
||||||
$('#mc-wserror').removeClass('hide');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Log messages from the server
|
|
||||||
connection.onmessage = function (e) {
|
|
||||||
console.log('WebSocket from server: ' + e.data);
|
|
||||||
ws_waiting = 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// Modes
|
|
||||||
// ******************************************************************
|
|
||||||
$("#pane2").on("click", ".btn_mode", function() {
|
|
||||||
var mode = $(this).attr("data-mode");
|
|
||||||
last_mode = mode;
|
|
||||||
var btn = $(this);
|
|
||||||
setMode(mode, function() {
|
|
||||||
$(".btn_mode, .btn_mode_static").removeClass("red").addClass("blue");
|
|
||||||
btn.removeClass("blue").addClass("red");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#pane2").on("click", ".btn_mode_static", function() {
|
|
||||||
var mode = $(this).attr("data-mode");
|
|
||||||
var btn = $(this);
|
|
||||||
|
|
||||||
wsSendCommand("=" + mode);
|
|
||||||
$(".btn_mode, .btn_mode_static").removeClass("red").addClass("blue");
|
|
||||||
btn.removeClass("blue").addClass("red");
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#pane2").on("change", ".update_colors", setMainColor);
|
|
||||||
|
|
||||||
$("#pane2").on("change", ".update_delay", function() {
|
|
||||||
var delay = $("#rng_delay").val();
|
|
||||||
|
|
||||||
wsSendCommand("?" + delay);
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#pane2").on("change", ".update_brightness", function() {
|
|
||||||
var brightness = $("#rng_brightness").val();
|
|
||||||
|
|
||||||
wsSendCommand("%" + brightness);
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#autoSwitch").on("change", function () {
|
|
||||||
if ($(this).prop('checked')) {
|
|
||||||
wsSendCommand("start");
|
|
||||||
} else {
|
|
||||||
wsSendCommand("stop");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function setMode(mode, finish_funtion) {
|
|
||||||
console.log("Mode: ", mode);
|
|
||||||
|
|
||||||
wsSendCommand("/" + mode);
|
|
||||||
finish_funtion();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setMainColor() {
|
|
||||||
var white = $("#rng_white").val();
|
|
||||||
var red = $("#rng_red").val();
|
|
||||||
var green = $("#rng_green").val();
|
|
||||||
var blue = $("#rng_blue").val();
|
|
||||||
|
|
||||||
var hexColor = componentToHex(white) + componentToHex(red) + componentToHex(green) + componentToHex(blue);
|
|
||||||
var statusColor = "#" + componentToHex(red) + componentToHex(green) + componentToHex(blue);
|
|
||||||
wsSetMainColor(hexColor);
|
|
||||||
$('#status').css("backgroundColor", statusColor);
|
|
||||||
$('#status_color').text(statusColor + "- R=" + red + ", G=" + green + ", B=" + blue);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// WebSocket commands
|
|
||||||
// ******************************************************************
|
|
||||||
function wsSendCommand(cmd) {
|
|
||||||
console.log("Send WebSocket command:", cmd);
|
|
||||||
if (ws_waiting == 0) {
|
|
||||||
connection.send(cmd);
|
|
||||||
ws_waiting++;
|
|
||||||
} else {
|
|
||||||
console.log("++++++++ WS call waiting, skip")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function wsSetAll(hexColor) {
|
|
||||||
console.log("wsSetAll() Set all colors to:", hexColor);
|
|
||||||
wsSendCommand("*" + hexColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
function wsSetMainColor(hexColor) {
|
|
||||||
console.log("wsSetMainColor() Set main colors to:", hexColor);
|
|
||||||
wsSendCommand("#" + hexColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// Colorwheel
|
|
||||||
// ******************************************************************
|
|
||||||
// this is supposed to work on mobiles (touch) as well as on a desktop (click)
|
|
||||||
// since we couldn't find a decent one .. this try of writing one by myself
|
|
||||||
// + google. swiping would be really nice - I will possibly implement it with
|
|
||||||
// jquery later - or never.
|
|
||||||
|
|
||||||
var canvas = document.getElementById("myCanvas");
|
|
||||||
// FIX: Cancel touch end event and handle click via touchstart
|
|
||||||
// canvas.addEventListener("touchend", function(e) { e.preventDefault(); }, false);
|
|
||||||
canvas.addEventListener("touchmove", doTouch, false);
|
|
||||||
canvas.addEventListener("click", doClick, false);
|
|
||||||
//canvas.addEventListener("mousemove", doClick, false);
|
|
||||||
|
|
||||||
|
|
||||||
var context = canvas.getContext('2d');
|
|
||||||
var centerX = canvas.width / 2;
|
|
||||||
var centerY = canvas.height / 2;
|
|
||||||
var innerRadius = canvas.width / 4.5;
|
|
||||||
var outerRadius = (canvas.width - 10) / 2
|
|
||||||
|
|
||||||
//outer border
|
|
||||||
context.beginPath();
|
|
||||||
//outer circle
|
|
||||||
context.arc(centerX, centerY, outerRadius, 0, 2 * Math.PI, false);
|
|
||||||
//draw the outer border: (gets drawn around the circle!)
|
|
||||||
context.lineWidth = 4;
|
|
||||||
context.strokeStyle = '#000000';
|
|
||||||
context.stroke();
|
|
||||||
context.closePath();
|
|
||||||
|
|
||||||
//fill with beautiful colors
|
|
||||||
//taken from here: http://stackoverflow.com/questions/18265804/building-a-color-wheel-in-html5
|
|
||||||
for(var angle=0; angle<=360; angle+=1) {
|
|
||||||
var startAngle = (angle-2)*Math.PI/180;
|
|
||||||
var endAngle = angle * Math.PI/180;
|
|
||||||
context.beginPath();
|
|
||||||
context.moveTo(centerX, centerY);
|
|
||||||
context.arc(centerX, centerY, outerRadius, startAngle, endAngle, false);
|
|
||||||
context.closePath();
|
|
||||||
context.fillStyle = 'hsl('+angle+', 100%, 50%)';
|
|
||||||
context.fill();
|
|
||||||
context.closePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
//inner border
|
|
||||||
context.beginPath();
|
|
||||||
//context.arc(centerX, centerY, radius, startAngle, endAngle, counterClockwise);
|
|
||||||
context.arc(centerX, centerY, innerRadius, 0, 2 * Math.PI, false);
|
|
||||||
//fill the center
|
|
||||||
var my_gradient=context.createLinearGradient(0,0,170,0);
|
|
||||||
my_gradient.addColorStop(0,"black");
|
|
||||||
my_gradient.addColorStop(1,"white");
|
|
||||||
|
|
||||||
context.fillStyle = my_gradient;
|
|
||||||
context.fillStyle = "white";
|
|
||||||
context.fill();
|
|
||||||
|
|
||||||
//draw the inner line
|
|
||||||
context.lineWidth = 2;
|
|
||||||
context.strokeStyle = '#000000';
|
|
||||||
context.stroke();
|
|
||||||
context.closePath();
|
|
||||||
|
|
||||||
//get Mouse x/y canvas position
|
|
||||||
function getMousePos(canvas, evt) {
|
|
||||||
var rect = canvas.getBoundingClientRect();
|
|
||||||
return {
|
|
||||||
x: evt.clientX - rect.left,
|
|
||||||
y: evt.clientY - rect.top
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//comp to Hex
|
|
||||||
function componentToHex(c) {
|
|
||||||
//var hex = c.toString(16);
|
|
||||||
//return hex.length == 1 ? "0" + hex : hex;
|
|
||||||
return ("0"+(Number(c).toString(16))).slice(-2).toUpperCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
//rgb/rgba to Hex
|
|
||||||
function rgbToHex(rgb) {
|
|
||||||
return componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//display the touch/click position and color info
|
|
||||||
function updateStatus(pos, color) {
|
|
||||||
//var hexColor = rgbToHex(color);
|
|
||||||
//wsSetAll(hexColor);
|
|
||||||
var hexColor = componentToHex(color[0]) + componentToHex(color[1]) + componentToHex(color[2]);
|
|
||||||
wsSetMainColor(hexColor);
|
|
||||||
hexColor = "#" + hexColor;
|
|
||||||
|
|
||||||
$('#status').css("backgroundColor", hexColor);
|
|
||||||
$('#status_color').text(hexColor + " - R=" + color[0] + ", G=" + color[1] + ", B=" + color[2]);
|
|
||||||
$('#status_pos').text("x: " + pos.x + " - y: " + pos.y);
|
|
||||||
|
|
||||||
$("#rng_white").val(0);
|
|
||||||
$("#rng_red").val(color[0]);
|
|
||||||
$("#rng_green").val(color[1]);
|
|
||||||
$("#rng_blue").val(color[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//handle the touch event
|
|
||||||
function doTouch(event) {
|
|
||||||
//to not also fire on click
|
|
||||||
event.preventDefault();
|
|
||||||
var el = event.target;
|
|
||||||
|
|
||||||
//touch position
|
|
||||||
var pos = {x: Math.round(event.targetTouches[0].pageX - el.offsetLeft),
|
|
||||||
y: Math.round(event.targetTouches[0].pageY - el.offsetTop)};
|
|
||||||
//color
|
|
||||||
var color = context.getImageData(pos.x, pos.y, 1, 1).data;
|
|
||||||
|
|
||||||
updateStatus(pos, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
function doClick(event) {
|
|
||||||
//click position
|
|
||||||
var pos = getMousePos(canvas, event);
|
|
||||||
//color
|
|
||||||
var color = context.getImageData(pos.x, pos.y, 1, 1).data;
|
|
||||||
|
|
||||||
//console.log("click", pos.x, pos.y, color);
|
|
||||||
updateStatus(pos, color);
|
|
||||||
|
|
||||||
//now do sth with the color rgbToHex(color);
|
|
||||||
//don't do stuff when #000000 (outside circle and lines
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// main
|
|
||||||
// ******************************************************************
|
|
||||||
init();
|
|
||||||
|
|
||||||
}); // end of document ready
|
|
||||||
})(jQuery); // end of jQuery name space</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
var gulp = require('gulp'),
|
|
||||||
request = require('request'),
|
|
||||||
fs = require('fs'),
|
|
||||||
connect = require('gulp-connect'),
|
|
||||||
fileinclude = require('gulp-file-include');
|
|
||||||
|
|
||||||
var src_dir = "src/";
|
|
||||||
var build_dir = "build/";
|
|
||||||
|
|
||||||
|
|
||||||
gulp.task('html', function() {
|
|
||||||
gulp.src(src_dir + '*.htm')
|
|
||||||
.pipe(fileinclude({
|
|
||||||
prefix: '@@',
|
|
||||||
basepath: '@file'
|
|
||||||
}))
|
|
||||||
.pipe(gulp.dest('build'))
|
|
||||||
.pipe(connect.reload());
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
gulp.task('connect', function() {
|
|
||||||
connect.server({
|
|
||||||
root: 'build',
|
|
||||||
livereload: true
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('watch', function() {
|
|
||||||
gulp.watch(src_dir + '*.htm', ['html']);
|
|
||||||
gulp.watch(src_dir + 'js/*.js', ['html']);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
gulp.task('upload', ['html'], function() {
|
|
||||||
var url = 'http://192.168.0.49/edit';
|
|
||||||
var options = {
|
|
||||||
url: url,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'multipart/form-data'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var r = request.post(options, function optionalCallback(err, httpResponse, body) {
|
|
||||||
if (err) {
|
|
||||||
return console.error('upload failed:', err);
|
|
||||||
}
|
|
||||||
console.log('Upload successful! Server responded with:', body);
|
|
||||||
});
|
|
||||||
var form = r.form();
|
|
||||||
form.append('data', fs.createReadStream(__dirname + "/" + build_dir + '/index.htm'), {filename: '/index.htm', contentType: "application/octet-stream"});
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('default', ['html']);
|
|
||||||
gulp.task('serve', ['watch', 'connect']);
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "mc_lighting",
|
|
||||||
"version": "2.0.0",
|
|
||||||
"description": "Web client for Mc Lighting",
|
|
||||||
"main": "index.html",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"author": "Tobias Blum",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"fs": "0.0.2",
|
|
||||||
"gulp": "^3.9.1",
|
|
||||||
"gulp-connect": "^5.0.0",
|
|
||||||
"gulp-file-include": "^1.0.0",
|
|
||||||
"request": "^2.72.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!--Import Google Icon Font-->
|
|
||||||
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
||||||
<!--Import materialize.css-->
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css" media="screen,projection" />
|
|
||||||
|
|
||||||
<!--Let browser know website is optimized for mobile-->
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
|
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
|
||||||
<title>McLighting (RGBW) v2</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<nav class="blue light-blueXXX lighten-1XXX" role="navigation" id="mc-nav">
|
|
||||||
<div class="nav-wrapper container">
|
|
||||||
<a id="logo-container" href="#" class="brand-logo">McLighting (RGBW) v2</a>
|
|
||||||
|
|
||||||
<ul class="right hide-on-med-and-down">
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane1">Wheel</a></li>
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane2">Modes</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul id="nav-mobile" class="side-nav">
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane1">Wheel</a></li>
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane2">Modes</a></li>
|
|
||||||
</ul>
|
|
||||||
<a href="#" data-activates="nav-mobile" class="button-collapse"><i class="material-icons">menu</i></a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div class="container mc_pane" id="pane0">
|
|
||||||
<div class="section">
|
|
||||||
<div class="row" id="mc-wsloader">
|
|
||||||
<div class="col">
|
|
||||||
<div class="preloader-wrapper active">
|
|
||||||
<div class="spinner-layer spinner-blue-only">
|
|
||||||
<div class="circle-clipper left">
|
|
||||||
<div class="circle"></div>
|
|
||||||
</div>
|
|
||||||
<div class="gap-patch">
|
|
||||||
<div class="circle"></div>
|
|
||||||
</div>
|
|
||||||
<div class="circle-clipper right">
|
|
||||||
<div class="circle"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row hide" id="mc-wserror">
|
|
||||||
<div class="col">
|
|
||||||
<div>Error on websocket connect.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container mc_pane hide" id="pane1">
|
|
||||||
<div class="section">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col s12 m6">
|
|
||||||
<div style="height: 330px; width: 330px;">
|
|
||||||
<canvas id="myCanvas" width="330" height="330" style="-webkit-user-select: none;-webkit-tap-highlight-color: rgba(0,0,0,0);-moz-user-select:none;"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col s12 m6">
|
|
||||||
<div class="card-panel" id="status">
|
|
||||||
<div id="status_pos">pick a color</div>
|
|
||||||
<div id="status_color"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col s12 m6">
|
|
||||||
<div class="right switch">Auto:<br>
|
|
||||||
<label>Off
|
|
||||||
<input id="autoSwitch" type="checkbox"><span class="lever"></span>On
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container mc_pane hide" id="pane2">
|
|
||||||
<div class="section">
|
|
||||||
<div class="row">
|
|
||||||
<form class="col s12">
|
|
||||||
<div class="row">
|
|
||||||
<div class="input-field col s12 l4">
|
|
||||||
<label for="txt_red">Red</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_red" min="0" max="255" class="update_colors" /></p>
|
|
||||||
</div>
|
|
||||||
<div class="input-field col s12 l4">
|
|
||||||
<label for="txt_green">Green</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_green" min="0" max="255" class="update_colors" /></p>
|
|
||||||
</div>
|
|
||||||
<div class="input-field col s12 l4">
|
|
||||||
<label for="txt_blue">Blue</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_blue" min="0" max="255" class="update_colors" /></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="input-field col s12">
|
|
||||||
<label for="txt_white">White</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_white" min="0" max="255" class="update_colors" /></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="input-field col s12">
|
|
||||||
<label for="txt_delay">Speed</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_delay" min="0" max="255" value="196" class="update_delay" /></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="input-field col s12">
|
|
||||||
<label for="txt_delay">Brightness</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_brightness" min="0" max="255" value="196" class="update_brightness" /></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div id="modes">
|
|
||||||
<div class="input-field col s12">
|
|
||||||
Loading animations...
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<footer class="page-footer blue">
|
|
||||||
<div class="footer-copyright">
|
|
||||||
<div class="container">© 2017
|
|
||||||
<a class="grey-text text-lighten-4 right" href="https://github.com/toblum/McLighting">Project home</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<style type="text/css">
|
|
||||||
.btn_grid {
|
|
||||||
margin: 7px 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<!--Import jQuery before materialize.js-->
|
|
||||||
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
|
|
||||||
<script type="text/javascript">@@include('js/script.js')</script>
|
|
||||||
</body>
|
|
||||||
\ No newline at end of file
|
|
||||||
</html>
|
|
||||||
@@ -1,331 +0,0 @@
|
|||||||
(function($){
|
|
||||||
$(function(){
|
|
||||||
|
|
||||||
// Settings
|
|
||||||
var host = window.location.hostname;
|
|
||||||
//host = "esp8266_02.local";
|
|
||||||
|
|
||||||
var ws_url = 'ws://' + host + ':81';
|
|
||||||
var connection;
|
|
||||||
var ws_waiting = 0;
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// Side navigation
|
|
||||||
// ******************************************************************
|
|
||||||
$('.button-collapse').sideNav();
|
|
||||||
|
|
||||||
// Navlinks
|
|
||||||
$('#mc-nav').on('click', '.mc-navlink', function(){
|
|
||||||
console.log("Navigate to pane: ", $(this).data("pane"));
|
|
||||||
showPane($(this).data("pane"));
|
|
||||||
});
|
|
||||||
|
|
||||||
function showPane(pane) {
|
|
||||||
$('.mc_pane').addClass('hide');
|
|
||||||
$('#' + pane).removeClass('hide');
|
|
||||||
$('.button-collapse').sideNav('hide');
|
|
||||||
|
|
||||||
//if (pane == "pane2") {
|
|
||||||
// setMainColor();
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// init()
|
|
||||||
// ******************************************************************
|
|
||||||
function init() {
|
|
||||||
console.log("Connection websockets to:", ws_url);
|
|
||||||
connection = new WebSocket(ws_url, ['arduino']);
|
|
||||||
var mode = 0;
|
|
||||||
var ws2812fx_mode = 0;
|
|
||||||
$.getJSON("http://" + host + "/status", function(data) {
|
|
||||||
console.log("status", data);
|
|
||||||
mode = data.mode;
|
|
||||||
ws2812fx_mode = data.ws2812fx_mode;
|
|
||||||
$("#rng_delay").val(data.speed);
|
|
||||||
$("#rng_brightness").val(data.brightness);
|
|
||||||
$("#rng_white").val(data.color[0]);
|
|
||||||
$("#rng_red").val(data.color[1]);
|
|
||||||
$("#rng_green").val(data.color[2]);
|
|
||||||
$("#rng_blue").val(data.color[3]);
|
|
||||||
var statusColor = "#" + componentToHex(data.color[1]) + componentToHex(data.color[2]) + componentToHex(data.color[3]);
|
|
||||||
$('#status').css("backgroundColor", statusColor);
|
|
||||||
$('#status_color').text(statusColor + "- R=" + data.color[1] + ", G=" + data.color[2] + ", B=" + data.color[3]);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Load modes async
|
|
||||||
// List of all color modes
|
|
||||||
// enum MODE {OFF, AUTO, TV, E131, SET_MODE, HOLD, CUSTOM, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW};
|
|
||||||
$.getJSON("http://" + host + "/get_modes", function(data) {
|
|
||||||
console.log("modes", data);
|
|
||||||
var modes_html = "";
|
|
||||||
data.forEach(function(current_mode){
|
|
||||||
if (current_mode.mode !== undefined) {
|
|
||||||
modes_html += '<div class="col s12 m6 l6 btn_grid">';
|
|
||||||
if ((mode == "5" && current_mode.mode == ws2812fx_mode) || (mode == "0" && current_mode.mode == "off") || (mode == "2" && current_mode.mode == "tv") || (mode == "3" && current_mode.mode == "e131")){
|
|
||||||
modes_html += '<a class="btn waves-effect waves-light btn_mode red" name="action" data-mode="' + current_mode.mode + '">(' + current_mode.mode +') '+ current_mode.name;
|
|
||||||
} else {
|
|
||||||
modes_html += '<a class="btn waves-effect waves-light btn_mode blue" name="action" data-mode="' + current_mode.mode + '">(' + current_mode.mode +') '+ current_mode.name;
|
|
||||||
}
|
|
||||||
modes_html += '<i class="material-icons right">send</i>';
|
|
||||||
modes_html += '</a>';
|
|
||||||
modes_html += '</div>';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#modes').html(modes_html);
|
|
||||||
});
|
|
||||||
// When the connection is open, send some data to the server
|
|
||||||
connection.onopen = function () {
|
|
||||||
//connection.send('Ping'); // Send the message 'Ping' to the server
|
|
||||||
console.log('WebSocket Open');
|
|
||||||
showPane('pane1');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Log errors
|
|
||||||
connection.onerror = function (error) {
|
|
||||||
console.log('WebSocket Error ' + error);
|
|
||||||
$('#mc-wsloader').addClass('hide');
|
|
||||||
$('#mc-wserror').removeClass('hide');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Log messages from the server
|
|
||||||
connection.onmessage = function (e) {
|
|
||||||
console.log('WebSocket from server: ' + e.data);
|
|
||||||
ws_waiting = 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// Modes
|
|
||||||
// ******************************************************************
|
|
||||||
$("#pane2").on("click", ".btn_mode", function() {
|
|
||||||
var mode = $(this).attr("data-mode");
|
|
||||||
last_mode = mode;
|
|
||||||
var btn = $(this);
|
|
||||||
setMode(mode, function() {
|
|
||||||
$(".btn_mode, .btn_mode_static").removeClass("red").addClass("blue");
|
|
||||||
btn.removeClass("blue").addClass("red");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#pane2").on("click", ".btn_mode_static", function() {
|
|
||||||
var mode = $(this).attr("data-mode");
|
|
||||||
var btn = $(this);
|
|
||||||
|
|
||||||
wsSendCommand("=" + mode);
|
|
||||||
$(".btn_mode, .btn_mode_static").removeClass("red").addClass("blue");
|
|
||||||
btn.removeClass("blue").addClass("red");
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#pane2").on("change", ".update_colors", setMainColor);
|
|
||||||
|
|
||||||
$("#pane2").on("change", ".update_delay", function() {
|
|
||||||
var delay = $("#rng_delay").val();
|
|
||||||
|
|
||||||
wsSendCommand("?" + delay);
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#pane2").on("change", ".update_brightness", function() {
|
|
||||||
var brightness = $("#rng_brightness").val();
|
|
||||||
|
|
||||||
wsSendCommand("%" + brightness);
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#autoSwitch").on("change", function () {
|
|
||||||
if ($(this).prop('checked')) {
|
|
||||||
wsSendCommand("start");
|
|
||||||
} else {
|
|
||||||
wsSendCommand("stop");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function setMode(mode, finish_funtion) {
|
|
||||||
console.log("Mode: ", mode);
|
|
||||||
|
|
||||||
wsSendCommand("/" + mode);
|
|
||||||
finish_funtion();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setMainColor() {
|
|
||||||
var white = $("#rng_white").val();
|
|
||||||
var red = $("#rng_red").val();
|
|
||||||
var green = $("#rng_green").val();
|
|
||||||
var blue = $("#rng_blue").val();
|
|
||||||
|
|
||||||
var hexColor = componentToHex(white) + componentToHex(red) + componentToHex(green) + componentToHex(blue);
|
|
||||||
var statusColor = "#" + componentToHex(red) + componentToHex(green) + componentToHex(blue);
|
|
||||||
wsSetMainColor(hexColor);
|
|
||||||
$('#status').css("backgroundColor", statusColor);
|
|
||||||
$('#status_color').text(statusColor + "- R=" + red + ", G=" + green + ", B=" + blue);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// WebSocket commands
|
|
||||||
// ******************************************************************
|
|
||||||
function wsSendCommand(cmd) {
|
|
||||||
console.log("Send WebSocket command:", cmd);
|
|
||||||
if (ws_waiting == 0) {
|
|
||||||
connection.send(cmd);
|
|
||||||
ws_waiting++;
|
|
||||||
} else {
|
|
||||||
console.log("++++++++ WS call waiting, skip")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function wsSetAll(hexColor) {
|
|
||||||
console.log("wsSetAll() Set all colors to:", hexColor);
|
|
||||||
wsSendCommand("*" + hexColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
function wsSetMainColor(hexColor) {
|
|
||||||
console.log("wsSetMainColor() Set main colors to:", hexColor);
|
|
||||||
wsSendCommand("#" + hexColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// Colorwheel
|
|
||||||
// ******************************************************************
|
|
||||||
// this is supposed to work on mobiles (touch) as well as on a desktop (click)
|
|
||||||
// since we couldn't find a decent one .. this try of writing one by myself
|
|
||||||
// + google. swiping would be really nice - I will possibly implement it with
|
|
||||||
// jquery later - or never.
|
|
||||||
|
|
||||||
var canvas = document.getElementById("myCanvas");
|
|
||||||
// FIX: Cancel touch end event and handle click via touchstart
|
|
||||||
// canvas.addEventListener("touchend", function(e) { e.preventDefault(); }, false);
|
|
||||||
canvas.addEventListener("touchmove", doTouch, false);
|
|
||||||
canvas.addEventListener("click", doClick, false);
|
|
||||||
//canvas.addEventListener("mousemove", doClick, false);
|
|
||||||
|
|
||||||
|
|
||||||
var context = canvas.getContext('2d');
|
|
||||||
var centerX = canvas.width / 2;
|
|
||||||
var centerY = canvas.height / 2;
|
|
||||||
var innerRadius = canvas.width / 4.5;
|
|
||||||
var outerRadius = (canvas.width - 10) / 2
|
|
||||||
|
|
||||||
//outer border
|
|
||||||
context.beginPath();
|
|
||||||
//outer circle
|
|
||||||
context.arc(centerX, centerY, outerRadius, 0, 2 * Math.PI, false);
|
|
||||||
//draw the outer border: (gets drawn around the circle!)
|
|
||||||
context.lineWidth = 4;
|
|
||||||
context.strokeStyle = '#000000';
|
|
||||||
context.stroke();
|
|
||||||
context.closePath();
|
|
||||||
|
|
||||||
//fill with beautiful colors
|
|
||||||
//taken from here: http://stackoverflow.com/questions/18265804/building-a-color-wheel-in-html5
|
|
||||||
for(var angle=0; angle<=360; angle+=1) {
|
|
||||||
var startAngle = (angle-2)*Math.PI/180;
|
|
||||||
var endAngle = angle * Math.PI/180;
|
|
||||||
context.beginPath();
|
|
||||||
context.moveTo(centerX, centerY);
|
|
||||||
context.arc(centerX, centerY, outerRadius, startAngle, endAngle, false);
|
|
||||||
context.closePath();
|
|
||||||
context.fillStyle = 'hsl('+angle+', 100%, 50%)';
|
|
||||||
context.fill();
|
|
||||||
context.closePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
//inner border
|
|
||||||
context.beginPath();
|
|
||||||
//context.arc(centerX, centerY, radius, startAngle, endAngle, counterClockwise);
|
|
||||||
context.arc(centerX, centerY, innerRadius, 0, 2 * Math.PI, false);
|
|
||||||
//fill the center
|
|
||||||
var my_gradient=context.createLinearGradient(0,0,170,0);
|
|
||||||
my_gradient.addColorStop(0,"black");
|
|
||||||
my_gradient.addColorStop(1,"white");
|
|
||||||
|
|
||||||
context.fillStyle = my_gradient;
|
|
||||||
context.fillStyle = "white";
|
|
||||||
context.fill();
|
|
||||||
|
|
||||||
//draw the inner line
|
|
||||||
context.lineWidth = 2;
|
|
||||||
context.strokeStyle = '#000000';
|
|
||||||
context.stroke();
|
|
||||||
context.closePath();
|
|
||||||
|
|
||||||
//get Mouse x/y canvas position
|
|
||||||
function getMousePos(canvas, evt) {
|
|
||||||
var rect = canvas.getBoundingClientRect();
|
|
||||||
return {
|
|
||||||
x: evt.clientX - rect.left,
|
|
||||||
y: evt.clientY - rect.top
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//comp to Hex
|
|
||||||
function componentToHex(c) {
|
|
||||||
//var hex = c.toString(16);
|
|
||||||
//return hex.length == 1 ? "0" + hex : hex;
|
|
||||||
return ("0"+(Number(c).toString(16))).slice(-2).toUpperCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
//rgb/rgba to Hex
|
|
||||||
function rgbToHex(rgb) {
|
|
||||||
return componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//display the touch/click position and color info
|
|
||||||
function updateStatus(pos, color) {
|
|
||||||
//var hexColor = rgbToHex(color);
|
|
||||||
//wsSetAll(hexColor);
|
|
||||||
var hexColor = componentToHex(color[0]) + componentToHex(color[1]) + componentToHex(color[2]);
|
|
||||||
wsSetMainColor(hexColor);
|
|
||||||
hexColor = "#" + hexColor;
|
|
||||||
|
|
||||||
$('#status').css("backgroundColor", hexColor);
|
|
||||||
$('#status_color').text(hexColor + " - R=" + color[0] + ", G=" + color[1] + ", B=" + color[2]);
|
|
||||||
$('#status_pos').text("x: " + pos.x + " - y: " + pos.y);
|
|
||||||
|
|
||||||
$("#rng_white").val(0);
|
|
||||||
$("#rng_red").val(color[0]);
|
|
||||||
$("#rng_green").val(color[1]);
|
|
||||||
$("#rng_blue").val(color[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//handle the touch event
|
|
||||||
function doTouch(event) {
|
|
||||||
//to not also fire on click
|
|
||||||
event.preventDefault();
|
|
||||||
var el = event.target;
|
|
||||||
|
|
||||||
//touch position
|
|
||||||
var pos = {x: Math.round(event.targetTouches[0].pageX - el.offsetLeft),
|
|
||||||
y: Math.round(event.targetTouches[0].pageY - el.offsetTop)};
|
|
||||||
//color
|
|
||||||
var color = context.getImageData(pos.x, pos.y, 1, 1).data;
|
|
||||||
|
|
||||||
updateStatus(pos, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
function doClick(event) {
|
|
||||||
//click position
|
|
||||||
var pos = getMousePos(canvas, event);
|
|
||||||
//color
|
|
||||||
var color = context.getImageData(pos.x, pos.y, 1, 1).data;
|
|
||||||
|
|
||||||
//console.log("click", pos.x, pos.y, color);
|
|
||||||
updateStatus(pos, color);
|
|
||||||
|
|
||||||
//now do sth with the color rgbToHex(color);
|
|
||||||
//don't do stuff when #000000 (outside circle and lines
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// main
|
|
||||||
// ******************************************************************
|
|
||||||
init();
|
|
||||||
|
|
||||||
}); // end of document ready
|
|
||||||
})(jQuery); // end of jQuery name space
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
@@ -1,466 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!--Import Google Icon Font-->
|
|
||||||
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
||||||
<!--Import materialize.css-->
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css" media="screen,projection" />
|
|
||||||
|
|
||||||
<!--Let browser know website is optimized for mobile-->
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
|
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<title>McLighting v2</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<nav class="blue light-blueXXX lighten-1XXX" role="navigation" id="mc-nav">
|
|
||||||
<div class="nav-wrapper container">
|
|
||||||
<a id="logo-container" href="#" class="brand-logo">Mc Lighting v2</a>
|
|
||||||
|
|
||||||
<ul class="right hide-on-med-and-down">
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane1">Wheel</a></li>
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane2">Modes</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul id="nav-mobile" class="side-nav">
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane1">Wheel</a></li>
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane2">Modes</a></li>
|
|
||||||
</ul>
|
|
||||||
<a href="#" data-activates="nav-mobile" class="button-collapse"><i class="material-icons">menu</i></a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div class="container mc_pane" id="pane0">
|
|
||||||
<div class="section">
|
|
||||||
<div class="row" id="mc-wsloader">
|
|
||||||
<div class="col">
|
|
||||||
<div class="preloader-wrapper active">
|
|
||||||
<div class="spinner-layer spinner-blue-only">
|
|
||||||
<div class="circle-clipper left">
|
|
||||||
<div class="circle"></div>
|
|
||||||
</div>
|
|
||||||
<div class="gap-patch">
|
|
||||||
<div class="circle"></div>
|
|
||||||
</div>
|
|
||||||
<div class="circle-clipper right">
|
|
||||||
<div class="circle"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row hide" id="mc-wserror">
|
|
||||||
<div class="col">
|
|
||||||
<div>Error on websocket connect.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container mc_pane hide" id="pane1">
|
|
||||||
<div class="section">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col s12 m6">
|
|
||||||
<div style="height: 330px; width: 330px;">
|
|
||||||
<canvas id="myCanvas" width="330" height="330" style="-webkit-user-select: none;-webkit-tap-highlight-color: rgba(0,0,0,0);-moz-user-select:none;"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col s12 m6">
|
|
||||||
<div class="card-panel" id="status">
|
|
||||||
<div id="status_pos">pick a color</div>
|
|
||||||
<div id="status_color"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col s12 m6">
|
|
||||||
<div class="right switch">Auto:<br>
|
|
||||||
<label>Off
|
|
||||||
<input id="autoSwitch" type="checkbox"><span class="lever"></span>On
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container mc_pane hide" id="pane2">
|
|
||||||
<div class="section">
|
|
||||||
<div class="row">
|
|
||||||
<form class="col s12">
|
|
||||||
<div class="row">
|
|
||||||
<div class="input-field col s12 l4">
|
|
||||||
<label for="txt_red">Red</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_red" min="0" max="255" class="update_colors" /></p>
|
|
||||||
</div>
|
|
||||||
<div class="input-field col s12 l4">
|
|
||||||
<label for="txt_green">Green</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_green" min="0" max="255" class="update_colors" /></p>
|
|
||||||
</div>
|
|
||||||
<div class="input-field col s12 l4">
|
|
||||||
<label for="txt_blue">Blue</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_blue" min="0" max="255" class="update_colors" /></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="input-field col s12">
|
|
||||||
<label for="txt_delay">Speed</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_delay" min="0" max="255" value="196" class="update_delay" /></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="input-field col s12">
|
|
||||||
<label for="txt_delay">Brightness</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_brightness" min="0" max="255" value="196" class="update_brightness" /></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col s12 m6 l6 btn_grid">
|
|
||||||
<a class="btn waves-effect waves-light btn_mode_static blue" name="action" data-mode="off">OFF
|
|
||||||
<i class="material-icons right">send</i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col s12 m6 l6 btn_grid">
|
|
||||||
<a class="btn waves-effect waves-light btn_mode_static blue" name="action" data-mode="tv">TV
|
|
||||||
<i class="material-icons right">send</i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="modes">
|
|
||||||
<div class="input-field col s12">
|
|
||||||
Loading animations...
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<footer class="page-footer blue">
|
|
||||||
<div class="footer-copyright">
|
|
||||||
<div class="container">© 2017
|
|
||||||
<a class="grey-text text-lighten-4 right" href="https://github.com/toblum/McLighting">Project home</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<style type="text/css">
|
|
||||||
.btn_grid {
|
|
||||||
margin: 7px 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<!--Import jQuery before materialize.js-->
|
|
||||||
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
|
|
||||||
<script type="text/javascript">(function($){
|
|
||||||
$(function(){
|
|
||||||
|
|
||||||
// Settings
|
|
||||||
var host = window.location.hostname;
|
|
||||||
//host = "esp8266_02.local";
|
|
||||||
|
|
||||||
var ws_url = 'ws://' + host + ':81';
|
|
||||||
var connection;
|
|
||||||
var ws_waiting = 0;
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// Side navigation
|
|
||||||
// ******************************************************************
|
|
||||||
$('.button-collapse').sideNav();
|
|
||||||
|
|
||||||
// Navlinks
|
|
||||||
$('#mc-nav').on('click', '.mc-navlink', function(){
|
|
||||||
console.log("Navigate to pane: ", $(this).data("pane"));
|
|
||||||
showPane($(this).data("pane"));
|
|
||||||
});
|
|
||||||
|
|
||||||
function showPane(pane) {
|
|
||||||
$('.mc_pane').addClass('hide');
|
|
||||||
$('#' + pane).removeClass('hide');
|
|
||||||
$('.button-collapse').sideNav('hide');
|
|
||||||
|
|
||||||
if (pane == "pane2") {
|
|
||||||
setMainColor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// init()
|
|
||||||
// ******************************************************************
|
|
||||||
function init() {
|
|
||||||
console.log("Connection websockets to:", ws_url);
|
|
||||||
connection = new WebSocket(ws_url, ['arduino']);
|
|
||||||
|
|
||||||
// Load modes async
|
|
||||||
$.getJSON("http://" + host + "/get_modes", function(data) {
|
|
||||||
//console.log("modes", data);
|
|
||||||
|
|
||||||
var modes_html = "";
|
|
||||||
data.forEach(function(current_mode){
|
|
||||||
if (current_mode.mode !== undefined) {
|
|
||||||
modes_html += '<div class="col s12 m6 l6 btn_grid">';
|
|
||||||
modes_html += '<a class="btn waves-effect waves-light btn_mode blue" name="action" data-mode="' + current_mode.mode + '">(' + current_mode.mode +') '+ current_mode.name;
|
|
||||||
modes_html += '<i class="material-icons right">send</i>';
|
|
||||||
modes_html += '</a>';
|
|
||||||
modes_html += '</div>';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#modes').html(modes_html);
|
|
||||||
});
|
|
||||||
|
|
||||||
// When the connection is open, send some data to the server
|
|
||||||
connection.onopen = function () {
|
|
||||||
//connection.send('Ping'); // Send the message 'Ping' to the server
|
|
||||||
console.log('WebSocket Open');
|
|
||||||
showPane('pane1');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Log errors
|
|
||||||
connection.onerror = function (error) {
|
|
||||||
console.log('WebSocket Error ' + error);
|
|
||||||
$('#mc-wsloader').addClass('hide');
|
|
||||||
$('#mc-wserror').removeClass('hide');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Log messages from the server
|
|
||||||
connection.onmessage = function (e) {
|
|
||||||
console.log('WebSocket from server: ' + e.data);
|
|
||||||
ws_waiting = 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// Modes
|
|
||||||
// ******************************************************************
|
|
||||||
$("#pane2").on("click", ".btn_mode", function() {
|
|
||||||
var mode = $(this).attr("data-mode");
|
|
||||||
last_mode = mode;
|
|
||||||
var btn = $(this);
|
|
||||||
setMode(mode, function() {
|
|
||||||
$(".btn_mode, .btn_mode_static").removeClass("red").addClass("blue");
|
|
||||||
btn.removeClass("blue").addClass("red");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#pane2").on("click", ".btn_mode_static", function() {
|
|
||||||
var mode = $(this).attr("data-mode");
|
|
||||||
var btn = $(this);
|
|
||||||
|
|
||||||
wsSendCommand("=" + mode);
|
|
||||||
$(".btn_mode, .btn_mode_static").removeClass("red").addClass("blue");
|
|
||||||
btn.removeClass("blue").addClass("red");
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#pane2").on("change", ".update_colors", setMainColor);
|
|
||||||
|
|
||||||
$("#pane2").on("change", ".update_delay", function() {
|
|
||||||
var delay = $("#rng_delay").val();
|
|
||||||
|
|
||||||
wsSendCommand("?" + delay);
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#pane2").on("change", ".update_brightness", function() {
|
|
||||||
var brightness = $("#rng_brightness").val();
|
|
||||||
|
|
||||||
wsSendCommand("%" + brightness);
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#autoSwitch").on("change", function () {
|
|
||||||
if ($(this).prop('checked')) {
|
|
||||||
wsSendCommand("start");
|
|
||||||
} else {
|
|
||||||
wsSendCommand("stop");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function setMode(mode, finish_funtion) {
|
|
||||||
console.log("Mode: ", mode);
|
|
||||||
|
|
||||||
wsSendCommand("/" + mode);
|
|
||||||
finish_funtion();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setMainColor() {
|
|
||||||
var red = $("#rng_red").val();
|
|
||||||
var green = $("#rng_green").val();
|
|
||||||
var blue = $("#rng_blue").val();
|
|
||||||
|
|
||||||
var mainColorHex = componentToHex(red) + componentToHex(green) + componentToHex(blue);
|
|
||||||
wsSetMainColor(mainColorHex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// WebSocket commands
|
|
||||||
// ******************************************************************
|
|
||||||
function wsSendCommand(cmd) {
|
|
||||||
console.log("Send WebSocket command:", cmd);
|
|
||||||
if (ws_waiting == 0) {
|
|
||||||
connection.send(cmd);
|
|
||||||
ws_waiting++;
|
|
||||||
} else {
|
|
||||||
console.log("++++++++ WS call waiting, skip")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function wsSetAll(hexColor) {
|
|
||||||
console.log("wsSetAll() Set all colors to:", hexColor);
|
|
||||||
wsSendCommand("*" + hexColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
function wsSetMainColor(hexColor) {
|
|
||||||
console.log("wsSetMainColor() Set main colors to:", hexColor);
|
|
||||||
wsSendCommand("#" + hexColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// Colorwheel
|
|
||||||
// ******************************************************************
|
|
||||||
// this is supposed to work on mobiles (touch) as well as on a desktop (click)
|
|
||||||
// since we couldn't find a decent one .. this try of writing one by myself
|
|
||||||
// + google. swiping would be really nice - I will possibly implement it with
|
|
||||||
// jquery later - or never.
|
|
||||||
|
|
||||||
var canvas = document.getElementById("myCanvas");
|
|
||||||
// FIX: Cancel touch end event and handle click via touchstart
|
|
||||||
// canvas.addEventListener("touchend", function(e) { e.preventDefault(); }, false);
|
|
||||||
canvas.addEventListener("touchmove", doTouch, false);
|
|
||||||
canvas.addEventListener("click", doClick, false);
|
|
||||||
//canvas.addEventListener("mousemove", doClick, false);
|
|
||||||
|
|
||||||
|
|
||||||
var context = canvas.getContext('2d');
|
|
||||||
var centerX = canvas.width / 2;
|
|
||||||
var centerY = canvas.height / 2;
|
|
||||||
var innerRadius = canvas.width / 4.5;
|
|
||||||
var outerRadius = (canvas.width - 10) / 2
|
|
||||||
|
|
||||||
//outer border
|
|
||||||
context.beginPath();
|
|
||||||
//outer circle
|
|
||||||
context.arc(centerX, centerY, outerRadius, 0, 2 * Math.PI, false);
|
|
||||||
//draw the outer border: (gets drawn around the circle!)
|
|
||||||
context.lineWidth = 4;
|
|
||||||
context.strokeStyle = '#000000';
|
|
||||||
context.stroke();
|
|
||||||
context.closePath();
|
|
||||||
|
|
||||||
//fill with beautiful colors
|
|
||||||
//taken from here: http://stackoverflow.com/questions/18265804/building-a-color-wheel-in-html5
|
|
||||||
for(var angle=0; angle<=360; angle+=1) {
|
|
||||||
var startAngle = (angle-2)*Math.PI/180;
|
|
||||||
var endAngle = angle * Math.PI/180;
|
|
||||||
context.beginPath();
|
|
||||||
context.moveTo(centerX, centerY);
|
|
||||||
context.arc(centerX, centerY, outerRadius, startAngle, endAngle, false);
|
|
||||||
context.closePath();
|
|
||||||
context.fillStyle = 'hsl('+angle+', 100%, 50%)';
|
|
||||||
context.fill();
|
|
||||||
context.closePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
//inner border
|
|
||||||
context.beginPath();
|
|
||||||
//context.arc(centerX, centerY, radius, startAngle, endAngle, counterClockwise);
|
|
||||||
context.arc(centerX, centerY, innerRadius, 0, 2 * Math.PI, false);
|
|
||||||
//fill the center
|
|
||||||
var my_gradient=context.createLinearGradient(0,0,170,0);
|
|
||||||
my_gradient.addColorStop(0,"black");
|
|
||||||
my_gradient.addColorStop(1,"white");
|
|
||||||
|
|
||||||
context.fillStyle = my_gradient;
|
|
||||||
context.fillStyle = "white";
|
|
||||||
context.fill();
|
|
||||||
|
|
||||||
//draw the inner line
|
|
||||||
context.lineWidth = 2;
|
|
||||||
context.strokeStyle = '#000000';
|
|
||||||
context.stroke();
|
|
||||||
context.closePath();
|
|
||||||
|
|
||||||
//get Mouse x/y canvas position
|
|
||||||
function getMousePos(canvas, evt) {
|
|
||||||
var rect = canvas.getBoundingClientRect();
|
|
||||||
return {
|
|
||||||
x: evt.clientX - rect.left,
|
|
||||||
y: evt.clientY - rect.top
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//comp to Hex
|
|
||||||
function componentToHex(c) {
|
|
||||||
//var hex = c.toString(16);
|
|
||||||
//return hex.length == 1 ? "0" + hex : hex;
|
|
||||||
return ("0"+(Number(c).toString(16))).slice(-2).toUpperCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
//rgb/rgba to Hex
|
|
||||||
function rgbToHex(rgb) {
|
|
||||||
return componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//display the touch/click position and color info
|
|
||||||
function updateStatus(pos, color) {
|
|
||||||
var hexColor = rgbToHex(color);
|
|
||||||
wsSetAll(hexColor);
|
|
||||||
|
|
||||||
hexColor = "#" + hexColor;
|
|
||||||
|
|
||||||
$('#status').css("backgroundColor", hexColor);
|
|
||||||
$('#status_color').text(hexColor + " - R=" + color[0] + ", G=" + color[1] + ", B=" + color[2]);
|
|
||||||
$('#status_pos').text("x: " + pos.x + " - y: " + pos.y);
|
|
||||||
|
|
||||||
$("#rng_red").val(color[0]);
|
|
||||||
$("#rng_green").val(color[1]);
|
|
||||||
$("#rng_blue").val(color[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//handle the touch event
|
|
||||||
function doTouch(event) {
|
|
||||||
//to not also fire on click
|
|
||||||
event.preventDefault();
|
|
||||||
var el = event.target;
|
|
||||||
|
|
||||||
//touch position
|
|
||||||
var pos = {x: Math.round(event.targetTouches[0].pageX - el.offsetLeft),
|
|
||||||
y: Math.round(event.targetTouches[0].pageY - el.offsetTop)};
|
|
||||||
//color
|
|
||||||
var color = context.getImageData(pos.x, pos.y, 1, 1).data;
|
|
||||||
|
|
||||||
updateStatus(pos, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
function doClick(event) {
|
|
||||||
//click position
|
|
||||||
var pos = getMousePos(canvas, event);
|
|
||||||
//color
|
|
||||||
var color = context.getImageData(pos.x, pos.y, 1, 1).data;
|
|
||||||
|
|
||||||
//console.log("click", pos.x, pos.y, color);
|
|
||||||
updateStatus(pos, color);
|
|
||||||
|
|
||||||
//now do sth with the color rgbToHex(color);
|
|
||||||
//don't do stuff when #000000 (outside circle and lines
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// main
|
|
||||||
// ******************************************************************
|
|
||||||
init();
|
|
||||||
|
|
||||||
}); // end of document ready
|
|
||||||
})(jQuery); // end of jQuery name space</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -0,0 +1,676 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>SPIFFS Editor</title>
|
||||||
|
<style type="text/css" media="screen">
|
||||||
|
.contextMenu {
|
||||||
|
z-index: 300;
|
||||||
|
position: absolute;
|
||||||
|
left: 5px;
|
||||||
|
border: 1px solid #444;
|
||||||
|
background-color: #F5F5F5;
|
||||||
|
display: none;
|
||||||
|
box-shadow: 0 0 10px rgba( 0, 0, 0, .4 );
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-weight:bold;
|
||||||
|
}
|
||||||
|
.contextMenu ul {
|
||||||
|
list-style: none;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.contextMenu li {
|
||||||
|
position: relative;
|
||||||
|
min-width: 60px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.contextMenu span {
|
||||||
|
color: #444;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
.contextMenu li:hover { background: #444; }
|
||||||
|
.contextMenu li:hover span { color: #EEE; }
|
||||||
|
|
||||||
|
.css-treeview ul, .css-treeview li {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview input {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview {
|
||||||
|
font: normal 11px Verdana, Arial, Sans-serif;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview span {
|
||||||
|
color: #00f;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview span:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview input + label + ul {
|
||||||
|
margin: 0 0 0 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview input ~ ul {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview label, .css-treeview label::before {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview input:disabled + label {
|
||||||
|
cursor: default;
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview input:checked:not(:disabled) ~ ul {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview label, .css-treeview label::before {
|
||||||
|
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAACgCAYAAAAFOewUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAApxJREFUeNrslM1u00AQgGdthyalFFOK+ClIIKQKyqUVQvTEE3DmAhLwAhU8QZoH4A2Q2gMSFace4MCtJ8SPBFwAkRuiHKpA6sRN/Lu7zG5i14kctaUqRGhGXnu9O/Pt7MzsMiklvF+9t2kWTDvyIrAsA0aKRRi1T0C/hJ4LUbt5/8rNpWVlp8RSr9J40b48fxFaTQ9+ft8EZ6MJYb0Ok+dnYGpmPgXwKIAvLx8vYXc5GdMAQJgQEkpjRTh36TS2U+DWW/D17WuYgm8pwJyY1npZsZKOxImOV1I/h4+O6vEg5GCZBpgmA6hX8wHKUHDRBXQYicQ4rlc3Tf0VMs8DHBS864F2YFspjgUYjKX/Az3gsdQd2eeBHwmdGWXHcgBGSkZXOXohcEXebRoQcAgjqediNY+AVyu3Z3sAKqfKoGMsewBeEIOPgQxxPJIjcGH6qtL/0AdADzKGnuuD+2tLK7Q8DhHHbOBW+KEzcHLuYc82MkEUekLiwuvVH+guQBQzOG4XdAb8EOcRcqQvDkY2iCLuxECJ43JobMXoutqGgDa2T7UqLKwt9KRyuxKVByqVXXqIoCCUCAqhUOioTWC7G4TQEOD0APy2/7G2Xpu1J4+lxeQ4TXBbITDpoVelRN/BVFbwu5oMMJUBhoXy5tmdRcMwymP2OLQaLjx9/vnBo6V3K6izATmSnMa0Dq7ferIohJhr1p01zrlz49rZF4OMs8JkX23vVQzYp+wbYGV/KpXKjvspl8tsIKCrMNAYFxj2GKS5ZWxg4ewKsJfaGMIY5KXqPz8LBBj6+yDvVP79+yDp/9F9oIx3OisHWwe7Oal0HxCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgwD8E/BZgAP0qhKj3rXO7AAAAAElFTkSuQmCC") no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview label, .css-treeview span, .css-treeview label::before {
|
||||||
|
display: inline-block;
|
||||||
|
height: 16px;
|
||||||
|
line-height: 16px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview label {
|
||||||
|
background-position: 18px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview label::before {
|
||||||
|
content: "";
|
||||||
|
width: 16px;
|
||||||
|
margin: 0 22px 0 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-position: 0 -32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-treeview input:checked + label::before {
|
||||||
|
background-position: 0 -16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* webkit adjacent element selector bugfix */
|
||||||
|
@media screen and (-webkit-min-device-pixel-ratio:0)
|
||||||
|
{
|
||||||
|
.css-treeview{
|
||||||
|
-webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes webkit-adjacent-element-selector-bugfix
|
||||||
|
{
|
||||||
|
from {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploader {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
height:28px;
|
||||||
|
line-height: 24px;
|
||||||
|
padding-left: 10px;
|
||||||
|
background-color: #444;
|
||||||
|
color:#EEE;
|
||||||
|
}
|
||||||
|
#tree {
|
||||||
|
position: absolute;
|
||||||
|
top: 28px;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width:200px;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
#editor, #preview {
|
||||||
|
position: absolute;
|
||||||
|
top: 28px;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 200px;
|
||||||
|
}
|
||||||
|
#preview {
|
||||||
|
background-color: #EEE;
|
||||||
|
padding:5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function createFileUploader(element, tree, editor){
|
||||||
|
var xmlHttp;
|
||||||
|
var input = document.createElement("input");
|
||||||
|
input.type = "file";
|
||||||
|
input.multiple = false;
|
||||||
|
input.name = "data";
|
||||||
|
document.getElementById(element).appendChild(input);
|
||||||
|
var path = document.createElement("input");
|
||||||
|
path.id = "upload-path";
|
||||||
|
path.type = "text";
|
||||||
|
path.name = "path";
|
||||||
|
path.defaultValue = "/";
|
||||||
|
document.getElementById(element).appendChild(path);
|
||||||
|
var button = document.createElement("button");
|
||||||
|
button.innerHTML = 'Upload';
|
||||||
|
document.getElementById(element).appendChild(button);
|
||||||
|
var mkdir = document.createElement("button");
|
||||||
|
mkdir.innerHTML = 'MkDir';
|
||||||
|
document.getElementById(element).appendChild(mkdir);
|
||||||
|
var mkfile = document.createElement("button");
|
||||||
|
mkfile.innerHTML = 'MkFile';
|
||||||
|
document.getElementById(element).appendChild(mkfile);
|
||||||
|
var para = document.createElement("text");
|
||||||
|
para.innerHTML = " Press Ctrl-S for save, Ctrl-Z for undo, Ctrl-Shift-Z for redo";
|
||||||
|
document.getElementById(element).appendChild(para);
|
||||||
|
function httpPostProcessRequest(){
|
||||||
|
if (xmlHttp.readyState == 4){
|
||||||
|
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||||
|
else {
|
||||||
|
tree.refreshPath(path.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function createPath(p){
|
||||||
|
xmlHttp = new XMLHttpRequest();
|
||||||
|
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append("path", p);
|
||||||
|
xmlHttp.open("PUT", "/edit");
|
||||||
|
xmlHttp.send(formData);
|
||||||
|
}
|
||||||
|
|
||||||
|
mkfile.onclick = function(e){
|
||||||
|
if(path.value.indexOf(".") === -1) return;
|
||||||
|
createPath(path.value);
|
||||||
|
editor.loadUrl(path.value);
|
||||||
|
};
|
||||||
|
mkdir.onclick = function(e){
|
||||||
|
if(path.value.length < 2) return;
|
||||||
|
var dir = path.value
|
||||||
|
if(dir.indexOf(".") !== -1){
|
||||||
|
if(dir.lastIndexOf("/") === 0) return;
|
||||||
|
dir = dir.substring(0, dir.lastIndexOf("/"));
|
||||||
|
}
|
||||||
|
createPath(dir);
|
||||||
|
};
|
||||||
|
button.onclick = function(e){
|
||||||
|
if(input.files.length === 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xmlHttp = new XMLHttpRequest();
|
||||||
|
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append("data", input.files[0], path.value);
|
||||||
|
xmlHttp.open("POST", "/edit");
|
||||||
|
xmlHttp.send(formData);
|
||||||
|
}
|
||||||
|
input.onchange = function(e){
|
||||||
|
if(input.files.length === 0) return;
|
||||||
|
var filename = input.files[0].name;
|
||||||
|
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
|
||||||
|
var name = /(.*)\.[^.]+$/.exec(filename)[1];
|
||||||
|
if(typeof name !== undefined){
|
||||||
|
if(name.length > 8) name = name.substring(0, 8);
|
||||||
|
filename = name;
|
||||||
|
}
|
||||||
|
if(typeof ext !== undefined){
|
||||||
|
if(ext === "html") ext = "htm";
|
||||||
|
else if(ext === "jpeg") ext = "jpg";
|
||||||
|
filename = filename + "." + ext;
|
||||||
|
}
|
||||||
|
if(path.value === "/" || path.value.lastIndexOf("/") === 0){
|
||||||
|
path.value = "/"+filename;
|
||||||
|
} else {
|
||||||
|
path.value = path.value.substring(0, path.value.lastIndexOf("/")+1)+filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTree(element, editor){
|
||||||
|
var preview = document.getElementById("preview");
|
||||||
|
var treeRoot = document.createElement("div");
|
||||||
|
treeRoot.className = "css-treeview";
|
||||||
|
document.getElementById(element).appendChild(treeRoot);
|
||||||
|
|
||||||
|
function loadDownload(path){
|
||||||
|
document.getElementById('download-frame').src = path+"?download=true";
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadPreview(path){
|
||||||
|
document.getElementById("editor").style.display = "none";
|
||||||
|
preview.style.display = "block";
|
||||||
|
preview.innerHTML = '<img src="'+path+'" style="max-width:100%; max-height:100%; margin:auto; display:block;" />';
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillFolderMenu(el, path){
|
||||||
|
var list = document.createElement("ul");
|
||||||
|
el.appendChild(list);
|
||||||
|
var action = document.createElement("li");
|
||||||
|
list.appendChild(action);
|
||||||
|
var isChecked = document.getElementById(path).checked;
|
||||||
|
var expnd = document.createElement("li");
|
||||||
|
list.appendChild(expnd);
|
||||||
|
if(isChecked){
|
||||||
|
expnd.innerHTML = "<span>Collapse</span>";
|
||||||
|
expnd.onclick = function(e){
|
||||||
|
document.getElementById(path).checked = false;
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
var refrsh = document.createElement("li");
|
||||||
|
list.appendChild(refrsh);
|
||||||
|
refrsh.innerHTML = "<span>Refresh</span>";
|
||||||
|
refrsh.onclick = function(e){
|
||||||
|
var leaf = document.getElementById(path).parentNode;
|
||||||
|
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||||
|
httpGet(leaf, path);
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
expnd.innerHTML = "<span>Expand</span>";
|
||||||
|
expnd.onclick = function(e){
|
||||||
|
document.getElementById(path).checked = true;
|
||||||
|
var leaf = document.getElementById(path).parentNode;
|
||||||
|
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||||
|
httpGet(leaf, path);
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var upload = document.createElement("li");
|
||||||
|
list.appendChild(upload);
|
||||||
|
upload.innerHTML = "<span>Upload</span>";
|
||||||
|
upload.onclick = function(e){
|
||||||
|
var pathEl = document.getElementById("upload-path");
|
||||||
|
if(pathEl){
|
||||||
|
var subPath = pathEl.value;
|
||||||
|
if(subPath.lastIndexOf("/") < 1) pathEl.value = path+subPath;
|
||||||
|
else pathEl.value = path.substring(subPath.lastIndexOf("/"))+subPath;
|
||||||
|
}
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
var delFile = document.createElement("li");
|
||||||
|
list.appendChild(delFile);
|
||||||
|
delFile.innerHTML = "<span>Delete</span>";
|
||||||
|
delFile.onclick = function(e){
|
||||||
|
httpDelete(path);
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillFileMenu(el, path){
|
||||||
|
var list = document.createElement("ul");
|
||||||
|
el.appendChild(list);
|
||||||
|
var action = document.createElement("li");
|
||||||
|
list.appendChild(action);
|
||||||
|
if(isTextFile(path)){
|
||||||
|
action.innerHTML = "<span>Edit</span>";
|
||||||
|
action.onclick = function(e){
|
||||||
|
editor.loadUrl(path);
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
} else if(isImageFile(path)){
|
||||||
|
action.innerHTML = "<span>Preview</span>";
|
||||||
|
action.onclick = function(e){
|
||||||
|
loadPreview(path);
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var download = document.createElement("li");
|
||||||
|
list.appendChild(download);
|
||||||
|
download.innerHTML = "<span>Download</span>";
|
||||||
|
download.onclick = function(e){
|
||||||
|
loadDownload(path);
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
var delFile = document.createElement("li");
|
||||||
|
list.appendChild(delFile);
|
||||||
|
delFile.innerHTML = "<span>Delete</span>";
|
||||||
|
delFile.onclick = function(e){
|
||||||
|
httpDelete(path);
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function showContextMenu(e, path, isfile){
|
||||||
|
var divContext = document.createElement("div");
|
||||||
|
var scrollTop = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;
|
||||||
|
var scrollLeft = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft;
|
||||||
|
var left = e.clientX + scrollLeft;
|
||||||
|
var top = e.clientY + scrollTop;
|
||||||
|
divContext.className = 'contextMenu';
|
||||||
|
divContext.style.display = 'block';
|
||||||
|
divContext.style.left = left + 'px';
|
||||||
|
divContext.style.top = top + 'px';
|
||||||
|
if(isfile) fillFileMenu(divContext, path);
|
||||||
|
else fillFolderMenu(divContext, path);
|
||||||
|
document.body.appendChild(divContext);
|
||||||
|
var width = divContext.offsetWidth;
|
||||||
|
var height = divContext.offsetHeight;
|
||||||
|
divContext.onmouseout = function(e){
|
||||||
|
if(e.clientX < left || e.clientX > (left + width) || e.clientY < top || e.clientY > (top + height)){
|
||||||
|
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(divContext);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTreeLeaf(path, name, size){
|
||||||
|
var leaf = document.createElement("li");
|
||||||
|
leaf.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
|
||||||
|
var label = document.createElement("span");
|
||||||
|
label.textContent = name.toLowerCase();
|
||||||
|
leaf.appendChild(label);
|
||||||
|
leaf.onclick = function(e){
|
||||||
|
if(isTextFile(leaf.id)){
|
||||||
|
editor.loadUrl(leaf.id);
|
||||||
|
} else if(isImageFile(leaf.id)){
|
||||||
|
loadPreview(leaf.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
leaf.oncontextmenu = function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
showContextMenu(e, leaf.id, true);
|
||||||
|
};
|
||||||
|
return leaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTreeBranch(path, name, disabled){
|
||||||
|
var leaf = document.createElement("li");
|
||||||
|
var check = document.createElement("input");
|
||||||
|
check.type = "checkbox";
|
||||||
|
check.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
|
||||||
|
if(typeof disabled !== "undefined" && disabled) check.disabled = "disabled";
|
||||||
|
leaf.appendChild(check);
|
||||||
|
var label = document.createElement("label");
|
||||||
|
label.for = check.id;
|
||||||
|
label.textContent = name.toLowerCase();
|
||||||
|
leaf.appendChild(label);
|
||||||
|
check.onchange = function(e){
|
||||||
|
if(check.checked){
|
||||||
|
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||||
|
httpGet(leaf, check.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
label.onclick = function(e){
|
||||||
|
if(!check.checked){
|
||||||
|
check.checked = true;
|
||||||
|
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||||
|
httpGet(leaf, check.id);
|
||||||
|
} else {
|
||||||
|
check.checked = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
leaf.oncontextmenu = function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
showContextMenu(e, check.id, false);
|
||||||
|
}
|
||||||
|
return leaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addList(parent, path, items){
|
||||||
|
var list = document.createElement("ul");
|
||||||
|
parent.appendChild(list);
|
||||||
|
var ll = items.length;
|
||||||
|
for(var i = 0; i < ll; i++){
|
||||||
|
var item = items[i];
|
||||||
|
var itemEl;
|
||||||
|
if(item.type === "file"){
|
||||||
|
itemEl = createTreeLeaf(path, item.name, item.size);
|
||||||
|
} else {
|
||||||
|
itemEl = createTreeBranch(path, item.name);
|
||||||
|
}
|
||||||
|
list.appendChild(itemEl);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTextFile(path){
|
||||||
|
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
|
||||||
|
if(typeof ext !== undefined){
|
||||||
|
switch(ext){
|
||||||
|
case "txt":
|
||||||
|
case "htm":
|
||||||
|
case "html":
|
||||||
|
case "js":
|
||||||
|
case "json":
|
||||||
|
case "c":
|
||||||
|
case "h":
|
||||||
|
case "cpp":
|
||||||
|
case "css":
|
||||||
|
case "xml":
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isImageFile(path){
|
||||||
|
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
|
||||||
|
if(typeof ext !== undefined){
|
||||||
|
switch(ext){
|
||||||
|
case "png":
|
||||||
|
case "jpg":
|
||||||
|
case "gif":
|
||||||
|
case "ico":
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.refreshPath = function(path){
|
||||||
|
if(path.lastIndexOf('/') < 1){
|
||||||
|
path = '/';
|
||||||
|
treeRoot.removeChild(treeRoot.childNodes[0]);
|
||||||
|
httpGet(treeRoot, "/");
|
||||||
|
} else {
|
||||||
|
path = path.substring(0, path.lastIndexOf('/'));
|
||||||
|
var leaf = document.getElementById(path).parentNode;
|
||||||
|
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||||
|
httpGet(leaf, path);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function delCb(path){
|
||||||
|
return function(){
|
||||||
|
if (xmlHttp.readyState == 4){
|
||||||
|
if(xmlHttp.status != 200){
|
||||||
|
alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||||
|
} else {
|
||||||
|
if(path.lastIndexOf('/') < 1){
|
||||||
|
path = '/';
|
||||||
|
treeRoot.removeChild(treeRoot.childNodes[0]);
|
||||||
|
httpGet(treeRoot, "/");
|
||||||
|
} else {
|
||||||
|
path = path.substring(0, path.lastIndexOf('/'));
|
||||||
|
var leaf = document.getElementById(path).parentNode;
|
||||||
|
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||||
|
httpGet(leaf, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function httpDelete(filename){
|
||||||
|
xmlHttp = new XMLHttpRequest();
|
||||||
|
xmlHttp.onreadystatechange = delCb(filename);
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append("path", filename);
|
||||||
|
xmlHttp.open("DELETE", "/edit");
|
||||||
|
xmlHttp.send(formData);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCb(parent, path){
|
||||||
|
return function(){
|
||||||
|
if (xmlHttp.readyState == 4){
|
||||||
|
//clear loading
|
||||||
|
if(xmlHttp.status == 200) addList(parent, path, JSON.parse(xmlHttp.responseText));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function httpGet(parent, path){
|
||||||
|
xmlHttp = new XMLHttpRequest(parent, path);
|
||||||
|
xmlHttp.onreadystatechange = getCb(parent, path);
|
||||||
|
xmlHttp.open("GET", "/list?dir="+path, true);
|
||||||
|
xmlHttp.send(null);
|
||||||
|
//start loading
|
||||||
|
}
|
||||||
|
|
||||||
|
httpGet(treeRoot, "/");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createEditor(element, file, lang, theme, type){
|
||||||
|
function getLangFromFilename(filename){
|
||||||
|
var lang = "plain";
|
||||||
|
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
|
||||||
|
if(typeof ext !== undefined){
|
||||||
|
switch(ext){
|
||||||
|
case "txt": lang = "plain"; break;
|
||||||
|
case "htm": lang = "html"; break;
|
||||||
|
case "js": lang = "javascript"; break;
|
||||||
|
case "c": lang = "c_cpp"; break;
|
||||||
|
case "cpp": lang = "c_cpp"; break;
|
||||||
|
case "css":
|
||||||
|
case "scss":
|
||||||
|
case "php":
|
||||||
|
case "html":
|
||||||
|
case "json":
|
||||||
|
case "xml":
|
||||||
|
lang = ext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof file === "undefined") file = "/index.htm";
|
||||||
|
|
||||||
|
if(typeof lang === "undefined"){
|
||||||
|
lang = getLangFromFilename(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof theme === "undefined") theme = "textmate";
|
||||||
|
|
||||||
|
if(typeof type === "undefined"){
|
||||||
|
type = "text/"+lang;
|
||||||
|
if(lang === "c_cpp") type = "text/plain";
|
||||||
|
}
|
||||||
|
|
||||||
|
var xmlHttp = null;
|
||||||
|
var editor = ace.edit(element);
|
||||||
|
|
||||||
|
//post
|
||||||
|
function httpPostProcessRequest(){
|
||||||
|
if (xmlHttp.readyState == 4){
|
||||||
|
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function httpPost(filename, data, type){
|
||||||
|
xmlHttp = new XMLHttpRequest();
|
||||||
|
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append("data", new Blob([data], { type: type }), filename);
|
||||||
|
xmlHttp.open("POST", "/edit");
|
||||||
|
xmlHttp.send(formData);
|
||||||
|
}
|
||||||
|
//get
|
||||||
|
function httpGetProcessRequest(){
|
||||||
|
if (xmlHttp.readyState == 4){
|
||||||
|
document.getElementById("preview").style.display = "none";
|
||||||
|
document.getElementById("editor").style.display = "block";
|
||||||
|
if(xmlHttp.status == 200) editor.setValue(xmlHttp.responseText);
|
||||||
|
else editor.setValue("");
|
||||||
|
editor.clearSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function httpGet(theUrl){
|
||||||
|
xmlHttp = new XMLHttpRequest();
|
||||||
|
xmlHttp.onreadystatechange = httpGetProcessRequest;
|
||||||
|
xmlHttp.open("GET", theUrl, true);
|
||||||
|
xmlHttp.send(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
|
||||||
|
editor.setTheme("ace/theme/"+theme);
|
||||||
|
editor.$blockScrolling = Infinity;
|
||||||
|
editor.getSession().setUseSoftTabs(true);
|
||||||
|
editor.getSession().setTabSize(2);
|
||||||
|
editor.setHighlightActiveLine(true);
|
||||||
|
editor.setShowPrintMargin(false);
|
||||||
|
editor.commands.addCommand({
|
||||||
|
name: 'saveCommand',
|
||||||
|
bindKey: {win: 'Ctrl-S', mac: 'Command-S'},
|
||||||
|
exec: function(editor) {
|
||||||
|
httpPost(file, editor.getValue()+"", type);
|
||||||
|
},
|
||||||
|
readOnly: false
|
||||||
|
});
|
||||||
|
editor.commands.addCommand({
|
||||||
|
name: 'undoCommand',
|
||||||
|
bindKey: {win: 'Ctrl-Z', mac: 'Command-Z'},
|
||||||
|
exec: function(editor) {
|
||||||
|
editor.getSession().getUndoManager().undo(false);
|
||||||
|
},
|
||||||
|
readOnly: false
|
||||||
|
});
|
||||||
|
editor.commands.addCommand({
|
||||||
|
name: 'redoCommand',
|
||||||
|
bindKey: {win: 'Ctrl-Shift-Z', mac: 'Command-Shift-Z'},
|
||||||
|
exec: function(editor) {
|
||||||
|
editor.getSession().getUndoManager().redo(false);
|
||||||
|
},
|
||||||
|
readOnly: false
|
||||||
|
});
|
||||||
|
httpGet(file);
|
||||||
|
editor.loadUrl = function(filename){
|
||||||
|
file = filename;
|
||||||
|
lang = getLangFromFilename(file);
|
||||||
|
type = "text/"+lang;
|
||||||
|
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
|
||||||
|
httpGet(file);
|
||||||
|
}
|
||||||
|
return editor;
|
||||||
|
}
|
||||||
|
function onBodyLoad(){
|
||||||
|
var vars = {};
|
||||||
|
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value; });
|
||||||
|
var editor = createEditor("editor", vars.file, vars.lang, vars.theme);
|
||||||
|
var tree = createTree("tree", editor);
|
||||||
|
createFileUploader("uploader", tree, editor);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.9/ace.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
</head>
|
||||||
|
<body onload="onBodyLoad();">
|
||||||
|
<div id="uploader"></div>
|
||||||
|
<div id="tree"></div>
|
||||||
|
<div id="editor"></div>
|
||||||
|
<div id="preview" style="display:none;"></div>
|
||||||
|
<iframe id=download-frame style='display:none;'></iframe>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
Binary file not shown.
Binary file not shown.
@@ -1,55 +0,0 @@
|
|||||||
var gulp = require('gulp'),
|
|
||||||
request = require('request'),
|
|
||||||
fs = require('fs'),
|
|
||||||
connect = require('gulp-connect'),
|
|
||||||
fileinclude = require('gulp-file-include');
|
|
||||||
|
|
||||||
var src_dir = "src/";
|
|
||||||
var build_dir = "build/";
|
|
||||||
|
|
||||||
|
|
||||||
gulp.task('html', function() {
|
|
||||||
gulp.src(src_dir + '*.htm')
|
|
||||||
.pipe(fileinclude({
|
|
||||||
prefix: '@@',
|
|
||||||
basepath: '@file'
|
|
||||||
}))
|
|
||||||
.pipe(gulp.dest('build'))
|
|
||||||
.pipe(connect.reload());
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
gulp.task('connect', function() {
|
|
||||||
connect.server({
|
|
||||||
root: 'build',
|
|
||||||
livereload: true
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('watch', function() {
|
|
||||||
gulp.watch(src_dir + '*.htm', ['html']);
|
|
||||||
gulp.watch(src_dir + 'js/*.js', ['html']);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
gulp.task('upload', ['html'], function() {
|
|
||||||
var url = 'http://192.168.0.49/edit';
|
|
||||||
var options = {
|
|
||||||
url: url,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'multipart/form-data'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var r = request.post(options, function optionalCallback(err, httpResponse, body) {
|
|
||||||
if (err) {
|
|
||||||
return console.error('upload failed:', err);
|
|
||||||
}
|
|
||||||
console.log('Upload successful! Server responded with:', body);
|
|
||||||
});
|
|
||||||
var form = r.form();
|
|
||||||
form.append('data', fs.createReadStream(__dirname + "/" + build_dir + '/index.htm'), {filename: '/index.htm', contentType: "application/octet-stream"});
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('default', ['html']);
|
|
||||||
gulp.task('serve', ['watch', 'connect']);
|
|
||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "mc_lighting",
|
|
||||||
"version": "2.0.0",
|
|
||||||
"description": "Web client for Mc Lighting",
|
|
||||||
"main": "index.html",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"author": "Tobias Blum",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"fs": "0.0.2",
|
|
||||||
"gulp": "^3.9.1",
|
|
||||||
"gulp-connect": "^5.0.0",
|
|
||||||
"gulp-file-include": "^1.0.0",
|
|
||||||
"request": "^2.72.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!--Import Google Icon Font-->
|
|
||||||
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
||||||
<!--Import materialize.css-->
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css" media="screen,projection" />
|
|
||||||
|
|
||||||
<!--Let browser know website is optimized for mobile-->
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
|
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<title>McLighting v2</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<nav class="blue light-blueXXX lighten-1XXX" role="navigation" id="mc-nav">
|
|
||||||
<div class="nav-wrapper container">
|
|
||||||
<a id="logo-container" href="#" class="brand-logo">Mc Lighting v2</a>
|
|
||||||
|
|
||||||
<ul class="right hide-on-med-and-down">
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane1">Wheel</a></li>
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane2">Modes</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul id="nav-mobile" class="side-nav">
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane1">Wheel</a></li>
|
|
||||||
<li><a href="#" class="mc-navlink" data-pane="pane2">Modes</a></li>
|
|
||||||
</ul>
|
|
||||||
<a href="#" data-activates="nav-mobile" class="button-collapse"><i class="material-icons">menu</i></a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div class="container mc_pane" id="pane0">
|
|
||||||
<div class="section">
|
|
||||||
<div class="row" id="mc-wsloader">
|
|
||||||
<div class="col">
|
|
||||||
<div class="preloader-wrapper active">
|
|
||||||
<div class="spinner-layer spinner-blue-only">
|
|
||||||
<div class="circle-clipper left">
|
|
||||||
<div class="circle"></div>
|
|
||||||
</div>
|
|
||||||
<div class="gap-patch">
|
|
||||||
<div class="circle"></div>
|
|
||||||
</div>
|
|
||||||
<div class="circle-clipper right">
|
|
||||||
<div class="circle"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row hide" id="mc-wserror">
|
|
||||||
<div class="col">
|
|
||||||
<div>Error on websocket connect.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container mc_pane hide" id="pane1">
|
|
||||||
<div class="section">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col s12 m6">
|
|
||||||
<div style="height: 330px; width: 330px;">
|
|
||||||
<canvas id="myCanvas" width="330" height="330" style="-webkit-user-select: none;-webkit-tap-highlight-color: rgba(0,0,0,0);-moz-user-select:none;"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col s12 m6">
|
|
||||||
<div class="card-panel" id="status">
|
|
||||||
<div id="status_pos">pick a color</div>
|
|
||||||
<div id="status_color"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col s12 m6">
|
|
||||||
<div class="right switch">Auto:<br>
|
|
||||||
<label>Off
|
|
||||||
<input id="autoSwitch" type="checkbox"><span class="lever"></span>On
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container mc_pane hide" id="pane2">
|
|
||||||
<div class="section">
|
|
||||||
<div class="row">
|
|
||||||
<form class="col s12">
|
|
||||||
<div class="row">
|
|
||||||
<div class="input-field col s12 l4">
|
|
||||||
<label for="txt_red">Red</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_red" min="0" max="255" class="update_colors" /></p>
|
|
||||||
</div>
|
|
||||||
<div class="input-field col s12 l4">
|
|
||||||
<label for="txt_green">Green</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_green" min="0" max="255" class="update_colors" /></p>
|
|
||||||
</div>
|
|
||||||
<div class="input-field col s12 l4">
|
|
||||||
<label for="txt_blue">Blue</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_blue" min="0" max="255" class="update_colors" /></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="input-field col s12">
|
|
||||||
<label for="txt_delay">Speed</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_delay" min="0" max="255" value="196" class="update_delay" /></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="input-field col s12">
|
|
||||||
<label for="txt_delay">Brightness</label><br/>
|
|
||||||
<p class="range-field"><input type="range" id="rng_brightness" min="0" max="255" value="196" class="update_brightness" /></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col s12 m6 l6 btn_grid">
|
|
||||||
<a class="btn waves-effect waves-light btn_mode_static blue" name="action" data-mode="off">OFF
|
|
||||||
<i class="material-icons right">send</i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col s12 m6 l6 btn_grid">
|
|
||||||
<a class="btn waves-effect waves-light btn_mode_static blue" name="action" data-mode="tv">TV
|
|
||||||
<i class="material-icons right">send</i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="modes">
|
|
||||||
<div class="input-field col s12">
|
|
||||||
Loading animations...
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<footer class="page-footer blue">
|
|
||||||
<div class="footer-copyright">
|
|
||||||
<div class="container">© 2017
|
|
||||||
<a class="grey-text text-lighten-4 right" href="https://github.com/toblum/McLighting">Project home</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<style type="text/css">
|
|
||||||
.btn_grid {
|
|
||||||
margin: 7px 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<!--Import jQuery before materialize.js-->
|
|
||||||
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
|
|
||||||
<script type="text/javascript">@@include('js/script.js')</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,305 +0,0 @@
|
|||||||
(function($){
|
|
||||||
$(function(){
|
|
||||||
|
|
||||||
// Settings
|
|
||||||
var host = window.location.hostname;
|
|
||||||
//host = "esp8266_02.local";
|
|
||||||
|
|
||||||
var ws_url = 'ws://' + host + ':81';
|
|
||||||
var connection;
|
|
||||||
var ws_waiting = 0;
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// Side navigation
|
|
||||||
// ******************************************************************
|
|
||||||
$('.button-collapse').sideNav();
|
|
||||||
|
|
||||||
// Navlinks
|
|
||||||
$('#mc-nav').on('click', '.mc-navlink', function(){
|
|
||||||
console.log("Navigate to pane: ", $(this).data("pane"));
|
|
||||||
showPane($(this).data("pane"));
|
|
||||||
});
|
|
||||||
|
|
||||||
function showPane(pane) {
|
|
||||||
$('.mc_pane').addClass('hide');
|
|
||||||
$('#' + pane).removeClass('hide');
|
|
||||||
$('.button-collapse').sideNav('hide');
|
|
||||||
|
|
||||||
if (pane == "pane2") {
|
|
||||||
setMainColor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// init()
|
|
||||||
// ******************************************************************
|
|
||||||
function init() {
|
|
||||||
console.log("Connection websockets to:", ws_url);
|
|
||||||
connection = new WebSocket(ws_url, ['arduino']);
|
|
||||||
|
|
||||||
// Load modes async
|
|
||||||
$.getJSON("http://" + host + "/get_modes", function(data) {
|
|
||||||
//console.log("modes", data);
|
|
||||||
|
|
||||||
var modes_html = "";
|
|
||||||
data.forEach(function(current_mode){
|
|
||||||
if (current_mode.mode !== undefined) {
|
|
||||||
modes_html += '<div class="col s12 m6 l6 btn_grid">';
|
|
||||||
modes_html += '<a class="btn waves-effect waves-light btn_mode blue" name="action" data-mode="' + current_mode.mode + '">(' + current_mode.mode +') '+ current_mode.name;
|
|
||||||
modes_html += '<i class="material-icons right">send</i>';
|
|
||||||
modes_html += '</a>';
|
|
||||||
modes_html += '</div>';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#modes').html(modes_html);
|
|
||||||
});
|
|
||||||
|
|
||||||
// When the connection is open, send some data to the server
|
|
||||||
connection.onopen = function () {
|
|
||||||
//connection.send('Ping'); // Send the message 'Ping' to the server
|
|
||||||
console.log('WebSocket Open');
|
|
||||||
showPane('pane1');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Log errors
|
|
||||||
connection.onerror = function (error) {
|
|
||||||
console.log('WebSocket Error ' + error);
|
|
||||||
$('#mc-wsloader').addClass('hide');
|
|
||||||
$('#mc-wserror').removeClass('hide');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Log messages from the server
|
|
||||||
connection.onmessage = function (e) {
|
|
||||||
console.log('WebSocket from server: ' + e.data);
|
|
||||||
ws_waiting = 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// Modes
|
|
||||||
// ******************************************************************
|
|
||||||
$("#pane2").on("click", ".btn_mode", function() {
|
|
||||||
var mode = $(this).attr("data-mode");
|
|
||||||
last_mode = mode;
|
|
||||||
var btn = $(this);
|
|
||||||
setMode(mode, function() {
|
|
||||||
$(".btn_mode, .btn_mode_static").removeClass("red").addClass("blue");
|
|
||||||
btn.removeClass("blue").addClass("red");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#pane2").on("click", ".btn_mode_static", function() {
|
|
||||||
var mode = $(this).attr("data-mode");
|
|
||||||
var btn = $(this);
|
|
||||||
|
|
||||||
wsSendCommand("=" + mode);
|
|
||||||
$(".btn_mode, .btn_mode_static").removeClass("red").addClass("blue");
|
|
||||||
btn.removeClass("blue").addClass("red");
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#pane2").on("change", ".update_colors", setMainColor);
|
|
||||||
|
|
||||||
$("#pane2").on("change", ".update_delay", function() {
|
|
||||||
var delay = $("#rng_delay").val();
|
|
||||||
|
|
||||||
wsSendCommand("?" + delay);
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#pane2").on("change", ".update_brightness", function() {
|
|
||||||
var brightness = $("#rng_brightness").val();
|
|
||||||
|
|
||||||
wsSendCommand("%" + brightness);
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#autoSwitch").on("change", function () {
|
|
||||||
if ($(this).prop('checked')) {
|
|
||||||
wsSendCommand("start");
|
|
||||||
} else {
|
|
||||||
wsSendCommand("stop");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function setMode(mode, finish_funtion) {
|
|
||||||
console.log("Mode: ", mode);
|
|
||||||
|
|
||||||
wsSendCommand("/" + mode);
|
|
||||||
finish_funtion();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setMainColor() {
|
|
||||||
var red = $("#rng_red").val();
|
|
||||||
var green = $("#rng_green").val();
|
|
||||||
var blue = $("#rng_blue").val();
|
|
||||||
|
|
||||||
var mainColorHex = componentToHex(red) + componentToHex(green) + componentToHex(blue);
|
|
||||||
wsSetMainColor(mainColorHex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// WebSocket commands
|
|
||||||
// ******************************************************************
|
|
||||||
function wsSendCommand(cmd) {
|
|
||||||
console.log("Send WebSocket command:", cmd);
|
|
||||||
if (ws_waiting == 0) {
|
|
||||||
connection.send(cmd);
|
|
||||||
ws_waiting++;
|
|
||||||
} else {
|
|
||||||
console.log("++++++++ WS call waiting, skip")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function wsSetAll(hexColor) {
|
|
||||||
console.log("wsSetAll() Set all colors to:", hexColor);
|
|
||||||
wsSendCommand("*" + hexColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
function wsSetMainColor(hexColor) {
|
|
||||||
console.log("wsSetMainColor() Set main colors to:", hexColor);
|
|
||||||
wsSendCommand("#" + hexColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// Colorwheel
|
|
||||||
// ******************************************************************
|
|
||||||
// this is supposed to work on mobiles (touch) as well as on a desktop (click)
|
|
||||||
// since we couldn't find a decent one .. this try of writing one by myself
|
|
||||||
// + google. swiping would be really nice - I will possibly implement it with
|
|
||||||
// jquery later - or never.
|
|
||||||
|
|
||||||
var canvas = document.getElementById("myCanvas");
|
|
||||||
// FIX: Cancel touch end event and handle click via touchstart
|
|
||||||
// canvas.addEventListener("touchend", function(e) { e.preventDefault(); }, false);
|
|
||||||
canvas.addEventListener("touchmove", doTouch, false);
|
|
||||||
canvas.addEventListener("click", doClick, false);
|
|
||||||
//canvas.addEventListener("mousemove", doClick, false);
|
|
||||||
|
|
||||||
|
|
||||||
var context = canvas.getContext('2d');
|
|
||||||
var centerX = canvas.width / 2;
|
|
||||||
var centerY = canvas.height / 2;
|
|
||||||
var innerRadius = canvas.width / 4.5;
|
|
||||||
var outerRadius = (canvas.width - 10) / 2
|
|
||||||
|
|
||||||
//outer border
|
|
||||||
context.beginPath();
|
|
||||||
//outer circle
|
|
||||||
context.arc(centerX, centerY, outerRadius, 0, 2 * Math.PI, false);
|
|
||||||
//draw the outer border: (gets drawn around the circle!)
|
|
||||||
context.lineWidth = 4;
|
|
||||||
context.strokeStyle = '#000000';
|
|
||||||
context.stroke();
|
|
||||||
context.closePath();
|
|
||||||
|
|
||||||
//fill with beautiful colors
|
|
||||||
//taken from here: http://stackoverflow.com/questions/18265804/building-a-color-wheel-in-html5
|
|
||||||
for(var angle=0; angle<=360; angle+=1) {
|
|
||||||
var startAngle = (angle-2)*Math.PI/180;
|
|
||||||
var endAngle = angle * Math.PI/180;
|
|
||||||
context.beginPath();
|
|
||||||
context.moveTo(centerX, centerY);
|
|
||||||
context.arc(centerX, centerY, outerRadius, startAngle, endAngle, false);
|
|
||||||
context.closePath();
|
|
||||||
context.fillStyle = 'hsl('+angle+', 100%, 50%)';
|
|
||||||
context.fill();
|
|
||||||
context.closePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
//inner border
|
|
||||||
context.beginPath();
|
|
||||||
//context.arc(centerX, centerY, radius, startAngle, endAngle, counterClockwise);
|
|
||||||
context.arc(centerX, centerY, innerRadius, 0, 2 * Math.PI, false);
|
|
||||||
//fill the center
|
|
||||||
var my_gradient=context.createLinearGradient(0,0,170,0);
|
|
||||||
my_gradient.addColorStop(0,"black");
|
|
||||||
my_gradient.addColorStop(1,"white");
|
|
||||||
|
|
||||||
context.fillStyle = my_gradient;
|
|
||||||
context.fillStyle = "white";
|
|
||||||
context.fill();
|
|
||||||
|
|
||||||
//draw the inner line
|
|
||||||
context.lineWidth = 2;
|
|
||||||
context.strokeStyle = '#000000';
|
|
||||||
context.stroke();
|
|
||||||
context.closePath();
|
|
||||||
|
|
||||||
//get Mouse x/y canvas position
|
|
||||||
function getMousePos(canvas, evt) {
|
|
||||||
var rect = canvas.getBoundingClientRect();
|
|
||||||
return {
|
|
||||||
x: evt.clientX - rect.left,
|
|
||||||
y: evt.clientY - rect.top
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//comp to Hex
|
|
||||||
function componentToHex(c) {
|
|
||||||
//var hex = c.toString(16);
|
|
||||||
//return hex.length == 1 ? "0" + hex : hex;
|
|
||||||
return ("0"+(Number(c).toString(16))).slice(-2).toUpperCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
//rgb/rgba to Hex
|
|
||||||
function rgbToHex(rgb) {
|
|
||||||
return componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//display the touch/click position and color info
|
|
||||||
function updateStatus(pos, color) {
|
|
||||||
var hexColor = rgbToHex(color);
|
|
||||||
wsSetAll(hexColor);
|
|
||||||
|
|
||||||
hexColor = "#" + hexColor;
|
|
||||||
|
|
||||||
$('#status').css("backgroundColor", hexColor);
|
|
||||||
$('#status_color').text(hexColor + " - R=" + color[0] + ", G=" + color[1] + ", B=" + color[2]);
|
|
||||||
$('#status_pos').text("x: " + pos.x + " - y: " + pos.y);
|
|
||||||
|
|
||||||
$("#rng_red").val(color[0]);
|
|
||||||
$("#rng_green").val(color[1]);
|
|
||||||
$("#rng_blue").val(color[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//handle the touch event
|
|
||||||
function doTouch(event) {
|
|
||||||
//to not also fire on click
|
|
||||||
event.preventDefault();
|
|
||||||
var el = event.target;
|
|
||||||
|
|
||||||
//touch position
|
|
||||||
var pos = {x: Math.round(event.targetTouches[0].pageX - el.offsetLeft),
|
|
||||||
y: Math.round(event.targetTouches[0].pageY - el.offsetTop)};
|
|
||||||
//color
|
|
||||||
var color = context.getImageData(pos.x, pos.y, 1, 1).data;
|
|
||||||
|
|
||||||
updateStatus(pos, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
function doClick(event) {
|
|
||||||
//click position
|
|
||||||
var pos = getMousePos(canvas, event);
|
|
||||||
//color
|
|
||||||
var color = context.getImageData(pos.x, pos.y, 1, 1).data;
|
|
||||||
|
|
||||||
//console.log("click", pos.x, pos.y, color);
|
|
||||||
updateStatus(pos, color);
|
|
||||||
|
|
||||||
//now do sth with the color rgbToHex(color);
|
|
||||||
//don't do stuff when #000000 (outside circle and lines
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// main
|
|
||||||
// ******************************************************************
|
|
||||||
init();
|
|
||||||
|
|
||||||
}); // end of document ready
|
|
||||||
})(jQuery); // end of jQuery name space
|
|
||||||
+49
-13
@@ -11,39 +11,72 @@
|
|||||||
[platformio]
|
[platformio]
|
||||||
src_dir = ./Arduino/McLighting/
|
src_dir = ./Arduino/McLighting/
|
||||||
data_dir = ./Arduino/McLighting/data/
|
data_dir = ./Arduino/McLighting/data/
|
||||||
env_default = nodemcuv2
|
default_envs = nodemcuv2
|
||||||
description = The ESP8266 based multi-client lighting gadget
|
description = The ESP8266 based multi-client lighting gadget
|
||||||
|
|
||||||
[common]
|
[common]
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# PLATFORM:
|
||||||
|
# !! DO NOT confuse platformio's ESP8266 development platform with Arduino core for ESP8266
|
||||||
|
# We use Arduino Core 2.5.0 (platformIO 2.0.4) as default
|
||||||
|
#
|
||||||
|
# arduino core 2.3.0 = platformIO 1.5.0
|
||||||
|
# arduino core 2.4.0 = platformIO 1.6.0
|
||||||
|
# arduino core 2.4.1 = platformIO 1.7.3
|
||||||
|
# arduino core 2.4.2 = platformIO 1.8.0
|
||||||
|
# arduino core 2.5.0 = platformIO 2.0.4
|
||||||
|
# arduino core 2.5.1 = platformIO 2.1.1
|
||||||
|
# arduino core 2.5.2 = platformIO 2.2.3
|
||||||
|
# arduino core 2.6.1 = platformIO 2.3.0
|
||||||
|
# arduino core 2.6.2 = platformIO 2.3.1
|
||||||
|
# arduino core 2.6.3 = platformIO 2.3.2
|
||||||
|
# arduino core stage = platformIO feature#stage
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
arduino_core_2_3_0 = espressif8266@1.5.0
|
||||||
|
arduino_core_2_4_0 = espressif8266@1.6.0
|
||||||
|
arduino_core_2_4_1 = espressif8266@1.7.3
|
||||||
|
arduino_core_2_4_2 = espressif8266@1.8.0
|
||||||
|
arduino_core_2_5_0 = espressif8266@2.0.4
|
||||||
|
arduino_core_2_5_1 = espressif8266@2.1.1
|
||||||
|
arduino_core_2_5_2 = espressif8266@2.2.3
|
||||||
|
arduino_core_2_6_1 = espressif8266@2.3.0
|
||||||
|
arduino_core_2_6_2 = espressif8266@2.3.1
|
||||||
|
arduino_core_2_6_3 = espressif8266@2.3.2
|
||||||
|
arduino_core_stage = https://github.com/platformio/platform-espressif8266.git#feature/stage
|
||||||
|
|
||||||
framework = arduino
|
framework = arduino
|
||||||
platform = espressif8266@1.8.0
|
;platform = ${common.arduino_core_2_4_2}
|
||||||
; platform = https://github.com/platformio/platform-espressif8266.git
|
platform = ${common.arduino_core_2_6_3}
|
||||||
; platform = https://github.com/platformio/platform-espressif8266.git#feature/stage
|
|
||||||
; platform = https://github.com/platformio/platform-espressif8266.git#develop
|
|
||||||
build_flags =
|
build_flags =
|
||||||
-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||||
-DMQTT_MAX_PACKET_SIZE=2048 ; PubSubClient Specific flags
|
-DMQTT_MAX_PACKET_SIZE=512 ; PubSubClient Specific flags
|
||||||
-w ; supress all warnings
|
-w ; supress all warnings
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
board_build.flash_mode = dout
|
board_build.flash_mode = dio
|
||||||
upload_speed = 115200
|
upload_speed = 115200
|
||||||
upload_resetmethod = nodemcu
|
upload_resetmethod = nodemcu
|
||||||
lib_deps =
|
lib_deps =
|
||||||
WiFiManager@0.14
|
WiFiManager
|
||||||
AsyncMqttClient
|
AsyncMqttClient
|
||||||
https://github.com/bblanchon/ArduinoJson.git#v6.7.0-beta
|
ArduinoJson
|
||||||
WS2812FX
|
WS2812FX
|
||||||
NeoPixelBus@2.4.1
|
NeoPixelBus
|
||||||
WebSockets
|
WebSockets
|
||||||
ESPAsyncE131
|
ESPAsyncE131
|
||||||
ESPAsyncUDP
|
ESPAsyncUDP
|
||||||
Brzo_I2C
|
https://github.com/FabLab-Luenen/GY33_MCU
|
||||||
|
Brzo I2C
|
||||||
|
IRremoteESP8266
|
||||||
|
FastLED
|
||||||
|
|
||||||
[env:esp01_1m]
|
[env:esp01_1m]
|
||||||
board = esp01_1m
|
board = esp01_1m
|
||||||
framework = ${common.framework}
|
framework = ${common.framework}
|
||||||
platform = ${common.platform}
|
platform = ${common.platform}
|
||||||
build_flags = ${common.build_flags} -D D1=2
|
board_build.f_cpu = 160000000L
|
||||||
|
build_flags =
|
||||||
|
${common.build_flags} -D D1=2
|
||||||
|
-Wl,-Teagle.flash.1m128.ld ; Required for core > v2.5.0 or staging version
|
||||||
monitor_speed = ${common.monitor_speed}
|
monitor_speed = ${common.monitor_speed}
|
||||||
upload_speed = ${common.upload_speed}
|
upload_speed = ${common.upload_speed}
|
||||||
upload_resetmethod = ${common.upload_resetmethod}
|
upload_resetmethod = ${common.upload_resetmethod}
|
||||||
@@ -54,7 +87,10 @@ lib_deps = ${common.lib_deps}
|
|||||||
board = nodemcuv2
|
board = nodemcuv2
|
||||||
framework = ${common.framework}
|
framework = ${common.framework}
|
||||||
platform = ${common.platform}
|
platform = ${common.platform}
|
||||||
build_flags = ${common.build_flags}
|
board_build.f_cpu = 160000000L
|
||||||
|
build_flags =
|
||||||
|
${common.build_flags}
|
||||||
|
-Wl,-Teagle.flash.4m2m.ld ; Required for core > v2.5.0 or staging version
|
||||||
monitor_speed = ${common.monitor_speed}
|
monitor_speed = ${common.monitor_speed}
|
||||||
upload_speed = ${common.upload_speed}
|
upload_speed = ${common.upload_speed}
|
||||||
upload_resetmethod = ${common.upload_resetmethod}
|
upload_resetmethod = ${common.upload_resetmethod}
|
||||||
|
|||||||
Reference in New Issue
Block a user