Arduino - Servidor Web con Varias Páginas

En este tutorial, aprenderemos cómo convertir un Arduino en un servidor web que pueda manejar varias páginas al mismo tiempo, como index.html, temperature.html, led.html, error_404.html y error_405.html... El contenido de cada página, incluidos HTML, CSS y JavaScript, se almacenará en archivos diferentes en el IDE de Arduino. Al acceder al Arduino Web Server desde un navegador web en tu PC o teléfono inteligente, podrás ver y controlar sensores y actuadores conectados al Arduino a través de la web. Además, el servidor web estará diseñado para aceptar enlaces con o sin la extensión .html.

Navegador web de Arduino

Siguiendo este tutorial, podrás convertir tu Arduino en un servidor web con algunas características interesantes:

Puede parecer complicado, ¡pero no te preocupes! Este tutorial ofrece instrucciones paso a paso, y el código está diseñado para ser amigable para principiantes, asegurando que puedas comprenderlo fácilmente y crear tu propio servidor web de Arduino.

Acerca de Arduino Uno R4 y el Servidor Web

Si no estás familiarizado con Arduino Uno R4 y el servidor web (incluido el diagrama de pines, cómo funciona y la programación), puedes aprender sobre ellos a través de los siguientes tutoriales:

Cómo funciona un servidor web en Arduino

Cuando un navegador web envía una solicitud HTTP a la placa Arduino, el Arduino debe estar programado para realizar las siguientes tareas:

  • Crear un servidor web que pueda escuchar solicitudes HTTP desde el navegador web.
  • Leer la primera línea de la cabecera de la solicitud HTTP cuando reciba una solicitud HTTP.
  • Enrutar las solicitudes basándose en la primera línea de la solicitud HTTP para determinar qué páginas web debe devolver el Arduino.
  • (Opcional) Analizar la cabecera de la solicitud HTTP para identificar comandos de control enviados por el usuario.
  • (Opcional) Controlar los dispositivos conectados al Arduino en función de los comandos de control recibidos.
  • Enviar una respuesta HTTP de vuelta al navegador web, que incluye:
    • Una cabecera de respuesta HTTP.
    • El cuerpo de la respuesta HTTP, que contiene contenido HTML y (si procede) datos de sensores o el estado de los dispositivos.

    Al realizar estas tareas, el Arduino puede manejar eficazmente las solicitudes HTTP y proporcionar respuestas adecuadas al navegador web, lo que permite el control e interacción basados en la web con los dispositivos conectados al Arduino.

    La función de enrutamiento es la tarea más importante y se explicará en detalle. Otras partes están cubiertas en el tutorial Arduino - Web Server. Una vez que entiendas el algoritmo de enrutamiento, procederemos a ver el código completo de un servidor web con múltiples páginas.

Servidor Web de Arduino - Algoritmo de Enrutamiento

Antes de escribir código para la función de enrutamiento, deberías crear una lista de páginas web y sus métodos HTTP correspondientes que estén disponibles en Arduino. En este tutorial, solo soportaremos el método GET. Sin embargo, puedes ampliarlo fácilmente para incluir otros métodos HTTP si es necesario. A continuación, se muestra una lista de ejemplo:

  • GET página de inicio
  • GET página de temperatura
  • GET página de la puerta
  • GET página LED

Después de eso, necesitas crear una lista de las cabeceras de la primera línea de la solicitud HTTP correspondientes a la lista de páginas:

  • GET página de inicio:
    • GET /
    • GET /index.html
  • GET página de temperatura
    • GET /temperature.html
  • GET página de la puerta
    • GET /door
  • GET página de LED
    • GET /led.html

    En resumen, tenemos la siguiente lista:

    GET / GET /index.html GET /temperature.html GET /door.html GET /led.html

Código de Arduino - Servidor web de múltiples páginas

A continuación se presenta el código completo de Arduino que crea un servidor web con varias páginas. Para mantenerlo sencillo, el contenido HTML de cada página es muy simple y está incrustado directamente en el código de Arduino. En la próxima parte, aprenderemos cómo separar los contenidos HTML de cada página en archivos separados, lo que hará que el código esté más organizado y manejable.

