Compare commits

..

14 Commits

Author SHA1 Message Date
Aircoookie
65a0f60257 Merge pull request #27 from Aircoookie/development
Development
2018-06-24 01:38:12 +02:00
cschwinne
094bdf02c4 Release of v0.7.0
Substantial optimizations of mobile UI
Added option to save current preset cycle as boot default
Added option not to use first LED in strip
Realtime UI error now includes source IP address
Removed /down and /cleareeprom pages
Fixed bug (turning receiveDirect off would crash on UDP packet)
2018-06-24 01:20:15 +02:00
cschwinne
5d8d12bc89 First commit to development branch
Added AutoRGBW feature
Nightlight turns off if its target brightness is set
2018-05-31 19:26:16 +02:00
cschwinne
89b9fd8a45 Mobile UI by StormPie added 2018-05-22 21:11:19 +02:00
cschwinne
ce1ba3bc2c Added Hyperion support on UDP port 19446 2018-05-18 23:24:47 +02:00
cschwinne
3afb499930 Changed preset cycle API format
Added secondary color transition
Added option to have UI while receiving realtime
Fixed mDNS not working
Fixed Arduino OTA not working when locked but enabled
2018-05-10 19:55:58 +02:00
cschwinne
356ff57005 Added more usermod functions 2018-04-24 12:03:25 +02:00
cschwinne
16ce67057d Updated version in readme
(I always forget this!)
2018-04-15 18:49:47 +02:00
cschwinne
4c9dc739ae Release of v0.6.4
Added Limited support of up to 1200 (ESP8266) or 600 (ESP32) LEDs
Changed &ND API call to activate Nightight without requiring NL
2018-04-15 15:27:54 +02:00
cschwinne
a665607fac Finished Dynamic LED drivers 2018-04-14 18:56:35 +02:00
cschwinne
7f5671f975 Started with wrapper to support dynamic LED counts and pixel features 2018-04-13 00:28:29 +02:00
cschwinne
ee6676cd89 Release of v0.6.3
Added Preset Cycle feature
Added Transition Time API call
Added Adalight serial ambilight protocol
Added DRGB and DRGBW UDP direct-drive protocols
Improved transition flickering
Easter eggs are eaten now
2018-04-11 23:50:35 +02:00
cschwinne
df05754872 Updated readme 2018-04-01 00:15:14 +02:00
cschwinne
72223c7e42 Release of v0.6.2
Added /easter joke subpage
Added Easter (6) effect
Merged Single and Multi Dynamic (7) effects
Added Easter theme
Added North Korea timezone
2018-04-01 00:08:50 +02:00
30 changed files with 1603 additions and 455 deletions

View File

@@ -1,22 +1,7 @@
### Where are the new binaries?
## Where are the new binaries?
From v0.5.0 on forward, the GitHub [releases](https://github.com/Aircoookie/WLED/releases) system will be used for binaries.
### What binary should I choose?
Currently WLED supports the ESP8266 and a very early, experimental version of ESP32 support.
Be sure to choose the correct binary for your platform and LED type.
- Do you have a standard RGB WS2812B NeoPixel strip?
--> Use wled05dev_XXXXXXX_RGB_PLATFORM.bin
- Do you have an RGBW SK6812 strip (half of the LED is white)?
--> Use wled05dev_XXXXXXX_RGBW_PLATFORM.bin
- Do you have a Cronixie clock set by Diamex?
--> Use wled05dev_XXXXXXX_CRONIXIE_PLATFORM.bin
### What about wled03 and wled04?
These are legacy releases only for the ESP8266. They don't include the latest features and may have unfixed bugs - only use them if the new wled05dev test builds don't work for you!
You should always try to use the binaries from the release page. This directory is for legacy purposes only!

View File

@@ -1,30 +1,29 @@
## Welcome to my project WLED!
WLED is a fast and (relatively) secure implementation of an ESP8266 webserver to control NeoPixel (WS2812B) LEDs!
Now also with experimental ESP32 support.
WLED is a fast and (relatively) secure implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B) LEDs!
### Features: (V0.6.1)
### Features: (V0.7.0)
- RGB, HSB, and brightness sliders
- All new, mobile-friendly web UI!
- Settings page - configuration over network
- Access Point and station mode - automatic failsafe AP
- WS2812FX library integrated for over 50 special effects!
- WS2812FX library integrated for over 50 special effects (+Custom Theater Chase)!
- Secondary color support lets you use even more effect combinations
- Alexa smart home device server (including dimming)
- Beta syncronization to Philips hue lights
- Support for RGBW strips
- 25 user presets! Save your favorite colors and effects and apply them easily!
- 25 user presets! Save colors and effects and apply them easily! Supports cycling through them.
- HTTP request API for simple integration
- Macro functions to automatically execute API calls
- Nightlight function (gradually dims down)
- Notifier function (multiple ESPs sync color via UDP broadcast)
- Support for power pushbutton
- Custom Theater Chase
- Support for the Adalight serial ambilight protocol!
- Full OTA software update capability (HTTP and ArduinoOTA)
- Password protected OTA page for added security (OTA lock)
- NTP and configurable analog clock function
- Support for the Cronixie Clock kit by Diamex
- Realtime UDP Packet Control (WARLS) possible
- Client HTML UI controlled, customizable themes
- Realtime UDP Packet Control (Hyperion, WARLS, DRGB, DRGBW)
### Quick start guide and documentation:

176
wled00/NpbWrapper.h Normal file
View File

@@ -0,0 +1,176 @@
//this code is a modified version of https://github.com/Makuna/NeoPixelBus/issues/103
#define WORKAROUND_ESP32_BITBANG
//see https://github.com/Aircoookie/WLED/issues/2 for flicker free ESP32 support
//uncomment this if red and green are swapped
//#define SWAPRG
//automatically uses the right driver method for each platform
#ifdef ARDUINO_ARCH_ESP32
#ifdef WORKAROUND_ESP32_BITBANG
#define PIXELMETHOD NeoEsp32BitBangWs2813Method
#else
#define PIXELMETHOD NeoEsp32RmtWS2813_V3Method
#endif
#else
#define PIXELMETHOD NeoEsp8266Uart800KbpsMethod
#endif
//handle swapping Red and Green automatically
#ifdef SWAPRG
#define PIXELFEATURE3 NeoRgbFeature
#define PIXELFEATURE4 NeoRgbwFeature
#else
#define PIXELFEATURE3 NeoGrbFeature
#define PIXELFEATURE4 NeoGrbwFeature
#endif
#include <NeoPixelBrightnessBus.h>
enum NeoPixelType
{
NeoPixelType_None = 0,
NeoPixelType_Grb = 1,
NeoPixelType_Grbw = 2,
NeoPixelType_End = 3
};
class NeoPixelWrapper
{
public:
NeoPixelWrapper() :
// initialize each member to null
_pGrb(NULL),
_pGrbw(NULL),
_type(NeoPixelType_None)
{
}
~NeoPixelWrapper()
{
cleanup();
}
void Begin(NeoPixelType type, uint16_t countPixels, uint8_t pin)
{
cleanup();
_type = type;
switch (_type) {
case NeoPixelType_Grb:
_pGrb = new NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>(countPixels, pin);
_pGrb->Begin();
break;
case NeoPixelType_Grbw:
_pGrbw = new NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>(countPixels, pin);
_pGrbw->Begin();
break;
}
}
void Show()
{
#ifdef ARDUINO_ARCH_ESP32
#ifdef WORKAROUND_ESP32_BITBANG
delay(1);
portDISABLE_INTERRUPTS(); //this is a workaround to prevent flickering (see https://github.com/adafruit/Adafruit_NeoPixel/issues/139)
#endif
#endif
switch (_type) {
case NeoPixelType_Grb: _pGrb->Show(); break;
case NeoPixelType_Grbw: _pGrbw->Show(); break;
}
#ifdef ARDUINO_ARCH_ESP32
#ifdef WORKAROUND_ESP32_BITBANG
portENABLE_INTERRUPTS();
#endif
#endif
}
bool CanShow() const
{
switch (_type) {
case NeoPixelType_Grb: _pGrb->CanShow(); break;
case NeoPixelType_Grbw: _pGrbw->CanShow(); break;
}
}
void SetPixelColor(uint16_t indexPixel, RgbColor color)
{
switch (_type) {
case NeoPixelType_Grb: _pGrb->SetPixelColor(indexPixel, color); break;
case NeoPixelType_Grbw:_pGrbw->SetPixelColor(indexPixel, color); break;
}
}
void SetPixelColor(uint16_t indexPixel, RgbwColor color)
{
switch (_type) {
case NeoPixelType_Grb: _pGrbw->SetPixelColor(indexPixel, color); break;
case NeoPixelType_Grbw: _pGrbw->SetPixelColor(indexPixel, color); break;
}
}
void SetBrightness(byte b)
{
switch (_type) {
case NeoPixelType_Grb: _pGrb->SetBrightness(b); break;
case NeoPixelType_Grbw:_pGrbw->SetBrightness(b); break;
}
}
RgbColor GetPixelColor(uint16_t indexPixel) const
{
switch (_type) {
case NeoPixelType_Grb: return _pGrb->GetPixelColor(indexPixel); break;
case NeoPixelType_Grbw: /*doesn't support it so we don't return it*/ break;
}
return 0;
}
// NOTE: Due to feature differences, some support RGBW but the method name
// here needs to be unique, thus GetPixeColorRgbw
RgbwColor GetPixelColorRgbw(uint16_t indexPixel) const
{
switch (_type) {
case NeoPixelType_Grb: return _pGrb->GetPixelColor(indexPixel); break;
case NeoPixelType_Grbw: return _pGrbw->GetPixelColor(indexPixel); break;
}
return 0;
}
void ClearTo(RgbColor color)
{
switch (_type) {
case NeoPixelType_Grb: _pGrb->ClearTo(color); break;
case NeoPixelType_Grbw:_pGrbw->ClearTo(color); break;
}
}
void ClearTo(RgbwColor color)
{
switch (_type) {
case NeoPixelType_Grb: break;
case NeoPixelType_Grbw:_pGrbw->ClearTo(color); break;
}
}
private:
NeoPixelType _type;
// have a member for every possible type
NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>* _pGrb;
NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>* _pGrbw;
void cleanup()
{
switch (_type) {
case NeoPixelType_Grb: delete _pGrb ; _pGrb = NULL; break;
case NeoPixelType_Grbw: delete _pGrbw; _pGrbw = NULL; break;
}
}
};

View File

