Entrada de datos en formato HTML Servidor web ESP32/ESP8266 con Arduino IDE

¿Alguna vez te has preguntado cómo enviar datos desde un ESP32/ESP8266 a un servidor web utilizando Arduino IDE? En este artículo te enseñaremos cómo realizar la entrada de datos en formato HTML, una tarea esencial para la comunicación entre dispositivos. ¡Sigue leyendo para descubrir cómo puedes lograrlo de manera sencilla y efectiva!

En esta guía aprenderá cómo crear un servidor web ESP32/ESP8266 con tres campos de entrada para pasar valores a su ESP a través de un formulario HTML. Luego puede utilizar estos valores como variables en su código. Programaremos las placas usando el IDE de Arduino.

Entrada de datos en formato HTML Servidor web ESP32/ESP8266 con Arduino IDE

Descripción del proyecto

En este tutorial crearemos un servidor web asincrónico usando el Biblioteca ESPAsyncWebServer Esto muestra tres campos de entrada para pasar valores que puede usar en su código para actualizar variables.

Veremos dos ejemplos similares. La siguiente figura ilustra cómo funciona el primer ejemplo.

Entrada de datos en formato HTML Servidor web ESP32/ESP8266 con Arduino IDE

Tiene una página web con tres campos de entrada a los que puede acceder con cualquier navegador de su red. Cuando ingresa un nuevo valor y hace clic en el botón Enviar, su ESP actualiza una variable con el nuevo valor.

Si alguna vez necesitó actualizar una variable a través de un servidor web ESP, debe seguir este proyecto. Este método evita la codificación estricta de variables porque puede crear un campo de entrada en una página web para actualizar cada variable con un nuevo valor. Esto puede ser particularmente útil para establecer umbrales, configurar SSID/contraseña, cambiar claves API, etc.

Más adelante, también le mostraremos cómo almacenar y acceder permanentemente a estas variables usando LittleFS. Así es como funciona este segundo ejemplo.

Entrada de datos en formato HTML Servidor web ESP32/ESP8266 con Arduino IDE

Esta página web le permite ingresar tres tipos de variables: String, Int y Float. Cada vez que ingresa un nuevo valor, se guarda en un archivo en el sistema de archivos LittleFS. Esta página web también contiene un marcador de posición para mostrar los valores actuales.

requisitos

Antes de continuar con el proyecto para compilar el código, asegúrese de revisar todos los requisitos previos en esta sección.

1. Instale la placa ESP32/ESP8266 en el IDE de Arduino

Programamos ESP32 y ESP8266 con Arduino IDE. Por lo que debes tener instalado el complemento ESP32 o ESP8266. Siga uno de los siguientes tutoriales para instalar el complemento ESP:

  • Instalación de la placa ESP32 en el IDE Arduino (Windows, Mac OS X, Linux)
  • Instalación de la placa ESP8266 en Arduino IDE (Windows, Mac OS X, Linux)

2. Instalación de bibliotecas

Para crear el servidor web asíncrono, debe instalar estas bibliotecas.

Estas bibliotecas no se pueden instalar a través del Administrador de bibliotecas Arduino. Por lo tanto, debe copiar los archivos de la biblioteca a la carpeta de instalación de Arduino. Alternativamente, puedes hacerlo en tu IDE de Arduino. Bosquejo > incluir biblioteca > Agregar biblioteca .zip y seleccione las bibliotecas que acaba de descargar.

3. Piezas necesarias

Para seguir este tutorial solo necesitas uno ESP32 o ESP8266 (leer ESP32 frente a ESP8266). No existe ningún circuito para este proyecto.


1. ESP32/ESP8266 procesa campos de entrada en páginas web con formularios HTML

Copie el siguiente código en el IDE de Arduino. Luego ingrese sus credenciales de red (SSID y contraseña) para que funcione para usted.

