How to Serve Html Files From SD Card on ESP32
by iamrachelle in Circuits > Arduino
8944 Views, 12 Favorites, 0 Comments
How to Serve Html Files From SD Card on ESP32
In this tutorial, we will setup the ESP32 as a server which can be accessed by going to its IP address.
SOFTWARE:
Supplies
Ready Your HTML File
Ready your HTML file on any text editor you use. I use VSCODE and here's the html I used. The image tag <img> source (src) should be "/" + path . For example, to show the image named "plants.jpg", the image tag is as follows:<img class="picture" style="max-width:100%;" src="/plants.jpg">. Change all source tags to be similar to your path.
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Greenhouse</title>
<meta name="description" content="Greenhouse">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.center {
margin: auto;
text-align: center;
}
.left {
float: left;
}
.right {
float: right;
}
.card {
border-style: solid;
border-width: 1px;
border-color: #F7DC6F;
padding: 5px;
margin: 20px;
}
.container {
position: relative;
}
.top-left {
position: absolute;
top: 8px;
left: 16px;
text-align: left;
}
.hide {
position: absolute;
opacity: 0;
}
input[type=checkbox]+label {
color: rgb(129, 129, 129);
font-style: italic;
padding: 5px;
}
input[type=checkbox]:checked+label {
color: #000000;
font-style: normal;
padding: 5px;
}
</style>
</head>
<body class="center" onload="onload()" style="font-family: Verdana, Geneva, Tahoma, sans-serif;">
<h1 class="center">Pulilan Greenhouse</h1>
<div class=card style="border-color: #ffffff;">
<img class="picture" id="slideshow" src="/picture/1.jpg" style="max-width:100%;">
<p> </p>
<button class="left" id="prev">❮ Prev</button>
<button class="right" id="next">❯ Next</button>
<button href="/picture/1.jpg" download id="download">Download</button>
<button id="take_photo">Take Photo</button>
</div>
<div class=card>
<div style="background-color:#F7DC6F;">
STATUS
</div>
<div class="container">
<img class="picture" style="max-width:100%;" src="/plants.jpg">
<div class="top-left">
<p id="temp"> Temp: 0 ℃ </p>
<p id="RH"> RH: 0 % </p>
</div>
</div>
</div>
<div class=card>
<div style="background-color:#F7DC6F;">
CONTROL
</div>
<table style="width: 100%;">
<tbody>
<tr>
<td>
<input class="hide" type="checkbox" onchange="relay(this.id)" id="1">
<label for="1">Relay 1</label>
</td>
<td>
<input class="hide" type="checkbox" onchange="relay(this.id)" id="2">
<label for="2">Relay 2</label>
</td>
<td>
<input class="hide" type="checkbox" onchange="relay(this.id)" id="3">
<label for="3">Relay 3</label>
</td>
</tr>
<tr>
<td>
<input class="hide" type="checkbox" onchange="relay(this.id)" id="4">
<label for="4">Relay 4</label>
</td>
<td>
<input class="hide" type="checkbox" onchange="relay(this.id)" id="5">
<label for="5">Relay 5</label>
</td>
<td>
<input class="hide" type="checkbox" onchange="relay(this.id)" id="6">
<label for="6">Relay 6</label>
</td>
</tr>
</tbody>
</table>
</div>
<div class=card>
<div style="background-color:#F7DC6F;text-align: center;">
SCHEDULE
</div>
<div class="container" style="text-align: left;">
Time: <input type="time"><br>
Duration: <input type="number" style=" width:50px;"> mins <br>
Days: <span class="days">
<input class="hide" onchange="day_selection(this.id)" id="sun" name="sun" type="checkbox" value="0">
<label for="sun">S</label>
<input class="hide" onchange="day_selection(this.id)" id="mon" type="checkbox" value="0">
<label for="mon">M</label>
<input class="hide" onchange="day_selection(this.id)" id="tue" type="checkbox" value="0">
<label for="tue">T</label>
<input class="hide" onchange="day_selection(this.id)" id="wed" type="checkbox" value="0">
<label for="wed">W</label>
<input class="hide" onchange="day_selection(this.id)" id="thur" type="checkbox" value="0">
<label for="thur">T</label>
<input class="hide" onchange="day_selection(this.id)" id="fri" type="checkbox" value="0">
<label for="fri">F</label>
<input class="hide" onchange="day_selection(this.id)" id="sat" type="checkbox" value="0">
<label for="sat">S</label>
</span>
</div>
</div>
<script>
function onload() {
console.log("loaded");}
var picture = 1;
var next = document.getElementById("next");
next.addEventListener("click", function () {
picture += 1;
console.log("picture", picture);
document.getElementById("slideshow").src = "/picture/" + picture + ".jpg";
});
var download = document.getElementById("download");
download.addEventListener("click", function () {
console.log("downlaod", document.getElementById("slideshow").src);
window.open(document.getElementById("slideshow").src)
});
var prev = document.getElementById("prev");
prev.addEventListener("click", function () {
picture -= 1;
console.log("picture", picture);
document.getElementById("slideshow").src = "/picture/" + picture + ".jpg";;
});
var take_photo = document.getElementById("take_photo");
take_photo.addEventListener("click",function(){
});
function relay(id) {
console.log(id, document.getElementById(id).checked);
}
function day_selection(id) {
console.log("id", id, document.getElementById(id).value);
}
</script>
</body>
</html>
Prepare Your SD Card
- Format your sd card as shown in the picture
- Place Your index.html file and pictures. Ensure the picture filenames are the same that is included in your html file.
ESP32 Web Server Code
This Code serves HTML File from the SD Card built in with the ESP32 Dev Module I'm using. Upload it on your ESP32 and go to the ip address displayed on your serial monitor. While uploading press the flash button continuously and reset button once while connecting until it starts writing (uploading).
//Load necessaries libraries from https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/src/WiFi.h
#include <WiFi.h> // Add Wifi Capabilities
#include <WebServer.h> //To make a simple webserver that accomodates only one simultaneous client
#include "FS.h" //To access the file system
#include "SD_MMC.h" //To access the SD Card
//replace with your network credentials
#ifndef STASSID
#define STASSID "replace_with_your_ssid"<br>#define STAPSK "replace_with_your_ssid_pass"<br>
#endif
const char* ssid = STASSID;
const char* password = STAPSK;
WebServer server(80); //Set the server at port 80
void setup() {
Serial.begin(115200); //Set the baud rate for serial communication with ESP
/////////////////sdcard
if (!SD_MMC.begin()) { //initialize SD Card
Serial.println("SD Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType(); //get sd card type
if (cardType == CARD_NONE) { //check if the sd card presence
Serial.println("No SD Card attached");
return;
}
////////////////Wifi
WiFi.mode(WIFI_STA); //Connect it to a wifi Network
WiFi.begin(ssid, password); //with the ssid and password defined earlier
Serial.println("");
while (WiFi.status() != WL_CONNECTED) {// Wait for connection
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP()); //prints the local ip given to the esp by the router
////////////////Server
server.onNotFound(handleRoot); //Calls the function handleRoot regardless of the server uri ex.(192.168.100.110/edit server uri is "/edit")
server.begin();//starts the server
Serial.println("HTTP server started");
}
void handleRoot() {
/* SD_MMC pertains to the sd card "memory". It is save as a
variable at the same address given to fs in the fs library
with "FS" class to enable the file system wrapper to make
changes on the sd cards memory */
fs::FS &fs = SD_MMC;
String path = server.uri(); //saves the to a string server uri ex.(192.168.100.110/edit server uri is "/edit")
Serial.print("path "); Serial.println(path);
//To send the index.html when the serves uri is "/"
if (path.endsWith("/")) {
path += "index.html";
}
//gets the extension name and its corresponding content type
String contentType = getContentType(path);
Serial.print("contentType ");
Serial.println(contentType);
File file = fs.open(path, "r"); //Open the File with file name = to path with intention to read it. For other modes see <a href="https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html" style="font-size: 13.5px;"> https://arduino-esp8266.readthedocs.io/en/latest/...</a>
size_t sent = server.streamFile(file, contentType); //sends the file to the server references from <a href="https://github.com/espressif/arduino-esp32/blob/master/libraries/WebServer/src/WebServer.h" style="font-size: 13.5px;"> https://arduino-esp8266.readthedocs.io/en/latest/...</a>
file.close(); //Close the file
}
//This functions returns a String of content type
String getContentType(String filename) {
if (server.hasArg("download")) { // check if the parameter "download" exists
return "application/octet-stream";
} else if (filename.endsWith(".htm")) { //check if the string filename ends with ".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";
}
void loop() {
/*Waits For connection on the server and is responsible for
sending and receivingdata request on server uri from the client*/
server.handleClient();
}Next Steps
In this tutorial, I’ve shown you how to build a web server with the ESP32. In combination with the websockest library for arduino, I've used this to take make a Dashboard that shows ESP32 CAM pictures and sensors data fro my greenhouse. Hope it worked fro you! Feel free to ask for questions! Good luck makers! :)