Merge pull request #27 from Aircoookie/development

Development
This commit is contained in:
Aircoookie 2018-06-24 01:38:12 +02:00 committed by GitHub
commit 65a0f60257
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 1079 additions and 233 deletions

View File

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

View File

@ -37,8 +37,8 @@
#define CALL_MODE(n) (this->*_mode[n])();
void WS2812FX::init(bool supportWhite, uint16_t countPixels, uint8_t pin) {
begin(supportWhite,countPixels,pin);
void WS2812FX::init(bool supportWhite, uint16_t countPixels, uint8_t pin,bool skipFirst) {
begin(supportWhite,countPixels,pin,skipFirst);
for (int i=0; i < _led_count; i++) _locked[i] = false;
WS2812FX::setBrightness(_brightness);
show();
@ -2032,6 +2032,7 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
if (_reverseMode) i = _led_count - 1 -i;
if (!_cronixieMode)
{
if (_skipFirstMode) {i++;if(i==1)setPixelColorRaw(0,0,0,0,0);}
if (_rgbwMode)
{
bus->SetPixelColor(i, RgbwColor(r,g,b,w));
@ -2050,27 +2051,27 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
byte wCorr = (int)(((double)((_color_sec>>24) & 0xFF))*_cronixieSecMultiplier);
for (int j=o; j< o+19; j++)
{
setPixelColorRaw(j,rCorr,gCorr,bCorr,wCorr);
setPixelColorRaw((_skipFirstMode)?j+1:j,rCorr,gCorr,bCorr,wCorr);
}
} else
{
for (int j=o; j< o+19; j++)
{
setPixelColorRaw(j,0,0,0,0);
setPixelColorRaw((_skipFirstMode)?j+1:j,0,0,0,0);
}
}
switch(_cronixieDigits[i])
{
case 0: setPixelColorRaw(o+5,r,g,b,w); break;
case 1: setPixelColorRaw(o+0,r,g,b,w); break;
case 2: setPixelColorRaw(o+6,r,g,b,w); break;
case 3: setPixelColorRaw(o+1,r,g,b,w); break;
case 4: setPixelColorRaw(o+7,r,g,b,w); break;
case 5: setPixelColorRaw(o+2,r,g,b,w); break;
case 6: setPixelColorRaw(o+8,r,g,b,w); break;
case 7: setPixelColorRaw(o+3,r,g,b,w); break;
case 8: setPixelColorRaw(o+9,r,g,b,w); break;
case 9: setPixelColorRaw(o+4,r,g,b,w); break;
case 0: setPixelColorRaw((_skipFirstMode)?o+6:o+5,r,g,b,w); break;
case 1: setPixelColorRaw((_skipFirstMode)?o+1:o+0,r,g,b,w); break;
case 2: setPixelColorRaw((_skipFirstMode)?o+7:o+6,r,g,b,w); break;
case 3: setPixelColorRaw((_skipFirstMode)?o+2:o+1,r,g,b,w); break;
case 4: setPixelColorRaw((_skipFirstMode)?o+8:o+7,r,g,b,w); break;
case 5: setPixelColorRaw((_skipFirstMode)?o+3:o+2,r,g,b,w); break;
case 6: setPixelColorRaw((_skipFirstMode)?o+9:o+8,r,g,b,w); break;
case 7: setPixelColorRaw((_skipFirstMode)?o+4:o+3,r,g,b,w); break;
case 8: setPixelColorRaw((_skipFirstMode)?o+10:o+9,r,g,b,w); break;
case 9: setPixelColorRaw((_skipFirstMode)?o+5:o+4,r,g,b,w); break;
default: break;
}
}
@ -2134,17 +2135,19 @@ void WS2812FX::clear()
bus->ClearTo(RgbColor(0));
}
void WS2812FX::begin(bool supportWhite, uint16_t countPixels, uint8_t pin)
void WS2812FX::begin(bool supportWhite, uint16_t countPixels, uint8_t pin, bool skipFirst)
{
if (supportWhite == _rgbwMode && countPixels == _led_count && _locked != NULL) return;
_rgbwMode = supportWhite;
_skipFirstMode = skipFirst;
_led_count = countPixels;
_cc_i2 = _led_count -1;
if (_skipFirstMode) _led_count++;
uint8_t ty = 1;
if (supportWhite) ty =2;
bus->Begin((NeoPixelType)ty, countPixels, pin);
bus->Begin((NeoPixelType)ty, _led_count, pin);
if (_locked != NULL) delete _locked;
_locked = new bool[countPixels];
_locked = new bool[_led_count];
}
//For some reason min and max are not declared here

View File

@ -199,6 +199,7 @@ class WS2812FX {
_counter_ccStep = 0;
_fastStandard = false;
_reverseMode = false;
_skipFirstMode = false;
_locked = NULL;
_cronixieDigits = new byte[6];
bus = new NeoPixelWrapper();
@ -208,7 +209,7 @@ class WS2812FX {
show(void),
setPixelColor(uint16_t i, byte r, byte g, byte b),
setPixelColor(uint16_t i, byte r, byte g, byte b, byte w),
init(bool supportWhite, uint16_t countPixels, uint8_t pin),
init(bool supportWhite, uint16_t countPixels, uint8_t pin, bool skipFirst),
service(void),
start(void),
stop(void),
@ -277,7 +278,7 @@ class WS2812FX {
NeoPixelWrapper *bus;
void
begin(bool supportWhite, uint16_t countPixels, uint8_t pin),
begin(bool supportWhite, uint16_t countPixels, uint8_t pin, bool skipFirst),
clear(void),
setPixelColor(uint16_t i, uint32_t c),
setPixelColorRaw(uint16_t i, byte r, byte g, byte b, byte w),
@ -348,6 +349,7 @@ class WS2812FX {
bool
_triggered,
_rgbwMode,
_skipFirstMode,
_fastStandard,
_reverseMode,
_cronixieMode,

View File

@ -1,8 +1,8 @@
<!DOCTYPE html>
<html>
<head><meta charset="utf-8">
<head><meta charset="utf-8"><meta name="theme-color" content="#fff">
<link rel='shortcut icon' type='image/x-icon' href='/favicon.ico'/>
<title>WLED 0.6.4</title>
<title>WLED 0.7.0</title>
<script>
var d=document;
var w=window.getComputedStyle(d.querySelector("html"));
@ -33,6 +33,7 @@
aC = w.getPropertyValue("--aCol");
bC = w.getPropertyValue("--bCol");
dC = w.getPropertyValue("--dCol");
d.querySelector("meta[name=theme-color]").setAttribute("content",bC);
CV(0);
setInterval('GIO()', 5000);
GIO();
@ -197,6 +198,7 @@
function SwFX(s)
{
var n=Cf.TX.selectedIndex+s;
if (n==-1||n==58) return;
Cf.TX.selectedIndex =n;
if (n < 0) Cf.TX.selectedIndex = 0;
if (n > 57) Cf.TX.selectedIndex = 53;
@ -217,21 +219,22 @@
if (d.Cf.FF.value < 1) d.Cf.FF.value = 1;
if (d.Cf.FF.value > 25) d.Cf.FF.value = 25;
}
function PAt()
{
resp+=(d.Cf.BC.checked)?"&PA=1":"&PA=0";
resp+=(d.Cf.CC.checked)?"&PC=1":"&PC=0";
resp+=(d.Cf.FC.checked)?"&PX=1":"&PX=0";
}
function PSIO(sv)
{
PAt();
if(sv)
{
resp+="&PS=";
resp+=d.Cf.FF.value;
} else
{
if (d.Cf.BC.checked&&d.Cf.CC.checked&&d.Cf.FC.checked)
{resp+="&PL=";resp+=d.Cf.FF.value;}
else {
if(d.Cf.BC.checked){resp+="&PA=";resp+=d.Cf.FF.value;}
if(d.Cf.CC.checked){resp+="&PC=";resp+=d.Cf.FF.value;}
if(d.Cf.FC.checked){resp+="&PX=";resp+=d.Cf.FF.value;}
}
resp+="&PL=";resp+=d.Cf.FF.value;
}
GIO();
}
@ -337,13 +340,11 @@
}
function uCY()
{
PAt();
resp+=(d.Cf.CY.checked)?"&CY=1":"&CY=0";
resp+="&P1=" + Cf.P1.value;
resp+="&P2=" + Cf.P2.value;
resp+="&PT=" + Cf.PT.value;
if(d.Cf.BC.checked){resp+="&PA";}
if(d.Cf.CC.checked){resp+="&PC";}
if(d.Cf.FC.checked){resp+="&PX";}
GIO();
}
function R()
@ -353,11 +354,12 @@
</script>
<style>
:root {
--aCol: #0ac;
--bCol: #124;
--cCol: #334;
--dCol: #288;
--sCol: #FF00FF;
--aCol: #D9B310;
--bCol: #0B3C5D;
--cCol: #1D2731;
--dCol: #328CC1;
--sCol: #000;
--tCol: #328CC1;
--cFn: Verdana;
}
.ctrl_box {

File diff suppressed because one or more lines are too long

View File

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

View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

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

View File

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

View File

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

View File

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

View File

@ -3,10 +3,14 @@
*/
/*
* @title WLED project sketch
* @version 0.6.4
* @version 0.7.0
* @author Christian Schwinne
*/
//ESP8266-01 got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.3.0 and the setting 512K(64K SPIFFS).
//Uncomment the following line to disable some features (currently Mobile UI) to compile for ESP8266-01
//#define WLED_FLASH_512K_MODE
#include <Arduino.h>
#ifdef ARDUINO_ARCH_ESP32
#include <WiFi.h>
@ -33,8 +37,8 @@
#include "WS2812FX.h"
//version in format yymmddb (b = daily build)
#define VERSION 1804151
const String versionString = "0.6.4";
#define VERSION 1806240
const String versionString = "0.7.0";
//AP and OTA default passwords (change them!)
String apPass = "wled1234";
@ -54,8 +58,9 @@ byte auxDefaultState = 0; //0: input 1: high 2: low
byte auxTriggeredState = 0; //0: input 1: high 2: low
//Default CONFIG
String serverDescription = versionString;
String serverDescription = "WLED Light";
byte currentTheme = 0;
byte uiConfiguration = 0; //0: auto 1: classic 2: mobile
String clientSSID = "Your_Network";
String clientPass = "";
String cmDNS = "led";
@ -69,9 +74,9 @@ IPAddress staticIP(0, 0, 0, 0);
IPAddress staticGateway(0, 0, 0, 0);
IPAddress staticSubnet(255, 255, 255, 0);
IPAddress staticDNS(8, 8, 8, 8); //only for NTP
bool useHSB = true, useHSBDefault = true, useRGBW = false;
bool useHSB = true, useHSBDefault = true, useRGBW = false, autoRGBtoRGBW = false;
bool turnOnAtBoot = true;
bool initLedsLast = false;
bool initLedsLast = false, skipFirstLed = false;
byte bootPreset = 0;
byte colS[]{255, 159, 0};
byte colSecS[]{0, 0, 0};
@ -81,6 +86,7 @@ byte briS = 127;
byte nightlightTargetBri = 0;
bool fadeTransition = true;
bool sweepTransition = false, sweepDirection = true;
bool disableSecTransition = true;
uint16_t transitionDelay = 1200, transitionDelayDefault = transitionDelay;
bool reverseMode = false;
bool otaLock = false, wifiLock = false;
@ -91,7 +97,7 @@ bool receiveNotifications = true, receiveNotificationBrightness = true, receiveN
byte briMultiplier = 100;
byte nightlightDelayMins = 60;
bool nightlightFade = true;
uint16_t udpPort = 21324;
uint16_t udpPort = 21324, udpRgbPort = 19446;
byte effectDefault = 0;
byte effectSpeedDefault = 75;
byte effectIntensityDefault = 128;
@ -126,15 +132,19 @@ IPAddress hueIP = (0,0,0,0);
bool notifyHue = true;
bool hueApplyOnOff = true, hueApplyBri = true, hueApplyColor = true;
uint16_t userVar0 = 0, userVar1 = 0;
//Internal vars
byte col[]{0, 0, 0};
byte colOld[]{0, 0, 0};
byte colT[]{0, 0, 0};
byte colIT[]{0, 0, 0};
byte colSec[]{0, 0, 0};
byte colSecT[]{0, 0, 0};
byte colSecOld[]{0, 0, 0};
byte colSecIT[]{0, 0, 0};
byte white, whiteOld, whiteT, whiteIT;
byte whiteSec, whiteSecIT;
byte whiteSec, whiteSecOld, whiteSecT, whiteSecIT;
byte lastRandomIndex = 0;
uint16_t transitionDelayTemp = transitionDelay;
unsigned long transitionStartTime;
@ -153,20 +163,20 @@ byte notificationSentCallMode = 0;
bool notificationTwoRequired = false;
bool nightlightActive = false;
bool nightlightActiveOld = false;
uint32_t nightlightDelayMs;
byte briNlT;
uint32_t nightlightDelayMs = 10;
byte briNlT = 0;
byte effectCurrent = 0;
byte effectSpeed = 75;
byte effectIntensity = 128;
bool onlyAP = false;
bool udpConnected = false;
bool udpConnected = false, udpRgbConnected = false;
String cssCol[]={"","","","","",""};
String cssFont="Verdana";
String cssColorString="";
//NTP stuff
bool ntpConnected = false;
byte currentTimezone = 0;
time_t local;
time_t local = 0;
int utcOffsetSecs = 0;
//hue
@ -207,15 +217,17 @@ bool presetCyclingEnabled = false;
byte presetCycleMin = 1, presetCycleMax = 5;
uint16_t presetCycleTime = 1250;
unsigned long presetCycledTime = 0; byte presetCycCurr = presetCycleMin;
bool presetCycleBri, presetCycleCol, presetCycleFx;
bool presetApplyBri = true, presetApplyCol = true, presetApplyFx = true;
bool saveCurrPresetCycConf = false;
uint32_t arlsTimeoutMillis = 2500;
bool arlsTimeout = false;
bool receiveDirect = true;
unsigned long arlsTimeoutTime;
bool receiveDirect = true, enableRealtimeUI = false;
IPAddress realtimeIP = (0,0,0,0);
unsigned long arlsTimeoutTime = 0;
byte auxTime = 0;
unsigned long auxStartTime;
bool auxActive, auxActiveBefore;
unsigned long auxStartTime = 0;
bool auxActive = false, auxActiveBefore = false;
bool showWelcomePage = false;
bool useGammaCorrectionBri = false;
@ -240,7 +252,7 @@ ESP8266WebServer server(80);
#endif
HTTPClient hueClient;
ESP8266HTTPUpdateServer httpUpdater;
WiFiUDP notifierUdp;
WiFiUDP notifierUdp, rgbUdp;
WiFiUDP ntpUdp;
IPAddress ntpServerIP;
unsigned int ntpLocalPort = 2390;
@ -294,14 +306,6 @@ String txd = "Please disable OTA Lock in security settings!";
void serveMessage(int,String,String,int=255);
void down()
{
briT = 0;
setAllLeds();
DEBUG_PRINTLN("MODULE TERMINATED");
while (1) {delay(1000);}
}
void reset()
{
briT = 0;
@ -323,7 +327,7 @@ void loop() {
yield();
handleButton();
handleNetworkTime();
if (!otaLock && aOtaEnabled) ArduinoOTA.handle();
if (aOtaEnabled) ArduinoOTA.handle();
handleAlexa();
handleOverlays();
if (!arlsTimeout) //block stuff if WARLS/Adalight is enabled

View File

@ -148,6 +148,7 @@ void saveSettingsToEEPROM()
EEPROM.write(396, (utcOffsetSecs<0)); //is negative
EEPROM.write(397, initLedsLast);
EEPROM.write(398, (ledCount >> 8) & 0xFF);
EEPROM.write(399, disableSecTransition);
for (int k=0;k<6;k++){
int in = 900+k*8;
@ -209,6 +210,25 @@ void saveSettingsToEEPROM()
EEPROM.write(2180, macroCountdown);
EEPROM.write(2181, macroNl);
EEPROM.write(2200,!receiveDirect);
EEPROM.write(2201,enableRealtimeUI);
EEPROM.write(2202,uiConfiguration);
EEPROM.write(2203,autoRGBtoRGBW);
EEPROM.write(2204,skipFirstLed);
if (saveCurrPresetCycConf)
{
EEPROM.write(2205,presetCyclingEnabled);
EEPROM.write(2206,(presetCycleTime >> 0) & 0xFF);
EEPROM.write(2207,(presetCycleTime >> 8) & 0xFF);
EEPROM.write(2208,presetCycleMin);
EEPROM.write(2209,presetCycleMax);
EEPROM.write(2210,presetApplyBri);
EEPROM.write(2211,presetApplyCol);
EEPROM.write(2212,presetApplyFx);
saveCurrPresetCycConf = false;
}
EEPROM.commit();
}
@ -260,7 +280,7 @@ void loadSettingsFromEEPROM(bool first)
if (apChannel > 13 || apChannel < 1) apChannel = 1;
apHide = EEPROM.read(228);
if (apHide > 1) apHide = 1;
ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200) ledCount = 10;
ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10;
notifyButton = EEPROM.read(230);
notifyTwice = EEPROM.read(231);
buttonEnabled = EEPROM.read(232);
@ -416,14 +436,37 @@ void loadSettingsFromEEPROM(bool first)
macroCountdown = EEPROM.read(2180);
macroNl = EEPROM.read(2181);
}
receiveDirect = !EEPROM.read(2200);
enableRealtimeUI = EEPROM.read(2201);
uiConfiguration = EEPROM.read(2202);
#ifdef WLED_FLASH_512K_MODE
uiConfiguration = 1;
//force default UI since mobile is unavailable
#endif
autoRGBtoRGBW = EEPROM.read(2203);
skipFirstLed = EEPROM.read(2204);
if (EEPROM.read(2210) || EEPROM.read(2211) || EEPROM.read(2212))
{
presetCyclingEnabled = EEPROM.read(2205);
presetCycleTime = ((EEPROM.read(2206) << 0) & 0xFF) + ((EEPROM.read(2207) << 8) & 0xFF00);
presetCycleMin = EEPROM.read(2208);
presetCycleMax = EEPROM.read(2209);
presetApplyBri = EEPROM.read(2210);
presetApplyCol = EEPROM.read(2211);
presetApplyFx = EEPROM.read(2212);
}
bootPreset = EEPROM.read(389);
wifiLock = EEPROM.read(393);
utcOffsetSecs = ((EEPROM.read(394) << 0) & 0xFF) + ((EEPROM.read(395) << 8) & 0xFF00);
if (EEPROM.read(396)) utcOffsetSecs = -utcOffsetSecs; //negative
initLedsLast = EEPROM.read(397);
disableSecTransition = EEPROM.read(399);
//favorite setting memory (25 slots/ each 20byte)
//favorite setting (preset) memory (25 slots/ each 20byte)
//400 - 899 reserved
currentTheme = EEPROM.read(948);

View File

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

View File

@ -121,7 +121,9 @@ void handleSettingsSet(byte subPage)
if (ledCount > 600) ledCount = 600;
#endif
}
ccIndex2 = ledCount -1;
useRGBW = server.hasArg("EW");
autoRGBtoRGBW = server.hasArg("AW");
if (server.hasArg("IS")) //ignore settings and save current brightness, colors and fx as default
{
colS[0] = col[0];
@ -193,6 +195,7 @@ void handleSettingsSet(byte subPage)
if (i >= 0 && i <= 255) effectIntensityDefault = i;
}
}
saveCurrPresetCycConf = server.hasArg("PC");
turnOnAtBoot = server.hasArg("BO");
if (server.hasArg("BP"))
{
@ -211,6 +214,7 @@ void handleSettingsSet(byte subPage)
transitionDelay = i;
}
}
disableSecTransition = !server.hasArg("T2");
if (server.hasArg("TB"))
{
nightlightTargetBri = server.arg("TB").toInt();
@ -229,6 +233,7 @@ void handleSettingsSet(byte subPage)
int i = server.arg("WO").toInt();
if (i >= -255 && i <= 255) arlsOffset = i;
}
skipFirstLed = server.hasArg("SL");
if (server.hasArg("BF"))
{
int i = server.arg("BF").toInt();
@ -239,6 +244,7 @@ void handleSettingsSet(byte subPage)
//UI
if (subPage == 3)
{
if (server.hasArg("UI")) uiConfiguration = server.arg("UI").toInt();
if (server.hasArg("DS")) serverDescription = server.arg("DS");
useHSBDefault = server.hasArg("MD");
useHSB = useHSBDefault;
@ -267,6 +273,8 @@ void handleSettingsSet(byte subPage)
notifyDirect = notifyDirectDefault;
notifyButton = server.hasArg("SB");
notifyTwice = server.hasArg("S2");
receiveDirect = server.hasArg("RD");
enableRealtimeUI = server.hasArg("RU");
alexaEnabled = server.hasArg("AL");
if (server.hasArg("AI")) alexaInvocationName = server.arg("AI");
alexaNotify = server.hasArg("SA");
@ -381,7 +389,7 @@ void handleSettingsSet(byte subPage)
}
}
saveSettingsToEEPROM();
if (subPage == 2) strip.init(useRGBW,ledCount,PIN);
if (subPage == 2) strip.init(useRGBW,ledCount,PIN,skipFirstLed);
}
bool handleSet(String req)
@ -703,6 +711,8 @@ bool handleSet(String req)
}
}
}
//deactivate nightlight if target brightness is reached
if (bri == nightlightTargetBri) nightlightActive = false;
//set time (unix timestamp)
pos = req.indexOf("ST=");
if (pos > 0) {
@ -729,6 +739,12 @@ bool handleSet(String req)
if (_cc_updated) strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd);
//set presets
pos = req.indexOf("P1="); //sets first preset for cycle
if (pos > 0) presetCycleMin = req.substring(pos + 3).toInt();
pos = req.indexOf("P2="); //sets last preset for cycle
if (pos > 0) presetCycleMax = req.substring(pos + 3).toInt();
if (req.indexOf("CY=") > 0) //preset cycle
{
presetCyclingEnabled = true;
@ -736,61 +752,36 @@ bool handleSet(String req)
{
presetCyclingEnabled = false;
}
bool all = true;
if (req.indexOf("&PA") > 0)
{
presetCycleBri = true;
all = false;
}
if (req.indexOf("&PC") > 0)
{
presetCycleCol = true;
all = false;
}
if (req.indexOf("&PX") > 0)
{
presetCycleFx = true;
all = false;
}
if (all)
{
presetCycleBri = true;
presetCycleCol = true;
presetCycleFx = true;
}
presetCycCurr = presetCycleMin;
}
pos = req.indexOf("PT="); //sets cycle time in ms
if (pos > 0) {
int v = req.substring(pos + 3).toInt();
if (v > 49) presetCycleTime = v;
}
pos = req.indexOf("P1="); //sets first preset for cycle
if (pos > 0) presetCycleMin = req.substring(pos + 3).toInt();
pos = req.indexOf("P2="); //sets last preset for cycle
if (pos > 0) presetCycleMax = req.substring(pos + 3).toInt();
if (req.indexOf("PA=") > 0) //apply brightness from preset
{
presetApplyBri = true;
if (req.indexOf("PA=0") > 0) presetApplyBri = false;
}
if (req.indexOf("PC=") > 0) //apply color from preset
{
presetApplyCol = true;
if (req.indexOf("PC=0") > 0) presetApplyCol = false;
}
if (req.indexOf("PX=") > 0) //apply effects from preset
{
presetApplyFx = true;
if (req.indexOf("PX=0") > 0) presetApplyFx = false;
}
pos = req.indexOf("PS="); //saves current in preset
if (pos > 0) {
savePreset(req.substring(pos + 3).toInt());
}
pos = req.indexOf("PL="); //applies entire preset
if (pos > 0) {
applyPreset(req.substring(pos + 3).toInt(), true, true, true);
effectUpdated = true;
}
pos = req.indexOf("PA="); //applies brightness from preset
if (pos > 0) {
applyPreset(req.substring(pos + 3).toInt(), true, false, false);
}
pos = req.indexOf("PC="); //applies color from preset
if (pos > 0) {
applyPreset(req.substring(pos + 3).toInt(), false, true, false);
}
pos = req.indexOf("PX="); //applies effects from preset
if (pos > 0) {
applyPreset(req.substring(pos + 3).toInt(), false, false, true);
effectUpdated = true;
applyPreset(req.substring(pos + 3).toInt(), presetApplyBri, presetApplyCol, presetApplyFx);
if (presetApplyFx) effectUpdated = true;
}
//cronixie
@ -817,6 +808,15 @@ bool handleSet(String req)
if (overlayCurrent == 4) strip.setCronixieBacklight(cronixieBacklight);
overlayRefreshedTime = 0;
}
pos = req.indexOf("U0="); //user var 0
if (pos > 0) {
userVar0 = req.substring(pos + 3).toInt();
}
pos = req.indexOf("U1="); //user var 1
if (pos > 0) {
userVar1 = req.substring(pos + 3).toInt();
}
//you can add more if you need
//internal call, does not send XML response
pos = req.indexOf("IN");