@@ -37,9 +37,9 @@
#define CALL_MODE(n) (this->*_mode[n])();
void WS2812FX::init() {
void WS2812FX::init(bool supportWhite, uint16_t countPixels, uint8_t pin,bool skipFirst) {
begin(supportWhite,countPixels,pin,skipFirst);
for (int i=0; i < _led_count; i++) _locked[i] = false;
begin();
WS2812FX::setBrightness(_brightness);
show();
}
@@ -66,6 +66,7 @@ void WS2812FX::start() {
_counter_mode_step = 0;
_mode_last_call_time = 0;
_running = true;
show();
}
void WS2812FX::stop() {
@@ -85,11 +86,8 @@ void WS2812FX::setMode(byte m) {
}
void WS2812FX::setSpeed(byte s) {
_counter_mode_call = 0;
_counter_mode_step = 0;
_mode_last_call_time = 0;
_speed = constrain(s, SPEED_MIN, SPEED_MAX);
strip_off_respectLock();
}
void WS2812FX::increaseSpeed(byte s) {
@@ -322,31 +320,35 @@ void WS2812FX::mode_random_color(void) {
/*
* Lights every LED in a random color. Changes one random LED after the other
* to another random color.
* Lights some pastel colors
*/
void WS2812FX::mode_single_dynamic(void) {
if(_counter_mode_call == 0) {
for(uint16_t i=0; i < _led_count; i++) {
if (!_locked[i])
setPixelColor(i, color_wheel(random(256)));
}
}
int ran = random(_led_count);
if (!_locked[ran])
setPixelColor(ran, color_wheel(random(256)));
show();
_mode_delay = 10 + ((5000 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX);
void WS2812FX::mode_easter(void) {
//uint32_t cols[]{0x00F7ECC5,0x00F8D5C7,0x00F9E2E7,0x00BED9D4,0x00F7ECC5,0x00F8D5C7,0x00F9E2E7};
uint32_t cols[]{0x00FF8040,0x00E5D241,0x0077FF77,0x0077F0F0,0x00FF8040,0x00E5D241,0x0077FF77};
mode_colorful_internal(cols);
}
/*
* Lights multiple random leds in a random color (higher intensity, more updates)
*/
void WS2812FX::mode_multi_dynamic(void) {
for(uint16_t i=0; i < _led_count; i++) {
if (!_locked[i] && random(256)<=_intensity)
setPixelColor(i, color_wheel(random(256)));
void WS2812FX::mode_dynamic(void) {
if(_counter_mode_call == 0) {
for(uint16_t i=0; i < _led_count; i++) {
if (!_locked[i])
setPixelColor(i, color_wheel(random(256)));
}
}
if (_intensity > 0) //multi dynamic
{
for(uint16_t i=0; i < _led_count; i++) {
if (!_locked[i] && random(256)<_intensity)
setPixelColor(i, color_wheel(random(256)));
}
} else { //single dynamic
int ran = random(_led_count);
if (!_locked[ran])
setPixelColor(ran, color_wheel(random(256)));
}
show();
_mode_delay = 100 + ((5000 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX);
@@ -384,7 +386,7 @@ void WS2812FX::mode_breath(void) {
setPixelColor(i, _color); // set all LEDs to selected color
}
int b = map(breath_brightness, 0, 255, 0, _brightness); // keep brightness below brightness set by user
NeoPixelBrightnessBus::SetBrightness(b); // set new brightness to leds
bus->SetBrightness(b); // set new brightness to leds
show();
_mode_color = breath_brightness; // we use _mode_color to store the brightness
@@ -1024,14 +1026,20 @@ void WS2812FX::mode_chase_rainbow_white(void) {
_mode_delay = 10 + ((30 * (uint32_t)(SPEED_MAX - _speed)) / _led_count);
}
/*
* Red - Amber - Green - Blue lights running
*/
void WS2812FX::mode_colorful(void) {
uint32_t cols[]{0x00FF0000,0x00EEBB00,0x0000EE00,0x000077CC,0x00FF0000,0x00EEBB00,0x0000EE00};
mode_colorful_internal(cols);
}
/*
* Common function for 4-color-running (Colorful, easter)
*/
void WS2812FX::mode_colorful_internal(uint32_t cols[]) {
int i = 0;
for (i; i < _led_count-3 ; i+=4)
for (i; i < _led_count ; i+=4)
{
if(!_locked[i])setPixelColor(i, cols[_counter_mode_step]);
if(!_locked[i+1])setPixelColor(i+1, cols[_counter_mode_step+1]);
@@ -1057,7 +1065,7 @@ void WS2812FX::mode_colorful(void) {
show();
if (_speed > SPEED_MIN) _counter_mode_step++; //static if lowest speed
if (_counter_mode_step >3) _counter_mode_step = 0;
_mode_delay = 100 + (25 * (uint32_t)(SPEED_MAX - _speed));
_mode_delay = 50 + (15 * (uint32_t)(SPEED_MAX - _speed));
}
@@ -1888,11 +1896,6 @@ void WS2812FX::unlockAll()
_locked[x] = false;
}
void WS2812FX::setLedCount(uint16_t i)
{
_led_count = i;
}
void WS2812FX::setFastUpdateMode(bool y)
{
_fastStandard = y;
@@ -1922,16 +1925,12 @@ void WS2812FX::setCronixieDigits(byte d[])
}
}
double WS2812FX::getPowerEstimate(byte leds, uint32_t c, byte b)
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);
#ifdef RGBW
_sum /= 1024;
#else
_sum /= 768;
#endif
_sum /= (_rgbwMode)? 1024:768;
double _mAPerLed = 50*(_mul*_sum);
_mARequired += leds*_mAPerLed;
return _mARequired;
@@ -1942,7 +1941,7 @@ double WS2812FX::getPowerEstimate(byte leds, uint32_t c, byte b)
//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, byte leds, uint32_t c, byte b)
double WS2812FX::getSafePowerMultiplier(double safeMilliAmps, uint16_t leds, uint32_t c, byte b)
{
double _mARequired = getPowerEstimate(leds,c,b);
if (_mARequired > safeMilliAmps)
@@ -1959,7 +1958,7 @@ void WS2812FX::setCCIndex1(byte i1)
_counter_ccStep = 0;
}
void WS2812FX::setCCIndex2(byte i2)
void WS2812FX::setCCIndex2(uint16_t i2)
{
if (i2 > _cc_i1) _cc_i2 = i2;
if (_cc_i2 >= _led_count) _cc_i2 = _led_count-1;
@@ -2004,7 +2003,7 @@ void WS2812FX::setCCFE(bool fe)
_counter_ccStep = 0;
}
void WS2812FX::setCustomChase(byte i1, byte i2, byte is, byte np, byte ns, byte stp, bool fs, bool fe)
void WS2812FX::setCustomChase(byte i1, uint16_t i2, byte is, byte np, byte ns, byte stp, bool fs, bool fe)
{
setCCIndex1(i1);
setCCIndex2(i2);
@@ -2019,11 +2018,13 @@ void WS2812FX::setCustomChase(byte i1, byte i2, byte is, byte np, byte ns, byte
//Added for quick NeoPixelBus compatibility with Adafruit syntax
void WS2812FX::setPixelColorRaw(uint16_t i, byte r, byte g, byte b, byte w)
{
#ifdef RGBW
NeoPixelBrightnessBus::SetPixelColor(i, RgbwColor(r,g,b,w));
#else
NeoPixelBrightnessBus::SetPixelColor(i, RgbColor(r,g,b));
#endif
if (_rgbwMode)
{
bus->SetPixelColor(i, RgbwColor(r,g,b,w));
} else
{
bus->SetPixelColor(i, RgbColor(r,g,b));
}
}
void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
@@ -2031,11 +2032,14 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
if (_reverseMode) i = _led_count - 1 -i;
if (!_cronixieMode)
{
#ifdef RGBW
NeoPixelBrightnessBus::SetPixelColor(i, RgbwColor(r,g,b,w));
#else
NeoPixelBrightnessBus::SetPixelColor(i, RgbColor(r,g,b));
#endif
if (_skipFirstMode) {i++;if(i==1)setPixelColorRaw(0,0,0,0,0);}
if (_rgbwMode)
{
bus->SetPixelColor(i, RgbwColor(r,g,b,w));
} else
{
bus->SetPixelColor(i, RgbColor(r,g,b));
}
} else {
if(i>6)return;
byte o = 10*i;
@@ -2047,27 +2051,27 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
byte wCorr = (int)(((double)((_color_sec>>24) & 0xFF))*_cronixieSecMultiplier);
for (int j=o; j< o+19; j++)
{
setPixelColorRaw(j,rCorr,gCorr,bCorr,wCorr);
setPixelColorRaw((_skipFirstMode)?j+1:j,rCorr,gCorr,bCorr,wCorr);
}
} else
{
for (int j=o; j< o+19; j++)
{
setPixelColorRaw(j,0,0,0,0);
setPixelColorRaw((_skipFirstMode)?j+1:j,0,0,0,0);
}
}
switch(_cronixieDigits[i])
{
case 0: setPixelColorRaw(o+5,r,g,b,w); break;
case 1: setPixelColorRaw(o+0,r,g,b,w); break;
case 2: setPixelColorRaw(o+6,r,g,b,w); break;
case 3: setPixelColorRaw(o+1,r,g,b,w); break;
case 4: setPixelColorRaw(o+7,r,g,b,w); break;
case 5: setPixelColorRaw(o+2,r,g,b,w); break;
case 6: setPixelColorRaw(o+8,r,g,b,w); break;
case 7: setPixelColorRaw(o+3,r,g,b,w); break;
case 8: setPixelColorRaw(o+9,r,g,b,w); break;
case 9: setPixelColorRaw(o+4,r,g,b,w); break;
case 0: setPixelColorRaw((_skipFirstMode)?o+6:o+5,r,g,b,w); break;
case 1: setPixelColorRaw((_skipFirstMode)?o+1:o+0,r,g,b,w); break;
case 2: setPixelColorRaw((_skipFirstMode)?o+7:o+6,r,g,b,w); break;
case 3: setPixelColorRaw((_skipFirstMode)?o+2:o+1,r,g,b,w); break;
case 4: setPixelColorRaw((_skipFirstMode)?o+8:o+7,r,g,b,w); break;
case 5: setPixelColorRaw((_skipFirstMode)?o+3:o+2,r,g,b,w); break;
case 6: setPixelColorRaw((_skipFirstMode)?o+9:o+8,r,g,b,w); break;
case 7: setPixelColorRaw((_skipFirstMode)?o+4:o+3,r,g,b,w); break;
case 8: setPixelColorRaw((_skipFirstMode)?o+10:o+9,r,g,b,w); break;
case 9: setPixelColorRaw((_skipFirstMode)?o+5:o+4,r,g,b,w); break;
default: break;
}
}
@@ -2104,62 +2108,57 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
default: return 0;
}
}
#ifdef RGBW
RgbwColor lColor = NeoPixelBrightnessBus::GetPixelColor(i);
return lColor.W*16777216 + lColor.R*65536 + lColor.G*256 + lColor.B;
#else
RgbColor lColor = NeoPixelBrightnessBus::GetPixelColor(i);
return lColor.R*65536 + lColor.G*256 + lColor.B;
#endif
if (_rgbwMode)
{
RgbwColor lColor = bus->GetPixelColorRgbw(i);
return lColor.W*16777216 + lColor.R*65536 + lColor.G*256 + lColor.B;
} else {
RgbColor lColor = bus->GetPixelColor(i);
return lColor.R*65536 + lColor.G*256 + lColor.B;
}
}
void WS2812FX::setBrightness(byte b)
{
_brightness = constrain(b, BRIGHTNESS_MIN, BRIGHTNESS_MAX);
NeoPixelBrightnessBus::SetBrightness(_brightness);
show();
bus->SetBrightness(_brightness);
if (_mode_last_call_time + _mode_delay > millis()+50 || b == 0) show(); //only update right away if long time until next refresh
}
void WS2812FX::show()
{
#ifdef ARDUINO_ARCH_ESP32
#ifdef WORKAROUND_ESP32_BITBANG
delay(1);
portDISABLE_INTERRUPTS(); //this is a workaround to prevent flickering (see https://github.com/adafruit/Adafruit_NeoPixel/issues/139)
#endif
#endif
NeoPixelBrightnessBus::Show();
#ifdef ARDUINO_ARCH_ESP32
#ifdef WORKAROUND_ESP32_BITBANG
portENABLE_INTERRUPTS();
#endif
#endif
bus->Show();
}
void WS2812FX::clear()
{
#ifdef RGBW
NeoPixelBrightnessBus::ClearTo(RgbwColor(0));
#else
NeoPixelBrightnessBus::ClearTo(RgbColor(0));
#endif
bus->ClearTo(RgbColor(0));
}
void WS2812FX::begin()
void WS2812FX::begin(bool supportWhite, uint16_t countPixels, uint8_t pin, bool skipFirst)
{
NeoPixelBrightnessBus::Begin();
if (supportWhite == _rgbwMode && countPixels == _led_count && _locked != NULL) return;
_rgbwMode = supportWhite;
_skipFirstMode = skipFirst;
_led_count = countPixels;
_cc_i2 = _led_count -1;
if (_skipFirstMode) _led_count++;
uint8_t ty = 1;
if (supportWhite) ty =2;
bus->Begin((NeoPixelType)ty, _led_count, pin);
if (_locked != NULL) delete _locked;
_locked = new bool[_led_count];
}
//For some reason min and max are not declared here
byte WS2812FX::minval (byte v, byte w)
uint16_t WS2812FX::minval (uint16_t v, uint16_t w)
{
if (w > v) return v;
return w;
}
byte WS2812FX::maxval (byte v, byte w)
uint16_t WS2812FX::maxval (uint16_t v, uint16_t w)
{
if (w > v) return w;
return v;

View File

@@ -1,25 +1,4 @@
//#define RGBW
#define PIN 2 //strip pin. Only change for ESP32
#define WORKAROUND_ESP32_BITBANG
//see https://github.com/Aircoookie/WLED/issues/2 for flicker free ESP32 support
//automatically uses the right driver method for each platform
#ifdef ARDUINO_ARCH_ESP32
#ifdef WORKAROUND_ESP32_BITBANG
#define PIXELMETHOD NeoEsp32BitBangWs2813Method
#else
#define PIXELMETHOD NeoEsp32RmtWS2813_V3Method
#endif
#else
#define PIXELMETHOD NeoEsp8266Uart800KbpsMethod
#endif
//selects correct feature for RGB/RGBW
#ifdef RGBW
#define PIXELFEATURE NeoGrbwFeature
#else
#define PIXELFEATURE NeoGrbFeature
#endif
//pixelmethod now in NpbWrapper.h
/*
WS2812FX.h - Library for WS2812 LED effects.
@@ -50,14 +29,14 @@
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.
Modified to work with WLED - differs from Github WS2812FX
Heavily modified to work with WLED - differs from Github WS2812FX
*/
#ifndef WS2812FX_h
#define WS2812FX_h
#include "Arduino.h"
#include <NeoPixelBrightnessBus.h>
#include "NpbWrapper.h"
#define DEFAULT_BRIGHTNESS 50
#define DEFAULT_MODE 0
@@ -78,8 +57,8 @@
#define FX_MODE_COLOR_WIPE 3
#define FX_MODE_COLOR_WIPE_RANDOM 4
#define FX_MODE_RANDOM_COLOR 5
#define FX_MODE_SINGLE_DYNAMIC 6
#define FX_MODE_MULTI_DYNAMIC 7
#define FX_MODE_EASTER 6
#define FX_MODE_DYNAMIC 7
#define FX_MODE_RAINBOW 8
#define FX_MODE_RAINBOW_CYCLE 9
#define FX_MODE_SCAN 10
@@ -132,10 +111,10 @@
#define FX_MODE_CC_RANDOM 57
class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
class WS2812FX {
typedef void (WS2812FX::*mode_ptr)(void);
public:
WS2812FX(uint16_t n) : NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD>(n,PIN) {
WS2812FX(){
_mode[FX_MODE_STATIC] = &WS2812FX::mode_static;
_mode[FX_MODE_BLINK] = &WS2812FX::mode_blink;
@@ -143,8 +122,8 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
_mode[FX_MODE_COLOR_WIPE] = &WS2812FX::mode_color_wipe;
_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_EASTER] = &WS2812FX::mode_easter;
_mode[FX_MODE_DYNAMIC] = &WS2812FX::mode_dynamic;
_mode[FX_MODE_RAINBOW] = &WS2812FX::mode_rainbow;
_mode[FX_MODE_RAINBOW_CYCLE] = &WS2812FX::mode_rainbow_cycle;
_mode[FX_MODE_SCAN] = &WS2812FX::mode_scan;
@@ -200,7 +179,7 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
_speed = DEFAULT_SPEED;
_brightness = DEFAULT_BRIGHTNESS;
_running = false;
_led_count = n;
_led_count = 255;
_mode_last_call_time = 0;
_mode_delay = 0;
_color = DEFAULT_COLOR;
@@ -211,7 +190,7 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
_cc_fe = false;
_cc_is = 0;
_cc_i1 = 0;
_cc_i2 = n-1;
_cc_i2 = 254;
_cc_num1 = 5;
_cc_num2 = 5;
_ccStep = 1;
@@ -220,21 +199,24 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
_counter_ccStep = 0;
_fastStandard = false;
_reverseMode = false;
_locked = new bool[n];
_skipFirstMode = false;
_locked = NULL;
_cronixieDigits = new byte[6];
bus = new NeoPixelWrapper();
}
void
show(void),
setPixelColor(uint16_t i, byte r, byte g, byte b),
init(void),
setPixelColor(uint16_t i, byte r, byte g, byte b, byte w),
init(bool supportWhite, uint16_t countPixels, uint8_t pin, bool skipFirst),
service(void),
start(void),
stop(void),
setMode(byte m),
setCustomChase(byte i1, byte i2, byte is, byte np, byte ns, byte stp, bool fs, bool fe),
setCustomChase(byte i1, uint16_t i2, byte is, byte np, byte ns, byte stp, bool fs, bool fe),
setCCIndex1(byte i1),
setCCIndex2(byte i2),
setCCIndex2(uint16_t i2),
setCCStart(byte is),
setCCNum1(byte np),
setCCNum2(byte ns),
@@ -270,7 +252,6 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
unlockAll(void),
setFastUpdateMode(bool b),
trigger(void),
setLedCount(uint16_t i),
setFade(int sp);
bool
@@ -290,16 +271,16 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
getColor(void);
double
getPowerEstimate(byte leds, uint32_t c, byte b),
getSafePowerMultiplier(double safeMilliAmps, byte leds, uint32_t c, byte b);
getPowerEstimate(uint16_t leds, uint32_t c, byte b),
getSafePowerMultiplier(double safeMilliAmps, uint16_t leds, uint32_t c, byte b);
private:
NeoPixelWrapper *bus;
void
begin(void),
begin(bool supportWhite, uint16_t countPixels, uint8_t pin, bool skipFirst),
clear(void),
setPixelColor(uint16_t i, uint32_t c),
setPixelColor(uint16_t i, byte r, byte g, byte b, byte w),
setPixelColorRaw(uint16_t i, byte r, byte g, byte b, byte w),
dofade(void),
strip_off(void),
@@ -309,8 +290,8 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
mode_color_wipe(void),
mode_color_wipe_random(void),
mode_random_color(void),
mode_single_dynamic(void),
mode_multi_dynamic(void),
mode_easter(void),
mode_dynamic(void),
mode_breath(void),
mode_fade(void),
mode_scan(void),
@@ -339,6 +320,7 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
mode_chase_flash_random(void),
mode_chase_rainbow_white(void),
mode_colorful(void),
mode_colorful_internal(uint32_t*),
mode_traffic_light(void),
mode_color_sweep_random(void),
mode_running_color(void),
@@ -366,6 +348,8 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
bool
_triggered,
_rgbwMode,
_skipFirstMode,
_fastStandard,
_reverseMode,
_cronixieMode,
@@ -378,13 +362,10 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
_locked;
byte
minval(byte v, byte w),
maxval(byte v, byte w),
_mode_index,
_speed,
_intensity,
_cc_i1,
_cc_i2,
_cc_is,
_cc_num1,
_cc_num2,
@@ -395,6 +376,9 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
_cronixieDigits;
uint16_t
minval(uint16_t v, uint16_t w),
maxval(uint16_t v, uint16_t w),
_cc_i2,
_led_count;
uint32_t

View File

@@ -1,8 +1,8 @@
<!DOCTYPE html>
<html>
<head><meta charset="utf-8">
<head><meta charset="utf-8"><meta name="theme-color" content="#fff">
<link rel='shortcut icon' type='image/x-icon' href='/favicon.ico'/>
<title>WLED 0.6.1</title>
<title>WLED 0.7.0</title>
<script>
var d=document;
var w=window.getComputedStyle(d.querySelector("html"));
@@ -33,6 +33,7 @@
aC = w.getPropertyValue("--aCol");
bC = w.getPropertyValue("--bCol");
dC = w.getPropertyValue("--dCol");
d.querySelector("meta[name=theme-color]").setAttribute("content",bC);
CV(0);
setInterval('GIO()', 5000);
GIO();
@@ -75,7 +76,7 @@
}
}
}
request.open("GET", "win/" +resp +nocache, true);
request.open("GET", "win" +resp +nocache, true);
request.send(null);
resp="";
}
@@ -197,6 +198,7 @@
function SwFX(s)
{
var n=Cf.TX.selectedIndex+s;
if (n==-1||n==58) return;
Cf.TX.selectedIndex =n;
if (n < 0) Cf.TX.selectedIndex = 0;
if (n > 57) Cf.TX.selectedIndex = 53;
@@ -214,24 +216,25 @@
function SwitchPS(x)
{
d.Cf.FF.value = parseInt(d.Cf.FF.value) +x;
if (d.Cf.FF.value < 0) d.Cf.FF.value = 0;
if (d.Cf.FF.value > 24) d.Cf.FF.value = 24;
if (d.Cf.FF.value < 1) d.Cf.FF.value = 1;
if (d.Cf.FF.value > 25) d.Cf.FF.value = 25;
}
function PAt()
{
resp+=(d.Cf.BC.checked)?"&PA=1":"&PA=0";
resp+=(d.Cf.CC.checked)?"&PC=1":"&PC=0";
resp+=(d.Cf.FC.checked)?"&PX=1":"&PX=0";
}
function PSIO(sv)
{
PAt();
if(sv)
{
resp+="&PS=";
resp+=d.Cf.FF.value;
} else
{
if (d.Cf.BC.checked&&d.Cf.CC.checked&&d.Cf.FC.checked)
{resp+="&PL=";resp+=d.Cf.FF.value;}
else {
if(d.Cf.BC.checked){resp+="&PA=";resp+=d.Cf.FF.value;}
if(d.Cf.CC.checked){resp+="&PC=";resp+=d.Cf.FF.value;}
if(d.Cf.FC.checked){resp+="&PX=";resp+=d.Cf.FF.value;}
}
resp+="&PL=";resp+=d.Cf.FF.value;
}
GIO();
}
@@ -335,14 +338,28 @@
}
GIO();
}
function uCY()
{
PAt();
resp+=(d.Cf.CY.checked)?"&CY=1":"&CY=0";
resp+="&P1=" + Cf.P1.value;
resp+="&P2=" + Cf.P2.value;
resp+="&PT=" + Cf.PT.value;
GIO();
}
function R()
{
resp+="&PL=0";GIO();
}
</script>
<style>
:root {
--aCol: #0ac;
--bCol: #124;
--cCol: #334;
--dCol: #288;
--sCol: #FF00FF;
--aCol: #D9B310;
--bCol: #0B3C5D;
--cCol: #1D2731;
--dCol: #328CC1;
--sCol: #000;
--tCol: #328CC1;
--cFn: Verdana;
}
.ctrl_box {
@@ -575,14 +592,14 @@
<svg id="fmf" onclick="SwFX(1)"><use xlink:href="#lnr-arrow-right-circle"></use></svg>
<svg id="fof" onclick="SwFX(99)"><use xlink:href="#lnr-rocket"></use></svg><br><br>
<select name="TX" onchange="GX()">
<option value="0" selected>Static (0)</option>
<option value="0" selected>Solid (0)</option>
<option value="1">Blink (1)</option>
<option value="2">Breath (2)</option>
<option value="3">Wipe (3)</option>
<option value="4">Wipe Random (4)</option>
<option value="5">Color R (5)</option>
<option value="6">Single Dynamic (6)</option>
<option value="7">All Dynamic (7)</option>
<option value="6">Easter (6)</option>
<option value="7">Dynamic (7)</option>
<option value="8">Colorloop (8)</option>
<option value="9">Rainbow (9)</option>
<option value="10">Scan (10)</option>
@@ -659,9 +676,10 @@
<svg id="psp" onclick="SwitchPS(-1)"><use xlink:href="#lnr-arrow-left-circle"></use></svg>
<svg id="psn" onclick="SwitchPS(1)"><use xlink:href="#lnr-arrow-right-circle"></use></svg>
<svg id="pss" onclick="PSIO(true)"><use xlink:href="#lnr-arrow-down-circle"></use></svg>
<br><input id="psI" name = "FF" type="number" value="0" min="0" max="25" step="1"><br><br>
Click checkmark to apply <input type="checkbox" checked="true" name="BC"> brightness, <input type="checkbox" checked="true" name="CC"> color and <input type="checkbox" checked="true" name="FC"> effects.<br>
Effect 0 is the configuration when the light is powered up.
<br><input id="psI" name = "FF" type="number" value="1" min="1" max="25" step="1"><br><br>
Click checkmark to apply <input type="checkbox" checked="true" name="BC"> brightness, <input type="checkbox" checked="true" name="CC"> color and <input type="checkbox" checked="true" name="FC"> effects.<br><br>
Cycle through presets <input id="cy1" name="P1" type="number" value="1" min="1" max="25" step="1"> to <input id="cy2" name="P2" type="number" value="5" min="1" max="25" step="1">, keep each for <input id="cyT" name="PT" type="number" value="1250" min="50" max="65501" step="1">ms: <input type="checkbox" name="CY" onclick="uCY()"><br><br>
<button type="button" onclick="R()">Apply boot config</button><br>
</div>
<div id="tlN" class="tools">
Timed Light<br><br>

File diff suppressed because one or more lines are too long

View File

@@ -9,7 +9,7 @@
window.location = "/settings";
}
function RP() {
top.location.href=top.location.href;
top.location.href="/";
}
</script>
<style>

View File

@@ -19,6 +19,9 @@
margin: 0;
background-attachment: fixed;
}
html {
--h:11.55vh;
}
button {
background: var(--bCol);
color: var(--tCol);
@@ -27,13 +30,23 @@
display: inline-block;
filter: drop-shadow( -5px -5px 5px var(--sCol) );
font-size: 8vmin;
height:13.86vh;
height:var(--h);
width: 95%;
margin-top: 2.4vh;
}
</style>
<script>
function BB()
{
if (window.frameElement) {
document.getElementById("b").style.display = "none";
document.documentElement.style.setProperty('--h',"13.86vh");
}
}
</script>
</head>
<body>
<body onload="BB()">
<form action="/"><button type=submit id="b">Back</button></form>
<form action="/settings/wifi"><button type="submit">WiFi Setup</button></form>
<form action="/settings/leds"><button type="submit">LED Preferences</button></form>
<form action="/settings/ui"><button type="submit">User Interface</button></form>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -7,15 +7,15 @@ body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol);
const char PAGE_settings0[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<head>
<title>WLED Settings</title>
<html><head><title>WLED Settings</title>
)=====";
const char PAGE_settings1[] PROGMEM = R"=====(
body{text-align:center;background:var(--cCol);height:100%;margin:0;background-attachment:fixed}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:8vmin;height:13.86vh;width:95%;margin-top:2.4vh}</style>
body{text-align:center;background:var(--cCol);height:100%;margin:0;background-attachment:fixed}html{--h:11.55vh}button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),Helvetica,sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:8vmin;height:var(--h);width:95%;margin-top:2.4vh}</style>
<script>function BB(){if(window.frameElement){document.getElementById("b").style.display="none";document.documentElement.style.setProperty("--h","13.86vh")}};</script>
</head>
<body>
<body onload=BB()>
<form action=/><button type=submit id=b>Back</button></form>
<form action=/settings/wifi><button type=submit>WiFi Setup</button></form>
<form action=/settings/leds><button type=submit>LED Preferences</button></form>
<form action=/settings/ui><button type=submit>User Interface</button></form>
@@ -28,8 +28,7 @@ body{text-align:center;background:var(--cCol);height:100%;margin:0;background-at
const char PAGE_settings_wifi0[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<head>
<html><head>
<title>WiFi Settings</title><script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#wifi-settings");}function B(){window.history.back();}function GetV(){var d = document;
)=====";
const char PAGE_settings_wifi1[] PROGMEM = R"=====(
@@ -85,24 +84,26 @@ const char PAGE_settings_leds1[] PROGMEM = R"=====(
<div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
<h2>LED setup</h2>
LED count (max. 255): <input name="LC" type="number" min="1" max="255" required><br>
<i>The default boot color is always saved in preset slot 0.</i><br>
Alternatively, apply preset <input name="BP" type="number" min="0" max="25" required> at boot<br>
LED count: <input name="LC" type="number" min="1" max="1200" required><br>
LEDs are 4-channel type (RGBW): <input type="checkbox" name="EW"><br>
Apply preset <input name="BP" type="number" min="0" max="25" required> at boot (0 uses defaults)<br>
Default RGB color:
<input name="CR" type="number" min="0" max="255" required>
<input name="CG" type="number" min="0" max="255" required>
<input name="CB" type="number" min="0" max="255" required><br>
Default white value (only RGBW): <input name="CW" type="number" min="0" max="255" required><br>
Auto-calculate white from RGB instead: <input type="checkbox" name="AW"><br>
Default brightness: <input name="CA" type="number" min="0" max="255" required> (0-255)<br>
Default white value (only RGBW, -1 to disable): <input name="CW" type="number" min="-1" max="255" required><br>
Default effect ID: <input name="FX" type="number" min="0" max="57" required> <br>
Default effect speed: <input name="SX" type="number" min="0" max="255" required> <br>
Default effect intensity: <input name="IX" type="number" min="0" max="255" required> <br>
Default effect ID: <input name="FX" type="number" min="0" max="57" required><br>
Default effect speed: <input name="SX" type="number" min="0" max="255" required><br>
Default effect intensity: <input name="IX" type="number" min="0" max="255" required><br>
Default secondary RGB(W):<br>
<input name="SR" type="number" min="0" max="255" required>
<input name="SG" type="number" min="0" max="255" required>
<input name="SB" type="number" min="0" max="255" required>
<input name="SW" type="number" min="0" max="255" required><br>
Ignore and use current color, brightness and effects: <input type="checkbox" name="IS"><br>
Save current preset cycle configuration as boot default: <input type="checkbox" name="PC"><br>
Turn on after power up/reset: <input type="checkbox" name="BO"><br>
Use Gamma correction for brightness: <input type="checkbox" name="GB"><br>
Use Gamma correction for color: <input type="checkbox" name="GC"><br>
@@ -110,7 +111,8 @@ Brightness factor: <input name="BF" type="number" min="0" max="255" required> %
<h3>Transitions</h3>
Fade: <input type="checkbox" name="TF"><br>
Sweep: <input type="checkbox" name="TS"> Invert direction: <input type="checkbox" name="TI"><br>
Transition Delay: <input name="TD" maxlength="5" size="2"> ms
Transition Time: <input name="TD" maxlength="5" size="2"> ms<br>
Enable transition for secondary color: <input type="checkbox" name="T2"><br>
<h3>Timed light</h3>
Default Duration: <input name="TL" type="number" min="1" max="255" required> min<br>
Default Target brightness: <input name="TB" type="number" min="0" max="255" required><br>
@@ -118,7 +120,8 @@ Fade down: <input type="checkbox" name="TW"><br>
<h3>Advanced</h3>
Reverse LED order (rotate 180): <input type="checkbox" name="RV"><br>
Init LEDs after WiFi: <input type="checkbox" name="EI"><br>
WARLS offset: <input name="WO" type="number" min="-255" max="255" required><hr>
WARLS offset: <input name="WO" type="number" min="-255" max="255" required><br>
Skip first LED: <input type="checkbox" name="SL"><hr>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
</form>
</body>
@@ -127,8 +130,7 @@ WARLS offset: <input name="WO" type="number" min="-255" max="255" required><hr>
const char PAGE_settings_ui0[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<head>
<html><head>
<title>UI Settings</title><script>
function gId(s){return document.getElementById(s);}function S(){GetV();Ct();}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#user-interface-settings");}function B(){window.history.back();}function Ct(){if (gId("co").selected){gId("cth").style.display="block";}else{gId("cth").style.display="none";}}function GetV(){var d = document;
)=====";
@@ -139,7 +141,14 @@ const char PAGE_settings_ui1[] PROGMEM = R"=====(
<div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
<h2>Web Setup</h2>
Server description: <input name="DS" maxlength="32"><br>
User Interface Mode:
<select name="UI">
<option value="0" selected>Auto</option>
<option value="1">Classic</option>
<option value="2">Mobile</option>
</select><br>
Server description: <input name="DS" maxlength="32"><br><br>
<i>The following options are for the classic UI!</i><br>
Use HSB sliders instead of RGB by default: <input type="checkbox" name="MD"><br>
Color Theme:
<select name="TH" onchange="Ct()">
@@ -155,7 +164,7 @@ Color Theme:
<option value="9">Nixie</option>
<option value="10">Terminal</option>
<option value="11">C64</option>
<option value="12">Placeholder</option>
<option value="12">Easter</option>
<option value="13">Placeholder</option>
<option value="14">The End</option>
<option value="15" id="co">Custom</option>
@@ -197,12 +206,16 @@ Send notifications on direct change: <input type="checkbox" name="SD"><br>
Send notifications on button press: <input type="checkbox" name="SB"><br>
Send Alexa notifications: <input type="checkbox" name="SA"><br>
Send Philips Hue change notifications: <input type="checkbox" name="SH"><br>
Send notifications twice: <input type="checkbox" name="S2">
Send notifications twice: <input type="checkbox" name="S2"><br>
Receive UDP realtime: <input type="checkbox" name="RD"><br>
Enable UI access during realtime: <input type="checkbox" name="RU"> (can cause issues)
<h3>Alexa Voice Assistant</h3>
Emulate Alexa device: <input type="checkbox" name="AL"><br>
Alexa invocation name: <input name="AI" maxlength="32"><br>
<h3>Philips Hue</h3>
<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
Poll Hue light <input name="HL" type="number" min="1" max="99" required> every <input name="HI" type="number" min="100" max="65000" required> ms: <input type="checkbox" name="HP"><br>
Then, receive <input type="checkbox" name="HO"> On/Off, <input type="checkbox" name="HB"> Brightness, and <input type="checkbox" name="HC"> Color<br>
Hue Bridge IP:<br>
<input name="H0" type="number" min="0" max="255" required> .
<input name="H1" type="number" min="0" max="255" required> .
@@ -210,8 +223,6 @@ Hue Bridge IP:<br>
<input name="H3" type="number" min="0" max="255" required><br>
<b>Press the pushlink button on the bridge, after that save this page!</b><br>
(when first connecting)<br>
Poll Hue light <input name="HL" type="number" min="1" max="99" required> every <input name="HI" type="number" min="100" max="65000" required> ms: <input type="checkbox" name="HP"><br>
Then, receive <input type="checkbox" name="HO"> On/Off, <input type="checkbox" name="HB"> Brightness, and <input type="checkbox" name="HC"> Color<br>
Hue status: <span class="hms"> Internal ESP Error! </span><hr>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
</form>
@@ -248,6 +259,7 @@ Time zone:
<option value="10">JST(KST)</option>
<option value="11">AEST/AEDT</option>
<option value="12">NZST/NZDT</option>
<option value="13">North Korea</option>
</select><br>
UTC offset: <input name="UO" type="number" min="-65500" max="65500" required> seconds (max. 18 hours)<br>
Current local time is <span class="times">unknown</span>.
@@ -318,7 +330,7 @@ const char PAGE_settings_sec1[] PROGMEM = R"=====(
<div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit">Save & Reboot</button><hr>
<h2>Security & Update setup</h2>
Enable OTA lock: <input type="checkbox" name="NO"><br>
Lock wireless (OTA) software update: <input type="checkbox" name="NO"><br>
Passphrase: <input type="password" name="OP" maxlength="32"><br>
To enable OTA, for security reasons you need to also enter the correct password!<br>
The password should be changed when OTA is enabled.<br>
@@ -335,10 +347,12 @@ HTTP traffic is unencrypted. An attacker in the same network can intercept form
<button type="button" onclick="U()">Manual OTA Update</button><br>
Enable ArduinoOTA: <input type="checkbox" name="AO"><br>
<h3>About</h3>
<a href="https://github.com/Aircoookie/WLED">WLED</a> version 0.6.1<br>
<a href="https://github.com/Aircoookie/WLED">WLED</a> version 0.7.0<br><br>
<b>Contributors:</b><br>
StormPie <i>(Mobile HTML UI)</i><br><br>
(c) 2016-2018 Christian Schwinne <br>
<i>Licensed under the MIT license</i><br><br>
<i>Uses libraries:</i><br>
<b>Uses libraries:</b><br>
<i>ESP8266/ESP32 Arduino Core</i><br>
<i>(ESP32) <a href="https://github.com/bbx10/WebServer_tng">WebServer_tng</a> by bbx10</i><br>
<i><a href="https://github.com/kitesurfer1404/WS2812FX">WS2812FX</a> by kitesurfer1404 (modified)</i><br>

View File

@@ -1,3 +1,7 @@
//USER HTML
const char PAGE_usermod[] PROGMEM = R"=====(
<html><body>There is no usermod installed or it doesn't specify a custom web page.</body></html>
)=====";
/*
* Various
*/
@@ -5,7 +9,7 @@ const char PAGE_msg0[] PROGMEM = R"=====(
<!DOCTYPE html>
<html><head>
<title>WLED Message</title>
<script>function B(){window.history.back()};function RS(){window.location = "/settings";}function RP(){top.location.href=top.location.href;}</script>
<script>function B(){window.history.back()};function RS(){window.location = "/settings";}function RP(){top.location.href="/";}</script>
)=====";
const char PAGE_msg1[] PROGMEM = R"=====(
button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:20px;margin:8px;margin-top:12px}body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol);color:var(--tCol);line-height:200%;margin:0;background-attachment:fixed}</style>

