Servindo Páginas HTML Simples com o ESP32

O ESP32 é um microcontrolador poderoso que oferece conectividade Wi-Fi e Bluetooth integradas. Uma das aplicações mais interessantes é a capacidade de hospedar um servidor web, permitindo que o dispositivo sirva páginas HTML e interaja com usuários através de uma interface web. Neste artigo, vamos explorar como servir páginas HTML simples utilizando o ESP32.

Por que Servir Páginas HTML com o ESP32?🔗

Servir páginas HTML diretamente do ESP32 abre um mundo de possibilidades para projetos de automação e IoT. Com isso, é possível:

  • Monitorar sensores em tempo real: Exibir dados coletados pelo ESP32 diretamente em uma página web acessível por qualquer dispositivo na mesma rede.
  • Controlar dispositivos: Acionar relés, LEDs e outros atuadores através de botões e controles em uma interface web.
  • Configurar o dispositivo: Permitir que usuários alterem configurações sem a necessidade de reprogramar o ESP32.

Pré-requisitos🔗

Antes de começar, certifique-se de ter:

  • ESP32: Qualquer placa de desenvolvimento com o microcontrolador ESP32.
  • Ambiente de Desenvolvimento Arduino IDE: Configurado para programar o ESP32.
  • Conhecimentos básicos de HTML: Será útil entender a estrutura das páginas que vamos servir.

Configurando o Ambiente🔗

Para servir páginas HTML, precisamos:

1. Conectar o ESP32 à rede Wi-Fi: O ESP32 atuará como servidor, então deve estar conectado à mesma rede dos dispositivos que acessarão as páginas.

2. Configurar o servidor web: Utilizar bibliotecas específicas para criar o servidor e definir rotas.

3. Criar o conteúdo HTML: Escrever a página que será servida.

Conectando o ESP32 à Rede Wi-Fi🔗

Primeiramente, vamos conectar o ESP32 à rede Wi-Fi. Para isso, utilizaremos a biblioteca WiFi.h.

#include <WiFi.h>
const char* ssid = "NOME_DA_REDE";
const char* password = "SENHA_DA_REDE";
void setup()
{
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.print("Conectando-se à rede Wi-Fi");
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("Conectado! Endereço IP: ");
  Serial.println(WiFi.localIP());
}
void loop()
{
  // Código principal
}
Explicação:
  • WiFi.begin(ssid, password);: Inicia a conexão com a rede especificada.
  • WiFi.status(): Verifica o status da conexão.
  • WiFi.localIP(): Obtém o endereço IP atribuído ao ESP32.

Configurando o Servidor Web🔗

Com a conexão estabelecida, é hora de configurar o servidor web. Usaremos a biblioteca WebServer.h.

#include <WebServer.h>
WebServer server(80); // Cria um servidor na porta 80
void setup()
{
  // Código de conexão Wi-Fi (como no exemplo anterior)
  // Inicia o servidor
  server.begin();
  Serial.println("Servidor web iniciado");
}
void loop()
{
  server.handleClient(); // Lida com clientes conectados
}

Servindo uma Página HTML Simples🔗

Para servir uma página, precisamos definir uma rota e o conteúdo que será enviado ao cliente.

void handleRoot()
{
  String html = "<!DOCTYPE html><html><head><title>Página ESP32</title></head><body><h1>Olá, mundo!</h1><p>Esta é uma página servida pelo ESP32.</p></body></html>";
  server.send(200, "text/html", html);
}
void setup()
{
  // Código anterior
  // Define a rota raiz
  server.on("/", handleRoot);
  // Inicia o servidor
  server.begin();
  Serial.println("Servidor web iniciado");
}
void loop()
{
  server.handleClient();
}
Explicação:
  • server.on("/", handleRoot);: Define que, quando a raiz (/) for acessada, a função handleRoot será chamada.
  • server.send(200, "text/html", html);: Envia uma resposta HTTP com código 200 (OK), especificando o tipo de conteúdo (text/html) e o conteúdo em si.

