diff --git a/cores/esp8266/spiffs/spiffs_esp8266.c b/cores/esp8266/spiffs/spiffs_esp8266.c index e0a79d505..7cd4fd684 100644 --- a/cores/esp8266/spiffs/spiffs_esp8266.c +++ b/cores/esp8266/spiffs/spiffs_esp8266.c @@ -1,3 +1,10 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/anakod/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + ****/ + #include "spiffs_esp8266.h" #include "spi_flash.h" #include "esp8266_peri.h" @@ -152,6 +159,6 @@ uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size ){ //shorthand when start and end addresses of the sector are not needed uint32_t flashmem_get_sector_of_address( uint32_t addr ){ - return (addr - INTERNAL_FLASH_START_ADDRESS) / INTERNAL_FLASH_SECTOR_SIZE;; + return (addr - INTERNAL_FLASH_START_ADDRESS) / INTERNAL_FLASH_SECTOR_SIZE; } diff --git a/cores/esp8266/spiffs/spiffs_esp8266.h b/cores/esp8266/spiffs/spiffs_esp8266.h index d97f3e3e0..cd1eb3544 100644 --- a/cores/esp8266/spiffs/spiffs_esp8266.h +++ b/cores/esp8266/spiffs/spiffs_esp8266.h @@ -1,3 +1,10 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/anakod/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + ****/ + #ifndef SYSTEM_FLASHMEM_H_ #define SYSTEM_FLASHMEM_H_ @@ -17,7 +24,6 @@ The small 4KB sectors allow for greater flexibility in applications that require #define SPIFFS_API_DBG_V(fmt, ...) //os_printf(fmt, ##__VA_ARGS__) #define SPIFFS_API_DBG_E(fmt, ...) //os_printf("ERROR: " fmt , ##__VA_ARGS__) -#define INTERNAL_FLASH_PAGE_SIZE 256 #define INTERNAL_FLASH_SECTOR_SIZE 4096 #define INTERNAL_FLASH_START_ADDRESS 0x40200000 @@ -27,7 +33,6 @@ The small 4KB sectors allow for greater flexibility in applications that require extern uint32_t flashmem_write( const void *from, uint32_t toaddr, uint32_t size ); extern uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size ); extern bool flashmem_erase_sector( uint32_t sector_id ); -uint32_t flashmem_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend ); uint32_t flashmem_get_sector_of_address( uint32_t addr ); #ifdef __cplusplus diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/FSWebServer.ino b/libraries/ESP8266WebServer/examples/FSWebServer/FSWebServer.ino new file mode 100644 index 000000000..fccf2b3eb --- /dev/null +++ b/libraries/ESP8266WebServer/examples/FSWebServer/FSWebServer.ino @@ -0,0 +1,258 @@ +/* + FSWebServer - Example WebServer with SPIFFS backend for esp8266 + + Copyright (c) 2015 Hristo Gochkov. All rights reserved. + This file is part of the ESP8266WebServer library for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE) + !!! This will erase any previous SPIFFS data you may have! + !!! Make Backups First !!! + if you do not have it, get it at : << +#include +#include +#include +#include + +#define DBG_OUTPUT_PORT Serial + +const char* ssid = "**********"; +const char* password = "**********"; +const char* hostname = "esp8266fs"; + +MDNSResponder mdns; +ESP8266WebServer server(80); +//holds the current upload +FSFile fsUploadFile; + +//format bytes +char *formatBytes(size_t bytes){ + if (bytes < 1024){ + return (char *)String(String(bytes)+"B").c_str(); + } else if(bytes < (1024 * 1024)){ + return (char *)String(String(bytes/1024.0)+"KB").c_str(); + } else if(bytes < (1024 * 1024 * 1024)){ + return (char *)String(String(bytes/1024.0/1024.0)+"MB").c_str(); + } else { + return (char *)String(String(bytes/1024.0/1024.0/1024.0)+"GB").c_str(); + } +} + +String getContentType(String filename){ + if(server.hasArg("download")) return "application/octet-stream"; + else if(filename.endsWith(".htm")) 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){ + if(path.endsWith("/")) path += "index.htm"; + String contentType = getContentType(path); + if(FS.exists((char *)(path+".gz").c_str()) || FS.exists((char *)path.c_str())){ + if(FS.exists((char *)(path+".gz").c_str())) + path += ".gz"; + FSFile file = FS.open((char *)path.c_str()); + server.streamFile(file, contentType); + file.close(); + return true; + } + return false; +} + +void handleFileUpdate(){ + if(server.uri() != "/edit") return; + HTTPUpload& upload = server.upload(); + if(upload.status == UPLOAD_FILE_START){ + String filename = upload.filename; + DBG_OUTPUT_PORT.print("Upload Name: "); DBG_OUTPUT_PORT.println(filename); + fsUploadFile = FS.open((char *)filename.c_str(), FSFILE_OVERWRITE); + filename = String(); + } else if(upload.status == UPLOAD_FILE_WRITE){ + //DBG_OUTPUT_PORT.print("Upload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize); + if(fsUploadFile) + fsUploadFile.write(upload.buf, upload.currentSize); + } else if(upload.status == UPLOAD_FILE_END){ + if(fsUploadFile) + fsUploadFile.close(); + DBG_OUTPUT_PORT.print("Upload Size: "); DBG_OUTPUT_PORT.println(upload.totalSize); + } +} + +void handleFileDelete(){ + if(server.args() == 0) return server.send(500, "text/plain", "BAD ARGS"); + String path = server.arg(0); + if(path == "/") + return server.send(500, "text/plain", "BAD PATH"); + if(!FS.exists((char *)(path.c_str()))) + return server.send(404, "text/plain", "FileNotFound"); + FS.remove((char *)path.c_str()); + 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); + if(path == "/") + return server.send(500, "text/plain", "BAD PATH"); + if(FS.exists((char *)path.c_str())) + return server.send(500, "text/plain", "FILE EXISTS"); + FSFile file = FS.open((char *)path.c_str(), FSFILE_OVERWRITE); + 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")) return server.send(500, "text/plain", "BAD ARGS"); + String path = server.arg("dir"); + + FSFile entry; + FSFile dir = FS.open((char *)path.c_str()); + path = String(); + if(!dir.isDirectory()){ + dir.close(); + server.send(500, "text/plain", "NOT DIR"); + return; + } + dir.rewindDirectory(); + + WiFiClient client = server.client(); + client.print("HTTP/1.1 200 OK\r\nContent-Type: text/json\r\nConnection: close\r\n\r\n"); + String output = "["; + while(true){ + entry = dir.openNextFile(); + if (!entry) break; + if(!FS.exists(entry.name())){ + os_printf("Entry[%s] Not Exists!\n", entry.name()); + entry.remove(); + entry.close(); + continue; + } + if(output != "[") output += ','; + output += "{\"type\":\""; + output += (entry.isDirectory())?"dir":"file"; + output += "\",\"name\":\""; + output += String(entry.name()).substring(1); + output += "\"}"; + entry.close(); + } + dir.close(); + + output += "]"; + client.write(output.c_str(), output.length()); + output = String(); + uint16_t maxWait = HTTP_MAX_CLOSE_WAIT; + while(client.connected() && maxWait--) { + delay(1); + } +} + +void setup(void){ + DBG_OUTPUT_PORT.begin(115200); + DBG_OUTPUT_PORT.print("\n"); + + //SPIFFS INIT + DBG_OUTPUT_PORT.printf("\n==== SPIFFS Info ====\n"); + DBG_OUTPUT_PORT.printf("FS Mount: %d\n", FS.mount()); + DBG_OUTPUT_PORT.printf("FS Size: %s\n", formatBytes(FS.size())); + DBG_OUTPUT_PORT.printf("FS Bytes: total: %s, used: %s\n", formatBytes(FS.totalBytes()), formatBytes(FS.usedBytes())); + DBG_OUTPUT_PORT.printf("FS Blocks: total: %d, free: %d, size: %s\n", FS.totalBlocks(), FS.freeBlocks(), formatBytes(FS.blockSize())); + DBG_OUTPUT_PORT.printf("FS Pages: allocated: %d, deleted: %d, size: %s\n", FS.allocatedPages(), FS.deletedPages(), formatBytes(FS.pageSize())); + FSFile entry; + FSFile dir = FS.open((char *)"/"); + while(true){ + entry = dir.openNextFile(); + if (!entry) break; + DBG_OUTPUT_PORT.printf("FS File: %s, type: %s, size: %s\n", entry.name(), (entry.isDirectory())?"dir":"file", formatBytes(entry.size())); + entry.close(); + } + dir.close(); + DBG_OUTPUT_PORT.printf("\n"); + + //WIFI INIT + DBG_OUTPUT_PORT.printf("Connecting to %s\n", ssid); + WiFi.begin(ssid, password); + if(WiFi.waitForConnectResult() != WL_CONNECTED){ + DBG_OUTPUT_PORT.printf("Could not connect to %s\n", ssid); + while(1) delay(500); + } + DBG_OUTPUT_PORT.print("Connected! IP address: "); + DBG_OUTPUT_PORT.println(WiFi.localIP()); + + //mDNS INIT + if (mdns.begin(hostname, WiFi.localIP())) + DBG_OUTPUT_PORT.printf("mDNS responder started for %s.local\n", hostname); + + //SERVER INIT + //list directory + server.on("/list", HTTP_GET, handleFileList); + //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); + //called after file upload + server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); }); + //called when a file is received inside POST data + server.onFileUpload(handleFileUpdate); + + //called when the url is not defined here + //use it to load content from SPIFFS + server.onNotFound([](){ + if(!handleFileRead(server.uri())) + server.send(404, "text/plain", "FileNotFound"); + }); + + //get heap status, analog input value and all GPIO statuses in one json call + server.on("/all", HTTP_GET, [](){ + String json = "{"; + json += "\"heap\":"+String(ESP.getFreeHeap()); + json += ", \"analog\":"+String(analogRead(A0)); + json += ", \"gpio\":"+String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16))); + json += "}"; + server.send(200, "text/json", json); + json = String(); + }); + server.begin(); + DBG_OUTPUT_PORT.println("HTTP server started"); + +} + +void loop(void){ + server.handleClient(); +} diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/data/edit.htm.gz b/libraries/ESP8266WebServer/examples/FSWebServer/data/edit.htm.gz new file mode 100644 index 000000000..9ee1b81f0 Binary files /dev/null and b/libraries/ESP8266WebServer/examples/FSWebServer/data/edit.htm.gz differ diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/data/favicon.ico b/libraries/ESP8266WebServer/examples/FSWebServer/data/favicon.ico new file mode 100644 index 000000000..71b25fe6e Binary files /dev/null and b/libraries/ESP8266WebServer/examples/FSWebServer/data/favicon.ico differ diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/data/graphs.js.gz b/libraries/ESP8266WebServer/examples/FSWebServer/data/graphs.js.gz new file mode 100644 index 000000000..72435445a Binary files /dev/null and b/libraries/ESP8266WebServer/examples/FSWebServer/data/graphs.js.gz differ diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/data/index.htm b/libraries/ESP8266WebServer/examples/FSWebServer/data/index.htm new file mode 100644 index 000000000..facca7b97 --- /dev/null +++ b/libraries/ESP8266WebServer/examples/FSWebServer/data/index.htm @@ -0,0 +1,100 @@ + + + + + + ESP Monitor + + + + +
+ + + + +
+
+
+
+ + \ No newline at end of file diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/data/src/edit-src.htm b/libraries/ESP8266WebServer/examples/FSWebServer/data/src/edit-src.htm new file mode 100644 index 000000000..980acc168 --- /dev/null +++ b/libraries/ESP8266WebServer/examples/FSWebServer/data/src/edit-src.htm @@ -0,0 +1,512 @@ + + + + +ESP Editor + + + + + +
+
+
+ + + + diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/data/src/edit.htm b/libraries/ESP8266WebServer/examples/FSWebServer/data/src/edit.htm new file mode 100644 index 000000000..cfd70baf7 --- /dev/null +++ b/libraries/ESP8266WebServer/examples/FSWebServer/data/src/edit.htm @@ -0,0 +1,3 @@ +ESP Editor
diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/data/src/graphs-src.js b/libraries/ESP8266WebServer/examples/FSWebServer/data/src/graphs-src.js new file mode 100644 index 000000000..23a295587 --- /dev/null +++ b/libraries/ESP8266WebServer/examples/FSWebServer/data/src/graphs-src.js @@ -0,0 +1,281 @@ +/* + FSWebServer - Sample Graphing Library + + Copyright (c) 2015 Hristo Gochkov. All rights reserved. + This file is part of the ESP8266WebServer library for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +function ce(t){ return document.createElement(t); } +function ac(a,b){ a.appendChild(b); } + +function createGraph(el, t, w, h, l, m, ib, tc, cb){ + if(typeof el === "undefined" || !el) return null; + if(typeof ib === "undefined" || !ib) ib = false; + w = (w>360)?w:360; + h = (h<100)?100:h; + var vs = new Array(); + var bgc = "black"; + var lc = (typeof tc === "undefined" && tc)?"yellow":tc; + var bc = "#444"; + var vcb = (typeof cb === "undefined" && cb)?null:cb; + var minV = m; + var maxV = 0; + var sv = 1; + var ov = l; + var gh = h+20; + + el.style.display = "block"; + el.style.backgroundColor = "#eee"; + el.style.border = "1px solid "+bc; + el.style.padding = "5px"; + el.style.margin = "5px"; + el.style.width = (w+2)+"px"; + + var g = ce("canvas"); + g.style.border = "1px solid "+bc; + g.style.marginTop = "5px"; + g.width = w; + g.height = gh; + + var c = g.getContext("2d"); + + var sl = ce("span"); + sl.innerText = "Scale: "; + sl.style.paddingLeft = "5px"; + + var st = ce("input"); + st.type = "text"; + st.size = 3; + st.value = sv; + st.onchange = function(e){ sv = st.value; }; + + var sm = ce("button"); + sm.innerText = "-"; + sm.onclick = function(e){ if(sv > 1) sv--; st.value = sv; }; + + var sp = ce("button"); + sp.innerText = "+"; + sp.onclick = function(e){ sv++; st.value = parseInt(sv); }; + + var ol = ce("span"); + ol.innerText = "Offset: "; + ol.style.paddingLeft = "5px"; + + var ot = ce("input"); + ot.type = "text"; + ot.size = 5; + ot.value = ov; + ot.onchange = function(e){ ov = parseInt(ot.value); }; + + var om = ce("button"); + om.innerText = "-"; + om.onclick = function(e){ if(ov > l) ov--; ot.value = ov; }; + + var op = ce("button"); + op.innerText = "+"; + op.onclick = function(e){ if(ov < m) ov++; ot.value = ov; }; + + ac(el,sl); + ac(el,sm); + ac(el,st); + ac(el,sp); + ac(el,ol); + ac(el,om); + ac(el,ot); + ac(el,op); + ac(el,ce("br")); + ac(el,g); + + function scv(v){ + if(v <= ov) return 0; + if(v > (((m - l) / sv) + ov)) return h; + return Math.round((v - ov) * (h / ((m - l) / sv))); + } + + g.add = function(v){ + if(vcb) v = vcb(v); + vs.push(v); + if(v < minV) minV = v; + if(v > maxV) maxV = v; + if(vs.length > w) vs.shift(); + c.canvas.width = w; + c.lineWidth = 1; + c.shadowBlur=2; + c.shadowColor="black"; + + c.fillStyle = bc; + c.fillRect(0, 0, w, 20); + c.fillStyle = lc; + c.font = "14px Verdana"; + var header = t+": "+(vs[vs.length - 1])+" | Min: "+minV+" | Max: "+maxV; + c.fillText(header,5,15); + + c.fillStyle = bgc; + c.fillRect(0, 20, w, gh); + c.strokeStyle = lc; + + for(var i = 0; i < vs.length; i++){ + if(ib){ + c.moveTo(i, gh); + c.lineTo(i, gh - scv(vs[i])); + c.stroke(); + continue; + } + if(i === 0){ + c.moveTo(0, gh - scv(vs[0])); + c.lineTo(0, gh - scv(vs[0])); + c.stroke(); + } else { + c.moveTo((i - 1), gh - scv(vs[i - 1])); + c.lineTo(i, gh - scv(vs[i])); + c.stroke(); + } + } + c.fillStyle = lc; + c.font = "10px Verdana"; + c.fillText(ov, 2, gh - 5); + c.fillText(Math.round((((m - l) / sv) + ov) * 10) / 10, 2, 30); + }; + return g; +} + +function createDigiGraph(el, t, w, h, m, tc){ + if(typeof el === "undefined" || !el) return null; + w = (w>360)?w:360; + h = (h<20)?20:h; + var vs = new Array(); + var bgc = "black"; + var lc = (typeof tc === "undefined" && tc)?"pink":tc; + var bc = "#444"; + var sv = 1; + var gh = h+20; + + el.style.display = "block"; + el.style.backgroundColor = "#eee"; + el.style.border = "1px solid "+bc; + el.style.padding = "5px"; + el.style.margin = "5px"; + el.style.width = (w+2)+"px"; + + var g = ce("canvas"); + g.style.border = "1px solid "+bc; + g.style.marginTop = "5px"; + g.width = w; + g.height = gh; + + var c = g.getContext("2d"); + + var sl = ce("span"); + sl.innerText = "Scale: "; + sl.style.paddingLeft = "5px"; + + var st = ce("input"); + st.type = "text"; + st.size = 3; + st.value = sv; + st.onchange = function(e){ sv = st.value; }; + + var sm = ce("button"); + sm.innerText = "-"; + sm.onclick = function(e){ if(sv > 1) sv--; st.value = sv; }; + + var sp = ce("button"); + sp.innerText = "+"; + sp.onclick = function(e){ sv++; st.value = parseInt(sv); }; + + ac(el,sl); + ac(el,sm); + ac(el,st); + ac(el,sp); + ac(el,ce("br")); + ac(el,g); + + function gpos(p){ + var each = Math.floor(((h - ((m.length - 1)*2))/m.length)); + var s = (p * 2) + (p * each); + return [s, s + each]; + } + + function gact(i,p){ + return ((vs[i] & (1 << m[p])) !== 0);; + } + + var vc = ["aqua","yellow","#FF4500","#00FF7F","orange","cyan","magenta","#7FFF00","#FAF0E6","#00CED1","#FFD700","#EE82EE","#00FF00","#00BFFF","#FF4500","#EEE8AA","#FF1493"]; + + g.add = function(v){ + vs.push(v); + if(vs.length > w) vs.shift(); + c.canvas.width = w; + c.lineWidth=1; + c.shadowBlur=2; + c.shadowColor="black"; + + c.fillStyle = bc; + c.fillRect(0, 0, w, 20); + c.fillStyle = lc; + c.font = "14px Verdana"; + c.fillText(t,5,15); + + c.fillStyle = bgc; + c.fillRect(0, 20, w, gh); + + c.strokeStyle = bc; + c.lineWidth = 1; + c.shadowBlur=0; + c.shadowColor=""; + for(var p=0;p35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('8 H(t){K 21.1Y(t)}8 9(a,b){a.1S(b)}8 1O(b,t,w,h,l,m,d,f,j){6(Q b==="S"||!b)K 1f;6(Q d==="S"||!d)d=1P;w=(w>1b)?w:1b;h=(h<1N)?1N:h;4 k=1M 1L();4 n="V";4 o=(Q f==="S"&&f)?"1J":f;4 p="#1I";4 q=(Q j==="S"&&j)?1f:j;4 r=m;4 s=0;4 u=1;4 x=l;4 y=h+20;b.7.1H="1G";b.7.1F="#1s";b.7.1c="12 11 "+p;b.7.1D="N";b.7.1C="N";b.7.P=(w+2)+"1B";4 g=H("1a");g.7.1c="12 11 "+p;g.7.1z="N";g.P=w;g.1w=y;4 c=g.1v("2d");4 z=H("1j");z.M="1u: ";z.7.1m="N";4 A=H("1p");A.1i="1r";A.1e=3;A.I=u;A.1h=8(e){u=A.I};4 B=H("T");B.M="-";B.U=8(e){6(u>1)u--;A.I=u};4 C=H("T");C.M="+";C.U=8(e){u++;A.I=1n(u)};4 D=H("1j");D.M="1Q: ";D.7.1m="N";4 E=H("1p");E.1i="1r";E.1e=5;E.I=x;E.1h=8(e){x=1n(E.I)};4 F=H("T");F.M="-";F.U=8(e){6(x>l)x--;E.I=x};4 G=H("T");G.M="+";G.U=8(e){6(x(((m-l)/u)+x))K h;K 1d.1o((v-x)*(h/((m-l)/u)))}g.1x=8(v){6(q)v=q(v);k.1y(v);6(vs)s=v;6(k.L>w)k.1A();c.1a.P=w;c.1g=1;c.17=2;c.Y="V";c.O=p;c.J(0,0,w,20);c.O=o;c.X="1q Z";4 a=t+": "+(k[k.L-1])+" | 1U: "+r+" | 23: "+s;c.W(a,5,15);c.O=n;c.J(0,20,w,y);c.1K=o;18(4 i=0;i1b)?w:1b;h=(h<20)?20:h;4 l=1M 1L();4 n="V";4 o=(Q k==="S"&&k)?"1X":k;4 q="#1I";4 r=1;4 u=h+20;j.7.1H="1G";j.7.1F="#1s";j.7.1c="12 11 "+q;j.7.1D="N";j.7.1C="N";j.7.P=(w+2)+"1B";4 g=H("1a");g.7.1c="12 11 "+q;g.7.1z="N";g.P=w;g.1w=u;4 c=g.1v("2d");4 x=H("1j");x.M="1u: ";x.7.1m="N";4 y=H("1p");y.1i="1r";y.1e=3;y.I=r;y.1h=8(e){r=y.I};4 z=H("T");z.M="-";z.U=8(e){6(r>1)r--;y.I=r};4 A=H("T");A.M="+";A.U=8(e){r++;y.I=1n(r)};9(j,x);9(j,z);9(j,y);9(j,A);9(j,H("1E"));9(j,g);8 1l(p){4 a=1d.1Z(((h-((m.L-1)*2))/m.L));4 s=(p*2)+(p*a);K[s,s+a]}8 1k(i,p){K((l[i]&(1<w)l.1A();c.1a.P=w;c.1g=1;c.17=2;c.Y="V";c.O=q;c.J(0,0,w,20);c.O=o;c.X="1q Z";c.W(t,5,15);c.O=n;c.J(0,20,w,u);c.1K=q;c.1g=1;c.17=0;c.Y="";18(4 p=0;p + + + + + ESP Monitor + + + + +
+ + + + +
+
+
+
+ + \ No newline at end of file diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 9f2b16480..0b553b518 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -88,6 +88,13 @@ template size_t streamFile(T &file, String contentType){ head += file.size(); head += "\r\nConnection: close"; head += "\r\nAccess-Control-Allow-Origin: *"; + if( + String(file.name()).endsWith(".gz") && + contentType != "application/x-gzip" && + contentType != "application/octet-stream" + ){ + head += "\r\nContent-Encoding: gzip"; + } head += "\r\n\r\n"; _currentClient.print(head); head = String();