View File

@@ -90,8 +90,8 @@ WebServer::~WebServer() {
void WebServer::begin() {
_currentStatus = HC_NONE;
_server.begin();
if(!_headerKeysCount)
collectHeaders(0, 0);
//if(!_headerKeysCount)
//collectHeaders(0, 0);
}
bool WebServer::authenticate(const char * username, const char * password){
@@ -408,15 +408,13 @@ String WebServer::header(String name) {
return String();
}
void WebServer::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) {
_headerKeysCount = headerKeysCount + 1;
if (_currentHeaders)
delete[]_currentHeaders;
_currentHeaders = new RequestArgument[_headerKeysCount];
//Modified by Aircoookie to work for WLED
void WebServer::collectHeaders(String headerKey) {
_headerKeysCount = 2;
if (_currentHeaders) delete[]_currentHeaders;
_currentHeaders = new RequestArgument[2];
_currentHeaders[0].key = AUTHORIZATION_HEADER;
for (int i = 1; i < _headerKeysCount; i++){
_currentHeaders[i].key = headerKeys[i-1];
}
_currentHeaders[1].key = headerKey;
}
String WebServer::header(int i) {

View File

@@ -105,7 +105,7 @@ public:
String argName(int i); // get request argument name by number
int args(); // get arguments count
bool hasArg(String name); // check if argument exists
void collectHeaders(const char* headerKeys[], const size_t headerKeysCount); // set the request headers to collect
void collectHeaders(String headerKey); // set the request headers to collect
String header(String name); // get request header value by name
String header(int i); // get request header value by number
String headerName(int i); // get request header name by number

View File

@@ -3,10 +3,14 @@
*/
/*
* @title WLED project sketch
* @version 0.6.1
* @version 0.7.0
* @author Christian Schwinne
*/
//ESP8266-01 got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.3.0 and the setting 512K(64K SPIFFS).
//Uncomment the following line to disable some features (currently Mobile UI) to compile for ESP8266-01
//#define WLED_FLASH_512K_MODE
#include <Arduino.h>
#ifdef ARDUINO_ARCH_ESP32
#include <WiFi.h>
@@ -33,16 +37,13 @@
#include "WS2812FX.h"
//version in format yymmddb (b = daily build)
#define VERSION 1803182
const String versionString = "0.6.1";
#define VERSION 1806240
const String versionString = "0.7.0";
//AP and OTA default passwords (change them!)
String apPass = "wled1234";
String otaPass = "wledota";
//If you have an RGBW strip, also uncomment first line in WS2812FX.h!
bool useRGBW = false;
//spiffs FS only useful for debug (only ESP8266)
//#define USEFS
@@ -50,19 +51,20 @@ bool useRGBW = false;
//#define DEBUG
//Hardware-settings (only changeble via code)
#define LEDCOUNT 255 //maximum, exact count set-able via settings
#define PIN 2 //strip pin. Only change for ESP32
byte buttonPin = 0; //needs pull-up
byte auxPin = 15; //use e.g. for external relay
byte auxDefaultState = 0; //0: input 1: high 2: low
byte auxTriggeredState = 0; //0: input 1: high 2: low
//Default CONFIG
String serverDescription = versionString;
String serverDescription = "WLED Light";
byte currentTheme = 0;
byte uiConfiguration = 0; //0: auto 1: classic 2: mobile
String clientSSID = "Your_Network";
String clientPass = "";
String cmDNS = "led";
byte ledCount = 10; //lowered to prevent accidental overcurrent
uint16_t ledCount = 10; //lowered to prevent accidental overcurrent
String apSSID = ""; //AP off by default (unless setup)
byte apChannel = 1;
byte apHide = 0;
@@ -72,9 +74,9 @@ IPAddress staticIP(0, 0, 0, 0);
IPAddress staticGateway(0, 0, 0, 0);
IPAddress staticSubnet(255, 255, 255, 0);
IPAddress staticDNS(8, 8, 8, 8); //only for NTP
bool useHSB = false, useHSBDefault = false;
bool useHSB = true, useHSBDefault = true, useRGBW = false, autoRGBtoRGBW = false;
bool turnOnAtBoot = true;
bool initLedsLast = false;
bool initLedsLast = false, skipFirstLed = false;
byte bootPreset = 0;
byte colS[]{255, 159, 0};
byte colSecS[]{0, 0, 0};
@@ -84,7 +86,8 @@ byte briS = 127;
byte nightlightTargetBri = 0;
bool fadeTransition = true;
bool sweepTransition = false, sweepDirection = true;
uint16_t transitionDelay = 1200;
bool disableSecTransition = true;
uint16_t transitionDelay = 1200, transitionDelayDefault = transitionDelay;
bool reverseMode = false;
bool otaLock = false, wifiLock = false;
bool aOtaEnabled = true;
@@ -94,7 +97,7 @@ bool receiveNotifications = true, receiveNotificationBrightness = true, receiveN
byte briMultiplier = 100;
byte nightlightDelayMins = 60;
bool nightlightFade = true;
uint16_t udpPort = 21324;
uint16_t udpPort = 21324, udpRgbPort = 19446;
byte effectDefault = 0;
byte effectSpeedDefault = 75;
byte effectIntensityDefault = 128;
@@ -105,7 +108,7 @@ String ntpServerName = "0.wled.pool.ntp.org";
byte ccNumPrimary = 2;
byte ccNumSecondary = 4;
byte ccIndex1 = 0;
byte ccIndex2 = ledCount -1;
uint16_t ccIndex2 = ledCount -1;
bool ccFromStart = true, ccFromEnd = false;
byte ccStep = 1;
byte ccStart = 0;
@@ -120,8 +123,6 @@ byte macroButton = 0, macroCountdown = 0, macroLongPress = 0;
unsigned long countdownTime = 1514764800L;
double transitionResolution = 0.011;
//hue
bool huePollingEnabled = false, hueAttempt = false;
uint16_t huePollIntervalMs = 2500;
@@ -131,15 +132,19 @@ IPAddress hueIP = (0,0,0,0);
bool notifyHue = true;
bool hueApplyOnOff = true, hueApplyBri = true, hueApplyColor = true;
uint16_t userVar0 = 0, userVar1 = 0;
//Internal vars
byte col[]{0, 0, 0};
byte colOld[]{0, 0, 0};
byte colT[]{0, 0, 0};
byte colIT[]{0, 0, 0};
byte colSec[]{0, 0, 0};
byte colSecT[]{0, 0, 0};
byte colSecOld[]{0, 0, 0};
byte colSecIT[]{0, 0, 0};
byte white, whiteOld, whiteT, whiteIT;
byte whiteSec, whiteSecIT;
byte whiteSec, whiteSecOld, whiteSecT, whiteSecIT;
byte lastRandomIndex = 0;
uint16_t transitionDelayTemp = transitionDelay;
unsigned long transitionStartTime;
@@ -158,20 +163,20 @@ byte notificationSentCallMode = 0;
bool notificationTwoRequired = false;
bool nightlightActive = false;
bool nightlightActiveOld = false;
uint32_t nightlightDelayMs;
byte briNlT;
uint32_t nightlightDelayMs = 10;
byte briNlT = 0;
byte effectCurrent = 0;
byte effectSpeed = 75;
byte effectIntensity = 128;
bool onlyAP = false;
bool udpConnected = false;
bool udpConnected = false, udpRgbConnected = false;
String cssCol[]={"","","","","",""};
String cssFont="Verdana";
String cssColorString="";
//NTP stuff
bool ntpConnected = false;
byte currentTimezone = 0;
time_t local;
time_t local = 0;
int utcOffsetSecs = 0;
//hue
@@ -208,12 +213,21 @@ bool cronixieBacklight = true;
bool countdownMode = false;
bool cronixieInit = false;
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 saveCurrPresetCycConf = false;
uint32_t arlsTimeoutMillis = 2500;
bool arlsTimeout = false;
unsigned long arlsTimeoutTime;
bool receiveDirect = true, enableRealtimeUI = false;
IPAddress realtimeIP = (0,0,0,0);
unsigned long arlsTimeoutTime = 0;
byte auxTime = 0;
unsigned long auxStartTime;
bool auxActive, auxActiveBefore;
unsigned long auxStartTime = 0;
bool auxActive = false, auxActiveBefore = false;
bool showWelcomePage = false;
bool useGammaCorrectionBri = false;
@@ -238,7 +252,7 @@ ESP8266WebServer server(80);
#endif
HTTPClient hueClient;
ESP8266HTTPUpdateServer httpUpdater;
WiFiUDP notifierUdp;
WiFiUDP notifierUdp, rgbUdp;
WiFiUDP ntpUdp;
IPAddress ntpServerIP;
unsigned int ntpLocalPort = 2390;
@@ -247,7 +261,7 @@ byte ntpPacketBuffer[NTP_PACKET_SIZE];
unsigned long ntpLastSyncTime = 999000000L;
unsigned long ntpPacketSentTime = 999000000L;
WS2812FX strip = WS2812FX(LEDCOUNT);
WS2812FX strip = WS2812FX();
#ifdef DEBUG
#define DEBUG_PRINT(x) Serial.print (x)
@@ -292,14 +306,6 @@ String txd = "Please disable OTA Lock in security settings!";
void serveMessage(int,String,String,int=255);
void down()
{
briT = 0;
setAllLeds();
DEBUG_PRINTLN("MODULE TERMINATED");
while (1) {delay(1000);}
}
void reset()
{
briT = 0;
@@ -314,16 +320,17 @@ void setup() {
void loop() {
server.handleClient();
handleSerial();
handleNotifications();
handleTransitions();
userLoop();
yield();
handleButton();
handleNetworkTime();
if (!otaLock && aOtaEnabled) ArduinoOTA.handle();
if (aOtaEnabled) ArduinoOTA.handle();
handleAlexa();
handleOverlays();
if (!arlsTimeout) //block stuff if WARLS is enabled
if (!arlsTimeout) //block stuff if WARLS/Adalight is enabled
{
if (dnsActive) dnsServer.processNextRequest();
handleHue();

View File

@@ -61,7 +61,7 @@ void saveSettingsToEEPROM()
EEPROM.write(226, notifyDirectDefault);
EEPROM.write(227, apChannel);
EEPROM.write(228, apHide);
EEPROM.write(229, ledCount);
EEPROM.write(229, (ledCount >> 0) & 0xFF);
EEPROM.write(230, notifyButton);
EEPROM.write(231, notifyTwice);
EEPROM.write(232, buttonEnabled);
@@ -85,8 +85,8 @@ void saveSettingsToEEPROM()
EEPROM.write(250, receiveNotificationBrightness);
EEPROM.write(251, fadeTransition);
EEPROM.write(252, reverseMode);
EEPROM.write(253, (transitionDelay >> 0) & 0xFF);
EEPROM.write(254, (transitionDelay >> 8) & 0xFF);
EEPROM.write(253, (transitionDelayDefault >> 0) & 0xFF);
EEPROM.write(254, (transitionDelayDefault >> 8) & 0xFF);
EEPROM.write(255, briMultiplier);
//255,250,231,230,226 notifier bytes
for (int i = 256; i < 288; ++i)
@@ -147,6 +147,8 @@ void saveSettingsToEEPROM()
EEPROM.write(395, (abs(utcOffsetSecs) >> 8) & 0xFF);
EEPROM.write(396, (utcOffsetSecs<0)); //is negative
EEPROM.write(397, initLedsLast);
EEPROM.write(398, (ledCount >> 8) & 0xFF);
EEPROM.write(399, disableSecTransition);
for (int k=0;k<6;k++){
int in = 900+k*8;
@@ -207,6 +209,25 @@ void saveSettingsToEEPROM()
EEPROM.write(2179, macroLongPress);
EEPROM.write(2180, macroCountdown);
EEPROM.write(2181, macroNl);
EEPROM.write(2200,!receiveDirect);
EEPROM.write(2201,enableRealtimeUI);
EEPROM.write(2202,uiConfiguration);
EEPROM.write(2203,autoRGBtoRGBW);
EEPROM.write(2204,skipFirstLed);
if (saveCurrPresetCycConf)
{
EEPROM.write(2205,presetCyclingEnabled);
EEPROM.write(2206,(presetCycleTime >> 0) & 0xFF);
EEPROM.write(2207,(presetCycleTime >> 8) & 0xFF);
EEPROM.write(2208,presetCycleMin);
EEPROM.write(2209,presetCycleMax);
EEPROM.write(2210,presetApplyBri);
EEPROM.write(2211,presetApplyCol);
EEPROM.write(2212,presetApplyFx);
saveCurrPresetCycConf = false;
}
EEPROM.commit();
}
@@ -259,7 +280,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); if (ledCount > LEDCOUNT) ledCount = LEDCOUNT;
ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10;
notifyButton = EEPROM.read(230);
notifyTwice = EEPROM.read(231);
buttonEnabled = EEPROM.read(232);
@@ -286,7 +307,8 @@ void loadSettingsFromEEPROM(bool first)
receiveNotificationBrightness = EEPROM.read(250);
fadeTransition = EEPROM.read(251);
reverseMode = EEPROM.read(252);
transitionDelay = ((EEPROM.read(253) << 0) & 0xFF) + ((EEPROM.read(254) << 8) & 0xFF00);
transitionDelayDefault = ((EEPROM.read(253) << 0) & 0xFF) + ((EEPROM.read(254) << 8) & 0xFF00);
transitionDelay = transitionDelayDefault;
briMultiplier = EEPROM.read(255);
otaPass = "";
for (int i = 256; i < 288; ++i)
@@ -414,14 +436,37 @@ void loadSettingsFromEEPROM(bool first)
macroCountdown = EEPROM.read(2180);
macroNl = EEPROM.read(2181);
}
receiveDirect = !EEPROM.read(2200);
enableRealtimeUI = EEPROM.read(2201);
uiConfiguration = EEPROM.read(2202);
#ifdef WLED_FLASH_512K_MODE
uiConfiguration = 1;
//force default UI since mobile is unavailable
#endif
autoRGBtoRGBW = EEPROM.read(2203);
skipFirstLed = EEPROM.read(2204);
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);
presetCycleMin = EEPROM.read(2208);
presetCycleMax = EEPROM.read(2209);
presetApplyBri = EEPROM.read(2210);
presetApplyCol = EEPROM.read(2211);
presetApplyFx = EEPROM.read(2212);
}
bootPreset = EEPROM.read(389);
wifiLock = EEPROM.read(393);
utcOffsetSecs = ((EEPROM.read(394) << 0) & 0xFF) + ((EEPROM.read(395) << 8) & 0xFF00);
if (EEPROM.read(396)) utcOffsetSecs = -utcOffsetSecs; //negative
initLedsLast = EEPROM.read(397);
disableSecTransition = EEPROM.read(399);
//favorite setting memory (25 slots/ each 20byte)
//favorite setting (preset) memory (25 slots/ each 20byte)
//400 - 899 reserved
currentTheme = EEPROM.read(948);
@@ -471,6 +516,7 @@ 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);
@@ -480,7 +526,7 @@ void applyPreset(byte index, bool loadBri, bool loadCol, bool loadFX)
ccFromStart = (EEPROM.read(i+14)<2);
ccStep = EEPROM.read(i+15);
strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd);
strip.setMode(effectCurrent);
if (lastfx != effectCurrent) strip.setMode(effectCurrent);
strip.setSpeed(effectSpeed);
strip.setIntensity(effectIntensity);
}

