XML settings done

This commit is contained in:
cschwinne 2016-09-11 23:07:18 +02:00
commit 9062faf7d5
8 changed files with 969 additions and 0 deletions

21
TODO.txt Normal file
View File

@ -0,0 +1,21 @@
switch dev enviroment to 100% git pc -- done
fix current issues -- done
implement brightness slider -- vip -- done
remove settings lock option -- done
toolbar preparation
add toolbar conf in settings
additional color picker field
change slider height to relative values
fully implement EEPROM -- vip -- done
implement settings getter/setter -- vip
implement OTA
implement OTA lock
implement button
implement LED Control (NeoPixelBus?) -- vip
implement HSB slider option
implement default color on boot
FAILURE SOURCE?? --> non-null String
+4917693264270

8
readme.md Normal file
View File

@ -0,0 +1,8 @@
WLED is a basic, fast and (relatively) (ok, VERY relatively) secure implementation of a ESP8266 webserver to control Neopixel (WS2812B) leds
Features:
- 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.

BIN
wled00/data/button.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

3
wled00/data/edit.htm Normal file

File diff suppressed because one or more lines are too long

BIN
wled00/data/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 B

209
wled00/data/index.htm Normal file
View File

@ -0,0 +1,209 @@
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>WLED 0.1c</title>
<!--<meta name="viewport" content="width=device-width, initial-scale=1.5">-->
<script>
strA = "";
strR = "";
strG = "";
strB = "";
function Startup()
{
setInterval('GetArduinoIO()', 5000);
GetArduinoIO();
}
function GetArduinoIO()
{
nocache = "&nocache=" + Math.random() * 1000000;
var request = new XMLHttpRequest();
request.onreadystatechange = function()
{
if (this.readyState == 4) {
if (this.status == 200) {
if (this.responseXML != null) {
document.Ctrl_form.SA.value = this.responseXML.getElementsByTagName('act')[0].childNodes[0].nodeValue;
document.Ctrl_form.SR.value = this.responseXML.getElementsByTagName('cl')[0].childNodes[0].nodeValue;
document.Ctrl_form.SG.value = this.responseXML.getElementsByTagName('cl')[1].childNodes[0].nodeValue;
document.Ctrl_form.SB.value = this.responseXML.getElementsByTagName('cl')[2].childNodes[0].nodeValue;
UpdateVals();
}
}
}
}
// send HTTP request
request.open("GET", "ajax_in/" + strA + strR + strG + strB + nocache, true);
request.send(null);
strA = "";
strR = "";
strG = "";
strB = "";
}
function GetCheck()
{
strA = "&A=" + Ctrl_form.SA.value;
strR = "&R=" + Ctrl_form.SR.value;
strG = "&G=" + Ctrl_form.SG.value;
strB = "&B=" + Ctrl_form.SB.value;
UpdateVals();
GetArduinoIO();
}
function rgb2hex(red, green, blue) {
var rgb = blue | (green << 8) | (red << 16);
return '#' + (0x1000000 + rgb).toString(16).slice(1)
}
function lingrad(red, green, blue) {
return "linear-gradient(white, " + rgb2hex(red, green, blue) + ")";
}
function UpdateVals()
{
document.body.style.background = lingrad(Ctrl_form.SR.value, Ctrl_form.SG.value, Ctrl_form.SB.value);
}
function OpenSettings()
{
window.open("/settings","_self");
}
</script>
<style>
.ctrl_box {
border: 0.3ch solid grey;
margin: auto;
width: 80vw;
background-color: #B9B9B9;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.sliders {
width: 100%;
}
.sliderA {
margin-left: auto;
margin-right: auto;
width: 77vw;
background: linear-gradient(to right, black, yellow);
}
.sliderR {
margin-left: auto;
margin-right: auto;
width: 77vw;
background: linear-gradient(to right, black, red);
}
.sliderG {
margin-left: auto;
margin-right: auto;
width: 77vw;
background: linear-gradient(to right, black, green);
}
.sliderB {
margin-left: auto;
margin-right: auto;
width: 77vw;
background: linear-gradient(to right, black, blue);
}
body {
text-align: right;
background: linear-gradient(white, black);
height: 100%;
margin: 0;
background-repeat: no-repeat;
background-attachment: fixed;
}
html {
height: 100%;
}
.tool_box {
}
.settingsbutton {
width: 1.5cm;
height: 1.5cm;
margin-top: 4px;
margin-right: 4px;
}
input[type=range] {
-webkit-appearance: none;
width: 100%;
margin: -4px 0;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 102px;
cursor: pointer;
background: #DDDDDD;
}
input[type=range]::-webkit-slider-thumb {
height: 78px;
width: 78px;
background: #ffffff;
cursor: pointer;
-webkit-appearance: none;
margin-top: 12px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #DDDDDD;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 102px;
cursor: pointer;
background: #DDDDDD;
}
input[type=range]::-moz-range-thumb {
height: 78px;
width: 78px;
background: #ffffff;
cursor: pointer;
}
input[type=range]::-ms-track {
width: 100%;
height: 102px;
cursor: pointer;
background: transparent;
border-color: transparent;
color: transparent;
}
input[type=range]::-ms-fill-lower {
background: #DDDDDD;
}
input[type=range]::-ms-fill-upper {
background: #DDDDDD;
}
input[type=range]::-ms-thumb {
width: 78px;
background: #ffffff;
cursor: pointer;
height: 78px;
}
input[type=range]:focus::-ms-fill-lower {
background: #DDDDDD;
}
input[type=range]:focus::-ms-fill-upper {
background: #DDDDDD;
}
</style>
<style id="holderjs-style" type="text/css"></style></head>
<body onload="Startup()" class=" __plain_text_READY__">
<div id="tbB" class="tool_box">
<input type="image" class="settingsbutton" src="/button.png" onclick="OpenSettings()"id="tool">
</div>
<div id="cdB" class="ctrl_box">
<form id="form_c" name="Ctrl_form">
<br>
<div id="slA" class="sliderA">
<input type="range" class="sliders" name="SA" value="0" min="0" max="255" step="1" onchange="GetCheck()"> </div> <br>
<div id="slR" class="sliderR">
<input type="range" class="sliders" name="SR" value="0" min="0" max="255" step="1" onchange="GetCheck()"> </div> <br>
<div id="slR" class="sliderG">
<input type="range" class="sliders" name="SG" value="0" min="0" max="255" step="1" onchange="GetCheck()"> </div> <br>
<div id="slR" class="sliderB">
<input type="range" class="sliders" name="SB" value="0" min="0" max="255" step="1" onchange="GetCheck()"> </div> <br>
</form>
</div>
</div></body></html>

