Weekly tutorial: WebServer.h and ESP32
By Savalio (Slightly edited by Swee post-migration to Jekyll)
If you want to find more in-depth tutorial for this cool web server library you found, you’re in the right place! I’ll teach you everything you need to make your own STA-mode web server!
Introduction
This library is like ESPAsyncWebServer.h
, but much more simple.
It takes less lines of code and less parameters to write code with the same functionality in WebServer.h
than in the ESPAsyncWebServer.h
. So, let’s dive in!
Part 1: Hardware prep
You won’t need much for this project since it’s more software-focused one. Supplies:
-
ESP32-compatible board. I am using my favorite teeny-tiny Xiao ESP32-S3 Sense for this, but it can work with any ESP32 board.
-
Programming cable (duh)
Optional:
- External LED
NOTE: If you don’t want to change code much, use an ESP32 board with a built-in user LED.
Part 2: Code Prep and Functionality
Now that you have your beloved ESP32, we can get to the code! Here’s the code, just paste it into the Arduino IDE and change the ssid
and password
variables to your credentials.
/*
CODE BY SAVALIO
https://blogs.swee.codes/team#Savalio
*/
#include <WiFi.h> // All the nessesary libraries
#include <WebServer.h>
// CHANGE TO YOUR SSID AND PASSWORD //
const char* ssid = "..."; // WiFi name
const char* password = "..."; // WiFi password
bool LEDState = false; // Sets up a boolean to control the LED's state
String displayText = "You have not set the display text yet..."; // Sets up a string for the display text
WebServer server(80); // Declares the WebServer object to use the functions
void setup() {
Serial.begin(115200); // Begins the Serial monitor
pinMode(LED_BUILTIN, OUTPUT); // Sets the pin of the built-in LED to output
Serial.println("Connecting to WiFi:"); // Prints out the name of the network ESP32 is trying to connect
Serial.println(ssid);
WiFi.begin(ssid, password); // Connect to your local WiFi network
// Checks if your ESP32 is connected to WiFi network
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("Connected!");
Serial.println("Local IP:"); Serial.println(WiFi.localIP()); // Prints out the Local IP so you can view the web page
server.on("/", handle_OnConnect); // If user is on the home page, then call handle_OnConnect
server.on("/setLEDState", handle_SetLEDState); // If the user is on the setLEDState page, then call handle_SetLEDState
server.on("/setHomeText", handle_SetHomeText); // If the user is on the setHomeText page, then call handle_SetHomeText
server.onNotFound(handle_NotFound); // If the user is on any other page, tell them that the page was not found
server.begin(); // Gets the server up and running
Serial.println("HTTP server started");
}
void loop() {
server.handleClient(); // THIS MUST BE IN THE LOOP! IT HANDLES THE CLIENT
if (LEDState) { // Switches on/off the LED based off of the LEDState boolean
digitalWrite(LED_BUILTIN, HIGH);
} else {
digitalWrite(LED_BUILTIN, LOW);
}
}
void handle_OnConnect() {
String html = String("<center> \n") + String("<h1>ESP32 Web Server tutorial example</h1>");
html += String("<h4>Display text: ") + displayText + String("</h4>"); // Adding the user set display text at the top
html += R"(
<form action="/setLEDState">
<input type="submit" value="Turn on/off the built-in LED">
</form>
<form action="/setHomeText">
<label for="txt">Display text:</label>
<input type="text" id="txt" name="txt" placeholder="Blahblahblah...">
<input type="submit" value="Set text">
</form>
</center>
)";
server.send(200, "text/html", html); // Sends the html web page to the user
}
void handle_SetLEDState() {
String html; // Defines the html object in the function so errors won't scare you
if (LEDState) { // Switches the LED state
html = R"(
<center>
<h1>Succesfully turned off the Built-in LED!</h1>
<form action="/">
<input type="submit" value="Go home">
</form>
</center>
)";
LEDState = false;
} else {
html = R"(
<center>
<h1>Succesfully turned on the Built-in LED!</h1>
<form action="/">
<input type="submit" value="Go home">
</form>
</center>
)";
LEDState = true;
}
server.send(200, "text/html", html); // Sends the html web page to the user
}
void handle_SetHomeText() {
displayText = server.arg("txt"); // Sets the display text to the server argument txt
String html = R"(
<center>
<h1>Succesfully turned off the Built-in LED!</h1>
<form action="/">
<input type="submit" value="Go home">
</form>
</center>
)";
server.send(200, "text/html", html); // Sends the html web page to the user
}
void handle_NotFound() {
server.send(200, "text/html", "<h1>404: Page Not Found</h1>");
}
Now, upload the code to the ESP32, and look at the serial monitor and search for the local IP. It should look something like this:
Local IP:
10.0.0.90
Type in the IP into your browser window. It should look like this:
If you click on the top button, you will see this:
Now, look at your ESP32. It should look like this:
On the other hand, if you enter “Hello!” into the input field and press “Set Text” button and press “Go Home” in the next web page, you should see this:
Part 3: Code Explanation
Part 3.1:
void setup()
In this function, we connect to the WiFi network with the WiFi.begin(ssid, password)
function, and wait until we connect and then print out the Local IP.
Then, we set the functionality for the web pages and begin the web server with this chunk of code:
server.on("/", handle_OnConnect);
server.on("/setLEDState", handle_SetLEDState);
server.on("/setHomeText", handle_SetHomeText);
server.onNotFound(handle_NotFound);
server.begin();
If you have noticed, the server.on function calls the functions without requiring parenthesis, which inhibits you from providing any variables, which you, most likely, will never need.
Here’s the structure of the functions we’ve discussed:
server.on(String page, functionName);
server.onNotFound(functionName);
Part 3.2:
void loop()
There’s nothing much to talk about. You can see that there’s server.handleClient()
function, which has no arguments. It it self-explanatory: it handles clients (shocking).
Part 3.3: Special functions
Now we’re in the interesting territory. We have the rawliteral String
named html
and this function:
server.send(200, "text/html", html)
The first argument is the HTTP status code, 200
meaning it was successful.
The second argument is the mimetype (if you’ve played with Linux before, you’ve probably heard of this), it tells the browser what type of file the path is using, text/html
is the mimetype for HTML. (Plain text mimetype will be text/plain
)
The last argument is the content of the file, it is self-explanatory.
server.send(200, String fileType, String content);
And in the function handle_SetHomeText()
you will find this function setting the displayText String:
displayText = server.arg("txt");
This function searches for an argument you define in the parenthesis.
The arguments are defined after the question mark like in this screenshot of a YouTube video argument (e.g. https://youtube.com/watch?v=<id>
)
The arguments let us save the data we entered in this html block to a variable:
<form action="/setHomeText">
<label for="txt">Display text:</label>
<input type="text" id="txt" name="txt" placeholder="Blahblahblah...">
<input type="submit" value="Set text">
</form>
Here’s the structure of the server.arg()
:
String var = server.arg(String arg);
Now what?
You can modify the code to have more arguments for a web page, style the web page with CSS, use it to play/pause GIFs on the Arduino’s TFT with the AnimatedGIF.h
library, controlling relays, and more!
If you liked the tutorial, subscribe to the newsletter for more tutorials like this!