NTP added

added more settings
updated readme
improved boot time
This commit is contained in:
cschwinne 2016-12-29 00:03:58 +01:00
parent bce00eea0c
commit 19d8bbc0c3
10 changed files with 267 additions and 55 deletions

View File

@ -1,6 +1,3 @@
color cycle
other vfx (fire...)
sequence
simple slide transition
additional color picker field
implement HSB slider option
@ -14,6 +11,8 @@ use iframe for all adv. features?
/dumpeeprom and /pusheeprom (ota lock!)
aux trigger pin
randomizer
ir, touch, pin input
Automations
clock functions:
analog clock on range (dots)

View File

@ -1,8 +1,18 @@
WLED is a basic, fast and (relatively) (ok, VERY relatively) secure implementation of a ESP8266 webserver to control Neopixel (WS2812B) leds
Features:
Uses ESP8266 Arduino libraries from 15th August 2016! Untested with newer version!
Contents in the /data directory need to be uploaded to SPIFFS.
Features: (V0.2)
- RGB and brightness sliders
- Settings page - configuration over network
- Access Point and station mode - automatic failsafe AP
- Edit page. Change html and other files via OTA. Support for ArduinoOTA.
- Edit page. Change html and other files via OTA.
Additions for V0.3 (nearly complete!)
- WS2812FX library integrated for nearly 50 special effects!
- Nightlight function (gradually dims down)
- Notifier function (multiple ESPs sync color via UDP broadcast)
- Support for power pushbutton
- Full OTA software update capability
- Password protected OTA page for added security (OTA lock)

View File