/* * Este código de Arduino fue desarrollado por es.newbiely.com * Este código de Arduino se proporciona al público sin ninguna restricción. * Para tutoriales completos y diagramas de cableado, visite: * https://es.newbiely.com/tutorials/arduino/arduino-web-server-multiple-pages */ #include <UnoR4WiFi_WebServer.h> // WiFi credentials const char WIFI_SSID[] = "YOUR_WIFI_SSID"; // change your network SSID (name) const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD"; // change your network password // Create web server instance UnoR4WiFi_WebServer server; float getTemperature() { // YOUR SENSOR IMPLEMENTATION HERE // simulate the temperature value float temp_x100 = random(0, 10000); // a ramdom value from 0 to 10000 return temp_x100 / 100; // return the simulated temperature value from 0 to 100 in float } // Page handlers void handleHome(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { server.sendResponse(client, "This is home page"); } void handleTemperature(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { server.sendResponse(client, "This is temperature page"); } void handleDoor(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { server.sendResponse(client, "This is door page"); } void handleLed(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { server.sendResponse(client, "This is LED page"); } void handleNotFound(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { server.sendResponse(client, "Page Not Found"); } void setup() { Serial.begin(9600); delay(1000); Serial.println("Arduino Uno R4 WiFi - Multi-Page Web Server"); // Connect to WiFi Serial.print("Connecting to "); Serial.println(WIFI_SSID); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(" connected!"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); // Configure routes server.addRoute("/", handleHome); server.addRoute("/index", handleHome); server.addRoute("/index.html", handleHome); server.addRoute("/temperature", handleTemperature); server.addRoute("/temperature.html", handleTemperature); server.addRoute("/door", handleDoor); server.addRoute("/door.html", handleDoor); server.addRoute("/led", handleLed); server.addRoute("/led.html", handleLed); // Set custom 404 handler server.setNotFoundHandler(handleNotFound); // Start server server.begin(); Serial.println("\n=== Web Server Ready! ==="); Serial.print("Visit: http://"); Serial.println(WiFi.localIP()); } void loop() { server.handleClient(); }

Pasos R\u00e1pidos

  • Si esta es la primera vez que usas Arduino Uno R4, consulta cómo configurar el entorno para Arduino Uno R4 en Arduino IDE.
  • Abre el Administrador de Bibliotecas haciendo clic en el icono Administrador de Bibliotecas ubicado en el lado izquierdo del IDE de Arduino.
  • Busca Web Server for Arduino Uno R4 WiFi y localiza la biblioteca Web Server creada por DIYables.
  • Haz clic en el botón Instalar para agregar la biblioteca Web Server.
Biblioteca del servidor web de Arduino UNO R4
  • Copia el código anterior y ábrelo con el IDE de Arduino
  • Cambia la información de wifi (SSID y contraseña) en el código por la tuya
  • Haz clic en el botón Subir en el IDE de Arduino para subir el código al Arduino
  • Abre el Monitor serie
  • Revisa el resultado en el Monitor serie
COM6
Send
Connecting to YOUR_WIFI_SSID connected! IP address: 192.168.0.254 Starting web server on IP: 192.168.0.254 === Web Server Ready! === Visit: http://192.168.0.254
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  
  • Verás una dirección IP en el Monitor Serial, por ejemplo: 192.168.0.2
  • Escribe la siguiente lista uno por uno en la barra de direcciones de un navegador web en tu teléfono móvil o PC.
192.168.0.2 192.168.0.2/index 192.168.0.2/index.html 192.168.0.2/led 192.168.0.2/led.html 192.168.0.2/door 192.168.0.2/door.html 192.168.0.2/temperature 192.168.0.2/temperature.html 192.168.0.2/blabla 192.168.0.2/blabla.html
  • Por favor, tenga en cuenta que debe cambiar la 192.168.0.2 por la dirección IP que obtuvo en el Monitor Serial.
  • Verá las siguientes páginas: página de inicio, página de LED, página de la puerta, página de temperatura y la página No Encontrada.
  • También puede ver la salida en el Monitor Serial.

