Servidor WebSocket ESP32 - Tutorial de Comunicación en Tiempo Real

Ejemplo de WebServerWithWebSocket - Comunicación en tiempo real

Vista general

Este ejemplo demuestra cómo crear un servidor web avanzado de múltiples páginas con comunicación WebSocket en tiempo real en ESP32, permitiendo el intercambio bidireccional de datos entre el navegador y el ESP32.

Características

  • Comunicación WebSocket en tiempo real para mensajería bidireccional instantánea
  • Comandos simples basados en cadenas (ping, hola, hora, LED encendido/apagado)
  • Control del LED mediante comandos WebSocket
  • Servidor HTTP integrado que sirve la interfaz de prueba de WebSocket
  • Funcionalidad de eco para probar la transmisión de mensajes
  • Monitoreo del estado de la conexión con reconexión automática

Hardware Requerido

1×Módulo de Desarrollo ESP32 ESP-WROOM-32
1×Cable USB Tipo-A a Tipo-C (para PC USB-A)
1×Cable USB Tipo-C a Tipo-C (para PC USB-C)
1×(Recomendado) Placa de Expansión de Terminales de Tornillo para ESP32
1×(Recomendado) Breakout Expansion Board for ESP32
1×(Recomendado) Divisor de Alimentación para ESP32

Or you can buy the following kits:

1×DIYables ESP32 Starter Kit (ESP32 included)
1×DIYables Sensor Kit (30 sensors/displays)
1×DIYables Sensor Kit (18 sensors/displays)
Divulgación: Algunos de los enlaces proporcionados en esta sección son enlaces de afiliado de Amazon. Podemos recibir una comisión por las compras realizadas a través de estos enlaces sin costo adicional para usted. Apreciamos su apoyo.

Instalación de la biblioteca

Sigue estas instrucciones paso a paso:

  • Si es la primera vez que usas el ESP32, consulta el tutorial sobre configurar el entorno para ESP32 en el IDE de Arduino.
  • Conecta la placa ESP32 a tu computadora usando un cable USB.
  • Inicia el IDE de Arduino en tu computadora.
  • Selecciona la placa ESP32 adecuada (p. ej., ESP32) y el puerto COM.
  • Abre el Administrador de Bibliotecas haciendo clic en el icono de Administrador de Bibliotecas en el lado izquierdo del IDE de Arduino.
  • Busca Servidor Web para ESP32 y localiza el mWebSockets de DIYables.
  • Haz clic en el botón Instalar para agregar la biblioteca mWebSockets.
Librería del servidor web ESP32

Ejemplo de WebSocket

  • En el IDE de Arduino, ve a Archivo Ejemplos Servidor Web para ESP32 WebServerWithWebSocket ejemplo para abrir el código de ejemplo

Estructura de código

El proyecto consta de dos archivos principales:

  1. websocket_html.h:

Contiene el código HTML, CSS y JavaScript para la interfaz web. Este archivo define la interfaz de usuario para interactuar con el ESP32 a través de WebSocket, incluyendo botones para enviar comandos, un registro de mensajes y indicadores de estado de la conexión.

i. WebServerWithWebSocket.ino:

Implementa la lógica principal del servidor en el ESP32. Este archivo configura los servidores HTTP y WebSocket, gestiona la conectividad WiFi, procesa los mensajes entrantes de WebSocket y controla el hardware (como el LED integrado) según los comandos recibidos.

Conexión del circuito

No se requieren componentes externos: este ejemplo utiliza el LED incorporado en el pin 13.

Comunicación WebSocket

Detalles de la conexión

  • Puerto del servidor web: 80 (HTTP)
  • Puerto de WebSocket: 81 (WebSocket)
  • Protocolo: WebSocket compatible con RFC 6455

Tipos de mensajes

