Compare commits

...

10 Commits

Author SHA1 Message Date
cschwinne
d09a97f230 Full release of v0.6.0
Added transitionDelay from notification used for smoother sync
Fixed random color too dim
2018-03-15 13:03:50 +01:00
cschwinne
89afdd2b17 Most 0.6.0 features working
LEDs now turn on instantly after boot
Support Hardware ESP32 RMT NeopixelBus library
Added setting to force old LED boot behavior (init after WiFi)
Fixed overlay switching bug
Fixed ? characters in usused macros
Added transitionDelay to notifier packet
2018-03-15 12:04:14 +01:00
cschwinne
8d7a066680 Refactored settings names to save bandwidth and heap
Fixed update page back button
2018-03-14 19:05:51 +01:00
cschwinne
c93b185f54 Refactored variables for better readability 2018-03-14 13:16:28 +01:00
cschwinne
3ef4a2b9d2 Added Captive Portal DNS server for AP
Fixed overlay and AP password bugs
2018-03-14 11:41:24 +01:00
cschwinne
37f91c4d50 Finished implementing most time-related settings
Use wled default vendor zone for NTP server
2018-03-14 00:25:54 +01:00
cschwinne
bbb27dd70b Interim commit
Added option to send UDP notifications twice to increase reliability
Added a C64 color theme
Added clock options
Added 12 timezones
Merged Cronixie and useoverlay build options
Removed abbrev char[] from Timezone lib to save memory
Added setting to reverse/flip LEDs
Added long press random color button function
2018-03-06 23:47:08 +01:00
cschwinne
e7e11b8bd2 Added Philips Hue synchronization
Added HU and SA API calls to set color via Hue and Saturation values
2018-02-28 00:27:10 +01:00
cschwinne
1b0d735e50 Added user modification file 2018-02-25 14:46:11 +01:00
cschwinne
9aebaa78fa Fixed secondary white value setting having same value as white default
Changed default notification receive behavior to be like pre0.5.0 if no settings are changed
2018-02-23 22:18:31 +01:00
32 changed files with 1878 additions and 1118 deletions

View File

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

View File