El código anterior tiene un contenido HTML muy simple para cada página. Pero si queremos crear una interfaz elegante con mucho HTML, el código puede hacerse grande y desordenado. Para simplificarlo, aprenderemos cómo separar el HTML del código de Arduino. Esto nos permite mantener el HTML en archivos separados, lo que facilita su gestión y uso.

Código de Arduino - Servidor web completo de varias páginas

  • Abre el IDE de Arduino.
  • Crea un nuevo sketch y asígnale un nombre, por ejemplo, ArduinoWebServer.ino.
  • Copia el código proporcionado y pégalo en ese archivo.
/* * Este código de Arduino fue desarrollado por es.newbiely.com * Este código de Arduino se proporciona al público sin ninguna restricción. * Para tutoriales completos y diagramas de cableado, visite: * https://es.newbiely.com/tutorials/arduino/arduino-web-server-multiple-pages */ #include <UnoR4WiFi_WebServer.h> #include "index.h" #include "temperature.h" #include "door.h" #include "led.h" #include "error_404.h" // WiFi credentials const char WIFI_SSID[] = "YOUR_WIFI_SSID"; // change your network SSID (name) const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD"; // change your network password // Create web server instance UnoR4WiFi_WebServer server; float getTemperature() { // YOUR SENSOR IMPLEMENTATION HERE // simulate the temperature value float temp_x100 = random(0, 10000); // a ramdom value from 0 to 10000 return temp_x100 / 100; // return the simulated temperature value from 0 to 100 in float } // Page handlers void handleHome(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { server.sendResponse(client, HTML_CONTENT_HOME); } void handleTemperature(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { String html = String(HTML_CONTENT_TEMPERATURE); html.replace("TEMPERATURE_MARKER", String(getTemperature(), 2)); server.sendResponse(client, html.c_str()); } void handleDoor(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { String html = String(HTML_CONTENT_DOOR); html.replace("DOOR_STATE_MARKER", "OPENED"); server.sendResponse(client, html.c_str()); } void handleLed(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { String html = String(HTML_CONTENT_LED); html.replace("LED_STATE_MARKER", "OFF"); server.sendResponse(client, html.c_str()); } void handleNotFound(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { String html = String(HTML_CONTENT_404 ); server.sendResponse(client, html.c_str()); } void setup() { Serial.begin(9600); delay(1000); Serial.println("Arduino Uno R4 WiFi - Multi-Page Web Server"); // Connect to WiFi Serial.print("Connecting to "); Serial.println(WIFI_SSID); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(" connected!"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); // Configure routes server.addRoute("/", handleHome); server.addRoute("/index", handleHome); server.addRoute("/index.html", handleHome); server.addRoute("/temperature", handleTemperature); server.addRoute("/temperature.html", handleTemperature); server.addRoute("/door", handleDoor); server.addRoute("/door.html", handleDoor); server.addRoute("/led", handleLed); server.addRoute("/led.html", handleLed); // Set custom 404 handler server.setNotFoundHandler(handleNotFound); // Start server server.begin(); Serial.println("\n=== Web Server Ready! ==="); Serial.print("Visit: http://"); Serial.println(WiFi.localIP()); } void loop() { server.handleClient(); }
  • Cambia la información de WiFi (SSID y contraseña) en el código por la tuya
  • Crea el archivo index.h en el IDE de Arduino haciendo:
    • Haz clic en el botón justo debajo del icono del monitor serie y elige New Tab, o usa las teclas Ctrl+Shift+N
    Arduino IDE 2 añade archivo
    • Escribe el nombre del archivo index.h y haz clic en el botón Aceptar
    Arduino IDE 2 añade el archivo index.h
    • Copie el código de abajo y péguelo en el archivo index.h.
    /* * Este código de Arduino fue desarrollado por es.newbiely.com * Este código de Arduino se proporciona al público sin ninguna restricción. * Para tutoriales completos y diagramas de cableado, visite: * https://es.newbiely.com/tutorials/arduino/arduino-web-server-multiple-pages */ const char *HTML_CONTENT_HOME = R""""( <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="icon" href="data:,"> <title>Home Page</title> </head> <body> <h1>Welcome to the Home Page</h1> <ul> <li><a href="/led">LED Page</a></li> <li><a href="/temperature">Temperature Page</a></li> <li><a href="/door">Door Page</a></li> </ul> </body> </html> )"""";
    • Del mismo modo, crea el archivo temperature.h en el IDE de Arduino con el siguiente contenido.
    /* * Este código de Arduino fue desarrollado por es.newbiely.com * Este código de Arduino se proporciona al público sin ninguna restricción. * Para tutoriales completos y diagramas de cableado, visite: * https://es.newbiely.com/tutorials/arduino/arduino-web-server-multiple-pages */ const char *HTML_CONTENT_TEMPERATURE = R""""( <!DOCTYPE html> <html> <head> <title>Arduino - Web Temperature</title> <meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=0.7"> <meta charset="utf-8"> <link rel="icon" href="https://diyables.io/images/page/diyables.svg"> <style> body { font-family: "Georgia"; text-align: center; font-size: width/2pt;} h1 { font-weight: bold; font-size: width/2pt;} h2 { font-weight: bold; font-size: width/2pt;} button { font-weight: bold; font-size: width/2pt;} </style> <script> var cvs_width = 200, cvs_height = 450; function init() { var canvas = document.getElementById("cvs"); canvas.width = cvs_width; canvas.height = cvs_height + 50; var ctx = canvas.getContext("2d"); ctx.translate(cvs_width/2, cvs_height - 80); update_view(TEMPERATURE_MARKER); } function update_view(temp) { var canvas = document.getElementById("cvs"); var ctx = canvas.getContext("2d"); var radius = 70; var offset = 5; var width = 45; var height = 330; ctx.clearRect(-cvs_width/2, -350, cvs_width, cvs_height); ctx.strokeStyle="blue"; ctx.fillStyle="blue"; //5-step Degree var x = -width/2; ctx.lineWidth=2; for (var i = 0; i <= 100; i+=5) { var y = -(height - radius)*i/100 - radius - 5; ctx.beginPath(); ctx.lineTo(x, y); ctx.lineTo(x - 20, y); ctx.stroke(); } //20-step Degree ctx.lineWidth=5; for (var i = 0; i <= 100; i+=20) { var y = -(height - radius)*i/100 - radius - 5; ctx.beginPath(); ctx.lineTo(x, y); ctx.lineTo(x - 25, y); ctx.stroke(); ctx.font="20px Georgia"; ctx.textBaseline="middle"; ctx.textAlign="right"; ctx.fillText(i.toString(), x - 35, y); } // shape ctx.lineWidth=16; ctx.beginPath(); ctx.arc(0, 0, radius, 0, 2 * Math.PI); ctx.stroke(); ctx.beginPath(); ctx.rect(-width/2, -height, width, height); ctx.stroke(); ctx.beginPath(); ctx.arc(0, -height, width/2, 0, 2 * Math.PI); ctx.stroke(); ctx.fillStyle="#e6e6ff"; ctx.beginPath(); ctx.arc(0, 0, radius, 0, 2 * Math.PI); ctx.fill(); ctx.beginPath(); ctx.rect(-width/2, -height, width, height); ctx.fill(); ctx.beginPath(); ctx.arc(0, -height, width/2, 0, 2 * Math.PI); ctx.fill(); ctx.fillStyle="#ff1a1a"; ctx.beginPath(); ctx.arc(0, 0, radius - offset, 0, 2 * Math.PI); ctx.fill(); temp = Math.round(temp * 100) / 100; var y = (height - radius)*temp/100.0 + radius + 5; ctx.beginPath(); ctx.rect(-width/2 + offset, -y, width - 2*offset, y); ctx.fill(); ctx.fillStyle="red"; ctx.font="bold 34px Georgia"; ctx.textBaseline="middle"; ctx.textAlign="center"; ctx.fillText(temp.toString() + "°C", 0, 100); } window.onload = init; </script> </head> <body> <h1>Arduino - Web Temperature</h1> <canvas id="cvs"></canvas> </body> </html> )"""";
    • De igual manera, crea el archivo door.h en el IDE de Arduino con el siguiente contenido.
    /* * Este código de Arduino fue desarrollado por es.newbiely.com * Este código de Arduino se proporciona al público sin ninguna restricción. * Para tutoriales completos y diagramas de cableado, visite: * https://es.newbiely.com/tutorials/arduino/arduino-web-server-multiple-pages */ const char *HTML_CONTENT_DOOR = R""""( <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="icon" href="data:,"> <title>Door Page</title> </head> <body> <h1>Door Page</h1> <p>Door State: <span style="color: red;">DOOR_STATE_MARKER</span></p> </body> </html> )"""";
    • Del mismo modo, crea el archivo led.h en el IDE de Arduino con el siguiente contenido.
    /* * Este código de Arduino fue desarrollado por es.newbiely.com * Este código de Arduino se proporciona al público sin ninguna restricción. * Para tutoriales completos y diagramas de cableado, visite: * https://es.newbiely.com/tutorials/arduino/arduino-web-server-multiple-pages */ const char *HTML_CONTENT_LED = R""""( <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="icon" href="data:,"> <title>LED Page</title> </head> <body> <h1>LED Page</h1> <p>LED State: <span style="color: red;">LED_STATE_MARKER</span></p> </body> </html> )"""";
    • Del mismo modo, cree el archivo error_404.h en el IDE de Arduino con el siguiente contenido.
    /* * Este código de Arduino fue desarrollado por es.newbiely.com * Este código de Arduino se proporciona al público sin ninguna restricción. * Para tutoriales completos y diagramas de cableado, visite: * https://es.newbiely.com/tutorials/arduino/arduino-web-server-multiple-pages */ const char *HTML_CONTENT_404 = R""""( <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="icon" href="data:,"> <title>404 - Page Not Found</title> <style> h1 {color: #ff4040;} </style> </head> <body> <h1>404</h1> <p>Oops! The page you are looking for could not be found on Arduino Web Server.</p> <p>Please check the URL or go back to the <a href="/">homepage</a>.</p> <p>Or check <a href="https://arduinogetstarted.com/tutorials/arduino-web-server-multiple-pages"> Arduino Web Server</a> tutorial.</p> </body> </html> )"""";
    • Ahora tienes varios archivos en el IDE de Arduino como se muestra a continuación:
    Arduino IDE 2 múltiples archivos
    • Haz clic en el botón Subir en el IDE de Arduino para subir código al Arduino
    • Accede a las páginas web de la placa Arduino a través del navegador web una por una como antes. Verás todas las páginas web como se muestran a continuación:
    Varias páginas web de Arduino

    ※ Nota:

    • Si realizas cambios en el contenido HTML dentro del archivo index.h pero no modificas nada en el archivo ArduinoWebServer.ino, el IDE de Arduino no actualizará ni refrescará el contenido HTML cuando compiles y subas el código al ESP32.
    • Para forzar al IDE de Arduino a actualizar el contenido HTML en esta situación, debes realizar una modificación en el archivo ArduinoWebServer.ino. Por ejemplo, puedes añadir una línea en blanco o insertar un comentario. Esta acción hace que el IDE reconozca que ha habido cambios en el proyecto, asegurando que tu contenido HTML actualizado se incluya en la subida.

※ NUESTROS MENSAJES

  • No dude en compartir el enlace de este tutorial. Sin embargo, por favor no use nuestro contenido en otros sitios web. Hemos invertido mucho esfuerzo y tiempo en crear el contenido, ¡por favor respete nuestro trabajo!