Testando o Servidor Web🔗

Após carregar o código no ESP32:

1. Abra o monitor serial: Para obter o endereço IP do ESP32.

2. No navegador, digite o endereço IP exibido no monitor serial.

Você deverá ver a página com a mensagem "Olá, mundo!".

Melhorando o Código HTML🔗

Para tornar o código mais legível e gerenciável, podemos armazenar o conteúdo HTML como uma constante do tipo char.

const char index_html[] = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
  <title>Página ESP32</title>
</head>
<body>
  <h1>Olá, mundo!</h1>
  <p>Esta é uma página servida pelo ESP32.</p>
</body>
</html>
)rawliteral";
void handleRoot()
{
  server.send(200, "text/html", index_html);
}
Explicação:
  • R"rawliteral(...)": Permite inserir strings multilinhas sem a necessidade de caracteres de escape.

Adicionando Estilo à Página🔗

Podemos incluir CSS para melhorar a aparência.

const char index_html[] = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
  <title>Página ESP32</title>
  <style>
    body { font-family: Arial, sans-serif; text-align: center; }
    h1 { color: #0275d8; }
    p { font-size: 1.2em; }
  </style>
</head>
<body>
  <h1>Bem-vindo ao ESP32</h1>
  <p>Esta é uma página servida pelo ESP32.</p>
</body>
</html>
)rawliteral";

Criando Rotas Adicionais🔗

Podemos adicionar novas rotas para servir diferentes páginas ou executar ações específicas.

void handleNotFound()
{
  server.send(404, "text/plain", "Página não encontrada");
}
void setup()
{
  // Código anterior
  // Rota raiz
  server.on("/", handleRoot);
  // Rota para /sobre
  server.on("/sobre", []()
  {
    server.send(200, "text/plain", "Esta é a página Sobre.");
  });
  // Tratamento para páginas não encontradas
  server.onNotFound(handleNotFound);
  // Inicia o servidor
  server.begin();
}
Explicação:
  • server.on("/sobre", ...);: Define uma nova rota /sobre.
  • server.onNotFound(handleNotFound);: Define o que acontece quando uma rota não existente é acessada.

Interagindo com o ESP32 via Web🔗

Além de servir páginas estáticas, podemos interagir com o hardware do ESP32.

Controlando um LED

Vamos adicionar um LED ao pino GPIO 2 e controlá-lo através da interface web.

Circuito:
  • Conecte um LED ao pino GPIO 2 com um resistor apropriado.
Código:
#define LED_PIN 2
void handleLEDOn()
{
  digitalWrite(LED_PIN, HIGH);
  server.send(200, "text/plain", "LED aceso");
}
void handleLEDOff()
{
  digitalWrite(LED_PIN, LOW);
  server.send(200, "text/plain", "LED apagado");
}
void setup()
{
  pinMode(LED_PIN, OUTPUT);
  // Código de configuração do Wi-Fi e servidor
  // Rota para acender o LED
  server.on("/led/on", handleLEDOn);
  // Rota para apagar o LED
  server.on("/led/off", handleLEDOff);
  // Inicia o servidor
  server.begin();
}
Testando:
  • Acesse http://ENDERECO_IP/led/on para acender o LED.
  • Acesse http://ENDERECO_IP/led/off para apagar o LED.

Integrando Botões na Página

Podemos tornar o controle mais intuitivo adicionando botões na página HTML.

Atualize o conteúdo HTML:
const char index_html[] = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
  <title>Controle de LED</title>
  <style>
    body { font-family: Arial, sans-serif; text-align: center; }
    h1 { color: #0275d8; }
    button {
      padding: 15px 25px;
      font-size: 24px;
      margin: 20px;
      cursor: pointer;
    }
  </style>
</head>
<body>
  <h1>Controle de LED com ESP32</h1>
  <button onclick="fetch('/led/on')">Acender LED</button>
  <button onclick="fetch('/led/off')">Apagar LED</button>
</body>
</html>
)rawliteral";
Explicação:
  • onclick="fetch('/led/on')": Quando o botão é clicado, faz uma requisição à rota especificada.
  • fetch(): Função JavaScript para realizar requisições HTTP.

