diff --git a/wled00/data/edit.htm b/wled00/data/edit.htm
index cfd70baf7..4f0664233 100644
--- a/wled00/data/edit.htm
+++ b/wled00/data/edit.htm
@@ -1,3 +1,586 @@
-
ESP Editor
+
+
+
+
+ESP8266 SPIFFS File Editor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/wled00/html_other.h b/wled00/html_other.h
index 90b661640..720b01168 100644
--- a/wled00/html_other.h
+++ b/wled00/html_other.h
@@ -49,18 +49,6 @@ const char PAGE_welcome[] PROGMEM = "";
#endif
-/*
- * SPIFFS editor html
- */
-#ifdef USEFS
-const char PAGE_edit[] PROGMEM = R"=====(ESP)=====";
-#else
-const char PAGE_edit[] PROGMEM = R"=====(SPIFFS disabled)=====";
-#endif
-
-
/*
* favicon
*/
diff --git a/wled00/wled00.ino b/wled00/wled00.ino
index a79fb35dc..a552c415e 100644
--- a/wled00/wled00.ino
+++ b/wled00/wled00.ino
@@ -24,15 +24,21 @@
//#define WLED_DISABLE_INFRARED //there is no pin left for this on ESP8266-01
//#define WLED_DISABLE_MOBILE_UI
-//to toggle usb serial debug (un)comment following line(s)
+#define WLED_DISABLE_FILESYSTEM //SPIFFS is not used by any WLED feature yet
+//#define WLED_ENABLE_FS_SERVING //Enable sending html file from SPIFFS before serving progmem version
+//#define WLED_ENABLE_FS_EDITOR //enable /edit page for editing SPIFFS content. Will also be disabled with OTA lock
+
+//to toggle usb serial debug (un)comment the following line
//#define WLED_DEBUG
+
//library inclusions
#include
#ifdef ARDUINO_ARCH_ESP32
#include
#include
#include
+ #include "SPIFFS.h"
#else
#include
#include
@@ -46,6 +52,7 @@
#ifndef WLED_DISABLE_OTA
#include
#endif
+#include
#include "src/dependencies/time/Time.h"
#include "src/dependencies/time/TimeLib.h"
#include "src/dependencies/timezone/Timezone.h"
@@ -69,6 +76,7 @@
#include "WS2812FX.h"
#include "ir_codes.h"
+
#if IR_PIN < 0
#ifndef WLED_DISABLE_INFRARED
#define WLED_DISABLE_INFRARED
@@ -89,7 +97,7 @@
//version code in format yymmddb (b = daily build)
-#define VERSION 1903131
+#define VERSION 1903161
char versionString[] = "0.8.4-dev";
@@ -98,10 +106,6 @@ char apPass[65] = "wled1234";
char otaPass[33] = "wledota";
-//spiffs FS only useful for debug (only ESP8266)
-//#define USEFS
-
-
//Hardware CONFIG (only changeble HERE, not at runtime)
//LED strip pin, button pin and IR pin changeable in NpbWrapper.h!
@@ -438,9 +442,12 @@ WS2812FX strip = WS2812FX();
#endif
//filesystem
-#ifdef USEFS
- #include ;
- File fsUploadFile;
+#ifndef WLED_DISABLE_FILESYSTEM
+ #include
+ #ifdef ARDUINO_ARCH_ESP32
+ #include "SPIFFS.h"
+ #endif
+ #include "SPIFFSEditor.h"
#endif
//gamma 2.4 lookup table used for color correction
@@ -465,6 +472,7 @@ const byte gamma8[] = {
//function prototypes
void serveMessage(AsyncWebServerRequest*,uint16_t,String,String,byte);
+
//turns all LEDs off and restarts ESP
void reset()
{
@@ -514,7 +522,7 @@ void loop() {
userLoop();
yield();
- handleButton();
+ handleIO();
handleIR();
handleNetworkTime();
if (!onlyAP) handleAlexa();
diff --git a/wled00/wled01_eeprom.ino b/wled00/wled01_eeprom.ino
index 3a8219842..19e9cc0db 100644
--- a/wled00/wled01_eeprom.ino
+++ b/wled00/wled01_eeprom.ino
@@ -577,13 +577,11 @@ void savePreset(byte index)
}
-char* loadMacro(byte index)
+void loadMacro(byte index, char* m)
{
index-=1;
- char m[65];
- if (index > 15) return m;
+ if (index > 15) return;
readStringFromEEPROM(1024+64*index, m, 64);
- return m;
}
@@ -592,7 +590,9 @@ void applyMacro(byte index)
index-=1;
if (index > 15) return;
String mc="win&";
- mc += loadMacro(index+1);
+ char m[65];
+ loadMacro(index+1, m);
+ mc += m;
mc += "&IN"; //internal, no XML response
if (!notifyMacro) mc += "&NN";
String forbidden = "&M="; //dont apply if called by the macro itself to prevent loop
diff --git a/wled00/wled02_xml.ino b/wled00/wled02_xml.ino
index afe6831f1..603734c90 100644
--- a/wled00/wled02_xml.ino
+++ b/wled00/wled02_xml.ino
@@ -3,10 +3,17 @@
*/
//build XML response to HTTP /win API request
-char* XML_response(AsyncWebServerRequest *request, bool includeTheme)
+char* XML_response(AsyncWebServerRequest *request, bool includeTheme, char* dest = nullptr)
{
- char sbuf[1024];
- olen = 0; obuf = sbuf;
+ if (dest == nullptr) //allocate local buffer if none passed
+ {
+ char sbuf[1024];
+ obuf = sbuf;
+ } else {
+ obuf = dest;
+ }
+
+ olen = 0;
oappend("");
oappendi((nightlightActive && nightlightFade) ? briT : bri);
oappend("");
@@ -98,8 +105,7 @@ char* XML_response(AsyncWebServerRequest *request, bool includeTheme)
oappend("");
}
oappend("");
- if (request != nullptr) request->send(200, "text/xml", sbuf);
- return sbuf;
+ if (request != nullptr) request->send(200, "text/xml", obuf);
}
//append a numeric setting to string buffer
@@ -157,15 +163,15 @@ void sappends(char stype, char* key, char* val)
//get values for settings form in javascript
-char* getSettingsJS(byte subPage)
+void getSettingsJS(byte subPage, char* dest)
{
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec
DEBUG_PRINT("settings resp");
DEBUG_PRINTLN(subPage);
- char sbuf[2048];
- olen = 0; obuf = sbuf;
+ obuf = dest;
+ olen = 0;
- if (subPage <1 || subPage >6) return sbuf;
+ if (subPage <1 || subPage >6) return;
if (subPage == 1) {
sappends('s',"CS",clientSSID);
@@ -328,7 +334,9 @@ char* getSettingsJS(byte subPage)
sappend('c',"CF",!useAMPM);
sappend('i',"TZ",currentTimezone);
sappend('v',"UO",utcOffsetSecs);
- sappends('m',"(\"times\")[0]",getTimeString());
+ char tm[32];
+ getTimeString(tm);
+ sappends('m',"(\"times\")[0]",tm);
sappend('i',"OL",overlayCurrent);
sappend('v',"O1",overlayMin);
sappend('v',"O2",overlayMax);
@@ -344,12 +352,13 @@ char* getSettingsJS(byte subPage)
sappend('v',"CH",countdownHour);
sappend('v',"CM",countdownMin);
sappend('v',"CS",countdownSec);
-
char k[4]; k[0]= 'M';
for (int i=1;i<17;i++)
{
+ char m[65];
+ loadMacro(i, m);
sprintf(k+1,"%i",i);
- sappends('s',k,loadMacro(i));
+ sappends('s',k,m);
}
sappend('v',"MB",macroBoot);
@@ -386,7 +395,6 @@ char* getSettingsJS(byte subPage)
oappend(") OK\";");
}
oappend("}");
- return sbuf;
}
diff --git a/wled00/wled04_file.ino b/wled00/wled04_file.ino
index 0c9f3d5d8..384e5c2da 100644
--- a/wled00/wled04_file.ino
+++ b/wled00/wled04_file.ino
@@ -37,129 +37,43 @@ void handleSerial()
}
}
-#ifdef USEFS
-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";
+#if !defined WLED_DISABLE_FILESYSTEM && defined WLED_ENABLE_FS_SERVING
+//Un-comment any file types you need
+String getContentType(AsyncWebServerRequest* request, String filename){
+ if(request->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(".css")) return "text/css";
+// else if(filename.endsWith(".js")) return "application/javascript";
+ else if(filename.endsWith(".json")) return "application/json";
else if(filename.endsWith(".png")) return "image/png";
- else if(filename.endsWith(".gif")) return "image/gif";
+// 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";
+// 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){
- DEBUG_PRINTLN("handleFileRead: " + path);
+bool handleFileRead(AsyncWebServerRequest* request, String path){
+ DEBUG_PRINTLN("FileRead: " + path);
if(path.endsWith("/")) path += "index.htm";
- String contentType = getContentType(path);
+ String contentType = getContentType(request, 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();
+ if(SPIFFS.exists(pathWithGz)){
+ request->send(SPIFFS, pathWithGz, contentType);
+ return true;
+ }
+ if(SPIFFS.exists(path)) {
+ request->send(SPIFFS, path, contentType);
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;
- DEBUG_PRINT("handleFileUpload Name: "); DEBUG_PRINTLN(filename);
- fsUploadFile = SPIFFS.open(filename, "w");
- filename = String();
- } else if(upload.status == UPLOAD_FILE_WRITE){
- //DEBUG_PRINT("handleFileUpload Data: "); DEBUG_PRINTLN(upload.currentSize);
- if(fsUploadFile)
- fsUploadFile.write(upload.buf, upload.currentSize);
- } else if(upload.status == UPLOAD_FILE_END){
- if(fsUploadFile)
- fsUploadFile.close();
- DEBUG_PRINT("handleFileUpload Size: "); DEBUG_PRINTLN(upload.totalSize);
- }
-}
-
-void handleFileDelete(){
- if(server->args() == 0) return server->send(500, "text/plain", "BAD ARGS");
- String path = server->arg(0);
- DEBUG_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 handleFileList() {
- if(!server->hasArg("dir")) {server->send(500, "text/plain", "BAD ARGS"); return;}
-
- String path = server->arg("dir");
- DEBUG_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 handleFileCreate(){
- if(server->args() == 0)
- return server->send(500, "text/plain", "BAD ARGS");
- String path = server->arg(0);
- DEBUG_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();
-}
-
#else
-bool handleFileRead(String path){return false;}
+bool handleFileRead(AsyncWebServerRequest*, String path){return false;}
#endif
diff --git a/wled00/wled05_init.ino b/wled00/wled05_init.ino
index 015f4284c..75818aa38 100644
--- a/wled00/wled05_init.ino
+++ b/wled00/wled05_init.ino
@@ -30,8 +30,11 @@ void wledInit()
DEBUG_PRINT("LEDs inited. heap usage ~");
DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
- #ifdef USEFS
- SPIFFS.begin();
+ #ifndef WLED_DISABLE_FILESYSTEM
+ #ifdef ARDUINO_ARCH_ESP32
+ SPIFFS.begin(true);
+ #endif
+ SPIFFS.begin();
#endif
DEBUG_PRINTLN("Load EEPROM");
diff --git a/wled00/wled10_ntp.ino b/wled00/wled10_ntp.ino
index 23eb4b6b4..49679119c 100644
--- a/wled00/wled10_ntp.ino
+++ b/wled00/wled10_ntp.ino
@@ -123,10 +123,9 @@ void updateLocalTime()
local = timezones[currentTimezone]->toLocal(tmc);
}
-char* getTimeString()
+void getTimeString(char* out)
{
updateLocalTime();
- char out[32];
sprintf(out,"%i-%i-%i, %i:%s%i:%s%i",year(local), month(local), day(local),
(useAMPM)? hour(local)%12:hour(local),
(minute(local)<10)?"0":"",minute(local),
@@ -135,26 +134,6 @@ char* getTimeString()
{
strcat(out,(hour(local) > 11)? " PM":" AM");
}
- return out;
- /*
- String ret = year(local) + "-";
- ret = ret + month(local);
- ret = ret + "-";
- ret = ret + day(local);
- ret = ret + ", ";
- ret += (useAMPM)? hour(local)%12:hour(local);
- ret = ret + ":";
- if (minute(local) < 10) ret = ret + "0";
- ret = ret + minute(local);
- ret = ret + ":";
- if (second(local) < 10) ret = ret + "0";
- ret = ret + second(local);
- if (useAMPM)
- {
- ret += (hour(local) > 11)? " PM":" AM";
- }
- return ret;
- */
}
void setCountdown()
diff --git a/wled00/wled17_mqtt.ino b/wled00/wled17_mqtt.ino
index d8be91e48..191e70ff6 100644
--- a/wled00/wled17_mqtt.ino
+++ b/wled00/wled17_mqtt.ino
@@ -88,9 +88,11 @@ void publishMqtt()
strcat(subuf, "/c");
mqtt->publish(subuf, 0, true, s);
+ char apires[1024];
+ XML_response(nullptr, false, apires);
strcpy(subuf, mqttDeviceTopic);
strcat(subuf, "/v");
- mqtt->publish(subuf, 0, true, XML_response(nullptr, false));
+ mqtt->publish(subuf, 0, true, apires);
}
diff --git a/wled00/wled18_server.ino b/wled00/wled18_server.ino
index efccbdde4..2cfc0d5d0 100644
--- a/wled00/wled18_server.ino
+++ b/wled00/wled18_server.ino
@@ -15,7 +15,7 @@ void initServer()
});
server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request){
- if(!handleFileRead("/favicon.ico"))
+ if(!handleFileRead(request, "/favicon.ico"))
{
request->send_P(200, "image/x-icon", favicon, 156);
}
@@ -102,14 +102,16 @@ void initServer()
//if OTA is allowed
if (!otaLock){
+ #if !defined WLED_DISABLE_FILESYSTEM && defined WLED_ENABLE_FS_EDITOR
+ #ifdef ARDUINO_ARCH_ESP32
+ server.addHandler(new SPIFFSEditor(SPIFFS));//http_username,http_password));
+ #else
+ server.addHandler(new SPIFFSEditor());//http_username,http_password));
+ #endif
+ #else
server.on("/edit", HTTP_GET, [](AsyncWebServerRequest *request){
- request->send(200, "text/html", PAGE_edit);
+ serveMessage(request, 501, "Not implemented", "The SPIFFS editor is disabled in this build.", 254);
});
- #ifdef USEFS
- server.on("/edit", HTTP_PUT, handleFileCreate);
- server.on("/edit", HTTP_DELETE, handleFileDelete);
- server.on("/edit", HTTP_POST, [](){ server->send(200, "text/plain", ""); }, handleFileUpload);
- server.on("/list", HTTP_GET, handleFileList);
#endif
//init ota page
#ifndef WLED_DISABLE_OTA
@@ -146,19 +148,16 @@ void initServer()
#else
server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){
- serveMessage(request, 500, "Not implemented", "OTA updates are unsupported in this build.", 254);
+ serveMessage(request, 501, "Not implemented", "OTA updates are disabled in this build.", 254);
});
#endif
} else
{
server.on("/edit", HTTP_GET, [](AsyncWebServerRequest *request){
- serveMessage(request, 500, "Access Denied", "Please unlock OTA in security settings!", 254);
+ serveMessage(request, 500, "Access Denied", "Please unlock OTA in security settings!", 254);
});
server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){
- serveMessage(request, 500, "Access Denied", "Please unlock OTA in security settings!", 254);
- });
- server.on("/list", HTTP_GET, [](AsyncWebServerRequest *request){
- serveMessage(request, 500, "Access Denied", "Please unlock OTA in security settings!", 254);
+ serveMessage(request, 500, "Access Denied", "Please unlock OTA in security settings!", 254);
});
}
@@ -177,12 +176,14 @@ void initServer()
request->send(200); return;
}
- if(!handleSet(request, request->url())){
- #ifndef WLED_DISABLE_ALEXA
- if(!espalexa.handleAlexaApiCall(request))
- #endif
- request->send(404, "text/plain", "Not Found");
- }
+ if(handleSet(request, request->url())) return;
+ #ifndef WLED_DISABLE_ALEXA
+ if(espalexa.handleAlexaApiCall(request)) return;
+ #endif
+ #ifdef WLED_ENABLE_FS_SERVING
+ if(handleFileRead(request, request->url())) return;
+ #endif
+ request->send(404, "text/plain", "Not Found");
});
}
@@ -218,6 +219,16 @@ void serveIndex(AsyncWebServerRequest* request)
if (uiConfiguration == 0 && request->hasHeader("User-Agent")) serveMobile = checkClientIsMobile(request->getHeader("User-Agent")->value());
else if (uiConfiguration == 2) serveMobile = true;
+ #ifdef WLED_ENABLE_FS_SERVING
+ if (serveMobile)
+ {
+ if (handleFileRead(request, "/index_mobile.htm")) return;
+ } else
+ {
+ if (handleFileRead(request, "/index.htm")) return;
+ }
+ #endif
+
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html",
(serveMobile) ? (uint8_t*)PAGE_indexM : PAGE_index,
(serveMobile) ? PAGE_indexM_L : PAGE_index_L);
@@ -235,7 +246,13 @@ void serveIndex(AsyncWebServerRequest* request)
String msgProcessor(const String& var)
{
- if (var == "CSS") return String(obuf);
+ if (var == "CSS") {
+ char css[512];
+ obuf = css;
+ olen = 0;
+ getCSSColors();
+ return String(obuf);
+ }
if (var == "MSG") {
String messageBody = messageHead;
messageBody += "";
@@ -266,8 +283,10 @@ String msgProcessor(const String& var)
void serveMessage(AsyncWebServerRequest* request, uint16_t code, String headl, String subl="", byte optionT=255)
{
- char buf[512];
+ #ifndef ARDUINO_ARCH_ESP32
+ char buf[256];
obuf = buf;
+ #endif
olen = 0;
getCSSColors();
messageHead = headl;
@@ -281,9 +300,10 @@ void serveMessage(AsyncWebServerRequest* request, uint16_t code, String headl, S
String settingsProcessor(const String& var)
{
if (var == "CSS") {
- char* buf = getSettingsJS(optionType);
+ char buf[2048];
+ getSettingsJS(optionType, buf);
getCSSColors();
- return buf;
+ return String(buf);
}
if (var == "SCSS") return String(PAGE_settingsCss);
return String();
diff --git a/wled00/wled19_json.ino b/wled00/wled19_json.ino
index 15bb63152..caa3dd829 100644
--- a/wled00/wled19_json.ino
+++ b/wled00/wled19_json.ino
@@ -195,7 +195,7 @@ void serializeInfo(JsonObject& root)
#ifndef WLED_DISABLE_CRONIXIE
os += 0x10;
#endif
- #ifdef USEFS
+ #ifndef WLED_DISABLE_FILESYSTEM
os += 0x08;
#endif
#ifndef WLED_DISABLE_HUESYNC