Release of v0.6.3

Added Preset Cycle feature
Added Transition Time API call
Added Adalight serial ambilight protocol
Added DRGB and DRGBW UDP direct-drive protocols
Improved transition flickering
Easter eggs are eaten now
This commit is contained in:
cschwinne 2018-04-11 23:50:35 +02:00
parent df05754872
commit ee6676cd89
16 changed files with 256 additions and 130 deletions

View File

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

View File

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

View File

@ -66,6 +66,7 @@ void WS2812FX::start() {
_counter_mode_step = 0; _counter_mode_step = 0;
_mode_last_call_time = 0; _mode_last_call_time = 0;
_running = true; _running = true;
show();
} }
void WS2812FX::stop() { void WS2812FX::stop() {
@ -85,11 +86,8 @@ void WS2812FX::setMode(byte m) {
} }
void WS2812FX::setSpeed(byte s) { void WS2812FX::setSpeed(byte s) {
_counter_mode_call = 0;
_counter_mode_step = 0;
_mode_last_call_time = 0; _mode_last_call_time = 0;
_speed = constrain(s, SPEED_MIN, SPEED_MAX); _speed = constrain(s, SPEED_MIN, SPEED_MAX);
strip_off_respectLock();
} }
void WS2812FX::increaseSpeed(byte s) { void WS2812FX::increaseSpeed(byte s) {
@ -2127,7 +2125,7 @@ void WS2812FX::setBrightness(byte b)
{ {
_brightness = constrain(b, BRIGHTNESS_MIN, BRIGHTNESS_MAX); _brightness = constrain(b, BRIGHTNESS_MIN, BRIGHTNESS_MAX);
NeoPixelBrightnessBus::SetBrightness(_brightness); NeoPixelBrightnessBus::SetBrightness(_brightness);
show(); if (_mode_last_call_time + _mode_delay > millis()+50 || b == 0) show(); //only update right away if long time until next refresh
} }
void WS2812FX::show() void WS2812FX::show()

View File

@ -227,6 +227,7 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
void void
show(void), show(void),
setPixelColor(uint16_t i, byte r, byte g, byte b), setPixelColor(uint16_t i, byte r, byte g, byte b),
setPixelColor(uint16_t i, byte r, byte g, byte b, byte w),
init(void), init(void),
service(void), service(void),
start(void), start(void),
@ -299,7 +300,6 @@ class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
begin(void), begin(void),
clear(void), clear(void),
setPixelColor(uint16_t i, uint32_t c), setPixelColor(uint16_t i, uint32_t c),
setPixelColor(uint16_t i, byte r, byte g, byte b, byte w),
setPixelColorRaw(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), dofade(void),
strip_off(void), strip_off(void),

View File

@ -2,7 +2,7 @@
<html> <html>
<head><meta charset="utf-8"> <head><meta charset="utf-8">
<link rel='shortcut icon' type='image/x-icon' href='/favicon.ico'/> <link rel='shortcut icon' type='image/x-icon' href='/favicon.ico'/>
<title>WLED 0.6.2</title> <title>WLED 0.6.3</title>
<script> <script>
var d=document; var d=document;
var w=window.getComputedStyle(d.querySelector("html")); var w=window.getComputedStyle(d.querySelector("html"));
@ -75,7 +75,7 @@
} }
} }
} }
request.open("GET", "win/" +resp +nocache, true); request.open("GET", "win" +resp +nocache, true);
request.send(null); request.send(null);
resp=""; resp="";
} }
@ -214,8 +214,8 @@
function SwitchPS(x) function SwitchPS(x)
{ {
d.Cf.FF.value = parseInt(d.Cf.FF.value) +x; d.Cf.FF.value = parseInt(d.Cf.FF.value) +x;
if (d.Cf.FF.value < 0) d.Cf.FF.value = 0; if (d.Cf.FF.value < 1) d.Cf.FF.value = 1;
if (d.Cf.FF.value > 24) d.Cf.FF.value = 24; if (d.Cf.FF.value > 25) d.Cf.FF.value = 25;
} }
function PSIO(sv) function PSIO(sv)
{ {
@ -335,6 +335,21 @@
} }
GIO(); GIO();
} }
function uCY()
{
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()
{
resp+="&PL=0";GIO();
}
</script> </script>
<style> <style>
:root { :root {
@ -659,9 +674,10 @@
<svg id="psp" onclick="SwitchPS(-1)"><use xlink:href="#lnr-arrow-left-circle"></use></svg> <svg id="psp" onclick="SwitchPS(-1)"><use xlink:href="#lnr-arrow-left-circle"></use></svg>
<svg id="psn" onclick="SwitchPS(1)"><use xlink:href="#lnr-arrow-right-circle"></use></svg> <svg id="psn" onclick="SwitchPS(1)"><use xlink:href="#lnr-arrow-right-circle"></use></svg>
<svg id="pss" onclick="PSIO(true)"><use xlink:href="#lnr-arrow-down-circle"></use></svg> <svg id="pss" onclick="PSIO(true)"><use xlink:href="#lnr-arrow-down-circle"></use></svg>
<br><input id="psI" name = "FF" type="number" value="0" min="0" max="25" step="1"><br><br> <br><input id="psI" name = "FF" type="number" value="1" min="1" max="25" step="1"><br><br>
Click checkmark to apply <input type="checkbox" checked="true" name="BC"> brightness, <input type="checkbox" checked="true" name="CC"> color and <input type="checkbox" checked="true" name="FC"> effects.<br> Click checkmark to apply <input type="checkbox" checked="true" name="BC"> brightness, <input type="checkbox" checked="true" name="CC"> color and <input type="checkbox" checked="true" name="FC"> effects.<br><br>
Effect 0 is the configuration when the light is powered up. Cycle through presets <input id="cy1" name="P1" type="number" value="1" min="1" max="25" step="1"> to <input id="cy2" name="P2" type="number" value="5" min="1" max="25" step="1">, keep each for <input id="cyT" name="PT" type="number" value="1250" min="50" max="65501" step="1">ms: <input type="checkbox" name="CY" onclick="uCY()"><br><br>
<button type="button" onclick="R()">Apply boot config</button><br>
</div> </div>
<div id="tlN" class="tools"> <div id="tlN" class="tools">
Timed Light<br><br> Timed Light<br><br>

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -110,7 +110,7 @@ Brightness factor: <input name="BF" type="number" min="0" max="255" required> %
<h3>Transitions</h3> <h3>Transitions</h3>
Fade: <input type="checkbox" name="TF"><br> Fade: <input type="checkbox" name="TF"><br>
Sweep: <input type="checkbox" name="TS"> Invert direction: <input type="checkbox" name="TI"><br> Sweep: <input type="checkbox" name="TS"> Invert direction: <input type="checkbox" name="TI"><br>
Transition Delay: <input name="TD" maxlength="5" size="2"> ms Transition Time: <input name="TD" maxlength="5" size="2"> ms
<h3>Timed light</h3> <h3>Timed light</h3>
Default Duration: <input name="TL" type="number" min="1" max="255" required> min<br> Default Duration: <input name="TL" type="number" min="1" max="255" required> min<br>
Default Target brightness: <input name="TB" type="number" min="0" max="255" required><br> Default Target brightness: <input name="TB" type="number" min="0" max="255" required><br>
@ -336,7 +336,7 @@ HTTP traffic is unencrypted. An attacker in the same network can intercept form
<button type="button" onclick="U()">Manual OTA Update</button><br> <button type="button" onclick="U()">Manual OTA Update</button><br>
Enable ArduinoOTA: <input type="checkbox" name="AO"><br> Enable ArduinoOTA: <input type="checkbox" name="AO"><br>
<h3>About</h3> <h3>About</h3>
<a href="https://github.com/Aircoookie/WLED">WLED</a> version 0.6.2<br> <a href="https://github.com/Aircoookie/WLED">WLED</a> version 0.6.3<br>
(c) 2016-2018 Christian Schwinne <br> (c) 2016-2018 Christian Schwinne <br>
<i>Licensed under the MIT license</i><br><br> <i>Licensed under the MIT license</i><br><br>
<i>Uses libraries:</i><br> <i>Uses libraries:</i><br>

View File

@ -3,7 +3,7 @@
*/ */
/* /*
* @title WLED project sketch * @title WLED project sketch
* @version 0.6.2 * @version 0.6.3
* @author Christian Schwinne * @author Christian Schwinne
*/ */
@ -33,8 +33,8 @@
#include "WS2812FX.h" #include "WS2812FX.h"
//version in format yymmddb (b = daily build) //version in format yymmddb (b = daily build)
#define VERSION 1804011 #define VERSION 1804111
const String versionString = "0.6.2"; const String versionString = "0.6.3";
//AP and OTA default passwords (change them!) //AP and OTA default passwords (change them!)
String apPass = "wled1234"; String apPass = "wled1234";
@ -84,7 +84,7 @@ byte briS = 127;
byte nightlightTargetBri = 0; byte nightlightTargetBri = 0;
bool fadeTransition = true; bool fadeTransition = true;
bool sweepTransition = false, sweepDirection = true; bool sweepTransition = false, sweepDirection = true;
uint16_t transitionDelay = 1200; uint16_t transitionDelay = 1200, transitionDelayDefault = transitionDelay;
bool reverseMode = false; bool reverseMode = false;
bool otaLock = false, wifiLock = false; bool otaLock = false, wifiLock = false;
bool aOtaEnabled = true; bool aOtaEnabled = true;
@ -120,8 +120,6 @@ byte macroButton = 0, macroCountdown = 0, macroLongPress = 0;
unsigned long countdownTime = 1514764800L; unsigned long countdownTime = 1514764800L;
double transitionResolution = 0.011;
//hue //hue
bool huePollingEnabled = false, hueAttempt = false; bool huePollingEnabled = false, hueAttempt = false;
uint16_t huePollIntervalMs = 2500; uint16_t huePollIntervalMs = 2500;
@ -208,8 +206,15 @@ bool cronixieBacklight = true;
bool countdownMode = false; bool countdownMode = false;
bool cronixieInit = false; bool cronixieInit = false;
bool presetCyclingEnabled = false;
byte presetCycleMin = 1, presetCycleMax = 5;
uint16_t presetCycleTime = 1250;
unsigned long presetCycledTime = 0; byte presetCycCurr = presetCycleMin;
bool presetCycleBri, presetCycleCol, presetCycleFx;
uint32_t arlsTimeoutMillis = 2500; uint32_t arlsTimeoutMillis = 2500;
bool arlsTimeout = false; bool arlsTimeout = false;
bool receiveDirect = true;
unsigned long arlsTimeoutTime; unsigned long arlsTimeoutTime;
byte auxTime = 0; byte auxTime = 0;
unsigned long auxStartTime; unsigned long auxStartTime;
@ -314,6 +319,7 @@ void setup() {
void loop() { void loop() {
server.handleClient(); server.handleClient();
handleSerial();
handleNotifications(); handleNotifications();
handleTransitions(); handleTransitions();
userLoop(); userLoop();
@ -323,7 +329,7 @@ void loop() {
if (!otaLock && aOtaEnabled) ArduinoOTA.handle(); if (!otaLock && aOtaEnabled) ArduinoOTA.handle();
handleAlexa(); handleAlexa();
handleOverlays(); handleOverlays();
if (!arlsTimeout) //block stuff if WARLS is enabled if (!arlsTimeout) //block stuff if WARLS/Adalight is enabled
{ {
if (dnsActive) dnsServer.processNextRequest(); if (dnsActive) dnsServer.processNextRequest();
handleHue(); handleHue();

View File

@ -85,8 +85,8 @@ void saveSettingsToEEPROM()
EEPROM.write(250, receiveNotificationBrightness); EEPROM.write(250, receiveNotificationBrightness);
EEPROM.write(251, fadeTransition); EEPROM.write(251, fadeTransition);
EEPROM.write(252, reverseMode); EEPROM.write(252, reverseMode);
EEPROM.write(253, (transitionDelay >> 0) & 0xFF); EEPROM.write(253, (transitionDelayDefault >> 0) & 0xFF);
EEPROM.write(254, (transitionDelay >> 8) & 0xFF); EEPROM.write(254, (transitionDelayDefault >> 8) & 0xFF);
EEPROM.write(255, briMultiplier); EEPROM.write(255, briMultiplier);
//255,250,231,230,226 notifier bytes //255,250,231,230,226 notifier bytes
for (int i = 256; i < 288; ++i) for (int i = 256; i < 288; ++i)
@ -286,7 +286,8 @@ void loadSettingsFromEEPROM(bool first)
receiveNotificationBrightness = EEPROM.read(250); receiveNotificationBrightness = EEPROM.read(250);
fadeTransition = EEPROM.read(251); fadeTransition = EEPROM.read(251);
reverseMode = EEPROM.read(252); reverseMode = EEPROM.read(252);
transitionDelay = ((EEPROM.read(253) << 0) & 0xFF) + ((EEPROM.read(254) << 8) & 0xFF00); transitionDelayDefault = ((EEPROM.read(253) << 0) & 0xFF) + ((EEPROM.read(254) << 8) & 0xFF00);
transitionDelay = transitionDelayDefault;
briMultiplier = EEPROM.read(255); briMultiplier = EEPROM.read(255);
otaPass = ""; otaPass = "";
for (int i = 256; i < 288; ++i) for (int i = 256; i < 288; ++i)
@ -471,6 +472,7 @@ void applyPreset(byte index, bool loadBri, bool loadCol, bool loadFX)
} }
if (loadFX) if (loadFX)
{ {
byte lastfx = effectCurrent;
effectCurrent = EEPROM.read(i+10); effectCurrent = EEPROM.read(i+10);
effectSpeed = EEPROM.read(i+11); effectSpeed = EEPROM.read(i+11);
effectIntensity = EEPROM.read(i+16); effectIntensity = EEPROM.read(i+16);
@ -480,7 +482,7 @@ void applyPreset(byte index, bool loadBri, bool loadCol, bool loadFX)
ccFromStart = (EEPROM.read(i+14)<2); ccFromStart = (EEPROM.read(i+14)<2);
ccStep = EEPROM.read(i+15); ccStep = EEPROM.read(i+15);
strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd); strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd);
strip.setMode(effectCurrent); if (lastfx != effectCurrent) strip.setMode(effectCurrent);
strip.setSpeed(effectSpeed); strip.setSpeed(effectSpeed);
strip.setIntensity(effectIntensity); strip.setIntensity(effectIntensity);
} }

View File

@ -651,7 +651,7 @@ bool handleSet(String req)
bri = briT; bri = briT;
} else { } else {
nightlightActive = true; nightlightActive = true;
nightlightDelayMins = req.substring(pos + 3).toInt(); if (req.indexOf("&ND") <= 0) nightlightDelayMins = req.substring(pos + 3).toInt();
nightlightStartTime = millis(); nightlightStartTime = millis();
} }
} }
@ -679,6 +679,10 @@ bool handleSet(String req)
auxActive = true; auxActive = true;
if (auxTime == 0) auxActive = false; if (auxTime == 0) auxActive = false;
} }
pos = req.indexOf("TT=");
if (pos > 0) {
transitionDelay = req.substring(pos + 3).toInt();
}
//main toggle on/off //main toggle on/off
pos = req.indexOf("&T="); pos = req.indexOf("&T=");
if (pos > 0) { if (pos > 0) {
@ -721,6 +725,47 @@ bool handleSet(String req)
if (_cc_updated) strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd); if (_cc_updated) strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd);
//set presets //set presets
if (req.indexOf("CY=") > 0) //preset cycle
{
presetCyclingEnabled = true;
if (req.indexOf("CY=0") > 0)
{
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;
}
}
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();
pos = req.indexOf("PS="); //saves current in preset pos = req.indexOf("PS="); //saves current in preset
if (pos > 0) { if (pos > 0) {
savePreset(req.substring(pos + 3).toInt()); savePreset(req.substring(pos + 3).toInt());

View File

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

View File

@ -8,6 +8,7 @@ void wledInit()
if (!EEPROM.read(397)) strip.init(); //quick init if (!EEPROM.read(397)) strip.init(); //quick init
Serial.begin(115200); Serial.begin(115200);
Serial.setTimeout(50);
#ifdef USEFS #ifdef USEFS
SPIFFS.begin(); SPIFFS.begin();
@ -16,7 +17,7 @@ void wledInit()
DEBUG_PRINTLN("Load EEPROM"); DEBUG_PRINTLN("Load EEPROM");
loadSettingsFromEEPROM(true); loadSettingsFromEEPROM(true);
if (!initLedsLast) initStrip(); if (!initLedsLast) initStrip();
DEBUG_PRINT("C-SSID: "); DEBUG_PRINT("CSSID: ");
DEBUG_PRINT(clientSSID); DEBUG_PRINT(clientSSID);
buildCssColorString(); buildCssColorString();
userBeginPreConnection(); userBeginPreConnection();
@ -55,28 +56,8 @@ void wledInit()
dnsServer.start(53, "*", WiFi.softAPIP()); dnsServer.start(53, "*", WiFi.softAPIP());
dnsActive = true; dnsActive = true;
} }
if (!initLedsLast) strip.service();
//SERVER INIT //SERVER INIT
//seasonal greetings
server.on("/easter", HTTP_GET, [](){
if (currentTheme == 12)
{
effectCurrent = 6;
strip.setMode(effectCurrent);
effectSpeed = 200;
strip.setSpeed(effectSpeed);
uint8_t chance = random(255);
if (chance > 250) {serveMessage(200, "&#x1F423;&#x1F423;&#x1F423;&#x1F423;&#x1F423;", "You are super special! Here are 5 chicks for you!", 254);}
else if (chance > 230) {serveMessage(200, "&#x1F423;&#x1F423;&#x1F423;&#x1F423;", "You are genuinely special! Here are 4 chicks for you!", 254);}
else if (chance > 200) {serveMessage(200, "&#x1F423;&#x1F423;&#x1F423;", "You are very special! Here are 3 chicks for you!", 254);}
else if (chance > 140) {serveMessage(200, "&#x1F423;&#x1F423;", "You are quite special! Here are 2 chicks for you!", 254);}
else if (chance > 1) {serveMessage(200, "&#x1F423;", "Happy Easter to you! Here's your personal chick!", 254);}
else {serveMessage(200, "&#x1F430;My basket is empty!&#x1F430;", "So sorry you always have bad luck... Why not try again?", 254);}
} else
{
serveMessage(200, "&#x1F608;April Fools!&#x1F608;", "You could try to <a href=\"/settings/ui\">decorate</a> for Easter first!", 254);
}
});
//settings page //settings page
server.on("/settings", HTTP_GET, [](){ server.on("/settings", HTTP_GET, [](){
serveSettings(0); serveSettings(0);
@ -184,6 +165,10 @@ void wledInit()
server.on("/freeheap", HTTP_GET, [](){ server.on("/freeheap", HTTP_GET, [](){
server.send(200, "text/plain", (String)ESP.getFreeHeap()); 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, [](){ 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());
@ -196,38 +181,7 @@ void wledInit()
}); });
server.on("/build", HTTP_GET, [](){ server.on("/build", HTTP_GET, [](){
String info = "hard-coded build info:\r\n\n"; server.send(200, "text/plain", getBuildInfo());
#ifdef ARDUINO_ARCH_ESP32
info += "platform: esp32\r\n";
#else
info += "platform: esp8266\r\n";
#endif
info += "version: " + versionString + "\r\n";
info += "build: " + (String)VERSION + "\r\n";
info += "eepver: " + String(EEPVER) + "\r\n";
#ifdef RGBW
info += "rgbw: true\r\n";
#else
info += "rgbw: false\r\n";
#endif
info += "max-leds: " + (String)LEDCOUNT + "\r\n";
#ifdef USEFS
info += "spiffs: true\r\n";
#else
info += "spiffs: false\r\n";
#endif
#ifdef DEBUG
info += "debug: true\r\n";
#else
info += "debug: false\r\n";
#endif
info += "button-pin: gpio" + String(buttonPin) + "\r\n";
#ifdef ARDUINO_ARCH_ESP32
info += "strip-pin: gpio" + String(PIN) + "\r\n";
#else
info += "strip-pin: gpio2\r\n";
#endif
server.send(200, "text/plain", info);
}); });
//if OTA is allowed //if OTA is allowed
if (!otaLock){ if (!otaLock){
@ -272,6 +226,7 @@ void wledInit()
server.send(404, "text/plain", "Not Found"); server.send(404, "text/plain", "Not Found");
} }
}); });
if (!initLedsLast) strip.service();
//init Alexa hue emulation //init Alexa hue emulation
if (alexaEnabled) alexaInit(); if (alexaEnabled) alexaInit();
@ -295,6 +250,7 @@ void wledInit()
if (initLedsLast) initStrip(); if (initLedsLast) initStrip();
userBegin(); userBegin();
if (macroBoot>0) applyMacro(macroBoot); if (macroBoot>0) applyMacro(macroBoot);
Serial.println("Ada");
} }
void initStrip() void initStrip()
@ -527,6 +483,42 @@ void serveSettings(byte subPage)
} }
} }
String getBuildInfo()
{
String info = "hard-coded build info:\r\n\n";
#ifdef ARDUINO_ARCH_ESP32
info += "platform: esp32\r\n";
#else
info += "platform: esp8266\r\n";
#endif
info += "version: " + versionString + "\r\n";
info += "build: " + (String)VERSION + "\r\n";
info += "eepver: " + String(EEPVER) + "\r\n";
#ifdef RGBW
info += "rgbw: true\r\n";
#else
info += "rgbw: false\r\n";
#endif
info += "max-leds: " + (String)LEDCOUNT + "\r\n";
#ifdef USEFS
info += "spiffs: true\r\n";
#else
info += "spiffs: false\r\n";
#endif
#ifdef DEBUG
info += "debug: true\r\n";
#else
info += "debug: false\r\n";
#endif
info += "button-pin: gpio" + String(buttonPin) + "\r\n";
#ifdef ARDUINO_ARCH_ESP32
info += "strip-pin: gpio" + String(PIN) + "\r\n";
#else
info += "strip-pin: gpio2\r\n";
#endif
info += "build-type: src\r\n";
return info;
}