View File

@@ -141,11 +141,9 @@ String getSettings(byte subPage)
resp += ds + "CG" + v + colS[1] +";";
resp += ds + "CB" + v + colS[2] +";";
resp += ds + "CA" + v + briS +";";
if (useRGBW) {
resp += ds + "CW" + v + whiteS +";";
} else {
resp += ds + "CW" + v + "-1;";
}
resp += ds + "EW" + c + useRGBW +";";
resp += ds + "AW" + c + autoRGBtoRGBW +";";
resp += ds + "CW" + v + whiteS +";";
resp += ds + "SR" + v + colSecS[0] +";";
resp += ds + "SG" + v + colSecS[1] +";";
resp += ds + "SB" + v + colSecS[2] +";";
@@ -161,6 +159,7 @@ String getSettings(byte subPage)
resp += ds + "TS" + c + sweepTransition +";";
resp += ds + "TI" + c + !sweepDirection +";";
resp += ds + "TD" + v + transitionDelay +";";
resp += ds + "T2" + c + !disableSecTransition +";";
resp += ds + "BF" + v + briMultiplier +";";
resp += ds + "TB" + v + nightlightTargetBri +";";
resp += ds + "TL" + v + nightlightDelayMins +";";
@@ -168,10 +167,12 @@ String getSettings(byte subPage)
resp += ds + "RV" + c + reverseMode +";";
resp += ds + "EI" + c + initLedsLast +";";
resp += ds + "WO" + v + arlsOffset +";";
resp += ds + "SL" + c + skipFirstLed +";";
}
if (subPage == 3)
{
resp += ds + "UI" + si + String(uiConfiguration) + ";";
resp += ds + "DS" + v + "\"" + serverDescription + "\";";
resp += ds + "MD" + c + useHSBDefault + ";";
resp += ds + "TH" + si + String(currentTheme) + ";";
@@ -191,6 +192,8 @@ String getSettings(byte subPage)
resp += ds + "SB" + c + notifyButton +";";
resp += ds + "SH" + c + notifyHue +";";
resp += ds + "S2" + c + notifyTwice +";";
resp += ds + "RD" + c + receiveDirect +";";
resp += ds + "RU" + c + enableRealtimeUI +";";
resp += ds + "AL" + c + alexaEnabled +";";
resp += ds + "AI" + v + "\"" + alexaInvocationName + "\";";
resp += ds + "SA" + c + alexaNotify +";";

View File

@@ -115,9 +115,15 @@ void handleSettingsSet(byte subPage)
if (server.hasArg("LC"))
{
int i = server.arg("LC").toInt();
if (i >= 0 && i <= LEDCOUNT) ledCount = i;
strip.setLedCount(ledCount);
if (i > 0 && i <= 1200) ledCount = i;
//RMT eats up too much RAM
#ifdef ARDUINO_ARCH_ESP32
if (ledCount > 600) ledCount = 600;
#endif
}
ccIndex2 = ledCount -1;
useRGBW = server.hasArg("EW");
autoRGBtoRGBW = server.hasArg("AW");
if (server.hasArg("IS")) //ignore settings and save current brightness, colors and fx as default
{
colS[0] = col[0];
@@ -166,14 +172,7 @@ void handleSettingsSet(byte subPage)
if (server.hasArg("CW"))
{
int i = server.arg("CW").toInt();
if (i >= 0 && i <= 255)
{
useRGBW = true;
whiteS = i;
} else {
useRGBW = false;
whiteS = 0;
}
if (i >= 0 && i <= 255) whiteS = i;
}
if (server.hasArg("CA"))
{
@@ -196,6 +195,7 @@ void handleSettingsSet(byte subPage)
if (i >= 0 && i <= 255) effectIntensityDefault = i;
}
}
saveCurrPresetCycConf = server.hasArg("PC");
turnOnAtBoot = server.hasArg("BO");
if (server.hasArg("BP"))
{
@@ -214,6 +214,7 @@ void handleSettingsSet(byte subPage)
transitionDelay = i;
}
}
disableSecTransition = !server.hasArg("T2");
if (server.hasArg("TB"))
{
nightlightTargetBri = server.arg("TB").toInt();
@@ -232,6 +233,7 @@ void handleSettingsSet(byte subPage)
int i = server.arg("WO").toInt();
if (i >= -255 && i <= 255) arlsOffset = i;
}
skipFirstLed = server.hasArg("SL");
if (server.hasArg("BF"))
{
int i = server.arg("BF").toInt();
@@ -242,6 +244,7 @@ void handleSettingsSet(byte subPage)
//UI
if (subPage == 3)
{
if (server.hasArg("UI")) uiConfiguration = server.arg("UI").toInt();
if (server.hasArg("DS")) serverDescription = server.arg("DS");
useHSBDefault = server.hasArg("MD");
useHSB = useHSBDefault;
@@ -270,6 +273,8 @@ void handleSettingsSet(byte subPage)
notifyDirect = notifyDirectDefault;
notifyButton = server.hasArg("SB");
notifyTwice = server.hasArg("S2");
receiveDirect = server.hasArg("RD");
enableRealtimeUI = server.hasArg("RU");
alexaEnabled = server.hasArg("AL");
if (server.hasArg("AI")) alexaInvocationName = server.arg("AI");
alexaNotify = server.hasArg("SA");
@@ -383,8 +388,8 @@ void handleSettingsSet(byte subPage)
aOtaEnabled = server.hasArg("AO");
}
}
saveSettingsToEEPROM();
if (subPage == 2) strip.init(useRGBW,ledCount,PIN,skipFirstLed);
}
bool handleSet(String req)
@@ -642,6 +647,8 @@ bool handleSet(String req)
}
}
//toggle nightlight mode
bool aNlDef = false;
if (req.indexOf("&ND") > 0) aNlDef = true;
pos = req.indexOf("NL=");
if (pos > 0)
{
@@ -651,9 +658,13 @@ bool handleSet(String req)
bri = briT;
} else {
nightlightActive = true;
nightlightDelayMins = req.substring(pos + 3).toInt();
if (!aNlDef) nightlightDelayMins = req.substring(pos + 3).toInt();
nightlightStartTime = millis();
}
} else if (aNlDef)
{
nightlightActive = true;
nightlightStartTime = millis();
}
//set nightlight target brightness
pos = req.indexOf("NT=");
@@ -679,6 +690,10 @@ bool handleSet(String req)
auxActive = true;
if (auxTime == 0) auxActive = false;
}
pos = req.indexOf("TT=");
if (pos > 0) {
transitionDelay = req.substring(pos + 3).toInt();
}
//main toggle on/off
pos = req.indexOf("&T=");
if (pos > 0) {
@@ -696,6 +711,8 @@ bool handleSet(String req)
}
}
}
//deactivate nightlight if target brightness is reached
if (bri == nightlightTargetBri) nightlightActive = false;
//set time (unix timestamp)
pos = req.indexOf("ST=");
if (pos > 0) {
@@ -718,30 +735,53 @@ bool handleSet(String req)
pos = req.indexOf("CM="); if (pos > 0) {ccStep = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CF="); if (pos > 0) {ccFromStart = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CE="); if (pos > 0) {ccFromEnd = (req.substring(pos + 3).toInt()); _cc_updated = true;}
if (ccIndex2 == 255) ccIndex2 = ledCount-1;
if (_cc_updated) strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd);
//set presets
pos = req.indexOf("P1="); //sets first preset for cycle
if (pos > 0) presetCycleMin = req.substring(pos + 3).toInt();
pos = req.indexOf("P2="); //sets last preset for cycle
if (pos > 0) presetCycleMax = req.substring(pos + 3).toInt();
if (req.indexOf("CY=") > 0) //preset cycle
{
presetCyclingEnabled = true;
if (req.indexOf("CY=0") > 0)
{
presetCyclingEnabled = false;
}
presetCycCurr = presetCycleMin;
}
pos = req.indexOf("PT="); //sets cycle time in ms
if (pos > 0) {
int v = req.substring(pos + 3).toInt();
if (v > 49) presetCycleTime = v;
}
if (req.indexOf("PA=") > 0) //apply brightness from preset
{
presetApplyBri = true;
if (req.indexOf("PA=0") > 0) presetApplyBri = false;
}
if (req.indexOf("PC=") > 0) //apply color from preset
{
presetApplyCol = true;
if (req.indexOf("PC=0") > 0) presetApplyCol = false;
}
if (req.indexOf("PX=") > 0) //apply effects from preset
{
presetApplyFx = true;
if (req.indexOf("PX=0") > 0) presetApplyFx = false;
}
pos = req.indexOf("PS="); //saves current in preset
if (pos > 0) {
savePreset(req.substring(pos + 3).toInt());
}
pos = req.indexOf("PL="); //applies entire preset
if (pos > 0) {
applyPreset(req.substring(pos + 3).toInt(), true, true, true);
effectUpdated = true;
}
pos = req.indexOf("PA="); //applies brightness from preset
if (pos > 0) {
applyPreset(req.substring(pos + 3).toInt(), true, false, false);
}
pos = req.indexOf("PC="); //applies color from preset
if (pos > 0) {
applyPreset(req.substring(pos + 3).toInt(), false, true, false);
}
pos = req.indexOf("PX="); //applies effects from preset
if (pos > 0) {
applyPreset(req.substring(pos + 3).toInt(), false, false, true);
effectUpdated = true;
applyPreset(req.substring(pos + 3).toInt(), presetApplyBri, presetApplyCol, presetApplyFx);
if (presetApplyFx) effectUpdated = true;
}
//cronixie
@@ -768,7 +808,16 @@ bool handleSet(String req)
if (overlayCurrent == 4) strip.setCronixieBacklight(cronixieBacklight);
overlayRefreshedTime = 0;
}
pos = req.indexOf("U0="); //user var 0
if (pos > 0) {
userVar0 = req.substring(pos + 3).toInt();
}
pos = req.indexOf("U1="); //user var 1
if (pos > 0) {
userVar1 = req.substring(pos + 3).toInt();
}
//you can add more if you need
//internal call, does not send XML response
pos = req.indexOf("IN");
if (pos < 1) XML_response();

