Atualização Dinâmica de Páginas com AJAX no ESP32

Introdução🔗

Imagine acessar uma página web hospedada no seu ESP32 e ver dados sendo atualizados em tempo real, sem a necessidade de recarregar a página inteira. Isso é possível graças ao uso de AJAX (Asynchronous JavaScript and XML). Neste artigo, vamos explorar como implementar a atualização dinâmica de páginas web utilizando AJAX no ESP32. Vamos passo a passo entender os conceitos por trás dessa tecnologia e como aplicá-la em um projeto prático.

O que é AJAX?🔗

AJAX é um conjunto de técnicas que permite a troca de dados entre o cliente (navegador) e o servidor de forma assíncrona, sem a necessidade de recarregar a página inteira. Em outras palavras, AJAX permite atualizar partes específicas de uma página web dinamicamente, melhorando a experiência do usuário e tornando as aplicações web mais responsivas.

AJAX utiliza principalmente:

  • JavaScript: Para manipulação de elementos da página e solicitação de dados ao servidor.
  • XMLHttpRequest ou Fetch API: Para realizar solicitações assíncronas ao servidor.
  • JSON ou XML: Para formatar os dados trocados entre o cliente e o servidor.

Por que usar AJAX com ESP32?🔗

O ESP32 é um microcontrolador poderoso com capacidade de se conectar à internet e hospedar um servidor web. Ao utilizar AJAX com o ESP32, podemos:

  • Atualizar dados em tempo real: Ideal para monitoramento de sensores.
  • Reduzir o tráfego de dados: Apenas informações necessárias são transferidas.
  • Melhorar a experiência do usuário: Páginas mais fluidas sem recarregamentos completos.

Configurando o Ambiente🔗

Antes de começarmos, certifique-se de:

  • Ter o Arduino IDE instalado.
  • Ter as bibliotecas do ESP32 configuradas no Arduino IDE.
  • Dispor de um ESP32 e um cabo USB para programação.

Criando um Web Server Simples no ESP32🔗

Vamos iniciar criando um servidor web básico que servirá uma página HTML ao cliente.

Código no ESP32

#include <WiFi.h>
// Substitua pelos dados da sua rede Wi-Fi
const char* ssid = "SEU_SSID";
const char* password = "SUA_SENHA";
WiFiServer server(80);
void setup() 
{
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(1000);
    Serial.println("Conectando ao Wi-Fi...");
  }
  Serial.println("Conectado!");
  Serial.print("Endereço IP: ");
  Serial.println(WiFi.localIP());
  server.begin();
}
void loop() 
{
  WiFiClient client = server.available();
  if (client) 
  {
    String request = client.readStringUntil('\r');
    client.flush();
    String response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
    response += "<!DOCTYPE HTML><html><body><h1>Olá do ESP32!</h1></body></html>";
    client.print(response);
    delay(1);
    client.stop();
    Serial.println("Cliente desconectado.");
  }
}

Este código estabelece uma conexão Wi-Fi, inicia um servidor na porta 80 e serve uma página HTML simples com a mensagem "Olá do ESP32!".

Implementando AJAX para Atualização Dinâmica🔗

Agora, vamos modificar o código para incluir uma atualização dinâmica de dados usando AJAX.

Código em Arduino para o ESP32

Primeiramente, precisamos preparar o ESP32 para responder às solicitações AJAX enviadas pelo cliente.

#include <WiFi.h>
const char* ssid = "SEU_SSID";
const char* password = "SUA_SENHA";
WiFiServer server(80);
String header;
int valorSensor = 0;
void setup() 
{
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(1000);
    Serial.println("Conectando ao Wi-Fi...");
  }
  Serial.println("Conectado!");
  Serial.print("Endereço IP: ");
  Serial.println(WiFi.localIP());
  server.begin();
}
void loop() 
{
  WiFiClient client = server.available();
  if (client) 
  {
    String currentLine = "";
    while (client.connected()) 
    {
      if (client.available()) 
      {
        char c = client.read();
        header += c;
        if (c == '\n') 
        {
          if (currentLine.length() == 0) 
          {
            if (header.indexOf("GET /dados") >= 0) 
            {
              valorSensor = analogRead(34); // Exemplo de leitura de sensor
              String jsonResponse = "{\"valor\":" + String(valorSensor) + "}";
              client.println("HTTP/1.1 200 OK");
              client.println("Content-Type: application/json");
              client.println("Connection: close");
              client.println();
              client.println(jsonResponse);
              break;
            }
            else 
            {
              client.println("HTTP/1.1 200 OK");
              client.println("Content-Type: text/html");
              client.println("Connection: close");
              client.println();
              client.println(index_html);
              break;
            }
          }
          else 
          {
            currentLine = "";
          }
        }
        else if (c != '\r') 
        {
          currentLine += c;
        }
      }
    }
    header = "";
    client.stop();
  }
}
const char* index_html = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <title>ESP32 com AJAX</title>
  <meta http-equiv="refresh" content="30">
</head>
<body>
  <h1>Leitura do Sensor</h1>
  <p>Valor: <span id="valorSensor">0</span></p>
  <script>
    setInterval(function() {
      var xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
          var jsonResposta = JSON.parse(this.responseText);
          document.getElementById("valorSensor").innerHTML = jsonResposta.valor;
        }
      };
      xhttp.open("GET", "/dados", true);
      xhttp.send();
    }, 1000);
  </script>
</body>
</html>
)rawliteral";

Explicação do Código