@@ -73,7 +73,7 @@ void WS2812FX::stop() {
strip_off(); strip_off();
} }
void WS2812FX::setMode(uint8_t m) { void WS2812FX::setMode(byte m) {
_counter_mode_call = 0; _counter_mode_call = 0;
_counter_mode_step = 0; _counter_mode_step = 0;
_mode_last_call_time = 0; _mode_last_call_time = 0;
@@ -83,7 +83,7 @@ void WS2812FX::setMode(uint8_t m) {
strip_off_respectLock(); strip_off_respectLock();
} }
void WS2812FX::setSpeed(uint8_t s) { void WS2812FX::setSpeed(byte s) {
_counter_mode_call = 0; _counter_mode_call = 0;
_counter_mode_step = 0; _counter_mode_step = 0;
_mode_last_call_time = 0; _mode_last_call_time = 0;
@@ -91,35 +91,35 @@ void WS2812FX::setSpeed(uint8_t s) {
strip_off_respectLock(); strip_off_respectLock();
} }
void WS2812FX::increaseSpeed(uint8_t s) { void WS2812FX::increaseSpeed(byte s) {
s = constrain(_speed + s, SPEED_MIN, SPEED_MAX); s = constrain(_speed + s, SPEED_MIN, SPEED_MAX);
setSpeed(s); setSpeed(s);
} }
void WS2812FX::decreaseSpeed(uint8_t s) { void WS2812FX::decreaseSpeed(byte s) {
s = constrain(_speed - s, SPEED_MIN, SPEED_MAX); s = constrain(_speed - s, SPEED_MIN, SPEED_MAX);
setSpeed(s); setSpeed(s);
} }
void WS2812FX::setIntensity(uint8_t in) { void WS2812FX::setIntensity(byte in) {
_intensity=in; _intensity=in;
} }
void WS2812FX::setColor(uint8_t r, uint8_t g, uint8_t b) { void WS2812FX::setColor(byte r, byte g, byte b) {
setColor(((uint32_t)r << 16) | ((uint32_t)g << 8) | b); setColor(((uint32_t)r << 16) | ((uint32_t)g << 8) | b);
} }
void WS2812FX::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { void WS2812FX::setColor(byte r, byte g, byte b, byte w) {
setColor(((uint32_t)w << 24)|((uint32_t)r << 16) | ((uint32_t)g << 8) | b); setColor(((uint32_t)w << 24)|((uint32_t)r << 16) | ((uint32_t)g << 8) | b);
} }
void WS2812FX::setSecondaryColor(uint8_t r, uint8_t g, uint8_t b) { void WS2812FX::setSecondaryColor(byte r, byte g, byte b) {
setSecondaryColor(((uint32_t)r << 16) | ((uint32_t)g << 8) | b); setSecondaryColor(((uint32_t)r << 16) | ((uint32_t)g << 8) | b);
} }
void WS2812FX::setSecondaryColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { void WS2812FX::setSecondaryColor(byte r, byte g, byte b, byte w) {
setSecondaryColor(((uint32_t)w << 24)|((uint32_t)r << 16) | ((uint32_t)g << 8) | b); setSecondaryColor(((uint32_t)w << 24)|((uint32_t)r << 16) | ((uint32_t)g << 8) | b);
} }
@@ -136,33 +136,33 @@ void WS2812FX::setSecondaryColor(uint32_t c) {
setBrightness(_brightness); setBrightness(_brightness);
} }
void WS2812FX::increaseBrightness(uint8_t s) { void WS2812FX::increaseBrightness(byte s) {
s = constrain(_brightness + s, BRIGHTNESS_MIN, BRIGHTNESS_MAX); s = constrain(_brightness + s, BRIGHTNESS_MIN, BRIGHTNESS_MAX);
setBrightness(s); setBrightness(s);
} }
void WS2812FX::decreaseBrightness(uint8_t s) { void WS2812FX::decreaseBrightness(byte s) {
s = constrain(_brightness - s, BRIGHTNESS_MIN, BRIGHTNESS_MAX); s = constrain(_brightness - s, BRIGHTNESS_MIN, BRIGHTNESS_MAX);
setBrightness(s); setBrightness(s);
} }
boolean WS2812FX::isRunning() { bool WS2812FX::isRunning() {
return _running; return _running;
} }
uint8_t WS2812FX::getMode(void) { byte WS2812FX::getMode(void) {
return _mode_index; return _mode_index;
} }
uint8_t WS2812FX::getSpeed(void) { byte WS2812FX::getSpeed(void) {
return _speed; return _speed;
} }
uint8_t WS2812FX::getBrightness(void) { byte WS2812FX::getBrightness(void) {
return _brightness; return _brightness;
} }
uint8_t WS2812FX::getModeCount(void) { byte WS2812FX::getModeCount(void) {
return MODE_COUNT; return MODE_COUNT;
} }
@@ -198,7 +198,7 @@ void WS2812FX::strip_off_respectLock() {
* The colours are a transition r -> g -> b -> back to r * The colours are a transition r -> g -> b -> back to r
* Inspired by the Adafruit examples. * Inspired by the Adafruit examples.
*/ */
uint32_t WS2812FX::color_wheel(uint8_t pos) { uint32_t WS2812FX::color_wheel(byte pos) {
pos = 255 - pos; pos = 255 - pos;
if(pos < 85) { if(pos < 85) {
return ((uint32_t)(255 - pos * 3) << 16) | ((uint32_t)(0) << 8) | (pos * 3); return ((uint32_t)(255 - pos * 3) << 16) | ((uint32_t)(0) << 8) | (pos * 3);
@@ -215,11 +215,11 @@ uint32_t WS2812FX::color_wheel(uint8_t pos) {
/* /*
* Returns a new, random wheel index with a minimum distance of 42 from pos. * Returns a new, random wheel index with a minimum distance of 42 from pos.
*/ */
uint8_t WS2812FX::get_random_wheel_index(uint8_t pos) { byte WS2812FX::get_random_wheel_index(byte pos) {
uint8_t r = 0; byte r = 0;
uint8_t x = 0; byte x = 0;
uint8_t y = 0; byte y = 0;
uint8_t d = 0; byte d = 0;
while(d < 42) { while(d < 42) {
r = random(256); r = random(256);
@@ -360,13 +360,13 @@ void WS2812FX::mode_multi_dynamic(void) {
void WS2812FX::mode_breath(void) { void WS2812FX::mode_breath(void) {
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // step // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // step
uint16_t breath_delay_steps[] = { 7, 9, 13, 15, 16, 17, 18, 930, 19, 18, 15, 13, 9, 7, 4, 5, 10 }; // magic numbers for breathing LED uint16_t breath_delay_steps[] = { 7, 9, 13, 15, 16, 17, 18, 930, 19, 18, 15, 13, 9, 7, 4, 5, 10 }; // magic numbers for breathing LED
uint8_t breath_brightness_steps[] = { 150, 125, 100, 75, 50, 25, 16, 15, 16, 25, 50, 75, 100, 125, 150, 220, 255 }; // even more magic numbers! byte breath_brightness_steps[] = { 150, 125, 100, 75, 50, 25, 16, 15, 16, 25, 50, 75, 100, 125, 150, 220, 255 }; // even more magic numbers!
if(_counter_mode_call == 0) { if(_counter_mode_call == 0) {
_mode_color = breath_brightness_steps[0] + 1; _mode_color = breath_brightness_steps[0] + 1;
} }
uint8_t breath_brightness = _mode_color; // we use _mode_color to store the brightness byte breath_brightness = _mode_color; // we use _mode_color to store the brightness
if(_counter_mode_step < 8) { if(_counter_mode_step < 8) {
breath_brightness--; breath_brightness--;
@@ -376,7 +376,7 @@ void WS2812FX::mode_breath(void) {
// update index of current delay when target brightness is reached, start over after the last step // update index of current delay when target brightness is reached, start over after the last step
if(breath_brightness == breath_brightness_steps[_counter_mode_step]) { if(breath_brightness == breath_brightness_steps[_counter_mode_step]) {
_counter_mode_step = (_counter_mode_step + 1) % (sizeof(breath_brightness_steps)/sizeof(uint8_t)); _counter_mode_step = (_counter_mode_step + 1) % (sizeof(breath_brightness_steps)/sizeof(byte));
} }
for(uint16_t i=0; i < _led_count; i++) { for(uint16_t i=0; i < _led_count; i++) {
@@ -400,10 +400,10 @@ void WS2812FX::mode_fade(void) {
int y = _counter_mode_step - 127; int y = _counter_mode_step - 127;
y = 256 - (abs(y) * 2); y = 256 - (abs(y) * 2);
double z = (double)y/256; double z = (double)y/256;
uint8_t w = ((_color >> 24) & 0xFF), ws = ((_color_sec >> 24) & 0xFF); byte w = ((_color >> 24) & 0xFF), ws = ((_color_sec >> 24) & 0xFF);
uint8_t r = ((_color >> 16) & 0xFF), rs = ((_color_sec >> 16) & 0xFF); byte r = ((_color >> 16) & 0xFF), rs = ((_color_sec >> 16) & 0xFF);
uint8_t g = ((_color >> 8) & 0xFF), gs = ((_color_sec >> 8) & 0xFF); byte g = ((_color >> 8) & 0xFF), gs = ((_color_sec >> 8) & 0xFF);
uint8_t b = (_color & 0xFF), bs = (_color_sec & 0xFF); byte b = (_color & 0xFF), bs = (_color_sec & 0xFF);
w = w+((ws - w)*z); w = w+((ws - w)*z);
r = r+((rs - r)*z); r = r+((rs - r)*z);
g = g+((gs - g)*z); g = g+((gs - g)*z);
@@ -506,7 +506,7 @@ void WS2812FX::mode_rainbow_cycle(void) {
* Inspired by the Adafruit examples. * Inspired by the Adafruit examples.
*/ */
void WS2812FX::mode_theater_chase(void) { void WS2812FX::mode_theater_chase(void) {
uint8_t j = _counter_mode_call % 6; byte j = _counter_mode_call % 6;
if(j % 2 == 0) { if(j % 2 == 0) {
for(uint16_t i=0; i < _led_count; i=i+3) { for(uint16_t i=0; i < _led_count; i=i+3) {
if (!_locked[i+(j/2)]) if (!_locked[i+(j/2)])
@@ -529,7 +529,7 @@ void WS2812FX::mode_theater_chase(void) {
* Inspired by the Adafruit examples. * Inspired by the Adafruit examples.
*/ */
void WS2812FX::mode_theater_chase_rainbow(void) { void WS2812FX::mode_theater_chase_rainbow(void) {
uint8_t j = _counter_mode_call % 6; byte j = _counter_mode_call % 6;
if(j % 2 == 0) { if(j % 2 == 0) {
for(uint16_t i=0; i < _led_count; i=i+3) { for(uint16_t i=0; i < _led_count; i=i+3) {
if (!_locked[i+(j/2)]) if (!_locked[i+(j/2)])
@@ -552,10 +552,10 @@ void WS2812FX::mode_theater_chase_rainbow(void) {
* Running lights effect with smooth sine transition. * Running lights effect with smooth sine transition.
*/ */
void WS2812FX::mode_running_lights(void) { void WS2812FX::mode_running_lights(void) {
uint8_t w = ((_color >> 24) & 0xFF); byte w = ((_color >> 24) & 0xFF);
uint8_t r = ((_color >> 16) & 0xFF); byte r = ((_color >> 16) & 0xFF);
uint8_t g = ((_color >> 8) & 0xFF); byte g = ((_color >> 8) & 0xFF);
uint8_t b = (_color & 0xFF); byte b = (_color & 0xFF);
for(uint16_t i=0; i < _led_count; i++) { for(uint16_t i=0; i < _led_count; i++) {
int s = (sin(i+_counter_mode_call) * 127) + 128; int s = (sin(i+_counter_mode_call) * 127) + 128;
@@ -900,8 +900,8 @@ void WS2812FX::mode_chase_rainbow(void) {
* _color_sec flashes running on _color. * _color_sec flashes running on _color.
*/ */
void WS2812FX::mode_chase_flash(void) { void WS2812FX::mode_chase_flash(void) {
const static uint8_t flash_count = 4; const static byte flash_count = 4;
uint8_t flash_step = _counter_mode_call % ((flash_count * 2) + 1); byte flash_step = _counter_mode_call % ((flash_count * 2) + 1);
for(uint16_t i=0; i < _led_count; i++) { for(uint16_t i=0; i < _led_count; i++) {
if (!_locked[i]) if (!_locked[i])
@@ -933,8 +933,8 @@ void WS2812FX::mode_chase_flash(void) {
* _color_sec flashes running, followed by random color. * _color_sec flashes running, followed by random color.
*/ */
void WS2812FX::mode_chase_flash_random(void) { void WS2812FX::mode_chase_flash_random(void) {
const static uint8_t flash_count = 4; const static byte flash_count = 4;
uint8_t flash_step = _counter_mode_call % ((flash_count * 2) + 1); byte flash_step = _counter_mode_call % ((flash_count * 2) + 1);
for(uint16_t i=0; i < _counter_mode_step; i++) { for(uint16_t i=0; i < _counter_mode_step; i++) {
if (!_locked[i]) if (!_locked[i])
@@ -1606,13 +1606,13 @@ void WS2812FX::mode_cc_core()
for (int i = 0; i < _cc_num1; i++) for (int i = 0; i < _cc_num1; i++)
{ {
int num = 0; int num = 0;
num = ((k + i + _counter_cc_step) % _cc_i2) +_cc_i1; num = ((k + i + _counter_ccStep) % _cc_i2) +_cc_i1;
if (_cc_fs) setPixelColor(num, _color); if (_cc_fs) setPixelColor(num, _color);
if (_cc_fe) setPixelColor(_cc_i2 - num, _color); if (_cc_fe) setPixelColor(_cc_i2 - num, _color);
} }
} }
show(); show();
_counter_cc_step = (_counter_cc_step + _cc_step) % (_cc_i2 - _cc_i1); _counter_ccStep = (_counter_ccStep + _ccStep) % (_cc_i2 - _cc_i1);
_mode_delay = 10 + ((250 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX); _mode_delay = 10 + ((250 * (uint32_t)(SPEED_MAX - _speed)) / SPEED_MAX);
} }
@@ -1816,6 +1816,11 @@ void WS2812FX::setFastUpdateMode(bool y)
if (_mode_index == 0) _mode_delay = 20; if (_mode_index == 0) _mode_delay = 20;
} }
void WS2812FX::setReverseMode(bool b)
{
_reverseMode = b;
}
void WS2812FX::driverModeCronixie(bool b) void WS2812FX::driverModeCronixie(bool b)
{ {
_cronixieMode = b; _cronixieMode = b;
@@ -1826,7 +1831,7 @@ void WS2812FX::setCronixieBacklight(bool b)
_cronixieBacklightEnabled = b; _cronixieBacklightEnabled = b;
} }
void WS2812FX::setCronixieDigits(uint8_t d[]) void WS2812FX::setCronixieDigits(byte d[])
{ {
for (int i = 0; i<6; i++) for (int i = 0; i<6; i++)
{ {
@@ -1834,7 +1839,7 @@ void WS2812FX::setCronixieDigits(uint8_t d[])
} }
} }
double WS2812FX::getPowerEstimate(uint8_t leds, uint32_t c, uint8_t b) double WS2812FX::getPowerEstimate(byte leds, uint32_t c, byte b)
{ {
double _mARequired = 100; //ESP power double _mARequired = 100; //ESP power
double _mul = (double)b/255; double _mul = (double)b/255;
@@ -1854,7 +1859,7 @@ double WS2812FX::getPowerEstimate(uint8_t leds, uint32_t c, uint8_t b)
//It is NOT guaranteed to stay within the safeAmps margin. //It is NOT guaranteed to stay within the safeAmps margin.
//Stay safe with high amperage and have a reasonable safety margin! //Stay safe with high amperage and have a reasonable safety margin!
//I am NOT to be held liable for burned down garages! //I am NOT to be held liable for burned down garages!
double WS2812FX::getSafePowerMultiplier(double safeMilliAmps, uint8_t leds, uint32_t c, uint8_t b) double WS2812FX::getSafePowerMultiplier(double safeMilliAmps, byte leds, uint32_t c, byte b)
{ {
double _mARequired = getPowerEstimate(leds,c,b); double _mARequired = getPowerEstimate(leds,c,b);
if (_mARequired > safeMilliAmps) if (_mARequired > safeMilliAmps)
@@ -1864,72 +1869,72 @@ double WS2812FX::getSafePowerMultiplier(double safeMilliAmps, uint8_t leds, uint
return 1.0; return 1.0;
} }
void WS2812FX::setCCIndex1(uint8_t i1) void WS2812FX::setCCIndex1(byte i1)
{ {
if (i1 < _led_count-1) _cc_i1 = i1; if (i1 < _led_count-1) _cc_i1 = i1;
if (_cc_i2 <= i1) _cc_i2 = i1+1; if (_cc_i2 <= i1) _cc_i2 = i1+1;
_counter_cc_step = 0; _counter_ccStep = 0;
} }
void WS2812FX::setCCIndex2(uint8_t i2) void WS2812FX::setCCIndex2(byte i2)
{ {
if (i2 > _cc_i1) _cc_i2 = i2; if (i2 > _cc_i1) _cc_i2 = i2;
if (_cc_i2 >= _led_count) _cc_i2 = _led_count-1; if (_cc_i2 >= _led_count) _cc_i2 = _led_count-1;
_counter_cc_step = 0; _counter_ccStep = 0;
} }
void WS2812FX::setCCStart(uint8_t is) void WS2812FX::setCCStart(byte is)
{ {
_cc_is = (is < _cc_i1 || is > _cc_i2) ? _cc_i1 : is; _cc_is = (is < _cc_i1 || is > _cc_i2) ? _cc_i1 : is;
_counter_cc_step = 0; _counter_ccStep = 0;
} }
void WS2812FX::setCCNum1(uint8_t np) void WS2812FX::setCCNum1(byte np)
{ {
_cc_num1 = np; _cc_num1 = np;
_counter_cc_step = 0; _counter_ccStep = 0;
} }
void WS2812FX::setCCNum2(uint8_t ns) void WS2812FX::setCCNum2(byte ns)
{ {
_cc_num2 = ns; _cc_num2 = ns;
_counter_cc_step = 0; _counter_ccStep = 0;
} }
void WS2812FX::setCCStep(uint8_t stp) void WS2812FX::setCCStep(byte stp)
{ {
_cc_step = stp; _ccStep = stp;
_counter_cc_step = 0; _counter_ccStep = 0;
} }
void WS2812FX::setCCFS(bool fs) void WS2812FX::setCCFS(bool fs)
{ {
_cc_fs = fs; _cc_fs = fs;
_cc_fe = (fs) ? _cc_fe : true; _cc_fe = (fs) ? _cc_fe : true;
_counter_cc_step = 0; _counter_ccStep = 0;
} }
void WS2812FX::setCCFE(bool fe) void WS2812FX::setCCFE(bool fe)
{ {
_cc_fe = fe; _cc_fe = fe;
_cc_fs = (fe) ? _cc_fs : true; _cc_fs = (fe) ? _cc_fs : true;
_counter_cc_step = 0; _counter_ccStep = 0;
} }
void WS2812FX::setCustomChase(uint8_t i1, uint8_t i2, uint8_t is, uint8_t np, uint8_t ns, uint8_t stp, bool fs, bool fe) void WS2812FX::setCustomChase(byte i1, byte i2, byte is, byte np, byte ns, byte stp, bool fs, bool fe)
{ {
setCCIndex1(i1); setCCIndex1(i1);
setCCIndex2(i2); setCCIndex2(i2);
setCCStart(is); setCCStart(is);
_cc_num1 = np; _cc_num1 = np;
_cc_num2 = ns; _cc_num2 = ns;
_cc_step = stp; _ccStep = stp;
setCCFS(fs); setCCFS(fs);
setCCFE(fe); setCCFE(fe);
} }
//Added for quick NeoPixelBus compatibility with Adafruit syntax //Added for quick NeoPixelBus compatibility with Adafruit syntax
void WS2812FX::setPixelColorRaw(uint16_t i, uint8_t r, uint8_t g, uint8_t b, uint8_t w) void WS2812FX::setPixelColorRaw(uint16_t i, byte r, byte g, byte b, byte w)
{ {
#ifdef RGBW #ifdef RGBW
NeoPixelBrightnessBus::SetPixelColor(i, RgbwColor(r,g,b,w)); NeoPixelBrightnessBus::SetPixelColor(i, RgbwColor(r,g,b,w));
@@ -1938,8 +1943,9 @@ void WS2812FX::setPixelColorRaw(uint16_t i, uint8_t r, uint8_t g, uint8_t b, uin
#endif #endif
} }
void WS2812FX::setPixelColor(uint16_t i, uint8_t r, uint8_t g, uint8_t b, uint8_t w) void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
{ {
if (_reverseMode) i = _led_count - 1 -i;
if (!_cronixieMode) if (!_cronixieMode)
{ {
#ifdef RGBW #ifdef RGBW
@@ -1949,13 +1955,13 @@ void WS2812FX::setPixelColor(uint16_t i, uint8_t r, uint8_t g, uint8_t b, uint8_
#endif #endif
} else { } else {
if(i>6)return; if(i>6)return;
uint8_t o = 10*i; byte o = 10*i;
if (_cronixieBacklightEnabled && _cronixieDigits[i] <11) if (_cronixieBacklightEnabled && _cronixieDigits[i] <11)
{ {
uint8_t rCorr = (int)(((double)((_color_sec>>16) & 0xFF))*_cronixieSecMultiplier); byte rCorr = (int)(((double)((_color_sec>>16) & 0xFF))*_cronixieSecMultiplier);
uint8_t gCorr = (int)(((double)((_color_sec>>8) & 0xFF))*_cronixieSecMultiplier); byte gCorr = (int)(((double)((_color_sec>>8) & 0xFF))*_cronixieSecMultiplier);
uint8_t bCorr = (int)(((double)((_color_sec) & 0xFF))*_cronixieSecMultiplier); byte bCorr = (int)(((double)((_color_sec) & 0xFF))*_cronixieSecMultiplier);
uint8_t wCorr = (int)(((double)((_color_sec>>24) & 0xFF))*_cronixieSecMultiplier); byte wCorr = (int)(((double)((_color_sec>>24) & 0xFF))*_cronixieSecMultiplier);
for (int j=o; j< o+19; j++) for (int j=o; j< o+19; j++)
{ {
setPixelColorRaw(j,rCorr,gCorr,bCorr,wCorr); setPixelColorRaw(j,rCorr,gCorr,bCorr,wCorr);
@@ -1984,7 +1990,7 @@ void WS2812FX::setPixelColor(uint16_t i, uint8_t r, uint8_t g, uint8_t b, uint8_
} }
} }
void WS2812FX::setPixelColor(uint16_t i, uint8_t r, uint8_t g, uint8_t b) void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b)
{ {
setPixelColor(i,r,g,b,0); setPixelColor(i,r,g,b,0);
} }
@@ -1999,7 +2005,7 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
if (_cronixieMode) if (_cronixieMode)
{ {
if(i>6)return 0; if(i>6)return 0;
uint8_t o = 10*i; byte o = 10*i;
switch(_cronixieDigits[i]) switch(_cronixieDigits[i])
{ {
case 0: i=o+5; break; case 0: i=o+5; break;
@@ -2024,7 +2030,7 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
#endif #endif
} }
void WS2812FX::setBrightness(uint8_t b) void WS2812FX::setBrightness(byte b)
{ {
_brightness = constrain(b, BRIGHTNESS_MIN, BRIGHTNESS_MAX); _brightness = constrain(b, BRIGHTNESS_MIN, BRIGHTNESS_MAX);
NeoPixelBrightnessBus::SetBrightness(_brightness); NeoPixelBrightnessBus::SetBrightness(_brightness);
@@ -2034,12 +2040,17 @@ void WS2812FX::setBrightness(uint8_t b)
void WS2812FX::show() void WS2812FX::show()
{ {
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
#ifdef WORKAROUND_ESP32_BITBANG
delay(1); delay(1);
portDISABLE_INTERRUPTS(); //this is a workaround to prevent flickering (see https://github.com/adafruit/Adafruit_NeoPixel/issues/139) portDISABLE_INTERRUPTS(); //this is a workaround to prevent flickering (see https://github.com/adafruit/Adafruit_NeoPixel/issues/139)
#endif
#endif
NeoPixelBrightnessBus::Show(); NeoPixelBrightnessBus::Show();
#ifdef ARDUINO_ARCH_ESP32
#ifdef WORKAROUND_ESP32_BITBANG
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
#else #endif
NeoPixelBrightnessBus::Show();
#endif #endif
} }
@@ -2059,13 +2070,13 @@ void WS2812FX::begin()
//For some reason min and max are not declared here //For some reason min and max are not declared here
uint8_t WS2812FX::minval (uint8_t v, uint8_t w) byte WS2812FX::minval (byte v, byte w)
{ {
if (w > v) return v; if (w > v) return v;
return w; return w;
} }
uint8_t WS2812FX::maxval (uint8_t v, uint8_t w) byte WS2812FX::maxval (byte v, byte w)
{ {
if (w > v) return w; if (w > v) return w;
return v; return v;

View File

@@ -1,10 +1,16 @@
//#define RGBW //#define RGBW
#define PIN 2 //strip pin. Only change for ESP32 #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 //automatically uses the right driver method for each platform
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
#ifdef WORKAROUND_ESP32_BITBANG
#define PIXELMETHOD NeoEsp32BitBangWs2813Method #define PIXELMETHOD NeoEsp32BitBangWs2813Method
#else #else
#define PIXELMETHOD NeoEsp32RmtWS2813_V3Method
#endif
#else
#define PIXELMETHOD NeoEsp8266Uart800KbpsMethod #define PIXELMETHOD NeoEsp8266Uart800KbpsMethod
#endif #endif
@@ -208,47 +214,49 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
_cc_i2 = n-1; _cc_i2 = n-1;
_cc_num1 = 5; _cc_num1 = 5;
_cc_num2 = 5; _cc_num2 = 5;
_cc_step = 1; _ccStep = 1;
_counter_mode_call = 0; _counter_mode_call = 0;
_counter_mode_step = 0; _counter_mode_step = 0;
_counter_cc_step = 0; _counter_ccStep = 0;
_fastStandard = false; _fastStandard = false;
_locked = new boolean[n]; _reverseMode = false;
_cronixieDigits = new uint8_t[6]; _locked = new bool[n];
_cronixieDigits = new byte[6];
} }
void void
show(void), show(void),
setPixelColor(uint16_t i, uint8_t r, uint8_t g, uint8_t b), setPixelColor(uint16_t i, byte r, byte g, byte b),
init(void), init(void),
service(void), service(void),
start(void), start(void),
stop(void), stop(void),
setMode(uint8_t m), setMode(byte m),
setCustomChase(uint8_t i1, uint8_t i2, uint8_t is, uint8_t np, uint8_t ns, uint8_t stp, bool fs, bool fe), setCustomChase(byte i1, byte i2, byte is, byte np, byte ns, byte stp, bool fs, bool fe),
setCCIndex1(uint8_t i1), setCCIndex1(byte i1),
setCCIndex2(uint8_t i2), setCCIndex2(byte i2),
setCCStart(uint8_t is), setCCStart(byte is),
setCCNum1(uint8_t np), setCCNum1(byte np),
setCCNum2(uint8_t ns), setCCNum2(byte ns),
setCCStep(uint8_t stp), setCCStep(byte stp),
setCCFS(bool fs), setCCFS(bool fs),
setCCFE(bool fe), setCCFE(bool fe),
setSpeed(uint8_t s), setSpeed(byte s),
setIntensity(uint8_t in), setIntensity(byte in),
increaseSpeed(uint8_t s), increaseSpeed(byte s),
decreaseSpeed(uint8_t s), decreaseSpeed(byte s),
setColor(uint8_t r, uint8_t g, uint8_t b), setColor(byte r, byte g, byte b),
setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w), setColor(byte r, byte g, byte b, byte w),
setColor(uint32_t c), setColor(uint32_t c),
setSecondaryColor(uint8_t r, uint8_t g, uint8_t b), setSecondaryColor(byte r, byte g, byte b),
setSecondaryColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w), setSecondaryColor(byte r, byte g, byte b, byte w),
setSecondaryColor(uint32_t c), setSecondaryColor(uint32_t c),
setBrightness(uint8_t b), setBrightness(byte b),
increaseBrightness(uint8_t s), increaseBrightness(byte s),
decreaseBrightness(uint8_t s), decreaseBrightness(byte s),
setReverseMode(bool b),
driverModeCronixie(bool b), driverModeCronixie(bool b),
setCronixieDigits(uint8_t* d), setCronixieDigits(byte* d),
setCronixieBacklight(bool b), setCronixieBacklight(bool b),
setIndividual(int i), setIndividual(int i),
setIndividual(int i, uint32_t col), setIndividual(int i, uint32_t col),
@@ -265,12 +273,12 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
setLedCount(uint16_t i), setLedCount(uint16_t i),
setFade(int sp); setFade(int sp);
boolean bool
isRunning(void), isRunning(void),
isLocked(int i); isLocked(int i);
uint8_t byte
get_random_wheel_index(uint8_t), get_random_wheel_index(byte),
getMode(void), getMode(void),
getSpeed(void), getSpeed(void),
getIntensity(void), getIntensity(void),
@@ -278,12 +286,12 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
getModeCount(void); getModeCount(void);
uint32_t uint32_t
color_wheel(uint8_t), color_wheel(byte),
getColor(void); getColor(void);
double double
getPowerEstimate(uint8_t leds, uint32_t c, uint8_t b), getPowerEstimate(byte leds, uint32_t c, byte b),
getSafePowerMultiplier(double safeMilliAmps, uint8_t leds, uint32_t c, uint8_t b); getSafePowerMultiplier(double safeMilliAmps, byte leds, uint32_t c, byte b);
private: private:
@@ -291,8 +299,8 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
begin(void), begin(void),
clear(void), clear(void),
setPixelColor(uint16_t i, uint32_t c), setPixelColor(uint16_t i, uint32_t c),
setPixelColor(uint16_t i, uint8_t r, uint8_t g, uint8_t b, uint8_t w), setPixelColor(uint16_t i, byte r, byte g, byte b, byte w),
setPixelColorRaw(uint16_t i, uint8_t r, uint8_t g, uint8_t b, uint8_t w), setPixelColorRaw(uint16_t i, byte r, byte g, byte b, byte w),
dofade(void), dofade(void),
strip_off(void), strip_off(void),
strip_off_respectLock(void), strip_off_respectLock(void),
@@ -357,21 +365,22 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
mode_cc_blink(void), mode_cc_blink(void),
mode_cc_random(void); mode_cc_random(void);
boolean bool
_triggered, _triggered,
_fastStandard, _fastStandard,
_reverseMode,
_cronixieMode, _cronixieMode,
_cronixieBacklightEnabled, _cronixieBacklightEnabled,
_cc_fs, _cc_fs,
_cc_fe, _cc_fe,
_running; _running;
boolean* bool*
_locked; _locked;
uint8_t byte
minval(uint8_t v, uint8_t w), minval(byte v, byte w),
maxval(uint8_t v, uint8_t w), maxval(byte v, byte w),
_mode_index, _mode_index,
_speed, _speed,
_intensity, _intensity,
@@ -380,10 +389,10 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
_cc_is, _cc_is,
_cc_num1, _cc_num1,
_cc_num2, _cc_num2,
_cc_step, _ccStep,
_brightness; _brightness;
uint8_t* byte*
_cronixieDigits; _cronixieDigits;
uint16_t uint16_t
@@ -395,7 +404,7 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
_color_sec, _color_sec,
_counter_mode_call, _counter_mode_call,
_counter_mode_step, _counter_mode_step,
_counter_cc_step, _counter_ccStep,
_mode_color, _mode_color,
_mode_color_sec, _mode_color_sec,
_mode_delay; _mode_delay;

View File

@@ -46,7 +46,7 @@
if (this.readyState == 4) { if (this.readyState == 4) {
if (this.status == 200) { if (this.status == 200) {
if (this.responseXML != null) { if (this.responseXML != null) {
d.Cf.SA.value = this.responseXML.getElementsByTagName('act')[0].childNodes[0].nodeValue; d.Cf.SA.value = this.responseXML.getElementsByTagName('ac')[0].childNodes[0].nodeValue;
d.Cf.SR.value = this.responseXML.getElementsByTagName('cl')[0].childNodes[0].nodeValue; d.Cf.SR.value = this.responseXML.getElementsByTagName('cl')[0].childNodes[0].nodeValue;
d.Cf.SG.value = this.responseXML.getElementsByTagName('cl')[1].childNodes[0].nodeValue; d.Cf.SG.value = this.responseXML.getElementsByTagName('cl')[1].childNodes[0].nodeValue;
d.Cf.SB.value = this.responseXML.getElementsByTagName('cl')[2].childNodes[0].nodeValue; d.Cf.SB.value = this.responseXML.getElementsByTagName('cl')[2].childNodes[0].nodeValue;
@@ -69,7 +69,7 @@
nState = 0; nState = 0;
nState = (this.responseXML.getElementsByTagName('nr')[0].innerHTML)!=0?1:0; nState = (this.responseXML.getElementsByTagName('nr')[0].innerHTML)!=0?1:0;
nState += (this.responseXML.getElementsByTagName('ns')[0].innerHTML)!=0?2:0; nState += (this.responseXML.getElementsByTagName('ns')[0].innerHTML)!=0?2:0;
d.getElementsByClassName("desc")[0].innerHTML = this.responseXML.getElementsByTagName('desc')[0].innerHTML; d.getElementsByClassName("desc")[0].innerHTML = this.responseXML.getElementsByTagName('ds')[0].innerHTML;
UV(); UV();
} }
} }

Binary file not shown.

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

@@ -37,37 +37,37 @@ const char PAGE_settings_wifi1[] PROGMEM = R"=====(
<body onload="GetV()"> <body onload="GetV()">
<form id="form_s" name="Sf" method="post"> <form id="form_s" name="Sf" method="post">
<div class="helpB"><button type="button" onclick="H()">?</button></div> <div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit" name="SUBM">Save & Reboot</button><hr> <button type="button" onclick="B()">Back</button><button type="submit">Save & Reboot</button><hr>
<h2>WiFi setup</h2> <h2>WiFi setup</h2>
<h3>Connect to existing network</h3> <h3>Connect to existing network</h3>
Network name (SSID, empty to not connect): <br><input name="CSSID" maxlength="32"> <br> Network name (SSID, empty to not connect): <br><input name="CS" maxlength="32"><br>
Network password: <br> <input type="password" name="CPASS" maxlength="63"> <br> Network password: <br> <input type="password" name="CP" maxlength="63"><br>
Static IP (leave at 0.0.0.0 for DHCP): <br> Static IP (leave at 0.0.0.0 for DHCP):<br>
<input name="CSIP0" type="number" min="0" max="255" required> . <input name="I0" type="number" min="0" max="255" required> .
<input name="CSIP1" type="number" min="0" max="255" required> . <input name="I1" type="number" min="0" max="255" required> .
<input name="CSIP2" type="number" min="0" max="255" required> . <input name="I2" type="number" min="0" max="255" required> .
<input name="CSIP3" type="number" min="0" max="255" required> <br> <input name="I3" type="number" min="0" max="255" required><br>
Static gateway: <br> Static gateway:<br>
<input name="CSGW0" type="number" min="0" max="255" required> . <input name="G0" type="number" min="0" max="255" required> .
<input name="CSGW1" type="number" min="0" max="255" required> . <input name="G1" type="number" min="0" max="255" required> .
<input name="CSGW2" type="number" min="0" max="255" required> . <input name="G2" type="number" min="0" max="255" required> .
<input name="CSGW3" type="number" min="0" max="255" required> <br> <input name="G3" type="number" min="0" max="255" required><br>
Static subnet mask: <br> Static subnet mask:<br>
<input name="CSSN0" type="number" min="0" max="255" required> . <input name="S0" type="number" min="0" max="255" required> .
<input name="CSSN1" type="number" min="0" max="255" required> . <input name="S1" type="number" min="0" max="255" required> .
<input name="CSSN2" type="number" min="0" max="255" required> . <input name="S2" type="number" min="0" max="255" required> .
<input name="CSSN3" type="number" min="0" max="255" required> <br> <input name="S3" type="number" min="0" max="255" required><br>
mDNS address (leave empty for no mDNS): <br/> mDNS address (leave empty for no mDNS):<br/>
http:// <input name="CMDNS" maxlength="32"> .local <br> http:// <input name="CM" maxlength="32"> .local<br>
Try connecting before opening AP for: <input name="APWTM" type="number" min="0" max="255" required> s <br> Try connecting before opening AP for: <input name="AT" type="number" min="0" max="255" required> s <br>
Client IP: <span class="sip"> Not connected </span> <br> Client IP: <span class="sip"> Not connected </span><br>
<h3>Configure Access Point</h3> <h3>Configure Access Point</h3>
AP SSID (leave empty for no AP): <br> <input name="APSSID" maxlength="32"> <br> AP SSID (leave empty for no AP):<br> <input name="AS" maxlength="32"><br>
Hide AP name: <input type="checkbox" name="APHSSID"> <br> Hide AP name: <input type="checkbox" name="AH"><br>
AP password (leave empty for open): <br> <input type="password" name="APPASS" maxlength="63"> <br> AP password (leave empty for open):<br> <input type="password" name="AP" maxlength="63"> <br>
Access Point WiFi channel: <input name="APCHAN" type="number" min="1" max="13" required> <br> Access Point WiFi channel: <input name="AC" type="number" min="1" max="13" required><br>
AP IP: <span class="sip"> Not active </span> <hr> AP IP: <span class="sip"> Not active </span><hr>
<button type="button" onclick="B()">Back</button><button type="submit" name="SUBM">Save & Reboot</button> <button type="button" onclick="B()">Back</button><button type="submit">Save & Reboot</button>
</form> </form>
</body> </body>
</html> </html>
@@ -83,46 +83,46 @@ const char PAGE_settings_leds1[] PROGMEM = R"=====(
<body onload="GetV()"> <body onload="GetV()">
<form id="form_s" name="Sf" method="post"> <form id="form_s" name="Sf" method="post">
<div class="helpB"><button type="button" onclick="H()">?</button></div> <div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit" name="SUBM">Save</button><hr> <button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
<h2>LED setup</h2> <h2>LED setup</h2>
LED count (max. 255): <input name="LEDCN" type="number" min="1" max="255" required> <br> 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> <i>The default boot color is always saved in preset slot 0.</i><br>
Alternatively, apply preset <input name="BOOTP" type="number" min="0" max="25" required> at boot<br> Alternatively, apply preset <input name="BP" type="number" min="0" max="25" required> at boot<br>
Default RGB color: Default RGB color:
<input name="CLDFR" type="number" min="0" max="255" required> <input name="CR" type="number" min="0" max="255" required>
<input name="CLDFG" type="number" min="0" max="255" required> <input name="CG" type="number" min="0" max="255" required>
<input name="CLDFB" type="number" min="0" max="255" required> <br> <input name="CB" type="number" min="0" max="255" required><br>
Default brightness: <input name="CLDFA" type="number" min="0" max="255" required> (0-255) <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="CLDFW" type="number" min="-1" max="255" required> <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="FXDEF" type="number" min="0" max="57" required> <br> Default effect ID: <input name="FX" type="number" min="0" max="57" required> <br>
Default effect speed: <input name="SXDEF" type="number" min="0" max="255" required> <br> Default effect speed: <input name="SX" type="number" min="0" max="255" required> <br>
Default effect intensity: <input name="IXDEF" 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> Default secondary RGB(W):<br>
<input name="CSECR" type="number" min="0" max="255" required> <input name="SR" type="number" min="0" max="255" required>
<input name="CSECG" type="number" min="0" max="255" required> <input name="SG" type="number" min="0" max="255" required>
<input name="CSECB" type="number" min="0" max="255" required> <input name="SB" type="number" min="0" max="255" required>
<input name="CSECW" type="number" min="0" max="255" required><br> <input name="SW" type="number" min="0" max="255" required><br>
Ignore and use current color, brightness and effects: <input type="checkbox" name="CBEOR"> <br> Ignore and use current color, brightness and effects: <input type="checkbox" name="IS"><br>
Turn on after power up/reset: <input type="checkbox" name="BOOTN"> <br> Turn on after power up/reset: <input type="checkbox" name="BO"><br>
Use Gamma correction for brightness: <input type="checkbox" name="GCBRI"> <br> Use Gamma correction for brightness: <input type="checkbox" name="GB"><br>
Use Gamma correction for color: <input type="checkbox" name="GCRGB"> <br> Use Gamma correction for color: <input type="checkbox" name="GC"><br>
Brightness factor: <input name="NRBRI" type="number" min="0" max="255" required> % Brightness factor: <input name="BF" type="number" min="0" max="255" required> %
<h3>Transitions</h3> <h3>Transitions</h3>
Fade: <input type="checkbox" name="TFADE"><br> Fade: <input type="checkbox" name="TF"><br>
Sweep: <input type="checkbox" name="TSWEE"> Invert direction: <input type="checkbox" name="TSDIR"><br> Sweep: <input type="checkbox" name="TS"> Invert direction: <input type="checkbox" name="TI"><br>
Transition Delay: <input name="TDLAY" maxlength="5" size="2"> ms Transition Delay: <input name="TD" maxlength="5" size="2"> ms
<h3>Timed light</h3> <h3>Timed light</h3>
Default Duration: <input name="TLDUR" type="number" min="1" max="255" required> min<br> Default Duration: <input name="TL" type="number" min="1" max="255" required> min<br>
Default Target brightness: <input name="TLBRI" type="number" min="0" max="255" required><br> Default Target brightness: <input name="TB" type="number" min="0" max="255" required><br>
Fade down: <input type="checkbox" name="TLFDE"><br> Fade down: <input type="checkbox" name="TW"><br>
<h3>Advanced</h3> <h3>Advanced</h3>
Default overlay ID: <input name="OLDEF" type="number" min="0" max="255" required> <br> Reverse LED order (rotate 180): <input type="checkbox" name="RV"><br>
WARLS offset: <input name="WOFFS" type="number" min="-255" max="255" required><hr> Init LEDs after WiFi: <input type="checkbox" name="EI"><br>
<button type="button" onclick="B()">Back</button><button type="submit" name="SUBM">Save</button> WARLS offset: <input name="WO" type="number" min="-255" max="255" required><hr>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
</form> </form>
</body> </body>
</html> </html>
)====="; )=====";
const char PAGE_settings_ui0[] PROGMEM = R"=====( const char PAGE_settings_ui0[] PROGMEM = R"=====(
@@ -137,12 +137,12 @@ const char PAGE_settings_ui1[] PROGMEM = R"=====(
<body onload="S()"> <body onload="S()">
<form id="form_s" name="Sf" method="post"> <form id="form_s" name="Sf" method="post">
<div class="helpB"><button type="button" onclick="H()">?</button></div> <div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit" name="SUBM">Save</button><hr> <button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
<h2>Web Setup</h2> <h2>Web Setup</h2>
Server description: <input name="DESC" maxlength="32"><br> Server description: <input name="DS" maxlength="32"><br>
Use HSB sliders instead of RGB by default: <input type="checkbox" name="COLMD"><br> Use HSB sliders instead of RGB by default: <input type="checkbox" name="MD"><br>
Color Theme: Color Theme:
<select name="THEME" onchange="Ct()"> <select name="TH" onchange="Ct()">
<option value="0" selected>Night</option> <option value="0" selected>Night</option>
<option value="1">Modern</option> <option value="1">Modern</option>
<option value="2">Bright</option> <option value="2">Bright</option>
@@ -154,7 +154,7 @@ Color Theme:
<option value="8">Air</option> <option value="8">Air</option>
<option value="9">Nixie</option> <option value="9">Nixie</option>
<option value="10">Terminal</option> <option value="10">Terminal</option>
<option value="11">Placeholder</option> <option value="11">C64</option>
<option value="12">Placeholder</option> <option value="12">Placeholder</option>
<option value="13">Placeholder</option> <option value="13">Placeholder</option>
<option value="14">The End</option> <option value="14">The End</option>
@@ -162,15 +162,15 @@ Color Theme:
</select><br> </select><br>
<div id="cth"> <div id="cth">
Please specify your custom hex colors (e.g. FF0000 for red)<br> Please specify your custom hex colors (e.g. FF0000 for red)<br>
Custom accent color: <input maxlength=9 name="CCOL0"><br> Custom accent color: <input maxlength=9 name="C0"><br>
Custom background: <input maxlength=9 name="CCOL1"><br> Custom background: <input maxlength=9 name="C1"><br>
Custom panel color: <input maxlength=9 name="CCOL2"><br> Custom panel color: <input maxlength=9 name="C2"><br>
Custom icon color: <input maxlength=9 name="CCOL3"><br> Custom icon color: <input maxlength=9 name="C3"><br>
Custom shadow: <input maxlength=9 name="CCOL4"><br> Custom shadow: <input maxlength=9 name="C4"><br>
Custom text color: <input maxlength=9 name="CCOL5"><br></div> Custom text color: <input maxlength=9 name="C5"><br></div>
Use font: <input maxlength=32 name="CFONT"><br> Use font: <input maxlength=32 name="CF"><br>
Make sure the font you use is installed on your system!<br> Make sure the font you use is installed on your system!<br>
<hr><button type="button" onclick="B()">Back</button><button type="submit" name="SUBM">Save</button> <hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button>
</form> </form>
</body> </body>
</html> </html>
@@ -186,39 +186,34 @@ const char PAGE_settings_sync1[] PROGMEM = R"=====(
<body onload="GetV()"> <body onload="GetV()">
<form id="form_s" name="Sf" method="post"> <form id="form_s" name="Sf" method="post">
<div class="helpB"><button type="button" onclick="H()">?</button></div> <div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit" name="SUBM">Save</button><hr> <button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
<h2>Sync setup</h2> <h2>Sync setup</h2>
<h3>Button setup</h3> <h3>Button setup</h3>
On/Off button enabled: <input type="checkbox" name="BTNON"> On/Off button enabled: <input type="checkbox" name="BT">
<h3>WLED Broadcast</h3> <h3>WLED Broadcast</h3>
UDP Port: <input name="NUDPP" maxlength="5" size="4"><br> UDP Port: <input name="UP" maxlength="5" size="4"><br>
Receive <input type="checkbox" name="NRCBR">Brightness, <input type="checkbox" name="NRCCL">Color, and <input type="checkbox" name="NRCFX">Effects<br> Receive <input type="checkbox" name="RB">Brightness, <input type="checkbox" name="RC">Color, and <input type="checkbox" name="RX">Effects<br>
Send notifications on direct change: <input type="checkbox" name="NSDIR"> <br> Send notifications on direct change: <input type="checkbox" name="SD"><br>
Send notifications on button press: <input type="checkbox" name="NSBTN"> <br> Send notifications on button press: <input type="checkbox" name="SB"><br>
Send Alexa notifications: <input type="checkbox" name="NSALX"> <br> Send Alexa notifications: <input type="checkbox" name="SA"><br>
<!--Send Philips Hue change notifications: <input type="checkbox" name="NSHUE">--> Send Philips Hue change notifications: <input type="checkbox" name="SH"><br>
Send notifications twice: <input type="checkbox" name="S2">
<h3>Alexa Voice Assistant</h3> <h3>Alexa Voice Assistant</h3>
Emulate Alexa device: <input type="checkbox" name="ALEXA"> <br> Emulate Alexa device: <input type="checkbox" name="AL"><br>
Alexa invocation name: <input name="AINVN" maxlength="32"><br> Alexa invocation name: <input name="AI" maxlength="32"><br>
<h3>Philips Hue</h3> <h3>Philips Hue</h3>
Coming soon! Not yet implemented! <i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
<!--<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
Hue Bridge IP:<br> Hue Bridge IP:<br>
<input name="HUIP0" type="number" min="0" max="255" required> . <input name="H0" type="number" min="0" max="255" required> .
<input name="HUIP1" type="number" min="0" max="255" required> . <input name="H1" type="number" min="0" max="255" required> .
<input name="HUIP2" type="number" min="0" max="255" required> . <input name="H2" type="number" min="0" max="255" required> .
<input name="HUIP3" type="number" min="0" max="255" required> <br> <input name="H3" type="number" min="0" max="255" required><br>
<b>For successful pairing, press the pushlink button on the bridge, then save this page!</b><br> <b>Press the pushlink button on the bridge, after that save this page!</b><br>
(when first connecting)<br> (when first connecting)<br>
<i> Use 0 for group and light to turn off sending/receiving </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>
Update Hue group <input name="HUEGR" type="number" min="0" max="99" required> <br> Then, receive <input type="checkbox" name="HO"> On/Off, <input type="checkbox" name="HB"> Brightness, and <input type="checkbox" name="HC"> Color<br>
Send <input type="checkbox" name="HUEIO"> On/Off, <input type="checkbox" name="HUEBR"> Brightness, and <input type="checkbox" name="HUECL"> Color<br> Hue status: <span class="hms"> Internal ESP Error! </span><hr>
Poll Hue light <input name="HUELI" type="number" min="0" max="99" required> every <input name="HUEPL" type="number" min="100" max="62000" required> ms<br> <button type="button" onclick="B()">Back</button><button type="submit">Save</button>
Then, receive <input type="checkbox" name="HURIO"> On/Off, <input type="checkbox" name="HURBR"> Brightness, and <input type="checkbox" name="HURCL"> Color<br>
After device color update, ignore Hue updates for <input name="HUELI" type="number" min="0" max="255" required> minutes<br>
Hue status: <span class="hms"> Internal ESP error! </span>-->
<hr>
<button type="button" onclick="B()">Back</button><button type="submit" name="SUBM">Save</button>
</form> </form>
</body> </body>
</html> </html>
@@ -227,77 +222,84 @@ Hue status: <span class="hms"> Internal ESP error! </span>-->
const char PAGE_settings_time0[] PROGMEM = R"=====( const char PAGE_settings_time0[] PROGMEM = R"=====(
<!DOCTYPE html> <!DOCTYPE html>
<html><head><title>Time Settings</title> <html><head><title>Time Settings</title>
<script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#time-settings");}function B(){window.open("/settings","_self");}function GetV(){var d = document; <script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#time-settings");}function B(){window.open("/settings","_self");}function S(){GetV();Cs();}function gId(s){return document.getElementById(s);}function Cs(){gId("cac").style.display="none";gId("coc").style.display="block";gId("ccc").style.display="none";if (gId("ca").selected){gId("cac").style.display="block";}if (gId("cc").selected){gId("coc").style.display="none";gId("ccc").style.display="block";}if (gId("cn").selected){gId("coc").style.display="none";}}function GetV(){var d = document;
)====="; )=====";
const char PAGE_settings_time1[] PROGMEM = R"=====( const char PAGE_settings_time1[] PROGMEM = R"=====(
</head> </head>
<body onload="GetV()"> <body onload="S()">
<form id="form_s" name="Sf" method="post"> <form id="form_s" name="Sf" method="post">
<div class="helpB"><button type="button" onclick="H()">?</button></div> <div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit" name="SUBM">Save</button><hr> <button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
<h2>Time setup</h2> <h2>Time setup</h2>
Get time from NTP server: <input type="checkbox" name="NTPON"><br> Get time from NTP server: <input type="checkbox" name="NT"><br>
<!--NTP server: <input name="NTPSR" maxlength="32"><br> Use 24h format: <input type="checkbox" name="CF"><br>
Time zone: Time zone:
<select name="TZONE"> <select name="TZ">
<option value="1" selected>GMT(UTC)</option> <option value="0" selected>GMT(UTC)</option>
<option value="2">GMT/BST</option> <option value="1">GMT/BST</option>
<option value="3">CET/CEST</option> <option value="2">CET/CEST</option>
<option value="4">EET/EEST</option> <option value="3">EET/EEST</option>
<option value="5">US-EST/EDT</option> <option value="4">US-EST/EDT</option>
<option value="6">US-CST/CDT</option> <option value="5">US-CST/CDT</option>
<option value="7">US-MST/MDT</option> <option value="6">US-MST/MDT</option>
<option value="8">US-AZ</option> <option value="7">US-AZ</option>
<option value="9">US-PST/PDT</option> <option value="8">US-PST/PDT</option>
<option value="10">CST(AWST)</option> <option value="9">CST(AWST)</option>
<option value="11">JST(KST)</option> <option value="10">JST(KST)</option>
<option value="12">AEST/AEDT</option> <option value="11">AEST/AEDT</option>
<option value="13">NZST/NZDT</option> <option value="12">NZST/NZDT</option>
</select><br> </select><br>
Hour/Min offset: <input name="TOFSH" type="number" min="-255" max="255" required> <input name="TOFSM" type="number" min="-255" max="255" required><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>. Current local time is <span class="times">unknown</span>.
<h3>Weather</h3> <h3>Clock</h3>
Coming soon! Not yet implemented! Clock Overlay:
<!--Get yours on open weather API.<br> <select name="OL" onchange="Cs()">
City code: <input name="WCITY" maxlength="32"><br> <option value="0" id="cn" selected>None</option>
Change color depending on weather: <input type="checkbox" name="WCCOL"><br> <option value="1">Static color</option>
Daylight Emulation: <input type="checkbox" name="WDAYL"><br> <option value="2" id="ca">Analog Clock</option>
Reverse (turns on at sunset): <input type="checkbox" name="WREVL"><br> <option value="3">Single Digit Clock</option>
Fade duration: <input name="WSDUR" type="number" min="0" max="255" required><br> <option value="4" id="cc">Cronixie Clock</option>
Sunrise/Sunset Offset: <input name="WSOFS" type="number" min="-255" max="255" required>--> </select><br>
<div id="coc">
First LED: <input name="O1" type="number" min="0" max="255" required> Last LED: <input name="O2" type="number" min="0" max="255" required><br>
<div id="cac">
12h LED: <input name="OM" type="number" min="0" max="255" required><br>
Show 5min marks: <input type="checkbox" name="O5"><br></div>
Seconds (as trail): <input type="checkbox" name="OS"><br>
</div>
<div id="ccc">
Cronixie Display: <input name="CX" maxlength="6"><br>
Cronixie Backlight: <input type="checkbox" name="CB"><br>
</div>
Countdown Mode: <input type="checkbox" name="CE"><br>
Countdown Goal: Year: 20 <input name="CY" type="number" min="0" max="99" required> Month: <input name="CI" type="number" min="1" max="12" required> Day: <input name="CD" type="number" min="1" max="31" required><br>
Hour: <input name="CH" type="number" min="0" max="23" required> Minute: <input name="CM" type="number" min="0" max="59" required> Second: <input name="CS" type="number" min="0" max="59" required><br>
<h3>Advanced Macros</h3> <h3>Advanced Macros</h3>
Coming soon! Not yet implemented! Define API macros here:<br>
<!--Define API macros here:<br> 1: <input name="M1" maxlength="64"><br>
0: <input name="MCR00" maxlength="64"><br> 2: <input name="M2" maxlength="64"><br>
1: <input name="MCR01" maxlength="64"><br> 3: <input name="M3" maxlength="64"><br>
2: <input name="MCR02" maxlength="64"><br> 4: <input name="M4" maxlength="64"><br>
3: <input name="MCR03" maxlength="64"><br> 5: <input name="M5" maxlength="64"><br>
4: <input name="MCR04" maxlength="64"><br> 6: <input name="M6" maxlength="64"><br>
5: <input name="MCR05" maxlength="64"><br> 7: <input name="M7" maxlength="64"><br>
6: <input name="MCR06" maxlength="64"><br> 8: <input name="M8" maxlength="64"><br>
7: <input name="MCR07" maxlength="64"><br> 9: <input name="M9" maxlength="64"><br>
8: <input name="MCR08" maxlength="64"><br> 10: <input name="M10" maxlength="64"><br>
9: <input name="MCR09" maxlength="64"><br> 11: <input name="M11" maxlength="64"><br>
10: <input name="MCR10" maxlength="64"><br> 12: <input name="M12" maxlength="64"><br>
11: <input name="MCR11" maxlength="64"><br> 13: <input name="M13" maxlength="64"><br>
12: <input name="MCR12" maxlength="64"><br> 14: <input name="M14" maxlength="64"><br>
13: <input name="MCR13" maxlength="64"><br> 15: <input name="M15" maxlength="64"><br>
14: <input name="MCR14" maxlength="64"><br> 16: <input name="M16" maxlength="64"><br><br>
15: <input name="MCR15" maxlength="64"><br> <i>Use 0 for the default action instead of a macro</i><br>
<br> Time controlled macros coming soon!<br>
<i>Use -1 to use the default action instead of a macro</i><br> Boot Macro: <input name="MB" type="number" min="0" max="16" required><br>
<--1st Time-Controlled Macro: Alexa On/Off Macros: <input name="A0" type="number" min="0" max="16" required> <input name="A1" type="number" min="0" max="16" required><br>
Alexa On/Off Macros: <input name="MCA0I" type="number" min="-1" max="15" required> <input name="MCA0O" type="number" min="-1" max="15" required><br> Button Macro: <input name="MP" type="number" min="0" max="16" required> Long Press: <input name="ML" type="number" min="0" max="16" required><br>
<--Emulate 2nd Alexa device: Countdown-Over Macro: <input name="MC" type="number" min="0" max="16" required><br>
Timed-Light-Over Macro: <input name="MN" type="number" min="0" max="16" required><hr>
Emulate 3rd Alexa device: <button type="button" onclick="B()">Back</button><button type="submit">Save</button>
Button Macro: <input name="MCBT0" type="number" min="-1" max="15" required><br>
Button Long Press Macro: <input name="MCBT1" type="number" min="-1" max="15" required><br>
<--Sunrise Macro
Sunset Macro
Countdown-Over Macro: <input name="MCNTD" type="number" min="-1" max="15" required><br>-->
<hr>
<button type="button" onclick="B()">Back</button><button type="submit" name="SUBM">Save</button>
</form> </form>
</body> </body>
</html> </html>
@@ -314,26 +316,26 @@ const char PAGE_settings_sec1[] PROGMEM = R"=====(
<body onload="GetV()"> <body onload="GetV()">
<form id="form_s" name="Sf" method="post"> <form id="form_s" name="Sf" method="post">
<div class="helpB"><button type="button" onclick="H()">?</button></div> <div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit" name="SUBM">Save & Reboot</button><hr> <button type="button" onclick="B()">Back</button><button type="submit">Save & Reboot</button><hr>
<h2>Security & Update setup</h2> <h2>Security & Update setup</h2>
Enable OTA lock: <input type="checkbox" name="NOOTA"><br> Enable OTA lock: <input type="checkbox" name="NO"><br>
Passphrase: <input type="password" name="OPASS" maxlength="32"><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> To enable OTA, for security reasons you need to also enter the correct password!<br>
The password may/should be changed when OTA is enabled.<br> The password should be changed when OTA is enabled.<br>
<b>Disable OTA when not in use, otherwise an attacker could reflash device software!</b><br> <b>Disable OTA when not in use, otherwise an attacker can reflash device software!</b><br>
<i>Settings on this page are only changable if OTA lock is disabled!</i><br> <i>Settings on this page are only changable if OTA lock is disabled!</i><br>
Deny access to WiFi settings if locked: <input type="checkbox" name="OWIFI"><br><br> Deny access to WiFi settings if locked: <input type="checkbox" name="OW"><br><br>
Disable recovery AP: <input type="checkbox" name="NORAP"><br> Disable recovery AP: <input type="checkbox" name="NA"><br>
In case of a connection error there will be no wireless recovery possible!<br> In case of an error there will be no wireless recovery possible!<br>
Completely disables all Access Point functions.<br><br> Completely disables all Access Point functions.<br><br>
Factory reset: <input type="checkbox" name="RESET"><br> Factory reset: <input type="checkbox" name="RS"><br>
All EEPROM content (settings) will be erased.<br><br> All EEPROM content (settings) will be erased.<br><br>
HTTP traffic is not encrypted. An attacker in the same network could intercept form data! HTTP traffic is unencrypted. An attacker in the same network can intercept form data!
<h3>Software Update</h3> <h3>Software Update</h3>
<button type="button" onclick="U()">Manual OTA Update</button><br> <button type="button" onclick="U()">Manual OTA Update</button><br>
Enable ArduinoOTA: <input type="checkbox" name="AROTA"><br> Enable ArduinoOTA: <input type="checkbox" name="AO"><br>
<h3>About</h3> <h3>About</h3>
<a href="https://github.com/Aircoookie/WLED">WLED</a> version 0.5.0<br> <a href="https://github.com/Aircoookie/WLED">WLED</a> version 0.6.0<br>
(c) 2016-2018 Christian Schwinne <br> (c) 2016-2018 Christian Schwinne <br>
<i>Licensed under the MIT license</i><br><br> <i>Licensed under the MIT license</i><br><br>
<i>Uses libraries:</i><br> <i>Uses libraries:</i><br>
@@ -344,7 +346,7 @@ Enable ArduinoOTA: <input type="checkbox" name="AROTA"><br>
<i><a href="https://github.com/Aircoookie/Espalexa">Espalexa</a> by Aircoookie (modified)</i><br><br> <i><a href="https://github.com/Aircoookie/Espalexa">Espalexa</a> by Aircoookie (modified)</i><br><br>
<i>UI icons by <a href="https://linearicons.com">Linearicons</a> created by <a href="https://perxis.com">Perxis</a>! (CC-BY-SA 4.0)</i> <br><br> <i>UI icons by <a href="https://linearicons.com">Linearicons</a> created by <a href="https://perxis.com">Perxis</a>! (CC-BY-SA 4.0)</i> <br><br>
Server message: <span class="msg"> Response error! </span><hr> Server message: <span class="msg"> Response error! </span><hr>
<button type="button" onclick="B()">Back</button><button type="submit" name="SUBM">Save & Reboot</button> <button type="button" onclick="B()">Back</button><button type="submit">Save & Reboot</button>
</form> </form>
</body> </body>
</html> </html>

View File

@@ -281,9 +281,9 @@ void setTime(time_t t) {
nextSyncTime = (uint32_t)t + syncInterval; nextSyncTime = (uint32_t)t + syncInterval;
Status = timeSet; Status = timeSet;
prevMillis = millis(); // restart counting from now (thanks to Korman for this fix) prevMillis = millis(); // restart counting from now (thanks to Korman for this fix)
} }
void setTime(int hr,int min,int sec,int dy, int mnth, int yr){ time_t getUnixTime(int hr,int min,int sec,int dy, int mnth, int yr){
// year can be given as full four digit year or two digts (2010 or 10 for 2010); // year can be given as full four digit year or two digts (2010 or 10 for 2010);
//it is converted to years since 1970 //it is converted to years since 1970
if( yr > 99) if( yr > 99)
@@ -296,7 +296,11 @@ void setTime(int hr,int min,int sec,int dy, int mnth, int yr){
tm.Hour = hr; tm.Hour = hr;
tm.Minute = min; tm.Minute = min;
tm.Second = sec; tm.Second = sec;
setTime(makeTime(tm)); return makeTime(tm);
}
void setTime(int hr,int min,int sec,int dy, int mnth, int yr){
setTime(getUnixTime(hr,min,sec,dy,mnth,yr));
} }
void adjustTime(long adjustment) { void adjustTime(long adjustment) {

View File

@@ -120,6 +120,7 @@ int year(time_t t); // the year for the given time
time_t now(); // return the current time as seconds since Jan 1 1970 time_t now(); // return the current time as seconds since Jan 1 1970
void setTime(time_t t); void setTime(time_t t);
void setTime(int hr,int min,int sec,int day, int month, int yr); void setTime(int hr,int min,int sec,int day, int month, int yr);
time_t getUnixTime(int hr,int min,int sec,int day, int month, int yr); //added by Aircoookie to get epoch time
void adjustTime(long adjustment); void adjustTime(long adjustment);
/* date strings */ /* date strings */

View File

@@ -27,12 +27,11 @@ enum month_t {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};
//or when standard time begins. //or when standard time begins.
struct TimeChangeRule struct TimeChangeRule
{ {
char abbrev[6]; //five chars max
uint8_t week; //First, Second, Third, Fourth, or Last week of the month uint8_t week; //First, Second, Third, Fourth, or Last week of the month
uint8_t dow; //day of week, 1=Sun, 2=Mon, ... 7=Sat uint8_t dow; //day of week, 1=Sun, 2=Mon, ... 7=Sat
uint8_t month; //1=Jan, 2=Feb, ... 12=Dec uint8_t month; //1=Jan, 2=Feb, ... 12=Dec
uint8_t hour; //0-23 uint8_t hour; //0-23
int offset; //offset from UTC in minutes int16_t offset; //offset from UTC in minutes
}; };
class Timezone class Timezone

View File

@@ -15,7 +15,7 @@ const char* ESP8266HTTPUpdateServer::_serverIndex =
R"(<html><head><script>function B(){window.history.back()}</script></head><body><h2>WLED Software Update</h2><br>Get the latest binaries on the <a href="https://github.com/Aircoookie/WLED/tree/master/bin">project GitHub page</a>!<br> R"(<html><head><script>function B(){window.history.back()}</script></head><body><h2>WLED Software Update</h2><br>Get the latest binaries on the <a href="https://github.com/Aircoookie/WLED/tree/master/bin">project GitHub page</a>!<br>
<i>Unsure which binary is correct? Go to the <a href="./build">/build subpage</a> for the details of this version.</i><br> <i>Unsure which binary is correct? Go to the <a href="./build">/build subpage</a> for the details of this version.</i><br>
<b>Be sure to upload a valid .bin file for your ESP! Otherwise you'll need USB recovery!</b><br> <b>Be sure to upload a valid .bin file for your ESP! Otherwise you'll need USB recovery!</b><br>
<br><br><button onclick="B()\">Back</button><br><br> <br><br><button onclick='B()'>Back</button><br><br>
<form method='POST' action='' enctype='multipart/form-data'> <form method='POST' action='' enctype='multipart/form-data'>
<input type='file' name='update'> <input type='file' name='update'>
<input type='submit' value='Update!'> <input type='submit' value='Update!'>

View File

@@ -3,7 +3,7 @@
*/ */
/* /*
* @title WLED project sketch * @title WLED project sketch
* @version 0.5.0 * @version 0.6.0
* @author Christian Schwinne * @author Christian Schwinne
*/ */
@@ -12,14 +12,17 @@
#include <WiFi.h> #include <WiFi.h>
#include <ESPmDNS.h> #include <ESPmDNS.h>
#include "src/dependencies/webserver/WebServer.h" #include "src/dependencies/webserver/WebServer.h"
#include <HTTPClient.h>
#else #else
#include <ESP8266WiFi.h> #include <ESP8266WiFi.h>
#include <ESP8266mDNS.h> #include <ESP8266mDNS.h>
#include <ESP8266WebServer.h> #include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#endif #endif
#include <EEPROM.h> #include <EEPROM.h>
#include <ArduinoOTA.h> #include <ArduinoOTA.h>
#include <WiFiUDP.h> #include <WiFiUDP.h>
#include <DNSServer.h>
#include "src/dependencies/webserver/ESP8266HTTPUpdateServer.h" #include "src/dependencies/webserver/ESP8266HTTPUpdateServer.h"
#include "src/dependencies/time/Time.h" #include "src/dependencies/time/Time.h"
#include "src/dependencies/time/TimeLib.h" #include "src/dependencies/time/TimeLib.h"
@@ -30,203 +33,191 @@
#include "WS2812FX.h" #include "WS2812FX.h"
//version in format yymmddb (b = daily build) //version in format yymmddb (b = daily build)
#define VERSION 1802222 #define VERSION 1803151
const String versionString = "0.5.0"; const String versionString = "0.6.0";
//AP and OTA default passwords (change them!) //AP and OTA default passwords (change them!)
String appass = "wled1234"; String apPass = "wled1234";
String otapass = "wledota"; String otaPass = "wledota";
//If you have an RGBW strip, also uncomment first line in WS2812FX.h! //If you have an RGBW strip, also uncomment first line in WS2812FX.h!
bool useRGBW = false; bool useRGBW = false;
//overlays, needed for clocks etc.
#define USEOVERLAYS
//support for the CRONIXIE clock by Diamex (disable overlays!)
//#define CRONIXIE
//spiffs FS only useful for debug (only ESP8266) //spiffs FS only useful for debug (only ESP8266)
//#define USEFS //#define USEFS
//to toggle usb serial debug (un)comment following line //to toggle usb serial debug (un)comment following line(s)
//#define DEBUG //#define DEBUG
//Hardware-settings (only changeble via code) //Hardware-settings (only changeble via code)
#define LEDCOUNT 255 //maximum, exact count set-able via settings #define LEDCOUNT 255 //maximum, exact count set-able via settings
uint8_t buttonPin = 0; //needs pull-up byte buttonPin = 0; //needs pull-up
uint8_t auxPin = 15; //use e.g. for external relay byte auxPin = 15; //use e.g. for external relay
uint8_t auxDefaultState = 0; //0: input 1: high 2: low byte auxDefaultState = 0; //0: input 1: high 2: low
uint8_t auxTriggeredState = 0; //0: input 1: high 2: low byte auxTriggeredState = 0; //0: input 1: high 2: low
TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; //Central European Summer Time
TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; //Central European Standard Time
Timezone TZ(CEST, CET);
TimeChangeRule *tcr; //pointer to the time change rule, use to get the TZ abbrev
time_t local;
//cronixie defaults
#ifdef CRONIXIE
#undef LEDCOUNT
#define LEDCOUNT 60
uint8_t ledcount = 6;
String apssid = "CRONIXIE-AP";
String alexaInvocationName = "Clock";
char cronixieDefault[] = "HHMMSS";
long cronixieRefreshMs = 497;
unsigned long cronixieRefreshedTime;
byte dP[]{0,0,0,0,0,0};
bool cronixieUseAMPM = false;
bool cronixieBacklight = true;
bool cronixieCountdown = false;
bool ntpEnabled = true;
#endif
//Default CONFIG //Default CONFIG
String serverDescription = versionString; String serverDescription = versionString;
uint8_t currentTheme = 0; byte currentTheme = 0;
String clientssid = "Your_Network_Here"; String clientSSID = "Your_Network";
String clientpass = "Dummy_Pass"; String clientPass = "";
String cmdns = "led"; String cmDNS = "led";
#ifndef CRONIXIE byte ledCount = 10; //lowered to prevent accidental overcurrent
uint8_t ledcount = 100; String apSSID = ""; //AP off by default (unless setup)
String apssid = "WLED-AP"; byte apChannel = 1;
#endif byte apHide = 0;
uint8_t apchannel = 1; byte apWaitTimeSecs = 32;
uint8_t aphide = 0; bool recoveryAPDisabled = false;
uint8_t apWaitTimeSecs = 32; IPAddress staticIP(0, 0, 0, 0);
boolean recoveryAPDisabled = false; IPAddress staticGateway(0, 0, 0, 0);
IPAddress staticip(0, 0, 0, 0); IPAddress staticSubnet(255, 255, 255, 0);
IPAddress staticgateway(0, 0, 0, 0); IPAddress staticDNS(8, 8, 8, 8); //only for NTP
IPAddress staticsubnet(255, 255, 255, 0);
IPAddress staticdns(8, 8, 8, 8); //only for NTP
bool useHSB = false, useHSBDefault = false; bool useHSB = false, useHSBDefault = false;
bool turnOnAtBoot = true; bool turnOnAtBoot = true;
uint8_t bootPreset = 0; bool initLedsLast = false;
byte col_s[]{255, 159, 0}; byte bootPreset = 0;
byte col_sec_s[]{0, 0, 0}; byte colS[]{255, 159, 0};
byte white_s = 0; byte colSecS[]{0, 0, 0};
byte white_sec_s = 0; byte whiteS = 0;
byte bri_s = 127; byte whiteSecS = 0;
uint8_t nightlightTargetBri = 0, bri_nl_t; byte briS = 127;
byte nightlightTargetBri = 0;
bool fadeTransition = true; bool fadeTransition = true;
bool sweepTransition = false, sweepDirection = true; bool sweepTransition = false, sweepDirection = true;
uint16_t transitionDelay = 1200; uint16_t transitionDelay = 1200;
bool reverseMode = false;
bool otaLock = false, wifiLock = false; bool otaLock = false, wifiLock = false;
bool aOtaEnabled = true; bool aOtaEnabled = true;
bool onlyAP = false;
bool buttonEnabled = true; bool buttonEnabled = true;
bool notifyDirect = true, notifyButton = true, notifyDirectDefault = true, alexaNotify = false, macroNotify = false; bool notifyDirect = true, notifyButton = true, notifyDirectDefault = true, alexaNotify = false, macroNotify = false, notifyTwice = false;
bool receiveNotifications = true, receiveNotificationBrightness = true, receiveNotificationColor = true, receiveNotificationEffects = true; bool receiveNotifications = true, receiveNotificationBrightness = true, receiveNotificationColor = true, receiveNotificationEffects = true;
uint8_t briMultiplier = 100; byte briMultiplier = 100;
uint8_t nightlightDelayMins = 60; byte nightlightDelayMins = 60;
bool nightlightFade = true; bool nightlightFade = true;
uint16_t udpPort = 21324; uint16_t udpPort = 21324;
uint8_t effectDefault = 0; byte effectDefault = 0;
uint8_t effectSpeedDefault = 75; byte effectSpeedDefault = 75;
uint8_t effectIntensityDefault = 128; byte effectIntensityDefault = 128;
//NTP stuff //NTP stuff
#ifndef CRONIXIE bool ntpEnabled = false;
boolean ntpEnabled = false; String ntpServerName = "0.wled.pool.ntp.org";
#endif
IPAddress ntpServerIP;
const char* ntpServerName = "pool.ntp.org";
//custom chase //custom chase
uint8_t cc_numPrimary = 2; byte ccNumPrimary = 2;
uint8_t cc_numSecondary = 4; byte ccNumSecondary = 4;
uint8_t cc_index1 = 0; byte ccIndex1 = 0;
uint8_t cc_index2 = ledcount -1; byte ccIndex2 = ledCount -1;
bool cc_fromStart = true, cc_fromEnd = false; bool ccFromStart = true, ccFromEnd = false;
uint8_t cc_step = 1; byte ccStep = 1;
uint8_t cc_start = 0; byte ccStart = 0;
//alexa //alexa
boolean alexaEnabled = true; bool alexaEnabled = true;
#ifndef CRONIXIE
String alexaInvocationName = "Light"; String alexaInvocationName = "Light";
#endif
uint8_t alexaOnMacro = 255, alexaOffMacro = 255; byte macroBoot = 0, macroNl = 0;
uint8_t buttonMacro = 255, countdownMacro = 255; byte macroAlexaOn = 0, macroAlexaOff = 0;
byte macroButton = 0, macroCountdown = 0, macroLongPress = 0;
unsigned long countdownTime = 1514764800L; unsigned long countdownTime = 1514764800L;
double transitionResolution = 0.011; double transitionResolution = 0.011;
//hue
bool huePollingEnabled = false, hueAttempt = false;
uint16_t huePollIntervalMs = 2500;
String hueApiKey = "api";
byte huePollLightId = 1;
IPAddress hueIP = (0,0,0,0);
bool notifyHue = true;
bool hueApplyOnOff = true, hueApplyBri = true, hueApplyColor = true;
//Internal vars //Internal vars
byte col[]{0, 0, 0}; byte col[]{0, 0, 0};
byte col_old[]{0, 0, 0}; byte colOld[]{0, 0, 0};
byte col_t[]{0, 0, 0}; byte colT[]{0, 0, 0};
byte col_it[]{0, 0, 0}; byte colIT[]{0, 0, 0};
byte col_sec[]{0, 0, 0}; byte colSec[]{0, 0, 0};
byte col_sec_it[]{0, 0, 0}; byte colSecIT[]{0, 0, 0};
byte white, white_old, white_t, white_it; byte white, whiteOld, whiteT, whiteIT;
byte white_sec, white_sec_it; byte whiteSec, whiteSecIT;
uint8_t lastRandomIndex = 0; byte lastRandomIndex = 0;
uint16_t transitionDelayTemp = transitionDelay;
unsigned long transitionStartTime; unsigned long transitionStartTime;
unsigned long nightlightStartTime; unsigned long nightlightStartTime;
float tper_last = 0; float tperLast = 0;
byte bri = 0; byte bri = 0;
byte bri_old = 0; byte briOld = 0;
byte bri_t = 0; byte briT = 0;
byte bri_it = 0; byte briIT = 0;
byte bri_last = 127; byte briLast = 127;
boolean transitionActive = false; bool transitionActive = false;
boolean buttonPressedBefore = false; bool buttonPressedBefore = false;
long buttonPressedTime = 0; unsigned long buttonPressedTime = 0;
boolean nightlightActive = false; unsigned long notificationSentTime = 0;
boolean nightlightActive_old = false; byte notificationSentCallMode = 0;
int nightlightDelayMs; bool notificationTwoRequired = false;
uint8_t effectCurrent = 0; bool nightlightActive = false;
uint8_t effectSpeed = 75; bool nightlightActiveOld = false;
uint8_t effectIntensity = 128; uint32_t nightlightDelayMs;
boolean udpConnected = false; byte briNlT;
byte udpIn[1026]; byte effectCurrent = 0;
byte effectSpeed = 75;
byte effectIntensity = 128;
bool onlyAP = false;
bool udpConnected = false;
String cssCol[]={"","","","","",""}; String cssCol[]={"","","","","",""};
String cssFont="Verdana"; String cssFont="Verdana";
String cssColorString=""; String cssColorString="";
//NTP stuff //NTP stuff
boolean ntpConnected = false; bool ntpConnected = false;
unsigned int ntpLocalPort = 2390; byte currentTimezone = 0;
const int NTP_PACKET_SIZE = 48; time_t local;
byte ntpPacketBuffer[NTP_PACKET_SIZE]; int utcOffsetSecs = 0;
unsigned long ntpLastSyncTime = 999000000L;
unsigned long ntpPacketSentTime = 999000000L; //hue
const unsigned long seventyYears = 2208988800UL; String hueError = "Inactive";
uint16_t hueFailCount = 0;
float hueXLast=0, hueYLast=0;
uint16_t hueHueLast=0, hueCtLast=0;
byte hueSatLast=0, hueBriLast=0;
long hueLastRequestSent = 0;
uint32_t huePollIntervalMsTemp = huePollIntervalMs;
//overlay stuff //overlay stuff
uint8_t overlayDefault = 0; byte overlayDefault = 0;
uint8_t overlayCurrent = 0; byte overlayCurrent = 0;
#ifdef USEOVERLAYS byte overlayMin = 0, overlayMax = ledCount-1;
int overlayMin = 0, overlayMax = 79; //bb: 35, 46, t: 0, 79 byte analogClock12pixel = 0;
int analogClock12pixel = 25; //bb: 41, t: 25 bool analogClockSecondsTrail = false;
bool overlayDimBg = true; bool analogClock5MinuteMarks = false;
boolean analogClockSecondsTrail = false; byte overlaySpeed = 200;
boolean analogClock5MinuteMarks = false; unsigned long overlayRefreshMs = 200;
boolean nixieClockDisplaySeconds = false;
boolean nixieClock12HourFormat = false;
boolean overlayReverse = true;
uint8_t overlaySpeed = 200;
long overlayRefreshMs = 200;
unsigned long overlayRefreshedTime; unsigned long overlayRefreshedTime;
int overlayArr[6]; int overlayArr[6];
int overlayDur[6]; uint16_t overlayDur[6];
int overlayPauseDur[6]; uint16_t overlayPauseDur[6];
int nixieClockI = -1; int nixieClockI = -1;
boolean nixiePause; bool nixiePause;
#endif byte countdownYear=19, countdownMonth=1, countdownDay=1, countdownHour=0, countdownMin=0, countdownSec=0; //year is actual year -2000
bool countdownOverTriggered = true; bool countdownOverTriggered = true;
//cronixie
String cronixieDisplay = "HHMMSS";
byte dP[]{0,0,0,0,0,0};
bool useAMPM = false;
bool cronixieBacklight = true;
bool countdownMode = false;
bool cronixieInit = false;
int arlsTimeoutMillis = 2500; uint32_t arlsTimeoutMillis = 2500;
boolean arlsTimeout = false; bool arlsTimeout = false;
long arlsTimeoutTime; unsigned long arlsTimeoutTime;
boolean arlsSign = true; byte auxTime = 0;
uint8_t auxTime = 0;
unsigned long auxStartTime; unsigned long auxStartTime;
boolean auxActive, auxActiveBefore; bool auxActive, auxActiveBefore;
boolean showWelcomePage = false; bool showWelcomePage = false;
boolean useGammaCorrectionBri = false; bool useGammaCorrectionBri = false;
boolean useGammaCorrectionRGB = true; bool useGammaCorrectionRGB = true;
int arlsOffset = -22; //10: -22 assuming arls52 int arlsOffset = -22; //10: -22 assuming arls52
//alexa udp //alexa udp
@@ -236,25 +227,28 @@ unsigned int portMulti = 1900;
char packetBuffer[255]; char packetBuffer[255];
String escapedMac; String escapedMac;
//dns server
DNSServer dnsServer;
bool dnsActive = false;
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
WebServer server(80); WebServer server(80);
#else #else
ESP8266WebServer server(80); ESP8266WebServer server(80);
#endif #endif
HTTPClient hueClient;
ESP8266HTTPUpdateServer httpUpdater; ESP8266HTTPUpdateServer httpUpdater;
WiFiUDP notifierUdp; WiFiUDP notifierUdp;
WiFiUDP ntpUdp; WiFiUDP ntpUdp;
IPAddress ntpServerIP;
unsigned int ntpLocalPort = 2390;
const uint16_t NTP_PACKET_SIZE = 48;
byte ntpPacketBuffer[NTP_PACKET_SIZE];
unsigned long ntpLastSyncTime = 999000000L;
unsigned long ntpPacketSentTime = 999000000L;
WS2812FX strip = WS2812FX(LEDCOUNT); WS2812FX strip = WS2812FX(LEDCOUNT);
//eeprom Version code, enables default settings instead of 0 init on update
#define EEPVER 4
//0 -> old version, default
//1 -> 0.4p 1711272 and up
//2 -> 0.4p 1711302 and up
//3 -> 0.4 1712121 and up
//4 -> 0.5.0 and up
#ifdef DEBUG #ifdef DEBUG
#define DEBUG_PRINT(x) Serial.print (x) #define DEBUG_PRINT(x) Serial.print (x)
#define DEBUG_PRINTLN(x) Serial.println (x) #define DEBUG_PRINTLN(x) Serial.println (x)
@@ -276,7 +270,7 @@ int lastWifiState = 3;
long wifiStateChangedTime = 0; long wifiStateChangedTime = 0;
#endif #endif
const uint8_t gamma8[] = { const byte gamma8[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
@@ -300,7 +294,7 @@ void serveMessage(int,String,String,int=255);
void down() void down()
{ {
bri_t = 0; briT = 0;
setAllLeds(); setAllLeds();
DEBUG_PRINTLN("MODULE TERMINATED"); DEBUG_PRINTLN("MODULE TERMINATED");
while (1) {delay(1000);} while (1) {delay(1000);}
@@ -308,7 +302,7 @@ void down()
void reset() void reset()
{ {
bri_t = 0; briT = 0;
setAllLeds(); setAllLeds();
DEBUG_PRINTLN("MODULE RESET"); DEBUG_PRINTLN("MODULE RESET");
ESP.restart(); ESP.restart();
@@ -322,21 +316,19 @@ void loop() {
server.handleClient(); server.handleClient();
handleNotifications(); handleNotifications();
handleTransitions(); handleTransitions();
userLoop();
yield(); yield();
handleButton(); handleButton();
handleNetworkTime(); handleNetworkTime();
if (!otaLock && aOtaEnabled) ArduinoOTA.handle(); if (!otaLock && aOtaEnabled) ArduinoOTA.handle();
#ifdef CRONIXIE
handleCronixie();
#endif
handleAlexa(); handleAlexa();
handleOverlays();
if (!arlsTimeout) //block stuff if WARLS is enabled if (!arlsTimeout) //block stuff if WARLS is enabled
{ {
if (dnsActive) dnsServer.processNextRequest();
handleHue();
handleNightlight(); handleNightlight();
#ifdef USEOVERLAYS if (briT) strip.service(); //do not update strip if off, prevents flicker on ESP32
handleOverlays();
#endif
if (bri_t) strip.service(); //do not update strip if off, prevents flicker on ESP32
} }
//DEBUG //DEBUG

View File

@@ -1,9 +1,21 @@
/* /*
* Methods to handle saving and loading to non-volatile memory * Methods to handle saving and loading to non-volatile memory
* EEPROM Map: https://github.com/Aircoookie/WLED/wiki/EEPROM-Map
*/ */
#define EEPSIZE 2048 #define EEPSIZE 3072
//eeprom Version code, enables default settings instead of 0 init on update
#define EEPVER 6
//0 -> old version, default
//1 -> 0.4p 1711272 and up
//2 -> 0.4p 1711302 and up
//3 -> 0.4 1712121 and up
//4 -> 0.5.0 and up
//5 -> 0.5.1 and up
//6 -> 0.6.0 and up
//todo add settings
void clearEEPROM() void clearEEPROM()
{ {
for (int i = 0; i < EEPSIZE; i++) for (int i = 0; i < EEPSIZE; i++)
@@ -26,59 +38,60 @@ void saveSettingsToEEPROM()
for (int i = 0; i < 32; ++i) for (int i = 0; i < 32; ++i)
{ {
EEPROM.write(i, clientssid.charAt(i)); EEPROM.write(i, clientSSID.charAt(i));
} }
for (int i = 32; i < 96; ++i) for (int i = 32; i < 96; ++i)
{ {
EEPROM.write(i, clientpass.charAt(i-32)); EEPROM.write(i, clientPass.charAt(i-32));
} }
for (int i = 96; i < 128; ++i) for (int i = 96; i < 128; ++i)
{ {
EEPROM.write(i, cmdns.charAt(i-96)); EEPROM.write(i, cmDNS.charAt(i-96));
} }
for (int i = 128; i < 160; ++i) for (int i = 128; i < 160; ++i)
{ {
EEPROM.write(i, apssid.charAt(i-128)); EEPROM.write(i, apSSID.charAt(i-128));
} }
for (int i = 160; i < 224; ++i) for (int i = 160; i < 224; ++i)
{ {
EEPROM.write(i, appass.charAt(i-160)); EEPROM.write(i, apPass.charAt(i-160));
} }
EEPROM.write(224, nightlightDelayMins); EEPROM.write(224, nightlightDelayMins);
EEPROM.write(225, nightlightFade); EEPROM.write(225, nightlightFade);
EEPROM.write(226, notifyDirectDefault); EEPROM.write(226, notifyDirectDefault);
EEPROM.write(227, apchannel); EEPROM.write(227, apChannel);
EEPROM.write(228, aphide); EEPROM.write(228, apHide);
EEPROM.write(229, ledcount); EEPROM.write(229, ledCount);
EEPROM.write(230, notifyButton); EEPROM.write(230, notifyButton);
//231 was notifyNightlight EEPROM.write(231, notifyTwice);
EEPROM.write(232, buttonEnabled); EEPROM.write(232, buttonEnabled);
//233 reserved for first boot flag //233 reserved for first boot flag
EEPROM.write(234, staticip[0]); EEPROM.write(234, staticIP[0]);
EEPROM.write(235, staticip[1]); EEPROM.write(235, staticIP[1]);
EEPROM.write(236, staticip[2]); EEPROM.write(236, staticIP[2]);
EEPROM.write(237, staticip[3]); EEPROM.write(237, staticIP[3]);
EEPROM.write(238, staticgateway[0]); EEPROM.write(238, staticGateway[0]);
EEPROM.write(239, staticgateway[1]); EEPROM.write(239, staticGateway[1]);
EEPROM.write(240, staticgateway[2]); EEPROM.write(240, staticGateway[2]);
EEPROM.write(241, staticgateway[3]); EEPROM.write(241, staticGateway[3]);
EEPROM.write(242, staticsubnet[0]); EEPROM.write(242, staticSubnet[0]);
EEPROM.write(243, staticsubnet[1]); EEPROM.write(243, staticSubnet[1]);
EEPROM.write(244, staticsubnet[2]); EEPROM.write(244, staticSubnet[2]);
EEPROM.write(245, staticsubnet[3]); EEPROM.write(245, staticSubnet[3]);
EEPROM.write(246, col_s[0]); EEPROM.write(246, colS[0]);
EEPROM.write(247, col_s[1]); EEPROM.write(247, colS[1]);
EEPROM.write(248, col_s[2]); EEPROM.write(248, colS[2]);
EEPROM.write(249, bri_s); EEPROM.write(249, briS);
EEPROM.write(250, receiveNotificationBrightness); EEPROM.write(250, receiveNotificationBrightness);
EEPROM.write(251, fadeTransition); EEPROM.write(251, fadeTransition);
EEPROM.write(252, reverseMode);
EEPROM.write(253, (transitionDelay >> 0) & 0xFF); EEPROM.write(253, (transitionDelay >> 0) & 0xFF);
EEPROM.write(254, (transitionDelay >> 8) & 0xFF); EEPROM.write(254, (transitionDelay >> 8) & 0xFF);
EEPROM.write(255, briMultiplier); EEPROM.write(255, briMultiplier);
//255,250,231,230,226 notifier bytes //255,250,231,230,226 notifier bytes
for (int i = 256; i < 288; ++i) for (int i = 256; i < 288; ++i)
{ {
EEPROM.write(i, otapass.charAt(i-256)); EEPROM.write(i, otaPass.charAt(i-256));
} }
EEPROM.write(288, nightlightTargetBri); EEPROM.write(288, nightlightTargetBri);
EEPROM.write(289, otaLock); EEPROM.write(289, otaLock);
@@ -92,8 +105,8 @@ void saveSettingsToEEPROM()
EEPROM.write(325, effectSpeedDefault); EEPROM.write(325, effectSpeedDefault);
EEPROM.write(326, effectIntensityDefault); EEPROM.write(326, effectIntensityDefault);
EEPROM.write(327, ntpEnabled); EEPROM.write(327, ntpEnabled);
//328 reserved for timezone setting EEPROM.write(328, currentTimezone);
//329 reserved for dst setting EEPROM.write(329, useAMPM);
EEPROM.write(330, useGammaCorrectionBri); EEPROM.write(330, useGammaCorrectionBri);
EEPROM.write(331, useGammaCorrectionRGB); EEPROM.write(331, useGammaCorrectionRGB);
EEPROM.write(332, overlayDefault); EEPROM.write(332, overlayDefault);
@@ -103,33 +116,37 @@ void saveSettingsToEEPROM()
EEPROM.write(i, alexaInvocationName.charAt(i-334)); EEPROM.write(i, alexaInvocationName.charAt(i-334));
} }
EEPROM.write(366, alexaNotify); EEPROM.write(366, alexaNotify);
EEPROM.write(367, arlsSign); EEPROM.write(367, (arlsOffset>=0));
EEPROM.write(368, abs(arlsOffset)); EEPROM.write(368, abs(arlsOffset));
EEPROM.write(369, turnOnAtBoot); EEPROM.write(369, turnOnAtBoot);
EEPROM.write(370, useHSBDefault); EEPROM.write(370, useHSBDefault);
EEPROM.write(371, white_s); EEPROM.write(371, whiteS);
EEPROM.write(372, useRGBW); EEPROM.write(372, useRGBW);
EEPROM.write(373, sweepTransition); EEPROM.write(373, sweepTransition);
EEPROM.write(374, sweepDirection); EEPROM.write(374, sweepDirection);
EEPROM.write(375, apWaitTimeSecs); EEPROM.write(375, apWaitTimeSecs);
EEPROM.write(376, recoveryAPDisabled); EEPROM.write(376, recoveryAPDisabled);
EEPROM.write(377, EEPVER); //eeprom was updated to latest EEPROM.write(377, EEPVER); //eeprom was updated to latest
EEPROM.write(378, col_sec_s[0]); EEPROM.write(378, colSecS[0]);
EEPROM.write(379, col_sec_s[1]); EEPROM.write(379, colSecS[1]);
EEPROM.write(380, col_sec_s[2]); EEPROM.write(380, colSecS[2]);
EEPROM.write(381, white_sec_s); EEPROM.write(381, whiteSecS);
EEPROM.write(382, cc_index1); EEPROM.write(382, ccIndex1);
EEPROM.write(383, cc_index2); EEPROM.write(383, ccIndex2);
EEPROM.write(384, cc_numPrimary); EEPROM.write(384, ccNumPrimary);
EEPROM.write(385, cc_numSecondary); EEPROM.write(385, ccNumSecondary);
EEPROM.write(386, cc_fromStart); EEPROM.write(386, ccFromStart);
EEPROM.write(387, cc_fromEnd); EEPROM.write(387, ccFromEnd);
EEPROM.write(388, cc_step); EEPROM.write(388, ccStep);
EEPROM.write(389, bootPreset); EEPROM.write(389, bootPreset);
EEPROM.write(390, aOtaEnabled); EEPROM.write(390, aOtaEnabled);
EEPROM.write(391, receiveNotificationColor); EEPROM.write(391, receiveNotificationColor);
EEPROM.write(392, receiveNotificationEffects); EEPROM.write(392, receiveNotificationEffects);
EEPROM.write(393, wifiLock); EEPROM.write(393, wifiLock);
EEPROM.write(394, (abs(utcOffsetSecs) >> 0) & 0xFF);
EEPROM.write(395, (abs(utcOffsetSecs) >> 8) & 0xFF);
EEPROM.write(396, (utcOffsetSecs<0)); //is negative
EEPROM.write(397, initLedsLast);
for (int k=0;k<6;k++){ for (int k=0;k<6;k++){
int in = 900+k*8; int in = 900+k*8;
@@ -143,6 +160,53 @@ void saveSettingsToEEPROM()
{ {
EEPROM.write(i, cssFont.charAt(i-950)); EEPROM.write(i, cssFont.charAt(i-950));
} }
EEPROM.write(2048, huePollingEnabled);
//EEPROM.write(2049, hueUpdatingEnabled);
for (int i = 2050; i < 2054; ++i)
{
EEPROM.write(i, hueIP[i-2050]);
}
for (int i = 2054; i < 2100; ++i)
{
EEPROM.write(i, hueApiKey.charAt(i-2054));
}
EEPROM.write(2100, (huePollIntervalMs >> 0) & 0xFF);
EEPROM.write(2101, (huePollIntervalMs >> 8) & 0xFF);
EEPROM.write(2102, notifyHue);
EEPROM.write(2103, hueApplyOnOff);
EEPROM.write(2104, hueApplyBri);
EEPROM.write(2105, hueApplyColor);
EEPROM.write(2106, huePollLightId);
EEPROM.write(2150, overlayMin);
EEPROM.write(2151, overlayMax);
EEPROM.write(2152, analogClock12pixel);
EEPROM.write(2153, analogClock5MinuteMarks);
EEPROM.write(2154, analogClockSecondsTrail);
EEPROM.write(2155, countdownMode);
EEPROM.write(2156, countdownYear);
EEPROM.write(2157, countdownMonth);
EEPROM.write(2158, countdownDay);
EEPROM.write(2159, countdownHour);
EEPROM.write(2160, countdownMin);
EEPROM.write(2161, countdownSec);
setCountdown();
for (int i = 2165; i < 2171; ++i)
{
EEPROM.write(i, cronixieDisplay.charAt(i-2165));
}
EEPROM.write(2171, cronixieBacklight);
setCronixie();
EEPROM.write(2175, macroBoot);
EEPROM.write(2176, macroAlexaOn);
EEPROM.write(2177, macroAlexaOff);
EEPROM.write(2178, macroButton);
EEPROM.write(2179, macroLongPress);
EEPROM.write(2180, macroCountdown);
EEPROM.write(2181, macroNl);
EEPROM.commit(); EEPROM.commit();
} }
@@ -157,77 +221,78 @@ void loadSettingsFromEEPROM(bool first)
} }
int lastEEPROMversion = EEPROM.read(377); //last EEPROM version before update int lastEEPROMversion = EEPROM.read(377); //last EEPROM version before update
clientssid = ""; clientSSID = "";
for (int i = 0; i < 32; ++i) for (int i = 0; i < 32; ++i)
{ {
if (EEPROM.read(i) == 0) break; if (EEPROM.read(i) == 0) break;
clientssid += char(EEPROM.read(i)); clientSSID += char(EEPROM.read(i));
} }
clientpass = ""; clientPass = "";
for (int i = 32; i < 96; ++i) for (int i = 32; i < 96; ++i)
{ {
if (EEPROM.read(i) == 0) break; if (EEPROM.read(i) == 0) break;
clientpass += char(EEPROM.read(i)); clientPass += char(EEPROM.read(i));
} }
cmdns = ""; cmDNS = "";
for (int i = 96; i < 128; ++i) for (int i = 96; i < 128; ++i)
{ {
if (EEPROM.read(i) == 0) break; if (EEPROM.read(i) == 0) break;
cmdns += char(EEPROM.read(i)); cmDNS += char(EEPROM.read(i));
} }
apssid = ""; apSSID = "";
for (int i = 128; i < 160; ++i) for (int i = 128; i < 160; ++i)
{ {
if (EEPROM.read(i) == 0) break; if (EEPROM.read(i) == 0) break;
apssid += char(EEPROM.read(i)); apSSID += char(EEPROM.read(i));
} }
appass = ""; apPass = "";
for (int i = 160; i < 224; ++i) for (int i = 160; i < 224; ++i)
{ {
if (EEPROM.read(i) == 0) break; if (EEPROM.read(i) == 0) break;
appass += char(EEPROM.read(i)); apPass += char(EEPROM.read(i));
} }
nightlightDelayMins = EEPROM.read(224); nightlightDelayMins = EEPROM.read(224);
nightlightFade = EEPROM.read(225); nightlightFade = EEPROM.read(225);
notifyDirectDefault = EEPROM.read(226); notifyDirectDefault = EEPROM.read(226);
notifyDirect = notifyDirectDefault; notifyDirect = notifyDirectDefault;
apchannel = EEPROM.read(227); apChannel = EEPROM.read(227);
if (apchannel > 13 || apchannel < 1) apchannel = 1; if (apChannel > 13 || apChannel < 1) apChannel = 1;
aphide = EEPROM.read(228); apHide = EEPROM.read(228);
if (aphide > 1) aphide = 1; if (apHide > 1) apHide = 1;
ledcount = EEPROM.read(229); if (ledcount > LEDCOUNT) ledcount = LEDCOUNT; ledCount = EEPROM.read(229); if (ledCount > LEDCOUNT) ledCount = LEDCOUNT;
notifyButton = EEPROM.read(230); notifyButton = EEPROM.read(230);
//231 was notifyNightlight notifyTwice = EEPROM.read(231);
buttonEnabled = EEPROM.read(232); buttonEnabled = EEPROM.read(232);
staticip[0] = EEPROM.read(234); staticIP[0] = EEPROM.read(234);
staticip[1] = EEPROM.read(235); staticIP[1] = EEPROM.read(235);
staticip[2] = EEPROM.read(236); staticIP[2] = EEPROM.read(236);
staticip[3] = EEPROM.read(237); staticIP[3] = EEPROM.read(237);
staticgateway[0] = EEPROM.read(238); staticGateway[0] = EEPROM.read(238);
staticgateway[1] = EEPROM.read(239); staticGateway[1] = EEPROM.read(239);
staticgateway[2] = EEPROM.read(240); staticGateway[2] = EEPROM.read(240);
staticgateway[3] = EEPROM.read(241); staticGateway[3] = EEPROM.read(241);
staticsubnet[0] = EEPROM.read(242); staticSubnet[0] = EEPROM.read(242);
staticsubnet[1] = EEPROM.read(243); staticSubnet[1] = EEPROM.read(243);
staticsubnet[2] = EEPROM.read(244); staticSubnet[2] = EEPROM.read(244);
staticsubnet[3] = EEPROM.read(245); staticSubnet[3] = EEPROM.read(245);
col_s[0] = EEPROM.read(246); col[0] = col_s[0]; colS[0] = EEPROM.read(246); col[0] = colS[0];
col_s[1] = EEPROM.read(247); col[1] = col_s[1]; colS[1] = EEPROM.read(247); col[1] = colS[1];
col_s[2] = EEPROM.read(248); col[2] = col_s[2]; colS[2] = EEPROM.read(248); col[2] = colS[2];
bri_s = EEPROM.read(249); bri = bri_s; briS = EEPROM.read(249); bri = briS;
if (!EEPROM.read(369) && first) if (!EEPROM.read(369) && first)
{ {
bri = 0; bri_last = bri_s; bri = 0; briLast = briS;
} }
receiveNotificationBrightness = EEPROM.read(250); receiveNotificationBrightness = EEPROM.read(250);
fadeTransition = EEPROM.read(251); fadeTransition = EEPROM.read(251);
reverseMode = EEPROM.read(252);
transitionDelay = ((EEPROM.read(253) << 0) & 0xFF) + ((EEPROM.read(254) << 8) & 0xFF00); transitionDelay = ((EEPROM.read(253) << 0) & 0xFF) + ((EEPROM.read(254) << 8) & 0xFF00);
briMultiplier = EEPROM.read(255); briMultiplier = EEPROM.read(255);
otapass = ""; otaPass = "";
for (int i = 256; i < 288; ++i) for (int i = 256; i < 288; ++i)
{ {
if (EEPROM.read(i) == 0) break; if (EEPROM.read(i) == 0) break;
otapass += char(EEPROM.read(i)); otaPass += char(EEPROM.read(i));
} }
nightlightTargetBri = EEPROM.read(288); nightlightTargetBri = EEPROM.read(288);
otaLock = EEPROM.read(289); otaLock = EEPROM.read(289);
@@ -241,6 +306,8 @@ void loadSettingsFromEEPROM(bool first)
effectDefault = EEPROM.read(324); effectCurrent = effectDefault; effectDefault = EEPROM.read(324); effectCurrent = effectDefault;
effectSpeedDefault = EEPROM.read(325); effectSpeed = effectSpeedDefault; effectSpeedDefault = EEPROM.read(325); effectSpeed = effectSpeedDefault;
ntpEnabled = EEPROM.read(327); ntpEnabled = EEPROM.read(327);
currentTimezone = EEPROM.read(328);
useAMPM = EEPROM.read(329);
useGammaCorrectionBri = EEPROM.read(330); useGammaCorrectionBri = EEPROM.read(330);
useGammaCorrectionRGB = EEPROM.read(331); useGammaCorrectionRGB = EEPROM.read(331);
overlayDefault = EEPROM.read(332); overlayDefault = EEPROM.read(332);
@@ -252,12 +319,11 @@ void loadSettingsFromEEPROM(bool first)
alexaInvocationName += char(EEPROM.read(i)); alexaInvocationName += char(EEPROM.read(i));
} }
alexaNotify = EEPROM.read(366); alexaNotify = EEPROM.read(366);
arlsSign = EEPROM.read(367);
arlsOffset = EEPROM.read(368); arlsOffset = EEPROM.read(368);
if (!arlsSign) arlsOffset = -arlsOffset; if (!EEPROM.read(367)) arlsOffset = -arlsOffset;
turnOnAtBoot = EEPROM.read(369); turnOnAtBoot = EEPROM.read(369);
useHSBDefault = EEPROM.read(370); useHSBDefault = EEPROM.read(370);
white_s = EEPROM.read(371); white = white_s; whiteS = EEPROM.read(371); white = whiteS;
useRGBW = EEPROM.read(372); useRGBW = EEPROM.read(372);
sweepTransition = EEPROM.read(373); sweepTransition = EEPROM.read(373);
sweepDirection = EEPROM.read(374); sweepDirection = EEPROM.read(374);
@@ -267,18 +333,18 @@ void loadSettingsFromEEPROM(bool first)
} }
//377 = lastEEPROMversion //377 = lastEEPROMversion
if (lastEEPROMversion > 1) { if (lastEEPROMversion > 1) {
col_sec_s[0] = EEPROM.read(378); col_sec[0] = col_sec_s[0]; colSecS[0] = EEPROM.read(378); colSec[0] = colSecS[0];
col_sec_s[1] = EEPROM.read(379); col_sec[1] = col_sec_s[1]; colSecS[1] = EEPROM.read(379); colSec[1] = colSecS[1];
col_sec_s[2] = EEPROM.read(380); col_sec[2] = col_sec_s[2]; colSecS[2] = EEPROM.read(380); colSec[2] = colSecS[2];
white_sec_s = EEPROM.read(381); white_sec = white_sec_s; whiteSecS = EEPROM.read(381); whiteSec = whiteSecS;
cc_index1 = EEPROM.read(382); ccIndex1 = EEPROM.read(382);
cc_index2 = EEPROM.read(383); ccIndex2 = EEPROM.read(383);
cc_numPrimary = EEPROM.read(384); ccNumPrimary = EEPROM.read(384);
cc_numSecondary = EEPROM.read(385); ccNumSecondary = EEPROM.read(385);
cc_fromStart = EEPROM.read(386); ccFromStart = EEPROM.read(386);
cc_fromEnd = EEPROM.read(387); ccFromEnd = EEPROM.read(387);
cc_step = EEPROM.read(388); ccStep = EEPROM.read(388);
strip.setCustomChase(cc_index1, cc_index2, cc_start, cc_numPrimary, cc_numSecondary, cc_step, cc_fromStart, cc_fromEnd); strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd);
} }
if (lastEEPROMversion > 3) { if (lastEEPROMversion > 3) {
effectIntensityDefault = EEPROM.read(326); effectIntensity = effectIntensityDefault; effectIntensityDefault = EEPROM.read(326); effectIntensity = effectIntensityDefault;
@@ -291,11 +357,69 @@ void loadSettingsFromEEPROM(bool first)
if (EEPROM.read(i) == 0) break; if (EEPROM.read(i) == 0) break;
cssFont += char(EEPROM.read(i)); cssFont += char(EEPROM.read(i));
} }
} else //keep receiving notification behavior from pre0.5.0 after update
{
receiveNotificationColor = receiveNotificationBrightness;
receiveNotificationEffects = receiveNotificationBrightness;
} }
receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects); receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
if (lastEEPROMversion > 4) {
huePollingEnabled = EEPROM.read(2048);
//hueUpdatingEnabled = EEPROM.read(2049);
for (int i = 2050; i < 2054; ++i)
{
hueIP[i-2050] = EEPROM.read(i);
}
hueApiKey = "";
for (int i = 2054; i < 2100; ++i)
{
if (EEPROM.read(i) == 0) break;
hueApiKey += char(EEPROM.read(i));
}
huePollIntervalMs = ((EEPROM.read(2100) << 0) & 0xFF) + ((EEPROM.read(2101) << 8) & 0xFF00);
notifyHue = EEPROM.read(2102);
hueApplyOnOff = EEPROM.read(2103);
hueApplyBri = EEPROM.read(2104);
hueApplyColor = EEPROM.read(2105);
huePollLightId = EEPROM.read(2106);
}
if (lastEEPROMversion > 5) {
overlayMin = EEPROM.read(2150);
overlayMax = EEPROM.read(2151);
analogClock12pixel = EEPROM.read(2152);
analogClock5MinuteMarks = EEPROM.read(2153);
analogClockSecondsTrail = EEPROM.read(2154);
countdownMode = EEPROM.read(2155);
countdownYear = EEPROM.read(2156);
countdownMonth = EEPROM.read(2157);
countdownDay = EEPROM.read(2158);
countdownHour = EEPROM.read(2159);
countdownMin = EEPROM.read(2160);
countdownSec = EEPROM.read(2161);
setCountdown();
cronixieDisplay = "";
for (int i = 2165; i < 2171; ++i)
{
if (EEPROM.read(i) == 0) break;
cronixieDisplay += char(EEPROM.read(i));
}
cronixieBacklight = EEPROM.read(2171);
macroBoot = EEPROM.read(2175);
macroAlexaOn = EEPROM.read(2176);
macroAlexaOff = EEPROM.read(2177);
macroButton = EEPROM.read(2178);
macroLongPress = EEPROM.read(2179);
macroCountdown = EEPROM.read(2180);
macroNl = EEPROM.read(2181);
}
bootPreset = EEPROM.read(389); bootPreset = EEPROM.read(389);
wifiLock = EEPROM.read(393); wifiLock = EEPROM.read(393);
utcOffsetSecs = ((EEPROM.read(394) << 0) & 0xFF) + ((EEPROM.read(395) << 8) & 0xFF00);
if (EEPROM.read(396)) utcOffsetSecs = -utcOffsetSecs; //negative
initLedsLast = EEPROM.read(397);
//favorite setting memory (25 slots/ each 20byte) //favorite setting memory (25 slots/ each 20byte)
//400 - 899 reserved //400 - 899 reserved
@@ -311,6 +435,9 @@ void loadSettingsFromEEPROM(bool first)
//custom macro memory (16 slots/ each 64byte) //custom macro memory (16 slots/ each 64byte)
//1024-2047 reserved //1024-2047 reserved
//user MOD memory
//2944 - 3071 reserved
useHSB = useHSBDefault; useHSB = useHSBDefault;
@@ -324,7 +451,7 @@ void loadSettingsFromEEPROM(bool first)
//0: preset purpose byte 0:invalid 1:valid preset 1.0 //0: preset purpose byte 0:invalid 1:valid preset 1.0
//1:a 2:r 3:g 4:b 5:w 6:er 7:eg 8:eb 9:ew 10:fx 11:sx | custom chase 12:numP 13:numS 14:(0:fs 1:both 2:fe) 15:step 16:ix 17-19:Zeros //1:a 2:r 3:g 4:b 5:w 6:er 7:eg 8:eb 9:ew 10:fx 11:sx | custom chase 12:numP 13:numS 14:(0:fs 1:both 2:fe) 15:step 16:ix 17-19:Zeros
void applyPreset(uint8_t index, bool loadBri, bool loadCol, bool loadFX) void applyPreset(byte index, bool loadBri, bool loadCol, bool loadFX)
{ {
if (index == 255 || index == 0) loadSettingsFromEEPROM(false);//load boot defaults if (index == 255 || index == 0) loadSettingsFromEEPROM(false);//load boot defaults
if (index > 25 || index < 1) return; if (index > 25 || index < 1) return;
@@ -337,29 +464,29 @@ void applyPreset(uint8_t index, bool loadBri, bool loadCol, bool loadFX)
col[1] = EEPROM.read(i+3); col[1] = EEPROM.read(i+3);
col[2] = EEPROM.read(i+4); col[2] = EEPROM.read(i+4);
white = EEPROM.read(i+5); white = EEPROM.read(i+5);
col_sec[0] = EEPROM.read(i+6); colSec[0] = EEPROM.read(i+6);
col_sec[1] = EEPROM.read(i+7); colSec[1] = EEPROM.read(i+7);
col_sec[2] = EEPROM.read(i+8); colSec[2] = EEPROM.read(i+8);
white_sec = EEPROM.read(i+9); whiteSec = EEPROM.read(i+9);
} }
if (loadFX) if (loadFX)
{ {
effectCurrent = EEPROM.read(i+10); effectCurrent = EEPROM.read(i+10);
effectSpeed = EEPROM.read(i+11); effectSpeed = EEPROM.read(i+11);
effectIntensity = EEPROM.read(i+16); effectIntensity = EEPROM.read(i+16);
cc_numPrimary = EEPROM.read(i+12); ccNumPrimary = EEPROM.read(i+12);
cc_numSecondary = EEPROM.read(i+13); ccNumSecondary = EEPROM.read(i+13);
cc_fromEnd = EEPROM.read(i+14); ccFromEnd = EEPROM.read(i+14);
cc_fromStart = (EEPROM.read(i+14)<2); ccFromStart = (EEPROM.read(i+14)<2);
cc_step = EEPROM.read(i+15); ccStep = EEPROM.read(i+15);
strip.setCustomChase(cc_index1, cc_index2, cc_start, cc_numPrimary, cc_numSecondary, cc_step, cc_fromStart, cc_fromEnd); strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd);
strip.setMode(effectCurrent); strip.setMode(effectCurrent);
strip.setSpeed(effectSpeed); strip.setSpeed(effectSpeed);
strip.setIntensity(effectIntensity); strip.setIntensity(effectIntensity);
} }
} }
void savePreset(uint8_t index) void savePreset(byte index)
{ {
if (index > 25) return; if (index > 25) return;
if (index < 1) {saveSettingsToEEPROM();return;} if (index < 1) {saveSettingsToEEPROM();return;}
@@ -370,32 +497,43 @@ void savePreset(uint8_t index)
EEPROM.write(i+3, col[1]); EEPROM.write(i+3, col[1]);
EEPROM.write(i+4, col[2]); EEPROM.write(i+4, col[2]);
EEPROM.write(i+5, white); EEPROM.write(i+5, white);
EEPROM.write(i+6, col_sec[0]); EEPROM.write(i+6, colSec[0]);
EEPROM.write(i+7, col_sec[1]); EEPROM.write(i+7, colSec[1]);
EEPROM.write(i+8, col_sec[2]); EEPROM.write(i+8, colSec[2]);
EEPROM.write(i+9, white_sec); EEPROM.write(i+9, whiteSec);
EEPROM.write(i+10, effectCurrent); EEPROM.write(i+10, effectCurrent);
EEPROM.write(i+11, effectSpeed); EEPROM.write(i+11, effectSpeed);
EEPROM.write(i+12, cc_numPrimary); EEPROM.write(i+12, ccNumPrimary);
EEPROM.write(i+13, cc_numSecondary); EEPROM.write(i+13, ccNumSecondary);
uint8_t m = 1; byte m = 1;
if (!cc_fromStart) m = 2; if (!ccFromStart) m = 2;
if (!cc_fromEnd) m = 0; if (!ccFromEnd) m = 0;
EEPROM.write(i+14, m); EEPROM.write(i+14, m);
EEPROM.write(i+15, cc_step); EEPROM.write(i+15, ccStep);
EEPROM.write(i+16, effectIntensity); EEPROM.write(i+16, effectIntensity);
EEPROM.commit(); EEPROM.commit();
} }
void applyMacro(uint8_t index) String loadMacro(byte index)
{ {
if (index > 15) return; index-=1;
String mc="win&"; String m="";
if (index > 15) return m;
for (int i = 1024+64*index; i < 1088+64*index; i++) for (int i = 1024+64*index; i < 1088+64*index; i++)
{ {
if (EEPROM.read(i) == 0) break; if (EEPROM.read(i) == 0) break;
mc += char(EEPROM.read(i)); m += char(EEPROM.read(i));
} }
if (m.charAt(0) < 65 || m.charAt(0) > 90) return ""; //do simple check if macro is valid (capital first letter)
return m;
}
void applyMacro(byte index)
{
index-=1;
if (index > 15) return;
String mc="win&";
mc += loadMacro(index+1);
mc += "&IN"; //internal, no XML response mc += "&IN"; //internal, no XML response
if (!macroNotify) mc += "&NN"; if (!macroNotify) mc += "&NN";
String forbidden = "&M="; //dont apply if called by the macro itself to prevent loop String forbidden = "&M="; //dont apply if called by the macro itself to prevent loop
@@ -408,14 +546,15 @@ void applyMacro(uint8_t index)
handleSet(mc); handleSet(mc);
} }
void saveMacro(uint8_t index, String mc) void saveMacro(byte index, String mc, bool sing=true) //only commit on single save, not in settings
{ {
index-=1;
if (index > 15) return; if (index > 15) return;
int s = 1024+index*64; int s = 1024+index*64;
for (int i = s; i < s+64; i++) for (int i = s; i < s+64; i++)
{ {
EEPROM.write(i, mc.charAt(i-s)); EEPROM.write(i, mc.charAt(i-s));
} }
EEPROM.commit(); if (sing) EEPROM.commit();
} }

View File

@@ -7,15 +7,15 @@ void XML_response()
String resp; String resp;
resp = resp + "<?xml version = \"1.0\" ?>"; resp = resp + "<?xml version = \"1.0\" ?>";
resp = resp + "<vs>"; resp = resp + "<vs>";
resp = resp + "<act>"; resp = resp + "<ac>";
if (nightlightActive && nightlightFade) if (nightlightActive && nightlightFade)
{ {
resp = resp + bri_t; resp = resp + briT;
} else } else
{ {
resp = resp + bri; resp = resp + bri;
} }
resp = resp + "</act>"; resp = resp + "</ac>";
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
@@ -49,14 +49,14 @@ void XML_response()
} }
resp = resp + "</wv><md>"; resp = resp + "</wv><md>";
resp = resp + useHSB; resp = resp + useHSB;
resp = resp + "</md><desc>"; resp = resp + "</md><ds>";
resp = resp + serverDescription; resp = resp + serverDescription;
resp = resp + "</desc>"; resp = resp + "</ds>";
resp = resp + "</vs>"; resp = resp + "</vs>";
server.send(200, "text/xml", resp); server.send(200, "text/xml", resp);
} }
String getSettings(uint8_t subPage) String getSettings(byte subPage)
{ {
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec //0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec
DEBUG_PRINT("settings resp"); DEBUG_PRINT("settings resp");
@@ -70,38 +70,39 @@ String getSettings(uint8_t subPage)
String v = ".value="; String v = ".value=";
String c = ".checked="; String c = ".checked=";
String ih = ".innerHTML="; String ih = ".innerHTML=";
String si = ".selectedIndex=";
if (subPage == 1) { if (subPage == 1) {
resp += ds + "CSSID" + v + "\"" + clientssid + "\";"; resp += ds + "CS" + v + "\"" + clientSSID + "\";";
resp += ds + "CPASS" + v + "\""; resp += ds + "CP" + v + "\"";
for (int i = 0; i < clientpass.length(); i++) for (int i = 0; i < clientPass.length(); i++)
{ {
resp += "*"; resp += "*";
} }
resp += "\";"; resp += "\";";
resp += ds + "CSIP0" + v + staticip[0] +";"; resp += ds + "I0" + v + staticIP[0] +";";
resp += ds + "CSIP1" + v + staticip[1] +";"; resp += ds + "I1" + v + staticIP[1] +";";
resp += ds + "CSIP2" + v + staticip[2] +";"; resp += ds + "I2" + v + staticIP[2] +";";
resp += ds + "CSIP3" + v + staticip[3] +";"; resp += ds + "I3" + v + staticIP[3] +";";
resp += ds + "CSGW0" + v + staticgateway[0] +";"; resp += ds + "G0" + v + staticGateway[0] +";";
resp += ds + "CSGW1" + v + staticgateway[1] +";"; resp += ds + "G1" + v + staticGateway[1] +";";
resp += ds + "CSGW2" + v + staticgateway[2] +";"; resp += ds + "G2" + v + staticGateway[2] +";";
resp += ds + "CSGW3" + v + staticgateway[3] +";"; resp += ds + "G3" + v + staticGateway[3] +";";
resp += ds + "CSSN0" + v + staticsubnet[0] +";"; resp += ds + "S0" + v + staticSubnet[0] +";";
resp += ds + "CSSN1" + v + staticsubnet[1] +";"; resp += ds + "S1" + v + staticSubnet[1] +";";
resp += ds + "CSSN2" + v + staticsubnet[2] +";"; resp += ds + "S2" + v + staticSubnet[2] +";";
resp += ds + "CSSN3" + v + staticsubnet[3] +";"; resp += ds + "S3" + v + staticSubnet[3] +";";
resp += ds + "CMDNS" + v + "\"" + cmdns + "\";"; resp += ds + "CM" + v + "\"" + cmDNS + "\";";
resp += ds + "APWTM" + v + apWaitTimeSecs +";"; resp += ds + "AT" + v + apWaitTimeSecs +";";
resp += ds + "APSSID" + v + "\"" + apssid + "\";"; resp += ds + "AS" + v + "\"" + apSSID + "\";";
resp += ds + "APHSSID" + c + aphide + ";"; resp += ds + "AH" + c + apHide + ";";
resp += ds + "APPASS" + v + "\""; resp += ds + "AP" + v + "\"";
for (int i = 0; i < clientpass.length(); i++) for (int i = 0; i < apPass.length(); i++)
{ {
resp += "*"; resp += "*";
} }
resp += "\";"; resp += "\";";
resp += ds + "APCHAN" + v + apchannel +";"; resp += ds + "AC" + v + apChannel +";";
resp += dg + "(\"sip\")[0]" + ih + "\""; resp += dg + "(\"sip\")[0]" + ih + "\"";
if (!WiFi.localIP()[0] == 0) if (!WiFi.localIP()[0] == 0)
{ {
@@ -135,75 +136,118 @@ String getSettings(uint8_t subPage)
} }
if (subPage == 2) { if (subPage == 2) {
resp += ds + "LEDCN" + v + ledcount +";"; resp += ds + "LC" + v + ledCount +";";
resp += ds + "CLDFR" + v + col_s[0] +";"; resp += ds + "CR" + v + colS[0] +";";
resp += ds + "CLDFG" + v + col_s[1] +";"; resp += ds + "CG" + v + colS[1] +";";
resp += ds + "CLDFB" + v + col_s[2] +";"; resp += ds + "CB" + v + colS[2] +";";
resp += ds + "CLDFA" + v + bri_s +";"; resp += ds + "CA" + v + briS +";";
if (useRGBW) { if (useRGBW) {
resp += ds + "CLDFW" + v + white_s +";"; resp += ds + "CW" + v + whiteS +";";
} else { } else {
resp += ds + "CLDFW" + v + "-1;"; resp += ds + "CW" + v + "-1;";
} }
resp += ds + "CSECR" + v + col_sec_s[0] +";"; resp += ds + "SR" + v + colSecS[0] +";";
resp += ds + "CSECG" + v + col_sec_s[1] +";"; resp += ds + "SG" + v + colSecS[1] +";";
resp += ds + "CSECB" + v + col_sec_s[2] +";"; resp += ds + "SB" + v + colSecS[2] +";";
resp += ds + "CSECW" + v + white_s +";"; resp += ds + "SW" + v + whiteSecS +";";
resp += ds + "BOOTN" + c + turnOnAtBoot +";"; resp += ds + "BO" + c + turnOnAtBoot +";";
resp += ds + "BOOTP" + v + bootPreset +";"; resp += ds + "BP" + v + bootPreset +";";
resp += ds + "FXDEF" + v + effectDefault +";"; resp += ds + "FX" + v + effectDefault +";";
resp += ds + "SXDEF" + v + effectSpeedDefault +";"; resp += ds + "SX" + v + effectSpeedDefault +";";
resp += ds + "IXDEF" + v + effectIntensityDefault +";"; resp += ds + "IX" + v + effectIntensityDefault +";";
resp += ds + "GCBRI" + c + useGammaCorrectionBri +";"; resp += ds + "GB" + c + useGammaCorrectionBri +";";
resp += ds + "GCRGB" + c + useGammaCorrectionRGB +";"; resp += ds + "GC" + c + useGammaCorrectionRGB +";";
resp += ds + "TFADE" + c + fadeTransition +";"; resp += ds + "TF" + c + fadeTransition +";";
resp += ds + "TSWEE" + c + sweepTransition +";"; resp += ds + "TS" + c + sweepTransition +";";
resp += ds + "TSDIR" + c + !sweepDirection +";"; resp += ds + "TI" + c + !sweepDirection +";";
resp += ds + "TDLAY" + v + transitionDelay +";"; resp += ds + "TD" + v + transitionDelay +";";
resp += ds + "NRBRI" + v + briMultiplier +";"; resp += ds + "BF" + v + briMultiplier +";";
resp += ds + "TLBRI" + v + nightlightTargetBri +";"; resp += ds + "TB" + v + nightlightTargetBri +";";
resp += ds + "TLDUR" + v + nightlightDelayMins +";"; resp += ds + "TL" + v + nightlightDelayMins +";";
resp += ds + "TLFDE" + c + nightlightFade +";"; resp += ds + "TW" + c + nightlightFade +";";
resp += ds + "OLDEF" + v + overlayDefault +";"; resp += ds + "RV" + c + reverseMode +";";
resp += ds + "WOFFS" + v + arlsOffset +";"; resp += ds + "EI" + c + initLedsLast +";";
resp += ds + "WO" + v + arlsOffset +";";
} }
if (subPage == 3) if (subPage == 3)
{ {
resp += ds + "DESC" + v + "\"" + serverDescription + "\";"; resp += ds + "DS" + v + "\"" + serverDescription + "\";";
resp += ds + "COLMD" + c + useHSBDefault + ";"; resp += ds + "MD" + c + useHSBDefault + ";";
resp += ds + "THEME.selectedIndex=" + String(currentTheme) + ";"; resp += ds + "TH" + si + String(currentTheme) + ";";
for(int i=0;i<6;i++) for(int i=0;i<6;i++)
resp += ds + "CCOL" + i + v + "\"" + cssCol[i] + "\";"; resp += ds + "C" + i + v + "\"" + cssCol[i] + "\";";
resp += ds + "CFONT" + v + "\"" + cssFont + "\";"; resp += ds + "CF" + v + "\"" + cssFont + "\";";
} }
if (subPage == 4) if (subPage == 4)
{ {
resp += ds + "BTNON" + c + buttonEnabled +";"; resp += ds + "BT" + c + buttonEnabled +";";
resp += ds + "NUDPP" + v + udpPort +";"; resp += ds + "UP" + v + udpPort +";";
resp += ds + "NRCBR" + c + receiveNotificationBrightness +";"; resp += ds + "RB" + c + receiveNotificationBrightness +";";
resp += ds + "NRCCL" + c + receiveNotificationColor +";"; resp += ds + "RC" + c + receiveNotificationColor +";";
resp += ds + "NRCFX" + c + receiveNotificationEffects +";"; resp += ds + "RX" + c + receiveNotificationEffects +";";
resp += ds + "NSDIR" + c + notifyDirectDefault +";"; resp += ds + "SD" + c + notifyDirectDefault +";";
resp += ds + "NSBTN" + c + notifyButton +";"; resp += ds + "SB" + c + notifyButton +";";
resp += ds + "ALEXA" + c + alexaEnabled +";"; resp += ds + "SH" + c + notifyHue +";";
resp += ds + "AINVN" + v + "\"" + alexaInvocationName + "\";"; resp += ds + "S2" + c + notifyTwice +";";
resp += ds + "NSALX" + c + alexaNotify +";"; resp += ds + "AL" + c + alexaEnabled +";";
resp += ds + "AI" + v + "\"" + alexaInvocationName + "\";";
resp += ds + "SA" + c + alexaNotify +";";
resp += ds + "H0" + v + hueIP[0] +";";
resp += ds + "H1" + v + hueIP[1] +";";
resp += ds + "H2" + v + hueIP[2] +";";
resp += ds + "H3" + v + hueIP[3] +";";
resp += ds + "HL" + v + huePollLightId +";";
resp += ds + "HI" + v + huePollIntervalMs +";";
resp += ds + "HP" + c + huePollingEnabled +";";
resp += ds + "HO" + c + hueApplyOnOff +";";
resp += ds + "HB" + c + hueApplyBri +";";
resp += ds + "HC" + c + hueApplyColor +";";
resp += dg + "(\"hms\")[0]" + ih + "\"" + hueError + "\";";
} }
if (subPage == 5) if (subPage == 5)
{ {
resp += ds + "NTPON" + c + ntpEnabled +";"; resp += ds + "NT" + c + ntpEnabled +";";
resp += ds + "CF" + c + !useAMPM +";";
resp += ds + "TZ" + si + String(currentTimezone) + ";";
resp += ds + "UO" + v + utcOffsetSecs +";";
resp += dg + "(\"times\")[0]" + ih + "\"" + getTimeString() + "\";"; resp += dg + "(\"times\")[0]" + ih + "\"" + getTimeString() + "\";";
resp += ds + "OL" + si + String(overlayCurrent) + ";";
resp += ds + "O1" + v + overlayMin +";";
resp += ds + "O2" + v + overlayMax +";";
resp += ds + "OM" + v + analogClock12pixel +";";
resp += ds + "OS" + c + analogClockSecondsTrail +";";
resp += ds + "O5" + c + analogClock5MinuteMarks +";";
resp += ds + "CX" + v + "\"" + cronixieDisplay + "\";";
resp += ds + "CB" + c + cronixieBacklight +";";
resp += ds + "CE" + c + countdownMode +";";
resp += ds + "CY" + v + countdownYear +";";
resp += ds + "CI" + v + countdownMonth +";";
resp += ds + "CD" + v + countdownDay +";";
resp += ds + "CH" + v + countdownHour +";";
resp += ds + "CM" + v + countdownMin +";";
resp += ds + "CS" + v + countdownSec +";";
for (int i=1;i<17;i++)
{
resp += ds + "M" + String(i) + v + "\"" + loadMacro(i) + "\";";
}
resp += ds + "MB" + v + macroBoot +";";
resp += ds + "A0" + v + macroAlexaOn +";";
resp += ds + "A1" + v + macroAlexaOff +";";
resp += ds + "MP" + v + macroButton +";";
resp += ds + "ML" + v + macroLongPress +";";
resp += ds + "MC" + v + macroCountdown +";";
resp += ds + "MN" + v + macroNl +";";
} }
if (subPage == 6) if (subPage == 6)
{ {
resp += ds + "NOOTA" + c + otaLock +";"; resp += ds + "NO" + c + otaLock +";";
resp += ds + "OWIFI" + c + wifiLock +";"; resp += ds + "OW" + c + wifiLock +";";
resp += ds + "AROTA" + c + aOtaEnabled +";"; resp += ds + "AO" + c + aOtaEnabled +";";
resp += ds + "NORAP" + c + recoveryAPDisabled +";"; resp += ds + "NA" + c + recoveryAPDisabled +";";
resp += dg + "(\"msg\")[0]" + ih + "\"WLED "+ versionString +" (build " + VERSION + ") OK\";"; resp += dg + "(\"msg\")[0]" + ih + "\"WLED "+ versionString +" (build " + VERSION + ") OK\";";
} }
resp += "}</script>"; resp += "}</script>";

View File

@@ -2,24 +2,18 @@
* Receives client input * Receives client input
*/ */
void _setRandomColor(bool _sec) void _setRandomColor(bool _sec,bool fromButton=false)
{ {
lastRandomIndex = strip.get_random_wheel_index(lastRandomIndex); lastRandomIndex = strip.get_random_wheel_index(lastRandomIndex);
uint32_t _color = strip.color_wheel(lastRandomIndex);
if (_sec){ if (_sec){
white_sec = ((_color >> 24) & 0xFF); colorHStoRGB(lastRandomIndex*256,255,colSec);
col_sec[0] = ((_color >> 16) & 0xFF);
col_sec[1] = ((_color >> 8) & 0xFF);
col_sec[2] = (_color & 0xFF);
} else { } else {
white = ((_color >> 24) & 0xFF); colorHStoRGB(lastRandomIndex*256,255,col);
col[0] = ((_color >> 16) & 0xFF);
col[1] = ((_color >> 8) & 0xFF);
col[2] = (_color & 0xFF);
} }
if (fromButton) colorUpdated(2);
} }
void handleSettingsSet(uint8_t subPage) void handleSettingsSet(byte subPage)
{ {
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec //0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec
if (subPage <1 || subPage >6) return; if (subPage <1 || subPage >6) return;
@@ -27,223 +21,220 @@ void handleSettingsSet(uint8_t subPage)
//WIFI SETTINGS //WIFI SETTINGS
if (subPage == 1) if (subPage == 1)
{ {
if (server.hasArg("CSSID")) clientssid = server.arg("CSSID"); if (server.hasArg("CS")) clientSSID = server.arg("CS");
if (server.hasArg("CPASS")) if (server.hasArg("CP"))
{ {
if (!server.arg("CPASS").indexOf('*') == 0) if (!server.arg("CP").indexOf('*') == 0)
{ {
DEBUG_PRINTLN("Setting pass"); DEBUG_PRINTLN("Setting pass");
clientpass = server.arg("CPASS"); clientPass = server.arg("CP");
} }
} }
if (server.hasArg("CMDNS")) cmdns = server.arg("CMDNS"); if (server.hasArg("CM")) cmDNS = server.arg("CM");
if (server.hasArg("APWTM")) if (server.hasArg("AT"))
{ {
int i = server.arg("APWTM").toInt(); int i = server.arg("AT").toInt();
if (i >= 0 && i <= 255) apWaitTimeSecs = i; if (i >= 0 && i <= 255) apWaitTimeSecs = i;
} }
if (server.hasArg("APSSID")) apssid = server.arg("APSSID"); if (server.hasArg("AS")) apSSID = server.arg("AS");
aphide = server.hasArg("APHSSID"); apHide = server.hasArg("AH");
if (server.hasArg("APPASS")) if (server.hasArg("AP"))
{ {
if (!server.arg("APPASS").indexOf('*') == 0) appass = server.arg("APPASS"); if (!server.arg("AP").indexOf('*') == 0) apPass = server.arg("AP");
} }
if (server.hasArg("APCHAN")) if (server.hasArg("AC"))
{ {
int chan = server.arg("APCHAN").toInt(); int chan = server.arg("AC").toInt();
if (chan > 0 && chan < 14) apchannel = chan; if (chan > 0 && chan < 14) apChannel = chan;
} }
if (server.hasArg("CSIP0")) if (server.hasArg("I0"))
{ {
int i = server.arg("CSIP0").toInt(); int i = server.arg("I0").toInt();
if (i >= 0 && i <= 255) staticip[0] = i; if (i >= 0 && i <= 255) staticIP[0] = i;
} }
if (server.hasArg("CSIP1")) if (server.hasArg("I1"))
{ {
int i = server.arg("CSIP1").toInt(); int i = server.arg("I1").toInt();
if (i >= 0 && i <= 255) staticip[1] = i; if (i >= 0 && i <= 255) staticIP[1] = i;
} }
if (server.hasArg("CSIP2")) if (server.hasArg("I2"))
{ {
int i = server.arg("CSIP2").toInt(); int i = server.arg("I2").toInt();
if (i >= 0 && i <= 255) staticip[2] = i; if (i >= 0 && i <= 255) staticIP[2] = i;
} }
if (server.hasArg("CSIP3")) if (server.hasArg("I3"))
{ {
int i = server.arg("CSIP3").toInt(); int i = server.arg("I3").toInt();
if (i >= 0 && i <= 255) staticip[3] = i; if (i >= 0 && i <= 255) staticIP[3] = i;
} }
if (server.hasArg("CSGW0")) if (server.hasArg("G0"))
{ {
int i = server.arg("CSGW0").toInt(); int i = server.arg("G0").toInt();
if (i >= 0 && i <= 255) staticgateway[0] = i; if (i >= 0 && i <= 255) staticGateway[0] = i;
} }
if (server.hasArg("CSGW1")) if (server.hasArg("G1"))
{ {
int i = server.arg("CSGW1").toInt(); int i = server.arg("G1").toInt();
if (i >= 0 && i <= 255) staticgateway[1] = i; if (i >= 0 && i <= 255) staticGateway[1] = i;
} }
if (server.hasArg("CSGW2")) if (server.hasArg("G2"))
{ {
int i = server.arg("CSGW2").toInt(); int i = server.arg("G2").toInt();
if (i >= 0 && i <= 255) staticgateway[2] = i; if (i >= 0 && i <= 255) staticGateway[2] = i;
} }
if (server.hasArg("CSGW3")) if (server.hasArg("G3"))
{ {
int i = server.arg("CSGW3").toInt(); int i = server.arg("G3").toInt();
if (i >= 0 && i <= 255) staticgateway[3] = i; if (i >= 0 && i <= 255) staticGateway[3] = i;
} }
if (server.hasArg("CSSN0")) if (server.hasArg("S0"))
{ {
int i = server.arg("CSSN0").toInt(); int i = server.arg("S0").toInt();
if (i >= 0 && i <= 255) staticsubnet[0] = i; if (i >= 0 && i <= 255) staticSubnet[0] = i;
} }
if (server.hasArg("CSSN1")) if (server.hasArg("S1"))
{ {
int i = server.arg("CSSN1").toInt(); int i = server.arg("S1").toInt();
if (i >= 0 && i <= 255) staticsubnet[1] = i; if (i >= 0 && i <= 255) staticSubnet[1] = i;
} }
if (server.hasArg("CSSN2")) if (server.hasArg("S2"))
{ {
int i = server.arg("CSSN2").toInt(); int i = server.arg("S2").toInt();
if (i >= 0 && i <= 255) staticsubnet[2] = i; if (i >= 0 && i <= 255) staticSubnet[2] = i;
} }
if (server.hasArg("CSSN3")) if (server.hasArg("S3"))
{ {
int i = server.arg("CSSN3").toInt(); int i = server.arg("S3").toInt();
if (i >= 0 && i <= 255) staticsubnet[3] = i; if (i >= 0 && i <= 255) staticSubnet[3] = i;
} }
} }
//LED SETTINGS //LED SETTINGS
if (subPage == 2) if (subPage == 2)
{ {
if (server.hasArg("LEDCN")) if (server.hasArg("LC"))
{ {
int i = server.arg("LEDCN").toInt(); int i = server.arg("LC").toInt();
if (i >= 0 && i <= LEDCOUNT) ledcount = i; if (i >= 0 && i <= LEDCOUNT) ledCount = i;
strip.setLedCount(ledcount); strip.setLedCount(ledCount);
} }
if (server.hasArg("CBEOR")) //ignore settings and save current brightness, colors and fx as default if (server.hasArg("IS")) //ignore settings and save current brightness, colors and fx as default
{ {
col_s[0] = col[0]; colS[0] = col[0];
col_s[1] = col[1]; colS[1] = col[1];
col_s[2] = col[2]; colS[2] = col[2];
if (useRGBW) white_s = white; if (useRGBW) whiteS = white;
bri_s = bri; briS = bri;
effectDefault = effectCurrent; effectDefault = effectCurrent;
effectSpeedDefault = effectSpeed; effectSpeedDefault = effectSpeed;
} else { } else {
if (server.hasArg("CLDFR")) if (server.hasArg("CR"))
{ {
int i = server.arg("CLDFR").toInt(); int i = server.arg("CR").toInt();
if (i >= 0 && i <= 255) col_s[0] = i; if (i >= 0 && i <= 255) colS[0] = i;
} }
if (server.hasArg("CLDFG")) if (server.hasArg("CG"))
{ {
int i = server.arg("CLDFG").toInt(); int i = server.arg("CG").toInt();
if (i >= 0 && i <= 255) col_s[1] = i; if (i >= 0 && i <= 255) colS[1] = i;
} }
if (server.hasArg("CLDFB")) if (server.hasArg("CB"))
{ {
int i = server.arg("CLDFB").toInt(); int i = server.arg("CB").toInt();
if (i >= 0 && i <= 255) col_s[2] = i; if (i >= 0 && i <= 255) colS[2] = i;
} }
if (server.hasArg("CSECR")) if (server.hasArg("SR"))
{ {
int i = server.arg("CSECR").toInt(); int i = server.arg("SR").toInt();
if (i >= 0 && i <= 255) col_sec_s[0] = i; if (i >= 0 && i <= 255) colSecS[0] = i;
} }
if (server.hasArg("CSECG")) if (server.hasArg("SG"))
{ {
int i = server.arg("CSECG").toInt(); int i = server.arg("SG").toInt();
if (i >= 0 && i <= 255) col_sec_s[1] = i; if (i >= 0 && i <= 255) colSecS[1] = i;
} }
if (server.hasArg("CSECB")) if (server.hasArg("SB"))
{ {
int i = server.arg("CSECB").toInt(); int i = server.arg("SB").toInt();
if (i >= 0 && i <= 255) col_sec_s[2] = i; if (i >= 0 && i <= 255) colSecS[2] = i;
} }
if (server.hasArg("CSECW")) if (server.hasArg("SW"))
{ {
int i = server.arg("CSECW").toInt(); int i = server.arg("SW").toInt();
if (i >= 0 && i <= 255) white_sec_s = i; if (i >= 0 && i <= 255) whiteSecS = i;
} }
if (server.hasArg("CLDFW")) if (server.hasArg("CW"))
{ {
int i = server.arg("CLDFW").toInt(); int i = server.arg("CW").toInt();
if (i >= 0 && i <= 255) if (i >= 0 && i <= 255)
{ {
useRGBW = true; useRGBW = true;
white_s = i; whiteS = i;
} else { } else {
useRGBW = false; useRGBW = false;
white_s = 0; whiteS = 0;
} }
} }
if (server.hasArg("CLDFA")) if (server.hasArg("CA"))
{ {
int i = server.arg("CLDFA").toInt(); int i = server.arg("CA").toInt();
if (i >= 0 && i <= 255) bri_s = i; if (i >= 0 && i <= 255) briS = i;
} }
if (server.hasArg("FXDEF")) if (server.hasArg("FX"))
{ {
int i = server.arg("FXDEF").toInt(); int i = server.arg("FX").toInt();
if (i >= 0 && i <= 255) effectDefault = i; if (i >= 0 && i <= 255) effectDefault = i;
} }
if (server.hasArg("SXDEF")) if (server.hasArg("SX"))
{ {
int i = server.arg("SXDEF").toInt(); int i = server.arg("SX").toInt();
if (i >= 0 && i <= 255) effectSpeedDefault = i; if (i >= 0 && i <= 255) effectSpeedDefault = i;
} }
if (server.hasArg("IXDEF")) if (server.hasArg("IX"))
{ {
int i = server.arg("IXDEF").toInt(); int i = server.arg("IX").toInt();
if (i >= 0 && i <= 255) effectIntensityDefault = i; if (i >= 0 && i <= 255) effectIntensityDefault = i;
} }
} }
turnOnAtBoot = server.hasArg("BOOTN"); turnOnAtBoot = server.hasArg("BO");
if (server.hasArg("BOOTP")) if (server.hasArg("BP"))
{ {
int i = server.arg("BOOTP").toInt(); int i = server.arg("BP").toInt();
if (i >= 0 && i <= 25) bootPreset = i; if (i >= 0 && i <= 25) bootPreset = i;
} }
useGammaCorrectionBri = server.hasArg("GCBRI"); useGammaCorrectionBri = server.hasArg("GB");
useGammaCorrectionRGB = server.hasArg("GCRGB"); useGammaCorrectionRGB = server.hasArg("GC");
fadeTransition = server.hasArg("TFADE"); fadeTransition = server.hasArg("TF");
sweepTransition = server.hasArg("TSWEE"); sweepTransition = server.hasArg("TS");
sweepDirection = !server.hasArg("TSDIR"); sweepDirection = !server.hasArg("TI");
if (server.hasArg("TDLAY")) if (server.hasArg("TD"))
{ {
int i = server.arg("TDLAY").toInt(); int i = server.arg("TD").toInt();
if (i > 0){ if (i > 0){
transitionDelay = i; transitionDelay = i;
} }
} }
if (server.hasArg("TLBRI")) if (server.hasArg("TB"))
{ {
nightlightTargetBri = server.arg("TLBRI").toInt(); nightlightTargetBri = server.arg("TB").toInt();
} }
if (server.hasArg("TLDUR")) if (server.hasArg("TL"))
{ {
int i = server.arg("TLDUR").toInt(); int i = server.arg("TL").toInt();
if (i > 0) nightlightDelayMins = i; if (i > 0) nightlightDelayMins = i;
} }
nightlightFade = server.hasArg("TLFDE"); nightlightFade = server.hasArg("TW");
if (server.hasArg("OLDEF")) reverseMode = server.hasArg("RV");
initLedsLast = server.hasArg("EI");
strip.setReverseMode(reverseMode);
if (server.hasArg("WO"))
{ {
int i = server.arg("OLDEF").toInt(); int i = server.arg("WO").toInt();
if (i >= 0 && i <= 255) overlayDefault = i;
}
if (server.hasArg("WOFFS"))
{
int i = server.arg("WOFFS").toInt();
if (i >= -255 && i <= 255) arlsOffset = i; if (i >= -255 && i <= 255) arlsOffset = i;
arlsSign = (i>=0)?true:false;
} }
if (server.hasArg("NRBRI")) if (server.hasArg("BF"))
{ {
int i = server.arg("NRBRI").toInt(); int i = server.arg("BF").toInt();
if (i > 0) briMultiplier = i; if (i > 0) briMultiplier = i;
} }
} }
@@ -251,49 +242,120 @@ void handleSettingsSet(uint8_t subPage)
//UI //UI
if (subPage == 3) if (subPage == 3)
{ {
if (server.hasArg("DESC")) serverDescription = server.arg("DESC"); if (server.hasArg("DS")) serverDescription = server.arg("DS");
useHSBDefault = server.hasArg("COLMD"); useHSBDefault = server.hasArg("MD");
useHSB = useHSBDefault; useHSB = useHSBDefault;
if (server.hasArg("THEME")) currentTheme = server.arg("THEME").toInt(); if (server.hasArg("TH")) currentTheme = server.arg("TH").toInt();
for(int i=0;i<6;i++) for(int i=0;i<6;i++)
{ {
if (server.hasArg("CCOL"+String(i))) cssCol[i] = server.arg("CCOL"+String(i)); if (server.hasArg("C"+String(i))) cssCol[i] = server.arg("C"+String(i));
} }
if (server.hasArg("CFONT")) cssFont = server.arg("CFONT"); if (server.hasArg("CF")) cssFont = server.arg("CF");
buildCssColorString(); buildCssColorString();
} }
//SYNC //SYNC
if (subPage == 4) if (subPage == 4)
{ {
buttonEnabled = server.hasArg("BTNON"); buttonEnabled = server.hasArg("BT");
if (server.hasArg("NUDPP")) if (server.hasArg("UP"))
{ {
udpPort = server.arg("NUDPP").toInt(); udpPort = server.arg("UP").toInt();
} }
receiveNotificationBrightness = server.hasArg("NRCBR"); receiveNotificationBrightness = server.hasArg("RB");
receiveNotificationColor = server.hasArg("NRCCL"); receiveNotificationColor = server.hasArg("RC");
receiveNotificationEffects = server.hasArg("NRCFX"); receiveNotificationEffects = server.hasArg("RX");
receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects); receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
notifyDirectDefault = server.hasArg("NSDIR"); notifyDirectDefault = server.hasArg("SD");
notifyDirect = notifyDirectDefault; notifyDirect = notifyDirectDefault;
notifyButton = server.hasArg("NSBTN"); notifyButton = server.hasArg("SB");
alexaEnabled = server.hasArg("ALEXA"); notifyTwice = server.hasArg("S2");
if (server.hasArg("AINVN")) alexaInvocationName = server.arg("AINVN"); alexaEnabled = server.hasArg("AL");
alexaNotify = server.hasArg("NSALX"); if (server.hasArg("AI")) alexaInvocationName = server.arg("AI");
alexaNotify = server.hasArg("SA");
notifyHue = server.hasArg("SH");
for (int i=0;i<4;i++){
String a = "H"+String(i);
if (server.hasArg(a))
hueIP[i] = server.arg(a).toInt();
}
if (server.hasArg("HL"))
{
int i = server.arg("HL").toInt();
if (i > 0) huePollLightId = i;
}
if (server.hasArg("HI"))
{
int i = server.arg("HI").toInt();
if (i > 50) huePollIntervalMs = i;
}
hueApplyOnOff = server.hasArg("HO");
hueApplyBri = server.hasArg("HB");
hueApplyColor = server.hasArg("HC");
if (server.hasArg("HP"))
{
if (!huePollingEnabled) hueAttempt = true;
if (!setupHue()) hueAttempt = true;
} else
{
huePollingEnabled = false;
hueError = "Inactive";
}
} }
//TIME //TIME
if (subPage == 5) if (subPage == 5)
{ {
ntpEnabled = server.hasArg("NTPON"); ntpEnabled = server.hasArg("NT");
useAMPM = !server.hasArg("CF");
if (server.hasArg("TZ")) currentTimezone = server.arg("TZ").toInt();
if (server.hasArg("UO")) utcOffsetSecs = server.arg("UO").toInt();
if (ntpEnabled && WiFi.status() == WL_CONNECTED && !ntpConnected) ntpConnected = ntpUdp.begin(ntpLocalPort); //start if not already connected if (ntpEnabled && WiFi.status() == WL_CONNECTED && !ntpConnected) ntpConnected = ntpUdp.begin(ntpLocalPort); //start if not already connected
if (server.hasArg("OL")){
overlayDefault = server.arg("OL").toInt();
overlayCurrent = overlayDefault;
strip.unlockAll();
}
if (server.hasArg("O1")) overlayMin = server.arg("O1").toInt();
if (server.hasArg("O2")) overlayMax = server.arg("O2").toInt();
if (server.hasArg("OM")) analogClock12pixel = server.arg("OM").toInt();
analogClock5MinuteMarks = server.hasArg("O5");
analogClockSecondsTrail = server.hasArg("OS");
if (server.hasArg("CX")) cronixieDisplay = server.arg("CX");
bool cbOld = cronixieBacklight;
cronixieBacklight = server.hasArg("CB");
if (cbOld != cronixieBacklight && overlayCurrent == 4)
{
strip.setCronixieBacklight(cronixieBacklight); overlayRefreshedTime = 0;
}
countdownMode = server.hasArg("CE");
if (server.hasArg("CY")) countdownYear = server.arg("CY").toInt();
if (server.hasArg("CI")) countdownMonth = server.arg("CI").toInt();
if (server.hasArg("CD")) countdownDay = server.arg("CD").toInt();
if (server.hasArg("CH")) countdownHour = server.arg("CH").toInt();
if (server.hasArg("CM")) countdownMin = server.arg("CM").toInt();
if (server.hasArg("CS")) countdownSec = server.arg("CS").toInt();
for (int i=1;i<17;i++)
{
String a = "M"+String(i);
if (server.hasArg(a)) saveMacro(i,server.arg(a),false);
}
if (server.hasArg("MB")) macroBoot = server.arg("MB").toInt();
if (server.hasArg("A0")) macroAlexaOn = server.arg("A0").toInt();
if (server.hasArg("A1")) macroAlexaOff = server.arg("A1").toInt();
if (server.hasArg("MP")) macroButton = server.arg("MP").toInt();
if (server.hasArg("ML")) macroLongPress = server.arg("ML").toInt();
if (server.hasArg("MC")) macroCountdown = server.arg("MC").toInt();
if (server.hasArg("MN")) macroNl = server.arg("MN").toInt();
} }
//SECURITY //SECURITY
if (subPage == 6) if (subPage == 6)
{ {
if (server.hasArg("RESET")) if (server.hasArg("RS"))
{ {
clearEEPROM(); clearEEPROM();
serveMessage(200, "All Settings erased.", "Connect to WLED-AP to setup again...",255); serveMessage(200, "All Settings erased.", "Connect to WLED-AP to setup again...",255);
@@ -301,33 +363,33 @@ void handleSettingsSet(uint8_t subPage)
} }
bool pwdCorrect = !otaLock; //always allow access if ota not locked bool pwdCorrect = !otaLock; //always allow access if ota not locked
if (server.hasArg("OPASS")) if (server.hasArg("OP"))
{ {
if (otaLock && otapass.equals(server.arg("OPASS"))) if (otaLock && otaPass.equals(server.arg("OP")))
{ {
pwdCorrect = true; pwdCorrect = true;
} }
if (!otaLock && server.arg("OPASS").length() > 0) if (!otaLock && server.arg("OP").length() > 0)
{ {
otapass = server.arg("OPASS"); otaPass = server.arg("OP");
} }
} }
if (pwdCorrect) //allow changes if correct pwd or no ota active if (pwdCorrect) //allow changes if correct pwd or no ota active
{ {
otaLock = server.hasArg("NOOTA"); otaLock = server.hasArg("NO");
wifiLock = server.hasArg("OWIFI"); wifiLock = server.hasArg("OW");
recoveryAPDisabled = server.hasArg("NORAP"); recoveryAPDisabled = server.hasArg("NA");
aOtaEnabled = server.hasArg("AROTA"); aOtaEnabled = server.hasArg("AO");
} }
} }
saveSettingsToEEPROM(); saveSettingsToEEPROM();
} }
boolean handleSet(String req) bool handleSet(String req)
{ {
boolean effectUpdated = false; bool effectUpdated = false;
if (!(req.indexOf("win") >= 0)) { if (!(req.indexOf("win") >= 0)) {
return false; return false;
} }
@@ -358,6 +420,19 @@ boolean handleSet(String req)
if (pos > 0) { if (pos > 0) {
bri = req.substring(pos + 3).toInt(); bri = req.substring(pos + 3).toInt();
} }
//set hue
pos = req.indexOf("HU=");
if (pos > 0) {
uint16_t temphue = req.substring(pos + 3).toInt();
byte tempsat = 255;
pos = req.indexOf("SA=");
if (pos > 0) {
tempsat = req.substring(pos + 3).toInt();
}
colorHStoRGB(temphue,tempsat,(req.indexOf("H2")>0)? colSec:col);
}
//set red value //set red value
pos = req.indexOf("&R="); pos = req.indexOf("&R=");
if (pos > 0) { if (pos > 0) {
@@ -382,45 +457,45 @@ boolean handleSet(String req)
//set 2nd red value //set 2nd red value
pos = req.indexOf("R2="); pos = req.indexOf("R2=");
if (pos > 0) { if (pos > 0) {
col_sec[0] = req.substring(pos + 3).toInt(); colSec[0] = req.substring(pos + 3).toInt();
} }
//set 2nd green value //set 2nd green value
pos = req.indexOf("G2="); pos = req.indexOf("G2=");
if (pos > 0) { if (pos > 0) {
col_sec[1] = req.substring(pos + 3).toInt(); colSec[1] = req.substring(pos + 3).toInt();
} }
//set 2nd blue value //set 2nd blue value
pos = req.indexOf("B2="); pos = req.indexOf("B2=");
if (pos > 0) { if (pos > 0) {
col_sec[2] = req.substring(pos + 3).toInt(); colSec[2] = req.substring(pos + 3).toInt();
} }
//set 2nd white value //set 2nd white value
pos = req.indexOf("W2="); pos = req.indexOf("W2=");
if (pos > 0) { if (pos > 0) {
white_sec = req.substring(pos + 3).toInt(); whiteSec = req.substring(pos + 3).toInt();
} }
//set 2nd to white //set 2nd to white
pos = req.indexOf("SW"); pos = req.indexOf("SW");
if (pos > 0) { if (pos > 0) {
if(useRGBW) { if(useRGBW) {
white_sec = 255; whiteSec = 255;
col_sec[0] = 0; colSec[0] = 0;
col_sec[1] = 0; colSec[1] = 0;
col_sec[2] = 0; colSec[2] = 0;
} else { } else {
col_sec[0] = 255; colSec[0] = 255;
col_sec[1] = 255; colSec[1] = 255;
col_sec[2] = 255; colSec[2] = 255;
} }
} }
//set 2nd to black //set 2nd to black
pos = req.indexOf("SB"); pos = req.indexOf("SB");
if (pos > 0) { if (pos > 0) {
white_sec = 0; whiteSec = 0;
col_sec[0] = 0; colSec[0] = 0;
col_sec[1] = 0; colSec[1] = 0;
col_sec[2] = 0; colSec[2] = 0;
} }
//set to random hue SR=0->1st SR=1->2nd //set to random hue SR=0->1st SR=1->2nd
pos = req.indexOf("SR"); pos = req.indexOf("SR");
@@ -430,24 +505,24 @@ boolean handleSet(String req)
//set 2nd to 1st //set 2nd to 1st
pos = req.indexOf("SP"); pos = req.indexOf("SP");
if (pos > 0) { if (pos > 0) {
col_sec[0] = col[0]; colSec[0] = col[0];
col_sec[1] = col[1]; colSec[1] = col[1];
col_sec[2] = col[2]; colSec[2] = col[2];
white_sec = white; whiteSec = white;
} }
//swap 2nd & 1st //swap 2nd & 1st
pos = req.indexOf("SC"); pos = req.indexOf("SC");
if (pos > 0) { if (pos > 0) {
uint8_t _temp[4]; byte _temp[4];
for (int i = 0; i<3; i++) for (int i = 0; i<3; i++)
{ {
_temp[i] = col[i]; _temp[i] = col[i];
col[i] = col_sec[i]; col[i] = colSec[i];
col_sec[i] = _temp[i]; colSec[i] = _temp[i];
} }
_temp[3] = white; _temp[3] = white;
white = white_sec; white = whiteSec;
white_sec = _temp[3]; whiteSec = _temp[3];
} }
//set current effect index //set current effect index
@@ -480,6 +555,19 @@ boolean handleSet(String req)
effectUpdated = true; effectUpdated = true;
} }
} }
//set hue polling light: 0 -off
pos = req.indexOf("HP=");
if (pos > 0) {
int id = req.substring(pos + 3).toInt();
if (id > 0)
{
if (id < 100) huePollLightId = id;
setupHue();
} else {
huePollingEnabled = false;
}
}
//set default control mode (0 - RGB, 1 - HSB) //set default control mode (0 - RGB, 1 - HSB)
pos = req.indexOf("MD="); pos = req.indexOf("MD=");
@@ -560,7 +648,7 @@ boolean handleSet(String req)
if (req.indexOf("NL=0") > 0) if (req.indexOf("NL=0") > 0)
{ {
nightlightActive = false; nightlightActive = false;
bri = bri_t; bri = briT;
} else { } else {
nightlightActive = true; nightlightActive = true;
nightlightDelayMins = req.substring(pos + 3).toInt(); nightlightDelayMins = req.substring(pos + 3).toInt();
@@ -571,7 +659,7 @@ boolean handleSet(String req)
pos = req.indexOf("NT="); pos = req.indexOf("NT=");
if (pos > 0) { if (pos > 0) {
nightlightTargetBri = req.substring(pos + 3).toInt(); nightlightTargetBri = req.substring(pos + 3).toInt();
nightlightActive_old = false; //re-init nightlightActiveOld = false; //re-init
} }
//toggle nightlight fade //toggle nightlight fade
if (req.indexOf("NF=") > 0) if (req.indexOf("NF=") > 0)
@@ -582,7 +670,7 @@ boolean handleSet(String req)
} else { } else {
nightlightFade = true; nightlightFade = true;
} }
nightlightActive_old = false; //re-init nightlightActiveOld = false; //re-init
} }
//toggle general purpose output //toggle general purpose output
pos = req.indexOf("AX="); pos = req.indexOf("AX=");
@@ -596,14 +684,14 @@ boolean handleSet(String req)
if (pos > 0) { if (pos > 0) {
switch (req.substring(pos + 3).toInt()) switch (req.substring(pos + 3).toInt())
{ {
case 0: if (bri != 0){bri_last = bri; bri = 0;} break; //off case 0: if (bri != 0){briLast = bri; bri = 0;} break; //off
case 1: bri = bri_last; break; //on case 1: bri = briLast; break; //on
default: if (bri == 0) //toggle default: if (bri == 0) //toggle
{ {
bri = bri_last; bri = briLast;
} else } else
{ {
bri_last = bri; briLast = bri;
bri = 0; bri = 0;
} }
} }
@@ -622,15 +710,15 @@ boolean handleSet(String req)
//set custom chase data //set custom chase data
bool _cc_updated = false; bool _cc_updated = false;
pos = req.indexOf("C0="); if (pos > 0) {cc_start = (req.substring(pos + 3).toInt()); _cc_updated = true;} pos = req.indexOf("C0="); if (pos > 0) {ccStart = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("C1="); if (pos > 0) {cc_index1 = (req.substring(pos + 3).toInt()); _cc_updated = true;} pos = req.indexOf("C1="); if (pos > 0) {ccIndex1 = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("C2="); if (pos > 0) {cc_index2 = (req.substring(pos + 3).toInt()); _cc_updated = true;} pos = req.indexOf("C2="); if (pos > 0) {ccIndex2 = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CP="); if (pos > 0) {cc_numPrimary = (req.substring(pos + 3).toInt()); _cc_updated = true;} pos = req.indexOf("CP="); if (pos > 0) {ccNumPrimary = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CS="); if (pos > 0) {cc_numSecondary = (req.substring(pos + 3).toInt()); _cc_updated = true;} pos = req.indexOf("CS="); if (pos > 0) {ccNumSecondary = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CM="); if (pos > 0) {cc_step = (req.substring(pos + 3).toInt()); _cc_updated = true;} pos = req.indexOf("CM="); if (pos > 0) {ccStep = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CF="); if (pos > 0) {cc_fromStart = (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) {cc_fromEnd = (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 (_cc_updated) strip.setCustomChase(cc_index1, cc_index2, cc_start, cc_numPrimary, cc_numSecondary, cc_step, cc_fromStart, cc_fromEnd); if (_cc_updated) strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd);
//set presets //set presets
pos = req.indexOf("PS="); //saves current in preset pos = req.indexOf("PS="); //saves current in preset
@@ -655,17 +743,19 @@ boolean handleSet(String req)
applyPreset(req.substring(pos + 3).toInt(), false, false, true); applyPreset(req.substring(pos + 3).toInt(), false, false, true);
effectUpdated = true; effectUpdated = true;
} }
#ifdef CRONIXIE
//cronixie
pos = req.indexOf("NX="); //sets digits to code pos = req.indexOf("NX="); //sets digits to code
if (pos > 0) { if (pos > 0) {
setCronixie(req.substring(pos + 3, pos + 9).c_str()); cronixieDisplay = req.substring(pos + 3, pos + 9);
setCronixie();
} }
pos = req.indexOf("NM="); //mode, 1 countdown pos = req.indexOf("NM="); //mode, 1 countdown
if (pos > 0) { if (pos > 0) {
cronixieCountdown = true; countdownMode = true;
if (req.indexOf("NM=0") > 0) if (req.indexOf("NM=0") > 0)
{ {
cronixieCountdown = false; countdownMode = false;
} }
} }
if (req.indexOf("NB=") > 0) //sets backlight if (req.indexOf("NB=") > 0) //sets backlight
@@ -675,10 +765,10 @@ boolean handleSet(String req)
{ {
cronixieBacklight = false; cronixieBacklight = false;
} }
strip.setCronixieBacklight(cronixieBacklight); if (overlayCurrent == 4) strip.setCronixieBacklight(cronixieBacklight);
cronixieRefreshedTime = 0; overlayRefreshedTime = 0;
} }
#endif
//internal call, does not send XML response //internal call, does not send XML response
pos = req.indexOf("IN"); pos = req.indexOf("IN");
if (pos < 1) XML_response(); if (pos < 1) XML_response();

View File

@@ -4,44 +4,37 @@
void wledInit() void wledInit()
{ {
EEPROM.begin(EEPSIZE);
if (!EEPROM.read(397)) strip.init(); //quick init
Serial.begin(115200); Serial.begin(115200);
#ifdef USEFS #ifdef USEFS
SPIFFS.begin(); SPIFFS.begin();
{
Dir dir = SPIFFS.openDir("/");
while (dir.next()) {
String fileName = dir.fileName();
size_t fileSize = dir.fileSize();
#ifdef DEBUG
Serial.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str());
#endif
}
DEBUG_PRINTF("\n");
}
#endif #endif
DEBUG_PRINTLN("Init EEPROM"); DEBUG_PRINTLN("Load EEPROM");
EEPROM.begin(EEPSIZE);
loadSettingsFromEEPROM(true); loadSettingsFromEEPROM(true);
DEBUG_PRINT("CC: SSID: "); if (!initLedsLast) initStrip();
DEBUG_PRINT(clientssid); DEBUG_PRINT("C-SSID: ");
DEBUG_PRINT(clientSSID);
buildCssColorString(); buildCssColorString();
userBeginPreConnection();
WiFi.disconnect(); //close old connections WiFi.disconnect(); //close old connections
if (staticip[0] != 0) if (staticIP[0] != 0)
{ {
WiFi.config(staticip, staticgateway, staticsubnet, staticdns); WiFi.config(staticIP, staticGateway, staticSubnet, staticDNS);
} else } else
{ {
WiFi.config(0U, 0U, 0U); WiFi.config(0U, 0U, 0U);
} }
if (apssid.length()>0) if (apSSID.length()>0)
{ {
DEBUG_PRINT("USING AP"); DEBUG_PRINT("USING AP");
DEBUG_PRINTLN(apssid.length()); DEBUG_PRINTLN(apSSID.length());
initAP(); initAP();
} else } else
{ {
@@ -54,9 +47,16 @@ void wledInit()
DEBUG_PRINTLN(""); DEBUG_PRINTLN("");
DEBUG_PRINT("Connected! IP address: "); DEBUG_PRINT("Connected! IP address: ");
DEBUG_PRINTLN(WiFi.localIP()); DEBUG_PRINTLN(WiFi.localIP());
if (hueIP[0] == 0)
{
hueIP[0] = WiFi.localIP()[0];
hueIP[1] = WiFi.localIP()[1];
hueIP[2] = WiFi.localIP()[2];
}
// Set up mDNS responder: // Set up mDNS responder:
if (cmdns != NULL && !onlyAP && !MDNS.begin(cmdns.c_str())) { if (cmDNS != NULL && !onlyAP && !MDNS.begin(cmDNS.c_str())) {
DEBUG_PRINTLN("Error setting up MDNS responder!"); DEBUG_PRINTLN("Error setting up MDNS responder!");
down(); down();
} }
@@ -69,6 +69,14 @@ void wledInit()
if (ntpEnabled && WiFi.status() == WL_CONNECTED) if (ntpEnabled && WiFi.status() == WL_CONNECTED)
ntpConnected = ntpUdp.begin(ntpLocalPort); ntpConnected = ntpUdp.begin(ntpLocalPort);
//start captive portal
if (onlyAP || apSSID.length() > 0)
{
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
dnsServer.start(53, "*", WiFi.softAPIP());
dnsActive = true;
}
//SERVER INIT //SERVER INIT
//settings page //settings page
server.on("/settings", HTTP_GET, [](){ server.on("/settings", HTTP_GET, [](){
@@ -106,15 +114,15 @@ void wledInit()
}); });
server.on("/", HTTP_GET, [](){ server.on("/", HTTP_GET, [](){
if (!showWelcomePage){ serveIndexOrWelcome();
if(!handleFileRead("/index.htm")) { });
serveIndex();
} server.on("/generate_204", HTTP_GET, [](){
}else{ serveIndexOrWelcome();
if(!handleFileRead("/welcome.htm")) { });
serveSettings(255);
} server.on("/fwlink", HTTP_GET, [](){
} serveIndexOrWelcome();
}); });
server.on("/sliders", HTTP_GET, serveIndex); server.on("/sliders", HTTP_GET, serveIndex);
@@ -124,7 +132,7 @@ void wledInit()
}); });
server.on("/reset", HTTP_GET, [](){ server.on("/reset", HTTP_GET, [](){
serveMessage(200,"Rebooting now...","(takes ~20 seconds, wait for auto-redirect)",139); serveMessage(200,"Rebooting now...","(takes ~20 seconds, wait for auto-redirect)",79);
reset(); reset();
}); });
@@ -146,7 +154,13 @@ void wledInit()
server.on("/settings/sync", HTTP_POST, [](){ server.on("/settings/sync", HTTP_POST, [](){
handleSettingsSet(4); handleSettingsSet(4);
serveMessage(200,"Sync settings saved.","Redirecting...",1); if (hueAttempt)
{
serveMessage(200,"Hue setup result",hueError,253);
} else {
serveMessage(200,"Sync settings saved.","Redirecting...",1);
}
hueAttempt = false;
}); });
server.on("/settings/time", HTTP_POST, [](){ server.on("/settings/time", HTTP_POST, [](){
@@ -173,7 +187,7 @@ void wledInit()
}); });
server.on("/power", HTTP_GET, [](){ server.on("/power", HTTP_GET, [](){
String val = (String)(int)strip.getPowerEstimate(ledcount,strip.getColor(),strip.getBrightness()); String val = (String)(int)strip.getPowerEstimate(ledCount,strip.getColor(),strip.getBrightness());
val += "mA currently"; 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); 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);
}); });
@@ -198,16 +212,6 @@ void wledInit()
info += "rgbw: false\r\n"; info += "rgbw: false\r\n";
#endif #endif
info += "max-leds: " + (String)LEDCOUNT + "\r\n"; info += "max-leds: " + (String)LEDCOUNT + "\r\n";
#ifdef USEOVERLAYS
info += "overlays: true\r\n";
#else
info += "overlays: false\r\n";
#endif
#ifdef CRONIXIE
info += "cronixie: true\r\n";
#else
info += "cronixie: false\r\n";
#endif
#ifdef USEFS #ifdef USEFS
info += "spiffs: true\r\n"; info += "spiffs: true\r\n";
#else #else
@@ -289,51 +293,66 @@ void wledInit()
ArduinoOTA.begin(); ArduinoOTA.begin();
} }
// Initialize NeoPixel Strip if (initLedsLast) initStrip();
strip.init(); userBegin();
strip.setLedCount(ledcount); if (macroBoot>0) applyMacro(macroBoot);
}
void initStrip()
{
// Initialize NeoPixel Strip and button
if (initLedsLast) strip.init();
strip.setLedCount(ledCount);
strip.setReverseMode(reverseMode);
strip.setColor(0); strip.setColor(0);
strip.setBrightness(255); strip.setBrightness(255);
strip.start(); strip.start();
pinMode(buttonPin, INPUT_PULLUP); pinMode(buttonPin, INPUT_PULLUP);
#ifdef CRONIXIE
strip.driverModeCronixie(true);
strip.setCronixieBacklight(cronixieBacklight);
setCronixie(cronixieDefault);
#endif
if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true); if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true);
colorUpdated(0); colorUpdated(0);
if(digitalRead(buttonPin) == LOW) buttonEnabled = false; //disable button if it is "pressed" unintentionally if(digitalRead(buttonPin) == LOW) buttonEnabled = false; //disable button if it is "pressed" unintentionally
} }
void initAP(){ void initAP(){
String save = apssid; String save = apSSID;
#ifdef CRONIXIE if (apSSID.length() <1) apSSID = "WLED-AP";
if (apssid.length() <1) apssid = "CRONIXIE-AP"; WiFi.softAP(apSSID.c_str(), apPass.c_str(), apChannel, apHide);
#else apSSID = save;
if (apssid.length() <1) apssid = "WLED-AP";
#endif
WiFi.softAP(apssid.c_str(), appass.c_str(), apchannel, aphide);
apssid = save;
} }
void initCon() void initCon()
{ {
int fail_count = 0; int fail_count = 0;
if (clientssid.length() <1 || clientssid.equals("Your_Network_Here")) fail_count = apWaitTimeSecs*2; if (clientSSID.length() <1 || clientSSID.equals("Your_Network")) fail_count = apWaitTimeSecs*2;
WiFi.begin(clientssid.c_str(), clientpass.c_str()); WiFi.begin(clientSSID.c_str(), clientPass.c_str());
while(WiFi.status() != WL_CONNECTED) { unsigned long lastTry = 0;
delay(500); bool con = false;
DEBUG_PRINTLN("C_NC"); while(!con)
fail_count++; {
if (!recoveryAPDisabled && fail_count > apWaitTimeSecs*2) yield();
if (!initLedsLast)
{ {
WiFi.disconnect(); handleTransitions();
DEBUG_PRINTLN("Can't connect. Opening AP..."); handleButton();
onlyAP = true; handleOverlays();
initAP(); if (briT) strip.service();
return; }
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)
{
WiFi.disconnect();
DEBUG_PRINTLN("Can't connect. Opening AP...");
onlyAP = true;
initAP();
return;
}
fail_count++;
} }
} }
} }
@@ -354,6 +373,7 @@ void buildCssColorString()
case 8: cs[0]="0ac"; cs[1]="124"; cs[2]="224"; cs[3]="003eff"; cs[4]="003eff"; cs[5]="003eff"; break;//air 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 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 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 14: cs[0]="fc7"; cs[1]="49274a"; cs[2]="94618e"; cs[3]="f4decb"; cs[4]="0008"; cs[5]="f4decb"; break; //end 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 case 15: for (int i=0;i<6;i++)cs[i]=cssCol[i];//custom
} }
@@ -374,6 +394,19 @@ void buildCssColorString()
cssColorString+=";}"; cssColorString+=";}";
} }
void serveIndexOrWelcome()
{
if (!showWelcomePage){
if(!handleFileRead("/index.htm")) {
serveIndex();
}
}else{
if(!handleFileRead("/welcome.htm")) {
serveSettings(255);
}
}
}
void serveIndex() void serveIndex()
{ {
if (!arlsTimeout) //do not serve while receiving realtime if (!arlsTimeout) //do not serve while receiving realtime
@@ -421,7 +454,7 @@ void serveMessage(int code, String headl, String subl="", int optionType)
server.sendContent(messageBody); server.sendContent(messageBody);
} }
void serveSettings(uint8_t subPage) void serveSettings(byte subPage)
{ {
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 255: welcomepage //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) //do not serve while receiving realtime

View File

@@ -1,6 +0,0 @@
/*
* foo
*/
String readFromFS(String filename){return "N";};
void writeToFS(String filename, String file) {};

21
wled00/wled06_usermod.ino Normal file
View File

@@ -0,0 +1,21 @@
/*
* This file allows you to add own functionality to WLED more easily
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
* EEPROM bytes 2944 to 3071 are reserved for your custom use case.
*/
void userBeginPreConnection()
{
}
void userBegin()
{
}
void userLoop()
{
}

View File

@@ -4,7 +4,7 @@
#define WLEDPACKETSIZE 24 #define WLEDPACKETSIZE 24
void notify(uint8_t callMode) void notify(byte callMode, bool followUp=false)
{ {
if (!udpConnected) return; if (!udpConnected) return;
switch (callMode) switch (callMode)
@@ -13,6 +13,7 @@ void notify(uint8_t callMode)
case 2: if (!notifyButton) return; break; case 2: if (!notifyButton) return; break;
case 4: if (!notifyDirect) return; break; case 4: if (!notifyDirect) return; break;
case 6: if (!notifyDirect) return; break; //fx change case 6: if (!notifyDirect) return; break; //fx change
case 7: if (!notifyHue) return; break;
default: return; default: return;
} }
byte udpOut[WLEDPACKETSIZE]; byte udpOut[WLEDPACKETSIZE];
@@ -27,12 +28,14 @@ void notify(uint8_t callMode)
udpOut[8] = effectCurrent; udpOut[8] = effectCurrent;
udpOut[9] = effectSpeed; udpOut[9] = effectSpeed;
udpOut[10] = white; udpOut[10] = white;
udpOut[11] = 3; //compatibilityVersionByte: 0: old 1: supports white 2: supports secondary color 3: supports FX intensity, 24 byte packet udpOut[11] = 4; //compatibilityVersionByte: 0: old 1: supports white 2: supports secondary color 3: supports FX intensity, 24 byte packet 4: supports transitionDelay
udpOut[12] = col_sec[0]; udpOut[12] = colSec[0];
udpOut[13] = col_sec[1]; udpOut[13] = colSec[1];
udpOut[14] = col_sec[2]; udpOut[14] = colSec[2];
udpOut[15] = white_sec; udpOut[15] = whiteSec;
udpOut[16] = effectIntensity; udpOut[16] = effectIntensity;
udpOut[17] = (transitionDelay >> 0) & 0xFF;
udpOut[18] = (transitionDelay >> 8) & 0xFF;
IPAddress broadcastIp; IPAddress broadcastIp;
broadcastIp = ~WiFi.subnetMask() | WiFi.gatewayIP(); broadcastIp = ~WiFi.subnetMask() | WiFi.gatewayIP();
@@ -40,14 +43,23 @@ void notify(uint8_t callMode)
notifierUdp.beginPacket(broadcastIp, udpPort); notifierUdp.beginPacket(broadcastIp, udpPort);
notifierUdp.write(udpOut, WLEDPACKETSIZE); notifierUdp.write(udpOut, WLEDPACKETSIZE);
notifierUdp.endPacket(); notifierUdp.endPacket();
notificationSentCallMode = callMode;
notificationSentTime = millis();
notificationTwoRequired = (followUp)? false:notifyTwice;
} }
void handleNotifications() void handleNotifications()
{ {
if(udpConnected && notificationTwoRequired && millis()-notificationSentTime > 250){
notify(notificationSentCallMode,true);
}
if(udpConnected && receiveNotifications){ if(udpConnected && receiveNotifications){
int packetSize = notifierUdp.parsePacket(); uint16_t packetSize = notifierUdp.parsePacket();
if (packetSize > 1026) return;
if(packetSize && notifierUdp.remoteIP() != WiFi.localIP()) //don't process broadcasts we send ourselves if(packetSize && notifierUdp.remoteIP() != WiFi.localIP()) //don't process broadcasts we send ourselves
{ {
byte udpIn[packetSize];
notifierUdp.read(udpIn, packetSize); notifierUdp.read(udpIn, packetSize);
if (udpIn[0] == 0 && !arlsTimeout) //wled notifier, block if realtime packets active if (udpIn[0] == 0 && !arlsTimeout) //wled notifier, block if realtime packets active
{ {
@@ -62,10 +74,10 @@ void handleNotifications()
white = udpIn[10]; white = udpIn[10];
if (udpIn[11] > 1 ) if (udpIn[11] > 1 )
{ {
col_sec[0] = udpIn[12]; colSec[0] = udpIn[12];
col_sec[1] = udpIn[13]; colSec[1] = udpIn[13];
col_sec[2] = udpIn[14]; colSec[2] = udpIn[14];
white_sec = udpIn[15]; whiteSec = udpIn[15];
} }
} }
if (udpIn[8] != effectCurrent && receiveNotificationEffects) if (udpIn[8] != effectCurrent && receiveNotificationEffects)
@@ -83,6 +95,10 @@ void handleNotifications()
effectIntensity = udpIn[16]; effectIntensity = udpIn[16];
strip.setIntensity(effectIntensity); strip.setIntensity(effectIntensity);
} }
if (udpIn[11] > 3)
{
transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00);
}
nightlightActive = udpIn[6]; nightlightActive = udpIn[6];
if (!nightlightActive) if (!nightlightActive)
{ {
@@ -97,7 +113,7 @@ void handleNotifications()
arlsTimeout = false; arlsTimeout = false;
} else { } else {
if (!arlsTimeout){ if (!arlsTimeout){
strip.setRange(0, ledcount-1, 0); strip.setRange(0, ledCount-1, 0);
strip.setMode(0); strip.setMode(0);
} }
arlsTimeout = true; arlsTimeout = true;
@@ -105,7 +121,7 @@ void handleNotifications()
} }
for (int i = 2; i < packetSize -3; i += 4) for (int i = 2; i < packetSize -3; i += 4)
{ {
if (udpIn[i] + arlsOffset < ledcount && udpIn[i] + arlsOffset >= 0) if (udpIn[i] + arlsOffset < ledCount && udpIn[i] + arlsOffset >= 0)
if (useGammaCorrectionRGB) if (useGammaCorrectionRGB)
{ {
strip.setPixelColor(udpIn[i] + arlsOffset, gamma8[udpIn[i+1]], gamma8[udpIn[i+2]], gamma8[udpIn[i+3]]); strip.setPixelColor(udpIn[i] + arlsOffset, gamma8[udpIn[i+1]], gamma8[udpIn[i+2]], gamma8[udpIn[i+3]]);

View File

@@ -3,7 +3,7 @@
*/ */
void setAllLeds() { void setAllLeds() {
double d = bri_t*briMultiplier; double d = briT*briMultiplier;
int val = d/100; int val = d/100;
if (val > 255) val = 255; if (val > 255) val = 255;
if (useGammaCorrectionBri) if (useGammaCorrectionBri)
@@ -14,26 +14,26 @@ void setAllLeds() {
} }
if (useGammaCorrectionRGB) if (useGammaCorrectionRGB)
{ {
strip.setColor(gamma8[col_t[0]], gamma8[col_t[1]], gamma8[col_t[2]], gamma8[white_t]); strip.setColor(gamma8[colT[0]], gamma8[colT[1]], gamma8[colT[2]], gamma8[whiteT]);
strip.setSecondaryColor(gamma8[col_sec[0]], gamma8[col_sec[1]], gamma8[col_sec[2]], gamma8[white_sec]); strip.setSecondaryColor(gamma8[colSec[0]], gamma8[colSec[1]], gamma8[colSec[2]], gamma8[whiteSec]);
} else { } else {
strip.setColor(col_t[0], col_t[1], col_t[2], white_t); strip.setColor(colT[0], colT[1], colT[2], whiteT);
strip.setSecondaryColor(col_sec[0], col_sec[1], col_sec[2], white_sec); strip.setSecondaryColor(colSec[0], colSec[1], colSec[2], whiteSec);
} }
} }
void setLedsStandard() void setLedsStandard()
{ {
col_old[0] = col[0]; colOld[0] = col[0];
col_old[1] = col[1]; colOld[1] = col[1];
col_old[2] = col[2]; colOld[2] = col[2];
white_old = white; whiteOld = white;
bri_old = bri; briOld = bri;
col_t[0] = col[0]; colT[0] = col[0];
col_t[1] = col[1]; colT[1] = col[1];
col_t[2] = col[2]; colT[2] = col[2];
white_t = white; whiteT = white;
bri_t = bri; briT = bri;
setAllLeds(); setAllLeds();
} }
@@ -41,17 +41,17 @@ bool colorChanged()
{ {
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
if (col[i] != col_it[i]) return true; if (col[i] != colIT[i]) return true;
if (col_sec[i] != col_sec_it[i]) return true; if (colSec[i] != colSecIT[i]) return true;
} }
if (white != white_it || white_sec != white_sec_it) return true; if (white != whiteIT || whiteSec != whiteSecIT) return true;
if (bri != bri_it) return true; if (bri != briIT) return true;
return false; return false;
} }
void colorUpdated(int callMode) void colorUpdated(int callMode)
{ {
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (no not.) (NN)6: fx changed //call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (NN)6: fx changed 7: hue
if (!colorChanged()) if (!colorChanged())
{ {
if (callMode == 6) notify(6); if (callMode == 6) notify(6);
@@ -59,31 +59,34 @@ void colorUpdated(int callMode)
} }
if (callMode != 5 && nightlightActive && nightlightFade) if (callMode != 5 && nightlightActive && nightlightFade)
{ {
bri_nl_t = bri; briNlT = bri;
nightlightDelayMs -= (millis() - nightlightStartTime); nightlightDelayMs -= (millis() - nightlightStartTime);
nightlightStartTime = millis(); nightlightStartTime = millis();
} }
col_it[0] = col[0]; colIT[0] = col[0];
col_it[1] = col[1]; colIT[1] = col[1];
col_it[2] = col[2]; colIT[2] = col[2];
col_sec_it[0] = col_sec[0]; colSecIT[0] = colSec[0];
col_sec_it[1] = col_sec[1]; colSecIT[1] = colSec[1];
col_sec_it[2] = col_sec[2]; colSecIT[2] = colSec[2];
white_it = white; whiteIT = white;
white_sec_it = white_sec; whiteSecIT = whiteSec;
bri_it = bri; briIT = bri;
if (bri > 0) bri_last = bri; if (bri > 0) briLast = bri;
notify(callMode); notify(callMode);
if (fadeTransition || sweepTransition) if (fadeTransition || sweepTransition)
{ {
//set correct delay if not using notification delay
if (callMode != 3) transitionDelayTemp = transitionDelay;
if (transitionActive) if (transitionActive)
{ {
col_old[0] = col_t[0]; colOld[0] = colT[0];
col_old[1] = col_t[1]; colOld[1] = colT[1];
col_old[2] = col_t[2]; colOld[2] = colT[2];
white_old = white_t; whiteOld = whiteT;
bri_old = bri_t; briOld = briT;
tper_last = 0; tperLast = 0;
} }
transitionActive = true; transitionActive = true;
transitionStartTime = millis(); transitionStartTime = millis();
@@ -97,40 +100,40 @@ void colorUpdated(int callMode)
void handleTransitions() void handleTransitions()
{ {
if (transitionActive && transitionDelay > 0) if (transitionActive && transitionDelayTemp > 0)
{ {
float tper = (millis() - transitionStartTime)/(float)transitionDelay; float tper = (millis() - transitionStartTime)/(float)transitionDelayTemp;
if (tper >= 1.0) if (tper >= 1.0)
{ {
transitionActive = false; transitionActive = false;
tper_last = 0; tperLast = 0;
if (sweepTransition) strip.unlockAll(); if (sweepTransition) strip.unlockAll();
setLedsStandard(); setLedsStandard();
strip.setFastUpdateMode(false); strip.setFastUpdateMode(false);
return; return;
} }
if (tper - tper_last < transitionResolution) if (tper - tperLast < transitionResolution)
{ {
return; return;
} }
tper_last = tper; tperLast = tper;
if (fadeTransition) if (fadeTransition)
{ {
col_t[0] = col_old[0]+((col[0] - col_old[0])*tper); colT[0] = colOld[0]+((col[0] - colOld[0])*tper);
col_t[1] = col_old[1]+((col[1] - col_old[1])*tper); colT[1] = colOld[1]+((col[1] - colOld[1])*tper);
col_t[2] = col_old[2]+((col[2] - col_old[2])*tper); colT[2] = colOld[2]+((col[2] - colOld[2])*tper);
white_t = white_old +((white - white_old )*tper); whiteT = whiteOld +((white - whiteOld )*tper);
bri_t = bri_old +((bri - bri_old )*tper); briT = briOld +((bri - briOld )*tper);
} }
if (sweepTransition) if (sweepTransition)
{ {
strip.lockAll(); strip.lockAll();
if (sweepDirection) if (sweepDirection)
{ {
strip.unlockRange(0, (int)(tper*(double)ledcount)); strip.unlockRange(0, (int)(tper*(double)ledCount));
} else } else
{ {
strip.unlockRange(ledcount - (int)(tper*(double)ledcount), ledcount); strip.unlockRange(ledCount - (int)(tper*(double)ledCount), ledCount);
} }
if (!fadeTransition) if (!fadeTransition)
{ {
@@ -145,18 +148,18 @@ void handleNightlight()
{ {
if (nightlightActive) if (nightlightActive)
{ {
if (!nightlightActive_old) //init if (!nightlightActiveOld) //init
{ {
nightlightStartTime = millis(); nightlightStartTime = millis();
notify(4); notify(4);
nightlightDelayMs = (int)(nightlightDelayMins*60000); nightlightDelayMs = (int)(nightlightDelayMins*60000);
nightlightActive_old = true; nightlightActiveOld = true;
bri_nl_t = bri; briNlT = bri;
} }
float nper = (millis() - nightlightStartTime)/((float)nightlightDelayMs); float nper = (millis() - nightlightStartTime)/((float)nightlightDelayMs);
if (nightlightFade) if (nightlightFade)
{ {
bri = bri_nl_t+((nightlightTargetBri - bri_nl_t)*nper); bri = briNlT+((nightlightTargetBri - briNlT)*nper);
colorUpdated(5); colorUpdated(5);
} }
if (nper >= 1) if (nper >= 1)
@@ -167,10 +170,10 @@ void handleNightlight()
bri = nightlightTargetBri; bri = nightlightTargetBri;
colorUpdated(5); colorUpdated(5);
} }
if (bri == 0) bri_last = bri_nl_t; if (bri == 0) briLast = briNlT;
} }
} else if (nightlightActive_old) //early de-init } else if (nightlightActiveOld) //early de-init
{ {
nightlightActive_old = false; nightlightActiveOld = false;
} }
} }

View File

@@ -10,27 +10,34 @@ void handleButton()
{ {
buttonPressedTime = millis(); buttonPressedTime = millis();
buttonPressedBefore = true; buttonPressedBefore = true;
if (buttonMacro == 255)
{
if (bri == 0)
{
bri = bri_last;
} else
{
bri_last = bri;
bri = 0;
}
colorUpdated(2);
} else {
applyMacro(buttonMacro);
}
} }
else if (digitalRead(buttonPin) == HIGH && buttonPressedBefore) else if (digitalRead(buttonPin) == HIGH && buttonPressedBefore)
{ {
delay(15); //debounce delay(15); //debounce
if (digitalRead(buttonPin) == HIGH) if (digitalRead(buttonPin) == HIGH)
{ {
if (millis() - buttonPressedTime > 7000) initAP(); if (millis() - buttonPressedTime > 7000) {initAP();}
else if (millis() - buttonPressedTime > 700)
{
if (macroLongPress != 0) {applyMacro(macroLongPress);}
else _setRandomColor(false,true);
}
else {
if (macroButton == 0)
{
if (bri == 0)
{
bri = briLast;
} else
{
briLast = bri;
bri = 0;
}
colorUpdated(2);
} else {
applyMacro(macroButton);
}
}
buttonPressedBefore = false; buttonPressedBefore = false;
} }
} }

View File

@@ -2,6 +2,55 @@
* Acquires time from NTP server * Acquires time from NTP server
*/ */
TimeChangeRule UTCr = {Last, Sun, Mar, 1, 0}; // UTC
Timezone tzUTC(UTCr, UTCr);
TimeChangeRule BST = {Last, Sun, Mar, 1, 60}; // British Summer Time
TimeChangeRule GMT = {Last, Sun, Oct, 2, 0}; // Standard Time
Timezone tzUK(BST, GMT);
TimeChangeRule CEST = {Last, Sun, Mar, 2, 120}; //Central European Summer Time
TimeChangeRule CET = {Last, Sun, Oct, 3, 60}; //Central European Standard Time
Timezone tzEUCentral(CEST, CET);
TimeChangeRule EEST = {Last, Sun, Mar, 3, 180}; //Central European Summer Time
TimeChangeRule EET = {Last, Sun, Oct, 4, 120}; //Central European Standard Time
Timezone tzEUEastern(EEST, EET);
TimeChangeRule EDT = {Second, Sun, Mar, 2, -240 }; //Daylight time = UTC - 4 hours
TimeChangeRule EST = {First, Sun, Nov, 2, -300 }; //Standard time = UTC - 5 hours
Timezone tzUSEastern(EDT, EST);
TimeChangeRule CDT = {Second, Sun, Mar, 2, -300 }; //Daylight time = UTC - 5 hours
TimeChangeRule CST = {First, Sun, Nov, 2, -360 }; //Standard time = UTC - 6 hours
Timezone tzUSCentral(CDT, CST);
TimeChangeRule MDT = {Second, Sun, Mar, 2, -360 }; //Daylight time = UTC - 6 hours
TimeChangeRule MST = {First, Sun, Nov, 2, -420 }; //Standard time = UTC - 7 hours
Timezone tzUSMountain(MDT, MST);
Timezone tzUSArizona(MST, MST); //Mountain without DST
TimeChangeRule PDT = {Second, Sun, Mar, 2, -420 }; //Daylight time = UTC - 7 hours
TimeChangeRule PST = {First, Sun, Nov, 2, -480 }; //Standard time = UTC - 8 hours
Timezone tzUSPacific(PDT, PST);
TimeChangeRule ChST = {Last, Sun, Mar, 1, 480}; // China Standard Time = UTC + 8 hours
Timezone tzChina(ChST, ChST);
TimeChangeRule JST = {Last, Sun, Mar, 1, 540}; // Japan Standard Time = UTC + 9 hours
Timezone tzJapan(JST, JST);
TimeChangeRule AEDT = {Second, Sun, Oct, 2, 660 }; //Daylight time = UTC + 11 hours
TimeChangeRule AEST = {First, Sun, Apr, 3, 600 }; //Standard time = UTC + 10 hours
Timezone tzAUEastern(AEDT, AEST);
TimeChangeRule NZDT = {Second, Sun, Sep, 2, 780 }; //Daylight time = UTC + 13 hours
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};
void handleNetworkTime() void handleNetworkTime()
{ {
if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > 50000000L && WiFi.status() == WL_CONNECTED) if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > 50000000L && WiFi.status() == WL_CONNECTED)
@@ -20,7 +69,8 @@ void handleNetworkTime()
void sendNTPPacket() void sendNTPPacket()
{ {
WiFi.hostByName(ntpServerName, ntpServerIP); const char* ntpsrv = ntpServerName.c_str();
WiFi.hostByName(ntpsrv, ntpServerIP);
DEBUG_PRINTLN("send NTP packet"); DEBUG_PRINTLN("send NTP packet");
memset(ntpPacketBuffer, 0, NTP_PACKET_SIZE); memset(ntpPacketBuffer, 0, NTP_PACKET_SIZE);
@@ -40,7 +90,7 @@ void sendNTPPacket()
ntpUdp.endPacket(); ntpUdp.endPacket();
} }
boolean checkNTPResponse() bool checkNTPResponse()
{ {
int cb = ntpUdp.parsePacket(); int cb = ntpUdp.parsePacket();
if (cb) { if (cb) {
@@ -56,7 +106,7 @@ boolean checkNTPResponse()
unsigned long secsSince1900 = highWord << 16 | lowWord; unsigned long secsSince1900 = highWord << 16 | lowWord;
DEBUG_PRINT("Unix time = "); DEBUG_PRINT("Unix time = ");
unsigned long epoch = secsSince1900 - seventyYears; unsigned long epoch = secsSince1900 - 2208988800UL; //subtract 70 years
setTime(epoch); setTime(epoch);
DEBUG_PRINTLN(epoch); DEBUG_PRINTLN(epoch);
if (countdownTime - now() > 0) countdownOverTriggered = false; if (countdownTime - now() > 0) countdownOverTriggered = false;
@@ -65,33 +115,49 @@ boolean checkNTPResponse()
return false; return false;
} }
void updateLocalTime()
{
unsigned long tmc = now()+ utcOffsetSecs;
local = timezones[currentTimezone]->toLocal(tmc);
}
String getTimeString() String getTimeString()
{ {
local = TZ.toLocal(now(), &tcr); updateLocalTime();
String ret = monthStr(month(local)); String ret = monthStr(month(local));
ret = ret + " "; ret = ret + " ";
ret = ret + day(local); ret = ret + day(local);
ret = ret + " "; ret = ret + " ";
ret = ret + year(local); ret = ret + year(local);
ret = ret + ", "; ret = ret + ", ";
ret = ret + hour(local); ret += (useAMPM)? hour(local)%12:hour(local);
ret = ret + ":"; ret = ret + ":";
if (minute(local) < 10) ret = ret + "0"; if (minute(local) < 10) ret = ret + "0";
ret = ret + minute(local); ret = ret + minute(local);
ret = ret + ":"; ret = ret + ":";
if (second(local) < 10) ret = ret + "0"; if (second(local) < 10) ret = ret + "0";
ret = ret + second(local); ret = ret + second(local);
if (useAMPM)
{
ret += (hour(local) > 11)? " PM":" AM";
}
return ret; return ret;
} }
void setCountdown()
{
countdownTime = timezones[currentTimezone]->toUTC(getUnixTime(countdownHour, countdownMin, countdownSec, countdownDay, countdownMonth, countdownYear));
if (countdownTime - now() > 0) countdownOverTriggered = false;
}
//returns true if countdown just over //returns true if countdown just over
bool checkCountdown() bool checkCountdown()
{ {
long diff = countdownTime - local; long diff = countdownTime - now();
local = abs(diff); local = abs(diff);
if (diff <0 && !countdownOverTriggered) if (diff <0 && !countdownOverTriggered)
{ {
applyMacro(countdownMacro); if (macroCountdown != 0) applyMacro(macroCountdown);
countdownOverTriggered = true; countdownOverTriggered = true;
return true; return true;
} }

View File

@@ -1,13 +1,27 @@
/* /*
* The Overlay function is over a year old, largely untested and not configurable during runtime. Consider it as deprecated for now, it might get either removed/simplified/reworked. * Used to draw clock overlays over the strip
*/ */
#ifdef USEOVERLAYS void initCronixie()
void _nixieDisplay(int num[], int dur[], int pausedur[], int cnt) {
if (overlayCurrent == 4 && !cronixieInit)
{
strip.driverModeCronixie(true);
strip.setCronixieBacklight(cronixieBacklight);
setCronixie();
cronixieInit = true;
} else if (cronixieInit && overlayCurrent != 4)
{
strip.driverModeCronixie(false);
cronixieInit = false;
}
}
void _nixieDisplay(int num[], uint16_t dur[], uint16_t pausedur[], byte cnt)
{ {
strip.setRange(overlayMin, overlayMax, 0); strip.setRange(overlayMin, overlayMax, 0);
if (num[nixieClockI] >= 0 && !nixiePause) if (num[nixieClockI] >= 0 && !nixiePause)
{ {
strip.setIndividual(num[nixieClockI],((uint32_t)white << 24)| ((uint32_t)col_t[0] << 16) | ((uint32_t)col_t[1] << 8) | col_t[2]); strip.setIndividual(num[nixieClockI],((uint32_t)white << 24)| ((uint32_t)colT[0] << 16) | ((uint32_t)colT[1] << 8) | colT[2]);
strip.unlock(num[nixieClockI]); strip.unlock(num[nixieClockI]);
} }
if (!nixiePause) if (!nixiePause)
@@ -84,8 +98,6 @@ void _nixieNumber(int number, int dur)
if (overlayArr[i] != -1) if (overlayArr[i] != -1)
{ {
overlayArr[i] = overlayArr[i] + overlayMin; overlayArr[i] = overlayArr[i] + overlayMin;
if (overlayReverse)
overlayArr[i] = overlayMax - overlayArr[i];
} }
} }
for (int i = 0; i <6; i++) for (int i = 0; i <6; i++)
@@ -106,38 +118,40 @@ void _nixieNumber(int number, int dur)
void handleOverlays() void handleOverlays()
{ {
//properties: range, (color)
//0 no overlay
//1 solid color (NI)
//2 analog clock
//3 digital nixie-style clock one digit
//4 just static hour (NI)
//5 analog countdown
//6 digital one digit countdown
if (millis() - overlayRefreshedTime > overlayRefreshMs) if (millis() - overlayRefreshedTime > overlayRefreshMs)
{ {
overlayRefreshedTime = millis(); initCronixie();
updateLocalTime();
switch (overlayCurrent) switch (overlayCurrent)
{ {
case 0: break;//no overlay
case 1: _overlaySolid(); break;//solid secondary color
case 2: _overlayAnalogClock(); break;//2 analog clock case 2: _overlayAnalogClock(); break;//2 analog clock
case 3: _overlayNixieClock(); break;//nixie 1-digit case 3: _overlayNixieClock(); break;//nixie 1-digit
case 5: _overlayAnalogCountdown(); break;//a.countdown case 4: _overlayCronixie();//Diamex cronixie clock kit
case 6: _overlayNixieCountdown(); break;//d.
} }
if (!countdownMode || overlayCurrent < 2) checkCountdown(); //countdown macro activation must work
overlayRefreshedTime = millis();
} }
} }
void _overlaySolid()
{
strip.unlockAll();
uint32_t cls = (useGammaCorrectionRGB)? gamma8[whiteSec*16777216] + gamma8[colSec[0]]*65536 + gamma8[colSec[1]]*256 + gamma8[colSec[2]]:whiteSec*16777216 + colSec[0]*65536 + colSec[1]*256 + colSec[2];
strip.setRange(overlayMin,overlayMax,cls);
overlayRefreshMs = 1902;
}
void _overlayAnalogClock() void _overlayAnalogClock()
{ {
int overlaySize = overlayMax - overlayMin +1; int overlaySize = overlayMax - overlayMin +1;
strip.unlockAll(); strip.unlockAll();
if (overlayDimBg) if (countdownMode)
{ {
uint32_t ct = (white>>1)*16777216 + (col[0]>>1)*65536 + (col[1]>>1)*256 + (col[2]>>1); _overlayAnalogCountdown(); return;
if (useGammaCorrectionRGB) ct = (gamma8[white]>>1)*16777216 + (gamma8[col[0]]>>1)*65536 + (gamma8[col[1]]>>1)*256 + (gamma8[col[2]]>>1);
strip.setRange(overlayMin, overlayMax, ct);
} }
local = TZ.toLocal(now(), &tcr); _overlaySolid();
double hourP = ((double)(hour(local)%12))/12; double hourP = ((double)(hour(local)%12))/12;
double minuteP = ((double)minute(local))/60; double minuteP = ((double)minute(local))/60;
hourP = hourP + minuteP/12; hourP = hourP + minuteP/12;
@@ -148,6 +162,17 @@ void _overlayAnalogClock()
if (minutePixel > overlayMax) minutePixel = overlayMin -1 + minutePixel - overlayMax; if (minutePixel > overlayMax) minutePixel = overlayMin -1 + minutePixel - overlayMax;
int secondPixel = floor(analogClock12pixel + overlaySize*secondP); int secondPixel = floor(analogClock12pixel + overlaySize*secondP);
if (secondPixel > overlayMax) secondPixel = overlayMin -1 + secondPixel - overlayMax; if (secondPixel > overlayMax) secondPixel = overlayMin -1 + secondPixel - overlayMax;
if (analogClockSecondsTrail)
{
if (secondPixel < analogClock12pixel)
{
strip.setRange(analogClock12pixel, overlayMax, 0xFF0000);
strip.setRange(overlayMin, secondPixel, 0xFF0000);
} else
{
strip.setRange(analogClock12pixel, secondPixel, 0xFF0000);
}
}
if (analogClock5MinuteMarks) if (analogClock5MinuteMarks)
{ {
int pix; int pix;
@@ -155,16 +180,10 @@ void _overlayAnalogClock()
{ {
pix = overlayMin + analogClock12pixel + (overlaySize/12)*i; pix = overlayMin + analogClock12pixel + (overlaySize/12)*i;
if (pix > overlayMax) pix = pix - overlayMax; if (pix > overlayMax) pix = pix - overlayMax;
strip.setIndividual(pix, 0xAAAAAA); strip.setIndividual(pix,0x00FFAA);
} }
} }
if (analogClockSecondsTrail) if (!analogClockSecondsTrail) strip.setIndividual(secondPixel, 0xFF0000);
{
strip.setRange(analogClock12pixel, secondPixel, 0xFF0000);
} else
{
strip.setIndividual(secondPixel, 0xFF0000);
}
strip.setIndividual(minutePixel, 0x00FF00); strip.setIndividual(minutePixel, 0x00FF00);
strip.setIndividual(hourPixel, 0x0000FF); strip.setIndividual(hourPixel, 0x0000FF);
overlayRefreshMs = 998; overlayRefreshMs = 998;
@@ -172,14 +191,14 @@ void _overlayAnalogClock()
void _overlayNixieClock() void _overlayNixieClock()
{ {
if (countdownMode)
{
_overlayNixieCountdown(); return;
}
if (nixieClockI < 0) if (nixieClockI < 0)
{ {
local = TZ.toLocal(now(), &tcr);
overlayArr[0] = hour(local); overlayArr[0] = hour(local);
if (nixieClock12HourFormat && overlayArr[0] > 12) if (useAMPM) overlayArr[0] = overlayArr[0]%12;
{
overlayArr[0] = overlayArr[0]%12;
}
overlayArr[1] = -1; overlayArr[1] = -1;
if (overlayArr[0] > 9) if (overlayArr[0] > 9)
{ {
@@ -191,7 +210,7 @@ void _overlayNixieClock()
overlayArr[2] = overlayArr[2]/10; overlayArr[2] = overlayArr[2]/10;
overlayArr[4] = -1; overlayArr[4] = -1;
overlayArr[5] = -1; overlayArr[5] = -1;
if (nixieClockDisplaySeconds) if (analogClockSecondsTrail)
{ {
overlayArr[4] = second(local); overlayArr[4] = second(local);
overlayArr[5] = overlayArr[4]%10; overlayArr[5] = overlayArr[4]%10;
@@ -202,8 +221,6 @@ void _overlayNixieClock()
if (overlayArr[i] != -1) if (overlayArr[i] != -1)
{ {
overlayArr[i] = overlayArr[i] + overlayMin; overlayArr[i] = overlayArr[i] + overlayMin;
if (overlayReverse)
overlayArr[i] = overlayMax - overlayArr[i];
} }
} }
overlayDur[0] = 12 + 12*(255 - overlaySpeed); overlayDur[0] = 12 + 12*(255 - overlaySpeed);
@@ -292,14 +309,14 @@ void _overlayAnalogCountdown()
int overlaySize = overlayMax - overlayMin +1; int overlaySize = overlayMax - overlayMin +1;
double perc = (pval-(double)diff)/pval; double perc = (pval-(double)diff)/pval;
if (perc > 1.0) perc = 1.0; if (perc > 1.0) perc = 1.0;
uint8_t pixelCnt = perc*overlaySize; byte pixelCnt = perc*overlaySize;
if (analogClock12pixel + pixelCnt > overlayMax) if (analogClock12pixel + pixelCnt > overlayMax)
{ {
strip.setRange(analogClock12pixel, overlayMax, ((uint32_t)white_sec << 24)| ((uint32_t)col_sec[0] << 16) | ((uint32_t)col_sec[1] << 8) | col_sec[2]); strip.setRange(analogClock12pixel, overlayMax, ((uint32_t)whiteSec << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
strip.setRange(overlayMin, overlayMin +pixelCnt -(1+ overlayMax -analogClock12pixel), ((uint32_t)white_sec << 24)| ((uint32_t)col_sec[0] << 16) | ((uint32_t)col_sec[1] << 8) | col_sec[2]); strip.setRange(overlayMin, overlayMin +pixelCnt -(1+ overlayMax -analogClock12pixel), ((uint32_t)whiteSec << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
} else } else
{ {
strip.setRange(analogClock12pixel, analogClock12pixel + pixelCnt, ((uint32_t)white_sec << 24)| ((uint32_t)col_sec[0] << 16) | ((uint32_t)col_sec[1] << 8) | col_sec[2]); strip.setRange(analogClock12pixel, analogClock12pixel + pixelCnt, ((uint32_t)whiteSec << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
} }
} }
overlayRefreshMs = 998; overlayRefreshMs = 998;
@@ -331,5 +348,5 @@ void _overlayNixieCountdown()
} }
_nixieNumber(diff, 800); _nixieNumber(diff, 800);
} }
overlayRefreshMs = 998;
} }
#endif

View File

@@ -46,12 +46,12 @@ void handleAlexa()
void alexaOn() void alexaOn()
{ {
if (alexaOnMacro == 255) if (macroAlexaOn == 0)
{ {
handleSet((alexaNotify)?"win&T=1&IN":"win&T=1&NN&IN"); handleSet((alexaNotify)?"win&T=1&IN":"win&T=1&NN&IN");
} else } else
{ {
applyMacro(alexaOnMacro); applyMacro(macroAlexaOn);
} }
String body = "[{\"success\":{\"/lights/1/state/on\":true}}]"; String body = "[{\"success\":{\"/lights/1/state/on\":true}}]";
@@ -64,12 +64,12 @@ void alexaOn()
void alexaOff() void alexaOff()
{ {
if (alexaOffMacro == 255) if (macroAlexaOff == 0)
{ {
handleSet((alexaNotify)?"win&T=0&IN":"win&T=0&NN&IN"); handleSet((alexaNotify)?"win&T=0&IN":"win&T=0&NN&IN");
} else } else
{ {
applyMacro(alexaOffMacro); applyMacro(macroAlexaOff);
} }
String body = "[{\"success\":{\"/lights/1/state/on\":false}}]"; String body = "[{\"success\":{\"/lights/1/state/on\":false}}]";
@@ -80,7 +80,7 @@ void alexaOff()
DEBUG_PRINTLN(body); DEBUG_PRINTLN(body);
} }
void alexaDim(uint8_t briL) void alexaDim(byte briL)
{ {
String body = "[{\"success\":{\"/lights/1/state/bri\":"+ String(briL) +"}}]"; String body = "[{\"success\":{\"/lights/1/state/bri\":"+ String(briL) +"}}]";
@@ -127,7 +127,7 @@ void respondToSearch() {
UDP.beginPacket(UDP.remoteIP(), UDP.remotePort()); UDP.beginPacket(UDP.remoteIP(), UDP.remotePort());
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
UDP.write((uint8_t*)response.c_str(), response.length()); UDP.write((byte*)response.c_str(), response.length());
#else #else
UDP.write(response.c_str()); UDP.write(response.c_str());
#endif #endif
@@ -223,7 +223,7 @@ String briForHue(int realBri)
return String(realBri); return String(realBri);
} }
boolean handleAlexaApiCall(String req, String body) //basic implementation of Philips hue api functions needed for basic Alexa control bool handleAlexaApiCall(String req, String body) //basic implementation of Philips hue api functions needed for basic Alexa control
{ {
DEBUG_PRINTLN("AlexaApiCall"); DEBUG_PRINTLN("AlexaApiCall");
if (req.indexOf("api") <0) return false; if (req.indexOf("api") <0) return false;
@@ -262,8 +262,8 @@ boolean handleAlexaApiCall(String req, String body) //basic implementation of Ph
return true; return true;
} }
boolean connectUDP(){ bool connectUDP(){
boolean state = false; bool state = false;
DEBUG_PRINTLN(""); DEBUG_PRINTLN("");
DEBUG_PRINTLN("Con UDP"); DEBUG_PRINTLN("Con UDP");

View File

@@ -1,10 +1,9 @@
/* /*
* Support for the Cronixie clock * Support for the Cronixie clock
*/ */
#ifdef CRONIXIE byte getSameCodeLength(char code, int index, char const digits[])
uint8_t getSameCodeLength(char code, int index, char const digits[])
{ {
uint8_t counter = 0; byte counter = 0;
for (int i = index+1; i < 6; i++) for (int i = index+1; i < 6; i++)
{ {
@@ -18,8 +17,9 @@ uint8_t getSameCodeLength(char code, int index, char const digits[])
return counter; return counter;
} }
void setCronixie(char const digits[]) void setCronixie()
{ {
char digits[6]; for (int a=0;a<6;a++) digits[a]=cronixieDisplay.charAt(a);
/* /*
* digit purpose index * digit purpose index
* 0-9 | 0-9 (incl. random) * 0-9 | 0-9 (incl. random)
@@ -86,7 +86,7 @@ void setCronixie(char const digits[])
DEBUG_PRINT("cset "); DEBUG_PRINT("cset ");
DEBUG_PRINTLN(digits); DEBUG_PRINTLN(digits);
cronixieRefreshMs = 1997; //Only refresh every 2secs if no seconds are displayed overlayRefreshMs = 1997; //Only refresh every 2secs if no seconds are displayed
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ {
@@ -107,8 +107,8 @@ void setCronixie(char const digits[])
case 'a': dP[i] = 58; i++; break; case 'a': dP[i] = 58; i++; break;
case 'm': dP[i] = 74 + getSameCodeLength('m',i,digits); i = i+dP[i]-74; break; case 'm': dP[i] = 74 + getSameCodeLength('m',i,digits); i = i+dP[i]-74; break;
case 'M': dP[i] = 24 + getSameCodeLength('M',i,digits); i = i+dP[i]-24; break; case 'M': dP[i] = 24 + getSameCodeLength('M',i,digits); i = i+dP[i]-24; break;
case 's': dP[i] = 80 + getSameCodeLength('s',i,digits); i = i+dP[i]-80; cronixieRefreshMs = 497; break; //refresh more often bc. of secs case 's': dP[i] = 80 + getSameCodeLength('s',i,digits); i = i+dP[i]-80; overlayRefreshMs = 497; break; //refresh more often bc. of secs
case 'S': dP[i] = 30 + getSameCodeLength('S',i,digits); i = i+dP[i]-30; cronixieRefreshMs = 497; break; case 'S': dP[i] = 30 + getSameCodeLength('S',i,digits); i = i+dP[i]-30; overlayRefreshMs = 497; break;
case 'Y': dP[i] = 36 + getSameCodeLength('Y',i,digits); i = i+dP[i]-36; break; case 'Y': dP[i] = 36 + getSameCodeLength('Y',i,digits); i = i+dP[i]-36; break;
case 'y': dP[i] = 86 + getSameCodeLength('y',i,digits); i = i+dP[i]-86; break; case 'y': dP[i] = 86 + getSameCodeLength('y',i,digits); i = i+dP[i]-86; break;
case 'I': dP[i] = 39 + getSameCodeLength('I',i,digits); i = i+dP[i]-39; break; //Month. Don't ask me why month and minute both start with M. case 'I': dP[i] = 39 + getSameCodeLength('I',i,digits); i = i+dP[i]-39; break; //Month. Don't ask me why month and minute both start with M.
@@ -139,27 +139,23 @@ void setCronixie(char const digits[])
} }
DEBUG_PRINTLN((int)dP[5]); DEBUG_PRINTLN((int)dP[5]);
cronixieRefreshedTime = 0; //refresh immediately _overlayCronixie(); //refresh
} }
void handleCronixie() void _overlayCronixie()
{ {
if (millis() - cronixieRefreshedTime > cronixieRefreshMs) if (countdownMode) checkCountdown();
{ byte h = hour(local);
cronixieRefreshedTime = millis(); byte h0 = h;
local = TZ.toLocal(now(), &tcr); byte m = minute(local);
if (cronixieCountdown) checkCountdown(); byte s = second(local);
uint8_t h = hour(local); byte d = day(local);
uint8_t h0 = h; byte mi = month(local);
uint8_t m = minute(local);
uint8_t s = second(local);
uint8_t d = day(local);
uint8_t mi = month(local);
int y = year(local); int y = year(local);
//this has to be changed in time for 22nd century //this has to be changed in time for 22nd century
y -= 2000; if (y<0) y += 30; //makes countdown work y -= 2000; if (y<0) y += 30; //makes countdown work
if (cronixieUseAMPM && !cronixieCountdown) if (useAMPM && !countdownMode)
{ {
if (h>12) h-=12; if (h>12) h-=12;
else if (h==0) h+=12; else if (h==0) h+=12;
@@ -213,6 +209,4 @@ void handleCronixie()
} }
strip.setCronixieDigits(_digitOut); strip.setCronixieDigits(_digitOut);
//strip.trigger(); //this has a drawback, no effects slower than RefreshMs. advantage: Quick update, not dependant on effect time //strip.trigger(); //this has a drawback, no effects slower than RefreshMs. advantage: Quick update, not dependant on effect time
}
} }
#endif

View File

@@ -1,27 +1,139 @@
/* /*
* Color conversion methods * Color conversion methods
*/ */
void colorCTtoRGB(uint16_t mired, uint8_t* rgb) //white spectrum to rgb void colorCTtoRGB(uint16_t mired, byte* rgb) //white spectrum to rgb
{ {
//this is only an approximation using WS2812B with gamma correction enabled
if (mired > 475)
{
rgb[0]=255;rgb[1]=199;rgb[2]=92;//500
} else if (mired > 425)
{
rgb[0]=255;rgb[1]=213;rgb[2]=118;//450
} else if (mired > 375)
{
rgb[0]=255;rgb[1]=216;rgb[2]=118;//400
} else if (mired > 325)
{
rgb[0]=255;rgb[1]=234;rgb[2]=140;//350
} else if (mired > 275)
{
rgb[0]=255;rgb[1]=243;rgb[2]=160;//300
} else if (mired > 225)
{
rgb[0]=250;rgb[1]=255;rgb[2]=188;//250
} else if (mired > 175)
{
rgb[0]=247;rgb[1]=255;rgb[2]=215;//200
} else
{
rgb[0]=237;rgb[1]=255;rgb[2]=239;//150
}
} }
void colorHSBtoRGB(uint16_t hue, uint8_t sat, uint8_t bri, uint8_t* rgb) //hue, sat, bri to rgb void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb
{ {
float h = ((float)hue)/65535.0;
float s = ((float)sat)/255.0;
byte i = floor(h*6);
float f = h * 6-i;
float p = 255 * (1-s);
float q = 255 * (1-f*s);
float t = 255 * (1-(1-f)*s);
switch (i%6) {
case 0: rgb[0]=255,rgb[1]=t,rgb[2]=p;break;
case 1: rgb[0]=q,rgb[1]=255,rgb[2]=p;break;
case 2: rgb[0]=p,rgb[1]=255,rgb[2]=t;break;
case 3: rgb[0]=p,rgb[1]=q,rgb[2]=255;break;
case 4: rgb[0]=t,rgb[1]=p,rgb[2]=255;break;
case 5: rgb[0]=255,rgb[1]=p,rgb[2]=q;
}
} }
void colorXYtoRGB(float x, float y, uint8_t* rgb) //coordinates to rgb (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy) void colorXYtoRGB(float x, float y, byte* rgb) //coordinates to rgb (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy)
{ {
float z = 1.0f - x - y; float z = 1.0f - x - y;
//float Y = 1.0f; // Brightness, we handle this separately
float X = (1.0f / y) * x; float X = (1.0f / y) * x;
float Z = (1.0f / y) * z; float Z = (1.0f / y) * z;
rgb[0] = (int)(X * 1.656492f - 0.354851f - Z * 0.255038f); float r = (int)255*(X * 1.656492f - 0.354851f - Z * 0.255038f);
rgb[1] = (int)(-X * 0.707196f + 1.655397f + Z * 0.036152f); float g = (int)255*(-X * 0.707196f + 1.655397f + Z * 0.036152f);
rgb[2] = (int)(X * 0.051713f - 0.121364f + Z * 1.011530f); float b = (int)255*(X * 0.051713f - 0.121364f + Z * 1.011530f);
if (r > b && r > g && r > 1.0f) {
// red is too big
g = g / r;
b = b / r;
r = 1.0f;
} else if (g > b && g > r && g > 1.0f) {
// green is too big
r = r / g;
b = b / g;
g = 1.0f;
} else if (b > r && b > g && b > 1.0f) {
// blue is too big
r = r / b;
g = g / b;
b = 1.0f;
}
// Apply gamma correction
r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * pow(r, (1.0f / 2.4f)) - 0.055f;
g = g <= 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * pow(g, (1.0f / 2.4f)) - 0.055f;
b = b <= 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * pow(b, (1.0f / 2.4f)) - 0.055f;
if (r > b && r > g) {
// red is biggest
if (r > 1.0f) {
g = g / r;
b = b / r;
r = 1.0f;
}
} else if (g > b && g > r) {
// green is biggest
if (g > 1.0f) {
r = r / g;
b = b / g;
g = 1.0f;
}
} else if (b > r && b > g) {
// blue is biggest
if (b > 1.0f) {
r = r / b;
g = g / b;
b = 1.0f;
}
}
rgb[0] = 255.0*r;
rgb[1] = 255.0*g;
rgb[2] = 255.0*b;
} }
void colorRGBtoXY(uint8_t* rgb, float* xy){} //rgb to coordinates (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy) void colorRGBtoXY(byte* rgb, float* xy) //rgb to coordinates (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy)
{
float X = rgb[0] * 0.664511f + rgb[1] * 0.154324f + rgb[2] * 0.162028f;
float Y = rgb[0] * 0.283881f + rgb[1] * 0.668433f + rgb[2] * 0.047685f;
float Z = rgb[0] * 0.000088f + rgb[1] * 0.072310f + rgb[2] * 0.986039f;
xy[0] = X / (X + Y + Z);
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;
return w;
}
float maxf (float v, float w)
{
if (w > v) return w;
return v;
}
void colorRGBtoRGBW(byte* rgb, byte* wht) //rgb to rgbw, untested and currently unused
{
*wht = (float)minf(rgb[0],minf(rgb[1],rgb[2]))*0.95;
rgb[0]-=wht;
rgb[1]-=wht;
rgb[2]-=wht;
}*/
void colorRGBtoRGBW(uint8_t* rgb, uint8_t* rgbw){} //rgb to rgbw, not imlemented yet

View File

@@ -1,4 +1,207 @@
/* /*
* Sync to Philips hue lights * Sync to Philips hue lights
*/ */
void foo(){}
void handleHue()
{
if (huePollingEnabled && WiFi.status() == WL_CONNECTED)
{
if (millis() - hueLastRequestSent > huePollIntervalMsTemp)
{
sendHuePoll(false);
}
}
}
bool setupHue()
{
if (WiFi.status() == WL_CONNECTED) //setup needed
{
if (hueApiKey.length()>20) //api key is probably ok
{
if (sendHuePoll(false))
{
huePollingEnabled = true;
return true;
}
if (hueError.charAt(0) == 'R' || hueError.charAt(0) == 'I') return false; //can't connect
delay(20);
}
sendHuePoll(true); //new API key
if (hueError.charAt(0) != 'C') return false; //still some error
delay(20);
if (sendHuePoll(false))
{
huePollingEnabled = true;
return true;
}
return false;
}
else return false;
return true;
}
bool sendHuePoll(bool sAuth)
{
bool st;
hueClient.setReuse(true);
hueClient.setTimeout(450);
String hueURL = "http://";
hueURL += hueIP.toString();
hueURL += "/api/";
if (!sAuth) {
hueURL += hueApiKey;
hueURL += "/lights/" + String(huePollLightId);
}
hueClient.begin(hueURL);
int httpCode = (sAuth)? hueClient.POST("{\"devicetype\":\"wled#esp\"}"):hueClient.GET();
//TODO this request may block operation for ages
if (httpCode>0){
st = handleHueResponse(hueClient.getString(),sAuth);
} else {
hueError = "Request timed out";
st = false;
}
if (!st){ //error
if (huePollIntervalMsTemp<300000) huePollIntervalMsTemp*=2; // only poll every ~5min when unable to connect
hueFailCount++;
if (hueFailCount > 150) huePollingEnabled = false; //disable after many hours offline
}
hueLastRequestSent = millis();
return st;
}
bool handleHueResponse(String hueResp, bool isAuth)
{
DEBUG_PRINTLN(hueApiKey);
DEBUG_PRINTLN(hueResp);
if (hueResp.indexOf("error")>0)//hue bridge returned error
{
int hueErrorCode = getJsonValue(&hueResp,"type").toInt();
switch (hueErrorCode)
{
case 1: hueError = "Unauthorized"; break;
case 3: hueError = "Invalid light ID"; break;
case 101: hueError = "Link button not pressed"; break;
default: hueError = "Bridge Error " + String(hueErrorCode);
}
return false;
}
if (isAuth)
{
String tempApi = getJsonValue(&hueResp,"username");
if (tempApi.length()>0)
{
hueApiKey = tempApi;
return true;
}
hueError = "Invalid response";
return false;
}
float hueX=0, hueY=0;
uint16_t hueHue=0, hueCt=0;
byte hueBri=0, hueSat=0, hueColormode=0;
if (getJsonValue(&hueResp,"on").charAt(0) == 't')
{
String tempV = getJsonValue(&hueResp,"bri");
if (tempV.length()>0) //Dimmable device
{
hueBri = (tempV.toInt())+1;
tempV = getJsonValue(&hueResp,"colormode");
if (hueApplyColor && tempV.length()>0) //Color device
{
if (tempV.charAt(0) == 'x') //xy mode
{
tempV = getJsonValue(&hueResp,"xy");
if (tempV.length()>0) //valid
{
hueColormode = 1;
hueX = tempV.toFloat();
tempV = tempV.substring(tempV.indexOf(',')+1);
hueY = tempV.toFloat();
}
} else if (tempV.charAt(0) == 'h') //hs mode
{
tempV = getJsonValue(&hueResp,"hue");
if (tempV.length()>0) //valid
{
hueColormode = 2;
hueHue = tempV.toInt();
tempV = getJsonValue(&hueResp,"sat");
if (tempV.length()>0) //valid
{
hueSat = tempV.toInt();
}
}
} else //ct mode
{
tempV = getJsonValue(&hueResp,"\"ct"); //dirty hack to not get effect value instead
if (tempV.length()>0) //valid
{
hueColormode = 3;
hueCt = tempV.toInt();
}
}
}
} else //On/Off device
{
hueBri = briLast;
}
} else
{
hueBri = 0;
}
hueFailCount = 0;
huePollIntervalMsTemp = huePollIntervalMs;
hueError = "Connected";
//applying vals
if (hueBri != hueBriLast)
{
bri = hueBri;
if (hueApplyOnOff)
{
if (hueBri==0) {bri = 0;}
else if (bri==0 && hueBri>0) bri = briLast;
}
if (hueApplyBri)
{
if (hueBri>0) bri = hueBri;
}
hueBriLast = hueBri;
}
if (hueApplyColor)
{
switch(hueColormode)
{
case 1: if (hueX != hueXLast || hueY != hueYLast) colorXYtoRGB(hueX,hueY,col); hueXLast = hueX; hueYLast = hueY; break;
case 2: if (hueHue != hueHueLast || hueSat != hueSatLast) colorHStoRGB(hueHue,hueSat,col); hueHueLast = hueHue; hueSatLast = hueSat; break;
case 3: if (hueCt != hueCtLast) colorCTtoRGB(hueCt,col); hueCtLast = hueCt; break;
}
}
colorUpdated(7);
return true;
}
String getJsonValue(String* req, String key)
{
//TODO may replace with ArduinoJSON if too complex
//this is horribly inefficient and designed to work only in this case
uint16_t pos = req->indexOf(key);
String b = req->substring(pos + key.length()+2);
if (b.charAt(0)=='\"') //is string
{
return b.substring(1,b.substring(1).indexOf('\"')+1);
} else if (b.charAt(0)=='[') //is array
{
return b.substring(1,b.indexOf(']'));
} else //is primitive type
{
return b.substring(0,b.indexOf(',')); //this works only if value not last
}
return "";
}