Introdução ao uso de CSS e JavaScript no Web Server do ESP32

O ESP32 é uma poderosa ferramenta para projetos de automação e IoT, permitindo não apenas o controle de dispositivos, mas também a criação de interfaces web para interagir com eles. Ao desenvolver um servidor web no ESP32, é possível enriquecer a experiência do usuário utilizando CSS e JavaScript para aprimorar o design e a interatividade das páginas. Neste artigo, exploraremos como integrar CSS e JavaScript em seu web server do ESP32, proporcionando interfaces mais atraentes e funcionais.

Por que usar CSS e JavaScript no ESP32?🔗

Antes de mergulharmos nos detalhes técnicos, é importante compreender os benefícios de incorporar CSS e JavaScript em seu servidor web:

  • Estética aprimorada: O CSS permite estilizar suas páginas, tornando-as visualmente mais agradáveis.
  • Interatividade: O JavaScript adiciona dinamismo às páginas, permitindo respostas a eventos do usuário sem a necessidade de recarregar a página.
  • Melhor usabilidade: Interfaces mais intuitivas e responsivas melhoram a experiência do usuário ao interagir com seu dispositivo.

Preparando o Ambiente🔗

Para começar, certifique-se de que você tem o ambiente configurado para programar o ESP32:

1. Arduino IDE instalado: Baixe e instale a versão mais recente do Arduino IDE.

2. Bibliotecas do ESP32: Adicione o suporte ao ESP32 seguindo as instruções em Espressif Arduino Core.

Criando um Web Server Básico🔗

Vamos começar criando um servidor web simples que servirá como base para incorporar CSS e JavaScript.

#include <WiFi.h>
#include <WebServer.h>
const char* ssid = "SEU_SSID";
const char* password = "SUA_SENHA";
WebServer server(80);
void setup()
{
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.print("Conectando-se a ");
  Serial.println(ssid);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi conectado.");
  Serial.println("Endereço IP: ");
  Serial.println(WiFi.localIP());
  server.on("/", handleRoot);
  server.begin();
  Serial.println("Servidor HTTP iniciado.");
}
void loop()
{
  server.handleClient();
}
void handleRoot()
{
  String html = "<!DOCTYPE html><html><head><title>ESP32 Web Server</title></head><body><h1>Olá, mundo!</h1></body></html>";
  server.send(200, "text/html", html);
}

Neste código, configuramos o ESP32 para conectar-se a uma rede Wi-Fi e iniciar um servidor HTTP na porta 80. A função handleRoot() é responsável por enviar uma página HTML simples quando a raiz (/) é acessada.

Adicionando Estilos com CSS🔗

Para melhorar a aparência da página, podemos incorporar CSS diretamente no arquivo HTML ou servi-lo como um arquivo separado. Vamos começar adicionando estilos embutidos.

CSS Embutido

Modifique a função handleRoot():

void handleRoot()
{
  String html = "<!DOCTYPE html><html><head><title>ESP32 Web Server</title>";
  html += "<style>";
  html += "body { font-family: Arial, sans-serif; background-color: #f0f0f0; text-align: center; padding-top: 50px; }";
  html += "h1 { color: #333; }";
  html += "</style></head><body><h1>Olá, mundo!</h1></body></html>";
  server.send(200, "text/html", html);
}

Agora, a página terá um fundo cinza claro, texto centralizado e uma fonte mais agradável.

Servindo CSS Externo

Para uma abordagem mais organizada, é recomendável servir o CSS como um arquivo externo.

Armazenando o CSS no Código

Uma maneira simplificada é armazenar o CSS como uma string no código C++:

const char* css = "body { font-family: Arial, sans-serif; background-color: #f0f0f0; text-align: center; padding-top: 50px; } h1 { color: #333; }";
void handleCss()
{
  server.send(200, "text/css", css);
}
void setup()
{
  // Código anterior...
  server.on("/style.css", handleCss);
  // Código posterior...
}

Modifique a função handleRoot() para referenciar o arquivo CSS:

void handleRoot()
{
  String html = "<!DOCTYPE html><html><head><title>ESP32 Web Server</title>";
  html += "<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">";
  html += "</head><body><h1>Olá, mundo!</h1></body></html>";
  server.send(200, "text/html", html);
}

Dessa forma, o navegador irá solicitar o arquivo /style.css, e o ESP32 responderá com o conteúdo CSS armazenado em css.

Utilizando SPIFFS para Armazenar o CSS

Para projetos maiores, é eficiente armazenar arquivos CSS e JavaScript no sistema de arquivos SPIFFS do ESP32.

Passo 1: Habilitar o SPIFFS

No Arduino IDE, instale o plugin ESP32 SPIFFS para fazer upload de arquivos ao sistema de arquivos.

Passo 2: Preparar os Arquivos

Crie uma pasta chamada data no mesmo diretório do seu sketch. Dentro dela, crie o arquivo style.css com o seguinte conteúdo:

body {
  font-family: Arial, sans-serif; 
  background-color: #f0f0f0; 
  text-align: center; 
  padding-top: 50px;
}
h1 {
  color: #333;
}
Passo 3: Modificar o Código para Servir Arquivos do SPIFFS

Inclua as bibliotecas necessárias e monte o sistema de arquivos:

#include <SPIFFS.h>
void setup()
{
  // Código anterior...
  if(!SPIFFS.begin(true))
  {
    Serial.println("Falha ao montar o sistema de arquivos");
    return;
  }
  server.on("/", handleRoot);
  server.on("/style.css", handleCss);
  server.begin();
  // Código posterior...
}
void handleCss()
{
  File file = SPIFFS.open("/style.css", "r");
  if (!file)
  {
    server.send(404, "text/plain", "Arquivo não encontrado");
    return;
  }
  server.streamFile(file, "text/css");
  file.close();
}

Atualize a função handleRoot() se necessário. Agora, quando o navegador solicitar /style.css, o ESP32 servirá o arquivo diretamente do SPIFFS.

Passo 4: Fazer Upload dos Arquivos para o SPIFFS

No Arduino IDE, vá em Ferramentas -> ESP32 Sketch Data Upload. Isso fará o upload dos arquivos da pasta data para o sistema de arquivos do ESP32.

Adicionando Interatividade com JavaScript🔗

O JavaScript permite que sua página responda a ações do usuário sem a necessidade de recarregar a página. Vamos adicionar um botão que, quando clicado, faz uma requisição ao ESP32 para acender um LED conectado a um pino.

Configurando o Hardware

Conecte um LED ao pino GPIO 2 do ESP32, com um resistor limitador de corrente.

Atualizando o Código do Servidor

Controlando o LED

No código, configure o pino do LED e crie uma função para manipulá-lo:

#define LED_PIN 2
void setup()
{
  // Código anterior...
  pinMode(LED_PIN, OUTPUT);
  server.on("/led_on", handleLedOn);
  server.on("/led_off", handleLedOff);
  // Código posterior...
}
void handleLedOn()
{
  digitalWrite(LED_PIN, HIGH);
  server.send(200, "text/plain", "LED ligado");
}
void handleLedOff()
{
  digitalWrite(LED_PIN, LOW);
  server.send(200, "text/plain", "LED desligado");
}

Servindo o JavaScript

Crie um arquivo script.js na pasta data:

function toggleLED(state) {
  var xhttp = new XMLHttpRequest();
  xhttp.open("GET", state ? "/led_on" : "/led_off", true);
  xhttp.send();
}

Atualize a função handleRoot() para incluir o script:

void handleRoot()
{
  File file = SPIFFS.open("/index.html", "r");
  if (!file)
  {
    server.send(404, "text/plain", "Arquivo não encontrado");
    return;
  }
  server.streamFile(file, "text/html");
  file.close();
}

Crie um arquivo index.html na pasta data com o seguinte conteúdo:

<!DOCTYPE html>
<html>
<head>
  <title>Controle de LED com ESP32</title>
  <link rel="stylesheet" type="text/css" href="/style.css">
