Input Data on HTML Form ESP32/ESP8266 Web Server using Arduino IDE
In this guide, you’ll learn how to create an ESP32/ESP8266 web server with three input fields to pass values to your ESP using an HTML form. Then, you can use those values as variables in your code. We’ll be using the Arduino IDE to program the boards.
Project Overview
In this tutorial we’ll build an asynchronous web server using the ESPAsyncWebServer library that displays three input fields to pass values that you can use in your code to update variables.
We’ll take a look at two similar examples. The following figure illustrates how the first example works.
How the code works
Let’s take a quick look at the code and see how it works.
Including libraries
First, include the necessary libraries. You include different libraries depending on the board you’re using. If you’re using an ESP32, the code loads the following libraries:
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
If you’re using an ESP8266, you include these libraries:
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
Network credentials
Don’t forget to insert your network credentials in the following variables, so that the ESP32 or ESP8266 can connect to your network.
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
HTML Forms and Input Fields
First, let’s take a look at the HTML that we need to display the input fields.
In our example, we display three input fields and each field has a “Submit” button. When the user enters data and presses the “Submit” button, that value is sent to the ESP and updates the variable.
For that, create three forms:
<form action="/get">
input1: <input type="text" name="input1">
<input type="submit" value="Submit">
</form><br>
<form action="/get">
input2: <input type="text" name="input2">
<input type="submit" value="Submit">
</form><br>
<form action="/get">
input3: <input type="text" name="input3">
<input type="submit" value="Submit">
</form>
In HTML, the <form> tag is used to create an HTML form for user input. In our case, the form should contain an input field and a submit button.
Let’s take a look at the first form to see how it works (the other forms work in a similar way).
<form action="/get">
input1: <input type="text" name="input1">
<input type="submit" value="Submit">
</form>
The action attribute specifies where to send the data inserted on the form after pressing submit. In this case, it makes an HTTP GET request to /get?input1=value. The value refers to the text you enter in the input field.
Then, we define two input fields: one text field and one submit button.
The following line defines a one line text input field.
input1: <input type="text" name="input1">
The type attribute specifies we want a text input field, and the name attribute specifies the name of the input element.
The next line defines a button for submitting the HTML form data.
<input type="submit" value="Submit">
In this case, the type attribute specifies you want a submit button, and the value specifies the text on the button.
Connect to your network
In the setup(), connect to your local network.
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("WiFi Failed!");
return;
}
Serial.println();
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
Handle HTTP GET requests
Then, you need to handle the HTTP GET requests.
When, you access the route URL, you send the HTML page to the client. In this case, the HTML text is saved on the index_html variable.
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html);
});
Then, you need to handle what happens when you receive a request on the /get routes.
server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
We create two variables: inputMessage and inputParam to save the input value and the input field.
Then, we need to check whether the HTTP GET request contains the input1, input2, or input3 parameters. These are saved on the PARAM_INPUT_1, PARAM_INPUT_2 and PARAM_INPUT_3 variables.
If the request contains the PARAM_INPUT_1 (i.e. input1), we set the inputMessage to the value inserted in the input1 field.
inputMessage = request->getParam(PARAM_INPUT_1)->value();
Now you have the value you’ve just inserted on the first form saved on the inputMessage variable.
Then, set the inputParam variable to PARAM_INPUT_1 so that we know where the input value comes from.
When you submit the form, you get a message saying the value you’ve inserted and in which field. We also display a link to get back to the route URL (Home Page).
request->send(200, "text/html", "HTTP GET request sent to your ESP on input field ("
+ inputParam + ") with value: " + inputMessage +
"<br><a href=\"/\">Return to Home Page</a>");
If you make a request on an invalid URL, we call the notFound() function, defined at the beginning of the sketch.
void notFound(AsyncWebServerRequest *request) {
request->send(404, "text/plain", "Not found");
}
Finally, start the server to handle clients.
server.begin();
Demonstration
After uploading code to your board, open your Arduino IDE Serial Monitor at a baud rate of 115200 to find the ESP IP address.
Then, open your browser and type the IP address. This web page should load:
For example, type 123456 on input1 field, then press the “Submit” button. A new page should load saying that value 123456 was sent to your ESP:
2. ESP32/ESP8266 Save Input Fields to SPIFFS
Now, let’s proceed to the second example. This example saves the data inserted on the input fields permanently on SPIFFS. We’ve also added placeholders on the web page to show the current values.
Copy the following sketch to Arduino IDE. Then, before uploading type your network credentials (SSID and password).
/*********
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-esp8266-input-data-html-form/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*********/
#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#include <SPIFFS.h>
#else
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <Hash.h>
#include <FS.h>
#endif
#include <ESPAsyncWebServer.h>
AsyncWebServer server(80);
// REPLACE WITH YOUR NETWORK CREDENTIALS
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
const char* PARAM_STRING = "inputString";
const char* PARAM_INT = "inputInt";
const char* PARAM_FLOAT = "inputFloat";
// HTML web page to handle 3 input fields (inputString, inputInt, inputFloat)
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html><head>
<title>ESP Input Form</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
function submitMessage() {
alert("Saved value to ESP SPIFFS");
setTimeout(function(){ document.location.reload(false); }, 500);
}
</script></head><body>
<form action="/get" target="hidden-form">
inputString (current value %inputString%): <input type="text" name="inputString">
<input type="submit" value="Submit" onclick="submitMessage()">
</form><br>
<form action="/get" target="hidden-form">
inputInt (current value %inputInt%): <input type="number " name="inputInt">
<input type="submit" value="Submit" onclick="submitMessage()">
</form><br>
<form action="/get" target="hidden-form">
inputFloat (current value %inputFloat%): <input type="number " name="inputFloat">
<input type="submit" value="Submit" onclick="submitMessage()">
</form>
<iframe style="display:none" name="hidden-form"></iframe>
</body></html>)rawliteral";
void notFound(AsyncWebServerRequest *request) {
request->send(404, "text/plain", "Not found");
}
String readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\r\n", path);
File file = fs.open(path, "r");
if(!file || file.isDirectory()){
Serial.println("- empty file or failed to open file");
return String();
}
Serial.println("- read from file:");
String fileContent;
while(file.available()){
fileContent+=String((char)file.read());
}
Serial.println(fileContent);
return fileContent;
}
void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\r\n", path);
File file = fs.open(path, "w");
if(!file){
Serial.println("- failed to open file for writing");
return;
}
if(file.print(message)){
Serial.println("- file written");
} else {
Serial.println("- write failed");
}
}
// Replaces placeholder with stored values
String processor(const String& var){
//Serial.println(var);
if(var == "inputString"){
return readFile(SPIFFS, "/inputString.txt");
}
else if(var == "inputInt"){
return readFile(SPIFFS, "/inputInt.txt");
}
else if(var == "inputFloat"){
return readFile(SPIFFS, "/inputFloat.txt");
}
return String();
}
void setup() {
Serial.begin(115200);
// Initialize SPIFFS
#ifdef ESP32
if(!SPIFFS.begin(true)){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
#else
if(!SPIFFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
#endif
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("WiFi Failed!");
return;
}
Serial.println();
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// Send web page with input fields to client
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
// Send a GET request to <ESP_IP>/get?inputString=<inputMessage>
server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
String inputMessage;
// GET inputString value on <ESP_IP>/get?inputString=<inputMessage>
if (request->hasParam(PARAM_STRING)) {
inputMessage = request->getParam(PARAM_STRING)->value();
writeFile(SPIFFS, "/inputString.txt", inputMessage.c_str());
}
// GET inputInt value on <ESP_IP>/get?inputInt=<inputMessage>
else if (request->hasParam(PARAM_INT)) {
inputMessage = request->getParam(PARAM_INT)->value();
writeFile(SPIFFS, "/inputInt.txt", inputMessage.c_str());
}
// GET inputFloat value on <ESP_IP>/get?inputFloat=<inputMessage>
else if (request->hasParam(PARAM_FLOAT)) {
inputMessage = request->getParam(PARAM_FLOAT)->value();
writeFile(SPIFFS, "/inputFloat.txt", inputMessage.c_str());
}
else {
inputMessage = "No message sent";
}
Serial.println(inputMessage);
request->send(200, "text/text", inputMessage);
});
server.onNotFound(notFound);
server.begin();
}
void loop() {
// To access your stored values on inputString, inputInt, inputFloat
String yourInputString = readFile(SPIFFS, "/inputString.txt");
Serial.print("*** Your inputString: ");
Serial.println(yourInputString);
int yourInputInt = readFile(SPIFFS, "/inputInt.txt").toInt();
Serial.print("*** Your inputInt: ");
Serial.println(yourInputInt);
float yourInputFloat = readFile(SPIFFS, "/inputFloat.txt").toFloat();
Serial.print("*** Your inputFloat: ");
Serial.println(yourInputFloat);
delay(5000);
}
Important: if you’re using an ESP8266, make sure you’ve enabled SPIFFS in Tools > Flash Size menu:How the Code Works
This code is very similar with the previous one with a few tweaks. Let’s take a quick look at it and see how it works.Including libraries
The code loads the following libraries if you’re using the ESP32. You need to load the SPIFFS library to write to SPIFFS.#include <WiFi.h> #include <ESPAsyncWebServer.h> #include <AsyncTCP.h> #include <SPIFFS.h>
If you’re using an ESP8266, you need to include the FS library to interface with SPIFFS.#include <ESP8266WiFi.h> #include <ESPAsyncWebServer.h> #include <ESPAsyncTCP.h> #include <Hash.h> #include <FS.h>
HTML Form
In this example, when you submit the values, a window opens saying the value was saved to SPIFFS, instead of being redirected to another page as in the previous example.For that, we need to a add a JavaScript function, in this case it’s called submitMessage() that pops an alert message saying the value was saved to SPIFFS. After that pop up, it reloads the web page so that it displays the current values.<script> function submitMessage() { alert("Saved value to ESP SPIFFS"); setTimeout(function(){ document.location.reload(false); }, 500); } </script>
The forms are also a bit different from the previous ones. Here’s the form for the first input.<form action="/get" target="hidden-form"> inputString (current value %inputString%): <input type="text" name="inputString"> <input type="submit" value="Submit" onclick="submitMessage()"> </form>
In this case, the target attribute and an <iframe> are used so that you remain on the same page after submitting the form.The name that shows up for the input field contains a placeholder %inputString% that will then be replaced by the current value of the inputString variable.The onclick=”submitMessage()” calls the submitMessage() JavaScript function after clicking the “Submit” button.Read and Write to SPIFFS
Then, we have some functions to read and write from SPIFFS.The readFile() reads the content from a file:String readFile(fs::FS &fs, const char * path){ Serial.printf("Reading file: %s\r\n", path); File file = fs.open(path, "r"); if(!file || file.isDirectory()){ Serial.println("- empty file or failed to open file"); return String(); } Serial.println("- read from file:"); String fileContent; while(file.available()){ fileContent+=String((char)file.read()); } Serial.println(fileContent); return fileContent;
The writeFile() writes content to a file:void writeFile(fs::FS &fs, const char * path, const char * message){ Serial.printf("Writing file: %s\r\n", path); File file = fs.open(path, "w"); if(!file){ Serial.println("- failed to open file for writing"); return; } if(file.print(message)){ Serial.println("- file written"); } else { Serial.println("- write failed"); } }
processor()
The processor() is responsible for searching for placeholders in the HTML text and replacing them with actual values saved on SPIFFS.String processor(const String& var){ //Serial.println(var); if(var == "inputString"){ return readFile(SPIFFS, "/inputString.txt"); } else if(var == "inputInt"){ return readFile(SPIFFS, "/inputInt.txt"); } else if(var == "inputFloat"){ return readFile(SPIFFS, "/inputFloat.txt"); } return String(); }
Handle HTTP GET requests
Handling the HTTP GET requests works the same way as in the previous example, but this time we save the variables on SPIFFS.For example, for the inputString field:if (request->hasParam(PARAM_STRING)) { inputMessage = request->getParam(PARAM_STRING)->value(); writeFile(SPIFFS, "/inputString.txt", inputMessage.c_str()); }
When the request contains inputString (i.e. PARAM_STRING), we set the inputMessage variable to the value submitted on the inputString form.inputMessage = request->getParam(PARAM_STRING)->value();
Then, save that value to SPIFFS.writeFile(SPIFFS, "/inputString.txt", inputMessage.c_str());
A similar process happens for the other forms.Accessing the variables
In the loop(), we demonstrate how you can access the variables.For example, create a String variable called yourInputString that reads the content of the inputString.txt file on SPIFFS.String yourInputString = readFile(SPIFFS, "/inputString.txt");
Then, print that variable in the Serial Monitor.Serial.println(yourInputString);
Demonstration
After uploading code to your board, open your Arduino IDE Serial Monitor at a baud rate of 115200 to find the ESP IP address.Open your browser and type the IP address. A similar web page should load (at first your current values will be blank).Type a String in the first input field and press “Submit”, repeat the same process for the Int and Float input values. Every time you press the Submit button for a field, you’ll see an alert message like this:Press the “OK” button to reload the web page and see the current values updated.If you have your Arduino IDE Serial Monitor open, you’ll see that the stored values are being printed over and over again:For a final project, you can delete all those lines in your loop() that print all stored values every 5 seconds, we just left them on purpose for debugging.Wrapping Up
In this tutorial you’ve learned how to handle input fields in a web page to update the ESP variable values. You can modify this project to set thresholds, change API Key values, set a PWM value, change a timer, set SSID/password, etc.Here’s other projects that you might like:
- How to Display Images in ESP32 and ESP8266 Web Server
- ESP32-CAM PIR Motion Detector with Photo Capture (saves to microSD card)
- ESP32 Web Server with BME280 – Advanced Weather Station
- ESP32 Pinout Reference: Which GPIO pins should you use?
Learn more about the ESP32 with our best-selling course:
沒有留言:
張貼留言