Servidor WebSocket no ESP32 - Tutorial de Comunicação em Tempo Real

Exemplo WebServerWithWebSocket - Comunicação em Tempo Real

Visão Geral

Este exemplo mostra como criar um servidor web avançado com várias páginas e comunicação WebSocket em tempo real no ESP32, permitindo a troca bidirecional de dados entre o navegador e o ESP32.

Recursos

  • Comunicação WebSocket em tempo real para mensagens bidirecionais instantâneas
  • Comandos simples baseados em string (ping, hello, time, led on/off)
  • Controle de LED por comandos WebSocket
  • Servidor HTTP integrado que serve a interface de teste do WebSocket
  • Função de eco para testar a transmissão de mensagens
  • Monitoramento do status da conexão com reconexão automática

Instalação da Biblioteca

Siga estas instruções passo a passo:

  • Se esta é a sua primeira vez usando o ESP32, consulte o tutorial sobre como configurar o ambiente do ESP32 no Arduino IDE.
  • Conecte a placa ESP32 ao seu computador com um cabo USB.
  • Abra o Arduino IDE no seu computador.
  • Selecione a placa ESP32 apropriada (por exemplo, ESP32) e a porta COM.
  • Abra o Library Manager clicando no ícone Library Manager no lado esquerdo do Arduino IDE.
  • Pesquise por Web Server for ESP32 e encontre a mWebSockets da DIYables.
  • Clique no botão Install para adicionar a biblioteca mWebSockets.
Biblioteca ESP32 Web Server

Exemplo de WebSocket

  • No Arduino IDE, vá em File Examples Web Server for ESP32 WebServerWithWebSocket para abrir o código do exemplo

Estrutura do Código

O projeto é composto por dois arquivos principais:

  1. websocket_html.h:

Contém o código HTML, CSS e JavaScript da interface web. Esse arquivo define a interface de usuário para interagir com o ESP32 via WebSocket, incluindo botões para enviar comandos, um registro de mensagens e indicadores do status da conexão.

  1. WebServerWithWebSocket.ino:

Implementa a lógica principal do servidor no ESP32. Esse arquivo configura os servidores HTTP e WebSocket, gerencia a conectividade WiFi, processa as mensagens WebSocket recebidas e controla o hardware (como o LED integrado) com base nos comandos recebidos.

Conexão do Circuito

Não são necessários componentes externos - este exemplo usa o LED integrado no pino 13.

Comunicação WebSocket

Detalhes da Conexão

  • Porta do Servidor Web: 80 (HTTP)
  • Porta do WebSocket: 81 (WebSocket)
  • Protocolo: WebSocket compatível com a RFC 6455

Tipos de Mensagem

A implementação real usa comandos simples em string:

  • Ping: "ping" → Resposta: "pong"
  • Saudação: "hello" → Resposta: "Hello from ESP32!"
  • Tempo ligado: "time" → Resposta: "Uptime: X seconds"
  • Controle do LED: "led on" / "led off" → Resposta: "LED ON" / "LED OFF"
  • Eco: Qualquer outro texto → Resposta: "Echo: [your message]"

Instruções de Configuração

1. Configuração da Rede

Edite as credenciais de WiFi diretamente no arquivo WebServerWithWebSocket.ino:

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

2. Faça o Upload do Código e Monitore a Saída

  • Conecte o ESP32 ao seu computador
  • Selecione a placa e a porta corretas no Arduino IDE
  • Faça o upload do sketch WebServerWithWebSocket.ino
  • Abra o Serial Monitor (9600 baud)
  • Aguarde a conexão WiFi
  • Anote os endereços dos servidores HTTP e WebSocket
  • Se você não vir o endereço IP no Serial Monitor, pressione o botão de reset na placa ESP32
  • Abra um navegador e digite o endereço IP do ESP32 na barra de endereços (por exemplo, http://192.168.x.x/). Você verá a interface web como a abaixo:
Interface WebSocket do ESP32
  • Clique no botão "Connect" para conectar a página web ao ESP32 via WebSocket.
  • Quando o status da conexão mostrar "Connected", clique em cada botão, um por um, para testar a comunicação bidirecional entre a interface web e o ESP32 via WebSocket. O resultado será como abaixo:
Demonstração do WebSocket no ESP32

Recursos da Interface Web

A interface HTML (do arquivo websocket_html.h) oferece:

  • Gerenciamento da conexão WebSocket com botões de conectar/desconectar
  • Botões de comando simples para ping, hello, time e LED ligado/desligado
  • Campo de entrada de mensagem para enviar comandos personalizados
  • Histórico de mensagens em tempo real mostrando as mensagens enviadas e recebidas
  • Indicador de status da conexão mostrando o estado do WebSocket

Explicação do Código

Configuração do 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(); }