131
wled00/data/settings.htm Normal file
View File

@ -0,0 +1,131 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Settings</title>
<script>
function GetCurrent()
{
nocache = "&nocache=" + Math.random() * 1000000;
var request = new XMLHttpRequest();
request.onreadystatechange = function()
{
if (this.readyState == 4) {
if (this.status == 200) {
if (this.responseXML != null) {
document.Settings_form.CSSID.value = this.responseXML.getElementsByTagName('cssid')[0].childNodes[0].nodeValue;
document.Settings_form.CPASS.value = this.responseXML.getElementsByTagName('cpass')[0].childNodes[0].nodeValue; //fake pass like ******
document.Settings_form.CSIP0.value = this.responseXML.getElementsByTagName('csips')[0].childNodes[0].nodeValue;
document.Settings_form.CSIP1.value = this.responseXML.getElementsByTagName('csips')[1].childNodes[0].nodeValue;
document.Settings_form.CSIP2.value = this.responseXML.getElementsByTagName('csips')[2].childNodes[0].nodeValue;
document.Settings_form.CSIP3.value = this.responseXML.getElementsByTagName('csips')[3].childNodes[0].nodeValue;
document.Settings_form.CSGW0.value = this.responseXML.getElementsByTagName('csgws')[0].childNodes[0].nodeValue;
document.Settings_form.CSGW1.value = this.responseXML.getElementsByTagName('csgws')[1].childNodes[0].nodeValue;
document.Settings_form.CSGW2.value = this.responseXML.getElementsByTagName('csgws')[2].childNodes[0].nodeValue;
document.Settings_form.CSGW3.value = this.responseXML.getElementsByTagName('csgws')[3].childNodes[0].nodeValue;
document.Settings_form.CSSN0.value = this.responseXML.getElementsByTagName('cssns')[0].childNodes[0].nodeValue;
document.Settings_form.CSSN1.value = this.responseXML.getElementsByTagName('cssns')[1].childNodes[0].nodeValue;
document.Settings_form.CSSN2.value = this.responseXML.getElementsByTagName('cssns')[2].childNodes[0].nodeValue;
document.Settings_form.CSSN3.value = this.responseXML.getElementsByTagName('cssns')[3].childNodes[0].nodeValue;
document.Settings_form.CMDNS.value = this.responseXML.getElementsByTagName('cmdns')[0].childNodes[0].nodeValue;
document.Settings_form.APSSID.value = this.responseXML.getElementsByTagName('apssid')[0].childNodes[0].nodeValue;
document.Settings_form.APHSSID.checked = (this.responseXML.getElementsByTagName('aphssid')[0].childNodes[0].nodeValue)!=0?true:false;
document.Settings_form.APPASS.value = this.responseXML.getElementsByTagName('appass')[0].childNodes[0].nodeValue; //fake pass like ******
document.Settings_form.APCHAN.value = this.responseXML.getElementsByTagName('apchan')[0].childNodes[0].nodeValue;
document.Settings_form.LEDS.value = this.responseXML.getElementsByTagName('leds')[0].childNodes[0].nodeValue;
document.Settings_form.PWRLED.checked = (this.responseXML.getElementsByTagName('pwrled')[0].childNodes[0].nodeValue)!=0?true:false;
document.Settings_form.BTNP.value = this.responseXML.getElementsByTagName('btnp')[0].childNodes[0].nodeValue;
document.Settings_form.NOOTA.checked = (this.responseXML.getElementsByTagName('noota')[0].childNodes[0].nodeValue)!=0?true:false;
document.Settings_form.NORAP.checked = (this.responseXML.getElementsByTagName('norap')[0].childNodes[0].nodeValue)!=0?true:false;
document.getElementsByClassName("sip")[0].innerHTML = this.responseXML.getElementsByTagName('sip')[0].childNodes[0].nodeValue;
document.getElementsByClassName("sip")[1].innerHTML = this.responseXML.getElementsByTagName('sip')[1].childNodes[0].nodeValue;
document.getElementsByClassName("otastat")[0].innerHTML = this.responseXML.getElementsByTagName('otastat')[0].childNodes[0].nodeValue;
document.getElementsByClassName("msg")[0].innerHTML = this.responseXML.getElementsByTagName('msg')[0].childNodes[0].nodeValue;
if (Settings_form.NOOTA.checked) {document.Settings_form.NOOTA.disabled="disabled";}
}
}
}
}
// send HTTP request
request.open("GET", "get-settings/" + nocache, true);
request.send(null);
}
function OpenMain()
{
window.open("/","_self");
}
</script>
<style>
body {
line-height: 150%;
}
</style>
</head>
<body onload="GetCurrent()" class=" __plain_text_READY__">
<h1>WLED Settings</h1>
<form id="form_s" name="Settings_form" action="save-settings/" method="post" autocomplete="off">
<input type="submit" name="SUBM" value="Save">
<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 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>
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>
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>
mDNS address (leave empty for no mDNS): <br/>
http:// <input type="text" 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>
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 IP: <span class="sip"> Not active </span> <br>
<h2>Application setup</h2>
<h3>LED setup</h3>
LED amount: <input type="text" name="LEDS" maxlength="3" size="2"> <br>
Disable Power LED: <input type="checkbox" name="PWRLED" value="0"> <br>
<h3>Button setup</h3>
Button pin: <input type="text" name="BTNP" maxlength="2" size="2"> <br>
Button function: Toggle on/off <br>
<h3>Toolbar</h3>
<i>Not implemented</i> <br>
<h3>Animations</h3>
<i>Not implemented</i> <br>
<h3>Daisy chain</h3>
<i>Not implemented</i> <br>
<h3>Security</h3>
Disable OTA: <input type="checkbox" name="NOOTA" value="0"> <br>
ArduinoOTA and the edit page will be inaccessible until a SPIFFS reflash! <br>
Checking this is advised for added security if you don't need software changes. <br>
Current status: <span class="otastat"> Unknown </span> <br> <br>
Disable recovery AP: <input type="checkbox" name="NORAP" value="0"> <br>
In case of a connection error there will be no wireless recovery possible! <br>
Completely disables all Access Point functions. <br> <br>
Factory reset: <input type="checkbox" name="RESET" value="0"> <br>
All EEPROM content (settings) will be erased. <br> <br>
HTTP traffic is not encrypted. An attacker in the same network could intercept form data!<br>
<h3>About</h3>
WLED version 0.1c <br>
Server message: <span class="msg"> XML response error! </span>
<br><br>
<input type="submit" name="SUBM" value="Save">
<input type="button" name="BACK" value="Back" onclick="OpenMain()">
</form>
</body>
</html>