View File

@ -9,11 +9,13 @@ void notify(byte callMode, bool followUp=false)
if (!udpConnected) return; if (!udpConnected) return;
switch (callMode) switch (callMode)
{ {
case 0: return;
case 1: if (!notifyDirect) return; break; case 1: if (!notifyDirect) return; break;
case 2: if (!notifyButton) return; break; case 2: if (!notifyButton) return; break;
case 4: if (!notifyDirect) return; break; case 4: if (!notifyDirect) return; break;
case 6: if (!notifyDirect) return; break; //fx change case 6: if (!notifyDirect) return; break; //fx change
case 7: if (!notifyHue) return; break; case 7: if (!notifyHue) return; break;
case 8: if (!notifyDirect) return; break;
default: return; default: return;
} }
byte udpOut[WLEDPACKETSIZE]; byte udpOut[WLEDPACKETSIZE];
@ -54,14 +56,14 @@ void handleNotifications()
notify(notificationSentCallMode,true); notify(notificationSentCallMode,true);
} }
if(udpConnected && receiveNotifications){ if(udpConnected && (receiveNotifications || receiveDirect)){
uint16_t packetSize = notifierUdp.parsePacket(); uint16_t packetSize = notifierUdp.parsePacket();
if (packetSize > 1026) return; if (packetSize > 1026) return;
if(packetSize && notifierUdp.remoteIP() != WiFi.localIP()) //don't process broadcasts we send ourselves if(packetSize && notifierUdp.remoteIP() != WiFi.localIP()) //don't process broadcasts we send ourselves
{ {
byte udpIn[packetSize]; byte udpIn[packetSize];
notifierUdp.read(udpIn, packetSize); notifierUdp.read(udpIn, packetSize);
if (udpIn[0] == 0 && !arlsTimeout) //wled notifier, block if realtime packets active if (udpIn[0] == 0 && !arlsTimeout && receiveNotifications) //wled notifier, block if realtime packets active
{ {
if (receiveNotificationColor) if (receiveNotificationColor)
{ {
@ -105,7 +107,7 @@ void handleNotifications()
if (receiveNotificationBrightness) bri = udpIn[2]; if (receiveNotificationBrightness) bri = udpIn[2];
colorUpdated(3); colorUpdated(3);
} }
} else if (udpIn[0] == 1) //warls } else if (udpIn[0] > 0 && udpIn[0] < 4) //1 warls //2 drgb //3 drgbw
{ {
if (packetSize > 1) { if (packetSize > 1) {
if (udpIn[1] == 0) if (udpIn[1] == 0)
@ -119,26 +121,56 @@ void handleNotifications()
arlsTimeout = true; arlsTimeout = true;
arlsTimeoutTime = millis() + 1000*udpIn[1]; arlsTimeoutTime = millis() + 1000*udpIn[1];
} }
for (int i = 2; i < packetSize -3; i += 4) if (udpIn[0] == 1) //warls
{ {
if (udpIn[i] + arlsOffset < ledCount && udpIn[i] + arlsOffset >= 0) for (int i = 2; i < packetSize -3; i += 4)
if (useGammaCorrectionRGB)
{ {
strip.setPixelColor(udpIn[i] + arlsOffset, gamma8[udpIn[i+1]], gamma8[udpIn[i+2]], gamma8[udpIn[i+3]]); if (udpIn[i] + arlsOffset < ledCount && udpIn[i] + arlsOffset >= 0)
} else { if (useGammaCorrectionRGB)
strip.setPixelColor(udpIn[i] + arlsOffset, udpIn[i+1], udpIn[i+2], udpIn[i+3]); {
strip.setPixelColor(udpIn[i] + arlsOffset, gamma8[udpIn[i+1]], gamma8[udpIn[i+2]], gamma8[udpIn[i+3]]);
} else {
strip.setPixelColor(udpIn[i] + arlsOffset, udpIn[i+1], udpIn[i+2], udpIn[i+3]);
}
}
} else if (udpIn[0] == 2 && receiveDirect) //drgb
{
int id = 0;
for (int i = 2; i < packetSize -2; i += 3)
{
if (useGammaCorrectionRGB)
{
strip.setPixelColor(id, gamma8[udpIn[i]], gamma8[udpIn[i+1]], gamma8[udpIn[i+2]]);
} else {
strip.setPixelColor(id, udpIn[i+0], udpIn[i+1], udpIn[i+2]);
}
id++; if (id >= ledCount) break;
}
} else if (udpIn[0] == 3 && receiveDirect) //drgbw
{
int id = 0;
for (int i = 2; i < packetSize -3; i += 4)
{
if (useGammaCorrectionRGB)
{
strip.setPixelColor(id, gamma8[udpIn[i]], gamma8[udpIn[i+1]], gamma8[udpIn[i+2]], gamma8[udpIn[i+3]]);
} else {
strip.setPixelColor(id, udpIn[i+0], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
}
id++; if (id >= ledCount) break;
} }
} }
strip.show(); strip.show();
} }
} }
} }
if (arlsTimeout && millis() > arlsTimeoutTime) }
{ if (arlsTimeout && millis() > arlsTimeoutTime)
strip.unlockAll(); {
arlsTimeout = false; strip.unlockAll();
strip.setMode(effectCurrent); if (bri == 0) strip.setBrightness(0);
} arlsTimeout = false;
strip.setMode(effectCurrent);
} }
} }