View File

@@ -1,6 +1,46 @@
/*
* Utility for SPIFFS filesystem
* Utility for SPIFFS filesystem & Serial console
*/
void handleSerial()
{
if (Serial.available() > 0) //support for Adalight protocol to high-speed control LEDs over serial (gamma correction done by PC)
{
if (Serial.find("Ada"))
{
if (!arlsTimeout){
if (bri == 0) strip.setBrightness(briLast);
strip.setRange(0, ledCount-1, 0);
strip.setMode(0);
}
arlsTimeout = true;
arlsTimeoutTime = millis() + 5200;
delay(1);
byte hi = Serial.read();
byte ledc = Serial.read();
byte chk = Serial.read();
if(chk != (hi ^ ledc ^ 0x55)) return;
if (ledCount < ledc) ledc = ledCount;
byte sc[3]; int t =-1; int to = 0;
for (int i=0; i < ledc; i++)
{
for (byte j=0; j<3; j++)
{
while (Serial.peek()<0) //no data yet available
{
delay(1);
to++;
if (to>5) {strip.show(); return;} //unexpected end of transmission
}
to = 0;
sc[j] = Serial.read();
}
strip.setPixelColor(i,sc[0],sc[1],sc[2],0);
}
strip.show();
}
}
}
#ifdef USEFS
String formatBytes(size_t bytes){

View File

@@ -3,11 +3,17 @@
*/
void wledInit()
{
{
EEPROM.begin(EEPSIZE);
if (!EEPROM.read(397)) strip.init(); //quick init
ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10;
//RMT eats up too much RAM
#ifdef ARDUINO_ARCH_ESP32
if (ledCount > 600) ledCount = 600;
#endif
if (!EEPROM.read(397)) strip.init(EEPROM.read(372),ledCount,PIN,EEPROM.read(2204)); //quick init
Serial.begin(115200);
Serial.setTimeout(50);
#ifdef USEFS
SPIFFS.begin();
@@ -16,32 +22,11 @@ void wledInit()
DEBUG_PRINTLN("Load EEPROM");
loadSettingsFromEEPROM(true);
if (!initLedsLast) initStrip();
DEBUG_PRINT("C-SSID: ");
DEBUG_PRINT("CSSID: ");
DEBUG_PRINT(clientSSID);
buildCssColorString();
userBeginPreConnection();
WiFi.disconnect(); //close old connections
if (staticIP[0] != 0)
{
WiFi.config(staticIP, staticGateway, staticSubnet, staticDNS);
} else
{
WiFi.config(0U, 0U, 0U);
}
if (apSSID.length()>0)
{
DEBUG_PRINT("USING AP");
DEBUG_PRINTLN(apSSID.length());
initAP();
} else
{
DEBUG_PRINTLN("NO AP");
WiFi.softAPdisconnect(true);
}
initCon();
DEBUG_PRINTLN("");
@@ -54,17 +39,11 @@ void wledInit()
hueIP[1] = WiFi.localIP()[1];
hueIP[2] = WiFi.localIP()[2];
}
// Set up mDNS responder:
if (cmDNS != NULL && !onlyAP && !MDNS.begin(cmDNS.c_str())) {
DEBUG_PRINTLN("Error setting up MDNS responder!");
down();
}
DEBUG_PRINTLN("mDNS responder started");
if (udpPort > 0 && udpPort != ntpLocalPort && WiFi.status() == WL_CONNECTED)
{
udpConnected = notifierUdp.begin(udpPort);
if (udpConnected && udpRgbPort != udpPort) udpRgbConnected = rgbUdp.begin(udpRgbPort);
}
if (ntpEnabled && WiFi.status() == WL_CONNECTED)
ntpConnected = ntpUdp.begin(ntpLocalPort);
@@ -76,7 +55,7 @@ void wledInit()
dnsServer.start(53, "*", WiFi.softAPIP());
dnsActive = true;
}
if (!initLedsLast) strip.service();
//SERVER INIT
//settings page
server.on("/settings", HTTP_GET, [](){
@@ -191,44 +170,19 @@ void wledInit()
val += "mA currently";
serveMessage(200,val,"This is just an estimate (does not take into account several factors like effects and wire resistance). It is NOT an accurate measurement!",254);
});
server.on("/u", HTTP_GET, [](){
server.setContentLength(strlen_P(PAGE_usermod));
server.send(200, "text/html", "");
server.sendContent_P(PAGE_usermod);
});
server.on("/teapot", HTTP_GET, [](){
serveMessage(418, "418. I'm a teapot.","(Tangible Embedded Advanced Project Of Twinkling)",254);
});
server.on("/build", HTTP_GET, [](){
String info = "hard-coded build info:\r\n\n";
#ifdef ARDUINO_ARCH_ESP32
info += "platform: esp32\r\n";
#else
info += "platform: esp8266\r\n";
#endif
info += "version: " + versionString + "\r\n";
info += "build: " + (String)VERSION + "\r\n";
info += "eepver: " + String(EEPVER) + "\r\n";
#ifdef RGBW
info += "rgbw: true\r\n";
#else
info += "rgbw: false\r\n";
#endif
info += "max-leds: " + (String)LEDCOUNT + "\r\n";
#ifdef USEFS
info += "spiffs: true\r\n";
#else
info += "spiffs: false\r\n";
#endif
#ifdef DEBUG
info += "debug: true\r\n";
#else
info += "debug: false\r\n";
#endif
info += "button-pin: gpio" + String(buttonPin) + "\r\n";
#ifdef ARDUINO_ARCH_ESP32
info += "strip-pin: gpio" + String(PIN) + "\r\n";
#else
info += "strip-pin: gpio2\r\n";
#endif
server.send(200, "text/plain", info);
server.send(200, "text/plain", getBuildInfo());
});
//if OTA is allowed
if (!otaLock){
@@ -241,8 +195,6 @@ void wledInit()
server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); }, handleFileUpload);
server.on("/list", HTTP_GET, handleFileList);
#endif
server.on("/down", HTTP_GET, down);
server.on("/cleareeprom", HTTP_GET, clearEEPROM);
//init ota page
httpUpdater.setup(&server);
} else
@@ -250,12 +202,6 @@ void wledInit()
server.on("/edit", HTTP_GET, [](){
serveMessage(500, "Access Denied", txd, 254);
});
server.on("/down", HTTP_GET, [](){
serveMessage(500, "Access Denied", txd, 254);
});
server.on("/cleareeprom", HTTP_GET, [](){
serveMessage(500, "Access Denied", txd, 254);
});
server.on("/update", HTTP_GET, [](){
serveMessage(500, "Access Denied", txd, 254);
});
@@ -273,13 +219,21 @@ void wledInit()
server.send(404, "text/plain", "Not Found");
}
});
#ifndef ARDUINO_ARCH_ESP32
const char * headerkeys[] = {"User-Agent"};
server.collectHeaders(headerkeys,sizeof(char*));
#else
String ua = "User-Agent";
server.collectHeaders(ua);
#endif
if (!initLedsLast) strip.service();
//init Alexa hue emulation
if (alexaEnabled) alexaInit();
server.begin();
DEBUG_PRINTLN("HTTP server started");
// Add service to MDNS
MDNS.addService("http", "tcp", 80);
//init ArduinoOTA
if (aOtaEnabled)
@@ -290,25 +244,38 @@ void wledInit()
#endif
DEBUG_PRINTLN("Start ArduinoOTA");
});
if (cmDNS.length() > 0) ArduinoOTA.setHostname(cmDNS.c_str());
ArduinoOTA.begin();
}
if (!initLedsLast) strip.service();
// Set up mDNS responder:
if (cmDNS.length() > 0 && !onlyAP)
{
MDNS.begin(cmDNS.c_str());
DEBUG_PRINTLN("mDNS responder started");
// Add service to MDNS
MDNS.addService("http", "tcp", 80);
}
if (initLedsLast) initStrip();
userBegin();
if (macroBoot>0) applyMacro(macroBoot);
Serial.println("Ada");
}
void initStrip()
{
// Initialize NeoPixel Strip and button
if (initLedsLast) strip.init();
strip.setLedCount(ledCount);
if (initLedsLast) strip.init(useRGBW,ledCount,PIN,skipFirstLed);
strip.setReverseMode(reverseMode);
strip.setColor(0);
strip.setBrightness(255);
strip.start();
pinMode(buttonPin, INPUT_PULLUP);
pinMode(4,OUTPUT); //this is only needed in special cases
digitalWrite(4,LOW);
if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true);
colorUpdated(0);
@@ -324,9 +291,35 @@ void initAP(){
void initCon()
{
WiFi.disconnect(); //close old connections
if (staticIP[0] != 0)
{
WiFi.config(staticIP, staticGateway, staticSubnet, staticDNS);
} else
{
WiFi.config(0U, 0U, 0U);
}
if (apSSID.length()>0)
{
DEBUG_PRINT("USING AP");
DEBUG_PRINTLN(apSSID.length());
initAP();
} else
{
DEBUG_PRINTLN("NO AP");
WiFi.softAPdisconnect(true);
}
int fail_count = 0;
if (clientSSID.length() <1 || clientSSID.equals("Your_Network")) fail_count = apWaitTimeSecs*2;
#ifndef ARDUINO_ARCH_ESP32
WiFi.hostname(serverDescription);
#endif
WiFi.begin(clientSSID.c_str(), clientPass.c_str());
#ifdef ARDUINO_ARCH_ESP32
WiFi.setHostname(serverDescription.c_str());
#endif
unsigned long lastTry = 0;
bool con = false;
while(!con)
@@ -341,7 +334,6 @@ void initCon()
}
if (millis()-lastTry > 499) {
con = (WiFi.status() == WL_CONNECTED);
if (con) DEBUG_PRINTLN("rofl");
lastTry = millis();
DEBUG_PRINTLN("C_NC");
if (!recoveryAPDisabled && fail_count > apWaitTimeSecs*2)
@@ -374,6 +366,7 @@ void buildCssColorString()
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
}
@@ -407,19 +400,46 @@ void serveIndexOrWelcome()
}
}
void serveRealtimeError(bool settings)
{
String mesg = "The ";
mesg += (settings)?"settings":"WLED";
mesg += " UI is not available while receiving real-time data (UDP from ";
mesg += realtimeIP[0];
for (int i = 1; i < 4; i++)
{
mesg += ".";
mesg += realtimeIP[i];
}
mesg += ").";
server.send(200, "text/plain", mesg);
}
void serveIndex()
{
if (!arlsTimeout) //do not serve while receiving realtime
bool serveMobile = false;
if (uiConfiguration == 0) serveMobile = checkClientIsMobile(server.header("User-Agent"));
else if (uiConfiguration == 2) serveMobile = true;
if (!arlsTimeout || enableRealtimeUI) //do not serve while receiving realtime
{
server.setContentLength(strlen_P(PAGE_index0) + cssColorString.length() + strlen_P(PAGE_index1) + strlen_P(PAGE_index2) + strlen_P(PAGE_index3));
server.send(200, "text/html", "");
server.sendContent_P(PAGE_index0);
server.sendContent(cssColorString);
server.sendContent_P(PAGE_index1);
server.sendContent_P(PAGE_index2);
server.sendContent_P(PAGE_index3);
if (serveMobile)
{
server.setContentLength(strlen_P(PAGE_indexM));
server.send(200, "text/html", "");
server.sendContent_P(PAGE_indexM);
} else
{
server.setContentLength(strlen_P(PAGE_index0) + cssColorString.length() + strlen_P(PAGE_index1) + strlen_P(PAGE_index2) + strlen_P(PAGE_index3));
server.send(200, "text/html", "");
server.sendContent_P(PAGE_index0);
server.sendContent(cssColorString);
server.sendContent_P(PAGE_index1);
server.sendContent_P(PAGE_index2);
server.sendContent_P(PAGE_index3);
}
} else {
server.send(200, "text/plain", "The WLED UI is not available while receiving real-time data.");
serveRealtimeError(false);
}
}
@@ -457,7 +477,7 @@ void serveMessage(int code, String headl, String subl="", int optionType)
void serveSettings(byte subPage)
{
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 255: welcomepage
if (!arlsTimeout) //do not serve while receiving realtime
if (!arlsTimeout || enableRealtimeUI) //do not serve while receiving realtime
{
int pl0, pl1;
switch (subPage)
@@ -504,10 +524,49 @@ void serveSettings(byte subPage)
default: server.sendContent_P(PAGE_settings1);
}
} else {
server.send(200, "text/plain", "The settings are not available while receiving real-time data.");
serveRealtimeError(true);
}
}
String getBuildInfo()
{
String info = "hard-coded build info:\r\n\n";
#ifdef ARDUINO_ARCH_ESP32
info += "platform: esp32\r\n";
#else
info += "platform: esp8266\r\n";
#endif
info += "version: " + versionString + "\r\n";
info += "build: " + (String)VERSION + "\r\n";
info += "eepver: " + String(EEPVER) + "\r\n";
#ifdef USEFS
info += "spiffs: true\r\n";
#else
info += "spiffs: false\r\n";
#endif
#ifdef DEBUG
info += "debug: true\r\n";
#else
info += "debug: false\r\n";
#endif
info += "button-pin: gpio" + String(buttonPin) + "\r\n";
#ifdef ARDUINO_ARCH_ESP32
info += "strip-pin: gpio" + String(PIN) + "\r\n";
#else
info += "strip-pin: gpio2\r\n";
#endif
info += "build-type: src\r\n";
return info;
}
bool checkClientIsMobile(String useragent)
{
//to save complexity this function is not comprehensive
if (useragent.indexOf("Android") >= 0) return true;
if (useragent.indexOf("iPhone") >= 0) return true;
if (useragent.indexOf("iPod") >= 0) return true;
return false;
}

