¿Se te ha ocurrido tener una página web en tu ESP32? Así es, puedes guardar una página dentro un ESP32 para mostrarla cuando alguien acceda a la dirección IP del mismo. Y aún más interesante es que desde esa página se pueden enviar instrucciones al ESP32.
WebServer es una de las funciones que puede desempeñar el ESP32. Como lo indica el nombre de la función, el ESP32 actuará como un servidor web. Esto quiere decir que alojará la página, recibirá solicitudes de clientes (otros equipos que accedan) y enviará respuestas a los mismos.
Se aplica protocolo HTTP para la comunicación entre cliente y servidor por lo que se puede hacer uso de los métodos GET y POST.
Utilidad de usar el ESP32 como WebServer
¿Qué utilidad tiene esto? El ejemplo que usaremos para este tutorial es el de almacenar una página web que podrás ver desde el navegador usando la IP del ESP32. Desde esa página podrás encender y apagar un diodo led que está soldado a la tarjeta de desarrollo.
Programación
En este ejemplo se usa el método de envío que se está utilizando es GET, por lo que la información de las solicitudes HTTP están directamente en la URL.
/*
* WebServer con el ESP32 para encender diodo led
* de la placa
* Henry Mera
* https://www.todomaker.com
*/
#include <WiFi.h> // Añade ibreria
#define LED 2 // Indica pin que se usará (D2)
String p="off"; // dato de apagado del led
// Credenciales de wifi
// Reemplazar con datos de tu red
const char *ssid = "SSID";
const char *password = "Contraseña";
// Crea servidor llamado "server" y establece el puerto 80 para acceder
WiFiServer server(80);
void setup() {
//Configura D2 como salida y lo pone en un estado bajo (0)
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
//Inicia puerto serial a velocidad de 115200 baudios
Serial.begin(115200);
Serial.println();
Serial.println("Configurando");
// Inicia conexión WiFi con las datos de la red especificados
WiFi.begin(ssid, password); //configurando las credenciales
Serial.print("Conectandome");
while (WiFi.status() != WL_CONNECTED) // Espera conexión a la red
{
delay(500);
Serial.print("."); // Imprime puntos
}
Serial.println();
Serial.print("Conectado, La dirección IP es: ");
Serial.println(WiFi.localIP()); // Imprime la IP del ESP32
server.begin(); // Inicia el servidor
Serial.println("Servidor iniciado");
}
void loop() {
WiFiClient client = server.available(); // Recibe las conexciones de clientes
if (client) { // Si hay un cliente
Serial.println("Nuevo cliente."); // Indica el acceso de un cliente
String currentLine = ""; // Variable para datos de fin de linea
while (client.connected()) { // Cliente conectado
if (client.available()) { // Datos disponibles para ser leido
char c = client.read(); // Lectura de byte en variable C
Serial.write(c); // Muestra los datos
if (c == '\n') { // Si el byte es un caracter de nuevo salto de linea
if (currentLine.length() == 0) { // Si no hay caracteres, entonces lanza el codgo HTML
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
client.println("<style>html{font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button {border: none;color: white;padding: 15px 32px; text-align: center;");
client.println("text-decoration: none;display: inline-block;font-size: 16px; margin: 4px 2px;cursor: pointer;}");
client.println(".button1 {background-color: #4CAF50;} /* Green */");
client.println(".button2 {background-color: #008CBA;} /* Blue */");
client.println("</style></head>");
// Creación de botones
client.print("<body><h1>WebServer con ESP32</h1>");
if(p=="off"){
client.println("<button type='button' class='button button1' onClick=location.href='/LED=ON'> ENCENDER </button><br><br>");
}
else{
client.println("<button type='button' class='button button2' onClick=location.href='/LED=OFF'> APAGAR </button><br><br>");
}
client.print("</body></html>");
client.println();
// Rompe el codigo del while-loop
break;
} else { // Limpiando variable
currentLine = "";
}
} else if (c != '\r') { // Si no hay retorno de carro
currentLine += c; // agrega al final de la linea
}
// Revisando el datos recibido del url
if (currentLine.indexOf("GET /LED=ON") != -1) {
digitalWrite(LED, HIGH); // GET /LED=ON
p="on";
}
if (currentLine.indexOf("GET /LED=OFF") != -1) {
digitalWrite(LED, LOW); // GET /LED=OFF
p="off";
}
}
}
// cerrando la conexión
client.stop();
Serial.println("Cliente Desconectado");
}
}
Explicación del código
Empezamos agregando la librería WiFi.h e indicando el pin del ESP32 que se usará para controlar el LED. También un dato de control que se usará más adelante con el WebServer.
Creamos una variables que guardarán los datos de la red WiFi a la que se conectará el ESP32. Estos datos son el nombre de la red (SSID) y la contraseña. Esta puede ser la red que tienes en tu casa o incluso una que hayas creado aunque no tenga acceso a internet.
Concluimos creando un servidor llamado server que operará mediante el puerto 80.
#include <WiFi.h> // Añade ibreria
#define LED 2 // Indica pin que se usará (D2)
String p="off"; // dato de apagado del led
// Credenciales de wifi
// Reemplazar con datos de tu red
const char *ssid = "SSID";
const char *password = "Contraseña";
// Crea servidor llamado "server" y establece el puerto 80 para acceder
WiFiServer server(80);
Dentro se setup configuraremos el pin para el led como salida y que inicie en un estado lógico de 0 (LOW) o apagado.
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
Iniciamos el monitor serial con una velocidad de 115200 baudios. Posteriormente imprimimos un mensaje por el mismo.
Serial.begin(115200);
Serial.println();
Serial.println("Configurando");
Iniciaremos la conexión WiFi usando los datos de SSID y contraseña declarados anteriormente.
WiFi.begin(ssid, password);
Este ciclo imprime un punto tras otro mientras no se establezca conexión.
while (WiFi.status() != WL_CONNECTED) // Espera conexión a la red
{
delay(500);
Serial.print("."); // Imprime puntos
}
Concluimos esta parte imprimiendo la IP que el módem le ha asignado al ESP32 e iniciando el servidor que anteriormente nombramos como server.
Serial.println();
Serial.print("Conectado, La dirección IP es: ");
Serial.println(WiFi.localIP()); // Imprime la IP del ESP32
server.begin(); // Inicia el servidor
Serial.println("Servidor iniciado");
En la sección loop agregaremos el código correspondiente para mostrar el sitio web embebido en el ESP32. Desde allí también se realizan los cambios de acuerdo a las solicitudes realizadas desde el cliente.
Las solicitudes que ocurrirán al presionar un botón en la pantalla se hacen mediante el método GET, por lo que las mismas serán visibles desde la URL de la página.
Empezamos creando un cliente al que se nombrará client. Un cliente será cualquier dispositivo de la red que entré a la dirección del ESP32.
WiFiClient client = server.available();
Se crea una condición en la que si el cliente al entrado se avise mediante el monitor serial. Además se crea una variable llamada currentLine que usaremos después.
if (client) { // Si hay un cliente
Serial.println("Nuevo cliente."); // Indica el acceso de un cliente
String currentLine = "";
Usaremos un ciclo while. Mientras el cliente esté conectado (connected) y haya datos (available) se guardarán los datos en una variable char llamada c y se imprimiran esos datos leídos del cliente.
while (client.connected()) { // Cliente conectado
if (client.available()) { // Datos disponibles para ser leido
char c = client.read(); // Lectura de byte en variable C
Serial.write(c); // Muestra los datos
Se crean unas condiciones en las que se toma en cuenta si el dato leído es un salto de línea (\n) y la longitud del valor (length) de currentLine es igual a 0 para que se cumplan.
if (c == '\n') {
if (currentLine.length() == 0) {
Si las condiciones anteriores se cumplen se despliega el sitio web desde el ESP32 hacia el cliente en formato HTML. Para ello se llama a client y se le da la instrucción println para imrpimir el HTML una línea a la vez.
La parte que se está viendo corresponde a los parámetros y cabecera (head) de un documento HTML. Dentro de la cabecera se indican datos que no se suelen visualizar al navegar en la página. Por ejemplo, los estilos (style) CSS de los botones (.button) que se usarán después.
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
client.println("<style>html{font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button {border: none;color: white;padding: 15px 32px; text-align: center;");
client.println("text-decoration: none;display: inline-block;font-size: 16px; margin: 4px 2px;cursor: pointer;}");
client.println(".button1 {background-color: #4CAF50;} /* Green */");
client.println(".button2 {background-color: #008CBA;} /* Blue */");
client.println("</style></head>");
Procedemos a crear el cuerpo (body) de la página. Se muestra un título usando la etiqueta H1.
Después usando la variable de estado llamada p se decide el texto y estilo que tendrá le botón para encender o apagar el led.
Recordemos que la variable tenía el valor “off” y programamos el led para que empiece estando apagado. Por ello se mostrará el botón con el texto “ENCENDER” para indicarnos que esa será la acción que podremos realizar.
Siguiendo con el botón “ENCENDER” hay que mencionar que al hacer clic (onClick) sobre él nos llevará a la dirección “/LED-ON” (location.href). Este cambio será visible en la URL.
client.print("<body><h1>WebServer con ESP32</h1>");
if (p == "off") {
client.println("<button type='button' class='button button1' onClick=location.href='/LED=ON'> ENCENDER </button><br><br>");
}
else {
client.println("<button type='button' class='button button2' onClick=location.href='/LED=OFF'> APAGAR </button><br><br>");
}
client.print("</body></html>");
client.println();
break;
}
En caso de que la longitud del valor de la variable currentLine no sea 0 se procede a asignarle un valor vacío. Y que se si no hay un caracter de retorno de carro en c todo se concatene en currentLine.
else { // Limpiando variable
currentLine = "";
}
} else if (c != '\r') { // Si no hay retorno de carro
currentLine += c; // agrega al final de la linea
}
La siguiente sección del código busca dentro de currentLine las direcciones que obtenemos al hacer clic en el botón de la página y modifica el estado del led de acuerdo a ello.
Por ejemplo. Si dentro hallamos “GET /LED=ON” quiere decir que presionamos el botón “ENCENDER”. En consecuencia, el pin del led se activará (HIGH) y la variable p cambiará a “on”.
Recuerda que en el código hay una sección que toma en cuenta el valor de p. En este caso al tener “on” el texto del botón será “APAGAR” y al hacer clic sobre él nos dirigirá a la dirección “/LED=ON”. Y así sucesivamente mientras se use el botón.
if (currentLine.indexOf("GET /LED=ON") != -1) {
digitalWrite(LED, HIGH); // GET /LED=ON
p = "on";
}
if (currentLine.indexOf("GET /LED=OFF") != -1) {
digitalWrite(LED, LOW); // GET /LED=OFF
p = "off";
}
Finalmente se cierra la conexión con el cliente.
client.stop();
Serial.println("Cliente Desconectado");
Demostración
Cuando el código empieza a ejecutarse podemos ver la dirección IP en el monitor serial.
Ahora debemos entrar a esa dirección desde el navegador de otro dispositivo conectado a la red, como un teléfono o computadora.
Cuando el sitio cargue veremos el título y botón que se creó con HTML en el ESP32.
Al mismo tiempo veremos un aviso de “nuevo cliente” en el monitor serial.
El led del ESP32 inicia apagado y al podemos cambiar su estado al presionar el botón que dice “ENCENDER”.
También podremos ver el cambio en la URL del sitio al presionar el botón.
Conclusiones
El ESP32 puede funcionar como un servidor web (WebServer) para cumplir las funciones de guardar un sitio web y atender las solicitudes de clientes.
Se puede interactuar con el ESP32 mediante la página web embebida así como mostrar información.
Como cualquier otro servidor web se hace uso del protocolo HTTP para comunicarnos con los clientes.
Te invitamos a tomar el curso de Introducción al ESP32: Introducción al ESP32 | TodoMaker’s School