597
wled00/wled00.ino Normal file
View File

@ -0,0 +1,597 @@
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <EEPROM.h>
#include <Hash.h>
#include <NeoPixelBus.h>
#include <FS.h>
//NeoPixelBus strip = NeoPixelBus(pixelCount, 8, NEO_GRB | NEO_KHZ800);
String clientssid = "Your_Network_Here";
String clientpass = "Dummy_Pass";
String cmdns = "led";
String apssid = "WLED-AP";
String appass = "wled1234";
int apchannel = 1;
int aphide = 0;
boolean useap = true;
IPAddress staticip(0, 0, 0, 0);
IPAddress staticgateway(0, 0, 0, 0);
IPAddress staticsubnet(255, 255, 255, 0);
//boolean wasConnected = false;
byte col[3];
byte bri;
byte hue, sat;
boolean ota_lock = false;
int led_amount = 16;
int nopwrled = 1;
char HTTP_req[150];
ESP8266WebServer server(80);
File fsUploadFile;
void down()
{
Serial.println("MODULE TERMINATED");
while (1) {delay(1000);}
}
void reset()
{
Serial.println("MODULE RESET");
ESP.reset();
}
void clearEEPROM()
{
for (int i = 0; i < 256; i++)
{
EEPROM.write(i, 0);
}
}
void saveSettingsToEEPROM()
{
if (EEPROM.read(233) != 233) //set no first boot flag
{
EEPROM.write(233, 233);
}
for (int i = 0; i < 32; ++i)
{
EEPROM.write(i, clientssid.charAt(i));
}
for (int i = 32; i < 96; ++i)
{
EEPROM.write(i, clientpass.charAt(i));
}
for (int i = 96; i < 128; ++i)
{
EEPROM.write(i, cmdns.charAt(i));
}
for (int i = 128; i < 160; ++i)
{
EEPROM.write(i, apssid.charAt(i));
}
for (int i = 160; i < 224; ++i)
{
EEPROM.write(i, appass.charAt(i));
}
EEPROM.write(228, aphide);
EEPROM.write(227, apchannel);
EEPROM.write(229, led_amount);
EEPROM.write(231, nopwrled);
EEPROM.write(234, staticip[0]);
EEPROM.write(235, staticip[1]);
EEPROM.write(236, staticip[2]);
EEPROM.write(237, staticip[3]);
EEPROM.write(238, staticgateway[0]);
EEPROM.write(239, staticgateway[1]);
EEPROM.write(240, staticgateway[2]);
EEPROM.write(241, staticgateway[3]);
EEPROM.write(242, staticsubnet[0]);
EEPROM.write(243, staticsubnet[1]);
EEPROM.write(244, staticsubnet[2]);
EEPROM.write(245, staticsubnet[3]);
}
void loadSettingsFromEEPROM()
{
if (EEPROM.read(233) != 233) //first boot/reset to default
{
saveSettingsToEEPROM();
return;
}
clientssid = "";
for (int i = 0; i < 32; ++i)
{
clientssid += char(EEPROM.read(i));
}
clientpass = "";
for (int i = 32; i < 96; ++i)
{
clientpass += char(EEPROM.read(i));
}
cmdns = "";
for (int i = 96; i < 128; ++i)
{
cmdns += char(EEPROM.read(i));
}
apssid = "";
for (int i = 128; i < 160; ++i)
{
apssid += char(EEPROM.read(i));
}
appass = "";
for (int i = 160; i < 224; ++i)
{
appass += char(EEPROM.read(i));
}
aphide = EEPROM.read(228);
if (aphide > 1) aphide = 1;
apchannel = EEPROM.read(227);
if (apchannel > 13 || apchannel < 1) apchannel = 1;
led_amount = EEPROM.read(229);
nopwrled = EEPROM.read(231);
if (nopwrled > 1) nopwrled = 1;
staticip[0] = EEPROM.read(234);
staticip[1] = EEPROM.read(235);
staticip[2] = EEPROM.read(236);
staticip[3] = EEPROM.read(237);
staticgateway[0] = EEPROM.read(238);
staticgateway[1] = EEPROM.read(239);
staticgateway[2] = EEPROM.read(240);
staticgateway[3] = EEPROM.read(241);
staticsubnet[0] = EEPROM.read(242);
staticsubnet[1] = EEPROM.read(243);
staticsubnet[2] = EEPROM.read(244);
staticsubnet[3] = EEPROM.read(245);
}
void XML_response()
{
String resp;
resp = resp + "<?xml version = \"1.0\" ?>";
resp = resp + "<vs>";
resp = resp + "<act>";
resp = resp + bri;
resp = resp + "</act>";
for (int i = 0; i < 3; i++)
{
resp = resp + "<cl>";
resp = resp + col[i];
resp = resp + "</cl>";
}
//enable toolbar here
resp = resp + "</vs>";
server.send(200, "text/xml", resp);
}
void XML_response_settings()
{
String resp;
resp = resp + "<?xml version = \"1.0\" ?>";
resp = resp + "<cssid>";
resp = resp + clientssid;
resp = resp + "</cssid>";
resp = resp + "<cpass>";
for (int i = 0; i < clientpass.length(); i++)
{
resp = resp + "*";
}
resp = resp + "</cpass>";
for (int i = 0; i < 4; i++)
{
resp = resp + "<csips>";
resp = resp + staticip[i];
resp = resp + "</csips>";
}
for (int i = 0; i < 4; i++)
{
resp = resp + "<csgws>";
resp = resp + staticgateway[i];
resp = resp + "</csgws>";
}
for (int i = 0; i < 4; i++)
{
resp = resp + "<cssns>";
resp = resp + staticsubnet[i];
resp = resp + "</cssns>";
}
resp = resp + "<cmdns>";
resp = resp + cmdns;
resp = resp + "</cmdns>";
resp = resp + "<apssid>";
resp = resp + apssid;
resp = resp + "</apssid>";
resp = resp + "<aphssid>";
resp = resp + aphide;
resp = resp + "</aphssid>";
resp = resp + "<appass>";
for (int i = 0; i < appass.length(); i++)
{
resp = resp + "*";
}
resp = resp + "</appass>";
resp = resp + "<apchan>";
resp = resp + apchannel;
resp = resp + "</apchan>";
resp = resp + "<leds>";
resp = resp + led_amount;
resp = resp + "</leds>";
resp = resp + "<pwrled>";
resp = resp + nopwrled;
resp = resp + "</pwrled>";
resp = resp + "<btnp>0</btnp>"; //NI
resp = resp + "<noota>0</noota>"; //NI
resp = resp + "<norap>0</norap>"; //NI
resp = resp + "<sip>";
if (!Wifi.localIP()[0] == 0)
{
resp = resp + WiFi.localIP();
} else
{
resp = resp + "Not connected";
}
resp = resp + "</sip>";
resp = resp + "<sip>";
if (!Wifi.softAPIP()[0] == 0)
{
resp = resp + WiFi.softAPIP();
} else
{
resp = resp + "Not active";
}
resp = resp + "</sip>";
server.send(200, "text/xml", resp);
}
char StrContains(char *str, char *sfind)
{
char found = 0;
char index = 0;
char len;
len = strlen(str);
if (strlen(sfind) > len) {
return 0;
}
while (index < len) {
if (str[index] == sfind[found]) {
found++;
if (strlen(sfind) == found) {
return index;
}
}
else {
found = 0;
}
index++;
}
return 0;
}
uint8_t getNumberAfterStringPos(char str[], char spos)
{
String op;
boolean no_n = false;
int i = 0;
while (!no_n) {
if (str[spos + i + 1] > 47 && str[spos + i + 1] < 58)
{
op += str[spos + i + 1];
}
else {no_n = true;}
i++;
}
return op.toInt();
}
boolean handleSet(String req)
{
Serial.println("handleSet:");
Serial.println(req);
req.toCharArray(HTTP_req, 150, 0);
if (!StrContains(HTTP_req, "ajax_in")) {
if (
return false;
}
int pos = 0;
pos = StrContains(HTTP_req, "A=");
if (pos > 0) {
bri = getNumberAfterStringPos(HTTP_req, pos);
}
pos = StrContains(HTTP_req, "R=");
if (pos > 0) {
col[0] = getNumberAfterStringPos(HTTP_req, pos);
}
pos = StrContains(HTTP_req, "G=");
if (pos > 0) {
col[1] = getNumberAfterStringPos(HTTP_req, pos);
}
pos = StrContains(HTTP_req, "B=");
if (pos > 0) {
col[2] = getNumberAfterStringPos(HTTP_req, pos);
}
Serial.println(col[0]);
XML_response();
return true;
}
//format bytes
String formatBytes(size_t bytes){
if (bytes < 1024){
return String(bytes)+"B";
} else if(bytes < (1024 * 1024)){
return String(bytes/1024.0)+"KB";
} else if(bytes < (1024 * 1024 * 1024)){
return String(bytes/1024.0/1024.0)+"MB";
} else {
return String(bytes/1024.0/1024.0/1024.0)+"GB";
}
}
String getContentType(String filename){
if(server.hasArg("download")) return "application/octet-stream";
else if(filename.endsWith(".htm")) return "text/html";
else if(filename.endsWith(".html")) return "text/html";
else if(filename.endsWith(".css")) return "text/css";
else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".png")) return "image/png";
else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
else if(filename.endsWith(".xml")) return "text/xml";
else if(filename.endsWith(".pdf")) return "application/x-pdf";
else if(filename.endsWith(".zip")) return "application/x-zip";
else if(filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
bool handleFileRead(String path){
Serial.println("handleFileRead: " + path);
if(path.endsWith("/")) path += "index.htm";
String contentType = getContentType(path);
String pathWithGz = path + ".gz";
if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){
if(SPIFFS.exists(pathWithGz))
path += ".gz";
File file = SPIFFS.open(path, "r");
size_t sent = server.streamFile(file, contentType);
file.close();
return true;
}
return false;
}
void handleFileUpload(){
if(server.uri() != "/edit") return;
HTTPUpload& upload = server.upload();
if(upload.status == UPLOAD_FILE_START){
String filename = upload.filename;
if(!filename.startsWith("/")) filename = "/"+filename;
Serial.print("handleFileUpload Name: "); Serial.println(filename);
fsUploadFile = SPIFFS.open(filename, "w");
filename = String();
} else if(upload.status == UPLOAD_FILE_WRITE){
//Serial.print("handleFileUpload Data: "); Serial.println(upload.currentSize);
if(fsUploadFile)
fsUploadFile.write(upload.buf, upload.currentSize);
} else if(upload.status == UPLOAD_FILE_END){
if(fsUploadFile)
fsUploadFile.close();
Serial.print("handleFileUpload Size: "); Serial.println(upload.totalSize);
}
}
void handleFileDelete(){
if(server.args() == 0) return server.send(500, "text/plain", "BAD ARGS");
String path = server.arg(0);
Serial.println("handleFileDelete: " + path);
if(path == "/")
return server.send(500, "text/plain", "BAD PATH");
if(!SPIFFS.exists(path))
return server.send(404, "text/plain", "FileNotFound");
SPIFFS.remove(path);
server.send(200, "text/plain", "");
path = String();
}
void handleFileCreate(){
if(server.args() == 0)
return server.send(500, "text/plain", "BAD ARGS");
String path = server.arg(0);
Serial.println("handleFileCreate: " + path);
if(path == "/")
return server.send(500, "text/plain", "BAD PATH");
if(SPIFFS.exists(path))
return server.send(500, "text/plain", "FILE EXISTS");
File file = SPIFFS.open(path, "w");
if(file)
file.close();
else
return server.send(500, "text/plain", "CREATE FAILED");
server.send(200, "text/plain", "");
path = String();
}
void handleFileList() {
if(!server.hasArg("dir")) {server.send(500, "text/plain", "BAD ARGS"); return;}
String path = server.arg("dir");
Serial.println("handleFileList: " + path);
Dir dir = SPIFFS.openDir(path);
path = String();
String output = "[";
while(dir.next()){
File entry = dir.openFile("r");
if (output != "[") output += ',';
bool isDir = false;
output += "{\"type\":\"";
output += (isDir)?"dir":"file";
output += "\",\"name\":\"";
output += String(entry.name()).substring(1);
output += "\"}";
entry.close();
}
output += "]";
server.send(200, "text/json", output);
}
void setLeds() {
/*for (int i=0; i<pixelCount; i++) {
strip.SetPixelColor(i, black);
}
strip.SetPixelColor(pixel, color);
strip.Show();*/
}
void setup() {
Serial.begin(115200);
Serial.println("T123");
Serial.println();
for(uint8_t t = 4; t > 0; t--) {
Serial.printf("[SETUP] BOOT WAIT %d...\n", t);
Serial.flush();
delay(1000);
}
SPIFFS.begin();
{
Dir dir = SPIFFS.openDir("/");
while (dir.next()) {
String fileName = dir.fileName();
size_t fileSize = dir.fileSize();
Serial.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str());
}
Serial.printf("\n");
}
Serial.println("Init EEPROM");
EEPROM.begin(256);
loadSettingsFromEEPROM();
if (staticip[0] != 0)
{
WiFi.config(staticip, staticgateway, staticsubnet);
} else
{
WiFi.config(0U, 0U, 0U);
}
if (useap)
{
initAP();
} else
{
WiFi.softAPdisconnect();
}
initCon();
Serial.println("");
Serial.print("Connected! IP address: ");
Serial.println(WiFi.localIP());
// Set up mDNS responder:
if (cmdns != NULL && !WL_CONNECTED && !MDNS.begin(cmdns.c_str())) {
Serial.println("Error setting up MDNS responder!");
down();
}
Serial.println("mDNS responder started");
//SERVER INIT
//settings page
server.on("/settings", HTTP_GET, [](){
if(!handleFileRead("/settings.htm")) server.send(404, "text/plain", "FileNotFound");
});
server.on("/button.png", HTTP_GET, [](){
if(!handleFileRead("/button.png")) server.send(404, "text/plain", "FileNotFound");
});
server.on("/favicon.ico", HTTP_GET, [](){
if(!handleFileRead("/favicon.ico")) server.send(404, "text/plain", "FileNotFound");
});
server.on("/", HTTP_GET, [](){
if(!handleFileRead("/index.htm")) server.send(404, "text/plain", "FileNotFound");
});
server.on("/reset", HTTP_GET, reset);
if (!ota_lock){
//load editor
server.on("/edit", HTTP_GET, [](){
if(!handleFileRead("/edit.htm")) server.send(404, "text/plain", "FileNotFound");
});
//create file
server.on("/edit", HTTP_PUT, handleFileCreate);
//delete file
server.on("/edit", HTTP_DELETE, handleFileDelete);
//first callback is called after the request has ended with all parsed arguments
//second callback handles file uploads at that location
server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); }, handleFileUpload);
//list directory
server.on("/list", HTTP_GET, handleFileList);
//kill module
server.on("/down", HTTP_GET, down);
}
//called when the url is not defined here, ajax-in; get-settings
server.onNotFound([](){
if(!handleSet(server.uri())){
server.send(404, "text/plain", "FileNotFound");
}
});
server.begin();
Serial.println("HTTP server started");
// Add service to MDNS
MDNS.addService("http", "tcp", 80);
/*/ Initialize NeoPixel Strip
strip.Begin();
strip.Show();*/
if (nopwrled == 0)
{
pinMode(BUILTIN_LED, OUTPUT);
}
}
void loop() {
server.handleClient();
/*if (wasConnected && !WL_CONNECTED)
{
initCon();
}*/
}
void initAP(){
WiFi.softAP(apssid.c_str(), appass.c_str(), apchannel, aphide);
}
void initCon()
{
WiFi.begin(clientssid.c_str(), clientpass.c_str());
int fail_count =0;
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("C_NC");
fail_count++;
if (fail_count > 32)
{
WiFi.disconnect();
Serial.println("Can't connect to network. Opening AP...");
initAP();
return;
}
}
//wasConnected = true;
}