Tratamento de Mensagens 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()); }

Loop Principal com Processamento do 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 em JavaScript

Gerenciamento da Conexão

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'); }; }

Tratamento de Mensagens

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'); }

Recursos da Interface HTML

Interface de Teste do WebSocket

A página HTML incluída oferece uma interface completa de teste do WebSocket:

  • Controles de conexão com a função de conectar/desconectar
  • Botões de comando rápido para os comandos comuns (ping, hello, time, controle do LED)
  • Campo de entrada de mensagem para enviar comandos de texto personalizados
  • Registro de mensagens em tempo real mostrando toda a comunicação
  • Exibição do status da conexão com indicadores visuais

Funções JavaScript Integradas

A interface HTML inclui funções JavaScript que correspondem à estrutura de comandos do 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'); };

Observações sobre a Implementação

Arquitetura Simplificada

A implementação real usa uma abordagem básica:

  • Servidores separados: WiFiServer para HTTP e WebSocketServer para WebSocket
  • Conexão WiFi manual: Configuração padrão com WiFi.begin(), sem gerenciamento de servidor integrado
  • Mensagens baseadas em string: Comandos simples em string em vez de protocolos JSON
  • Tratadores lambda: Os tratadores de eventos do WebSocket são definidos como funções lambda inline
  • Serviço HTML básico: Envio direto do conteúdo HTML do arquivo de cabeçalho com client.print()

Limitações da Implementação Atual

  • Sem streaming de dados de sensores (como mostrado nos exemplos da documentação)
  • Sem análise de mensagens JSON
  • Sem transmissão (broadcast) para vários clientes
  • Sem gerenciamento de conexão além do conectar/desconectar básico
  • Sem sistema de heartbeat ou keepalive
  • Sem fila de mensagens nem recursos de confiabilidade

Comandos Disponíveis

Os comandos que funcionam na implementação real:

  • ping → pong
  • hello → Hello from ESP32!
  • time → Uptime: X seconds
  • led on → LED ON (liga o LED_PIN)
  • led off → LED OFF (desliga o LED_PIN)
  • Qualquer outro texto → Echo: [your message]

Solução de Problemas

Problemas Comuns

Falha na Conexão WebSocket

  • Verifique se a porta do WebSocket (81) está acessível
  • Confirme que as configurações do firewall não bloqueiam a porta 81
  • Use as ferramentas de desenvolvedor do navegador para verificar erros do WebSocket
  • Confirme que o endereço IP do ESP32 está correto

Mensagens Não Recebidas

  • Verifique no Serial Monitor os eventos do WebSocket e o recebimento de mensagens
  • Confirme que as strings de comando coincidem exatamente (sem diferenciar maiúsculas de minúsculas)
  • Teste primeiro com comandos simples, como "ping"

LED Não Responde

  • Confirme que o LED_PIN está definido corretamente para a sua placa ESP32 (normalmente GPIO 2)
  • Verifique no Serial Monitor as mensagens de processamento de comandos
  • Confirme que os comandos "led on" e "led off" são enviados exatamente assim

Comandos de Depuração

Use estes comandos para testar a funcionalidade do WebSocket:

  • ping - Teste simples de conectividade
  • hello - Teste de resposta de saudação
  • time - Teste do tempo ligado do ESP32
  • led on / led off - Teste de controle de hardware
  • Qualquer outro texto será devolvido como eco para testar a comunicação

Aplicações no Mundo Real

Controle IoT Básico

A implementação simples atual é adequada para:

  • Controle remoto de LED para indicação básica do status de um dispositivo
  • Sistemas simples de comando/resposta para interação com dispositivos
  • Teste de conectividade WebSocket para fins de desenvolvimento
  • Demonstrações básicas de comunicação em tempo real

Possíveis Melhorias

Para ampliar este exemplo para uso em produção, considere adicionar:

  • Análise de mensagens JSON para dados estruturados
  • Recursos de streaming de dados de sensores
  • Gerenciamento de conexões de vários clientes
  • Recursos de autenticação e segurança
  • Tratamento de erros e lógica de reconexão

Próximos Passos

  • Adicione a análise de mensagens JSON usando a biblioteca ArduinoJson
  • Integre sensores reais (temperatura, umidade, etc.)
  • Implemente a transmissão (broadcast) para vários clientes WebSocket
  • Adicione autenticação para acesso seguro
  • Crie interfaces de aplicativos móveis usando conexões WebSocket

※ NOSSAS MENSAGENS

  • Fique à vontade para compartilhar o link deste tutorial. Porém, por favor, não use nosso conteúdo em outros sites. Investimos muito esforço e tempo para criar este conteúdo, por favor respeite nosso trabalho!