@ -1171,7 +1171,7 @@ void WS2812FX::mode_fire_flicker_soft(void) {
void WS2812FX::mode_fire_flicker_int(int rev_intensity)
{
byte p_r = (_color & 0x00FF0000) >> 16;
byte p_r = (_color & 0x00FF0000) >> 16;
byte p_g = (_color & 0x0000FF00) >> 8;
byte p_b = (_color & 0x000000FF) >> 0;
byte flicker_val = max(p_r,max(p_g, p_b))/rev_intensity;

View File

@ -32,6 +32,12 @@
document.S_form.APPASS.value = this.responseXML.getElementsByTagName('appass')[0].innerHTML; //fake pass like ******
document.S_form.APCHAN.value = this.responseXML.getElementsByTagName('apchan')[0].innerHTML;
document.S_form.DESC.value = this.responseXML.getElementsByTagName('desc')[0].innerHTML;
document.S_form.CLDFR.value = this.responseXML.getElementsByTagName('cldef')[0].innerHTML;
document.S_form.CLDFG.value = this.responseXML.getElementsByTagName('cldef')[1].innerHTML;
document.S_form.CLDFB.value = this.responseXML.getElementsByTagName('cldef')[2].innerHTML;
document.S_form.CLDFA.value = this.responseXML.getElementsByTagName('cldfa')[0].innerHTML;
document.S_form.FXDEF.value = this.responseXML.getElementsByTagName('fxdef')[0].innerHTML;
document.S_form.SXDEF.value = this.responseXML.getElementsByTagName('sxdef')[0].innerHTML;
document.S_form.BTNON.checked = (this.responseXML.getElementsByTagName('btnon')[0].innerHTML)!=0?true:false;
document.S_form.TFADE.checked = (this.responseXML.getElementsByTagName('tfade')[0].innerHTML)!=0?true:false;
document.S_form.TDLAY.value = this.responseXML.getElementsByTagName('tdlay')[0].innerHTML;
@ -44,6 +50,8 @@
document.S_form.NSDIR.checked = (this.responseXML.getElementsByTagName('nsdir')[0].innerHTML)!=0?true:false;
document.S_form.NSBTN.checked = (this.responseXML.getElementsByTagName('nsbtn')[0].innerHTML)!=0?true:false;
document.S_form.NSFWD.checked = (this.responseXML.getElementsByTagName('nsfwd')[0].innerHTML)!=0?true:false;
document.S_form.NTPON.checked = (this.responseXML.getElementsByTagName('ntpon')[0].innerHTML)!=0?true:false;
document.getElementsByClassName("times")[0].innerHTML = this.responseXML.getElementsByTagName('times')[0].innerHTML;
document.S_form.NOOTA.checked = (this.responseXML.getElementsByTagName('noota')[0].innerHTML)!=0?true:false;
document.S_form.NORAP.checked = (this.responseXML.getElementsByTagName('norap')[0].innerHTML)!=0?true:false;
document.getElementsByClassName("sip")[0].innerHTML = this.responseXML.getElementsByTagName('sip')[0].innerHTML;
@ -75,54 +83,64 @@
<input type="button" name="BACK" value="Back" onclick="OpenMain()">
<h2>WiFi setup</h2>
<h3>Connect to existing network</h3>
Network SSID (leave empty to not connect): <br> <input type="text" name="CSSID" maxlength="32"> <br>
Network SSID (leave 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 type="text" name="CSIP0" maxlength="3" size="2"> .
<input type="text" name="CSIP1" maxlength="3" size="2"> .
<input type="text" name="CSIP2" maxlength="3" size="2"> .
<input type="text" name="CSIP3" maxlength="3" size="2"> <br>
<input name="CSIP0" maxlength="3" size="2"> .
<input name="CSIP1" maxlength="3" size="2"> .
<input name="CSIP2" maxlength="3" size="2"> .
<input name="CSIP3" maxlength="3" size="2"> <br>
Static gateway: <br>
<input type="text" name="CSGW0" maxlength="3" size="2"> .
<input type="text" name="CSGW1" maxlength="3" size="2"> .
<input type="text" name="CSGW2" maxlength="3" size="2"> .
<input type="text" name="CSGW3" maxlength="3" size="2"> <br>
<input name="CSGW0" maxlength="3" size="2"> .
<input name="CSGW1" maxlength="3" size="2"> .
<input name="CSGW2" maxlength="3" size="2"> .
<input name="CSGW3" maxlength="3" size="2"> <br>
Static subnet mask: <br>
<input type="text" name="CSSN0" maxlength="3" size="2"> .
<input type="text" name="CSSN1" maxlength="3" size="2"> .
<input type="text" name="CSSN2" maxlength="3" size="2"> .
<input type="text" name="CSSN3" maxlength="3" size="2"> <br>
<input name="CSSN0" maxlength="3" size="2"> .
<input name="CSSN1" maxlength="3" size="2"> .
<input name="CSSN2" maxlength="3" size="2"> .
<input name="CSSN3" maxlength="3" size="2"> <br>
mDNS address (leave empty for no mDNS): <br/>
http:// <input type="text" name="CMDNS" maxlength="32"> .local <br>
http:// <input name="CMDNS" maxlength="32"> .local <br>
Client IP: <span class="sip"> Not connected </span> <br>
<h3>Configure Access Point</h3>
AP SSID (leave empty for no AP): <br> <input type="text" name="APSSID" maxlength="32"> <br>
AP SSID (leave empty for no AP): <br> <input name="APSSID" maxlength="32"> <br>
Hide AP SSID: <input type="checkbox" name="APHSSID" value="0"> <br>
AP password (leave empty for open): <br> <input type="password" name="APPASS" maxlength="63"> <br>
AP channel: <input type="text" name="APCHAN" maxlength="2" size="2"> <br>
AP channel: <input name="APCHAN" maxlength="2" size="2"> <br>
AP IP: <span class="sip"> Not active </span> <br>
<h2>Application setup</h2>
<h3>Web setup</h3>
Server description: <input type="text" name="DESC" maxlength="32"> <br>
Server description: <input name="DESC" maxlength="32"> <br>
<h3>LED setup</h3>
The default boot LED color is the current color when settings are saved. <br>
Brightness factor: <input type="text" name="NRBRI" maxlength="3" size="2"> % <br>
Default RGB color:
<input name="CLDFR" maxlength="3" size="2">
<input name="CLDFG" maxlength="3" size="2">
<input name="CLDFB" maxlength="3" size="2"> <br>
Default brightness: <input name="CLDFA" maxlength="3" size="2"> (0-255) <br>
Default effect ID: <input name="FXDEF" maxlength="3" size="2"> <br>
Default effect speed: <input name="SXDEF" maxlength="3" size="2"> <br>
Ignore and use current color, brightness and effects: <input type="checkbox" name="CBEOR" value="0"> <br>
Brightness factor: <input name="NRBRI" maxlength="3" size="2"> % <br>
<h3>Button setup</h3>
On/Off button enabled: <input type="checkbox" name="BTNON" value="0"> <br>
<h3>Transitions</h3>
Fade: <input type="checkbox" name="TFADE" value="0"> <br>
Transition Delay: <input type="text" name="TDLAY" maxlength="5" size="2"> ms <br>
Transition Delay: <input name="TDLAY" maxlength="5" size="2"> ms <br>
<h3>Timed light</h3>
Target brightness: <input type="text" name="TLBRI" maxlength="3" size="2"> (0-255) <br>
Change after: <input type="text" name="TLDUR" maxlength="3" size="2"> min <br>
Target brightness: <input name="TLBRI" maxlength="3" size="2"> (0-255) <br>
Change after: <input name="TLDUR" maxlength="3" size="2"> min <br>
Fade: <input type="checkbox" name="TLFDE" value="0"> <br>
<h3>Daisy chain</h3>
UDP Port: <input type="text" name="NUDPP" maxlength="5" size="2"><br>
UDP Port: <input name="NUDPP" maxlength="5" size="2"><br>
Receive notifications: <input type="checkbox" name="NRCVE" value="0"> <br>
Send notifications on direct change: <input type="checkbox" name="NSDIR" value="0"> <br>
Send notifications on button press: <input type="checkbox" name="NSBTN" value="0"> <br>
Send nightlight notifications: <input type="checkbox" name="NSFWD" value="0"> <br>
<h3>Time</h3>
Get time from NTP server: <input type="checkbox" name="NTPON" value="0"> <br>
Current local time is <span class="times">unknown</span> <br>
<h3>Security</h3>
OTA locked: <input type="checkbox" name="NOOTA" value="0"> <br>
Passphrase: <input type="password" name="OPASS" maxlength="32"> <br>

View File

@ -8,6 +8,9 @@
#include "WS2812FX.h"
#include <FS.h>
#include <WiFiUDP.h>
#include <Time.h>
#include <TimeLib.h>
#include <Timezone.h>
/*
* @title WLED project sketch
@ -15,8 +18,15 @@
* @author Christian Schwinne
*/
//Hardware-settings (only changeble via code)
uint8_t led_amount = 84;
uint8_t led_amount = 9;
uint8_t buttonPin = 0; //needs pull-up
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 CE(CEST, CET);
TimeChangeRule *tcr; //pointer to the time change rule, use to get the TZ abbrev
time_t local;
//Default CONFIG
String serverDescription = "WLED 0.3pd";
String clientssid = "Your_Network_Here";
@ -30,7 +40,8 @@ boolean useap = true;
IPAddress staticip(0, 0, 0, 0);
IPAddress staticgateway(0, 0, 0, 0);
IPAddress staticsubnet(255, 255, 255, 0);
byte col[]{255, 127, 0};
byte col_s[]{255, 127, 0};
byte bri_s = 127;
uint8_t bri_nl = 0;
boolean fadeTransition = true;
boolean seqTransition = false;
@ -45,19 +56,24 @@ uint8_t bri_n = 100;
uint8_t nightlightDelayMins = 60;
boolean nightlightFade = true;
uint16_t udpPort = 21324;
uint8_t effectCurrent = 0;
uint8_t effectSpeed = 75;
uint8_t effectDefault = 0;
uint8_t effectSpeedDefault = 75;
boolean ntpEnabled = true;
const char* ntpServerName = "time.nist.gov";
long ntpRetryMs = 20000;
long ntpResyncMs = 72000000;
double transitionResolution = 0.011;
//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};
long transitionStartTime;
long nightlightStartTime;
float tper_last = 0;
byte bri = 127;
byte bri = 0;
byte bri_old = 0;
byte bri_t = 0;
byte bri_it = 0;
@ -68,12 +84,21 @@ boolean nightlightActive = false;
boolean nightlightActive_old = false;
int transitionDelay_old;
int nightlightDelayMs;
uint8_t effectCurrent = 0;
uint8_t effectSpeed = 75;
boolean udpConnected = false;
byte udpIn[16];
IPAddress ntpIp;
byte ntpBuffer[48];
boolean ntpConnected = false;
boolean ntpSyncNeeded = true;
boolean ntpPacketSent = false;
long ntpPacketSentTime, ntpSyncTime;
ESP8266WebServer server(80);
ESP8266HTTPUpdateServer httpUpdater;
WiFiUDP notifierUdp;
WiFiUDP ntpUdp;
WS2812FX strip = WS2812FX(led_amount, 2, NEO_GRB + NEO_KHZ800);
@ -111,6 +136,7 @@ void loop() {
handleTransitions();
handleNightlight();
handleButton();
handleNetworkTime();
strip.service();
}

View File

@ -56,10 +56,10 @@ void saveSettingsToEEPROM()
EEPROM.write(243, staticsubnet[1]);
EEPROM.write(244, staticsubnet[2]);
EEPROM.write(245, staticsubnet[3]);
EEPROM.write(246, col[0]);
EEPROM.write(247, col[1]);
EEPROM.write(248, col[2]);
EEPROM.write(249, bri);
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(250, receiveNotificationsDefault);
EEPROM.write(251, fadeTransition);
EEPROM.write(253, (transitionDelay >> 0) & 0xFF);
@ -78,6 +78,12 @@ void saveSettingsToEEPROM()
{
EEPROM.write(i, serverDescription.charAt(i-292));
}
EEPROM.write(324, effectDefault);
EEPROM.write(325, effectSpeedDefault);
//326 reserved for effectIntensity
EEPROM.write(327, ntpEnabled);
//328 reserved for timezone setting
//329 reserved for dst setting
EEPROM.commit();
}
@ -141,10 +147,10 @@ void loadSettingsFromEEPROM()
staticsubnet[1] = EEPROM.read(243);
staticsubnet[2] = EEPROM.read(244);
staticsubnet[3] = EEPROM.read(245);
col[0] = EEPROM.read(246);
col[1] = EEPROM.read(247);
col[2] = EEPROM.read(248);
bri = EEPROM.read(249);
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;
receiveNotifications = EEPROM.read(250);
receiveNotificationsDefault = receiveNotifications;
fadeTransition = EEPROM.read(251);
@ -166,4 +172,7 @@ void loadSettingsFromEEPROM()
if (EEPROM.read(i) == 0) break;
serverDescription += char(EEPROM.read(i));
}
effectDefault = EEPROM.read(324); effectCurrent = effectDefault;
effectSpeedDefault = EEPROM.read(325); effectSpeed = effectSpeedDefault;
ntpEnabled = EEPROM.read(327);
}

