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

View File

@@ -73,7 +73,7 @@ void WS2812FX::stop() {
strip_off();
}
void WS2812FX::setMode(uint8_t m) {
void WS2812FX::setMode(byte m) {
_counter_mode_call = 0;
_counter_mode_step = 0;
_mode_last_call_time = 0;
@@ -83,7 +83,7 @@ void WS2812FX::setMode(uint8_t m) {
strip_off_respectLock();
}
void WS2812FX::setSpeed(uint8_t s) {
void WS2812FX::setSpeed(byte s) {
_counter_mode_call = 0;
_counter_mode_step = 0;
_mode_last_call_time = 0;
@@ -91,35 +91,35 @@ void WS2812FX::setSpeed(uint8_t s) {
strip_off_respectLock();
}
void WS2812FX::increaseSpeed(uint8_t s) {
void WS2812FX::increaseSpeed(byte s) {
s = constrain(_speed + s, SPEED_MIN, SPEED_MAX);
setSpeed(s);
}
void WS2812FX::decreaseSpeed(uint8_t s) {
void WS2812FX::decreaseSpeed(byte s) {
s = constrain(_speed - s, SPEED_MIN, SPEED_MAX);
setSpeed(s);
}
void WS2812FX::setIntensity(uint8_t in) {
void WS2812FX::setIntensity(byte 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);
}
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);
}
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);
}
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);
}
@@ -136,33 +136,33 @@ void WS2812FX::setSecondaryColor(uint32_t c) {
setBrightness(_brightness);
}
void WS2812FX::increaseBrightness(uint8_t s) {
void WS2812FX::increaseBrightness(byte s) {
s = constrain(_brightness + s, BRIGHTNESS_MIN, BRIGHTNESS_MAX);
setBrightness(s);
}
void WS2812FX::decreaseBrightness(uint8_t s) {
void WS2812FX::decreaseBrightness(byte s) {
s = constrain(_brightness - s, BRIGHTNESS_MIN, BRIGHTNESS_MAX);
setBrightness(s);
}
boolean WS2812FX::isRunning() {
bool WS2812FX::isRunning() {
return _running;
}
uint8_t WS2812FX::getMode(void) {
byte WS2812FX::getMode(void) {
return _mode_index;
}
uint8_t WS2812FX::getSpeed(void) {
byte WS2812FX::getSpeed(void) {
return _speed;
}
uint8_t WS2812FX::getBrightness(void) {
byte WS2812FX::getBrightness(void) {
return _brightness;
}
uint8_t WS2812FX::getModeCount(void) {
byte WS2812FX::getModeCount(void) {
return MODE_COUNT;
}
@@ -198,7 +198,7 @@ void WS2812FX::strip_off_respectLock() {
* The colours are a transition r -> g -> b -> back to r
* Inspired by the Adafruit examples.
*/
uint32_t WS2812FX::color_wheel(uint8_t pos) {
uint32_t WS2812FX::color_wheel(byte pos) {
pos = 255 - pos;
if(pos < 85) {
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.
*/
uint8_t WS2812FX::get_random_wheel_index(uint8_t pos) {
uint8_t r = 0;
uint8_t x = 0;
uint8_t y = 0;
uint8_t d = 0;
byte WS2812FX::get_random_wheel_index(byte pos) {
byte r = 0;
byte x = 0;
byte y = 0;
byte d = 0;
while(d < 42) {
r = random(256);
@@ -360,13 +360,13 @@ void WS2812FX::mode_multi_dynamic(void) {
void WS2812FX::mode_breath(void) {
// 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
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) {
_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) {
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
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++) {
@@ -400,10 +400,10 @@ void WS2812FX::mode_fade(void) {
int y = _counter_mode_step - 127;
y = 256 - (abs(y) * 2);
double z = (double)y/256;
uint8_t w = ((_color >> 24) & 0xFF), ws = ((_color_sec >> 24) & 0xFF);
uint8_t r = ((_color >> 16) & 0xFF), rs = ((_color_sec >> 16) & 0xFF);
uint8_t g = ((_color >> 8) & 0xFF), gs = ((_color_sec >> 8) & 0xFF);
uint8_t b = (_color & 0xFF), bs = (_color_sec & 0xFF);
byte w = ((_color >> 24) & 0xFF), ws = ((_color_sec >> 24) & 0xFF);
byte r = ((_color >> 16) & 0xFF), rs = ((_color_sec >> 16) & 0xFF);
byte g = ((_color >> 8) & 0xFF), gs = ((_color_sec >> 8) & 0xFF);
byte b = (_color & 0xFF), bs = (_color_sec & 0xFF);
w = w+((ws - w)*z);
r = r+((rs - r)*z);
g = g+((gs - g)*z);
@@ -506,7 +506,7 @@ void WS2812FX::mode_rainbow_cycle(void) {
* Inspired by the Adafruit examples.
*/
void WS2812FX::mode_theater_chase(void) {
uint8_t j = _counter_mode_call % 6;
byte j = _counter_mode_call % 6;
if(j % 2 == 0) {
for(uint16_t i=0; i < _led_count; i=i+3) {
if (!_locked[i+(j/2)])
@@ -529,7 +529,7 @@ void WS2812FX::mode_theater_chase(void) {
* Inspired by the Adafruit examples.
*/
void WS2812FX::mode_theater_chase_rainbow(void) {
uint8_t j = _counter_mode_call % 6;
byte j = _counter_mode_call % 6;
if(j % 2 == 0) {
for(uint16_t i=0; i < _led_count; i=i+3) {
if (!_locked[i+(j/2)])
@@ -552,10 +552,10 @@ void WS2812FX::mode_theater_chase_rainbow(void) {
* Running lights effect with smooth sine transition.
*/
void WS2812FX::mode_running_lights(void) {
uint8_t w = ((_color >> 24) & 0xFF);
uint8_t r = ((_color >> 16) & 0xFF);
uint8_t g = ((_color >> 8) & 0xFF);
uint8_t b = (_color & 0xFF);
byte w = ((_color >> 24) & 0xFF);
byte r = ((_color >> 16) & 0xFF);
byte g = ((_color >> 8) & 0xFF);
byte b = (_color & 0xFF);
for(uint16_t i=0; i < _led_count; i++) {
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.
*/
void WS2812FX::mode_chase_flash(void) {
const static uint8_t flash_count = 4;
uint8_t flash_step = _counter_mode_call % ((flash_count * 2) + 1);
const static byte flash_count = 4;
byte flash_step = _counter_mode_call % ((flash_count * 2) + 1);
for(uint16_t i=0; i < _led_count; i++) {
if (!_locked[i])
@@ -933,8 +933,8 @@ void WS2812FX::mode_chase_flash(void) {
* _color_sec flashes running, followed by random color.
*/
void WS2812FX::mode_chase_flash_random(void) {
const static uint8_t flash_count = 4;
uint8_t flash_step = _counter_mode_call % ((flash_count * 2) + 1);
const static byte flash_count = 4;
byte flash_step = _counter_mode_call % ((flash_count * 2) + 1);
for(uint16_t i=0; i < _counter_mode_step; i++) {
if (!_locked[i])
@@ -1606,13 +1606,13 @@ void WS2812FX::mode_cc_core()
for (int i = 0; i < _cc_num1; i++)
{
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_fe) setPixelColor(_cc_i2 - num, _color);
}
}
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);
}
@@ -1816,6 +1816,11 @@ void WS2812FX::setFastUpdateMode(bool y)
if (_mode_index == 0) _mode_delay = 20;
}
void WS2812FX::setReverseMode(bool b)
{
_reverseMode = b;
}
void WS2812FX::driverModeCronixie(bool b)
{
_cronixieMode = b;
@@ -1826,7 +1831,7 @@ void WS2812FX::setCronixieBacklight(bool b)
_cronixieBacklightEnabled = b;
}
void WS2812FX::setCronixieDigits(uint8_t d[])
void WS2812FX::setCronixieDigits(byte d[])
{
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 _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.
//Stay safe with high amperage and have a reasonable safety margin!
//I am NOT to be held liable for burned down garages!
double WS2812FX::getSafePowerMultiplier(double safeMilliAmps, 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);
if (_mARequired > safeMilliAmps)
@@ -1864,72 +1869,72 @@ double WS2812FX::getSafePowerMultiplier(double safeMilliAmps, uint8_t leds, uint
return 1.0;
}
void WS2812FX::setCCIndex1(uint8_t i1)
void WS2812FX::setCCIndex1(byte i1)
{
if (i1 < _led_count-1) _cc_i1 = i1;
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 (_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;
_counter_cc_step = 0;
_counter_ccStep = 0;
}
void WS2812FX::setCCNum1(uint8_t np)
void WS2812FX::setCCNum1(byte 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;
_counter_cc_step = 0;
_counter_ccStep = 0;
}
void WS2812FX::setCCStep(uint8_t stp)
void WS2812FX::setCCStep(byte stp)
{
_cc_step = stp;
_counter_cc_step = 0;
_ccStep = stp;
_counter_ccStep = 0;
}
void WS2812FX::setCCFS(bool fs)
{
_cc_fs = fs;
_cc_fe = (fs) ? _cc_fe : true;
_counter_cc_step = 0;
_counter_ccStep = 0;
}
void WS2812FX::setCCFE(bool fe)
{
_cc_fe = fe;
_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);
setCCIndex2(i2);
setCCStart(is);
_cc_num1 = np;
_cc_num2 = ns;
_cc_step = stp;
_ccStep = stp;
setCCFS(fs);
setCCFE(fe);
}
//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
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
}
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)
{
#ifdef RGBW
@@ -1949,13 +1955,13 @@ void WS2812FX::setPixelColor(uint16_t i, uint8_t r, uint8_t g, uint8_t b, uint8_
#endif
} else {
if(i>6)return;
uint8_t o = 10*i;
byte o = 10*i;
if (_cronixieBacklightEnabled && _cronixieDigits[i] <11)
{
uint8_t rCorr = (int)(((double)((_color_sec>>16) & 0xFF))*_cronixieSecMultiplier);
uint8_t gCorr = (int)(((double)((_color_sec>>8) & 0xFF))*_cronixieSecMultiplier);
uint8_t bCorr = (int)(((double)((_color_sec) & 0xFF))*_cronixieSecMultiplier);
uint8_t wCorr = (int)(((double)((_color_sec>>24) & 0xFF))*_cronixieSecMultiplier);
byte rCorr = (int)(((double)((_color_sec>>16) & 0xFF))*_cronixieSecMultiplier);
byte gCorr = (int)(((double)((_color_sec>>8) & 0xFF))*_cronixieSecMultiplier);
byte bCorr = (int)(((double)((_color_sec) & 0xFF))*_cronixieSecMultiplier);
byte wCorr = (int)(((double)((_color_sec>>24) & 0xFF))*_cronixieSecMultiplier);
for (int j=o; j< o+19; j++)
{
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);
}
@@ -1999,7 +2005,7 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
if (_cronixieMode)
{
if(i>6)return 0;
uint8_t o = 10*i;
byte o = 10*i;
switch(_cronixieDigits[i])
{
case 0: i=o+5; break;
@@ -2024,7 +2030,7 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
#endif
}
void WS2812FX::setBrightness(uint8_t b)
void WS2812FX::setBrightness(byte b)
{
_brightness = constrain(b, BRIGHTNESS_MIN, BRIGHTNESS_MAX);
NeoPixelBrightnessBus::SetBrightness(_brightness);
@@ -2034,12 +2040,17 @@ void WS2812FX::setBrightness(uint8_t b)
void WS2812FX::show()
{
#ifdef ARDUINO_ARCH_ESP32
#ifdef WORKAROUND_ESP32_BITBANG
delay(1);
portDISABLE_INTERRUPTS(); //this is a workaround to prevent flickering (see https://github.com/adafruit/Adafruit_NeoPixel/issues/139)
#endif
#endif
NeoPixelBrightnessBus::Show();
#ifdef ARDUINO_ARCH_ESP32
#ifdef WORKAROUND_ESP32_BITBANG
portENABLE_INTERRUPTS();
#else
NeoPixelBrightnessBus::Show();
#endif
#endif
}
@@ -2059,13 +2070,13 @@ void WS2812FX::begin()
//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;
return w;
}
uint8_t WS2812FX::maxval (uint8_t v, uint8_t w)
byte WS2812FX::maxval (byte v, byte w)
{
if (w > v) return w;
return v;

View File

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

View File

@@ -46,7 +46,7 @@
if (this.readyState == 4) {
if (this.status == 200) {
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.SG.value = this.responseXML.getElementsByTagName('cl')[1].childNodes[0].nodeValue;
d.Cf.SB.value = this.responseXML.getElementsByTagName('cl')[2].childNodes[0].nodeValue;
@@ -69,7 +69,7 @@
nState = 0;
nState = (this.responseXML.getElementsByTagName('nr')[0].innerHTML)!=0?1: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();
}
}

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()">
<form id="form_s" name="Sf" method="post">
<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>
<h3>Connect to existing network</h3>
Network name (SSID, empty to not connect): <br><input name="CSSID" maxlength="32"> <br>
Network password: <br> <input type="password" name="CPASS" maxlength="63"> <br>
Static IP (leave at 0.0.0.0 for DHCP): <br>
<input name="CSIP0" type="number" min="0" max="255" required> .
<input name="CSIP1" type="number" min="0" max="255" required> .
<input name="CSIP2" type="number" min="0" max="255" required> .
<input name="CSIP3" type="number" min="0" max="255" required> <br>
Static gateway: <br>
<input name="CSGW0" type="number" min="0" max="255" required> .
<input name="CSGW1" type="number" min="0" max="255" required> .
<input name="CSGW2" type="number" min="0" max="255" required> .
<input name="CSGW3" type="number" min="0" max="255" required> <br>
Static subnet mask: <br>
<input name="CSSN0" type="number" min="0" max="255" required> .
<input name="CSSN1" type="number" min="0" max="255" required> .
<input name="CSSN2" type="number" min="0" max="255" required> .
<input name="CSSN3" type="number" min="0" max="255" required> <br>
mDNS address (leave empty for no mDNS): <br/>
http:// <input name="CMDNS" maxlength="32"> .local <br>
Try connecting before opening AP for: <input name="APWTM" type="number" min="0" max="255" required> s <br>
Client IP: <span class="sip"> Not connected </span> <br>
Network name (SSID, empty to not connect): <br><input name="CS" maxlength="32"><br>
Network password: <br> <input type="password" name="CP" maxlength="63"><br>
Static IP (leave at 0.0.0.0 for DHCP):<br>
<input name="I0" type="number" min="0" max="255" required> .
<input name="I1" type="number" min="0" max="255" required> .
<input name="I2" type="number" min="0" max="255" required> .
<input name="I3" type="number" min="0" max="255" required><br>
Static gateway:<br>
<input name="G0" type="number" min="0" max="255" required> .
<input name="G1" type="number" min="0" max="255" required> .
<input name="G2" type="number" min="0" max="255" required> .
<input name="G3" type="number" min="0" max="255" required><br>
Static subnet mask:<br>
<input name="S0" type="number" min="0" max="255" required> .
<input name="S1" type="number" min="0" max="255" required> .
<input name="S2" type="number" min="0" max="255" required> .
<input name="S3" type="number" min="0" max="255" required><br>
mDNS address (leave empty for no mDNS):<br/>
http:// <input name="CM" maxlength="32"> .local<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>
<h3>Configure Access Point</h3>
AP SSID (leave empty for no AP): <br> <input name="APSSID" maxlength="32"> <br>
Hide AP name: <input type="checkbox" name="APHSSID"> <br>
AP password (leave empty for open): <br> <input type="password" name="APPASS" maxlength="63"> <br>
Access Point WiFi channel: <input name="APCHAN" type="number" min="1" max="13" required> <br>
AP IP: <span class="sip"> Not active </span> <hr>
<button type="button" onclick="B()">Back</button><button type="submit" name="SUBM">Save & Reboot</button>
AP SSID (leave empty for no AP):<br> <input name="AS" maxlength="32"><br>
Hide AP name: <input type="checkbox" name="AH"><br>
AP password (leave empty for open):<br> <input type="password" name="AP" maxlength="63"> <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>
<button type="button" onclick="B()">Back</button><button type="submit">Save & Reboot</button>
</form>
</body>
</html>
@@ -83,46 +83,46 @@ const char PAGE_settings_leds1[] PROGMEM = R"=====(
<body onload="GetV()">
<form id="form_s" name="Sf" method="post">
<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>
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>
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:
<input name="CLDFR" type="number" min="0" max="255" required>
<input name="CLDFG" type="number" min="0" max="255" required>
<input name="CLDFB" type="number" min="0" max="255" required> <br>
Default brightness: <input name="CLDFA" 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 effect ID: <input name="FXDEF" type="number" min="0" max="57" required> <br>
Default effect speed: <input name="SXDEF" type="number" min="0" max="255" required> <br>
Default effect intensity: <input name="IXDEF" type="number" min="0" max="255" required> <br>
<input name="CR" type="number" min="0" max="255" required>
<input name="CG" type="number" min="0" max="255" required>
<input name="CB" type="number" min="0" max="255" required><br>
Default brightness: <input name="CA" type="number" min="0" max="255" required> (0-255)<br>
Default white value (only RGBW, -1 to disable): <input name="CW" type="number" min="-1" max="255" required><br>
Default effect ID: <input name="FX" type="number" min="0" max="57" required> <br>
Default effect speed: <input name="SX" type="number" min="0" max="255" required> <br>
Default effect intensity: <input name="IX" type="number" min="0" max="255" required> <br>
Default secondary RGB(W):<br>
<input name="CSECR" type="number" min="0" max="255" required>
<input name="CSECG" type="number" min="0" max="255" required>
<input name="CSECB" type="number" min="0" max="255" required>
<input name="CSECW" type="number" min="0" max="255" required><br>
Ignore and use current color, brightness and effects: <input type="checkbox" name="CBEOR"> <br>
Turn on after power up/reset: <input type="checkbox" name="BOOTN"> <br>
Use Gamma correction for brightness: <input type="checkbox" name="GCBRI"> <br>
Use Gamma correction for color: <input type="checkbox" name="GCRGB"> <br>
Brightness factor: <input name="NRBRI" type="number" min="0" max="255" required> %
<input name="SR" type="number" min="0" max="255" required>
<input name="SG" type="number" min="0" max="255" required>
<input name="SB" type="number" min="0" max="255" required>
<input name="SW" type="number" min="0" max="255" required><br>
Ignore and use current color, brightness and effects: <input type="checkbox" name="IS"><br>
Turn on after power up/reset: <input type="checkbox" name="BO"><br>
Use Gamma correction for brightness: <input type="checkbox" name="GB"><br>
Use Gamma correction for color: <input type="checkbox" name="GC"><br>
Brightness factor: <input name="BF" type="number" min="0" max="255" required> %
<h3>Transitions</h3>
Fade: <input type="checkbox" name="TFADE"><br>
Sweep: <input type="checkbox" name="TSWEE"> Invert direction: <input type="checkbox" name="TSDIR"><br>
Transition Delay: <input name="TDLAY" maxlength="5" size="2"> ms
Fade: <input type="checkbox" name="TF"><br>
Sweep: <input type="checkbox" name="TS"> Invert direction: <input type="checkbox" name="TI"><br>
Transition Delay: <input name="TD" maxlength="5" size="2"> ms
<h3>Timed light</h3>
Default Duration: <input name="TLDUR" type="number" min="1" max="255" required> min<br>
Default Target brightness: <input name="TLBRI" type="number" min="0" max="255" required><br>
Fade down: <input type="checkbox" name="TLFDE"><br>
Default Duration: <input name="TL" type="number" min="1" max="255" required> min<br>
Default Target brightness: <input name="TB" type="number" min="0" max="255" required><br>
Fade down: <input type="checkbox" name="TW"><br>
<h3>Advanced</h3>
Default overlay ID: <input name="OLDEF" type="number" min="0" max="255" required> <br>
WARLS offset: <input name="WOFFS" type="number" min="-255" max="255" required><hr>
<button type="button" onclick="B()">Back</button><button type="submit" name="SUBM">Save</button>
Reverse LED order (rotate 180): <input type="checkbox" name="RV"><br>
Init LEDs after WiFi: <input type="checkbox" name="EI"><br>
WARLS offset: <input name="WO" type="number" min="-255" max="255" required><hr>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
</form>
</body>
</html>
)=====";
const char PAGE_settings_ui0[] PROGMEM = R"=====(
@@ -137,12 +137,12 @@ const char PAGE_settings_ui1[] PROGMEM = R"=====(
<body onload="S()">
<form id="form_s" name="Sf" method="post">
<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>
Server description: <input name="DESC" maxlength="32"><br>
Use HSB sliders instead of RGB by default: <input type="checkbox" name="COLMD"><br>
Server description: <input name="DS" maxlength="32"><br>
Use HSB sliders instead of RGB by default: <input type="checkbox" name="MD"><br>
Color Theme:
<select name="THEME" onchange="Ct()">
<select name="TH" onchange="Ct()">
<option value="0" selected>Night</option>
<option value="1">Modern</option>
<option value="2">Bright</option>
@@ -154,7 +154,7 @@ Color Theme:
<option value="8">Air</option>
<option value="9">Nixie</option>
<option value="10">Terminal</option>
<option value="11">Placeholder</option>
<option value="11">C64</option>
<option value="12">Placeholder</option>
<option value="13">Placeholder</option>
<option value="14">The End</option>
@@ -162,15 +162,15 @@ Color Theme:
</select><br>
<div id="cth">
Please specify your custom hex colors (e.g. FF0000 for red)<br>
Custom accent color: <input maxlength=9 name="CCOL0"><br>
Custom background: <input maxlength=9 name="CCOL1"><br>
Custom panel color: <input maxlength=9 name="CCOL2"><br>
Custom icon color: <input maxlength=9 name="CCOL3"><br>
Custom shadow: <input maxlength=9 name="CCOL4"><br>
Custom text color: <input maxlength=9 name="CCOL5"><br></div>
Use font: <input maxlength=32 name="CFONT"><br>
Custom accent color: <input maxlength=9 name="C0"><br>
Custom background: <input maxlength=9 name="C1"><br>
Custom panel color: <input maxlength=9 name="C2"><br>
Custom icon color: <input maxlength=9 name="C3"><br>
Custom shadow: <input maxlength=9 name="C4"><br>
Custom text color: <input maxlength=9 name="C5"><br></div>
Use font: <input maxlength=32 name="CF"><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>
</body>
</html>
@@ -186,39 +186,34 @@ const char PAGE_settings_sync1[] PROGMEM = R"=====(
<body onload="GetV()">
<form id="form_s" name="Sf" method="post">
<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>
<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>
UDP Port: <input name="NUDPP" 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>
Send notifications on direct change: <input type="checkbox" name="NSDIR"> <br>
Send notifications on button press: <input type="checkbox" name="NSBTN"> <br>
Send Alexa notifications: <input type="checkbox" name="NSALX"> <br>
<!--Send Philips Hue change notifications: <input type="checkbox" name="NSHUE">-->
UDP Port: <input name="UP" maxlength="5" size="4"><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="SD"><br>
Send notifications on button press: <input type="checkbox" name="SB"><br>
Send Alexa notifications: <input type="checkbox" name="SA"><br>
Send Philips Hue change notifications: <input type="checkbox" name="SH"><br>
Send notifications twice: <input type="checkbox" name="S2">
<h3>Alexa Voice Assistant</h3>
Emulate Alexa device: <input type="checkbox" name="ALEXA"> <br>
Alexa invocation name: <input name="AINVN" maxlength="32"><br>
Emulate Alexa device: <input type="checkbox" name="AL"><br>
Alexa invocation name: <input name="AI" maxlength="32"><br>
<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>
<input name="HUIP0" type="number" min="0" max="255" required> .
<input name="HUIP1" type="number" min="0" max="255" required> .
<input name="HUIP2" type="number" min="0" max="255" required> .
<input name="HUIP3" 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>
<input name="H0" type="number" min="0" max="255" required> .
<input name="H1" type="number" min="0" max="255" required> .
<input name="H2" type="number" min="0" max="255" required> .
<input name="H3" type="number" min="0" max="255" required><br>
<b>Press the pushlink button on the bridge, after that save this page!</b><br>
(when first connecting)<br>
<i> Use 0 for group and light to turn off sending/receiving </i><br>
Update Hue group <input name="HUEGR" type="number" min="0" max="99" required> <br>
Send <input type="checkbox" name="HUEIO"> On/Off, <input type="checkbox" name="HUEBR"> Brightness, and <input type="checkbox" name="HUECL"> Color<br>
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>
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>
Poll Hue light <input name="HL" type="number" min="1" max="99" required> every <input name="HI" type="number" min="100" max="65000" required> ms: <input type="checkbox" name="HP"><br>
Then, receive <input type="checkbox" name="HO"> On/Off, <input type="checkbox" name="HB"> Brightness, and <input type="checkbox" name="HC"> Color<br>
Hue status: <span class="hms"> Internal ESP Error! </span><hr>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
</form>
</body>
</html>
@@ -227,77 +222,84 @@ Hue status: <span class="hms"> Internal ESP error! </span>-->
const char PAGE_settings_time0[] PROGMEM = R"=====(
<!DOCTYPE html>
<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"=====(
</head>
<body onload="GetV()">
<body onload="S()">
<form id="form_s" name="Sf" method="post">
<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>
Get time from NTP server: <input type="checkbox" name="NTPON"><br>
<!--NTP server: <input name="NTPSR" maxlength="32"><br>
Get time from NTP server: <input type="checkbox" name="NT"><br>
Use 24h format: <input type="checkbox" name="CF"><br>
Time zone:
<select name="TZONE">
<option value="1" selected>GMT(UTC)</option>
<option value="2">GMT/BST</option>
<option value="3">CET/CEST</option>
<option value="4">EET/EEST</option>
<option value="5">US-EST/EDT</option>
<option value="6">US-CST/CDT</option>
<option value="7">US-MST/MDT</option>
<option value="8">US-AZ</option>
<option value="9">US-PST/PDT</option>
<option value="10">CST(AWST)</option>
<option value="11">JST(KST)</option>
<option value="12">AEST/AEDT</option>
<option value="13">NZST/NZDT</option>
<select name="TZ">
<option value="0" selected>GMT(UTC)</option>
<option value="1">GMT/BST</option>
<option value="2">CET/CEST</option>
<option value="3">EET/EEST</option>
<option value="4">US-EST/EDT</option>
<option value="5">US-CST/CDT</option>
<option value="6">US-MST/MDT</option>
<option value="7">US-AZ</option>
<option value="8">US-PST/PDT</option>
<option value="9">CST(AWST)</option>
<option value="10">JST(KST)</option>
<option value="11">AEST/AEDT</option>
<option value="12">NZST/NZDT</option>
</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>.
<h3>Weather</h3>
Coming soon! Not yet implemented!
<!--Get yours on open weather API.<br>
City code: <input name="WCITY" maxlength="32"><br>
Change color depending on weather: <input type="checkbox" name="WCCOL"><br>
Daylight Emulation: <input type="checkbox" name="WDAYL"><br>
Reverse (turns on at sunset): <input type="checkbox" name="WREVL"><br>
Fade duration: <input name="WSDUR" type="number" min="0" max="255" required><br>
Sunrise/Sunset Offset: <input name="WSOFS" type="number" min="-255" max="255" required>-->
<h3>Clock</h3>
Clock Overlay:
<select name="OL" onchange="Cs()">
<option value="0" id="cn" selected>None</option>
<option value="1">Static color</option>
<option value="2" id="ca">Analog Clock</option>
<option value="3">Single Digit Clock</option>
<option value="4" id="cc">Cronixie Clock</option>
</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>
Coming soon! Not yet implemented!
<!--Define API macros here:<br>
0: <input name="MCR00" maxlength="64"><br>
1: <input name="MCR01" maxlength="64"><br>
2: <input name="MCR02" maxlength="64"><br>
3: <input name="MCR03" maxlength="64"><br>
4: <input name="MCR04" maxlength="64"><br>
5: <input name="MCR05" maxlength="64"><br>
6: <input name="MCR06" maxlength="64"><br>
7: <input name="MCR07" maxlength="64"><br>
8: <input name="MCR08" maxlength="64"><br>
9: <input name="MCR09" maxlength="64"><br>
10: <input name="MCR10" maxlength="64"><br>
11: <input name="MCR11" maxlength="64"><br>
12: <input name="MCR12" maxlength="64"><br>
13: <input name="MCR13" maxlength="64"><br>
14: <input name="MCR14" maxlength="64"><br>
15: <input name="MCR15" maxlength="64"><br>
<br>
<i>Use -1 to use the default action instead of a macro</i><br>
<--1st Time-Controlled Macro:
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>
<--Emulate 2nd Alexa device:
Emulate 3rd Alexa device:
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>
Define API macros here:<br>
1: <input name="M1" maxlength="64"><br>
2: <input name="M2" maxlength="64"><br>
3: <input name="M3" maxlength="64"><br>
4: <input name="M4" maxlength="64"><br>
5: <input name="M5" maxlength="64"><br>
6: <input name="M6" maxlength="64"><br>
7: <input name="M7" maxlength="64"><br>
8: <input name="M8" maxlength="64"><br>
9: <input name="M9" maxlength="64"><br>
10: <input name="M10" maxlength="64"><br>
11: <input name="M11" maxlength="64"><br>
12: <input name="M12" maxlength="64"><br>
13: <input name="M13" maxlength="64"><br>
14: <input name="M14" maxlength="64"><br>
15: <input name="M15" maxlength="64"><br>
16: <input name="M16" maxlength="64"><br><br>
<i>Use 0 for the default action instead of a macro</i><br>
Time controlled macros coming soon!<br>
Boot Macro: <input name="MB" type="number" min="0" max="16" required><br>
Alexa On/Off Macros: <input name="A0" type="number" min="0" max="16" required> <input name="A1" type="number" min="0" max="16" required><br>
Button Macro: <input name="MP" type="number" min="0" max="16" required> Long Press: <input name="ML" type="number" min="0" max="16" required><br>
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>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
</form>
</body>
</html>
@@ -314,26 +316,26 @@ const char PAGE_settings_sec1[] PROGMEM = R"=====(
<body onload="GetV()">
<form id="form_s" name="Sf" method="post">
<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>
Enable OTA lock: <input type="checkbox" name="NOOTA"><br>
Passphrase: <input type="password" name="OPASS" maxlength="32"><br>
Enable OTA lock: <input type="checkbox" name="NO"><br>
Passphrase: <input type="password" name="OP" maxlength="32"><br>
To enable OTA, for security reasons you need to also enter the correct password!<br>
The password may/should be changed when OTA is enabled.<br>
<b>Disable OTA when not in use, otherwise an attacker could reflash device software!</b><br>
The password should be changed when OTA is enabled.<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>
Deny access to WiFi settings if locked: <input type="checkbox" name="OWIFI"><br><br>
Disable recovery AP: <input type="checkbox" name="NORAP"><br>
In case of a connection error there will be no wireless recovery possible!<br>
Deny access to WiFi settings if locked: <input type="checkbox" name="OW"><br><br>
Disable recovery AP: <input type="checkbox" name="NA"><br>
In case of an error there will be no wireless recovery possible!<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>
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>
<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>
<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>
<i>Licensed under the MIT license</i><br><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>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>
<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>
</body>
</html>

View File

@@ -281,9 +281,9 @@ void setTime(time_t t) {
nextSyncTime = (uint32_t)t + syncInterval;
Status = timeSet;
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);
//it is converted to years since 1970
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.Minute = min;
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) {

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
void setTime(time_t t);
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);
/* 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.
struct TimeChangeRule
{
char abbrev[6]; //five chars max
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 month; //1=Jan, 2=Feb, ... 12=Dec
uint8_t hour; //0-23
int offset; //offset from UTC in minutes
int16_t offset; //offset from UTC in minutes
};
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>
<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>
<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'>
<input type='file' name='update'>
<input type='submit' value='Update!'>

View File

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

View File

@@ -1,9 +1,21 @@
/*
* 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()
{
for (int i = 0; i < EEPSIZE; i++)
@@ -26,59 +38,60 @@ void saveSettingsToEEPROM()
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)
{
EEPROM.write(i, clientpass.charAt(i-32));
EEPROM.write(i, clientPass.charAt(i-32));
}
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)
{
EEPROM.write(i, apssid.charAt(i-128));
EEPROM.write(i, apSSID.charAt(i-128));
}
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(225, nightlightFade);
EEPROM.write(226, notifyDirectDefault);
EEPROM.write(227, apchannel);
EEPROM.write(228, aphide);
EEPROM.write(229, ledcount);
EEPROM.write(227, apChannel);
EEPROM.write(228, apHide);
EEPROM.write(229, ledCount);
EEPROM.write(230, notifyButton);
//231 was notifyNightlight
EEPROM.write(231, notifyTwice);
EEPROM.write(232, buttonEnabled);
//233 reserved for first boot flag
EEPROM.write(234, staticip[0]);
EEPROM.write(235, staticip[1]);
EEPROM.write(236, staticip[2]);
EEPROM.write(237, staticip[3]);
EEPROM.write(238, staticgateway[0]);
EEPROM.write(239, staticgateway[1]);
EEPROM.write(240, staticgateway[2]);
EEPROM.write(241, staticgateway[3]);
EEPROM.write(242, staticsubnet[0]);
EEPROM.write(243, staticsubnet[1]);
EEPROM.write(244, staticsubnet[2]);
EEPROM.write(245, staticsubnet[3]);
EEPROM.write(246, col_s[0]);
EEPROM.write(247, col_s[1]);
EEPROM.write(248, col_s[2]);
EEPROM.write(249, bri_s);
EEPROM.write(234, staticIP[0]);
EEPROM.write(235, staticIP[1]);
EEPROM.write(236, staticIP[2]);
EEPROM.write(237, staticIP[3]);
EEPROM.write(238, staticGateway[0]);
EEPROM.write(239, staticGateway[1]);
EEPROM.write(240, staticGateway[2]);
EEPROM.write(241, staticGateway[3]);
EEPROM.write(242, staticSubnet[0]);
EEPROM.write(243, staticSubnet[1]);
EEPROM.write(244, staticSubnet[2]);
EEPROM.write(245, staticSubnet[3]);
EEPROM.write(246, colS[0]);
EEPROM.write(247, colS[1]);
EEPROM.write(248, colS[2]);
EEPROM.write(249, briS);
EEPROM.write(250, receiveNotificationBrightness);
EEPROM.write(251, fadeTransition);
EEPROM.write(252, reverseMode);
EEPROM.write(253, (transitionDelay >> 0) & 0xFF);
EEPROM.write(254, (transitionDelay >> 8) & 0xFF);
EEPROM.write(255, briMultiplier);
//255,250,231,230,226 notifier bytes
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(289, otaLock);
@@ -92,8 +105,8 @@ void saveSettingsToEEPROM()
EEPROM.write(325, effectSpeedDefault);
EEPROM.write(326, effectIntensityDefault);
EEPROM.write(327, ntpEnabled);
//328 reserved for timezone setting
//329 reserved for dst setting
EEPROM.write(328, currentTimezone);
EEPROM.write(329, useAMPM);
EEPROM.write(330, useGammaCorrectionBri);
EEPROM.write(331, useGammaCorrectionRGB);
EEPROM.write(332, overlayDefault);
@@ -103,33 +116,37 @@ void saveSettingsToEEPROM()
EEPROM.write(i, alexaInvocationName.charAt(i-334));
}
EEPROM.write(366, alexaNotify);
EEPROM.write(367, arlsSign);
EEPROM.write(367, (arlsOffset>=0));
EEPROM.write(368, abs(arlsOffset));
EEPROM.write(369, turnOnAtBoot);
EEPROM.write(370, useHSBDefault);
EEPROM.write(371, white_s);
EEPROM.write(371, whiteS);
EEPROM.write(372, useRGBW);
EEPROM.write(373, sweepTransition);
EEPROM.write(374, sweepDirection);
EEPROM.write(375, apWaitTimeSecs);
EEPROM.write(376, recoveryAPDisabled);
EEPROM.write(377, EEPVER); //eeprom was updated to latest
EEPROM.write(378, col_sec_s[0]);
EEPROM.write(379, col_sec_s[1]);
EEPROM.write(380, col_sec_s[2]);
EEPROM.write(381, white_sec_s);
EEPROM.write(382, cc_index1);
EEPROM.write(383, cc_index2);
EEPROM.write(384, cc_numPrimary);
EEPROM.write(385, cc_numSecondary);
EEPROM.write(386, cc_fromStart);
EEPROM.write(387, cc_fromEnd);
EEPROM.write(388, cc_step);
EEPROM.write(378, colSecS[0]);
EEPROM.write(379, colSecS[1]);
EEPROM.write(380, colSecS[2]);
EEPROM.write(381, whiteSecS);
EEPROM.write(382, ccIndex1);
EEPROM.write(383, ccIndex2);
EEPROM.write(384, ccNumPrimary);
EEPROM.write(385, ccNumSecondary);
EEPROM.write(386, ccFromStart);
EEPROM.write(387, ccFromEnd);
EEPROM.write(388, ccStep);
EEPROM.write(389, bootPreset);
EEPROM.write(390, aOtaEnabled);
EEPROM.write(391, receiveNotificationColor);
EEPROM.write(392, receiveNotificationEffects);
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++){
int in = 900+k*8;
@@ -143,6 +160,53 @@ void saveSettingsToEEPROM()
{
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();
}
@@ -157,77 +221,78 @@ void loadSettingsFromEEPROM(bool first)
}
int lastEEPROMversion = EEPROM.read(377); //last EEPROM version before update
clientssid = "";
clientSSID = "";
for (int i = 0; i < 32; ++i)
{
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)
{
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)
{
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)
{
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)
{
if (EEPROM.read(i) == 0) break;
appass += char(EEPROM.read(i));
apPass += char(EEPROM.read(i));
}
nightlightDelayMins = EEPROM.read(224);
nightlightFade = EEPROM.read(225);
notifyDirectDefault = EEPROM.read(226);
notifyDirect = notifyDirectDefault;
apchannel = EEPROM.read(227);
if (apchannel > 13 || apchannel < 1) apchannel = 1;
aphide = EEPROM.read(228);
if (aphide > 1) aphide = 1;
ledcount = EEPROM.read(229); if (ledcount > LEDCOUNT) ledcount = LEDCOUNT;
apChannel = EEPROM.read(227);
if (apChannel > 13 || apChannel < 1) apChannel = 1;
apHide = EEPROM.read(228);
if (apHide > 1) apHide = 1;
ledCount = EEPROM.read(229); if (ledCount > LEDCOUNT) ledCount = LEDCOUNT;
notifyButton = EEPROM.read(230);
//231 was notifyNightlight
notifyTwice = EEPROM.read(231);
buttonEnabled = EEPROM.read(232);
staticip[0] = EEPROM.read(234);
staticip[1] = EEPROM.read(235);
staticip[2] = EEPROM.read(236);
staticip[3] = EEPROM.read(237);
staticgateway[0] = EEPROM.read(238);
staticgateway[1] = EEPROM.read(239);
staticgateway[2] = EEPROM.read(240);
staticgateway[3] = EEPROM.read(241);
staticsubnet[0] = EEPROM.read(242);
staticsubnet[1] = EEPROM.read(243);
staticsubnet[2] = EEPROM.read(244);
staticsubnet[3] = EEPROM.read(245);
col_s[0] = EEPROM.read(246); col[0] = col_s[0];
col_s[1] = EEPROM.read(247); col[1] = col_s[1];
col_s[2] = EEPROM.read(248); col[2] = col_s[2];
bri_s = EEPROM.read(249); bri = bri_s;
staticIP[0] = EEPROM.read(234);
staticIP[1] = EEPROM.read(235);
staticIP[2] = EEPROM.read(236);
staticIP[3] = EEPROM.read(237);
staticGateway[0] = EEPROM.read(238);
staticGateway[1] = EEPROM.read(239);
staticGateway[2] = EEPROM.read(240);
staticGateway[3] = EEPROM.read(241);
staticSubnet[0] = EEPROM.read(242);
staticSubnet[1] = EEPROM.read(243);
staticSubnet[2] = EEPROM.read(244);
staticSubnet[3] = EEPROM.read(245);
colS[0] = EEPROM.read(246); col[0] = colS[0];
colS[1] = EEPROM.read(247); col[1] = colS[1];
colS[2] = EEPROM.read(248); col[2] = colS[2];
briS = EEPROM.read(249); bri = briS;
if (!EEPROM.read(369) && first)
{
bri = 0; bri_last = bri_s;
bri = 0; briLast = briS;
}
receiveNotificationBrightness = EEPROM.read(250);
fadeTransition = EEPROM.read(251);
reverseMode = EEPROM.read(252);
transitionDelay = ((EEPROM.read(253) << 0) & 0xFF) + ((EEPROM.read(254) << 8) & 0xFF00);
briMultiplier = EEPROM.read(255);
otapass = "";
otaPass = "";
for (int i = 256; i < 288; ++i)
{
if (EEPROM.read(i) == 0) break;
otapass += char(EEPROM.read(i));
otaPass += char(EEPROM.read(i));
}
nightlightTargetBri = EEPROM.read(288);
otaLock = EEPROM.read(289);
@@ -241,6 +306,8 @@ void loadSettingsFromEEPROM(bool first)
effectDefault = EEPROM.read(324); effectCurrent = effectDefault;
effectSpeedDefault = EEPROM.read(325); effectSpeed = effectSpeedDefault;
ntpEnabled = EEPROM.read(327);
currentTimezone = EEPROM.read(328);
useAMPM = EEPROM.read(329);
useGammaCorrectionBri = EEPROM.read(330);
useGammaCorrectionRGB = EEPROM.read(331);
overlayDefault = EEPROM.read(332);
@@ -252,12 +319,11 @@ void loadSettingsFromEEPROM(bool first)
alexaInvocationName += char(EEPROM.read(i));
}
alexaNotify = EEPROM.read(366);
arlsSign = EEPROM.read(367);
arlsOffset = EEPROM.read(368);
if (!arlsSign) arlsOffset = -arlsOffset;
if (!EEPROM.read(367)) arlsOffset = -arlsOffset;
turnOnAtBoot = EEPROM.read(369);
useHSBDefault = EEPROM.read(370);
white_s = EEPROM.read(371); white = white_s;
whiteS = EEPROM.read(371); white = whiteS;
useRGBW = EEPROM.read(372);
sweepTransition = EEPROM.read(373);
sweepDirection = EEPROM.read(374);
@@ -267,18 +333,18 @@ void loadSettingsFromEEPROM(bool first)
}
//377 = lastEEPROMversion
if (lastEEPROMversion > 1) {
col_sec_s[0] = EEPROM.read(378); col_sec[0] = col_sec_s[0];
col_sec_s[1] = EEPROM.read(379); col_sec[1] = col_sec_s[1];
col_sec_s[2] = EEPROM.read(380); col_sec[2] = col_sec_s[2];
white_sec_s = EEPROM.read(381); white_sec = white_sec_s;
cc_index1 = EEPROM.read(382);
cc_index2 = EEPROM.read(383);
cc_numPrimary = EEPROM.read(384);
cc_numSecondary = EEPROM.read(385);
cc_fromStart = EEPROM.read(386);
cc_fromEnd = EEPROM.read(387);
cc_step = EEPROM.read(388);
strip.setCustomChase(cc_index1, cc_index2, cc_start, cc_numPrimary, cc_numSecondary, cc_step, cc_fromStart, cc_fromEnd);
colSecS[0] = EEPROM.read(378); colSec[0] = colSecS[0];
colSecS[1] = EEPROM.read(379); colSec[1] = colSecS[1];
colSecS[2] = EEPROM.read(380); colSec[2] = colSecS[2];
whiteSecS = EEPROM.read(381); whiteSec = whiteSecS;
ccIndex1 = EEPROM.read(382);
ccIndex2 = EEPROM.read(383);
ccNumPrimary = EEPROM.read(384);
ccNumSecondary = EEPROM.read(385);
ccFromStart = EEPROM.read(386);
ccFromEnd = EEPROM.read(387);
ccStep = EEPROM.read(388);
strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd);
}
if (lastEEPROMversion > 3) {
effectIntensityDefault = EEPROM.read(326); effectIntensity = effectIntensityDefault;
@@ -291,11 +357,69 @@ void loadSettingsFromEEPROM(bool first)
if (EEPROM.read(i) == 0) break;
cssFont += char(EEPROM.read(i));
}
} else //keep receiving notification behavior from pre0.5.0 after update
{
receiveNotificationColor = receiveNotificationBrightness;
receiveNotificationEffects = receiveNotificationBrightness;
}
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);
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)
//400 - 899 reserved
@@ -311,6 +435,9 @@ void loadSettingsFromEEPROM(bool first)
//custom macro memory (16 slots/ each 64byte)
//1024-2047 reserved
//user MOD memory
//2944 - 3071 reserved
useHSB = useHSBDefault;
@@ -324,7 +451,7 @@ void loadSettingsFromEEPROM(bool first)
//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
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 > 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[2] = EEPROM.read(i+4);
white = EEPROM.read(i+5);
col_sec[0] = EEPROM.read(i+6);
col_sec[1] = EEPROM.read(i+7);
col_sec[2] = EEPROM.read(i+8);
white_sec = EEPROM.read(i+9);
colSec[0] = EEPROM.read(i+6);
colSec[1] = EEPROM.read(i+7);
colSec[2] = EEPROM.read(i+8);
whiteSec = EEPROM.read(i+9);
}
if (loadFX)
{
effectCurrent = EEPROM.read(i+10);
effectSpeed = EEPROM.read(i+11);
effectIntensity = EEPROM.read(i+16);
cc_numPrimary = EEPROM.read(i+12);
cc_numSecondary = EEPROM.read(i+13);
cc_fromEnd = EEPROM.read(i+14);
cc_fromStart = (EEPROM.read(i+14)<2);
cc_step = EEPROM.read(i+15);
strip.setCustomChase(cc_index1, cc_index2, cc_start, cc_numPrimary, cc_numSecondary, cc_step, cc_fromStart, cc_fromEnd);
ccNumPrimary = EEPROM.read(i+12);
ccNumSecondary = EEPROM.read(i+13);
ccFromEnd = EEPROM.read(i+14);
ccFromStart = (EEPROM.read(i+14)<2);
ccStep = EEPROM.read(i+15);
strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd);
strip.setMode(effectCurrent);
strip.setSpeed(effectSpeed);
strip.setIntensity(effectIntensity);
}
}
void savePreset(uint8_t index)
void savePreset(byte index)
{
if (index > 25) return;
if (index < 1) {saveSettingsToEEPROM();return;}
@@ -370,32 +497,43 @@ void savePreset(uint8_t index)
EEPROM.write(i+3, col[1]);
EEPROM.write(i+4, col[2]);
EEPROM.write(i+5, white);
EEPROM.write(i+6, col_sec[0]);
EEPROM.write(i+7, col_sec[1]);
EEPROM.write(i+8, col_sec[2]);
EEPROM.write(i+9, white_sec);
EEPROM.write(i+6, colSec[0]);
EEPROM.write(i+7, colSec[1]);
EEPROM.write(i+8, colSec[2]);
EEPROM.write(i+9, whiteSec);
EEPROM.write(i+10, effectCurrent);
EEPROM.write(i+11, effectSpeed);
EEPROM.write(i+12, cc_numPrimary);
EEPROM.write(i+13, cc_numSecondary);
uint8_t m = 1;
if (!cc_fromStart) m = 2;
if (!cc_fromEnd) m = 0;
EEPROM.write(i+12, ccNumPrimary);
EEPROM.write(i+13, ccNumSecondary);
byte m = 1;
if (!ccFromStart) m = 2;
if (!ccFromEnd) m = 0;
EEPROM.write(i+14, m);
EEPROM.write(i+15, cc_step);
EEPROM.write(i+15, ccStep);
EEPROM.write(i+16, effectIntensity);
EEPROM.commit();
}
void applyMacro(uint8_t index)
String loadMacro(byte index)
{
if (index > 15) return;
String mc="win&";
index-=1;
String m="";
if (index > 15) return m;
for (int i = 1024+64*index; i < 1088+64*index; i++)
{
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
if (!macroNotify) mc += "&NN";
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);
}
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;
int s = 1024+index*64;
for (int i = s; i < s+64; i++)
{
EEPROM.write(i, mc.charAt(i-s));
}
EEPROM.commit();
if (sing) EEPROM.commit();
}

View File

@@ -7,15 +7,15 @@ void XML_response()
String resp;
resp = resp + "<?xml version = \"1.0\" ?>";
resp = resp + "<vs>";
resp = resp + "<act>";
resp = resp + "<ac>";
if (nightlightActive && nightlightFade)
{
resp = resp + bri_t;
resp = resp + briT;
} else
{
resp = resp + bri;
}
resp = resp + "</act>";
resp = resp + "</ac>";
for (int i = 0; i < 3; i++)
{
@@ -49,14 +49,14 @@ void XML_response()
}
resp = resp + "</wv><md>";
resp = resp + useHSB;
resp = resp + "</md><desc>";
resp = resp + "</md><ds>";
resp = resp + serverDescription;
resp = resp + "</desc>";
resp = resp + "</ds>";
resp = resp + "</vs>";
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
DEBUG_PRINT("settings resp");
@@ -70,38 +70,39 @@ String getSettings(uint8_t subPage)
String v = ".value=";
String c = ".checked=";
String ih = ".innerHTML=";
String si = ".selectedIndex=";
if (subPage == 1) {
resp += ds + "CSSID" + v + "\"" + clientssid + "\";";
resp += ds + "CPASS" + v + "\"";
for (int i = 0; i < clientpass.length(); i++)
resp += ds + "CS" + v + "\"" + clientSSID + "\";";
resp += ds + "CP" + v + "\"";
for (int i = 0; i < clientPass.length(); i++)
{
resp += "*";
}
resp += "\";";
resp += ds + "CSIP0" + v + staticip[0] +";";
resp += ds + "CSIP1" + v + staticip[1] +";";
resp += ds + "CSIP2" + v + staticip[2] +";";
resp += ds + "CSIP3" + v + staticip[3] +";";
resp += ds + "CSGW0" + v + staticgateway[0] +";";
resp += ds + "CSGW1" + v + staticgateway[1] +";";
resp += ds + "CSGW2" + v + staticgateway[2] +";";
resp += ds + "CSGW3" + v + staticgateway[3] +";";
resp += ds + "CSSN0" + v + staticsubnet[0] +";";
resp += ds + "CSSN1" + v + staticsubnet[1] +";";
resp += ds + "CSSN2" + v + staticsubnet[2] +";";
resp += ds + "CSSN3" + v + staticsubnet[3] +";";
resp += ds + "CMDNS" + v + "\"" + cmdns + "\";";
resp += ds + "APWTM" + v + apWaitTimeSecs +";";
resp += ds + "APSSID" + v + "\"" + apssid + "\";";
resp += ds + "APHSSID" + c + aphide + ";";
resp += ds + "APPASS" + v + "\"";
for (int i = 0; i < clientpass.length(); i++)
resp += ds + "I0" + v + staticIP[0] +";";
resp += ds + "I1" + v + staticIP[1] +";";
resp += ds + "I2" + v + staticIP[2] +";";
resp += ds + "I3" + v + staticIP[3] +";";
resp += ds + "G0" + v + staticGateway[0] +";";
resp += ds + "G1" + v + staticGateway[1] +";";
resp += ds + "G2" + v + staticGateway[2] +";";
resp += ds + "G3" + v + staticGateway[3] +";";
resp += ds + "S0" + v + staticSubnet[0] +";";
resp += ds + "S1" + v + staticSubnet[1] +";";
resp += ds + "S2" + v + staticSubnet[2] +";";
resp += ds + "S3" + v + staticSubnet[3] +";";
resp += ds + "CM" + v + "\"" + cmDNS + "\";";
resp += ds + "AT" + v + apWaitTimeSecs +";";
resp += ds + "AS" + v + "\"" + apSSID + "\";";
resp += ds + "AH" + c + apHide + ";";
resp += ds + "AP" + v + "\"";
for (int i = 0; i < apPass.length(); i++)
{
resp += "*";
}
resp += "\";";
resp += ds + "APCHAN" + v + apchannel +";";
resp += ds + "AC" + v + apChannel +";";
resp += dg + "(\"sip\")[0]" + ih + "\"";
if (!WiFi.localIP()[0] == 0)
{
@@ -135,75 +136,118 @@ String getSettings(uint8_t subPage)
}
if (subPage == 2) {
resp += ds + "LEDCN" + v + ledcount +";";
resp += ds + "CLDFR" + v + col_s[0] +";";
resp += ds + "CLDFG" + v + col_s[1] +";";
resp += ds + "CLDFB" + v + col_s[2] +";";
resp += ds + "CLDFA" + v + bri_s +";";
resp += ds + "LC" + v + ledCount +";";
resp += ds + "CR" + v + colS[0] +";";
resp += ds + "CG" + v + colS[1] +";";
resp += ds + "CB" + v + colS[2] +";";
resp += ds + "CA" + v + briS +";";
if (useRGBW) {
resp += ds + "CLDFW" + v + white_s +";";
resp += ds + "CW" + v + whiteS +";";
} else {
resp += ds + "CLDFW" + v + "-1;";
resp += ds + "CW" + v + "-1;";
}
resp += ds + "CSECR" + v + col_sec_s[0] +";";
resp += ds + "CSECG" + v + col_sec_s[1] +";";
resp += ds + "CSECB" + v + col_sec_s[2] +";";
resp += ds + "CSECW" + v + white_s +";";
resp += ds + "BOOTN" + c + turnOnAtBoot +";";
resp += ds + "BOOTP" + v + bootPreset +";";
resp += ds + "FXDEF" + v + effectDefault +";";
resp += ds + "SXDEF" + v + effectSpeedDefault +";";
resp += ds + "IXDEF" + v + effectIntensityDefault +";";
resp += ds + "GCBRI" + c + useGammaCorrectionBri +";";
resp += ds + "GCRGB" + c + useGammaCorrectionRGB +";";
resp += ds + "TFADE" + c + fadeTransition +";";
resp += ds + "TSWEE" + c + sweepTransition +";";
resp += ds + "TSDIR" + c + !sweepDirection +";";
resp += ds + "TDLAY" + v + transitionDelay +";";
resp += ds + "NRBRI" + v + briMultiplier +";";
resp += ds + "TLBRI" + v + nightlightTargetBri +";";
resp += ds + "TLDUR" + v + nightlightDelayMins +";";
resp += ds + "TLFDE" + c + nightlightFade +";";
resp += ds + "OLDEF" + v + overlayDefault +";";
resp += ds + "WOFFS" + v + arlsOffset +";";
resp += ds + "SR" + v + colSecS[0] +";";
resp += ds + "SG" + v + colSecS[1] +";";
resp += ds + "SB" + v + colSecS[2] +";";
resp += ds + "SW" + v + whiteSecS +";";
resp += ds + "BO" + c + turnOnAtBoot +";";
resp += ds + "BP" + v + bootPreset +";";
resp += ds + "FX" + v + effectDefault +";";
resp += ds + "SX" + v + effectSpeedDefault +";";
resp += ds + "IX" + v + effectIntensityDefault +";";
resp += ds + "GB" + c + useGammaCorrectionBri +";";
resp += ds + "GC" + c + useGammaCorrectionRGB +";";
resp += ds + "TF" + c + fadeTransition +";";
resp += ds + "TS" + c + sweepTransition +";";
resp += ds + "TI" + c + !sweepDirection +";";
resp += ds + "TD" + v + transitionDelay +";";
resp += ds + "BF" + v + briMultiplier +";";
resp += ds + "TB" + v + nightlightTargetBri +";";
resp += ds + "TL" + v + nightlightDelayMins +";";
resp += ds + "TW" + c + nightlightFade +";";
resp += ds + "RV" + c + reverseMode +";";
resp += ds + "EI" + c + initLedsLast +";";
resp += ds + "WO" + v + arlsOffset +";";
}
if (subPage == 3)
{
resp += ds + "DESC" + v + "\"" + serverDescription + "\";";
resp += ds + "COLMD" + c + useHSBDefault + ";";
resp += ds + "THEME.selectedIndex=" + String(currentTheme) + ";";
resp += ds + "DS" + v + "\"" + serverDescription + "\";";
resp += ds + "MD" + c + useHSBDefault + ";";
resp += ds + "TH" + si + String(currentTheme) + ";";
for(int i=0;i<6;i++)
resp += ds + "CCOL" + i + v + "\"" + cssCol[i] + "\";";
resp += ds + "CFONT" + v + "\"" + cssFont + "\";";
resp += ds + "C" + i + v + "\"" + cssCol[i] + "\";";
resp += ds + "CF" + v + "\"" + cssFont + "\";";
}
if (subPage == 4)
{
resp += ds + "BTNON" + c + buttonEnabled +";";
resp += ds + "NUDPP" + v + udpPort +";";
resp += ds + "NRCBR" + c + receiveNotificationBrightness +";";
resp += ds + "NRCCL" + c + receiveNotificationColor +";";
resp += ds + "NRCFX" + c + receiveNotificationEffects +";";
resp += ds + "NSDIR" + c + notifyDirectDefault +";";
resp += ds + "NSBTN" + c + notifyButton +";";
resp += ds + "ALEXA" + c + alexaEnabled +";";
resp += ds + "AINVN" + v + "\"" + alexaInvocationName + "\";";
resp += ds + "NSALX" + c + alexaNotify +";";
resp += ds + "BT" + c + buttonEnabled +";";
resp += ds + "UP" + v + udpPort +";";
resp += ds + "RB" + c + receiveNotificationBrightness +";";
resp += ds + "RC" + c + receiveNotificationColor +";";
resp += ds + "RX" + c + receiveNotificationEffects +";";
resp += ds + "SD" + c + notifyDirectDefault +";";
resp += ds + "SB" + c + notifyButton +";";
resp += ds + "SH" + c + notifyHue +";";
resp += ds + "S2" + c + notifyTwice +";";
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)
{
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 += 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)
{
resp += ds + "NOOTA" + c + otaLock +";";
resp += ds + "OWIFI" + c + wifiLock +";";
resp += ds + "AROTA" + c + aOtaEnabled +";";
resp += ds + "NORAP" + c + recoveryAPDisabled +";";
resp += ds + "NO" + c + otaLock +";";
resp += ds + "OW" + c + wifiLock +";";
resp += ds + "AO" + c + aOtaEnabled +";";
resp += ds + "NA" + c + recoveryAPDisabled +";";
resp += dg + "(\"msg\")[0]" + ih + "\"WLED "+ versionString +" (build " + VERSION + ") OK\";";
}
resp += "}</script>";

View File

@@ -2,24 +2,18 @@
* Receives client input
*/
void _setRandomColor(bool _sec)
void _setRandomColor(bool _sec,bool fromButton=false)
{
lastRandomIndex = strip.get_random_wheel_index(lastRandomIndex);
uint32_t _color = strip.color_wheel(lastRandomIndex);
if (_sec){
white_sec = ((_color >> 24) & 0xFF);
col_sec[0] = ((_color >> 16) & 0xFF);
col_sec[1] = ((_color >> 8) & 0xFF);
col_sec[2] = (_color & 0xFF);
colorHStoRGB(lastRandomIndex*256,255,colSec);
} else {
white = ((_color >> 24) & 0xFF);
col[0] = ((_color >> 16) & 0xFF);
col[1] = ((_color >> 8) & 0xFF);
col[2] = (_color & 0xFF);
colorHStoRGB(lastRandomIndex*256,255,col);
}
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
if (subPage <1 || subPage >6) return;
@@ -27,223 +21,220 @@ void handleSettingsSet(uint8_t subPage)
//WIFI SETTINGS
if (subPage == 1)
{
if (server.hasArg("CSSID")) clientssid = server.arg("CSSID");
if (server.hasArg("CPASS"))
if (server.hasArg("CS")) clientSSID = server.arg("CS");
if (server.hasArg("CP"))
{
if (!server.arg("CPASS").indexOf('*') == 0)
if (!server.arg("CP").indexOf('*') == 0)
{
DEBUG_PRINTLN("Setting pass");
clientpass = server.arg("CPASS");
clientPass = server.arg("CP");
}
}
if (server.hasArg("CMDNS")) cmdns = server.arg("CMDNS");
if (server.hasArg("APWTM"))
if (server.hasArg("CM")) cmDNS = server.arg("CM");
if (server.hasArg("AT"))
{
int i = server.arg("APWTM").toInt();
int i = server.arg("AT").toInt();
if (i >= 0 && i <= 255) apWaitTimeSecs = i;
}
if (server.hasArg("APSSID")) apssid = server.arg("APSSID");
aphide = server.hasArg("APHSSID");
if (server.hasArg("APPASS"))
if (server.hasArg("AS")) apSSID = server.arg("AS");
apHide = server.hasArg("AH");
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();
if (chan > 0 && chan < 14) apchannel = chan;
int chan = server.arg("AC").toInt();
if (chan > 0 && chan < 14) apChannel = chan;
}
if (server.hasArg("CSIP0"))
if (server.hasArg("I0"))
{
int i = server.arg("CSIP0").toInt();
if (i >= 0 && i <= 255) staticip[0] = i;
int i = server.arg("I0").toInt();
if (i >= 0 && i <= 255) staticIP[0] = i;
}
if (server.hasArg("CSIP1"))
if (server.hasArg("I1"))
{
int i = server.arg("CSIP1").toInt();
if (i >= 0 && i <= 255) staticip[1] = i;
int i = server.arg("I1").toInt();
if (i >= 0 && i <= 255) staticIP[1] = i;
}
if (server.hasArg("CSIP2"))
if (server.hasArg("I2"))
{
int i = server.arg("CSIP2").toInt();
if (i >= 0 && i <= 255) staticip[2] = i;
int i = server.arg("I2").toInt();
if (i >= 0 && i <= 255) staticIP[2] = i;
}
if (server.hasArg("CSIP3"))
if (server.hasArg("I3"))
{
int i = server.arg("CSIP3").toInt();
if (i >= 0 && i <= 255) staticip[3] = i;
int i = server.arg("I3").toInt();
if (i >= 0 && i <= 255) staticIP[3] = i;
}
if (server.hasArg("CSGW0"))
if (server.hasArg("G0"))
{
int i = server.arg("CSGW0").toInt();
if (i >= 0 && i <= 255) staticgateway[0] = i;
int i = server.arg("G0").toInt();
if (i >= 0 && i <= 255) staticGateway[0] = i;
}
if (server.hasArg("CSGW1"))
if (server.hasArg("G1"))
{
int i = server.arg("CSGW1").toInt();
if (i >= 0 && i <= 255) staticgateway[1] = i;
int i = server.arg("G1").toInt();
if (i >= 0 && i <= 255) staticGateway[1] = i;
}
if (server.hasArg("CSGW2"))
if (server.hasArg("G2"))
{
int i = server.arg("CSGW2").toInt();
if (i >= 0 && i <= 255) staticgateway[2] = i;
int i = server.arg("G2").toInt();
if (i >= 0 && i <= 255) staticGateway[2] = i;
}
if (server.hasArg("CSGW3"))
if (server.hasArg("G3"))
{
int i = server.arg("CSGW3").toInt();
if (i >= 0 && i <= 255) staticgateway[3] = i;
int i = server.arg("G3").toInt();
if (i >= 0 && i <= 255) staticGateway[3] = i;
}
if (server.hasArg("CSSN0"))
if (server.hasArg("S0"))
{
int i = server.arg("CSSN0").toInt();
if (i >= 0 && i <= 255) staticsubnet[0] = i;
int i = server.arg("S0").toInt();
if (i >= 0 && i <= 255) staticSubnet[0] = i;
}
if (server.hasArg("CSSN1"))
if (server.hasArg("S1"))
{
int i = server.arg("CSSN1").toInt();
if (i >= 0 && i <= 255) staticsubnet[1] = i;
int i = server.arg("S1").toInt();
if (i >= 0 && i <= 255) staticSubnet[1] = i;
}
if (server.hasArg("CSSN2"))
if (server.hasArg("S2"))
{
int i = server.arg("CSSN2").toInt();
if (i >= 0 && i <= 255) staticsubnet[2] = i;
int i = server.arg("S2").toInt();
if (i >= 0 && i <= 255) staticSubnet[2] = i;
}
if (server.hasArg("CSSN3"))
if (server.hasArg("S3"))
{
int i = server.arg("CSSN3").toInt();
if (i >= 0 && i <= 255) staticsubnet[3] = i;
int i = server.arg("S3").toInt();
if (i >= 0 && i <= 255) staticSubnet[3] = i;
}
}
//LED SETTINGS
if (subPage == 2)
{
if (server.hasArg("LEDCN"))
if (server.hasArg("LC"))
{
int i = server.arg("LEDCN").toInt();
if (i >= 0 && i <= LEDCOUNT) ledcount = i;
strip.setLedCount(ledcount);
int i = server.arg("LC").toInt();
if (i >= 0 && i <= LEDCOUNT) ledCount = i;
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];
col_s[1] = col[1];
col_s[2] = col[2];
if (useRGBW) white_s = white;
bri_s = bri;
colS[0] = col[0];
colS[1] = col[1];
colS[2] = col[2];
if (useRGBW) whiteS = white;
briS = bri;
effectDefault = effectCurrent;
effectSpeedDefault = effectSpeed;
} else {
if (server.hasArg("CLDFR"))
if (server.hasArg("CR"))
{
int i = server.arg("CLDFR").toInt();
if (i >= 0 && i <= 255) col_s[0] = i;
int i = server.arg("CR").toInt();
if (i >= 0 && i <= 255) colS[0] = i;
}
if (server.hasArg("CLDFG"))
if (server.hasArg("CG"))
{
int i = server.arg("CLDFG").toInt();
if (i >= 0 && i <= 255) col_s[1] = i;
int i = server.arg("CG").toInt();
if (i >= 0 && i <= 255) colS[1] = i;
}
if (server.hasArg("CLDFB"))
if (server.hasArg("CB"))
{
int i = server.arg("CLDFB").toInt();
if (i >= 0 && i <= 255) col_s[2] = i;
int i = server.arg("CB").toInt();
if (i >= 0 && i <= 255) colS[2] = i;
}
if (server.hasArg("CSECR"))
if (server.hasArg("SR"))
{
int i = server.arg("CSECR").toInt();
if (i >= 0 && i <= 255) col_sec_s[0] = i;
int i = server.arg("SR").toInt();
if (i >= 0 && i <= 255) colSecS[0] = i;
}
if (server.hasArg("CSECG"))
if (server.hasArg("SG"))
{
int i = server.arg("CSECG").toInt();
if (i >= 0 && i <= 255) col_sec_s[1] = i;
int i = server.arg("SG").toInt();
if (i >= 0 && i <= 255) colSecS[1] = i;
}
if (server.hasArg("CSECB"))
if (server.hasArg("SB"))
{
int i = server.arg("CSECB").toInt();
if (i >= 0 && i <= 255) col_sec_s[2] = i;
int i = server.arg("SB").toInt();
if (i >= 0 && i <= 255) colSecS[2] = i;
}
if (server.hasArg("CSECW"))
if (server.hasArg("SW"))
{
int i = server.arg("CSECW").toInt();
if (i >= 0 && i <= 255) white_sec_s = i;
int i = server.arg("SW").toInt();
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)
{
useRGBW = true;
white_s = i;
whiteS = i;
} else {
useRGBW = false;
white_s = 0;
whiteS = 0;
}
}
if (server.hasArg("CLDFA"))
if (server.hasArg("CA"))
{
int i = server.arg("CLDFA").toInt();
if (i >= 0 && i <= 255) bri_s = i;
int i = server.arg("CA").toInt();
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 (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 (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;
}
}
turnOnAtBoot = server.hasArg("BOOTN");
if (server.hasArg("BOOTP"))
turnOnAtBoot = server.hasArg("BO");
if (server.hasArg("BP"))
{
int i = server.arg("BOOTP").toInt();
int i = server.arg("BP").toInt();
if (i >= 0 && i <= 25) bootPreset = i;
}
useGammaCorrectionBri = server.hasArg("GCBRI");
useGammaCorrectionRGB = server.hasArg("GCRGB");
fadeTransition = server.hasArg("TFADE");
sweepTransition = server.hasArg("TSWEE");
sweepDirection = !server.hasArg("TSDIR");
if (server.hasArg("TDLAY"))
useGammaCorrectionBri = server.hasArg("GB");
useGammaCorrectionRGB = server.hasArg("GC");
fadeTransition = server.hasArg("TF");
sweepTransition = server.hasArg("TS");
sweepDirection = !server.hasArg("TI");
if (server.hasArg("TD"))
{
int i = server.arg("TDLAY").toInt();
int i = server.arg("TD").toInt();
if (i > 0){
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;
}
nightlightFade = server.hasArg("TLFDE");
if (server.hasArg("OLDEF"))
nightlightFade = server.hasArg("TW");
reverseMode = server.hasArg("RV");
initLedsLast = server.hasArg("EI");
strip.setReverseMode(reverseMode);
if (server.hasArg("WO"))
{
int i = server.arg("OLDEF").toInt();
if (i >= 0 && i <= 255) overlayDefault = i;
}
if (server.hasArg("WOFFS"))
{
int i = server.arg("WOFFS").toInt();
int i = server.arg("WO").toInt();
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;
}
}
@@ -251,49 +242,120 @@ void handleSettingsSet(uint8_t subPage)
//UI
if (subPage == 3)
{
if (server.hasArg("DESC")) serverDescription = server.arg("DESC");
useHSBDefault = server.hasArg("COLMD");
if (server.hasArg("DS")) serverDescription = server.arg("DS");
useHSBDefault = server.hasArg("MD");
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++)
{
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();
}
//SYNC
if (subPage == 4)
{
buttonEnabled = server.hasArg("BTNON");
if (server.hasArg("NUDPP"))
buttonEnabled = server.hasArg("BT");
if (server.hasArg("UP"))
{
udpPort = server.arg("NUDPP").toInt();
udpPort = server.arg("UP").toInt();
}
receiveNotificationBrightness = server.hasArg("NRCBR");
receiveNotificationColor = server.hasArg("NRCCL");
receiveNotificationEffects = server.hasArg("NRCFX");
receiveNotificationBrightness = server.hasArg("RB");
receiveNotificationColor = server.hasArg("RC");
receiveNotificationEffects = server.hasArg("RX");
receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
notifyDirectDefault = server.hasArg("NSDIR");
notifyDirectDefault = server.hasArg("SD");
notifyDirect = notifyDirectDefault;
notifyButton = server.hasArg("NSBTN");
alexaEnabled = server.hasArg("ALEXA");
if (server.hasArg("AINVN")) alexaInvocationName = server.arg("AINVN");
alexaNotify = server.hasArg("NSALX");
notifyButton = server.hasArg("SB");
notifyTwice = server.hasArg("S2");
alexaEnabled = server.hasArg("AL");
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
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 (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
if (subPage == 6)
{
if (server.hasArg("RESET"))
if (server.hasArg("RS"))
{
clearEEPROM();
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
if (server.hasArg("OPASS"))
if (server.hasArg("OP"))
{
if (otaLock && otapass.equals(server.arg("OPASS")))
if (otaLock && otaPass.equals(server.arg("OP")))
{
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
{
otaLock = server.hasArg("NOOTA");
wifiLock = server.hasArg("OWIFI");
recoveryAPDisabled = server.hasArg("NORAP");
aOtaEnabled = server.hasArg("AROTA");
otaLock = server.hasArg("NO");
wifiLock = server.hasArg("OW");
recoveryAPDisabled = server.hasArg("NA");
aOtaEnabled = server.hasArg("AO");
}
}
saveSettingsToEEPROM();
}
boolean handleSet(String req)
bool handleSet(String req)
{
boolean effectUpdated = false;
bool effectUpdated = false;
if (!(req.indexOf("win") >= 0)) {
return false;
}
@@ -358,6 +420,19 @@ boolean handleSet(String req)
if (pos > 0) {
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
pos = req.indexOf("&R=");
if (pos > 0) {
@@ -382,45 +457,45 @@ boolean handleSet(String req)
//set 2nd red value
pos = req.indexOf("R2=");
if (pos > 0) {
col_sec[0] = req.substring(pos + 3).toInt();
colSec[0] = req.substring(pos + 3).toInt();
}
//set 2nd green value
pos = req.indexOf("G2=");
if (pos > 0) {
col_sec[1] = req.substring(pos + 3).toInt();
colSec[1] = req.substring(pos + 3).toInt();
}
//set 2nd blue value
pos = req.indexOf("B2=");
if (pos > 0) {
col_sec[2] = req.substring(pos + 3).toInt();
colSec[2] = req.substring(pos + 3).toInt();
}
//set 2nd white value
pos = req.indexOf("W2=");
if (pos > 0) {
white_sec = req.substring(pos + 3).toInt();
whiteSec = req.substring(pos + 3).toInt();
}
//set 2nd to white
pos = req.indexOf("SW");
if (pos > 0) {
if(useRGBW) {
white_sec = 255;
col_sec[0] = 0;
col_sec[1] = 0;
col_sec[2] = 0;
whiteSec = 255;
colSec[0] = 0;
colSec[1] = 0;
colSec[2] = 0;
} else {
col_sec[0] = 255;
col_sec[1] = 255;
col_sec[2] = 255;
colSec[0] = 255;
colSec[1] = 255;
colSec[2] = 255;
}
}
//set 2nd to black
pos = req.indexOf("SB");
if (pos > 0) {
white_sec = 0;
col_sec[0] = 0;
col_sec[1] = 0;
col_sec[2] = 0;
whiteSec = 0;
colSec[0] = 0;
colSec[1] = 0;
colSec[2] = 0;
}
//set to random hue SR=0->1st SR=1->2nd
pos = req.indexOf("SR");
@@ -430,24 +505,24 @@ boolean handleSet(String req)
//set 2nd to 1st
pos = req.indexOf("SP");
if (pos > 0) {
col_sec[0] = col[0];
col_sec[1] = col[1];
col_sec[2] = col[2];
white_sec = white;
colSec[0] = col[0];
colSec[1] = col[1];
colSec[2] = col[2];
whiteSec = white;
}
//swap 2nd & 1st
pos = req.indexOf("SC");
if (pos > 0) {
uint8_t _temp[4];
byte _temp[4];
for (int i = 0; i<3; i++)
{
_temp[i] = col[i];
col[i] = col_sec[i];
col_sec[i] = _temp[i];
col[i] = colSec[i];
colSec[i] = _temp[i];
}
_temp[3] = white;
white = white_sec;
white_sec = _temp[3];
white = whiteSec;
whiteSec = _temp[3];
}
//set current effect index
@@ -480,6 +555,19 @@ boolean handleSet(String req)
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)
pos = req.indexOf("MD=");
@@ -560,7 +648,7 @@ boolean handleSet(String req)
if (req.indexOf("NL=0") > 0)
{
nightlightActive = false;
bri = bri_t;
bri = briT;
} else {
nightlightActive = true;
nightlightDelayMins = req.substring(pos + 3).toInt();
@@ -571,7 +659,7 @@ boolean handleSet(String req)
pos = req.indexOf("NT=");
if (pos > 0) {
nightlightTargetBri = req.substring(pos + 3).toInt();
nightlightActive_old = false; //re-init
nightlightActiveOld = false; //re-init
}
//toggle nightlight fade
if (req.indexOf("NF=") > 0)
@@ -582,7 +670,7 @@ boolean handleSet(String req)
} else {
nightlightFade = true;
}
nightlightActive_old = false; //re-init
nightlightActiveOld = false; //re-init
}
//toggle general purpose output
pos = req.indexOf("AX=");
@@ -596,14 +684,14 @@ boolean handleSet(String req)
if (pos > 0) {
switch (req.substring(pos + 3).toInt())
{
case 0: if (bri != 0){bri_last = bri; bri = 0;} break; //off
case 1: bri = bri_last; break; //on
case 0: if (bri != 0){briLast = bri; bri = 0;} break; //off
case 1: bri = briLast; break; //on
default: if (bri == 0) //toggle
{
bri = bri_last;
bri = briLast;
} else
{
bri_last = bri;
briLast = bri;
bri = 0;
}
}
@@ -622,15 +710,15 @@ boolean handleSet(String req)
//set custom chase data
bool _cc_updated = false;
pos = req.indexOf("C0="); if (pos > 0) {cc_start = (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("C2="); if (pos > 0) {cc_index2 = (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("CS="); if (pos > 0) {cc_numSecondary = (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("CF="); if (pos > 0) {cc_fromStart = (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;}
if (_cc_updated) strip.setCustomChase(cc_index1, cc_index2, cc_start, cc_numPrimary, cc_numSecondary, cc_step, cc_fromStart, cc_fromEnd);
pos = req.indexOf("C0="); if (pos > 0) {ccStart = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("C1="); if (pos > 0) {ccIndex1 = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("C2="); if (pos > 0) {ccIndex2 = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CP="); if (pos > 0) {ccNumPrimary = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CS="); if (pos > 0) {ccNumSecondary = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CM="); if (pos > 0) {ccStep = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CF="); if (pos > 0) {ccFromStart = (req.substring(pos + 3).toInt()); _cc_updated = true;}
pos = req.indexOf("CE="); if (pos > 0) {ccFromEnd = (req.substring(pos + 3).toInt()); _cc_updated = true;}
if (_cc_updated) strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd);
//set presets
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);
effectUpdated = true;
}
#ifdef CRONIXIE
//cronixie
pos = req.indexOf("NX="); //sets digits to code
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
if (pos > 0) {
cronixieCountdown = true;
countdownMode = true;
if (req.indexOf("NM=0") > 0)
{
cronixieCountdown = false;
countdownMode = false;
}
}
if (req.indexOf("NB=") > 0) //sets backlight
@@ -675,10 +765,10 @@ boolean handleSet(String req)
{
cronixieBacklight = false;
}
strip.setCronixieBacklight(cronixieBacklight);
cronixieRefreshedTime = 0;
if (overlayCurrent == 4) strip.setCronixieBacklight(cronixieBacklight);
overlayRefreshedTime = 0;
}
#endif
//internal call, does not send XML response
pos = req.indexOf("IN");
if (pos < 1) XML_response();

View File

@@ -4,44 +4,37 @@
void wledInit()
{
EEPROM.begin(EEPSIZE);
if (!EEPROM.read(397)) strip.init(); //quick init
Serial.begin(115200);
#ifdef USEFS
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
DEBUG_PRINTLN("Init EEPROM");
EEPROM.begin(EEPSIZE);
DEBUG_PRINTLN("Load EEPROM");
loadSettingsFromEEPROM(true);
DEBUG_PRINT("CC: SSID: ");
DEBUG_PRINT(clientssid);
if (!initLedsLast) initStrip();
DEBUG_PRINT("C-SSID: ");
DEBUG_PRINT(clientSSID);
buildCssColorString();
userBeginPreConnection();
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
{
WiFi.config(0U, 0U, 0U);
}
if (apssid.length()>0)
if (apSSID.length()>0)
{
DEBUG_PRINT("USING AP");
DEBUG_PRINTLN(apssid.length());
DEBUG_PRINTLN(apSSID.length());
initAP();
} else
{
@@ -54,9 +47,16 @@ void wledInit()
DEBUG_PRINTLN("");
DEBUG_PRINT("Connected! IP address: ");
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:
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!");
down();
}
@@ -69,6 +69,14 @@ void wledInit()
if (ntpEnabled && WiFi.status() == WL_CONNECTED)
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
//settings page
server.on("/settings", HTTP_GET, [](){
@@ -106,15 +114,15 @@ void wledInit()
});
server.on("/", HTTP_GET, [](){
if (!showWelcomePage){
if(!handleFileRead("/index.htm")) {
serveIndex();
}
}else{
if(!handleFileRead("/welcome.htm")) {
serveSettings(255);
}
}
serveIndexOrWelcome();
});
server.on("/generate_204", HTTP_GET, [](){
serveIndexOrWelcome();
});
server.on("/fwlink", HTTP_GET, [](){
serveIndexOrWelcome();
});
server.on("/sliders", HTTP_GET, serveIndex);
@@ -124,7 +132,7 @@ void wledInit()
});
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();
});
@@ -146,7 +154,13 @@ void wledInit()
server.on("/settings/sync", HTTP_POST, [](){
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, [](){
@@ -173,7 +187,7 @@ void wledInit()
});
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";
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";
#endif
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
info += "spiffs: true\r\n";
#else
@@ -289,51 +293,66 @@ void wledInit()
ArduinoOTA.begin();
}
// Initialize NeoPixel Strip
strip.init();
strip.setLedCount(ledcount);
if (initLedsLast) initStrip();
userBegin();
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.setBrightness(255);
strip.start();
pinMode(buttonPin, INPUT_PULLUP);
#ifdef CRONIXIE
strip.driverModeCronixie(true);
strip.setCronixieBacklight(cronixieBacklight);
setCronixie(cronixieDefault);
#endif
if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true);
colorUpdated(0);
if(digitalRead(buttonPin) == LOW) buttonEnabled = false; //disable button if it is "pressed" unintentionally
}
void initAP(){
String save = apssid;
#ifdef CRONIXIE
if (apssid.length() <1) apssid = "CRONIXIE-AP";
#else
if (apssid.length() <1) apssid = "WLED-AP";
#endif
WiFi.softAP(apssid.c_str(), appass.c_str(), apchannel, aphide);
apssid = save;
String save = apSSID;
if (apSSID.length() <1) apSSID = "WLED-AP";
WiFi.softAP(apSSID.c_str(), apPass.c_str(), apChannel, apHide);
apSSID = save;
}
void initCon()
{
int fail_count = 0;
if (clientssid.length() <1 || clientssid.equals("Your_Network_Here")) fail_count = apWaitTimeSecs*2;
WiFi.begin(clientssid.c_str(), clientpass.c_str());
while(WiFi.status() != WL_CONNECTED) {
delay(500);
DEBUG_PRINTLN("C_NC");
fail_count++;
if (!recoveryAPDisabled && fail_count > apWaitTimeSecs*2)
if (clientSSID.length() <1 || clientSSID.equals("Your_Network")) fail_count = apWaitTimeSecs*2;
WiFi.begin(clientSSID.c_str(), clientPass.c_str());
unsigned long lastTry = 0;
bool con = false;
while(!con)
{
yield();
if (!initLedsLast)
{
WiFi.disconnect();
DEBUG_PRINTLN("Can't connect. Opening AP...");
onlyAP = true;
initAP();
return;
handleTransitions();
handleButton();
handleOverlays();
if (briT) strip.service();
}
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 9: cs[0]="f70"; cs[1]="421"; cs[2]="221"; cs[3]="a50"; cs[4]="f70"; cs[5]="f70"; break;//nixie
case 10: cs[0]="2d2"; cs[1]="010"; cs[2]="121"; cs[3]="060"; cs[4]="040"; cs[5]="3f3"; break; //terminal
case 11: cs[0]="867ADE"; cs[1]="4033A3"; cs[2]="483AAA"; cs[3]="483AAA"; cs[4]=""; cs[5]="867ADE"; break; //c64
case 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
}
@@ -374,6 +394,19 @@ void buildCssColorString()
cssColorString+=";}";
}
void serveIndexOrWelcome()
{
if (!showWelcomePage){
if(!handleFileRead("/index.htm")) {
serveIndex();
}
}else{
if(!handleFileRead("/welcome.htm")) {
serveSettings(255);
}
}
}
void serveIndex()
{
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);
}
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
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
void notify(uint8_t callMode)
void notify(byte callMode, bool followUp=false)
{
if (!udpConnected) return;
switch (callMode)
@@ -13,6 +13,7 @@ void notify(uint8_t callMode)
case 2: if (!notifyButton) return; break;
case 4: if (!notifyDirect) return; break;
case 6: if (!notifyDirect) return; break; //fx change
case 7: if (!notifyHue) return; break;
default: return;
}
byte udpOut[WLEDPACKETSIZE];
@@ -27,12 +28,14 @@ void notify(uint8_t callMode)
udpOut[8] = effectCurrent;
udpOut[9] = effectSpeed;
udpOut[10] = white;
udpOut[11] = 3; //compatibilityVersionByte: 0: old 1: supports white 2: supports secondary color 3: supports FX intensity, 24 byte packet
udpOut[12] = col_sec[0];
udpOut[13] = col_sec[1];
udpOut[14] = col_sec[2];
udpOut[15] = white_sec;
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] = colSec[0];
udpOut[13] = colSec[1];
udpOut[14] = colSec[2];
udpOut[15] = whiteSec;
udpOut[16] = effectIntensity;
udpOut[17] = (transitionDelay >> 0) & 0xFF;
udpOut[18] = (transitionDelay >> 8) & 0xFF;
IPAddress broadcastIp;
broadcastIp = ~WiFi.subnetMask() | WiFi.gatewayIP();
@@ -40,14 +43,23 @@ void notify(uint8_t callMode)
notifierUdp.beginPacket(broadcastIp, udpPort);
notifierUdp.write(udpOut, WLEDPACKETSIZE);
notifierUdp.endPacket();
notificationSentCallMode = callMode;
notificationSentTime = millis();
notificationTwoRequired = (followUp)? false:notifyTwice;
}
void handleNotifications()
{
if(udpConnected && notificationTwoRequired && millis()-notificationSentTime > 250){
notify(notificationSentCallMode,true);
}
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
{
byte udpIn[packetSize];
notifierUdp.read(udpIn, packetSize);
if (udpIn[0] == 0 && !arlsTimeout) //wled notifier, block if realtime packets active
{
@@ -62,10 +74,10 @@ void handleNotifications()
white = udpIn[10];
if (udpIn[11] > 1 )
{
col_sec[0] = udpIn[12];
col_sec[1] = udpIn[13];
col_sec[2] = udpIn[14];
white_sec = udpIn[15];
colSec[0] = udpIn[12];
colSec[1] = udpIn[13];
colSec[2] = udpIn[14];
whiteSec = udpIn[15];
}
}
if (udpIn[8] != effectCurrent && receiveNotificationEffects)
@@ -83,6 +95,10 @@ void handleNotifications()
effectIntensity = udpIn[16];
strip.setIntensity(effectIntensity);
}
if (udpIn[11] > 3)
{
transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00);
}
nightlightActive = udpIn[6];
if (!nightlightActive)
{
@@ -97,7 +113,7 @@ void handleNotifications()
arlsTimeout = false;
} else {
if (!arlsTimeout){
strip.setRange(0, ledcount-1, 0);
strip.setRange(0, ledCount-1, 0);
strip.setMode(0);
}
arlsTimeout = true;
@@ -105,7 +121,7 @@ void handleNotifications()
}
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)
{
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() {
double d = bri_t*briMultiplier;
double d = briT*briMultiplier;
int val = d/100;
if (val > 255) val = 255;
if (useGammaCorrectionBri)
@@ -14,26 +14,26 @@ void setAllLeds() {
}
if (useGammaCorrectionRGB)
{
strip.setColor(gamma8[col_t[0]], gamma8[col_t[1]], gamma8[col_t[2]], gamma8[white_t]);
strip.setSecondaryColor(gamma8[col_sec[0]], gamma8[col_sec[1]], gamma8[col_sec[2]], gamma8[white_sec]);
strip.setColor(gamma8[colT[0]], gamma8[colT[1]], gamma8[colT[2]], gamma8[whiteT]);
strip.setSecondaryColor(gamma8[colSec[0]], gamma8[colSec[1]], gamma8[colSec[2]], gamma8[whiteSec]);
} else {
strip.setColor(col_t[0], col_t[1], col_t[2], white_t);
strip.setSecondaryColor(col_sec[0], col_sec[1], col_sec[2], white_sec);
strip.setColor(colT[0], colT[1], colT[2], whiteT);
strip.setSecondaryColor(colSec[0], colSec[1], colSec[2], whiteSec);
}
}
void setLedsStandard()
{
col_old[0] = col[0];
col_old[1] = col[1];
col_old[2] = col[2];
white_old = white;
bri_old = bri;
col_t[0] = col[0];
col_t[1] = col[1];
col_t[2] = col[2];
white_t = white;
bri_t = bri;
colOld[0] = col[0];
colOld[1] = col[1];
colOld[2] = col[2];
whiteOld = white;
briOld = bri;
colT[0] = col[0];
colT[1] = col[1];
colT[2] = col[2];
whiteT = white;
briT = bri;
setAllLeds();
}
@@ -41,17 +41,17 @@ bool colorChanged()
{
for (int i = 0; i < 3; i++)
{
if (col[i] != col_it[i]) return true;
if (col_sec[i] != col_sec_it[i]) return true;
if (col[i] != colIT[i]) return true;
if (colSec[i] != colSecIT[i]) return true;
}
if (white != white_it || white_sec != white_sec_it) return true;
if (bri != bri_it) return true;
if (white != whiteIT || whiteSec != whiteSecIT) return true;
if (bri != briIT) return true;
return false;
}
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 (callMode == 6) notify(6);
@@ -59,31 +59,34 @@ void colorUpdated(int callMode)
}
if (callMode != 5 && nightlightActive && nightlightFade)
{
bri_nl_t = bri;
briNlT = bri;
nightlightDelayMs -= (millis() - nightlightStartTime);
nightlightStartTime = millis();
}
col_it[0] = col[0];
col_it[1] = col[1];
col_it[2] = col[2];
col_sec_it[0] = col_sec[0];
col_sec_it[1] = col_sec[1];
col_sec_it[2] = col_sec[2];
white_it = white;
white_sec_it = white_sec;
bri_it = bri;
if (bri > 0) bri_last = bri;
colIT[0] = col[0];
colIT[1] = col[1];
colIT[2] = col[2];
colSecIT[0] = colSec[0];
colSecIT[1] = colSec[1];
colSecIT[2] = colSec[2];
whiteIT = white;
whiteSecIT = whiteSec;
briIT = bri;
if (bri > 0) briLast = bri;
notify(callMode);
if (fadeTransition || sweepTransition)
{
//set correct delay if not using notification delay
if (callMode != 3) transitionDelayTemp = transitionDelay;
if (transitionActive)
{
col_old[0] = col_t[0];
col_old[1] = col_t[1];
col_old[2] = col_t[2];
white_old = white_t;
bri_old = bri_t;
tper_last = 0;
colOld[0] = colT[0];
colOld[1] = colT[1];
colOld[2] = colT[2];
whiteOld = whiteT;
briOld = briT;
tperLast = 0;
}
transitionActive = true;
transitionStartTime = millis();
@@ -97,40 +100,40 @@ void colorUpdated(int callMode)
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)
{
transitionActive = false;
tper_last = 0;
tperLast = 0;
if (sweepTransition) strip.unlockAll();
setLedsStandard();
strip.setFastUpdateMode(false);
return;
}
if (tper - tper_last < transitionResolution)
if (tper - tperLast < transitionResolution)
{
return;
}
tper_last = tper;
tperLast = tper;
if (fadeTransition)
{
col_t[0] = col_old[0]+((col[0] - col_old[0])*tper);
col_t[1] = col_old[1]+((col[1] - col_old[1])*tper);
col_t[2] = col_old[2]+((col[2] - col_old[2])*tper);
white_t = white_old +((white - white_old )*tper);
bri_t = bri_old +((bri - bri_old )*tper);
colT[0] = colOld[0]+((col[0] - colOld[0])*tper);
colT[1] = colOld[1]+((col[1] - colOld[1])*tper);
colT[2] = colOld[2]+((col[2] - colOld[2])*tper);
whiteT = whiteOld +((white - whiteOld )*tper);
briT = briOld +((bri - briOld )*tper);
}
if (sweepTransition)
{
strip.lockAll();
if (sweepDirection)
{
strip.unlockRange(0, (int)(tper*(double)ledcount));
strip.unlockRange(0, (int)(tper*(double)ledCount));
} else
{
strip.unlockRange(ledcount - (int)(tper*(double)ledcount), ledcount);
strip.unlockRange(ledCount - (int)(tper*(double)ledCount), ledCount);
}
if (!fadeTransition)
{
@@ -145,18 +148,18 @@ void handleNightlight()
{
if (nightlightActive)
{
if (!nightlightActive_old) //init
if (!nightlightActiveOld) //init
{
nightlightStartTime = millis();
notify(4);
nightlightDelayMs = (int)(nightlightDelayMins*60000);
nightlightActive_old = true;
bri_nl_t = bri;
nightlightActiveOld = true;
briNlT = bri;
}
float nper = (millis() - nightlightStartTime)/((float)nightlightDelayMs);
if (nightlightFade)
{
bri = bri_nl_t+((nightlightTargetBri - bri_nl_t)*nper);
bri = briNlT+((nightlightTargetBri - briNlT)*nper);
colorUpdated(5);
}
if (nper >= 1)
@@ -167,10 +170,10 @@ void handleNightlight()
bri = nightlightTargetBri;
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();
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)
{
delay(15); //debounce
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;
}
}

View File

@@ -2,6 +2,55 @@
* 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()
{
if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > 50000000L && WiFi.status() == WL_CONNECTED)
@@ -20,7 +69,8 @@ void handleNetworkTime()
void sendNTPPacket()
{
WiFi.hostByName(ntpServerName, ntpServerIP);
const char* ntpsrv = ntpServerName.c_str();
WiFi.hostByName(ntpsrv, ntpServerIP);
DEBUG_PRINTLN("send NTP packet");
memset(ntpPacketBuffer, 0, NTP_PACKET_SIZE);
@@ -40,7 +90,7 @@ void sendNTPPacket()
ntpUdp.endPacket();
}
boolean checkNTPResponse()
bool checkNTPResponse()
{
int cb = ntpUdp.parsePacket();
if (cb) {
@@ -56,7 +106,7 @@ boolean checkNTPResponse()
unsigned long secsSince1900 = highWord << 16 | lowWord;
DEBUG_PRINT("Unix time = ");
unsigned long epoch = secsSince1900 - seventyYears;
unsigned long epoch = secsSince1900 - 2208988800UL; //subtract 70 years
setTime(epoch);
DEBUG_PRINTLN(epoch);
if (countdownTime - now() > 0) countdownOverTriggered = false;
@@ -65,33 +115,49 @@ boolean checkNTPResponse()
return false;
}
void updateLocalTime()
{
unsigned long tmc = now()+ utcOffsetSecs;
local = timezones[currentTimezone]->toLocal(tmc);
}
String getTimeString()
{
local = TZ.toLocal(now(), &tcr);
updateLocalTime();
String ret = monthStr(month(local));
ret = ret + " ";
ret = ret + day(local);
ret = ret + " ";
ret = ret + year(local);
ret = ret + ", ";
ret = ret + hour(local);
ret += (useAMPM)? hour(local)%12:hour(local);
ret = ret + ":";
if (minute(local) < 10) ret = ret + "0";
ret = ret + minute(local);
ret = ret + ":";
if (second(local) < 10) ret = ret + "0";
ret = ret + second(local);
if (useAMPM)
{
ret += (hour(local) > 11)? " PM":" AM";
}
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
bool checkCountdown()
{
long diff = countdownTime - local;
long diff = countdownTime - now();
local = abs(diff);
if (diff <0 && !countdownOverTriggered)
{
applyMacro(countdownMacro);
if (macroCountdown != 0) applyMacro(macroCountdown);
countdownOverTriggered = 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 _nixieDisplay(int num[], int dur[], int pausedur[], int cnt)
void initCronixie()
{
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);
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]);
}
if (!nixiePause)
@@ -84,8 +98,6 @@ void _nixieNumber(int number, int dur)
if (overlayArr[i] != -1)
{
overlayArr[i] = overlayArr[i] + overlayMin;
if (overlayReverse)
overlayArr[i] = overlayMax - overlayArr[i];
}
}
for (int i = 0; i <6; i++)
@@ -106,38 +118,40 @@ void _nixieNumber(int number, int dur)
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)
{
overlayRefreshedTime = millis();
initCronixie();
updateLocalTime();
switch (overlayCurrent)
{
case 0: break;//no overlay
case 1: _overlaySolid(); break;//solid secondary color
case 2: _overlayAnalogClock(); break;//2 analog clock
case 3: _overlayNixieClock(); break;//nixie 1-digit
case 5: _overlayAnalogCountdown(); break;//a.countdown
case 6: _overlayNixieCountdown(); break;//d.
case 4: _overlayCronixie();//Diamex cronixie clock kit
}
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()
{
int overlaySize = overlayMax - overlayMin +1;
strip.unlockAll();
if (overlayDimBg)
if (countdownMode)
{
uint32_t ct = (white>>1)*16777216 + (col[0]>>1)*65536 + (col[1]>>1)*256 + (col[2]>>1);
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);
_overlayAnalogCountdown(); return;
}
local = TZ.toLocal(now(), &tcr);
_overlaySolid();
double hourP = ((double)(hour(local)%12))/12;
double minuteP = ((double)minute(local))/60;
hourP = hourP + minuteP/12;
@@ -148,6 +162,17 @@ void _overlayAnalogClock()
if (minutePixel > overlayMax) minutePixel = overlayMin -1 + minutePixel - overlayMax;
int secondPixel = floor(analogClock12pixel + overlaySize*secondP);
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)
{
int pix;
@@ -155,16 +180,10 @@ void _overlayAnalogClock()
{
pix = overlayMin + analogClock12pixel + (overlaySize/12)*i;
if (pix > overlayMax) pix = pix - overlayMax;
strip.setIndividual(pix, 0xAAAAAA);
strip.setIndividual(pix,0x00FFAA);
}
}
if (analogClockSecondsTrail)
{
strip.setRange(analogClock12pixel, secondPixel, 0xFF0000);
} else
{
strip.setIndividual(secondPixel, 0xFF0000);
}
if (!analogClockSecondsTrail) strip.setIndividual(secondPixel, 0xFF0000);
strip.setIndividual(minutePixel, 0x00FF00);
strip.setIndividual(hourPixel, 0x0000FF);
overlayRefreshMs = 998;
@@ -172,14 +191,14 @@ void _overlayAnalogClock()
void _overlayNixieClock()
{
if (countdownMode)
{
_overlayNixieCountdown(); return;
}
if (nixieClockI < 0)
{
local = TZ.toLocal(now(), &tcr);
overlayArr[0] = hour(local);
if (nixieClock12HourFormat && overlayArr[0] > 12)
{
overlayArr[0] = overlayArr[0]%12;
}
if (useAMPM) overlayArr[0] = overlayArr[0]%12;
overlayArr[1] = -1;
if (overlayArr[0] > 9)
{
@@ -191,7 +210,7 @@ void _overlayNixieClock()
overlayArr[2] = overlayArr[2]/10;
overlayArr[4] = -1;
overlayArr[5] = -1;
if (nixieClockDisplaySeconds)
if (analogClockSecondsTrail)
{
overlayArr[4] = second(local);
overlayArr[5] = overlayArr[4]%10;
@@ -202,8 +221,6 @@ void _overlayNixieClock()
if (overlayArr[i] != -1)
{
overlayArr[i] = overlayArr[i] + overlayMin;
if (overlayReverse)
overlayArr[i] = overlayMax - overlayArr[i];
}
}
overlayDur[0] = 12 + 12*(255 - overlaySpeed);
@@ -292,14 +309,14 @@ void _overlayAnalogCountdown()
int overlaySize = overlayMax - overlayMin +1;
double perc = (pval-(double)diff)/pval;
if (perc > 1.0) perc = 1.0;
uint8_t pixelCnt = perc*overlaySize;
byte pixelCnt = perc*overlaySize;
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(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(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)whiteSec << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
} 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;
@@ -331,5 +348,5 @@ void _overlayNixieCountdown()
}
_nixieNumber(diff, 800);
}
overlayRefreshMs = 998;
}
#endif

View File

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

View File

@@ -1,10 +1,9 @@
/*
* Support for the Cronixie clock
*/
#ifdef CRONIXIE
uint8_t getSameCodeLength(char code, int index, char const digits[])
byte getSameCodeLength(char code, int index, char const digits[])
{
uint8_t counter = 0;
byte counter = 0;
for (int i = index+1; i < 6; i++)
{
@@ -18,8 +17,9 @@ uint8_t getSameCodeLength(char code, int index, char const digits[])
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
* 0-9 | 0-9 (incl. random)
@@ -86,7 +86,7 @@ void setCronixie(char const digits[])
DEBUG_PRINT("cset ");
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++)
{
@@ -107,8 +107,8 @@ void setCronixie(char const digits[])
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] = 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] = 30 + getSameCodeLength('S',i,digits); i = i+dP[i]-30; cronixieRefreshMs = 497; break;
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; overlayRefreshMs = 497; 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 '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]);
cronixieRefreshedTime = 0; //refresh immediately
_overlayCronixie(); //refresh
}
void handleCronixie()
void _overlayCronixie()
{
if (millis() - cronixieRefreshedTime > cronixieRefreshMs)
{
cronixieRefreshedTime = millis();
local = TZ.toLocal(now(), &tcr);
if (cronixieCountdown) checkCountdown();
uint8_t h = hour(local);
uint8_t h0 = h;
uint8_t m = minute(local);
uint8_t s = second(local);
uint8_t d = day(local);
uint8_t mi = month(local);
if (countdownMode) checkCountdown();
byte h = hour(local);
byte h0 = h;
byte m = minute(local);
byte s = second(local);
byte d = day(local);
byte mi = month(local);
int y = year(local);
//this has to be changed in time for 22nd century
y -= 2000; if (y<0) y += 30; //makes countdown work
if (cronixieUseAMPM && !cronixieCountdown)
if (useAMPM && !countdownMode)
{
if (h>12) h-=12;
else if (h==0) h+=12;
@@ -213,6 +209,4 @@ void handleCronixie()
}
strip.setCronixieDigits(_digitOut);
//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
*/
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 Y = 1.0f; // Brightness, we handle this separately
float X = (1.0f / y) * x;
float Z = (1.0f / y) * z;
rgb[0] = (int)(X * 1.656492f - 0.354851f - Z * 0.255038f);
rgb[1] = (int)(-X * 0.707196f + 1.655397f + Z * 0.036152f);
rgb[2] = (int)(X * 0.051713f - 0.121364f + Z * 1.011530f);
float r = (int)255*(X * 1.656492f - 0.354851f - Z * 0.255038f);
float g = (int)255*(-X * 0.707196f + 1.655397f + Z * 0.036152f);
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
*/
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 "";
}