No código acima, fizemos as seguintes alterações:

  • Leitura do Sensor: Simulamos a leitura de um sensor usando analogRead(34), onde o pino 34 é um pino analógico do ESP32.
  • Resposta a Solicitações AJAX: Quando o servidor recebe um GET /dados, ele responde com um JSON contendo o valor do sensor.
  • Página HTML com JavaScript: A página servida inclui um script que faz solicitações AJAX periódicas ao servidor para atualizar o valor do sensor na página.

Entendendo o Código JavaScript🔗

No trecho de código HTML, o script JavaScript faz o seguinte:

<script>
  setInterval(function() {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        var jsonResposta = JSON.parse(this.responseText);
        document.getElementById("valorSensor").innerHTML = jsonResposta.valor;
      }
    };
    xhttp.open("GET", "/dados", true);
    xhttp.send();
  }, 1000);
</script>
  • setInterval: Define uma função para ser executada a cada 1000 milissegundos (1 segundo).
  • XMLHttpRequest: Cria um objeto para realizar a solicitação AJAX.
  • onreadystatechange: Define uma função que é chamada sempre que o estado da solicitação muda.
  • responseText: Obtém a resposta do servidor como texto.
  • JSON.parse: Converte o texto JSON recebido em um objeto JavaScript.
  • Atualização do DOM: Atualiza o conteúdo do elemento com id valorSensor com o valor recebido.

Exemplo Prático: Monitorando Temperatura em Tempo Real🔗

Vamos agora implementar um exemplo prático onde o ESP32 lê a temperatura de um sensor (por exemplo, o DHT11) e atualiza essa informação em uma página web usando AJAX.

Componentes Necessários

  • ESP32
  • Sensor DHT11
  • Jumpers

Circuito

Conecte o sensor DHT11 ao ESP32 da seguinte forma:

  • VCC do DHT11 ao 3.3V do ESP32
  • GND do DHT11 ao GND do ESP32
  • Data do DHT11 ao pino GPIO 4 do ESP32

Código no ESP32

Inclua a biblioteca do DHT11 e ajuste o código:

#include <WiFi.h>
#include "DHT.h"
#define DHTPIN 4
#define DHTTYPE DHT11
const char* ssid = "SEU_SSID";
const char* password = "SUA_SENHA";
WiFiServer server(80);
String header;
DHT dht(DHTPIN, DHTTYPE);
void setup() 
{
  Serial.begin(115200);
  dht.begin();
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(1000);
    Serial.println("Conectando ao Wi-Fi...");
  }
  Serial.println("Conectado!");
  Serial.print("Endereço IP: ");
  Serial.println(WiFi.localIP());
  server.begin();
}
void loop() 
{
  WiFiClient client = server.available();
  if (client) 
  {
    String currentLine = "";
    while (client.connected()) 
    {
      if (client.available()) 
      {
        char c = client.read();
        header += c;
        if (c == '\n') 
        {
          if (currentLine.length() == 0) 
          {
            if (header.indexOf("GET /dados") >= 0) 
            {
              float temperatura = dht.readTemperature();
              String jsonResponse = "{\"temperatura\":" + String(temperatura) + "}";
              client.println("HTTP/1.1 200 OK");
              client.println("Content-Type: application/json");
              client.println("Connection: close");
              client.println();
              client.println(jsonResponse);
              break;
            }
            else 
            {
              client.println("HTTP/1.1 200 OK");
              client.println("Content-Type: text/html");
              client.println("Connection: close");
              client.println();
              client.println(index_html);
              break;
            }
          }
          else 
          {
            currentLine = "";
          }
        }
        else if (c != '\r') 
        {
          currentLine += c;
        }
      }
    }
    header = "";
    client.stop();
  }
}
const char* index_html = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <title>Monitor de Temperatura</title>
</head>
<body>
  <h1>Temperatura Atual</h1>
  <p>Temperatura: <span id="temperatura">--</span> °C</p>
  <script>
    setInterval(function() {
      var xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
          var jsonResposta = JSON.parse(this.responseText);
          document.getElementById("temperatura").innerHTML = jsonResposta.temperatura;
        }
      };
      xhttp.open("GET", "/dados", true);
      xhttp.send();
    }, 2000);
  </script>
</body>
</html>
)rawliteral";

Explicação Adicional

  • Leitura do Sensor de Temperatura: Utilizamos dht.readTemperature() para obter a temperatura atual.
  • JSON: A resposta agora inclui o campo "temperatura".
  • Intervalo de Atualização: Ajustamos o intervalo para a cada 2 segundos (2000 milissegundos).
  • Frontend: A página HTML exibe a temperatura atual em graus Celsius.

Considerações sobre Desempenho e Otimização🔗

Ao implementar atualização dinâmica com AJAX, é importante considerar:

  • Intervalo de Atualização: Intervalos muito curtos podem sobrecarregar o servidor. Ajuste conforme a necessidade.
  • Formato dos Dados: Utilizar JSON é eficiente para troca de dados estruturados.
  • Tratamento de Erros: Implemente verificações para lidar com falhas na comunicação.
  • Segurança: Em aplicações reais, considere autenticação e uso de HTTPS.

Conclusão🔗

A atualização dinâmica de páginas com AJAX no ESP32 permite criar interfaces web interativas e eficientes para monitoramento e controle de dispositivos em tempo real. Ao entender os conceitos de AJAX e como aplicá-los no ESP32, você pode expandir seus projetos IoT, oferecendo experiências ricas aos usuários sem a necessidade de recarregar páginas inteiras.

Experimentar com diferentes sensores e ajustar os intervalos de atualização conforme suas necessidades permitirá que você otimize seu projeto para melhor desempenho e usabilidade. Continue explorando e inovando em suas aplicações com o ESP32 e as possibilidades que o AJAX oferece.

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