View File

@ -31,9 +31,9 @@ void XML_response()
resp = resp + "<fx>";
resp = resp + effectCurrent;
resp = resp + "</fx>";
resp = resp + "<fx>";
resp = resp + "<sx>";
resp = resp + effectSpeed;
resp = resp + "</fx>";
resp = resp + "</sx>";
resp = resp + "<desc>";
resp = resp + serverDescription;
resp = resp + "</desc>";
@ -94,8 +94,23 @@ void XML_response_settings()
resp = resp + apchannel;
resp = resp + "</apchan>";
resp = resp + "<desc>";
resp = resp + serverDescription;
resp = resp + "</desc>";
resp = resp + serverDescription;
resp = resp + "</desc>";
for (int i = 0; i < 3; i++)
{
resp = resp + "<cldef>";
resp = resp + col_s[i];
resp = resp + "</cldef>";
}
resp = resp + "<cldfa>";
resp = resp + bri_s;
resp = resp + "</cldfa>";
resp = resp + "<fxdef>";
resp = resp + effectDefault;
resp = resp + "</fxdef>";
resp = resp + "<sxdef>";
resp = resp + effectSpeedDefault;
resp = resp + "</sxdef>";
resp = resp + "<btnon>";
resp = resp + bool2int(buttonEnabled);
resp = resp + "</btnon><tfade>";
@ -126,6 +141,14 @@ void XML_response_settings()
resp = resp + "</nsbtn><nsfwd>";
resp = resp + bool2int(notifyNightlight);
resp = resp + "</nsfwd>";
resp = resp + "<ntpon>";
resp = resp + bool2int(ntpEnabled);
resp = resp + "</ntpon>";
Serial.println("pretime");
resp = resp + "<times>";
resp = resp + getTimeString();
resp = resp + "</times>";
Serial.println("posttime");
resp = resp + "<noota>";
resp = resp + bool2int(ota_lock);
resp = resp +"</noota>";

