diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..2edd94122 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.pioenvs +.piolibdeps +.vscode +!.vscode/extensions.json diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..c4408c4cb --- /dev/null +++ b/.travis.yml @@ -0,0 +1,35 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + +language: python +python: + - "2.7" +sudo: false +cache: + directories: + - "~/.platformio" +env: + - PLATFORMIO_CI_SRC=wled00 +install: + - pip install -U platformio + - platformio update +script: + - platformio ci --project-conf=./platformio.ini -v diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..8281e64cc --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ] +} \ No newline at end of file diff --git a/include/README b/include/README new file mode 100644 index 000000000..194dcd432 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 000000000..6debab1e8 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 000000000..2ecc28ff9 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,121 @@ +; PlatformIO Project Configuration File +; Please visit documentation: https://docs.platformio.org/page/projectconf.html + +[platformio] +src_dir = ./wled00 +data_dir = ./wled00/data +lib_extra_dirs = ./wled00/src +; env_default = nodemcuv2 +env_default = esp01 +; env_default = esp01_1m +; env_default = d1_mini +; env_default = esp32dev + + +[common] +framework = arduino +monitor_speed = 115200 +board_build.flash_mode = dout +upload_speed = 921600 +build_flags = + ; -D VERSION=0.8.2-dev + ; -D DEBUG +# TODO replace libs in /lib with managed libs in here if possible. +# If they are not changed it's just a metter of setting the correfct version and change the import statement +lib_deps_external = + #Blynk@0.5.4 + #E131@1.0.0 + #webserver + FastLED@3.2.1 + NeoPixelBus@2.3.4 + #PubSubClient@2.7 + #Time@1.5 + #Timezone@1.2.1 + #WS2812FX@1.1.2 + +[common:esp8266] +platform = espressif8266@1.8.0 +build_flags = + -D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH + +[common:esp8266_512k] +platform = espressif8266@1.7.0 +build_flags = + -D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH + ; -D WLED_DISABLE_MOBILE_UI + -D WLED_DISABLE_OTA + -D WLED_DISABLE_ALEXA + ; -D WLED_DISABLE_BLYNK + ; -D WLED_DISABLE_CRONIXIE + -D WLED_DISABLE_HUESYNC + +[common:esp32] +platform = espressif32@1.5.0 +build_flags = + -D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH + -D ARDUINO_ARCH_ESP32 + -D WORKAROUND_ESP32_BITBANG + + +# see: http://docs.platformio.org/en/latest/platforms/espressif8266.html +[env:nodemcuv2] +board = nodemcuv2 +platform = ${common:esp8266.platform} +monitor_speed = ${common.monitor_speed} +upload_speed = ${common.upload_speed} +framework = ${common.framework} +build_flags = + ${common.build_flags} + ${common:esp8266.build_flags} +lib_deps = + ${common.lib_deps_external} + +[env:d1_mini] +board = d1_mini +platform = ${common:esp8266.platform} +monitor_speed = ${common.monitor_speed} +upload_speed = ${common.upload_speed} +framework = ${common.framework} +build_flags = + ${common.build_flags} + ${common:esp8266.build_flags} +lib_deps = + ${common.lib_deps_external} + +[env:esp01_1m] +board = esp01_1m +platform = ${common:esp8266.platform} +monitor_speed = ${common.monitor_speed} +upload_speed = ${common.upload_speed} +framework = ${common.framework} +build_flags = + ${common.build_flags} + ${common:esp8266.build_flags} +lib_deps = + ${common.lib_deps_external} + +[env:esp01] +board = esp01 +platform = ${common:esp8266_512k.platform} +monitor_speed = ${common.monitor_speed} +upload_speed = ${common.upload_speed} +framework = ${common.framework} +build_flags = + ${common.build_flags} + ${common:esp8266_512k.build_flags} +lib_deps = + ${common.lib_deps_external} + +# see: http://docs.platformio.org/en/latest/platforms/espressif32.html +[env:esp32dev] +board = esp32dev +platform = ${common:esp32.platform} +monitor_speed = ${common.monitor_speed} +upload_speed = ${common.upload_speed} +framework = ${common.framework} +build_flags = + ${common.build_flags} + ${common:esp32.build_flags} +lib_deps = + ${common.lib_deps_external} + \ No newline at end of file diff --git a/readme.md b/readme.md index 7eaffcdde..144412dba 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ ![WLED logo](https://raw.githubusercontent.com/Aircoookie/WLED/development/wled_logo.png) -## Welcome to my project WLED! (v0.8.1) +## Welcome to my project WLED! (v0.8.2-dev) A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B) LEDs! @@ -28,6 +28,7 @@ A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control - Sync to Philips hue lights - Adalight (PC ambilight via serial) - Sync color of multiple WLED devices (UDP notifier) +- Infrared remotes (24-key RGB, receiver required) - Simple timers/schedules (time from NTP, timezones/DST supported) ### Quick start guide and documentation: @@ -37,13 +38,13 @@ See the [wiki](https://github.com/Aircoookie/WLED/wiki)! ### Other Licensed under the MIT license -Credits in About page! +Credits [here](https://github.com/Aircoookie/WLED/wiki/Contributors-&-About)! Uses Linearicons by Perxis! Join the Discord [server](https://discord.gg/KuqP7NE) to discuss everything about WLED! You can also send me mails to [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com). -If you insist that you just love WLED too much, you can [send me a gift](https://paypal.me/aircoookie)! +If WLED really brightens up your every day, you can [send me a small gift](https://paypal.me/aircoookie)! diff --git a/test/README b/test/README new file mode 100644 index 000000000..df5066e64 --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h index 221fade57..c33c869c5 100644 --- a/wled00/NpbWrapper.h +++ b/wled00/NpbWrapper.h @@ -5,10 +5,12 @@ #define WORKAROUND_ESP32_BITBANG //see https://github.com/Aircoookie/WLED/issues/2 for flicker free ESP32 support -#define LEDPIN 2 //strip pin. Any for ESP32, gpio2 is recommended for ESP8266 +//PIN CONFIGURATION +#define LEDPIN 2 //strip pin. Any for ESP32, gpio2 is recommended for ESP8266 +#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended) +#define IR_PIN 4 //infrared pin. +#define AUXPIN 15 //unused auxiliary output pin -//uncomment this if red and green are swapped -//#define SWAPRG //automatically uses the right driver method for each platform @@ -31,14 +33,11 @@ #endif #endif -//handle swapping Red and Green automatically -#ifdef SWAPRG - #define PIXELFEATURE3 NeoRgbFeature - #define PIXELFEATURE4 NeoRgbwFeature -#else - #define PIXELFEATURE3 NeoGrbFeature - #define PIXELFEATURE4 NeoGrbwFeature -#endif + +//you can now change the color order in the web settings +#define PIXELFEATURE3 NeoGrbFeature +#define PIXELFEATURE4 NeoGrbwFeature + #include diff --git a/wled00/WS2812FX.cpp b/wled00/WS2812FX.cpp index 065079b64..60b90b9b2 100644 --- a/wled00/WS2812FX.cpp +++ b/wled00/WS2812FX.cpp @@ -59,7 +59,6 @@ void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst) _segments[0].stop = _length -1; unlockAll(); setBrightness(_brightness); - show(); _running = true; } @@ -93,7 +92,7 @@ void WS2812FX::clear() bool WS2812FX::modeUsesLock(uint8_t m) { - if (m == FX_MODE_FIRE_2012 || m == FX_MODE_COLORTWINKLE) return true; + if (m == FX_MODE_FIRE_2012 || m == FX_MODE_COLORTWINKLE || m == FX_MODE_METEOR || m == FX_MODE_METEOR_SMOOTH) return true; return false; } @@ -110,6 +109,14 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) if (_locked[i] && !modeUsesLock(SEGMENT.mode)) return; if (_reverseMode) i = _length - 1 -i; if (IS_REVERSE) i = SEGMENT.stop - (i - SEGMENT.start); //reverse just individual segment + byte tmpg = g; + switch (colorOrder) //0 = Grb, default + { + case 0: break; //0 = Grb, default + case 1: g = r; r = tmpg; break; //1 = Rgb, common for WS2811 + case 2: g = b; b = tmpg; break; //2 = Brg + case 3: g = b; b = r; r = tmpg; //3 = Rbg + } if (!_cronixieMode) { if (_skipFirstMode) {i++;if(i==1)bus->SetPixelColor(i, RgbwColor(0,0,0,0));} @@ -119,13 +126,13 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) byte o = 10*i; if (_cronixieBacklightEnabled && _cronixieDigits[i] <11) { - byte rCorr = (int)(((double)((_segments[0].colors[1]>>16) & 0xFF))*_cronixieSecMultiplier); - byte gCorr = (int)(((double)((_segments[0].colors[1]>>8) & 0xFF))*_cronixieSecMultiplier); - byte bCorr = (int)(((double)((_segments[0].colors[1]) & 0xFF))*_cronixieSecMultiplier); - byte wCorr = (int)(((double)((_segments[0].colors[1]>>24) & 0xFF))*_cronixieSecMultiplier); + byte r2 = (_segments[0].colors[1] >>16) & 0xFF; + byte g2 = (_segments[0].colors[1] >> 8) & 0xFF; + byte b2 = (_segments[0].colors[1] ) & 0xFF; + byte w2 = (_segments[0].colors[1] >>24) & 0xFF; for (int j=o; j< o+19; j++) { - bus->SetPixelColor((_skipFirstMode)?j+1:j,RgbwColor(rCorr,gCorr,bCorr,wCorr)); + bus->SetPixelColor((_skipFirstMode)?j+1:j,RgbwColor(r2,g2,b2,w2)); } } else { @@ -174,7 +181,75 @@ void WS2812FX::setCronixieDigits(byte d[]) } } + +//DISCLAIMER +//The following function attemps to calculate the current LED power usage, +//and will limit the brightness to stay below a set amperage threshold. +//It is NOT a measurement and NOT guaranteed to stay within the ablMilliampsMax margin. +//Stay safe with high amperage and have a reasonable safety margin! +//I am NOT to be held liable for burned down garages! + +//fine tune power estimation constants for your setup +#define PU_PER_MA 3600 //power units per milliamperere for accurate power estimation + //formula: 195075 divided by mA per fully lit LED, here ~54mA) + //lowering the value increases the estimated usage and therefore makes the ABL more aggressive + +#define MA_FOR_ESP 100 //how much mA does the ESP use (Wemos D1 about 80mA, ESP32 about 120mA) + //you can set it to 0 if the ESP is powered by USB and the LEDs by external + void WS2812FX::show(void) { + //power limit calculation + //each LED can draw up 195075 "power units" (approx. 53mA) + //one PU is the power it takes to have 1 channel 1 step brighter per brightness step + //so A=2,R=255,G=0,B=0 would use 510 PU per LED (1mA is about 3700 PU) + + if (ablMilliampsMax > 149 && ablMilliampsMax < 65000) //lower numbers and 65000 turn off calculation + { + uint32_t powerBudget = (ablMilliampsMax - MA_FOR_ESP) * PU_PER_MA; //100mA for ESP power + if (powerBudget > PU_PER_MA * _length) //each LED uses about 1mA in standby, exclude that from power budget + { + powerBudget -= PU_PER_MA * _length; + } else + { + powerBudget = 0; + } + + uint32_t powerSum = 0; + + for (uint16_t i = 0; i < _length; i++) //sum up the usage of each LED + { + RgbwColor c = bus->GetPixelColorRgbw(i); + powerSum += (c.R + c.G + c.B + c.W); + } + + if (_rgbwMode) //RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less + { + powerSum *= 3; + powerSum >> 2; //same as /= 4 + } + + uint32_t powerSum0 = powerSum; + powerSum *= _brightness; + + if (powerSum > powerBudget) //scale brightness down to stay in current limit + { + float scale = (float)powerBudget / (float)powerSum; + uint16_t scaleI = scale * 255; + uint8_t scaleB = (scaleI > 255) ? 255 : scaleI; + uint8_t newBri = scale8(_brightness, scaleB); + bus->SetBrightness(newBri); + currentMilliamps = (powerSum0 * newBri) / PU_PER_MA; + } else + { + currentMilliamps = powerSum / PU_PER_MA; + bus->SetBrightness(_brightness); + } + currentMilliamps += MA_FOR_ESP; //add power of ESP back to estimate + currentMilliamps += _length; //add standby power back to estimate + } else { + currentMilliamps = 0; + } + bus->Show(); } @@ -185,7 +260,8 @@ void WS2812FX::trigger() { void WS2812FX::setMode(uint8_t m) { RESET_RUNTIME; bool ua = modeUsesLock(_segments[0].mode) && !modeUsesLock(m); - _segments[0].mode = constrain(m, 0, MODE_COUNT - 1); + if (m > MODE_COUNT - 1) m = MODE_COUNT - 1; + _segments[0].mode = m; if (ua) unlockAll(); setBrightness(_brightness); } @@ -204,6 +280,16 @@ void WS2812FX::setPalette(uint8_t p) { _segments[0].palette = p; } +bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p) { + bool changed = false; + m = constrain(m, 0, MODE_COUNT - 1); + if (m != _segments[0].mode) { setMode(m); changed = true; } + if (s != _segments[0].speed) { setSpeed(s); changed = true; } + if (i != _segments[0].intensity) { setIntensity(i); changed = true; } + if (p != _segments[0].palette) { setPalette(p); changed = true; } + return changed; +} + void WS2812FX::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { setColor(((uint32_t)w << 24) |((uint32_t)r << 16) | ((uint32_t)g << 8) | b); } @@ -218,10 +304,10 @@ void WS2812FX::setColor(uint32_t c) { void WS2812FX::setSecondaryColor(uint32_t c) { _segments[0].colors[1] = c; - if (_cronixieMode) _cronixieSecMultiplier = getSafePowerMultiplier(900, 100, c, _brightness); } void WS2812FX::setBrightness(uint8_t b) { + if (_brightness == b) return; _brightness = b; bus->SetBrightness(_brightness); show(); @@ -275,7 +361,15 @@ uint32_t WS2812FX::getPixelColor(uint16_t i) } } RgbwColor lColor = bus->GetPixelColorRgbw(i); - return lColor.W*16777216 + lColor.R*65536 + lColor.G*256 + lColor.B; + byte r = lColor.R, g = lColor.G, b = lColor.B; + switch (colorOrder) + { + case 0: break; //0 = Grb + case 1: r = lColor.G; g = lColor.R; break; //1 = Rgb, common for WS2811 + case 2: g = lColor.B; b = lColor.G; break; //2 = Brg + case 3: r = lColor.B; g = lColor.R; b = lColor.G; //3 = Rbg + } + return ( (lColor.W << 24) | (r << 16) | (g << 8) | (b) ); } WS2812FX::Segment WS2812FX::getSegment(void) { @@ -414,33 +508,6 @@ uint32_t WS2812FX::color_blend(uint32_t color1, uint32_t color2, uint8_t blend) } -double WS2812FX::getPowerEstimate(uint16_t leds, uint32_t c, byte b) -{ - double _mARequired = 100; //ESP power - double _mul = (double)b/255; - double _sum = ((c & 0xFF000000) >> 24) + ((c & 0x00FF0000) >> 16) + ((c & 0x0000FF00) >> 8) + ((c & 0x000000FF) >> 0); - _sum /= (_rgbwMode)?1024:768; - double _mAPerLed = 50*(_mul*_sum); - _mARequired += leds*_mAPerLed; - return _mARequired; -} - -//DISCLAIMER -//This is just a helper function for huge amounts of LEDs. -//It is NOT guaranteed to stay within the safeAmps margin. -//Stay safe with high amperage and have a reasonable safety margin! -//I am NOT to be held liable for burned down garages! -double WS2812FX::getSafePowerMultiplier(double safeMilliAmps, uint16_t leds, uint32_t c, byte b) -{ - double _mARequired = getPowerEstimate(leds,c,b); - if (_mARequired > safeMilliAmps) - { - return safeMilliAmps/_mARequired; - } - return 1.0; -} - - /* ##################################################### # # Color and Blinken Functions @@ -2138,8 +2205,11 @@ void WS2812FX::handle_palette(void) { bool singleSegmentMode = (_segment_index == _segment_index_palette_last); _segment_index_palette_last = _segment_index; + + byte paletteIndex = SEGMENT.palette; + if ((SEGMENT.mode >= FX_MODE_METEOR) && SEGMENT.palette == 0) paletteIndex = 4; - switch (SEGMENT.palette) + switch (paletteIndex) { case 0: {//default palette. Differs depending on effect switch (SEGMENT.mode) @@ -2240,7 +2310,7 @@ uint16_t WS2812FX::mode_palette(void) setPixelColor(i, color_from_palette(colorIndex, false, true, 255)); } - SEGMENT_RUNTIME.counter_mode_step += SEGMENT.speed *2; + SEGMENT_RUNTIME.counter_mode_step += SEGMENT.speed; if (SEGMENT.speed == 0) SEGMENT_RUNTIME.counter_mode_step = 0; return 20; } @@ -2430,8 +2500,6 @@ uint16_t WS2812FX::mode_noise16_2(void) uint16_t shift_y = SEGMENT_RUNTIME.counter_mode_step/42; uint32_t real_x = (i + shift_x) * scale; // calculate the coordinates within the noise field - uint32_t real_y = (i + shift_y) * scale; // based on the precalculated positions - uint32_t real_z = 4223; uint8_t noise = inoise16(real_x, 0, 4223) >> 8; // get the noise data and scale it down @@ -2548,3 +2616,116 @@ uint16_t WS2812FX::mode_lake() { } return 33; } + + +// meteor effect +// send a meteor from begining to to the end of the strip with a trail that randomly decays. +// adapted from https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectMeteorRain +uint16_t WS2812FX::mode_meteor() { + byte meteorSize= 1+ SEGMENT_LENGTH / 10; + uint16_t in = SEGMENT.start + SEGMENT_RUNTIME.counter_mode_step; + + byte decayProb = 255 - SEGMENT.intensity; + + // fade all leds to colors[1] in LEDs one step + for (uint16_t i = SEGMENT.start; i <= SEGMENT.stop; i++) { + if (random8() <= decayProb) + { + byte meteorTrailDecay = 128 + random8(127); + _locked[i] = scale8(_locked[i], meteorTrailDecay); + setPixelColor(i, color_from_palette(_locked[i], false, true, 255)); + } + } + + // draw meteor + for(int j = 0; j < meteorSize; j++) { + uint16_t index = in + j; + if(in + j > SEGMENT.stop) { + index = SEGMENT.start + (in + j - SEGMENT.stop) -1; + } + + _locked[index] = 240; + setPixelColor(index, color_from_palette(_locked[index], false, true, 255)); + } + + SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % (SEGMENT_LENGTH); + return SPEED_FORMULA_L; +} + + +//smooth +//front ramping (maybe from get color +//50fps +//fade each led by a certain range (even ramp possible for sparkling) +//maybe dim to color[1] at end? +//_locked 0-15 bg-last 15-240 last-first 240-255 first-bg + +#define IS_PART_OF_METEOR 245 +// smooth meteor effect +// send a meteor from begining to to the end of the strip with a trail that randomly decays. +// adapted from https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectMeteorRain +uint16_t WS2812FX::mode_meteor_smooth() { + byte meteorSize= 1+ SEGMENT_LENGTH / 10; + uint16_t in = map((SEGMENT_RUNTIME.counter_mode_step >> 6 & 0xFF), 0, 255, SEGMENT.start, SEGMENT.stop); + + byte decayProb = 255 - SEGMENT.intensity; + + // fade all leds to colors[1] in LEDs one step + for (uint16_t i = SEGMENT.start; i <= SEGMENT.stop; i++) { + if (_locked[i] != IS_PART_OF_METEOR && _locked[i] != 0 && random8() <= decayProb) + { + int change = 3 - random8(12); //change each time between -8 and +3 + _locked[i] += change; + if (_locked[i] > 245) _locked[i] = 0; + if (_locked[i] > 240) _locked[i] = 240; + setPixelColor(i, color_from_palette(_locked[i], false, true, 255)); + } + } + + // draw meteor + for(int j = 0; j < meteorSize; j++) { + uint16_t index = in + j; + if(in + j > SEGMENT.stop) { + index = SEGMENT.start + (in + j - SEGMENT.stop) -1; + } + + _locked[index] = IS_PART_OF_METEOR; + setPixelColor(index, color_blend(getPixelColor(index), color_from_palette(240, false, true, 255), 48)); + + if (j == 0) _locked[index] = 240;//last pixel of meteor + } + + SEGMENT_RUNTIME.counter_mode_step += SEGMENT.speed +1; + return 20; +} + + +//Railway Crossing / Christmas Fairy lights +uint16_t WS2812FX::mode_railway() +{ + uint16_t dur = 40 + (255 - SEGMENT.speed) * 10; + uint16_t rampdur = (dur * SEGMENT.intensity) >> 8; + if (SEGMENT_RUNTIME.counter_mode_step > dur) + { + //reverse direction + SEGMENT_RUNTIME.counter_mode_step = 0; + SEGMENT_RUNTIME.aux_param = !SEGMENT_RUNTIME.aux_param; + } + uint8_t pos = 255; + if (rampdur != 0) + { + uint16_t p0 = (SEGMENT_RUNTIME.counter_mode_step * 255) / rampdur; + if (p0 < 255) pos = p0; + } + if (SEGMENT_RUNTIME.aux_param) pos = 255 - pos; + for (uint16_t i = SEGMENT.start; i <= SEGMENT.stop; i += 2) + { + setPixelColor(i, color_from_palette(255 - pos, false, false, 255)); + if (i != SEGMENT.stop) + { + setPixelColor(i + 1, color_from_palette(pos, false, false, 255)); + } + } + SEGMENT_RUNTIME.counter_mode_step += 20; + return 20; +} diff --git a/wled00/WS2812FX.h b/wled00/WS2812FX.h index 33e274ebf..679ee7312 100644 --- a/wled00/WS2812FX.h +++ b/wled00/WS2812FX.h @@ -44,9 +44,9 @@ #define FASTLED_INTERNAL //remove annoying pragma messages #include "FastLED.h" -#define DEFAULT_BRIGHTNESS (uint8_t)50 +#define DEFAULT_BRIGHTNESS (uint8_t)127 #define DEFAULT_MODE (uint8_t)0 -#define DEFAULT_SPEED (uint16_t)1000 +#define DEFAULT_SPEED (uint8_t)128 #define DEFAULT_COLOR (uint32_t)0xFF0000 #define min(a,b) ((a)<(b)?(a):(b)) @@ -85,7 +85,7 @@ #define REVERSE (uint8_t)0x80 #define IS_REVERSE ((SEGMENT.options & REVERSE) == REVERSE) -#define MODE_COUNT 76 +#define MODE_COUNT 79 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -164,6 +164,10 @@ #define FX_MODE_NOISE16_4 73 #define FX_MODE_COLORTWINKLE 74 #define FX_MODE_LAKE 75 +#define FX_MODE_METEOR 76 +#define FX_MODE_METEOR_SMOOTH 77 +#define FX_MODE_RAILWAY 78 + class WS2812FX { typedef uint16_t (WS2812FX::*mode_ptr)(void); @@ -268,6 +272,10 @@ class WS2812FX { _mode[FX_MODE_NOISE16_4] = &WS2812FX::mode_noise16_4; _mode[FX_MODE_COLORTWINKLE] = &WS2812FX::mode_colortwinkle; _mode[FX_MODE_LAKE] = &WS2812FX::mode_lake; + _mode[FX_MODE_METEOR] = &WS2812FX::mode_meteor; + _mode[FX_MODE_METEOR_SMOOTH] = &WS2812FX::mode_meteor_smooth; + _mode[FX_MODE_RAILWAY] = &WS2812FX::mode_railway; + _brightness = DEFAULT_BRIGHTNESS; _running = false; @@ -278,8 +286,11 @@ class WS2812FX { _segments[0].speed = DEFAULT_SPEED; _reverseMode = false; _skipFirstMode = false; + colorOrder = 0; paletteFade = 0; paletteBlend = 0; + ablMilliampsMax = 750; + currentMilliamps = 0; _locked = NULL; _cronixieDigits = new byte[6]; bus = new NeoPixelWrapper(); @@ -323,9 +334,13 @@ class WS2812FX { setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), show(void); + bool + setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p); + uint8_t paletteFade, paletteBlend, + colorOrder, getBrightness(void), getMode(void), getSpeed(void), @@ -339,10 +354,6 @@ class WS2812FX { getPixelColor(uint16_t), getColor(void); - double - getPowerEstimate(uint16_t leds, uint32_t c, byte b), - getSafePowerMultiplier(double safeMilliAmps, uint16_t leds, uint32_t c, byte b); - WS2812FX::Segment getSegment(void); @@ -354,6 +365,8 @@ class WS2812FX { // mode helper functions uint16_t + ablMilliampsMax, + currentMilliamps, blink(uint32_t, uint32_t, bool strobe, bool), color_wipe(uint32_t, uint32_t, bool , bool), scan(bool), @@ -443,6 +456,9 @@ class WS2812FX { mode_noise16_4(void), mode_colortwinkle(void), mode_lake(void), + mode_meteor(void), + mode_meteor_smooth(void), + mode_railway(void), mode_lightning(void); private: @@ -457,9 +473,6 @@ class WS2812FX { void handle_palette(void); bool modeUsesLock(uint8_t); - double - _cronixieSecMultiplier; - boolean _running, _rgbwMode, @@ -480,9 +493,9 @@ class WS2812FX { uint8_t _segment_index = 0; uint8_t _segment_index_palette_last = 99; uint8_t _num_segments = 1; - segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 20 bytes per element - // start, stop, speed, intensity, mode, options, color[] - { 0, 7, DEFAULT_SPEED, 128, FX_MODE_STATIC, NO_OPTIONS, {DEFAULT_COLOR}} + segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 21 bytes per element + // start, stop, speed, intensity, palette, mode, options, color[] + { 0, 7, DEFAULT_SPEED, 128, 0, FX_MODE_STATIC, NO_OPTIONS, {DEFAULT_COLOR}} }; segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 17 bytes per element }; diff --git a/wled00/data/index.htm b/wled00/data/index.htm index 954c19018..68ecbee74 100644 --- a/wled00/data/index.htm +++ b/wled00/data/index.htm @@ -2,7 +2,7 @@ - WLED 0.8.1 + WLED 0.8.2 )====="; @@ -27,12 +27,12 @@ button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-seri #ifndef WLED_DISABLE_MOBILE_UI const char PAGE_welcome0[] PROGMEM = R"=====( - + WLED Welcome! )====="; const char PAGE_welcome1[] PROGMEM = R"=====( -body{font-family:var(--cFn),sans-serif;text-align:center;background:linear-gradient(var(--bCol),black);height:100%;margin:0;background-repeat:no-repeat;background-attachment: fixed;color: var(--tCol);}svg {fill: var(--dCol);} +body{font-family:var(--cFn),sans-serif;text-align:center;background:linear-gradient(var(--bCol),black);margin:0;background-attachment: fixed;color: var(--tCol);}svg {fill: var(--dCol);} diff --git a/wled00/htmls01.h b/wled00/html_settings.h similarity index 86% rename from wled00/htmls01.h rename to wled00/html_settings.h index 36ced6af7..a83552d43 100644 --- a/wled00/htmls01.h +++ b/wled00/html_settings.h @@ -4,7 +4,7 @@ //common CSS of settings pages const char PAGE_settingsCss[] PROGMEM = R"=====( -body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol);color:var(--tCol);line-height:200%;margin:0;background-attachment:fixed}hr{border-color:var(--dCol);filter:drop-shadow(-5px -5px 5px var(--sCol))}button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:20px;margin:8px;margin-top:12px}.helpB{text-align:left;position:absolute;width:60px}input{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.5ch solid var(--bCol);filter:drop-shadow(-5px -5px 5px var(--sCol))}input[type=number]{width:3em}select{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:0.5ch solid var(--bCol);filter:drop-shadow( -5px -5px 5px var(--sCol) );} +body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol);color:var(--tCol);line-height:200%;margin:0;background-attachment:fixed}hr{border-color:var(--dCol);filter:drop-shadow(-5px -5px 5px var(--sCol))}button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:20px;margin:8px;margin-top:12px}.helpB{text-align:left;position:absolute;width:60px}input{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.5ch solid var(--bCol);filter:drop-shadow(-5px -5px 5px var(--sCol))}input[type=number]{width:4em}select{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:0.5ch solid var(--bCol);filter:drop-shadow( -5px -5px 5px var(--sCol) );} )====="; @@ -34,7 +34,7 @@ body{text-align:center;background:var(--cCol);height:100%;margin:0;background-at //wifi settings const char PAGE_settings_wifi0[] PROGMEM = R"=====( - + WiFi Settings -)====="; -#else -const char PAGE_indexM[] PROGMEM = R"=====( -Mobile UI is unsupported (limited storage). Go to /settings/ui and change UI mode to "Classic". -)====="; -#endif - - -/* - * Classic UI Index html - */ -//head0 (js) -const char PAGE_index0[] PROGMEM = R"=====( -WLED 0.8.1 - -)====="; - -//head1 (css) -const char PAGE_index1[] PROGMEM = R"=====( -.ctrl_box{margin:auto;width:80vw;background-color:var(--cCol);position:absolute;top:55%;left:50%;transform:translate(-50%,-50%);filter:drop-shadow(-5px -5px 5px var(--sCol))}.sds{width:100%;height:12vh;margin-top:2vh}.sl{margin-left:auto;margin-right:auto;margin-top:2vh;width:77vw}#slA{margin-top:0vh;background:linear-gradient(to right,black,yellow)}#slR{background:linear-gradient(to right,black,red)}#slG{background:linear-gradient(to right,black,green)}#slB{background:linear-gradient(to right,black,blue)}#slW{background:linear-gradient(to right,black,white)}#slH{background:linear-gradient(to right,red,orange,yellow,green,cyan,blue,violet,red)}#slS{background:linear-gradient(to right,grey,green)}#slN{background:linear-gradient(to right,black,turquoise)}#slT{background:linear-gradient(to right,black,yellow)}.tools{margin-left:auto;margin-right:auto;margin-top:2vh;width:77vw}#slX{background:linear-gradient(to right,black,white)}#slI{background:linear-gradient(to right,black,red)}body{font-family:var(--cFn),sans-serif;text-align:center;background:linear-gradient(var(--bCol),black);height:100%;margin:0;background-repeat:no-repeat;background-attachment:fixed;color:var(--tCol)}html{height:100%}iframe{display:none;border:0;filter:drop-shadow(-5px -5px 5px var(--sCol));margin:auto;width:80vw;height:60vh;position:absolute;top:55%;left:50%;transform:translate(-50%,-50%)}svg{fill:var(--dCol);width:12vw;height:10vmin;filter:drop-shadow(-5px -5px 5px var(--sCol))}input{filter:drop-shadow(-5px -5px 5px var(--sCol));}button{background:var(--bCol);color:var(--tCol);border:.5ch solid var(--bCol);margin-bottom:1vh;font-family:var(--cFn),sans-serif;filter:drop-shadow(-5px -5px 5px var(--sCol))}select{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.5ch solid var(--bCol);filter:drop-shadow(-5px -5px 5px var(--sCol))}input[type=number]{background:var(--bCol);color:var(--dCol);border:.5ch solid var(--bCol);font-family:var(--cFn),sans-serif;width:3em}input[type=range]{-webkit-appearance:none;margin:-4px 0}input[type=range]:focus{outline:0}input[type=range]::-webkit-slider-runnable-track{width:100%;height:12vh;cursor:pointer;background:var(--bCol)}input[type=range]::-webkit-slider-thumb{filter:drop-shadow(-5px -5px 5px var(--sCol));height:10vh;width:10vh;background:var(--aCol);cursor:pointer;-webkit-appearance:none;margin-top:1vh}input[type=range]::-moz-range-track{width:100%;height:12vh;cursor:pointer;background:var(--bCol)}input[type=range]::-moz-range-thumb{filter:drop-shadow(-5px -5px 5px var(--sCol));height:10vh;width:10vh;background:var(--aCol);cursor:pointer;margin-top:1vh}input[type=range]::-ms-track{width:100%;height:12vh;cursor:pointer;background:transparent;border-color:transparent;color:transparent}input[type=range]::-ms-fill-lower{background:#var(--bCol)}input[type=range]::-ms-fill-upper{background:#var(--bCol)}input[type=range]::-ms-thumb{width:10vh;background:var(--aCol);cursor:pointer;height:10vh} - - -Loading... -)====="; - -//body0 (svg defs) -const char PAGE_index2[] PROGMEM = R"=====( - - -//Linearicons.com/free - - - - - - - - - - - - - - - -)====="; - -//body1 (html) -const char PAGE_index3[] PROGMEM = R"=====( -
- - - - - - -
-
-
-
-
-
-
-
-
-Effect Panel

