Skip to content

Commit 4c07879

Browse files
author
Me No Dev
committed
Add SPIFFS WebServer Example
1 parent 1c1a67f commit 4c07879

File tree

5 files changed

+336
-0
lines changed

5 files changed

+336
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
/*
2+
FSWebServer - Example WebServer with SPIFFS backend for esp8266
3+
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
4+
This file is part of the ESP8266WebServer library for Arduino environment.
5+
6+
This library is free software; you can redistribute it and/or
7+
modify it under the terms of the GNU Lesser General Public
8+
License as published by the Free Software Foundation; either
9+
version 2.1 of the License, or (at your option) any later version.
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with this library; if not, write to the Free Software
16+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
18+
upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE)
19+
or you can upload the contents of a folder if you CD in that folder and run the following command:
20+
for file in `ls -A1`; do curl -F "file=@$PWD/$file" esp8266fs.local/edit; done
21+
22+
access the sample web page at http://esp8266fs.local
23+
edit the page by going to http://esp8266fs.local/edit
24+
*/
25+
#include <ESP8266WiFi.h>
26+
#include <WiFiClient.h>
27+
#include <ESP8266WebServer.h>
28+
#include <ESP8266mDNS.h>
29+
#include <FS.h>
30+
31+
#define DBG_OUTPUT_PORT Serial
32+
33+
const char* ssid = "wifi-ssid";
34+
const char* password = "wifi-password";
35+
const char* host = "esp8266fs";
36+
37+
ESP8266WebServer server(80);
38+
//holds the current upload
39+
File fsUploadFile;
40+
41+
//format bytes
42+
String formatBytes(size_t bytes){
43+
if (bytes < 1024){
44+
return String(bytes)+"B";
45+
} else if(bytes < (1024 * 1024)){
46+
return String(bytes/1024.0)+"KB";
47+
} else if(bytes < (1024 * 1024 * 1024)){
48+
return String(bytes/1024.0/1024.0)+"MB";
49+
} else {
50+
return String(bytes/1024.0/1024.0/1024.0)+"GB";
51+
}
52+
}
53+
54+
String getContentType(String filename){
55+
if(server.hasArg("download")) return "application/octet-stream";
56+
else if(filename.endsWith(".htm")) return "text/html";
57+
else if(filename.endsWith(".html")) return "text/html";
58+
else if(filename.endsWith(".css")) return "text/css";
59+
else if(filename.endsWith(".js")) return "application/javascript";
60+
else if(filename.endsWith(".png")) return "image/png";
61+
else if(filename.endsWith(".gif")) return "image/gif";
62+
else if(filename.endsWith(".jpg")) return "image/jpeg";
63+
else if(filename.endsWith(".ico")) return "image/x-icon";
64+
else if(filename.endsWith(".xml")) return "text/xml";
65+
else if(filename.endsWith(".pdf")) return "application/x-pdf";
66+
else if(filename.endsWith(".zip")) return "application/x-zip";
67+
else if(filename.endsWith(".gz")) return "application/x-gzip";
68+
return "text/plain";
69+
}
70+
71+
bool handleFileRead(String path){
72+
DBG_OUTPUT_PORT.println("handleFileRead: " + path);
73+
if(path.endsWith("/")) path += "index.htm";
74+
String contentType = getContentType(path);
75+
String pathWithGz = path + ".gz";
76+
if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){
77+
if(SPIFFS.exists(pathWithGz))
78+
path += ".gz";
79+
File file = SPIFFS.open(path, "r");
80+
size_t sent = server.streamFile(file, contentType);
81+
file.close();
82+
return true;
83+
}
84+
return false;
85+
}
86+
87+
void handleFileUpload(){
88+
if(server.uri() != "/edit") return;
89+
HTTPUpload& upload = server.upload();
90+
if(upload.status == UPLOAD_FILE_START){
91+
String filename = upload.filename;
92+
if(!filename.startsWith("/")) filename = "/"+filename;
93+
DBG_OUTPUT_PORT.print("handleFileUpload Name: "); DBG_OUTPUT_PORT.println(filename);
94+
fsUploadFile = SPIFFS.open(filename, "w");
95+
filename = String();
96+
} else if(upload.status == UPLOAD_FILE_WRITE){
97+
//DBG_OUTPUT_PORT.print("handleFileUpload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize);
98+
if(fsUploadFile)
99+
fsUploadFile.write(upload.buf, upload.currentSize);
100+
} else if(upload.status == UPLOAD_FILE_END){
101+
if(fsUploadFile)
102+
fsUploadFile.close();
103+
DBG_OUTPUT_PORT.print("handleFileUpload Size: "); DBG_OUTPUT_PORT.println(upload.totalSize);
104+
}
105+
}
106+
107+
void handleFileDelete(){
108+
if(server.args() == 0) return server.send(500, "text/plain", "BAD ARGS");
109+
String path = server.arg(0);
110+
DBG_OUTPUT_PORT.println("handleFileDelete: " + path);
111+
if(path == "/")
112+
return server.send(500, "text/plain", "BAD PATH");
113+
if(!SPIFFS.exists(path))
114+
return server.send(404, "text/plain", "FileNotFound");
115+
SPIFFS.remove(path);
116+
server.send(200, "text/plain", "");
117+
path = String();
118+
}
119+
120+
void handleFileCreate(){
121+
if(server.args() == 0)
122+
return server.send(500, "text/plain", "BAD ARGS");
123+
String path = server.arg(0);
124+
DBG_OUTPUT_PORT.println("handleFileCreate: " + path);
125+
if(path == "/")
126+
return server.send(500, "text/plain", "BAD PATH");
127+
if(SPIFFS.exists(path))
128+
return server.send(500, "text/plain", "FILE EXISTS");
129+
File file = SPIFFS.open(path, "w");
130+
if(file)
131+
file.close();
132+
else
133+
return server.send(500, "text/plain", "CREATE FAILED");
134+
server.send(200, "text/plain", "");
135+
path = String();
136+
}
137+
138+
void handleFileList() {
139+
if(!server.hasArg("dir")) {server.send(500, "text/plain", "BAD ARGS"); return;}
140+
141+
String path = server.arg("dir");
142+
DBG_OUTPUT_PORT.println("handleFileList: " + path);
143+
Dir dir = SPIFFS.openDir(path);
144+
path = String();
145+
146+
String output = "[";
147+
while(dir.next()){
148+
File entry = dir.openFile("r");
149+
if (output != "[") output += ',';
150+
bool isDir = false;
151+
output += "{\"type\":\"";
152+
output += (isDir)?"dir":"file";
153+
output += "\",\"name\":\"";
154+
output += String(entry.name()).substring(1);
155+
output += "\"}";
156+
entry.close();
157+
}
158+
159+
output += "]";
160+
server.send(200, "text/json", output);
161+
}
162+
163+
void setup(void){
164+
DBG_OUTPUT_PORT.begin(115200);
165+
DBG_OUTPUT_PORT.print("\n");
166+
DBG_OUTPUT_PORT.setDebugOutput(true);
167+
SPIFFS.begin();
168+
{
169+
Dir dir = SPIFFS.openDir("/");
170+
while (dir.next()) {
171+
String fileName = dir.fileName();
172+
size_t fileSize = dir.fileSize();
173+
DBG_OUTPUT_PORT.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str());
174+
}
175+
DBG_OUTPUT_PORT.printf("\n");
176+
}
177+
178+
179+
//WIFI INIT
180+
DBG_OUTPUT_PORT.printf("Connecting to %s\n", ssid);
181+
if (String(WiFi.SSID()) != String(ssid)) {
182+
WiFi.begin(ssid, password);
183+
}
184+
185+
while (WiFi.status() != WL_CONNECTED) {
186+
delay(500);
187+
DBG_OUTPUT_PORT.print(".");
188+
}
189+
DBG_OUTPUT_PORT.println("");
190+
DBG_OUTPUT_PORT.print("Connected! IP address: ");
191+
DBG_OUTPUT_PORT.println(WiFi.localIP());
192+
193+
MDNS.begin(host);
194+
DBG_OUTPUT_PORT.print("Open http://");
195+
DBG_OUTPUT_PORT.print(host);
196+
DBG_OUTPUT_PORT.println(".local/edit to see the file browser");
197+
198+
199+
//SERVER INIT
200+
//list directory
201+
server.on("/list", HTTP_GET, handleFileList);
202+
//load editor
203+
server.on("/edit", HTTP_GET, [](){
204+
if(!handleFileRead("/edit.htm")) server.send(404, "text/plain", "FileNotFound");
205+
});
206+
//create file
207+
server.on("/edit", HTTP_PUT, handleFileCreate);
208+
//delete file
209+
server.on("/edit", HTTP_DELETE, handleFileDelete);
210+
//called after file upload
211+
server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); });
212+
//called when a file is received inside POST data
213+
server.onFileUpload(handleFileUpload);
214+
215+
//called when the url is not defined here
216+
//use it to load content from SPIFFS
217+
server.onNotFound([](){
218+
if(!handleFileRead(server.uri()))
219+
server.send(404, "text/plain", "FileNotFound");
220+
});
221+
222+
//get heap status, analog input value and all GPIO statuses in one json call
223+
server.on("/all", HTTP_GET, [](){
224+
String json = "{";
225+
json += "\"heap\":"+String(ESP.getFreeHeap());
226+
json += ", \"analog\":"+String(analogRead(A0));
227+
json += ", \"gpio\":"+String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16)));
228+
json += "}";
229+
server.send(200, "text/json", json);
230+
json = String();
231+
});
232+
server.begin();
233+
DBG_OUTPUT_PORT.println("HTTP server started");
234+
235+
}
236+
237+
void loop(void){
238+
server.handleClient();
239+
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<!--
2+
FSWebServer - Example Index Page
3+
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
4+
This file is part of the ESP8266WebServer library for Arduino environment.
5+
6+
This library is free software; you can redistribute it and/or
7+
modify it under the terms of the GNU Lesser General Public
8+
License as published by the Free Software Foundation; either
9+
version 2.1 of the License, or (at your option) any later version.
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with this library; if not, write to the Free Software
16+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
-->
18+
<!DOCTYPE html>
19+
<html>
20+
<head>
21+
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
22+
<title>ESP Monitor</title>
23+
<script type="text/javascript" src="graphs.js"></script>
24+
<script type="text/javascript">
25+
var heap,temp,digi;
26+
var reloadPeriod = 1000;
27+
var running = false;
28+
29+
function loadValues(){
30+
if(!running) return;
31+
var xh = new XMLHttpRequest();
32+
xh.onreadystatechange = function(){
33+
if (xh.readyState == 4){
34+
if(xh.status == 200) {
35+
var res = JSON.parse(xh.responseText);
36+
heap.add(res.heap);
37+
temp.add(res.analog);
38+
digi.add(res.gpio);
39+
if(running) setTimeout(loadValues, reloadPeriod);
40+
} else running = false;
41+
}
42+
};
43+
xh.open("GET", "/all", true);
44+
xh.send(null);
45+
};
46+
47+
function run(){
48+
if(!running){
49+
running = true;
50+
loadValues();
51+
}
52+
}
53+
54+
function onBodyLoad(){
55+
var refreshInput = document.getElementById("refresh-rate");
56+
refreshInput.value = reloadPeriod;
57+
refreshInput.onchange = function(e){
58+
var value = parseInt(e.target.value);
59+
reloadPeriod = (value > 0)?value:0;
60+
e.target.value = reloadPeriod;
61+
}
62+
var stopButton = document.getElementById("stop-button");
63+
stopButton.onclick = function(e){
64+
running = false;
65+
}
66+
var startButton = document.getElementById("start-button");
67+
startButton.onclick = function(e){
68+
run();
69+
}
70+
71+
// Example with 10K thermistor
72+
//function calcThermistor(v) {
73+
// var t = Math.log(((10230000 / v) - 10000));
74+
// t = (1/(0.001129148+(0.000234125*t)+(0.0000000876741*t*t*t)))-273.15;
75+
// return (t>120)?0:Math.round(t*10)/10;
76+
//}
77+
//temp = createGraph(document.getElementById("analog"), "Temperature", 100, 128, 10, 40, false, "cyan", calcThermistor);
78+
79+
temp = createGraph(document.getElementById("analog"), "Analog Input", 100, 128, 0, 1023, false, "cyan");
80+
heap = createGraph(document.getElementById("heap"), "Current Heap", 100, 125, 0, 30000, true, "orange");
81+
digi = createDigiGraph(document.getElementById("digital"), "GPIO", 100, 146, [0, 4, 5, 16], "gold");
82+
run();
83+
}
84+
</script>
85+
</head>
86+
<body id="index" style="margin:0; padding:0;" onload="onBodyLoad()">
87+
<div id="controls" style="display: block; border: 1px solid rgb(68, 68, 68); padding: 5px; margin: 5px; width: 362px; background-color: rgb(238, 238, 238);">
88+
<label>Period (ms):</label>
89+
<input type="number" id="refresh-rate"/>
90+
<input type="button" id="start-button" value="Start"/>
91+
<input type="button" id="stop-button" value="Stop"/>
92+
</div>
93+
<div id="heap"></div>
94+
<div id="analog"></div>
95+
<div id="digital"></div>
96+
</body>
97+
</html>

0 commit comments

Comments
 (0)