View File

@ -13,7 +13,7 @@ void handleSerial()
strip.setMode(0);
}
arlsTimeout = true;
arlsTimeoutTime = millis() + 4900;
arlsTimeoutTime = millis() + 5200;
delay(1);
byte hi = Serial.read();
byte ledc = Serial.read();

View File

@ -5,12 +5,12 @@
void wledInit()
{
EEPROM.begin(EEPSIZE);
ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200) ledCount = 10;
ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10;
//RMT eats up too much RAM
#ifdef ARDUINO_ARCH_ESP32
if (ledCount > 600) ledCount = 600;
#endif
if (!EEPROM.read(397)) strip.init(EEPROM.read(372),ledCount,PIN); //quick init
if (!EEPROM.read(397)) strip.init(EEPROM.read(372),ledCount,PIN,EEPROM.read(2204)); //quick init
Serial.begin(115200);
Serial.setTimeout(50);
@ -40,16 +40,10 @@ void wledInit()
hueIP[2] = WiFi.localIP()[2];
}
// Set up mDNS responder:
if (cmDNS != NULL && !onlyAP && !MDNS.begin(cmDNS.c_str())) {
DEBUG_PRINTLN("Error setting up MDNS responder!");
down();
}
DEBUG_PRINTLN("mDNS responder started");
if (udpPort > 0 && udpPort != ntpLocalPort && WiFi.status() == WL_CONNECTED)
{
udpConnected = notifierUdp.begin(udpPort);
if (udpConnected && udpRgbPort != udpPort) udpRgbConnected = rgbUdp.begin(udpRgbPort);
}
if (ntpEnabled && WiFi.status() == WL_CONNECTED)
ntpConnected = ntpUdp.begin(ntpLocalPort);
@ -171,16 +165,18 @@ void wledInit()
server.send(200, "text/plain", (String)ESP.getFreeHeap());
});
server.on("/pdebug", HTTP_GET, [](){
server.send(200, "text/plain", (String)presetCycleTime);
});
server.on("/power", HTTP_GET, [](){
String val = (String)(int)strip.getPowerEstimate(ledCount,strip.getColor(),strip.getBrightness());
val += "mA currently";
serveMessage(200,val,"This is just an estimate (does not take into account several factors like effects and wire resistance). It is NOT an accurate measurement!",254);
});
server.on("/u", HTTP_GET, [](){
server.setContentLength(strlen_P(PAGE_usermod));
server.send(200, "text/html", "");
server.sendContent_P(PAGE_usermod);
});
server.on("/teapot", HTTP_GET, [](){
serveMessage(418, "418. I'm a teapot.","(Tangible Embedded Advanced Project Of Twinkling)",254);
});
@ -199,8 +195,6 @@ void wledInit()
server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); }, handleFileUpload);
server.on("/list", HTTP_GET, handleFileList);
#endif
server.on("/down", HTTP_GET, down);
server.on("/cleareeprom", HTTP_GET, clearEEPROM);
//init ota page
httpUpdater.setup(&server);
} else
@ -208,12 +202,6 @@ void wledInit()
server.on("/edit", HTTP_GET, [](){
serveMessage(500, "Access Denied", txd, 254);
});
server.on("/down", HTTP_GET, [](){
serveMessage(500, "Access Denied", txd, 254);
});
server.on("/cleareeprom", HTTP_GET, [](){
serveMessage(500, "Access Denied", txd, 254);
});
server.on("/update", HTTP_GET, [](){
serveMessage(500, "Access Denied", txd, 254);
});
@ -231,14 +219,21 @@ void wledInit()
server.send(404, "text/plain", "Not Found");
}
});
#ifndef ARDUINO_ARCH_ESP32
const char * headerkeys[] = {"User-Agent"};
server.collectHeaders(headerkeys,sizeof(char*));
#else
String ua = "User-Agent";
server.collectHeaders(ua);
#endif
if (!initLedsLast) strip.service();
//init Alexa hue emulation
if (alexaEnabled) alexaInit();
server.begin();
DEBUG_PRINTLN("HTTP server started");
// Add service to MDNS
MDNS.addService("http", "tcp", 80);
//init ArduinoOTA
if (aOtaEnabled)
@ -249,9 +244,20 @@ void wledInit()
#endif
DEBUG_PRINTLN("Start ArduinoOTA");
});
if (cmDNS.length() > 0) ArduinoOTA.setHostname(cmDNS.c_str());
ArduinoOTA.begin();
}
if (!initLedsLast) strip.service();
// Set up mDNS responder:
if (cmDNS.length() > 0 && !onlyAP)
{
MDNS.begin(cmDNS.c_str());
DEBUG_PRINTLN("mDNS responder started");
// Add service to MDNS
MDNS.addService("http", "tcp", 80);
}
if (initLedsLast) initStrip();
userBegin();
if (macroBoot>0) applyMacro(macroBoot);
@ -261,13 +267,15 @@ void wledInit()
void initStrip()
{
// Initialize NeoPixel Strip and button
if (initLedsLast) strip.init(useRGBW,ledCount,PIN);
if (initLedsLast) strip.init(useRGBW,ledCount,PIN,skipFirstLed);
strip.setReverseMode(reverseMode);
strip.setColor(0);
strip.setBrightness(255);
strip.start();
pinMode(buttonPin, INPUT_PULLUP);
pinMode(4,OUTPUT); //this is only needed in special cases
digitalWrite(4,LOW);
if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true);
colorUpdated(0);
@ -305,7 +313,13 @@ void initCon()
}
int fail_count = 0;
if (clientSSID.length() <1 || clientSSID.equals("Your_Network")) fail_count = apWaitTimeSecs*2;
#ifndef ARDUINO_ARCH_ESP32
WiFi.hostname(serverDescription);
#endif
WiFi.begin(clientSSID.c_str(), clientPass.c_str());
#ifdef ARDUINO_ARCH_ESP32
WiFi.setHostname(serverDescription.c_str());
#endif
unsigned long lastTry = 0;
bool con = false;
while(!con)
@ -386,19 +400,46 @@ void serveIndexOrWelcome()
}
}
void serveRealtimeError(bool settings)
{
String mesg = "The ";
mesg += (settings)?"settings":"WLED";
mesg += " UI is not available while receiving real-time data (UDP from ";
mesg += realtimeIP[0];
for (int i = 1; i < 4; i++)
{
mesg += ".";
mesg += realtimeIP[i];
}
mesg += ").";
server.send(200, "text/plain", mesg);
}
void serveIndex()
{
if (!arlsTimeout) //do not serve while receiving realtime
bool serveMobile = false;
if (uiConfiguration == 0) serveMobile = checkClientIsMobile(server.header("User-Agent"));
else if (uiConfiguration == 2) serveMobile = true;
if (!arlsTimeout || enableRealtimeUI) //do not serve while receiving realtime
{
server.setContentLength(strlen_P(PAGE_index0) + cssColorString.length() + strlen_P(PAGE_index1) + strlen_P(PAGE_index2) + strlen_P(PAGE_index3));
server.send(200, "text/html", "");
server.sendContent_P(PAGE_index0);
server.sendContent(cssColorString);
server.sendContent_P(PAGE_index1);
server.sendContent_P(PAGE_index2);
server.sendContent_P(PAGE_index3);
if (serveMobile)
{
server.setContentLength(strlen_P(PAGE_indexM));
server.send(200, "text/html", "");
server.sendContent_P(PAGE_indexM);
} else
{
server.setContentLength(strlen_P(PAGE_index0) + cssColorString.length() + strlen_P(PAGE_index1) + strlen_P(PAGE_index2) + strlen_P(PAGE_index3));
server.send(200, "text/html", "");
server.sendContent_P(PAGE_index0);
server.sendContent(cssColorString);
server.sendContent_P(PAGE_index1);
server.sendContent_P(PAGE_index2);
server.sendContent_P(PAGE_index3);
}
} else {
server.send(200, "text/plain", "The WLED UI is not available while receiving real-time data.");
serveRealtimeError(false);
}
}
@ -436,7 +477,7 @@ void serveMessage(int code, String headl, String subl="", int optionType)
void serveSettings(byte subPage)
{
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 255: welcomepage
if (!arlsTimeout) //do not serve while receiving realtime
if (!arlsTimeout || enableRealtimeUI) //do not serve while receiving realtime
{
int pl0, pl1;
switch (subPage)
@ -483,7 +524,7 @@ void serveSettings(byte subPage)
default: server.sendContent_P(PAGE_settings1);
}
} else {
server.send(200, "text/plain", "The settings are not available while receiving real-time data.");
serveRealtimeError(true);
}
}
@ -518,5 +559,14 @@ String getBuildInfo()
return info;
}
bool checkClientIsMobile(String useragent)
{
//to save complexity this function is not comprehensive
if (useragent.indexOf("Android") >= 0) return true;
if (useragent.indexOf("iPhone") >= 0) return true;
if (useragent.indexOf("iPod") >= 0) return true;
return false;
}