View File

@ -51,7 +51,7 @@ bool colorChanged()
void colorUpdated(int callMode) void colorUpdated(int callMode)
{ {
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (NN)6: fx changed 7: hue //call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (NN)6: fx changed 7: hue 8: preset cycle
if (!colorChanged()) if (!colorChanged())
{ {
if (callMode == 6) notify(6); if (callMode == 6) notify(6);
@ -78,6 +78,7 @@ void colorUpdated(int callMode)
{ {
//set correct delay if not using notification delay //set correct delay if not using notification delay
if (callMode != 3) transitionDelayTemp = transitionDelay; if (callMode != 3) transitionDelayTemp = transitionDelay;
if (transitionDelayTemp == 0) {setLedsStandard();strip.trigger();return;}
if (transitionActive) if (transitionActive)
{ {
@ -112,7 +113,7 @@ void handleTransitions()
strip.setFastUpdateMode(false); strip.setFastUpdateMode(false);
return; return;
} }
if (tper - tperLast < transitionResolution) if (tper - tperLast < 0.004)
{ {
return; return;
} }
@ -176,4 +177,14 @@ void handleNightlight()
{ {
nightlightActiveOld = false; nightlightActiveOld = false;
} }
//also handle preset cycle here
if (presetCyclingEnabled && (millis() - presetCycledTime > presetCycleTime))
{
applyPreset(presetCycCurr,presetCycleBri,presetCycleCol,presetCycleFx);
presetCycCurr++; if (presetCycCurr > presetCycleMax) presetCycCurr = presetCycleMin;
if (presetCycCurr > 25) presetCycCurr = 1;
colorUpdated(8);
presetCycledTime = millis();
}
} }

View File

@ -109,7 +109,7 @@ bool checkNTPResponse()
unsigned long secsSince1900 = highWord << 16 | lowWord; unsigned long secsSince1900 = highWord << 16 | lowWord;
DEBUG_PRINT("Unix time = "); DEBUG_PRINT("Unix time = ");
unsigned long epoch = secsSince1900 - 2208988800UL; //subtract 70 years unsigned long epoch = secsSince1900 - 2208988799UL; //subtract 70 years -1sec (on avg. more precision)
setTime(epoch); setTime(epoch);
DEBUG_PRINTLN(epoch); DEBUG_PRINTLN(epoch);
if (countdownTime - now() > 0) countdownOverTriggered = false; if (countdownTime - now() > 0) countdownOverTriggered = false;