View File

@@ -4,9 +4,11 @@
* EEPROM bytes 2944 to 3071 are reserved for your custom use case.
*/
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
void userBeginPreConnection()
{
}
void userBegin()
@@ -18,4 +20,3 @@ void userLoop()
{
}

View File

@@ -9,11 +9,13 @@ void notify(byte callMode, bool followUp=false)
if (!udpConnected) return;
switch (callMode)
{
case 0: return;
case 1: if (!notifyDirect) return; break;
case 2: if (!notifyButton) return; break;
case 4: if (!notifyDirect) return; break;
case 6: if (!notifyDirect) return; break; //fx change
case 7: if (!notifyHue) return; break;
case 8: if (!notifyDirect) return; break;
default: return;
}
byte udpOut[WLEDPACKETSIZE];
@@ -48,20 +50,66 @@ void notify(byte callMode, bool followUp=false)
notificationTwoRequired = (followUp)? false:notifyTwice;
}
void arlsLock(uint32_t timeoutMs)
{
if (!arlsTimeout){
strip.setRange(0, ledCount-1, 0);
strip.setMode(0);
}
arlsTimeout = true;
arlsTimeoutTime = millis() + timeoutMs;
}
void handleNotifications()
{
//send second notification if enabled
if(udpConnected && notificationTwoRequired && millis()-notificationSentTime > 250){
notify(notificationSentCallMode,true);
}
if(udpConnected && receiveNotifications){
//unlock strip when realtime UDP times out
if (arlsTimeout && millis() > arlsTimeoutTime)
{
strip.unlockAll();
if (bri == 0) strip.setBrightness(0);
arlsTimeout = false;
strip.setMode(effectCurrent);
}
//receive UDP notifications
if(udpConnected && (receiveNotifications || receiveDirect)){
uint16_t packetSize = notifierUdp.parsePacket();
//hyperion / raw RGB
if (!packetSize && udpRgbConnected) {
packetSize = rgbUdp.parsePacket();
if (!receiveDirect) return;
realtimeIP = rgbUdp.remoteIP();
if (packetSize > 1026 || packetSize < 3) return;
byte udpIn[packetSize];
rgbUdp.read(udpIn, packetSize);
arlsLock(5200);
uint16_t id = 0;
for (uint16_t i = 0; i < packetSize -2; i += 3)
{
if (useGammaCorrectionRGB)
{
strip.setPixelColor(id, gamma8[udpIn[i]], gamma8[udpIn[i+1]], gamma8[udpIn[i+2]]);
} else {
strip.setPixelColor(id, udpIn[i], udpIn[i+1], udpIn[i+2]);
}
id++; if (id >= ledCount) break;
}
strip.show();
return;
}
if (packetSize > 1026) return;
if(packetSize && notifierUdp.remoteIP() != WiFi.localIP()) //don't process broadcasts we send ourselves
{
byte udpIn[packetSize];
notifierUdp.read(udpIn, packetSize);
if (udpIn[0] == 0 && !arlsTimeout) //wled notifier, block if realtime packets active
if (udpIn[0] == 0 && !arlsTimeout && receiveNotifications) //wled notifier, block if realtime packets active
{
if (receiveNotificationColor)
{
@@ -105,40 +153,59 @@ void handleNotifications()
if (receiveNotificationBrightness) bri = udpIn[2];
colorUpdated(3);
}
} else if (udpIn[0] == 1) //warls
} else if (udpIn[0] > 0 && udpIn[0] < 4 && receiveDirect) //1 warls //2 drgb //3 drgbw
{
realtimeIP = notifierUdp.remoteIP();
if (packetSize > 1) {
if (udpIn[1] == 0)
{
arlsTimeout = false;
} else {
if (!arlsTimeout){
strip.setRange(0, ledCount-1, 0);
strip.setMode(0);
}
arlsTimeout = true;
arlsTimeoutTime = millis() + 1000*udpIn[1];
arlsLock(udpIn[1]*1000);
}
for (int i = 2; i < packetSize -3; i += 4)
if (udpIn[0] == 1) //warls
{
if (udpIn[i] + arlsOffset < ledCount && udpIn[i] + arlsOffset >= 0)
if (useGammaCorrectionRGB)
for (uint16_t i = 2; i < packetSize -3; i += 4)
{
strip.setPixelColor(udpIn[i] + arlsOffset, gamma8[udpIn[i+1]], gamma8[udpIn[i+2]], gamma8[udpIn[i+3]]);
} else {
strip.setPixelColor(udpIn[i] + arlsOffset, udpIn[i+1], udpIn[i+2], udpIn[i+3]);
if (udpIn[i] + arlsOffset < ledCount && udpIn[i] + arlsOffset >= 0)
if (useGammaCorrectionRGB)
{
strip.setPixelColor(udpIn[i] + arlsOffset, gamma8[udpIn[i+1]], gamma8[udpIn[i+2]], gamma8[udpIn[i+3]]);
} else {
strip.setPixelColor(udpIn[i] + arlsOffset, udpIn[i+1], udpIn[i+2], udpIn[i+3]);
}
}
} else if (udpIn[0] == 2) //drgb
{
uint16_t id = 0;
for (uint16_t i = 2; i < packetSize -2; i += 3)
{
if (useGammaCorrectionRGB)
{
strip.setPixelColor(id, gamma8[udpIn[i]], gamma8[udpIn[i+1]], gamma8[udpIn[i+2]]);
} else {
strip.setPixelColor(id, udpIn[i+0], udpIn[i+1], udpIn[i+2]);
}
id++; if (id >= ledCount) break;
}
} else if (udpIn[0] == 3) //drgbw
{
uint16_t id = 0;
for (uint16_t i = 2; i < packetSize -3; i += 4)
{
if (useGammaCorrectionRGB)
{
strip.setPixelColor(id, gamma8[udpIn[i]], gamma8[udpIn[i+1]], gamma8[udpIn[i+2]], gamma8[udpIn[i+3]]);
} else {
strip.setPixelColor(id, udpIn[i+0], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
}
id++; if (id >= ledCount) break;
}
}
strip.show();
}
}
}
if (arlsTimeout && millis() > arlsTimeoutTime)
{
strip.unlockAll();
arlsTimeout = false;
strip.setMode(effectCurrent);
}
}
}

View File

@@ -12,28 +12,44 @@ void setAllLeds() {
} else {
strip.setBrightness(val);
}
if (disableSecTransition)
{
for (byte i = 0; i<3; i++)
{
colSecT[i] = colSec[i];
}
whiteSecT = whiteSec;
}
if (autoRGBtoRGBW)
{
colorRGBtoRGBW(colT,&whiteT);
colorRGBtoRGBW(colSecT,&whiteSecT);
}
if (useGammaCorrectionRGB)
{
strip.setColor(gamma8[colT[0]], gamma8[colT[1]], gamma8[colT[2]], gamma8[whiteT]);
strip.setSecondaryColor(gamma8[colSec[0]], gamma8[colSec[1]], gamma8[colSec[2]], gamma8[whiteSec]);
strip.setSecondaryColor(gamma8[colSecT[0]], gamma8[colSecT[1]], gamma8[colSecT[2]], gamma8[whiteSecT]);
} else {
strip.setColor(colT[0], colT[1], colT[2], whiteT);
strip.setSecondaryColor(colSec[0], colSec[1], colSec[2], whiteSec);
strip.setSecondaryColor(colSecT[0], colSecT[1], colSecT[2], whiteSecT);
}
}
void setLedsStandard()
{
colOld[0] = col[0];
colOld[1] = col[1];
colOld[2] = col[2];
for (byte i = 0; i<3; i++)
{
colOld[i] = col[i];
colT[i] = col[i];
colSecOld[i] = colSec[i];
colSecT[i] = colSec[i];
}
whiteOld = white;
briOld = bri;
colT[0] = col[0];
colT[1] = col[1];
colT[2] = col[2];
whiteSecOld = whiteSec;
whiteT = white;
briT = bri;
whiteSecT = whiteSec;
setAllLeds();
}
@@ -51,7 +67,7 @@ bool colorChanged()
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
//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
if (!colorChanged())
{
if (callMode == 6) notify(6);
@@ -78,6 +94,7 @@ void colorUpdated(int callMode)
{
//set correct delay if not using notification delay
if (callMode != 3) transitionDelayTemp = transitionDelay;
if (transitionDelayTemp == 0) {setLedsStandard();strip.trigger();return;}
if (transitionActive)
{
@@ -85,6 +102,10 @@ void colorUpdated(int callMode)
colOld[1] = colT[1];
colOld[2] = colT[2];
whiteOld = whiteT;
colSecOld[0] = colSecT[0];
colSecOld[1] = colSecT[1];
colSecOld[2] = colSecT[2];
whiteSecOld = whiteSecT;
briOld = briT;
tperLast = 0;
}
@@ -112,17 +133,20 @@ void handleTransitions()
strip.setFastUpdateMode(false);
return;
}
if (tper - tperLast < transitionResolution)
if (tper - tperLast < 0.004)
{
return;
}
tperLast = tper;
if (fadeTransition)
{
colT[0] = colOld[0]+((col[0] - colOld[0])*tper);
colT[1] = colOld[1]+((col[1] - colOld[1])*tper);
colT[2] = colOld[2]+((col[2] - colOld[2])*tper);
for (byte i = 0; i<3; i++)
{
colT[i] = colOld[i]+((col[i] - colOld[i])*tper);
colSecT[i] = colSecOld[i]+((colSec[i] - colSecOld[i])*tper);
}
whiteT = whiteOld +((white - whiteOld )*tper);
whiteSecT = whiteSecOld +((whiteSec - whiteSecOld )*tper);
briT = briOld +((bri - briOld )*tper);
}
if (sweepTransition)
@@ -176,4 +200,14 @@ void handleNightlight()
{
nightlightActiveOld = false;
}
//also handle preset cycle here
if (presetCyclingEnabled && (millis() - presetCycledTime > presetCycleTime))
{
applyPreset(presetCycCurr,presetApplyBri,presetApplyCol,presetApplyFx);
presetCycCurr++; if (presetCycCurr > presetCycleMax) presetCycCurr = presetCycleMin;
if (presetCycCurr > 25) presetCycCurr = 1;
colorUpdated(8);
presetCycledTime = millis();
}
}