La implementación real utiliza comandos de cadena simples:

  • Ping: "ping" → Respuesta: "pong"
  • Saludo: "hello" → Respuesta: "¡Hola desde ESP32!"
  • Tiempo de actividad: "time" → Respuesta: "Tiempo de actividad: X segundos"
  • Control de LED: "led on" / "led off" → Respuesta: "LED ENCENDIDO" / "LED APAGADO"
  • Eco: Cualquier otro texto → Respuesta: "Eco: [tu mensaje]"

Instrucciones de configuración

1. Configuración de red

Edita las credenciales de WiFi directamente en el archivo WebServerWithWebSocket.ino:

const char WIFI_SSID[] = "YOUR_WIFI_SSID"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";

2. Subir código y monitorear la salida

  • Conecta tu ESP32 a tu ordenador
  • Selecciona la placa y el puerto correctos en Arduino IDE
  • Carga el sketch WebServerWithWebSocket.ino
  • Abre el Monitor Serial (baudios de 9600)
  • Espera la conexión a WiFi
  • Anota las direcciones de los servidores HTTP y WebSocket
  • Si no ves la dirección IP en el Monitor Serial, presiona el botón de reinicio en la placa ESP32
  • Abre un navegador web y escribe la dirección IP del ESP32 en la barra de direcciones (p. ej., http://192.168.x.x/). Verás que la interfaz web se ve como se muestra a continuación:
Interfaz WebSocket de ESP32
  • Haz clic en el botón 'Conectar' para conectar la página web al ESP32 mediante WebSocket.
  • Una vez que el estado de la conexión muestre 'Conectado', haz clic en cada botón uno por uno para probar la comunicación bidireccional entre la interfaz web y el ESP32 mediante WebSocket. El resultado será como se muestra a continuación:
Demostración de WebSocket en ESP32

Características de la interfaz web

La interfaz HTML (de websocket_html.h) proporciona:

  • Gestión de la conexión WebSocket con botones de conectar/desconectar
  • Botones de comandos simples para ping, hola, hora, LED encendido/apagado
  • Campo de entrada de mensajes para enviar comandos personalizados
  • Historial de mensajes en tiempo real que muestra mensajes enviados y recibidos
  • Indicador de estado de conexión que muestra el estado de WebSocket

Explicación del código

Configuración del servidor WebSocket

#include <DIYables_ESP32_WebServer.h> #include "websocket_html.h" // LED configuration #define LED_PIN 2 // ESP32 built-in LED pin // Server configuration WiFiServer httpServer(80); constexpr uint16_t wsPort = 81; WebSocketServer wss{wsPort}; void setup() { Serial.begin(9600); delay(1000); // Initialize built-in LED pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); // Connect to WiFi manually Serial.print("Connecting to "); Serial.println(WIFI_SSID); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } // Start HTTP server httpServer.begin(); // Configure WebSocket server with lambda handlers wss.onConnection([](WebSocket &ws) { Serial.println("New WebSocket connection"); // Set up message handler ws.onMessage([](WebSocket &ws, const WebSocket::DataType dataType, const char *message, uint16_t length) { handleWebSocketMessage(ws, message, length); }); // Send welcome message const char welcome[] = "Connected to ESP32!"; ws.send(WebSocket::DataType::TEXT, welcome, strlen(welcome)); }); // Start WebSocket server wss.begin(); }

Manejo de mensajes de WebSocket

void handleWebSocketMessage(WebSocket &ws, const char *message, uint16_t length) { Serial.print("[WebSocket] Received ("); Serial.print(length); Serial.print(" bytes): "); Serial.println(message); String msgStr = String(message); String response = ""; // Command processing with simple string matching if (msgStr.equalsIgnoreCase("ping")) { response = "pong"; } else if (msgStr.equalsIgnoreCase("hello")) { response = "Hello from ESP32!"; } else if (msgStr.equalsIgnoreCase("time")) { response = "Uptime: " + String(millis()/1000) + " seconds"; } else if (msgStr.equalsIgnoreCase("led on")) { digitalWrite(LED_PIN, HIGH); response = "LED ON"; } else if (msgStr.equalsIgnoreCase("led off")) { digitalWrite(LED_PIN, LOW); response = "LED OFF"; } else { response = "Echo: " + msgStr; } // Send response ws.send(WebSocket::DataType::TEXT, response.c_str(), response.length()); }

Bucle principal con procesamiento de WebSocket

void loop() { // Handle HTTP requests WiFiClient httpClient = httpServer.available(); if (httpClient) { handleHTTPClient(httpClient); } // Handle WebSocket connections wss.listen(); delay(10); } // HTTP request handler void handleHTTPClient(WiFiClient client) { String request = ""; // Read HTTP request while (client.connected() && client.available()) { String line = client.readStringUntil('\n'); if (line == "\r") break; if (request.length() == 0) request = line; } // Serve web page or 404 if (request.indexOf("GET / HTTP") >= 0) { client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); client.println(); client.print(htmlPage); } else { client.println("HTTP/1.1 404 Not Found"); client.println("Connection: close"); client.println(); } client.stop(); }

Cliente WebSocket de JavaScript

Gestión de Conexiones

let websocket; let isConnected = false; function initWebSocket() { const wsUrl = `ws://${window.location.hostname}:81/`; websocket = new WebSocket(wsUrl); websocket.onopen = function(event) { console.log('WebSocket connected'); isConnected = true; updateConnectionStatus('Connected'); }; websocket.onmessage = function(event) { handleWebSocketMessage(JSON.parse(event.data)); }; websocket.onclose = function(event) { console.log('WebSocket disconnected'); isConnected = false; updateConnectionStatus('Disconnected'); // Auto-reconnect after 3 seconds setTimeout(initWebSocket, 3000); }; websocket.onerror = function(error) { console.error('WebSocket error:', error); updateConnectionStatus('Error'); }; }

Manejo de mensajes

function handleWebSocketMessage(event) { const message = event.data; console.log('Received:', message); // Handle simple string responses (matching actual implementation) if (message === 'pong') { console.log('Ping response received'); addMessageToHistory('Received: pong'); } else if (message.startsWith('Hello from ESP32')) { addMessageToHistory('Received: ' + message); } else if (message.startsWith('Uptime:')) { updateUptimeDisplay(message); addMessageToHistory('Received: ' + message); } else if (message === 'LED ON' || message === 'LED OFF') { updateLedStatus(message); addMessageToHistory('Received: ' + message); } else if (message.startsWith('Echo:')) { addMessageToHistory('Received: ' + message); } else { addMessageToHistory('Received: ' + message); } }

Enviando comandos

// Simple string-based command sending (matching actual implementation) function sendCommand(command) { if (isConnected) { websocket.send(command); addMessageToHistory('Sent: ' + command); } else { alert('WebSocket not connected!'); } } function controlLED(action) { if (action === 'on') { sendCommand('led on'); } else if (action === 'off') { sendCommand('led off'); } } function sendPing() { sendCommand('ping'); } function sendHello() { sendCommand('hello'); } function getUptime() { sendCommand('time'); }

Características de la interfaz HTML

Interfaz de prueba de WebSocket

La página HTML incluida proporciona una interfaz completa de pruebas de WebSocket:

  • Controles de conexión con la funcionalidad de conectar/desconectar
  • Botones de comandos rápidos para comandos comunes (ping, hola, hora, control de LED)
  • Campo de entrada de mensajes para enviar comandos de texto personalizados
  • Registro de mensajes en tiempo real que muestra toda la comunicación
  • Visualización del estado de la conexión con indicadores visuales

Funciones integradas de JavaScript

La interfaz HTML incluye funciones de JavaScript que coinciden con la estructura de comandos ESP32:

// Send simple string commands to ESP32 function sendQuick(msg) { if (connected && ws) { ws.send(msg); addMsg('You: ' + msg, 'sent'); } else { addMsg('Not connected!'); } } // Handle WebSocket events ws.onmessage = function(event) { console.log('WebSocket message received:', event.data); addMsg('ESP32: ' + event.data, 'received'); };

Notas de implementación

Arquitectura Simplificada

La implementación actual utiliza un enfoque básico:

  • Servidores separados: WiFiServer para HTTP y WebSocketServer para WebSocket
  • Conexión WiFi manual: Configuración estándar de WiFi.begin() sin gestión integrada del servidor
  • Mensajería basada en cadenas: Comandos simples basados en cadenas en lugar de protocolos JSON
  • Manejadores lambda: Manejadores de eventos WebSocket definidos como funciones lambda en línea
  • Servidor básico de HTML: Imprimir directamente con client.print() el contenido HTML desde un archivo de cabecera

Limitaciones de la implementación actual

  • No hay transmisión de datos de sensores (como se muestra en los ejemplos de la documentación)
  • No hay análisis de mensajes JSON
  • No hay transmisión a múltiples clientes
  • No hay gestión de conexiones más allá de conectar y desconectar básicos
  • No hay sistema de latido o keepalive
  • No hay colas de mensajes ni características de fiabilidad

Comandos Disponibles

Los comandos que funcionan en la implementación real:

  • pingpong
  • hello¡Hola desde ESP32!
  • timeTiempo de actividad: X segundos
  • led onLED ENCENDIDO (enciende LED_PIN)
  • led offLED APAGADO (apaga LED_PIN)
  • Cualquier otro texto → Eco: [tu mensaje]

Solución de problemas

Problemas comunes

Conexión WebSocket fallida

  • Verificar si el puerto de WebSocket (81) es accesible
  • Verificar que la configuración del firewall no bloquee el puerto 81
  • Usar las herramientas de desarrollo del navegador para verificar errores de WebSocket
  • Asegúrate de que la dirección IP del ESP32 sea correcta

Mensajes no recibidos

  • Verifica el Monitor Serial para eventos de WebSocket y la recepción de mensajes
  • Verifica que las cadenas de comandos coincidan exactamente (sin distinguir entre mayúsculas y minúsculas)
  • Prueba con comandos simples como "ping" primero

LED no responde

  • Asegúrate de que LED_PIN esté definido correctamente para tu placa ESP32 (típicamente GPIO 2)
  • Verifica el Monitor Serial para mensajes de procesamiento de comandos
  • Verifica que los comandos "led on" y "led off" se envíen exactamente

Comandos de depuración

Utilice estos comandos para probar la funcionalidad de WebSocket:

  • ping - Prueba de conectividad simple
  • hello - Prueba de respuesta a saludo
  • time - Prueba de tiempo de actividad del ESP32
  • led on / led off - Prueba de control de hardware
  • Cualquier otro texto se devolverá como eco para pruebas de comunicación

Aplicaciones del mundo real

Control Básico de IoT

La implementación simple actual es adecuada para:

  • Control remoto de LED para la indicación básica del estado del dispositivo
  • Sistemas simples de comandos y respuestas para la interacción con el dispositivo
  • Pruebas de conectividad WebSocket para fines de desarrollo
  • Comunicación en tiempo real básica demostraciones

Mejoras potenciales

Para ampliar este ejemplo para uso en producción, considere agregar:

  • Análisis de mensajes JSON para datos estructurados
  • Capacidades de transmisión de datos de sensores
  • Gestión de múltiples conexiones de clientes
  • Características de autenticación y seguridad
  • Manejo de errores y lógica de reconexión

Próximos pasos

  • Agregar análisis de mensajes JSON usando la biblioteca ArduinoJson
  • Integrar sensores reales (temperatura, humedad, etc.)
  • Implementar la transmisión a múltiples clientes WebSocket
  • Agregar autenticación para un acceso seguro
  • Crear interfaces de aplicaciones móviles utilizando conexiones WebSocket

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