View File

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

View File

@ -50,14 +50,60 @@ void notify(byte callMode, bool followUp=false)
notificationTwoRequired = (followUp)? false:notifyTwice;
}
void arlsLock(uint32_t timeoutMs)
{
if (!arlsTimeout){
strip.setRange(0, ledCount-1, 0);
strip.setMode(0);
}
arlsTimeout = true;
arlsTimeoutTime = millis() + timeoutMs;
}
void handleNotifications()
{
//send second notification if enabled
if(udpConnected && notificationTwoRequired && millis()-notificationSentTime > 250){
notify(notificationSentCallMode,true);
}
//unlock strip when realtime UDP times out
if (arlsTimeout && millis() > arlsTimeoutTime)
{
strip.unlockAll();
if (bri == 0) strip.setBrightness(0);
arlsTimeout = false;
strip.setMode(effectCurrent);
}
//receive UDP notifications
if(udpConnected && (receiveNotifications || receiveDirect)){
uint16_t packetSize = notifierUdp.parsePacket();
//hyperion / raw RGB
if (!packetSize && udpRgbConnected) {
packetSize = rgbUdp.parsePacket();
if (!receiveDirect) return;
realtimeIP = rgbUdp.remoteIP();
if (packetSize > 1026 || packetSize < 3) return;
byte udpIn[packetSize];
rgbUdp.read(udpIn, packetSize);
arlsLock(5200);
uint16_t id = 0;
for (uint16_t i = 0; i < packetSize -2; i += 3)
{
if (useGammaCorrectionRGB)
{
strip.setPixelColor(id, gamma8[udpIn[i]], gamma8[udpIn[i+1]], gamma8[udpIn[i+2]]);
} else {
strip.setPixelColor(id, udpIn[i], udpIn[i+1], udpIn[i+2]);
}
id++; if (id >= ledCount) break;
}
strip.show();
return;
}
if (packetSize > 1026) return;
if(packetSize && notifierUdp.remoteIP() != WiFi.localIP()) //don't process broadcasts we send ourselves
{
@ -107,23 +153,19 @@ void handleNotifications()
if (receiveNotificationBrightness) bri = udpIn[2];
colorUpdated(3);
}
} else if (udpIn[0] > 0 && udpIn[0] < 4) //1 warls //2 drgb //3 drgbw
} else if (udpIn[0] > 0 && udpIn[0] < 4 && receiveDirect) //1 warls //2 drgb //3 drgbw
{
realtimeIP = notifierUdp.remoteIP();
if (packetSize > 1) {
if (udpIn[1] == 0)
{
arlsTimeout = false;
} else {
if (!arlsTimeout){
strip.setRange(0, ledCount-1, 0);
strip.setMode(0);
}
arlsTimeout = true;
arlsTimeoutTime = millis() + 1000*udpIn[1];
arlsLock(udpIn[1]*1000);
}
if (udpIn[0] == 1) //warls
{
for (int i = 2; i < packetSize -3; i += 4)
for (uint16_t i = 2; i < packetSize -3; i += 4)
{
if (udpIn[i] + arlsOffset < ledCount && udpIn[i] + arlsOffset >= 0)
if (useGammaCorrectionRGB)
@ -133,10 +175,10 @@ void handleNotifications()
strip.setPixelColor(udpIn[i] + arlsOffset, udpIn[i+1], udpIn[i+2], udpIn[i+3]);
}
}
} else if (udpIn[0] == 2 && receiveDirect) //drgb
} else if (udpIn[0] == 2) //drgb
{
int id = 0;
for (int i = 2; i < packetSize -2; i += 3)
uint16_t id = 0;
for (uint16_t i = 2; i < packetSize -2; i += 3)
{
if (useGammaCorrectionRGB)
{
@ -146,10 +188,10 @@ void handleNotifications()
}
id++; if (id >= ledCount) break;
}
} else if (udpIn[0] == 3 && receiveDirect) //drgbw
} else if (udpIn[0] == 3) //drgbw
{
int id = 0;
for (int i = 2; i < packetSize -3; i += 4)
uint16_t id = 0;
for (uint16_t i = 2; i < packetSize -3; i += 4)
{
if (useGammaCorrectionRGB)
{
@ -165,13 +207,6 @@ void handleNotifications()
}
}
}
if (arlsTimeout && millis() > arlsTimeoutTime)
{
strip.unlockAll();
if (bri == 0) strip.setBrightness(0);
arlsTimeout = false;
strip.setMode(effectCurrent);
}
}