- - - -

-

-Set secondary color to - - - - - -or
-
FastLED Palette

-
-
-
-Favorite Presets

- - - - -


-Click checkmark to apply brightness, color and effects.

-Cycle through presets to , keep each for ms:

-
-Timed Light

-

-Gradually dim down
-1st slider sets duration (1-255min), 2nd sets target brightness.
-
-
-
- -)====="; diff --git a/wled00/ir_codes.h b/wled00/ir_codes.h new file mode 100644 index 000000000..e9043bd9f --- /dev/null +++ b/wled00/ir_codes.h @@ -0,0 +1,95 @@ +//Infrared codes + +//Add your custom codes here +#define IRCUSTOM_ONOFF 0xA55AEA15 //Pioneer RC-975R "+FAV" button (example) +#define IRCUSTOM_MACRO1 0xFFFFFFFF //placeholder, will never be checked for + +//Infrared codes for 24-key remote from http://woodsgood.ca/projects/2015/02/13/rgb-led-strip-controllers-ir-codes/ +#define IR24_BRIGHTER 0xF700FF +#define IR24_DARKER 0xF7807F +#define IR24_OFF 0xF740BF +#define IR24_ON 0xF7C03F +#define IR24_RED 0xF720DF +#define IR24_REDDISH 0xF710EF +#define IR24_ORANGE 0xF730CF +#define IR24_YELLOWISH 0xF708F7 +#define IR24_YELLOW 0xF728D7 +#define IR24_GREEN 0xF7A05F +#define IR24_GREENISH 0xF7906F +#define IR24_TURQUOISE 0xF7B04F +#define IR24_CYAN 0xF78877 +#define IR24_AQUA 0xF7A857 +#define IR24_BLUE 0xF7609F +#define IR24_DEEPBLUE 0xF750AF +#define IR24_PURPLE 0xF7708F +#define IR24_MAGENTA 0xF748B7 +#define IR24_PINK 0xF76897 +#define IR24_WHITE 0xF7E01F +#define IR24_FLASH 0xF7D02F +#define IR24_STROBE 0xF7F00F +#define IR24_FADE 0xF7C837 +#define IR24_SMOOTH 0xF7E817 + +/* 44-key defs, to be done later +#define IR44_BPlus 0xFF3AC5 // +#define IR44_BMinus 0xFFBA45 // +#define IR44_ON 0xFF827D // +#define IR44_OFF 0xFF02FD // +#define IR44_R 0xFF1AE5 // +#define IR44_G 0xFF9A65 // +#define IR44_B 0xFFA25D // +#define IR44_W 0xFF22DD // +#define IR44_B1 0xFF2AD5 // +#define IR44_B2 0xFFAA55 // +#define IR44_B3 0xFF926D // +#define IR44_B4 0xFF12ED // +#define IR44_B5 0xFF0AF5 // +#define IR44_B6 0xFF8A75 // +#define IR44_B7 0xFFB24D // +#define IR44_B8 0xFF32CD // +#define IR44_B9 0xFF38C7 // +#define IR44_B10 0xFFB847 // +#define IR44_B11 0xFF7887 // +#define IR44_B12 0xFFF807 // +#define IR44_B13 0xFF18E7 // +#define IR44_B14 0xFF9867 // +#define IR44_B15 0xFF58A7 // +#define IR44_B16 0xFFD827 // +#define IR44_UPR 0xFF28D7 // +#define IR44_UPG 0xFFA857 // +#define IR44_UPB 0xFF6897 // +#define IR44_QUICK 0xFFE817 // +#define IR44_DOWNR 0xFF08F7 // +#define IR44_DOWNG 0xFF8877 // +#define IR44_DOWNB 0xFF48B7 // +#define IR44_SLOW 0xFFC837 // +#define IR44_DIY1 0xFF30CF // +#define IR44_DIY2 0xFFB04F // +#define IR44_DIY3 0xFF708F // +#define IR44_AUTO 0xFFF00F // +#define IR44_DIY4 0xFF10EF // +#define IR44_DIY5 0xFF906F // +#define IR44_DIY6 0xFF50AF // +#define IR44_FLASH 0xFFD02F // +#define IR44_JUMP3 0xFF20DF // +#define IR44_JUMP7 0xFFA05F // +#define IR44_FADE3 0xFF609F // +#define IR44_FADE7 0xFFE01F // +*/ + +#define COLOR_RED 0xFF0000 +#define COLOR_REDDISH 0xFF7800 +#define COLOR_ORANGE 0xFFA000 +#define COLOR_YELLOWISH 0xFFC800 +#define COLOR_YELLOW 0xFFFF00 +#define COLOR_GREEN 0x00FF00 +#define COLOR_GREENISH 0x00FF78 +#define COLOR_TURQUOISE 0x00FFA0 +#define COLOR_CYAN 0x00FFDC +#define COLOR_AQUA 0x00C8FF +#define COLOR_BLUE 0x00A0FF +#define COLOR_DEEPBLUE 0x0000FF +#define COLOR_PURPLE 0xAA00FF +#define COLOR_MAGENTA 0xFF00DC +#define COLOR_PINK 0xFF00A0 +#define COLOR_WHITE 0xFFFFDC diff --git a/wled00/wled00.ino b/wled00/wled00.ino index a04e0f461..fd6dc154c 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -3,7 +3,7 @@ */ /* * @title WLED project sketch - * @version 0.8.1 + * @version 0.8.2 * @author Christian Schwinne */ @@ -11,21 +11,22 @@ //ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.3.0 and the setting 512K(64K SPIFFS). //ESP8266-01 (black) has 1MB flash and can thus fit the whole program. Use 1M(64K SPIFFS). -//If you want the OTA update function though, you need to make sure the sketch is smaller than 479kB. //Uncomment some of the following lines to disable features to compile for ESP8266-01 (max flash size 434kB): -//You are required to disable these two features: -//#define WLED_DISABLE_MOBILE_UI -//#define WLED_DISABLE_OTA +//You are required to disable over-the-air updates: +#define WLED_DISABLE_OTA //You need to choose 1-2 of these features to disable: //#define WLED_DISABLE_ALEXA //#define WLED_DISABLE_BLYNK //#define WLED_DISABLE_CRONIXIE -//#define WLED_DISABLE_HUESYNC +#define WLED_DISABLE_HUESYNC +#define WLED_DISABLE_INFRARED //there is no pin left for this on ESP8266-01 +//#define WLED_DISABLE_MOBILE_UI //to toggle usb serial debug (un)comment following line(s) -//#define DEBUG +//#define WLED_DEBUG + //library inclusions #include @@ -34,11 +35,19 @@ #include #include "src/dependencies/webserver/WebServer.h" #include + /*#ifndef WLED_DISABLE_INFRARED + #include + #endif*/ //there are issues with ESP32 infrared, so it is disabled for now #else #include #include #include #include + #ifndef WLED_DISABLE_INFRARED + #include + #include + #include + #endif #endif #include @@ -56,15 +65,17 @@ #endif #include "src/dependencies/e131/E131.h" #include "src/dependencies/pubsubclient/PubSubClient.h" -#include "htmls00.h" -#include "htmls01.h" -#include "htmls02.h" +#include "html_classic.h" +#include "html_mobile.h" +#include "html_settings.h" +#include "html_other.h" #include "WS2812FX.h" +#include "ir_codes.h" //version code in format yymmddb (b = daily build) -#define VERSION 1811091 -char versionString[] = "0.8.1"; +#define VERSION 1812052 +char versionString[] = "0.8.2"; //AP and OTA default passwords (for maximum change them!) @@ -77,9 +88,8 @@ char otaPass[33] = "wledota"; //Hardware CONFIG (only changeble HERE, not at runtime) -//LED strip pin changeable in NpbWrapper.h. Only change for ESP32 -byte buttonPin = 0; //needs pull-up -byte auxPin = 15; //debug feature, use e.g. for external relay with API call AX= +//LED strip pin, button pin and IR pin changeable in NpbWrapper.h! + byte auxDefaultState = 0; //0: input 1: high 2: low byte auxTriggeredState = 0; //0: input 1: high 2: low char ntpServerName[] = "0.wled.pool.ntp.org"; //NTP server to use @@ -101,9 +111,10 @@ IPAddress staticDNS(8, 8, 8, 8); //only for NTP, google DNS server //LED CONFIG -uint16_t ledCount = 10; //lowered to prevent accidental overcurrent +uint16_t ledCount = 30; //overcurrent prevented by ABL bool useRGBW = false; //SK6812 strips can contain an extra White channel bool autoRGBtoRGBW = false; //if RGBW enabled, calculate White channel from RGB +#define ABL_MILLIAMPS_DEFAULT 850; //auto lower brightness to stay close to milliampere limit bool turnOnAtBoot = true; //turn on LEDs at power-up byte bootPreset = 0; //save preset to load after power-up @@ -144,7 +155,8 @@ bool useHSBDefault = useHSB; //Sync CONFIG -bool buttonEnabled = true; +bool buttonEnabled = true; +bool irEnabled = false; //Infrared receiver uint16_t udpPort = 21324; //WLED notifier default port uint16_t udpRgbPort = 19446; //Hyperion port @@ -153,7 +165,7 @@ bool receiveNotificationBrightness = true; //apply brightness from incoming n bool receiveNotificationColor = true; //apply color bool receiveNotificationEffects = true; //apply effects setup bool notifyDirect = true; //send notification if change via UI or HTTP API -bool notifyButton = true; +bool notifyButton = true; //send if updated by button or infrared remote bool notifyAlexa = false; //send notification if updated via Alexa bool notifyMacro = false; //send notification for macro bool notifyHue = true; //send notification if Hue light changes @@ -254,6 +266,7 @@ float tperLast = 0; //crossfade transition progress, 0 bool nightlightActive = false; bool nightlightActiveOld = false; uint32_t nightlightDelayMs = 10; +uint8_t nightlightDelayMinsDefault = nightlightDelayMins; unsigned long nightlightStartTime; byte briNlT = 0; //current nightlight brightness @@ -287,7 +300,6 @@ bool udpConnected = false, udpRgbConnected = false; //ui style char cssCol[6][9]={"","","","","",""}; -String cssColorString=""; bool showWelcomePage = false; //hue @@ -335,7 +347,7 @@ bool presetCyclingEnabled = false; byte presetCycleMin = 1, presetCycleMax = 5; uint16_t presetCycleTime = 1250; unsigned long presetCycledTime = 0; byte presetCycCurr = presetCycleMin; -bool presetApplyBri = true, presetApplyCol = true, presetApplyFx = true; +bool presetApplyBri = false, presetApplyCol = true, presetApplyFx = true; bool saveCurrPresetCycConf = false; //realtime @@ -376,7 +388,7 @@ unsigned int ntpLocalPort = 2390; #define NTP_PACKET_SIZE 48 //string temp buffer -#define OMAX 1750 +#define OMAX 2000 char obuf[OMAX]; uint16_t olen = 0; @@ -403,7 +415,7 @@ E131* e131; WS2812FX strip = WS2812FX(); //debug macros -#ifdef DEBUG +#ifdef WLED_DEBUG #define DEBUG_PRINT(x) Serial.print (x) #define DEBUG_PRINTLN(x) Serial.println (x) #define DEBUG_PRINTF(x) Serial.printf (x) @@ -493,6 +505,7 @@ void loop() { yield(); handleButton(); + handleIR(); handleNetworkTime(); if (!onlyAP) { @@ -519,7 +532,7 @@ void loop() { } //DEBUG serial logging - #ifdef DEBUG + #ifdef WLED_DEBUG if (millis() - debugTime > 5000) { DEBUG_PRINTLN("---MODULE DEBUG INFO---"); diff --git a/wled00/wled01_eeprom.ino b/wled00/wled01_eeprom.ino index 197c9fd5a..4927433e3 100644 --- a/wled00/wled01_eeprom.ino +++ b/wled00/wled01_eeprom.ino @@ -6,7 +6,7 @@ #define EEPSIZE 3072 //eeprom Version code, enables default settings instead of 0 init on update -#define EEPVER 9 +#define EEPVER 10 //0 -> old version, default //1 -> 0.4p 1711272 and up //2 -> 0.4p 1711302 and up @@ -17,6 +17,8 @@ //7 -> 0.7.1 and up //8 -> 0.8.0-a and up //9 -> 0.8.0 +//10-> 0.8.2 + /* * Erase all configuration data @@ -30,6 +32,7 @@ void clearEEPROM() EEPROM.commit(); } + void writeStringToEEPROM(uint16_t pos, char* str, uint16_t len) { for (int i = 0; i < len; ++i) @@ -39,6 +42,7 @@ void writeStringToEEPROM(uint16_t pos, char* str, uint16_t len) } } + void readStringFromEEPROM(uint16_t pos, char* str, uint16_t len) { for (int i = 0; i < len; ++i) @@ -49,6 +53,7 @@ void readStringFromEEPROM(uint16_t pos, char* str, uint16_t len) str[len] = 0; //make sure every string is properly terminated. str must be at least len +1 big. } + /* * Write configuration to flash */ @@ -66,12 +71,12 @@ void saveSettingsToEEPROM() writeStringToEEPROM(128, apSSID, 32); writeStringToEEPROM(160, apPass, 64); - EEPROM.write(224, nightlightDelayMins); + EEPROM.write(224, nightlightDelayMinsDefault); EEPROM.write(225, nightlightFade); EEPROM.write(226, notifyDirectDefault); EEPROM.write(227, apChannel); EEPROM.write(228, apHide); - EEPROM.write(229, (ledCount >> 0) & 0xFF); + EEPROM.write(229, ledCount & 0xFF); EEPROM.write(230, notifyButton); EEPROM.write(231, notifyTwice); EEPROM.write(232, buttonEnabled); @@ -92,7 +97,7 @@ void saveSettingsToEEPROM() EEPROM.write(250, receiveNotificationBrightness); EEPROM.write(251, fadeTransition); EEPROM.write(252, reverseMode); - EEPROM.write(253, (transitionDelayDefault >> 0) & 0xFF); + EEPROM.write(253, transitionDelayDefault & 0xFF); EEPROM.write(254, (transitionDelayDefault >> 8) & 0xFF); EEPROM.write(255, briMultiplier); @@ -101,7 +106,7 @@ void saveSettingsToEEPROM() EEPROM.write(288, nightlightTargetBri); EEPROM.write(289, otaLock); - EEPROM.write(290, (udpPort >> 0) & 0xFF); + EEPROM.write(290, udpPort & 0xFF); EEPROM.write(291, (udpPort >> 8) & 0xFF); writeStringToEEPROM(292, serverDescription, 32); @@ -138,14 +143,19 @@ void saveSettingsToEEPROM() EEPROM.write(380, colSecS[2]); EEPROM.write(381, whiteSecS); EEPROM.write(382, strip.paletteBlend); - + EEPROM.write(383, strip.colorOrder); + + EEPROM.write(385, irEnabled); + + EEPROM.write(387, strip.ablMilliampsMax & 0xFF); + EEPROM.write(388, (strip.ablMilliampsMax >> 8) & 0xFF); EEPROM.write(389, bootPreset); EEPROM.write(390, aOtaEnabled); EEPROM.write(391, receiveNotificationColor); EEPROM.write(392, receiveNotificationEffects); EEPROM.write(393, wifiLock); - EEPROM.write(394, (abs(utcOffsetSecs) >> 0) & 0xFF); + EEPROM.write(394, abs(utcOffsetSecs) & 0xFF); EEPROM.write(395, (abs(utcOffsetSecs) >> 8) & 0xFF); EEPROM.write(396, (utcOffsetSecs<0)); //is negative EEPROM.write(397, initLedsLast); @@ -170,7 +180,7 @@ void saveSettingsToEEPROM() EEPROM.write(i, hueIP[i-2050]); } writeStringToEEPROM(2054, hueApiKey, 46); - EEPROM.write(2100, (huePollIntervalMs >> 0) & 0xFF); + EEPROM.write(2100, huePollIntervalMs & 0xFF); EEPROM.write(2101, (huePollIntervalMs >> 8) & 0xFF); EEPROM.write(2102, notifyHue); EEPROM.write(2103, hueApplyOnOff); @@ -205,10 +215,10 @@ void saveSettingsToEEPROM() EEPROM.write(2180, macroCountdown); EEPROM.write(2181, macroNl); - EEPROM.write(2190, (e131Universe >> 0) & 0xFF); + EEPROM.write(2190, e131Universe & 0xFF); EEPROM.write(2191, (e131Universe >> 8) & 0xFF); EEPROM.write(2192, e131Multicast); - EEPROM.write(2193, (realtimeTimeoutMs >> 0) & 0xFF); + EEPROM.write(2193, realtimeTimeoutMs & 0xFF); EEPROM.write(2194, (realtimeTimeoutMs >> 8) & 0xFF); EEPROM.write(2195, arlsForceMaxBri); EEPROM.write(2196, arlsDisableGammaCorrection); @@ -222,7 +232,7 @@ void saveSettingsToEEPROM() if (saveCurrPresetCycConf) { EEPROM.write(2205, presetCyclingEnabled); - EEPROM.write(2206, (presetCycleTime >> 0) & 0xFF); + EEPROM.write(2206, presetCycleTime & 0xFF); EEPROM.write(2207, (presetCycleTime >> 8) & 0xFF); EEPROM.write(2208, presetCycleMin); EEPROM.write(2209, presetCycleMax); @@ -246,9 +256,10 @@ void saveSettingsToEEPROM() writeStringToEEPROM(2333, mqttDeviceTopic, 32); writeStringToEEPROM(2366, mqttGroupTopic, 32); - EEPROM.commit(); + commit(); } + /* * Read all configuration from flash */ @@ -256,7 +267,9 @@ void loadSettingsFromEEPROM(bool first) { if (EEPROM.read(233) != 233) //first boot/reset to default { + DEBUG_PRINT("Settings invalid, restoring defaults..."); saveSettingsToEEPROM(); + DEBUG_PRINTLN("done"); return; } int lastEEPROMversion = EEPROM.read(377); //last EEPROM version before update @@ -268,7 +281,8 @@ void loadSettingsFromEEPROM(bool first) readStringFromEEPROM(128, apSSID, 32); readStringFromEEPROM(160, apPass, 64); - nightlightDelayMins = EEPROM.read(224); + nightlightDelayMinsDefault = EEPROM.read(224); + nightlightDelayMins = nightlightDelayMinsDefault; nightlightFade = EEPROM.read(225); notifyDirectDefault = EEPROM.read(226); notifyDirect = notifyDirectDefault; @@ -277,7 +291,7 @@ void loadSettingsFromEEPROM(bool first) if (apChannel > 13 || apChannel < 1) apChannel = 1; apHide = EEPROM.read(228); if (apHide > 1) apHide = 1; - ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10; + ledCount = EEPROM.read(229) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 30; notifyButton = EEPROM.read(230); notifyTwice = EEPROM.read(231); @@ -307,7 +321,7 @@ void loadSettingsFromEEPROM(bool first) receiveNotificationBrightness = EEPROM.read(250); fadeTransition = EEPROM.read(251); reverseMode = EEPROM.read(252); - transitionDelayDefault = ((EEPROM.read(253) << 0) & 0xFF) + ((EEPROM.read(254) << 8) & 0xFF00); + transitionDelayDefault = EEPROM.read(253) + ((EEPROM.read(254) << 8) & 0xFF00); transitionDelay = transitionDelayDefault; briMultiplier = EEPROM.read(255); @@ -315,7 +329,7 @@ void loadSettingsFromEEPROM(bool first) nightlightTargetBri = EEPROM.read(288); otaLock = EEPROM.read(289); - udpPort = ((EEPROM.read(290) << 0) & 0xFF) + ((EEPROM.read(291) << 8) & 0xFF00); + udpPort = EEPROM.read(290) + ((EEPROM.read(291) << 8) & 0xFF00); readStringFromEEPROM(292, serverDescription, 32); @@ -377,7 +391,7 @@ void loadSettingsFromEEPROM(bool first) readStringFromEEPROM(2054, hueApiKey, 46); - huePollIntervalMs = ((EEPROM.read(2100) << 0) & 0xFF) + ((EEPROM.read(2101) << 8) & 0xFF00); + huePollIntervalMs = EEPROM.read(2100) + ((EEPROM.read(2101) << 8) & 0xFF00); notifyHue = EEPROM.read(2102); hueApplyOnOff = EEPROM.read(2103); hueApplyBri = EEPROM.read(2104); @@ -413,9 +427,9 @@ void loadSettingsFromEEPROM(bool first) if (lastEEPROMversion > 6) { - e131Universe = ((EEPROM.read(2190) << 0) & 0xFF) + ((EEPROM.read(2191) << 8) & 0xFF00); + e131Universe = EEPROM.read(2190) + ((EEPROM.read(2191) << 8) & 0xFF00); e131Multicast = EEPROM.read(2192); - realtimeTimeoutMs = ((EEPROM.read(2193) << 0) & 0xFF) + ((EEPROM.read(2194) << 8) & 0xFF00); + realtimeTimeoutMs = EEPROM.read(2193) + ((EEPROM.read(2194) << 8) & 0xFF00); arlsForceMaxBri = EEPROM.read(2195); arlsDisableGammaCorrection = EEPROM.read(2196); } @@ -430,8 +444,8 @@ void loadSettingsFromEEPROM(bool first) timerHours[i] = EEPROM.read(2260 + i); timerMinutes[i] = EEPROM.read(2270 + i); timerWeekday[i] = EEPROM.read(2280 + i); + timerMacro[i] = EEPROM.read(2290 + i); if (timerWeekday[i] == 0) timerWeekday[i] = 255; - timerMacro[i] = EEPROM.read(2290 + i); } } @@ -441,6 +455,18 @@ void loadSettingsFromEEPROM(bool first) readStringFromEEPROM(2333, mqttDeviceTopic, 32); readStringFromEEPROM(2366, mqttGroupTopic, 32); } + + if (lastEEPROMversion > 9) + { + strip.colorOrder = EEPROM.read(383); + irEnabled = EEPROM.read(385); + strip.ablMilliampsMax = EEPROM.read(387) + ((EEPROM.read(388) << 8) & 0xFF00); + } else if (lastEEPROMversion > 1) //ABL is off by default when updating from version older than 0.8.2 + { + strip.ablMilliampsMax = 65000; + } else { + strip.ablMilliampsMax = ABL_MILLIAMPS_DEFAULT; + } receiveDirect = !EEPROM.read(2200); enableRealtimeUI = EEPROM.read(2201); @@ -457,7 +483,7 @@ void loadSettingsFromEEPROM(bool first) if (EEPROM.read(2210) || EEPROM.read(2211) || EEPROM.read(2212)) { presetCyclingEnabled = EEPROM.read(2205); - presetCycleTime = ((EEPROM.read(2206) << 0) & 0xFF) + ((EEPROM.read(2207) << 8) & 0xFF00); + presetCycleTime = EEPROM.read(2206) + ((EEPROM.read(2207) << 8) & 0xFF00); presetCycleMin = EEPROM.read(2208); presetCycleMax = EEPROM.read(2209); presetApplyBri = EEPROM.read(2210); @@ -467,7 +493,7 @@ void loadSettingsFromEEPROM(bool first) bootPreset = EEPROM.read(389); wifiLock = EEPROM.read(393); - utcOffsetSecs = ((EEPROM.read(394) << 0) & 0xFF) + ((EEPROM.read(395) << 8) & 0xFF00); + utcOffsetSecs = EEPROM.read(394) + ((EEPROM.read(395) << 8) & 0xFF00); if (EEPROM.read(396)) utcOffsetSecs = -utcOffsetSecs; //negative initLedsLast = EEPROM.read(397); enableSecTransition = !EEPROM.read(399); @@ -491,23 +517,24 @@ void loadSettingsFromEEPROM(bool first) useHSB = useHSBDefault; - strip.setMode(effectCurrent); - strip.setSpeed(effectSpeed); - strip.setIntensity(effectIntensity); - strip.setPalette(effectPalette); overlayCurrent = overlayDefault; } + //PRESET PROTOCOL 20 bytes //0: preset purpose byte 0:invalid 1:valid preset 1.0 //1:a 2:r 3:g 4:b 5:w 6:er 7:eg 8:eb 9:ew 10:fx 11:sx | custom chase 12:numP 13:numS 14:(0:fs 1:both 2:fe) 15:step 16:ix 17: fp 18-19:Zeros -void applyPreset(byte index, bool loadBri, bool loadCol, bool loadFX) +bool applyPreset(byte index, bool loadBri = true, bool loadCol = true, bool loadFX = true) { - if (index == 255 || index == 0) loadSettingsFromEEPROM(false);//load boot defaults - if (index > 25 || index < 1) return; + if (index == 255 || index == 0) + { + loadSettingsFromEEPROM(false);//load boot defaults + return true; + } + if (index > 25 || index < 1) return false; uint16_t i = 380 + index*20; - if (EEPROM.read(i) == 0) return; + if (EEPROM.read(i) == 0) return false; if (loadBri) bri = EEPROM.read(i+1); if (loadCol) { @@ -522,16 +549,12 @@ void applyPreset(byte index, bool loadBri, bool loadCol, bool loadFX) } if (loadFX) { - byte lastfx = effectCurrent; effectCurrent = EEPROM.read(i+10); effectSpeed = EEPROM.read(i+11); effectIntensity = EEPROM.read(i+16); effectPalette = EEPROM.read(i+17); - if (lastfx != effectCurrent) strip.setMode(effectCurrent); - strip.setSpeed(effectSpeed); - strip.setIntensity(effectIntensity); - strip.setPalette(effectPalette); } + return true; } void savePreset(byte index) @@ -554,9 +577,10 @@ void savePreset(byte index) EEPROM.write(i+16, effectIntensity); EEPROM.write(i+17, effectPalette); - EEPROM.commit(); + commit(); } + String loadMacro(byte index) { index-=1; @@ -570,6 +594,7 @@ String loadMacro(byte index) return m; } + void applyMacro(byte index) { index-=1; @@ -588,6 +613,7 @@ void applyMacro(byte index) handleSet(mc); } + void saveMacro(byte index, String mc, bool sing=true) //only commit on single save, not in settings { index-=1; @@ -597,5 +623,23 @@ void saveMacro(byte index, String mc, bool sing=true) //only commit on single sa { EEPROM.write(i, mc.charAt(i-s)); } - if (sing) EEPROM.commit(); + if (sing) commit(); +} + + +void commit() +{ + DEBUG_PRINT("s"); + //this is to support IR on ESP32, needs work + /*#ifdef ARDUINO_ARCH_ESP32 + portMUX_TYPE mMux = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL(&mMux); + #endif*/ + + EEPROM.commit(); + + /*#ifdef ARDUINO_ARCH_ESP32 + portEXIT_CRITICAL(&mMux); + #endif*/ + DEBUG_PRINT("."); } diff --git a/wled00/wled02_xml.ino b/wled00/wled02_xml.ino index 8c6307ef5..2d3e31656 100644 --- a/wled00/wled02_xml.ino +++ b/wled00/wled02_xml.ino @@ -3,7 +3,7 @@ */ //build XML response to HTTP /win API request -void XML_response(bool isHTTP) +void XML_response(bool isHTTP, bool includeTheme) { olen = 0; oappend(""); @@ -47,7 +47,28 @@ void XML_response(bool isHTTP) oappendi(useHSB); oappend(""); oappend(serverDescription); - oappend(""); + oappend(""); + if (includeTheme) + { + char cs[6][9]; + getThemeColors(cs); + oappend("#"); + oappend(cs[0]); + oappend("#"); + oappend(cs[1]); + oappend("#"); + oappend(cs[2]); + oappend("#"); + oappend(cs[3]); + oappend("#"); + oappend(cs[4]); + oappend("#"); + oappend(cs[5]); + oappend(""); + oappend(cssFont); + oappend(""); + } + oappend(""); if (isHTTP) server.send(200, "text/xml", obuf); } @@ -170,11 +191,20 @@ void getSettingsJS(byte subPage) if (subPage == 2) { sappend('v',"LC",ledCount); + sappend('v',"MA",strip.ablMilliampsMax); + if (strip.currentMilliamps) + { + sappends('m',"(\"pow\")[0]",""); + olen -= 2; //delete "; + oappendi(strip.currentMilliamps); + oappend("mA\";"); + } sappend('v',"CR",colS[0]); sappend('v',"CG",colS[1]); sappend('v',"CB",colS[2]); sappend('v',"CA",briS); sappend('c',"EW",useRGBW); + sappend('i',"CO",strip.colorOrder); sappend('c',"AW",autoRGBtoRGBW); sappend('v',"CW",whiteS); sappend('v',"SR",colSecS[0]); @@ -195,7 +225,7 @@ void getSettingsJS(byte subPage) sappend('c',"T2",enableSecTransition); sappend('v',"BF",briMultiplier); sappend('v',"TB",nightlightTargetBri); - sappend('v',"TL",nightlightDelayMins); + sappend('v',"TL",nightlightDelayMinsDefault); sappend('c',"TW",nightlightFade); sappend('i',"PB",strip.paletteBlend); sappend('c',"RV",reverseMode); @@ -221,6 +251,7 @@ void getSettingsJS(byte subPage) if (subPage == 4) { sappend('c',"BT",buttonEnabled); + sappend('c',"IR",irEnabled); sappend('v',"UP",udpPort); sappend('c',"RB",receiveNotificationBrightness); sappend('c',"RC",receiveNotificationColor); @@ -320,3 +351,29 @@ void getSettingsJS(byte subPage) } oappend("}"); } + + +//get colors from current theme as c strings +void getThemeColors(char o[][9]) +{ + switch (currentTheme) + { + // accent color (aCol) background (bCol) panel (cCol) controls (dCol) shadows (sCol) text (tCol) + default: strcpy(o[0], "D9B310"); strcpy(o[1], "0B3C5D"); strcpy(o[2], "1D2731"); strcpy(o[3], "328CC1"); strcpy(o[4], "000"); strcpy(o[5], "328CC1"); break; //night + case 1: strcpy(o[0], "eee"); strcpy(o[1], "ddd"); strcpy(o[2], "b9b9b9"); strcpy(o[3], "049"); strcpy(o[4], "777"); strcpy(o[5], "049"); break; //modern + case 2: strcpy(o[0], "abc"); strcpy(o[1], "fff"); strcpy(o[2], "ddd"); strcpy(o[3], "000"); strcpy(o[4], "0004"); strcpy(o[5], "000"); break; //bright + case 3: strcpy(o[0], "c09f80"); strcpy(o[1], "d7cec7"); strcpy(o[2], "76323f"); strcpy(o[3], "888"); strcpy(o[4], "3334"); strcpy(o[5], "888"); break; //wine + case 4: strcpy(o[0], "3cc47c"); strcpy(o[1], "828081"); strcpy(o[2], "d9a803"); strcpy(o[3], "1e392a"); strcpy(o[4], "000a"); strcpy(o[5], "1e392a"); break; //electric + case 5: strcpy(o[0], "57bc90"); strcpy(o[1], "a5a5af"); strcpy(o[2], "015249"); strcpy(o[3], "88c9d4"); strcpy(o[4], "0004"); strcpy(o[5], "88c9d4"); break; //mint + case 6: strcpy(o[0], "f7c331"); strcpy(o[1], "dcc7aa"); strcpy(o[2], "6b7a8f"); strcpy(o[3], "f7882f"); strcpy(o[4], "0007"); strcpy(o[5], "f7882f"); break; //amber + case 7: strcpy(o[0], "fc3"); strcpy(o[1], "124"); strcpy(o[2], "334"); strcpy(o[3], "f1d"); strcpy(o[4], "f00"); strcpy(o[5], "f1d"); break; //club + case 8: strcpy(o[0], "0ac"); strcpy(o[1], "124"); strcpy(o[2], "224"); strcpy(o[3], "003eff"); strcpy(o[4], "003eff"); strcpy(o[5], "003eff"); break; //air + case 9: strcpy(o[0], "f70"); strcpy(o[1], "421"); strcpy(o[2], "221"); strcpy(o[3], "a50"); strcpy(o[4], "f70"); strcpy(o[5], "f70"); break; //nixie + case 10: strcpy(o[0], "2d2"); strcpy(o[1], "010"); strcpy(o[2], "121"); strcpy(o[3], "060"); strcpy(o[4], "040"); strcpy(o[5], "3f3"); break; //terminal + case 11: strcpy(o[0], "867ADE"); strcpy(o[1], "4033A3"); strcpy(o[2], "483AAA"); strcpy(o[3], "483AAA"); strcpy(o[4], ""); strcpy(o[5], "867ADE"); break; //c64 + case 12: strcpy(o[0], "fbe8a6"); strcpy(o[1], "d2fdff"); strcpy(o[2], "b4dfe5"); strcpy(o[3], "f4976c"); strcpy(o[4], ""); strcpy(o[5], "303c6c"); break; //easter + case 13: strcpy(o[0], "d4af37"); strcpy(o[1], "173305"); strcpy(o[2], "308505"); strcpy(o[3], "f21313"); strcpy(o[4], "f002"); strcpy(o[5], "d4af37"); break; //christmas + case 14: strcpy(o[0], "fc7"); strcpy(o[1], "49274a"); strcpy(o[2], "94618e"); strcpy(o[3], "f4decb"); strcpy(o[4], "0008"); strcpy(o[5], "f4decb"); break; //end + case 15: for (int i=0;i<6;i++) strcpy(o[i], cssCol[i]); //custom + } +} diff --git a/wled00/wled03_set.ino b/wled00/wled03_set.ino index 4b52a4c1c..175796ade 100644 --- a/wled00/wled03_set.ino +++ b/wled00/wled03_set.ino @@ -59,7 +59,9 @@ void handleSettingsSet(byte subPage) #ifdef ARDUINO_ARCH_ESP32 if (ledCount > 600) ledCount = 600; #endif + strip.ablMilliampsMax = server.arg("MA").toInt(); useRGBW = server.hasArg("EW"); + strip.colorOrder = server.arg("CO").toInt(); autoRGBtoRGBW = server.hasArg("AW"); //ignore settings and save current brightness, colors and fx as default @@ -109,7 +111,7 @@ void handleSettingsSet(byte subPage) nightlightTargetBri = server.arg("TB").toInt(); t = server.arg("TL").toInt(); - if (t > 0) nightlightDelayMins = t; + if (t > 0) nightlightDelayMinsDefault = t; nightlightFade = server.hasArg("TW"); t = server.arg("PB").toInt(); @@ -138,13 +140,13 @@ void handleSettingsSet(byte subPage) strcpy(cssCol[i],server.arg(k).c_str()); } strcpy(cssFont,server.arg("CF").c_str()); - buildCssColorString(); } //SYNC if (subPage == 4) { buttonEnabled = server.hasArg("BT"); + irEnabled = server.hasArg("IR"); int t = server.arg("UP").toInt(); if (t > 0) udpPort = t; receiveNotificationBrightness = server.hasArg("RB"); @@ -280,7 +282,7 @@ void handleSettingsSet(byte subPage) if (server.hasArg("RS")) //complete factory reset { clearEEPROM(); - serveMessage(200, "All Settings erased.", "Connect to WLED-AP to setup again...",255); + serveMessage(200, "All Settings erased.", "Connect to WLED-AP to setup again",255); reset(); } @@ -309,9 +311,17 @@ void handleSettingsSet(byte subPage) if (subPage == 2) strip.init(useRGBW,ledCount,skipFirstLed); } + +//helper to get int value at a position in string +int getNumVal(String* req, uint16_t pos) +{ + return req->substring(pos + 3).toInt(); +} + + +//HTTP API request parser bool handleSet(String req) { - bool effectUpdated = false; if (!(req.indexOf("win") >= 0)) return false; int pos = 0; @@ -331,7 +341,7 @@ bool handleSet(String req) } pos = req.indexOf("IN"); - if (pos < 1) XML_response(true); + if (pos < 1) XML_response(true, false); return true; //if you save a macro in one request, other commands in that request are ignored due to unwanted behavior otherwise } @@ -339,17 +349,17 @@ bool handleSet(String req) //set brigthness pos = req.indexOf("&A="); if (pos > 0) { - bri = req.substring(pos + 3).toInt(); + bri = getNumVal(&req, pos); } //set hue pos = req.indexOf("HU="); if (pos > 0) { - uint16_t temphue = req.substring(pos + 3).toInt(); + uint16_t temphue = getNumVal(&req, pos); byte tempsat = 255; pos = req.indexOf("SA="); if (pos > 0) { - tempsat = req.substring(pos + 3).toInt(); + tempsat = getNumVal(&req, pos); } colorHStoRGB(temphue,tempsat,(req.indexOf("H2")>0)? colSec:col); } @@ -357,43 +367,43 @@ bool handleSet(String req) //set red value pos = req.indexOf("&R="); if (pos > 0) { - col[0] = req.substring(pos + 3).toInt(); + col[0] = getNumVal(&req, pos); } //set green value pos = req.indexOf("&G="); if (pos > 0) { - col[1] = req.substring(pos + 3).toInt(); + col[1] = getNumVal(&req, pos); } //set blue value pos = req.indexOf("&B="); if (pos > 0) { - col[2] = req.substring(pos + 3).toInt(); + col[2] = getNumVal(&req, pos); } //set white value pos = req.indexOf("&W="); if (pos > 0) { - white = req.substring(pos + 3).toInt(); + white = getNumVal(&req, pos); } //set 2nd red value pos = req.indexOf("R2="); if (pos > 0) { - colSec[0] = req.substring(pos + 3).toInt(); + colSec[0] = getNumVal(&req, pos); } //set 2nd green value pos = req.indexOf("G2="); if (pos > 0) { - colSec[1] = req.substring(pos + 3).toInt(); + colSec[1] = getNumVal(&req, pos); } //set 2nd blue value pos = req.indexOf("B2="); if (pos > 0) { - colSec[2] = req.substring(pos + 3).toInt(); + colSec[2] = getNumVal(&req, pos); } //set 2nd white value pos = req.indexOf("W2="); if (pos > 0) { - whiteSec = req.substring(pos + 3).toInt(); + whiteSec = getNumVal(&req, pos); } //set color from HEX or 32bit DEC @@ -433,7 +443,7 @@ bool handleSet(String req) //set to random hue SR=0->1st SR=1->2nd pos = req.indexOf("SR"); if (pos > 0) { - _setRandomColor(req.substring(pos + 3).toInt()); + _setRandomColor(getNumVal(&req, pos)); } //set 2nd to 1st pos = req.indexOf("SP"); @@ -461,48 +471,28 @@ bool handleSet(String req) //set current effect index pos = req.indexOf("FX="); if (pos > 0) { - if (effectCurrent != req.substring(pos + 3).toInt()) - { - effectCurrent = req.substring(pos + 3).toInt(); - strip.setMode(effectCurrent); - effectUpdated = true; - } + effectCurrent = getNumVal(&req, pos); } //set effect speed pos = req.indexOf("SX="); if (pos > 0) { - if (effectSpeed != req.substring(pos + 3).toInt()) - { - effectSpeed = req.substring(pos + 3).toInt(); - strip.setSpeed(effectSpeed); - effectUpdated = true; - } + effectSpeed = getNumVal(&req, pos); } //set effect intensity pos = req.indexOf("IX="); if (pos > 0) { - if (effectIntensity != req.substring(pos + 3).toInt()) - { - effectIntensity = req.substring(pos + 3).toInt(); - strip.setIntensity(effectIntensity); - effectUpdated = true; - } + effectIntensity = req.substring(pos + 3).toInt(); } //set effect palette (only for FastLED effects) pos = req.indexOf("FP="); if (pos > 0) { - if (effectPalette != req.substring(pos + 3).toInt()) - { - effectPalette = req.substring(pos + 3).toInt(); - strip.setPalette(effectPalette); - effectUpdated = true; - } + effectPalette = req.substring(pos + 3).toInt(); } //set hue polling light: 0 -off pos = req.indexOf("HP="); if (pos > 0) { - int id = req.substring(pos + 3).toInt(); + int id = getNumVal(&req, pos); if (id > 0) { if (id < 100) huePollLightId = id; @@ -515,21 +505,21 @@ bool handleSet(String req) //set default control mode (0 - RGB, 1 - HSB) pos = req.indexOf("MD="); if (pos > 0) { - useHSB = req.substring(pos + 3).toInt(); + useHSB = getNumVal(&req, pos); } //set advanced overlay pos = req.indexOf("OL="); if (pos > 0) { - overlayCurrent = req.substring(pos + 3).toInt(); + overlayCurrent = getNumVal(&req, pos); strip.unlockAll(); } //(un)lock pixel (ranges) pos = req.indexOf("&L="); if (pos > 0){ - int index = req.substring(pos + 3).toInt(); + int index = getNumVal(&req, pos); pos = req.indexOf("L2="); if (pos > 0){ - int index2 = req.substring(pos + 3).toInt(); + int index2 = getNumVal(&req, pos); if (req.indexOf("UL") > 0) { strip.unlockRange(index, index2); @@ -552,7 +542,7 @@ bool handleSet(String req) //apply macro pos = req.indexOf("&M="); if (pos > 0) { - applyMacro(req.substring(pos + 3).toInt()); + applyMacro(getNumVal(&req, pos)); } //toggle send UDP direct notifications if (req.indexOf("SN=") > 0) @@ -586,7 +576,7 @@ bool handleSet(String req) bri = briT; } else { nightlightActive = true; - if (!aNlDef) nightlightDelayMins = req.substring(pos + 3).toInt(); + if (!aNlDef) nightlightDelayMins = getNumVal(&req, pos); nightlightStartTime = millis(); } } else if (aNlDef) @@ -598,7 +588,7 @@ bool handleSet(String req) //set nightlight target brightness pos = req.indexOf("NT="); if (pos > 0) { - nightlightTargetBri = req.substring(pos + 3).toInt(); + nightlightTargetBri = getNumVal(&req, pos); nightlightActiveOld = false; //re-init } @@ -617,31 +607,24 @@ bool handleSet(String req) //toggle general purpose output pos = req.indexOf("AX="); if (pos > 0) { - auxTime = req.substring(pos + 3).toInt(); + auxTime = getNumVal(&req, pos); auxActive = true; if (auxTime == 0) auxActive = false; } pos = req.indexOf("TT="); if (pos > 0) { - transitionDelay = req.substring(pos + 3).toInt(); + transitionDelay = getNumVal(&req, pos); } //main toggle on/off pos = req.indexOf("&T="); if (pos > 0) { nightlightActive = false; //always disable nightlight when toggling - switch (req.substring(pos + 3).toInt()) + switch (getNumVal(&req, pos)) { case 0: if (bri != 0){briLast = bri; bri = 0;} break; //off case 1: bri = briLast; break; //on - default: if (bri == 0) //toggle - { - bri = briLast; - } else - { - briLast = bri; - bri = 0; - } + default: toggleOnOff(); //toggle } } @@ -650,22 +633,22 @@ bool handleSet(String req) //set time (unix timestamp) pos = req.indexOf("ST="); if (pos > 0) { - setTime(req.substring(pos+3).toInt()); + setTime(getNumVal(&req, pos)); } //set countdown goal (unix timestamp) pos = req.indexOf("CT="); if (pos > 0) { - countdownTime = req.substring(pos+3).toInt(); + countdownTime = getNumVal(&req, pos); if (countdownTime - now() > 0) countdownOverTriggered = false; } //set presets pos = req.indexOf("P1="); //sets first preset for cycle - if (pos > 0) presetCycleMin = req.substring(pos + 3).toInt(); + if (pos > 0) presetCycleMin = getNumVal(&req, pos); pos = req.indexOf("P2="); //sets last preset for cycle - if (pos > 0) presetCycleMax = req.substring(pos + 3).toInt(); + if (pos > 0) presetCycleMax = getNumVal(&req, pos); if (req.indexOf("CY=") > 0) //preset cycle { @@ -678,7 +661,7 @@ bool handleSet(String req) } pos = req.indexOf("PT="); //sets cycle time in ms if (pos > 0) { - int v = req.substring(pos + 3).toInt(); + int v = getNumVal(&req, pos); if (v > 49) presetCycleTime = v; } if (req.indexOf("PA=") > 0) //apply brightness from preset @@ -699,12 +682,11 @@ bool handleSet(String req) pos = req.indexOf("PS="); //saves current in preset if (pos > 0) { - savePreset(req.substring(pos + 3).toInt()); + savePreset(getNumVal(&req, pos)); } pos = req.indexOf("PL="); //applies entire preset if (pos > 0) { - applyPreset(req.substring(pos + 3).toInt(), presetApplyBri, presetApplyCol, presetApplyFx); - if (presetApplyFx) effectUpdated = true; + applyPreset(getNumVal(&req, pos), presetApplyBri, presetApplyCol, presetApplyFx); } //cronixie @@ -734,30 +716,20 @@ bool handleSet(String req) pos = req.indexOf("U0="); //user var 0 if (pos > 0) { - userVar0 = req.substring(pos + 3).toInt(); + userVar0 = getNumVal(&req, pos); } pos = req.indexOf("U1="); //user var 1 if (pos > 0) { - userVar1 = req.substring(pos + 3).toInt(); + userVar1 = getNumVal(&req, pos); } //you can add more if you need //internal call, does not send XML response pos = req.indexOf("IN"); - if (pos < 1) XML_response(true); - //do not send UDP notifications this time - pos = req.indexOf("NN"); - if (pos > 0) - { - colorUpdated(5); - return true; - } - if (effectUpdated) - { - colorUpdated(6); - } else - { - colorUpdated(1); - } + if (pos < 1) XML_response(true, (req.indexOf("IT") > 0)); //include theme if firstload + + pos = req.indexOf("NN"); //do not send UDP notifications this time + colorUpdated((pos > 0) ? 5:1); + return true; } diff --git a/wled00/wled05_init.ino b/wled00/wled05_init.ino index 04d4dd211..ab98c7a69 100644 --- a/wled00/wled05_init.ino +++ b/wled00/wled05_init.ino @@ -5,7 +5,8 @@ void wledInit() { EEPROM.begin(EEPSIZE); - ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10; + ledCount = EEPROM.read(229) + ((EEPROM.read(398) << 8) & 0xFF00); + if (ledCount > 1200 || ledCount == 0) ledCount = 30; //RMT eats up too much RAM #ifdef ARDUINO_ARCH_ESP32 if (ledCount > 600) ledCount = 600; @@ -24,7 +25,6 @@ void wledInit() if (!initLedsLast) initStrip(); DEBUG_PRINT("CSSID: "); DEBUG_PRINT(clientSSID); - buildCssColorString(); userBeginPreConnection(); if (strcmp(clientSSID,"Your_Network") == 0) showWelcomePage = true; @@ -121,10 +121,12 @@ void wledInit() if (initLedsLast) initStrip(); userBegin(); + if (macroBoot>0) applyMacro(macroBoot); Serial.println("Ada"); } + void initStrip() { // Initialize NeoPixel Strip and button @@ -133,18 +135,16 @@ void initStrip() strip.setColor(0); strip.setBrightness(255); - pinMode(buttonPin, INPUT_PULLUP); - pinMode(4,OUTPUT); //this is only needed in special cases - digitalWrite(4,LOW); + pinMode(BTNPIN, INPUT_PULLUP); if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true); colorUpdated(0); //disable button if it is "pressed" unintentionally - if(digitalRead(buttonPin) == LOW) buttonEnabled = false; - + if(digitalRead(BTNPIN) == LOW) buttonEnabled = false; } + void initAP(){ bool set = apSSID[0]; if (!set) strcpy(apSSID,"WLED-AP"); @@ -152,6 +152,7 @@ void initAP(){ if (!set) apSSID[0] = 0; } + void initCon() { WiFi.disconnect(); //close old connections @@ -230,6 +231,12 @@ void getBuildInfo() oappendi(VERSION); oappend("\r\neepver: "); oappendi(EEPVER); + oappend("\r\nesp-core: "); + #ifdef ARDUINO_ARCH_ESP32 + oappend((char*)ESP.getSdkVersion()); + #else + oappend((char*)ESP.getCoreVersion().c_str()); + #endif oappend("\r\nopt: "); #ifndef WLED_DISABLE_ALEXA oappend("alexa "); @@ -254,16 +261,16 @@ void getBuildInfo() #else oappend("\r\nspiffs: false\r\n"); #endif - #ifdef DEBUG + #ifdef WLED_DEBUG oappend("debug: true\r\n"); #else oappend("debug: false\r\n"); #endif oappend("button-pin: gpio"); - oappendi(buttonPin); + oappendi(BTNPIN); oappend("\r\nstrip-pin: gpio"); oappendi(LEDPIN); - oappend("\r\nbrand: wled\r\n"); + oappend("\r\nbrand: wled"); oappend("\r\nbuild-type: src\r\n"); } diff --git a/wled00/wled07_notify.ino b/wled00/wled07_notify.ino index faa524d81..958f8a593 100644 --- a/wled00/wled07_notify.ino +++ b/wled00/wled07_notify.ino @@ -5,6 +5,7 @@ #define WLEDPACKETSIZE 24 #define UDP_IN_MAXSIZE 1472 + void notify(byte callMode, bool followUp=false) { if (!udpConnected) return; @@ -53,6 +54,7 @@ void notify(byte callMode, bool followUp=false) notificationTwoRequired = (followUp)? false:notifyTwice; } + void arlsLock(uint32_t timeoutMs) { if (!realtimeActive){ @@ -60,13 +62,14 @@ void arlsLock(uint32_t timeoutMs) { strip.setPixelColor(i,0,0,0,0); } - strip.setMode(0); + strip.unlockAll(); } realtimeActive = true; realtimeTimeout = millis() + timeoutMs; if (arlsForceMaxBri) strip.setBrightness(255); } + void initE131(){ if (WiFi.status() == WL_CONNECTED && e131Enabled) { @@ -77,6 +80,7 @@ void initE131(){ } } + void handleE131(){ //E1.31 protocol support if(e131Enabled) { @@ -98,6 +102,7 @@ void handleE131(){ } } + void handleNotifications() { //send second notification if enabled @@ -110,10 +115,10 @@ void handleNotifications() //unlock strip when realtime UDP times out if (realtimeActive && millis() > realtimeTimeout) { - strip.unlockAll(); + //strip.unlockAll(); strip.setBrightness(bri); realtimeActive = false; - strip.setMode(effectCurrent); + //strip.setMode(effectCurrent); realtimeIP[0] = 0; } @@ -150,56 +155,49 @@ void handleNotifications() olen = 0; notifierUdp.read(obuf, packetSize); char* udpIn = obuf; - - if (udpIn[0] == 0 && !realtimeActive && receiveNotifications) //wled notifier, block if realtime packets active + + //wled notifier, block if realtime packets active + if (udpIn[0] == 0 && !realtimeActive && receiveNotifications) { + //apply colors from notification if (receiveNotificationColor) { - col[0] = udpIn[3]; - col[1] = udpIn[4]; - col[2] = udpIn[5]; - } - if (udpIn[11] > 0 && receiveNotificationColor) //check if sending modules white val is inteded - { - white = udpIn[10]; - if (udpIn[11] > 1 ) + col[0] = udpIn[3]; + col[1] = udpIn[4]; + col[2] = udpIn[5]; + if (udpIn[11] > 0) //check if sending modules white val is inteded { - colSec[0] = udpIn[12]; - colSec[1] = udpIn[13]; - colSec[2] = udpIn[14]; - whiteSec = udpIn[15]; + white = udpIn[10]; + if (udpIn[11] > 1) + { + colSec[0] = udpIn[12]; + colSec[1] = udpIn[13]; + colSec[2] = udpIn[14]; + whiteSec = udpIn[15]; + } } } - if (udpIn[8] != effectCurrent && receiveNotificationEffects) + + //apply effects from notification + if (receiveNotificationEffects) { effectCurrent = udpIn[8]; - strip.setMode(effectCurrent); - } - if (udpIn[9] != effectSpeed && receiveNotificationEffects) - { - effectSpeed = udpIn[9]; - strip.setSpeed(effectSpeed); - } - if (udpIn[11] > 2 && udpIn[16] != effectIntensity && receiveNotificationEffects) - { - effectIntensity = udpIn[16]; - strip.setIntensity(effectIntensity); + effectSpeed = udpIn[9]; + if (udpIn[11] > 2) effectIntensity = udpIn[16]; + if (udpIn[11] > 4) effectPalette = udpIn[19]; } + if (udpIn[11] > 3) { transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00); } - if (udpIn[11] > 4 && udpIn[19] != effectPalette && receiveNotificationEffects) - { - effectPalette = udpIn[19]; - strip.setPalette(effectPalette); - } + nightlightActive = udpIn[6]; - if (!nightlightActive) - { - if (receiveNotificationBrightness) bri = udpIn[2]; - colorUpdated(3); - } + if (nightlightActive) nightlightDelayMins = udpIn[7]; + + if (receiveNotificationBrightness) bri = udpIn[2]; + colorUpdated(3); + } else if (udpIn[0] > 0 && udpIn[0] < 4 && receiveDirect) //1 warls //2 drgb //3 drgbw { realtimeIP = notifierUdp.remoteIP(); @@ -252,6 +250,7 @@ void handleNotifications() } } + void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w) { uint16_t pix = i + arlsOffset; diff --git a/wled00/wled08_led.ino b/wled00/wled08_led.ino index 48e27984f..ffda2762e 100644 --- a/wled00/wled08_led.ino +++ b/wled00/wled08_led.ino @@ -2,6 +2,19 @@ * LED methods */ +void toggleOnOff() +{ + if (bri == 0) + { + bri = briLast; + } else + { + briLast = bri; + bri = 0; + } +} + + void setAllLeds() { if (!realtimeActive || !arlsForceMaxBri) { @@ -38,6 +51,7 @@ void setAllLeds() { } } + void setLedsStandard() { for (byte i = 0; i<3; i++) @@ -56,6 +70,7 @@ void setLedsStandard() setAllLeds(); } + bool colorChanged() { for (int i = 0; i < 3; i++) @@ -68,12 +83,19 @@ bool colorChanged() return false; } + void colorUpdated(int callMode) { - //call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (NN)6: fx changed 7: hue 8: preset cycle 9: blynk + //call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification) + // 6: fx changed 7: hue 8: preset cycle 9: blynk + bool fxChanged = strip.setEffectConfig(effectCurrent, effectSpeed, effectIntensity, effectPalette); if (!colorChanged()) { - if (callMode == 6) notify(6); + if (nightlightActive && !nightlightActiveOld && callMode != 3 && callMode != 5) + { + notify(4); return; + } + else if (fxChanged) notify(6); return; //no change } if (callMode != 5 && nightlightActive && nightlightFade) @@ -133,6 +155,7 @@ void colorUpdated(int callMode) updateInterfaces(callMode); } + void updateInterfaces(uint8_t callMode) { if (callMode != 9 && callMode != 5) updateBlynk(); @@ -140,6 +163,7 @@ void updateInterfaces(uint8_t callMode) lastInterfaceUpdate = millis(); } + void handleTransitions() { //handle still pending interface update @@ -180,6 +204,7 @@ void handleTransitions() } } + void handleNightlight() { if (nightlightActive) @@ -187,7 +212,6 @@ void handleNightlight() if (!nightlightActiveOld) //init { nightlightStartTime = millis(); - notify(4); nightlightDelayMs = (int)(nightlightDelayMins*60000); nightlightActiveOld = true; briNlT = bri; diff --git a/wled00/wled09_button.ino b/wled00/wled09_button.ino index e28653b7a..839049277 100644 --- a/wled00/wled09_button.ino +++ b/wled00/wled09_button.ino @@ -6,15 +6,15 @@ void handleButton() { if (buttonEnabled) { - if (digitalRead(buttonPin) == LOW && !buttonPressedBefore) + if (digitalRead(BTNPIN) == LOW && !buttonPressedBefore) { buttonPressedTime = millis(); buttonPressedBefore = true; } - else if (digitalRead(buttonPin) == HIGH && buttonPressedBefore) + else if (digitalRead(BTNPIN) == HIGH && buttonPressedBefore) { delay(15); //debounce - if (digitalRead(buttonPin) == HIGH) + if (digitalRead(BTNPIN) == HIGH) { if (millis() - buttonPressedTime > 7000) {initAP();} else if (millis() - buttonPressedTime > 700) @@ -25,14 +25,7 @@ void handleButton() else { if (macroButton == 0) { - if (bri == 0) - { - bri = briLast; - } else - { - briLast = bri; - bri = 0; - } + toggleOnOff(); colorUpdated(2); } else { applyMacro(macroButton); @@ -51,9 +44,9 @@ void handleButton() auxActiveBefore = true; switch (auxTriggeredState) { - case 0: pinMode(auxPin, INPUT); break; - case 1: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, HIGH); break; - case 2: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, LOW); break; + case 0: pinMode(AUXPIN, INPUT); break; + case 1: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, HIGH); break; + case 2: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, LOW); break; } auxStartTime = millis(); } @@ -63,9 +56,9 @@ void handleButton() auxActiveBefore = false; switch (auxDefaultState) { - case 0: pinMode(auxPin, INPUT); break; - case 1: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, HIGH); break; - case 2: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, LOW); break; + case 0: pinMode(AUXPIN, INPUT); break; + case 1: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, HIGH); break; + case 2: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, LOW); break; } } } diff --git a/wled00/wled14_colors.ino b/wled00/wled14_colors.ino index 5140cf7e7..5dbf378bd 100644 --- a/wled00/wled14_colors.ino +++ b/wled00/wled14_colors.ino @@ -2,6 +2,14 @@ * Color conversion methods */ +void colorFromUint32(uint32_t in) +{ + white = in >> 24 & 0xFF; + col[0] = in >> 16 & 0xFF; + col[1] = in >> 8 & 0xFF; + col[2] = in & 0xFF; +} + void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb { float h = ((float)hue)/65535.0; diff --git a/wled00/wled16_blynk.ino b/wled00/wled16_blynk.ino index da9641805..df070d097 100644 --- a/wled00/wled16_blynk.ino +++ b/wled00/wled16_blynk.ino @@ -66,22 +66,19 @@ BLYNK_WRITE(V3) BLYNK_WRITE(V4) { effectCurrent = param.asInt()-1;//fx - strip.setMode(effectCurrent); - colorUpdated(6); + colorUpdated(9); } BLYNK_WRITE(V5) { effectSpeed = param.asInt();//sx - strip.setSpeed(effectSpeed); - colorUpdated(6); + colorUpdated(9); } BLYNK_WRITE(V6) { effectIntensity = param.asInt();//ix - strip.setIntensity(effectIntensity); - colorUpdated(6); + colorUpdated(9); } BLYNK_WRITE(V7) diff --git a/wled00/wled17_mqtt.ino b/wled00/wled17_mqtt.ino index 986183e66..1a1fd8ee3 100644 --- a/wled00/wled17_mqtt.ino +++ b/wled00/wled17_mqtt.ino @@ -5,7 +5,7 @@ void parseMQTTBriPayload(char* payload) { if (strcmp(payload, "ON") == 0) {bri = briLast; colorUpdated(1);} - else if (strcmp(payload, "T" ) == 0) {handleSet("win&T=2");} + else if (strcmp(payload, "T" ) == 0) {toggleOnOff(); colorUpdated(1);} else { uint8_t in = strtoul(payload, NULL, 10); if (in == 0 && bri > 0) briLast = bri; @@ -60,7 +60,7 @@ void publishMQTT() //if you want to use this, increase the MQTT buffer in PubSubClient.h to 350+ //it will publish the API response to MQTT - /*XML_response(false); + /*XML_response(false, false); strcpy(subuf, mqttDeviceTopic); strcat(subuf, "/v"); mqtt->publish(subuf, obuf);*/ diff --git a/wled00/wled18_server.ino b/wled00/wled18_server.ino index 23f56a215..0d4a09292 100644 --- a/wled00/wled18_server.ino +++ b/wled00/wled18_server.ino @@ -101,9 +101,16 @@ void initServer() }); server.on("/power", HTTP_GET, [](){ - String val = (String)(int)strip.getPowerEstimate(ledCount,strip.getColor(),strip.getBrightness()); - val += "mA currently"; - serveMessage(200,val,"This is just an estimate (does not take into account several factors like effects and wire resistance). It is NOT an accurate measurement!",254); + String val = ""; + if (strip.currentMilliamps == 0) + { + val = "Power calculation disabled"; + } else + { + val += (String)strip.currentMilliamps; + val += "mA currently"; + } + serveMessage(200, val, "This is just an estimate (does not account for factors like wire resistance). It is NOT a measurement!", 254); }); server.on("/u", HTTP_GET, [](){ @@ -113,7 +120,7 @@ void initServer() }); server.on("/teapot", HTTP_GET, [](){ - serveMessage(418, "418. I'm a teapot.","(Tangible Embedded Advanced Project Of Twinkling)",254); + serveMessage(418, "418. I'm a teapot.", "(Tangible Embedded Advanced Project Of Twinkling)", 254); }); server.on("/build", HTTP_GET, [](){ @@ -136,7 +143,7 @@ void initServer() httpUpdater.setup(&server); #else server.on("/update", HTTP_GET, [](){ - serveMessage(500, "Not implemented", "OTA updates are not supported in this build.", 254); + serveMessage(500, "Not implemented", "OTA updates are unsupported in this build.", 254); }); #endif } else @@ -185,43 +192,6 @@ void initServer() #endif } -void buildCssColorString() -{ - String cs[]={"","","","","",""}; - switch (currentTheme) - { - default: cs[0]="D9B310"; cs[1]="0B3C5D"; cs[2]="1D2731"; cs[3]="328CC1"; cs[4]="000"; cs[5]="328CC1"; break; //night - case 1: cs[0]="eee"; cs[1]="ddd"; cs[2]="b9b9b9"; cs[3]="049"; cs[4]="777"; cs[5]="049"; break; //modern - case 2: cs[0]="abc"; cs[1]="fff"; cs[2]="ddd"; cs[3]="000"; cs[4]="0004"; cs[5]="000"; break; //bright - case 3: cs[0]="c09f80"; cs[1]="d7cec7"; cs[2]="76323f"; cs[3]="888"; cs[4]="3334"; cs[5]="888"; break; //wine - case 4: cs[0]="3cc47c"; cs[1]="828081"; cs[2]="d9a803"; cs[3]="1e392a"; cs[4]="000a"; cs[5]="1e392a"; break; //electric - case 5: cs[0]="57bc90"; cs[1]="a5a5af"; cs[2]="015249"; cs[3]="88c9d4"; cs[4]="0004"; cs[5]="88c9d4"; break; //mint - case 6: cs[0]="f7c331"; cs[1]="dcc7aa"; cs[2]="6b7a8f"; cs[3]="f7882f"; cs[4]="0007"; cs[5]="f7882f"; break; //amber - case 7: cs[0]="fc3"; cs[1]="124"; cs[2]="334"; cs[3]="f1d"; cs[4]="f00"; cs[5]="f1d"; break;//club - case 8: cs[0]="0ac"; cs[1]="124"; cs[2]="224"; cs[3]="003eff"; cs[4]="003eff"; cs[5]="003eff"; break;//air - case 9: cs[0]="f70"; cs[1]="421"; cs[2]="221"; cs[3]="a50"; cs[4]="f70"; cs[5]="f70"; break;//nixie - case 10: cs[0]="2d2"; cs[1]="010"; cs[2]="121"; cs[3]="060"; cs[4]="040"; cs[5]="3f3"; break; //terminal - case 11: cs[0]="867ADE"; cs[1]="4033A3"; cs[2]="483AAA"; cs[3]="483AAA"; cs[4]=""; cs[5]="867ADE"; break; //c64 - case 12: cs[0]="fbe8a6"; cs[1]="d2fdff"; cs[2]="b4dfe5"; cs[3]="f4976c"; cs[4]=""; cs[5]="303c6c"; break; //c64 - case 14: cs[0]="fc7"; cs[1]="49274a"; cs[2]="94618e"; cs[3]="f4decb"; cs[4]="0008"; cs[5]="f4decb"; break; //end - case 15: for (int i=0;i<6;i++)cs[i]=cssCol[i];//custom - } - cssColorString="