como-recibir-datos-de-un-formulario-web-con-esp8266

Cómo recibir datos de un formulario web con ESP8266 o ESP32

Continuamos con los tutoriales del ESP8266 y el ESP32 actuando como servidor viendo cómo enviar datos desde una página Web estática a través de un formulario.

Haremos referencia al ESP8266, pero el mismo código es compatible para el ESP32, ajustando el nombre de las librerías. Al final tenéis el código tanto para el ESP8266 como para el ESP32.

Después de una pequeña pausa para ver la programación OTA a través de WiFi (que os será muy útil para las pruebas en las siguientes entradas) continuamos con el ESP8266 actuando como servidor, que dejamos en la última entrada viendo cómo montar un servidor asíncrono con ESPAsyncServer.

Cómo decíamos, la forma “preferida” de servir contenido en el ESP8266 es desde la memoria SPIFFS. El contenido servido es ‘estático’, en el sentido de que no cambia entre llamadas al servidor. Servir contenido realmente dinámico normalmente queda reservado casi exclusivamente para los endpoints.

Sin embargo, cómo ya adelantábamos que el contenido sea ‘estático’ no significa que “que no haga nada”.

Existen múltiples formas de intercambiar información entre el frontend y el backend (formularios, ajax, websockets). Iremos viendo todas ellas, y vamos a empezar por la más sencilla (y antigua), los sencillos y simples formularios.

En los tiempos que corren, usar formularios puede parecer antediluviano. Pero, por algún lugar hay que comenzar, y conviene no empezar la casa por el tejado. Veremos las otras formas más avanzadas (y complejas) en las siguientes entradas.

Nuestro programa principal queda invariante respecto al ejemplo del ESPAsyncServer

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

#include "config.h"  // Sustituir con datos de vuestra red
#include "Server.hpp"
#include "ESP8266_Utils.hpp"

void setup(void)
{
  Serial.begin(115200);
  SPIFFS.begin();
  
  ConnectWiFi_STA();

  InitServer();
}

void loop(void)
{
}

Los cambios los tenemos en la definición del comportamiento del servidor en el fichero ‘Server.hpp’. Además de la habitual función para servir el contenido desde el SPIFFS, hemos añadido un ruteo para la URL ‘/SetText’ para peticiones de POST, asociada a la función ‘handleFormText’. Es decir, hemos definido una ‘mini API’ en el backend con un único Endpoint.

AsyncWebServer server(80);

void handleFormText(AsyncWebServerRequest *request)
{
 String MiText = request->arg("miText");
 
 Serial.print("MiText:\t");
 Serial.println(MiText);

 //String response = "<a href='/'> Go Back </a>";
 //request->send(200, "text/html", response);

 // redirección directa
 request->redirect("/");
}

void InitServer()
{
  server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html");

  server.on("/SetText", HTTP_POST, handleFormText);

  server.onNotFound([](AsyncWebServerRequest *request) {
    request->send(400, "text/plain", "Not found");
  });

  server.begin();
    Serial.println("HTTP server started");
}

En este ejemplo, en la función handleFormText simplemente vamos a imprimir el texto recibido por puerto serie y redireccionar al cliente a la página del formulario. (En el mismo código tenéis comentado un ejemplo en el que devuelve un código html con un enlace para volver)

Por otro lado, dentro de la carpeta ‘data’ creamos un único fichero llamado ‘index.html’, con el siguiente contenido.

<!DOCTYPE html>
<html class="no-js" lang="">
   <head>
      <meta charset="utf-8">
      <meta http-equiv="x-ua-compatible" content="ie=edge">
      <title>ESP8266 Forms</title>
      <meta name="description" content="">
      <meta name="viewport" content="width=device-width, initial-scale=1">
   </head>
 
   <body>
    <h1>Form example</h1>
        <form action="/SetText" method="post">
      Texto:<br>
      <input type="text" name="miText" value="MiText"><br>
      <button type="submit" value="Submit">Send</button>
    </form> 
    </body>
</html>

Resultado

Esta sencillísima página web únicamente contiene un formulario cuya función de ‘Enviar’ (submit) está asociada al Endpoint ‘/SetText’ bajo el método POST. Recordamos que los métodos (o verbos) en un API web significan cosas. Estamos usando POST porque estamos emulando una acción que ejecutamos sobre el backend. Si estuviéramos realizando una petición usaríamos un método GET.

Si tenéis dudas sobre el uso correcto de los métodos en API Web, consultar la entrada sobre tipos de peticiones y parámetros, o cómo montar un API Rest en NodeJs.

Una vez cargado todo, accedemos al ESP8266 y veremos nuestra sencilla (y, reconozcamos, fea) página web.

esp8266-formulario-web-html

Si escribimos un texto y pulsamos en el botón ‘submit’ podemos ver que, efectivamente, el ESP8266 recibe correctamente el texto que enviamos y lo muestra por puerto serie. En proyecto real ya sería cuestión de que procesáramos el texto, e hiciéramos lo que fuera oportuno.

esp8266-formulario-web-serial-port

En próximas entradas veremos formas mucho más convenientes de realizar este intercambio de información. Este es un ejemplo sencillo, pero muy útil, que nos ha permitido introducir los conceptos (y el vocabulario) de métodos web, backend, frontend, endpoint. ¡Empezamos a meternos en harina!

En la siguiente entrada veremos una variación de este ejemplo donde veremos cómo aplicar lo que hemos visto para encender y apagar un LED conectado al ESP8266 a través de un formulario, por ejemplo, para variar la intensidad de luz en un LED. ¡Hasta pronto!

Descarga el código

Todo el código de esta entrada está disponible para su descarga en Github.

github-full

Versión para el ESP8266: https://github.com/luisllamasbinaburo/ESP8266-Examples

Versión para el ESP32: https://github.com/luisllamasbinaburo/ESP32-Examples