View File

@ -12,28 +12,44 @@ void setAllLeds() {
} else {
strip.setBrightness(val);
}
if (disableSecTransition)
{
for (byte i = 0; i<3; i++)
{
colSecT[i] = colSec[i];
}
whiteSecT = whiteSec;
}
if (autoRGBtoRGBW)
{
colorRGBtoRGBW(colT,&whiteT);
colorRGBtoRGBW(colSecT,&whiteSecT);
}
if (useGammaCorrectionRGB)
{
strip.setColor(gamma8[colT[0]], gamma8[colT[1]], gamma8[colT[2]], gamma8[whiteT]);
strip.setSecondaryColor(gamma8[colSec[0]], gamma8[colSec[1]], gamma8[colSec[2]], gamma8[whiteSec]);
strip.setSecondaryColor(gamma8[colSecT[0]], gamma8[colSecT[1]], gamma8[colSecT[2]], gamma8[whiteSecT]);
} else {
strip.setColor(colT[0], colT[1], colT[2], whiteT);
strip.setSecondaryColor(colSec[0], colSec[1], colSec[2], whiteSec);
strip.setSecondaryColor(colSecT[0], colSecT[1], colSecT[2], whiteSecT);
}
}
void setLedsStandard()
{
colOld[0] = col[0];
colOld[1] = col[1];
colOld[2] = col[2];
for (byte i = 0; i<3; i++)
{
colOld[i] = col[i];
colT[i] = col[i];
colSecOld[i] = colSec[i];
colSecT[i] = colSec[i];
}
whiteOld = white;
briOld = bri;
colT[0] = col[0];
colT[1] = col[1];
colT[2] = col[2];
whiteSecOld = whiteSec;
whiteT = white;
briT = bri;
whiteSecT = whiteSec;
setAllLeds();
}
@ -86,6 +102,10 @@ void colorUpdated(int callMode)
colOld[1] = colT[1];
colOld[2] = colT[2];
whiteOld = whiteT;
colSecOld[0] = colSecT[0];
colSecOld[1] = colSecT[1];
colSecOld[2] = colSecT[2];
whiteSecOld = whiteSecT;
briOld = briT;
tperLast = 0;
}
@ -120,10 +140,13 @@ void handleTransitions()
tperLast = tper;
if (fadeTransition)
{
colT[0] = colOld[0]+((col[0] - colOld[0])*tper);
colT[1] = colOld[1]+((col[1] - colOld[1])*tper);
colT[2] = colOld[2]+((col[2] - colOld[2])*tper);
for (byte i = 0; i<3; i++)
{
colT[i] = colOld[i]+((col[i] - colOld[i])*tper);
colSecT[i] = colSecOld[i]+((colSec[i] - colSecOld[i])*tper);
}
whiteT = whiteOld +((white - whiteOld )*tper);
whiteSecT = whiteSecOld +((whiteSec - whiteSecOld )*tper);
briT = briOld +((bri - briOld )*tper);
}
if (sweepTransition)
@ -181,7 +204,7 @@ void handleNightlight()
//also handle preset cycle here
if (presetCyclingEnabled && (millis() - presetCycledTime > presetCycleTime))
{
applyPreset(presetCycCurr,presetCycleBri,presetCycleCol,presetCycleFx);
applyPreset(presetCycCurr,presetApplyBri,presetApplyCol,presetApplyFx);
presetCycCurr++; if (presetCycCurr > presetCycleMax) presetCycCurr = presetCycleMin;
if (presetCycCurr > 25) presetCycCurr = 1;
colorUpdated(8);

View File

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