View File

@ -94,6 +94,46 @@ void handleSettingsSet()
if (i >= 0 && i <= 255) staticsubnet[3] = i;
}
if (server.hasArg("DESC")) serverDescription = server.arg("DESC");
if (server.hasArg("CBEOR"))
{
col_s[0] = col[0];
col_s[1] = col[1];
col_s[2] = col[2];
bri_s = bri;
effectDefault = effectCurrent;
effectSpeedDefault = effectSpeed;
} else {
if (server.hasArg("CLDFR"))
{
int i = server.arg("CLDFR").toInt();
if (i >= 0 && i <= 255) col_s[0] = i;
}
if (server.hasArg("CLDFG"))
{
int i = server.arg("CLDFG").toInt();
if (i >= 0 && i <= 255) col_s[1] = i;
}
if (server.hasArg("CLDFB"))
{
int i = server.arg("CLDFB").toInt();
if (i >= 0 && i <= 255) col_s[2] = i;
}
if (server.hasArg("CLDFA"))
{
int i = server.arg("CLDFA").toInt();
if (i >= 0 && i <= 255) bri_s = i;
}
if (server.hasArg("FXDEF"))
{
int i = server.arg("FXDEF").toInt();
if (i >= 0 && i <= 255) effectDefault = i;
}
if (server.hasArg("SXDEF"))
{
int i = server.arg("SXDEF").toInt();
if (i >= 0 && i <= 255) effectSpeedDefault = i;
}
}
buttonEnabled = server.hasArg("BTNON");
fadeTransition = server.hasArg("TFADE");
if (server.hasArg("TDLAY"))
@ -128,6 +168,7 @@ void handleSettingsSet()
notifyDirect = server.hasArg("NSDIR");
notifyButton = server.hasArg("NSBTN");
notifyNightlight = server.hasArg("NSFWD");
ntpEnabled = server.hasArg("NTPON");
if (server.hasArg("OPASS"))
{
if (!ota_lock)

View File

@ -1,13 +1,6 @@
void wledInit()
{
Serial.begin(115200);
Serial.println();
for(uint8_t t = 4; t > 0; t--) {
Serial.printf("[SETUP] BOOT WAIT %d...\n", t);
Serial.flush();
delay(1000);
}
SPIFFS.begin();
{
@ -59,10 +52,14 @@ void wledInit()
}
Serial.println("mDNS responder started");
if (udpPort > 0)
if (udpPort > 0 && udpPort != 123)
{
udpConnected = notifierUdp.begin(udpPort);
}
if (ntpEnabled && !only_ap)
{
ntpConnected = ntpUdp.begin(123);
}
//SERVER INIT
//settings page
@ -132,7 +129,7 @@ void wledInit()
MDNS.addService("http", "tcp", 80);
// Initialize NeoPixel Strip
strip.init();
strip.setMode(0);
strip.setMode(effectCurrent);
strip.setColor(0);
strip.setSpeed(effectSpeed);
strip.setBrightness(255);

89
wled00/wled10_ntp.ino Normal file
View File

@ -0,0 +1,89 @@
void handleNetworkTime()
{
if (ntpEnabled && ntpConnected)
{
if (ntpSyncNeeded)
{
if (ntpPacketSent)
{
if (getNtpTime())
{
ntpSyncNeeded = false;
ntpPacketSent = false;
ntpSyncTime = millis();
Serial.print("Time: ");
Serial.println(now());
} else
{
if (millis() - ntpPacketSentTime > ntpRetryMs)
{
ntpPacketSent = false; //try new packet
}
}
} else
{
WiFi.hostByName(ntpServerName, ntpIp);
sendNTPpacket();
ntpPacketSent = true;
ntpPacketSentTime = millis();
}
} else if (millis() - ntpSyncTime > ntpResyncMs)
{
ntpSyncNeeded = true;
}
}
}
bool getNtpTime()
{
int size = ntpUdp.parsePacket();
if (size >= 48) {
ntpUdp.read(ntpBuffer, 48); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)ntpBuffer[40] << 24;
secsSince1900 |= (unsigned long)ntpBuffer[41] << 16;
secsSince1900 |= (unsigned long)ntpBuffer[42] << 8;
secsSince1900 |= (unsigned long)ntpBuffer[43];
setTime(secsSince1900 - 2208988800UL + (millis() - ntpPacketSentTime)/2000); //naive approach to improve accuracy, utc
return true;
}
return false; //unable to get the time
}
void sendNTPpacket()
{
Serial.println("Sending NTP packet");
memset(ntpBuffer, 0, 48);
ntpBuffer[0] = 0b11100011; // LI, Version, Mode
ntpBuffer[1] = 0; // Stratum, or type of clock
ntpBuffer[2] = 6; // Polling Interval
ntpBuffer[3] = 0xEC; // Peer Clock Precision
ntpBuffer[12] = 49;
ntpBuffer[13] = 0x4E;
ntpBuffer[14] = 49;
ntpBuffer[15] = 52;
ntpUdp.beginPacket(ntpIp, 123); //NTP requests are to port 123
ntpUdp.write(ntpBuffer, 48);
ntpUdp.endPacket();
}
String getTimeString()
{
local = CE.toLocal(now(), &tcr);
String ret = monthStr(month(local));
ret = ret + " ";
ret = ret + day(local);
ret = ret + " ";
ret = ret + year(local);
ret = ret + ", ";
ret = ret + 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);
return ret;
}