esp8266-servidor-parametros

Cómo recibir parámetros HTTP con ESP32 como servidor

  • 5 min

Los parámetros HTTP son datos enviados en una petición para indicar al servidor qué queremos hacer.

El ejemplo está orientado a ESP32. En muchos casos también puede adaptarse a ESP8266 cambiando librerías y algunos detalles de pines.

Cuando nuestra placa ESP actúa como servidor, leer estos parámetros nos permite recibir formularios, comandos, identificadores, valores de configuración o cualquier otro dato que llegue desde el navegador o desde otro cliente.

Con un servidor web básico podríamos quedarnos únicamente en métodos (request) de tipo GET. Y hasta ahí se quedarían muchos tutoriales de Internet. Pero a nosotros nos gusta meternos en un poco más de profundidad ¿A que sí?

Para ello vamos a ver los distintos tipos de peticiones y sus parámetros. Como habíamos visto, una petición HTTP puede ser de distintos tipos (GET, POST, PATH, DELETE…).

esp8266-cliente-servidor

Hace mucho tiempo, cuando internet “era joven”, había mucha confusión sobre para que servían los distintos tipos de funciones. Pero en esta era API REST e interface M2M, debería estar muy claro el motivo por el que existen distintos tipos peticiones. Típicamente cada tipo se corresponde con ‘acciones’ que quieres realizar en el servidor.

Así que lo lógico es que la petición HTTP que te dice si un LED está encendido sea de tipo GET. Pero la que lo enciende y apaga lo correcto sería usar un PATCH (como mucho, se podría pasar un POST).

Para entender las peticiones y qué acción quieren que hagamos, no vale con routear un URI a una acción de callback, sino que además debemos poder lanzar acciones distintas en función del tipo de petición que recibimos.

De forma similar tenemos los parámetros. Recordar que en una petición HTTP podemos mandar parámetros, bien en la URL (en peticiones GET) o codificado de alguna de las diversas formas en el cuerpo de la petición.

Diferenciar tipo de petición

Para diferenciar el tipo de petición la librería WebServer dispone de la sobrecarga del método ‘on(…)’, que permite indicar el método que necesitamos

void on(const String &uri, HTTPMethod method, THandlerFunction fn);
Copied!
  • URI, dirección del recurso.
  • method, el método que queremos asociar (HTTP_ANY, HTTP_GET, HTTP_POST, HTTP_PUT, HTTP_PATCH, HTTP_DELETE, HTTP_OPTIONS)
  • fn, la función de callback a ejecutar.

Obtener parámetros

Por otro lado, para obtener los parámetros la librería WebServer dispone de los siguientes métodos.

const String& arg(String name) const;    // get request argument value by name
const String& arg(int i) const;          // get request argument value by number
const String& argName(int i) const;      // get request argument name by number
int args() const;                        // get arguments count
bool hasArg(const String& name) const;   // check if argument exists
Copied!

Veamos un ejemplo

Como siempre, lo mejor es verlo en un ejemplo sencillo. Supongamos que tenemos un ESP8266 con una serie de LED, que identificamos por su ID. Por un lado, queremos poder consultar el estado de cada LED y, además, queremos poder encender o apagar el LED.

Primero, vamos a ver como NO se hace. Lo que no se hace, es emplear una petición GET tanto encender y apagar el LED, ni se hacen “cosas raras” con la clase String para crear una petición a una URI con la siguiente forma.

/led?Id=10&Status=ON

No, eso no se hace. Lo correcto, es hacer dos routeos. Uno de tipo GET a la URI ‘/led’ que reciba el ID del LED que queremos consultar, y uno de tipo POST que reciba el ID del LED, y su nuevo estado.

Esto, lo podríamos hacer de la siguiente forma, donde simplemente creamos dos routeos y le asociamos una función que, en este ejemplo, simplemente muestra los parámetros recibidos.

El programa principal mantiene la misma estructura básica de un servidor HTTP sencillo.

#include <WiFi.h>
#include <WebServer.h>
 
WebServer server(80);
 
#include "config.h"  // Sustituir con datos de vuestra red
#include "ESP32_Utils.hpp"
#include "Server.hpp"

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

   ConnectWiFi_STA();
   
   InitServer();
}
 
void loop()
{
   server.handleClient();
}
Copied!

Modificamos el fichero Server.hpp con el siguiente contenido.

// Funcion al recibir petición GET
void getLED() 
{
   // devolver respuesta
   server.send(200, "text/plain", String("GET ") + server.arg(String("Id")));
}
 
// Funcion al recibir petición POST
void setLED() 
{
   // mostrar por puerto serie
   Serial.println(server.argName(0));
   
   // devolver respuesta
   server.send(200, "text/plain", String("POST ") + server.arg(String("Id")) + " " + server.arg(String("Status")));
}

// Funcion que se ejecutara en la URI '/'
void handleRoot() 
{
   server.send(200, "text/plain", "Hola mundo!");
}

void handleNotFound() 
{
   server.send(404, "text/plain", "Not found");
}

void InitServer()
{
   // Ruteo para '/'
   server.on("/", handleRoot);
 
   // Definimos dos routeos
   server.on("/led", HTTP_GET, getLED);
   server.on("/led", HTTP_POST, setLED);
 
   server.onNotFound(handleNotFound);
 
   server.begin();
   Serial.println("HTTP server started");
}
Copied!

Resultado

Ahora podemos usar Postman para lanzar las peticiones al ESP32 y comprobar que estamos leyendo correctamente el tipo y parámetro de la petición.

Para la petición GET haríamos,

esp8266-servidor-parametros-get

Y para la petición POST tendríamos,

esp8266-servidor-peticion-post

En este ejemplo, también veríamos en el puerto serie la petición. En un caso real, realizaríamos las acciones oportunas (en este caso, seguramente encender o apagar el LED).

esp8266-servidor-parametros

Hemos aprendido a leer el tipo y los parámetros de una petición HTTP cuando nuestra placa actúa como servidor. Aunque de momento únicamente devolvemos respuestas sencillas, esto es la base para montar formularios, APIs y paneles de control web.

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