</head>
<body>
  <h1>Controle de LED</h1>
  <button onclick="toggleLED(true)">Ligar LED</button>
  <button onclick="toggleLED(false)">Desligar LED</button>
  <script src="/script.js"></script>
</body>
</html>

Finalmente, adicione o manipulador para o script.js:

void handleScript()
{
  File file = SPIFFS.open("/script.js", "r");
  if (!file)
  {
    server.send(404, "text/plain", "Arquivo não encontrado");
    return;
  }
  server.streamFile(file, "application/javascript");
  file.close();
}
// No setup(), registre o manipulador
server.on("/script.js", handleScript);

Faça o upload dos arquivos para o SPIFFS novamente usando o ESP32 Sketch Data Upload.

Funcionamento do JavaScript

O script script.js define a função toggleLED(state), que cria uma requisição assíncrona ao servidor:

  • Se state for true, envia uma requisição a /led_on.
  • Se state for false, envia uma requisição a /led_off.

Isso aciona as funções correspondentes no ESP32, que ligam ou desligam o LED.

Atualizando Dados em Tempo Real🔗

Podemos usar JavaScript para obter dados do ESP32 em tempo real, como a leitura de um sensor.

Leitura de um Sensor

Suponha que temos um sensor de temperatura conectado ao ESP32. Vamos simular essa leitura.

Código no ESP32

Adicione uma função que retorna um valor de temperatura:

void handleTemperature()
{
  float temperature = random(20, 30) + random(0, 99) / 100.0;
  String temp = String(temperature);
  server.send(200, "text/plain", temp);
}
void setup()
{
  // Código anterior...
  server.on("/temperature", handleTemperature);
  // Código posterior...
}

Atualizando o JavaScript

No script.js, adicione uma função para atualizar a temperatura:

function getTemperature() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temp").innerHTML = this.responseText + " °C";
    }
  };
  xhttp.open("GET", "/temperature", true);
  xhttp.send();
}
setInterval(function() {
  getTemperature();
}, 5000); // Atualiza a cada 5 segundos

Atualizando o HTML

No index.html, adicione um elemento para exibir a temperatura:

<h2>Temperatura Atual: <span id="temp">--</span></h2>

Com isso, a página irá atualizar a temperatura automaticamente a cada 5 segundos, sem que o usuário precise recarregar a página.

Considerações sobre Desempenho🔗

Ao servir páginas com CSS e JavaScript, é importante considerar:

  • Tamanho dos arquivos: O ESP32 possui recursos limitados. Otimize seus arquivos para serem o menor possível.
  • Armazenamento: Utilize o SPIFFS para armazenar arquivos estáticos, liberando espaço na memória do programa.
  • Cache: Configure cabeçalhos HTTP para permitir que o navegador cache arquivos estáticos, reduzindo a carga no ESP32.

Segurança Básica🔗

Embora o foco deste artigo não seja segurança, é importante lembrar:

  • Validação de Entrada: Sempre verifique e valide as requisições recebidas para evitar comportamentos indesejados.
  • Autenticação: Para aplicações sensíveis, implemente métodos de autenticação para restringir o acesso.

Conclusão🔗

Integrar CSS e JavaScript em seu web server do ESP32 permite criar interfaces web ricas e interativas, melhorando significativamente a experiência do usuário. Neste artigo, exploramos como estilizar páginas com CSS, adicionar interatividade com JavaScript e servir arquivos estáticos utilizando o SPIFFS. Com essas ferramentas, você pode desenvolver aplicações web completas diretamente no ESP32, abrindo um leque de possibilidades para projetos de automação e IoT.

Próximos Passos:
  • Experimente adicionar mais recursos à interface, como gráficos em tempo real.
  • Explore o uso de frameworks JavaScript leves, como o Vue.js, para interfaces mais complexas.
  • Considere implementar WebSockets para comunicação bidirecional em tempo real entre o ESP32 e o navegador.
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