View File

@@ -49,7 +49,10 @@ TimeChangeRule NZDT = {Second, Sun, Sep, 2, 780 }; //Daylight time = UTC + 13
TimeChangeRule NZST = {First, Sun, Apr, 3, 720 }; //Standard time = UTC + 12 hours
Timezone tzNZ(NZDT, NZST);
Timezone* timezones[] = { &tzUTC, &tzUK, &tzEUCentral, &tzEUEastern, &tzUSEastern, &tzUSCentral, &tzUSMountain, &tzUSArizona, &tzUSPacific, &tzChina, &tzJapan, &tzAUEastern, &tzNZ};
TimeChangeRule NKST = {Last, Sun, Mar, 1, 510}; //Pyongyang Time = UTC + 8.5 hours
Timezone tzNK(NKST, NKST);
Timezone* timezones[] = {&tzUTC, &tzUK, &tzEUCentral, &tzEUEastern, &tzUSEastern, &tzUSCentral, &tzUSMountain, &tzUSArizona, &tzUSPacific, &tzChina, &tzJapan, &tzAUEastern, &tzNZ, &tzNK};
void handleNetworkTime()
{
@@ -106,7 +109,7 @@ bool checkNTPResponse()
unsigned long secsSince1900 = highWord << 16 | lowWord;
DEBUG_PRINT("Unix time = ");
unsigned long epoch = secsSince1900 - 2208988800UL; //subtract 70 years
unsigned long epoch = secsSince1900 - 2208988799UL; //subtract 70 years -1sec (on avg. more precision)
setTime(epoch);
DEBUG_PRINTLN(epoch);
if (countdownTime - now() > 0) countdownOverTriggered = false;

View File

@@ -115,8 +115,6 @@ void colorRGBtoXY(byte* rgb, float* xy) //rgb to coordinates (https://www.develo
xy[1] = Y / (X + Y + Z);
}
/*//For some reason min and max are not declared here
float minf (float v, float w)
{
if (w > v) return v;
@@ -129,11 +127,12 @@ float maxf (float v, float w)
return v;
}
void colorRGBtoRGBW(byte* rgb, byte* wht) //rgb to rgbw, untested and currently unused
void colorRGBtoRGBW(byte* rgb, byte* wht) //rgb to rgbw (http://codewelt.com/rgbw)
{
*wht = (float)minf(rgb[0],minf(rgb[1],rgb[2]))*0.95;
rgb[0]-=wht;
rgb[1]-=wht;
rgb[2]-=wht;
}*/
float low = minf(rgb[0],minf(rgb[1],rgb[2]));
float high = maxf(rgb[0],maxf(rgb[1],rgb[2]));
if (high < 0.1f) return;
float sat = 255.0f * ((high - low) / high);
*wht = (byte)((255.0f - sat) / 255.0f * (rgb[0] + rgb[1] + rgb[2]) / 3);
}