/*********
  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>
#else
  #include <ESP8266WiFi.h>
  #include <ESPAsyncTCP.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_INPUT_1 = "input1";
const char* PARAM_INPUT_2 = "input2";
const char* PARAM_INPUT_3 = "input3";

// HTML web page to handle 3 input fields (input1, input2, input3)
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">
  </head><body>
  <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>
</body></html>)rawliteral";

void notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
}

void setup() {
  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());

  // Send web page with input fields to client
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html);
  });

  // Send a GET request to <ESP_IP>/get?input1=<inputMessage>
  server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
    String inputMessage;
    String inputParam;
    // GET input1 value on <ESP_IP>/get?input1=<inputMessage>
    if (request->hasParam(PARAM_INPUT_1)) {
      inputMessage = request->getParam(PARAM_INPUT_1)->value();
      inputParam = PARAM_INPUT_1;
    }
    // GET input2 value on <ESP_IP>/get?input2=<inputMessage>
    else if (request->hasParam(PARAM_INPUT_2)) {
      inputMessage = request->getParam(PARAM_INPUT_2)->value();
      inputParam = PARAM_INPUT_2;
    }
    // GET input3 value on <ESP_IP>/get?input3=<inputMessage>
    else if (request->hasParam(PARAM_INPUT_3)) {
      inputMessage = request->getParam(PARAM_INPUT_3)->value();
      inputParam = PARAM_INPUT_3;
    }
    else {
      inputMessage = "No message sent";
      inputParam = "none";
    }
    Serial.println(inputMessage);
    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>");
  });
  server.onNotFound(notFound);
  server.begin();
}

void loop() {
  
}

Ver código sin formato

Así es como funciona el código

Echemos un vistazo rápido al código y veamos cómo funciona.

Incluyendo bibliotecas

Primero incluya las bibliotecas requeridas. Dependiendo de la placa que utilices, tendrás que integrar diferentes bibliotecas. Si está utilizando un ESP32, el código carga las siguientes bibliotecas:

#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>

Si está utilizando un ESP8266, incluya estas bibliotecas:

#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>

Credenciales de red

No olvide agregar sus credenciales de red a las siguientes variables para permitir que ESP32 o ESP8266 se conecten a su red.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Formularios HTML y campos de entrada

Primero, veamos el HTML que necesitamos para mostrar los campos de entrada.

En nuestro ejemplo, mostramos tres campos de entrada y cada campo tiene un botón «Enviar». Cuando el usuario ingresa datos y presiona el botón enviar, ese valor se envía al ESP y actualiza la variable.

Para hacer esto, cree tres formularios:

<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>

En HTML es

La etiqueta se utiliza para crear un formulario HTML para la entrada del usuario. En nuestro caso, el formulario debe contener un campo de entrada y un botón de envío.

Entrada de datos en formato HTML Servidor web ESP32/ESP8266 con Arduino IDE

Miremos la primera forma para ver cómo funciona (las otras formas funcionan de manera similar).

<form action="/get">
  input1: <input type="text" name="input1">
  <input type="submit" value="Submit">
</form>

El acción El atributo especifica dónde se deben enviar los datos ingresados ​​en el formulario después de presionar Enviar. En este caso se envía una solicitud HTTP GET /get?input1=Valor. El Valor se refiere al texto que ingresa en el campo de entrada.

Luego definimos dos campos de entrada: un campo de texto y un botón de enviar.

La siguiente línea define un campo de entrada de texto de una sola línea.

input1: <input type="text" name="input1">

El Tipo El atributo especifica que queremos un campo de entrada de texto y que Apellido El atributo especifica el nombre del elemento de entrada.

La siguiente línea define un botón para enviar los datos del formulario HTML.

<input type="submit" value="Submit">

En este caso Tipo El atributo indica que desea un botón de envío y que Valor Especifica el texto del botón.

Conéctate con tu red

En el configuración()conéctese a su red local.

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());

Manejo de solicitudes HTTP GET

Luego debe procesar las solicitudes HTTP GET.

Cuando visita la URL de la ruta, envía la página HTML al cliente. En este caso el texto HTML en el índice_html Variable.

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/html", index_html);
});

Entonces tienes que preocuparte por lo que sucede cuando haces una solicitud en el /recibir Rutas.

server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {

Creamos dos variables: Mensaje de entrada Y Parámetros de entrada para guardar el valor de entrada y el campo de entrada.

Luego debemos verificar si la solicitud HTTP GET cumple con los Entrada1, Entrada2o Entrada3 Parámetro. Estos estarán en el PARAM_INPUT_1, PARAM_INPUT_2 Y PARAM_INPUT_3 Variables.

¿Contiene la solicitud la PARAM_INPUT_1 (es decir Entrada1) configuramos eso Mensaje de entrada al valor insertado en el campo “entrada1”.

inputMessage = request->getParam(PARAM_INPUT_1)->value();

Ahora tiene el valor que acaba de ingresar en el primer formulario en la Mensaje de entrada Variable.

Luego configure el Parámetros de entrada variable PARAM_INPUT_1 para que sepamos de dónde viene el valor de entrada.

Cuando envíe el formulario, recibirá un mensaje con el valor y el campo ingresados. También mostramos un enlace para volver a la URL de la ruta (página de inicio).

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>");
Entrada de datos en formato HTML Servidor web ESP32/ESP8266 con Arduino IDE

Si realiza una solicitud a una URL no válida, llamaremos al extraviado() Función definida al inicio del boceto.

void notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
}

Finalmente, inicie el servidor para administrar los clientes.

server.begin();

demostración

Después de cargar el código en su placa, abra su monitor serie Arduino IDE con una velocidad de baudios de 115200 para encontrar la dirección IP del ESP.

Entrada de datos en formato HTML Servidor web ESP32/ESP8266 con Arduino IDE

Luego abra su navegador e ingrese la dirección IP. Esta página web debería cargarse:

Entrada de datos en formato HTML Servidor web ESP32/ESP8266 con Arduino IDE

Por ejemplo, dale 123456 En Entrada1 campo, luego presione el botón “Enviar”. Debería cargarse una nueva página mostrando este valor. 123456 fue enviado a tu ESP:

Entrada de datos en formato HTML Servidor web ESP32/ESP8266 con Arduino IDE

2. Guarde los campos de entrada ESP32/ESP8266 en LittleFS

Ahora pasemos al segundo ejemplo. Este ejemplo almacena permanentemente los datos ingresados ​​en los campos de entrada en LittleFS. También agregamos marcadores de posición en la página web para mostrar los valores actuales.

Copie el siguiente boceto en el IDE de Arduino. Luego ingrese sus credenciales de red (SSID y contraseña) antes de cargar.

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  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 <LittleFS.h>
#else
  #include <ESP8266WiFi.h>
  #include <ESPAsyncTCP.h>
  #include <Hash.h>
  #include <LittleFS.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 LittleFS");
      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: %srn", 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());
  }
  file.close();
  Serial.println(fileContent);
  return fileContent;
}

void writeFile(fs::FS &fs, const char * path, const char * message){
  Serial.printf("Writing file: %srn", 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");
  }
  file.close();
}

// Replaces placeholder with stored values
String processor(const String& var){
  //Serial.println(var);
  if(var == "inputString"){
    return readFile(LittleFS, "/inputString.txt");
  }
  else if(var == "inputInt"){
    return readFile(LittleFS, "/inputInt.txt");
  }
  else if(var == "inputFloat"){
    return readFile(LittleFS, "/inputFloat.txt");
  }
  return String();
}

void setup() {
  Serial.begin(115200);
  // Initialize LittleFS
  #ifdef ESP32
    if(!LittleFS.begin(true)){
      Serial.println("An Error has occurred while mounting LittleFS");
      return;
    }
  #else
    if(!LittleFS.begin()){
      Serial.println("An Error has occurred while mounting LittleFS");
      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(LittleFS, "/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(LittleFS, "/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(LittleFS, "/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(LittleFS, "/inputString.txt");
  Serial.print("*** Your inputString: ");
  Serial.println(yourInputString);
  
  int yourInputInt = readFile(LittleFS, "/inputInt.txt").toInt();
  Serial.print("*** Your inputInt: ");
  Serial.println(yourInputInt);
  
  float yourInputFloat = readFile(LittleFS, "/inputFloat.txt").toFloat();
  Serial.print("*** Your inputFloat: ");
  Serial.println(yourInputFloat);
  delay(5000);
}

Ver código sin formato

Cómo funciona el código

Este código es muy similar al anterior excepto por algunos cambios. Echemos un vistazo rápido y veamos cómo funciona.

Incluyendo bibliotecas

El código carga las siguientes bibliotecas cuando se usa ESP32. Debe cargar la biblioteca LittleFS para escribir en el sistema de archivos LittleFS.

#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <AsyncTCP.h>
#include <LittleFS.h>

Si está utilizando un ESP8266, deberá incluir las siguientes bibliotecas.

#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <ESPAsyncTCP.h>
#include <Hash.h>
#include <LittleFS.h>

formulario HTML

En este ejemplo, cuando envía los valores, se abre una ventana que indica que el valor se guardó en LittleFS, en lugar de redirigirlo a otra página como en el ejemplo anterior.

Para hacer esto necesitamos agregar una función de JavaScript, en este caso se llama Enviar mensaje() Luego verá un mensaje de advertencia indicando que el valor se ha guardado en LittleFS. Luego se recarga el sitio web para que se muestren los valores actuales.

<script>
  function submitMessage() {
    alert("Saved value to ESP LittleFS");
    setTimeout(function(){ document.location.reload(false); }, 500);
  }
</script>

Las formas también son ligeramente diferentes a las anteriores. Aquí está el formulario para la primera entrada.

<form action="/get" target="hidden-form">
  inputString (current value %inputString%): <input type="text" name="inputString">
  <input type="submit" value="Submit" onclick="submitMessage()">
</form>

En este caso Meta atributo y un