Lendo Dados do ESP32🔗

Além de enviar comandos, podemos ler informações do ESP32, como o estado do LED ou valores de sensores.

Exibindo o Estado do LED

Vamos modificar a função que trata a rota raiz para exibir o estado atual do LED.

void handleRoot()
{
  String ledState = digitalRead(LED_PIN) ? "Aceso" : "Apagado";
  String html = "<!DOCTYPE html><html><head><title>Estado do LED</title></head><body><h1>Estado do LED: " + ledState + "</h1></body></html>";
  server.send(200, "text/html", html);
}
Explicação:
  • digitalRead(LED_PIN): Lê o estado atual do pino do LED.
  • ledState: Armazena uma string baseada no estado do LED.

Melhorando a Interatividade com AJAX🔗

Para atualizar informações na página sem recarregá-la completamente, podemos utilizar AJAX.

Atualize o conteúdo HTML:
<button onclick="acenderLED()">Acender LED</button>
<button onclick="apagarLED()">Apagar LED</button>
<p id="status">Estado do LED: ...</p>
<script>
function acenderLED()
{
  fetch('/led/on').then(actualizarEstado);
}
function apagarLED()
{
  fetch('/led/off').then(actualizarEstado);
}
function atualizarEstado()
{
  fetch('/led/status')
    .then(response => response.text())
    .then(state => {
      document.getElementById('status').innerText = 'Estado do LED: ' + state;
    });
}
// Atualiza o estado ao carregar a página
window.onload = actualizarEstado;
</script>
No código do ESP32, adicione:
void handleLEDStatus()
{
  String ledState = digitalRead(LED_PIN) ? "Aceso" : "Apagado";
  server.send(200, "text/plain", ledState);
}
void setup()
{
  // Rotas anteriores
  // Rota para obter o estado do LED
  server.on("/led/status", handleLEDStatus);
  // Inicia o servidor
  server.begin();
}
Explicação:
  • Funções JavaScript: acenderLED(), apagarLED() e atualizarEstado() gerenciam as requisições e atualizam a página.
  • /led/status: Nova rota para obter o estado atual do LED.

Considerações de Segurança🔗

Embora este exemplo seja básico, é importante considerar aspectos de segurança em aplicações reais:

  • Restringir o acesso: Implementar autenticação para evitar que qualquer usuário na rede possa controlar o dispositivo.
  • Sanitizar entradas: Proteger o servidor contra ataques como injeção de código.

Conclusão🔗

Servir páginas HTML simples com o ESP32 é uma maneira eficaz de criar interfaces para controlar e monitorar dispositivos. A partir deste ponto, é possível expandir o projeto para incluir:

  • Design responsivo: Adaptar a interface para diferentes dispositivos (computadores, tablets, smartphones).
  • Controle de múltiplos dispositivos: Gerenciar vários atuadores e sensores.
  • Integração com serviços externos: Enviar dados para a nuvem ou interagir com APIs.

A chave é entender os princípios básicos de como o ESP32 pode servir conteúdo web e interagir com os usuários. Com criatividade e conhecimento, as possibilidades são infinitas.

Próximos Passos🔗

  • Explorar CSS e JavaScript: Para melhorar a experiência do usuário.
  • Implementar WebSockets: Para comunicação em tempo real entre o ESP32 e o navegador.
  • Adicionar segurança: Implementar HTTPS e autenticação.

A jornada com o ESP32 e o desenvolvimento web está apenas começando. Continue explorando e aprimorando suas habilidades para criar projetos cada vez mais completos e inovadores.

Autor: Marcelo V. Souza - Engenheiro de Sistemas e Entusiasta em IoT e Desenvolvimento de Software, com foco em inovação tecnológica.

Referências🔗

Artigos Relacionados