DEV Community

Pedro Fonseca
Pedro Fonseca

Posted on

ESP32 HTTP Client Sem Dores de Cabeça: Consuma REST APIs com Zero Alocação de Memória

Consumindo REST APIs no ESP32 sem Estourar a Memória: Conheça o ESP32-HTTP-Client

Se você já desenvolveu projetos IoT no ESP32 que se comunicam com APIs REST (seja para enviar dados de sensores para a nuvem, consultar status de serviços ou integrar com Firebase e AWS), provavelmente já enfrentou um destes problemas clássicos:

  1. Fragmentação e estouro de heap: O combo padrão HTTPClient + ArduinoJson precisa carregar todo o payload HTTP na RAM como String antes de desserializar o JSON. Em payloads médios ou grandes, isso gera Out of Memory ou travamentos intermitentes.
  2. Lentidão em requisições consecutivas: O HTTPClient padrão refaz o handshake TLS/TCP repetidamente, adicionando centenas de milissegundos a cada chamada.
  3. Código verboso e boilerplate excessivo: Mais de 15 a 20 linhas de código para instanciar clientes, extrair buffers, checar erros e navegar em nós JSON.

Para resolver esses gargalos de forma elegante e moderna, foi criada a biblioteca ESP32-HTTP-Client.


O que é o ESP32-HTTP-Client?

O ESP32-HTTP-Client é um cliente HTTP/REST moderno, fluente e orientado a objetos para ESP32, projetado especificamente para sistemas embarcados de alta eficiência.

Em vez de "fazer download da resposta, guardar na memória e depois processar", ele utiliza Direct Memory Binding (injeção direta) e Stream Parsing: os dados do JSON são lidos diretamente do stream da rede e injetados direto nas suas variáveis ou structs em C++, sem armazenar o payload inteiro na RAM.

// Uma linha. Zero strings intermediárias. Injeção direta em memória.
client.get("/sensor").getBody("temperature", &myFloatVariable);
Enter fullscreen mode Exit fullscreen mode

Benchmark: ESP32-HTTP-Client vs Abordagem Tradicional

Em testes controlados com 100 requisições HTTP consecutivas contendo payloads JSON (usando o endpoint /users do JSONPlaceholder), os resultados comprovam a economia de recursos:

Métrica / Recurso HTTPClient + ArduinoJson (Padrão) ESP32-HTTP-Client Diferencial
Heap alocado por requisição ~58.2 KB ~0.0 KB (15 bytes) ~99.9% menos RAM por request
Uso médio de RAM do sistema ~34.2% ~24.3% ~29% menos memória total
Heap livre mínimo absoluto 114.3 KB 128.6 KB Muito mais seguro p/ apps robustas
Tempo de Execução Médio ~750 ms ~59 ms ~12x mais rápido (Keep-Alive nativo)
Linhas de Código ~15-20 linhas 1 cadeia fluente Código limpo e sustentável
Parsing de JSON Exige buffer DynamicJsonDocument Streaming direto na variável Zero buffer allocation

Nota sobre desempenho:

O ESP32-HTTP-Client reutiliza a mesma conexão TCP/TLS ativa (HTTP Keep-Alive) e decodifica Transfer-Encoding: chunked no fluxo de dados. Isso elimina a sobrecarga de refazer negociações criptográficas TLS a cada ciclo de leitura do seu sensor.


Quick Start: Seu primeiro request em 2 minutos

Instalação

  • PlatformIO (adicione ao seu platformio.ini):
  lib_deps =
      PedroFnseca/ESP32-HTTP-Client@^1.4.0
Enter fullscreen mode Exit fullscreen mode
  • Arduino IDE: Abra Sketch → Include Library → Manage Libraries..., procure por ESP32-HTTP-Client e clique em Install.

Exemplo Básico: GET com Injeção de Dados

#include <Arduino.h>
#include <WiFi.h>
#include "ESP32HTTPClient.h"

const char* ssid     = "SEU_WIFI";
const char* password = "SUA_SENHA";

// Inicialize o client apontando para a base URL
ESP32HTTPClient client("https://jsonplaceholder.typicode.com");

void setup() {
    Serial.begin(115200);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) delay(100);

    int userId = 0;
    char title[64] = {0};
    bool completed = false;

    // Resposta esperada: { "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false }
    client.get("/todos/1")
          .getBody("userId", &userId)
          .getBody("title", title, sizeof(title))
          .getBody("completed", &completed);

    Serial.printf("User ID: %d | Title: %s | Completed: %s\n", 
                  userId, title, completed ? "true" : "false");
}

void loop() {}
Enter fullscreen mode Exit fullscreen mode

Recursos Avançados

O ESP32-HTTP-Client foi desenvolvido pensando em cenários reais de engenharia IoT:

1. Mapeamento Bidirecional de struct <-> JSON

Você pode mapear estruturas C++ inteiras usando a macro REST_JSON_MAP. Isso permite enviar e receber objetos completos sem tocar em bibliotecas adicionais de parsing:

// 1. Defina a struct com o mapa de campos
struct DeviceTelemetry {
    int deviceId = 101;
    float temperature = 26.4;
    float humidity = 58.0;
    bool statusOk = true;

    REST_JSON_MAP(
        REST_FIELD(deviceId),
        REST_FIELD(temperature),
        REST_FIELD(humidity),
        REST_FIELD(statusOk)
    )
};

// 2. Envie o struct diretamente no POST (serialização zero-copy)
DeviceTelemetry telemetry;
client.post("/api/telemetry").body(telemetry);

// 3. Receba dados diretamente no struct
DeviceTelemetry serverConfig;
client.get("/api/config").getBody(&serverConfig);
Enter fullscreen mode Exit fullscreen mode

2. Autenticação Simplificada (Bearer, Basic, API Key)

Configurar cabeçalhos de autenticação que persistem durante o ciclo de vida do cliente:

// JWT / Bearer Token
client.bearer("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ...");

// HTTP Basic Auth (Base64 gerado automaticamente)
client.basic("admin", "senhaSuperSecreta");

// Header de API Key personalizado
client.apiKey("X-API-KEY", "minha-chave-de-acesso");
Enter fullscreen mode Exit fullscreen mode

3. Extração com Dot Notation e Índices de Array

Para ler uma propriedade profundamente aninhada ou um item específico de uma lista sem carregar a árvore JSON inteira:

char cityName[32];
int secondSensorVal;

// Navegação por ponto: { "company": { "address": { "city": "São Paulo" } } }
client.get("/profile").getBody("company.address.city", cityName, sizeof(cityName));

// Acesso por índice de array: [ { "val": 10 }, { "val": 25 } ]
client.get("/sensors").getBody("1.val", &secondSensorVal);
Enter fullscreen mode Exit fullscreen mode

4. Resiliência: Timeouts, Retries Automáticos e Callbacks

Em redes IoT com oscilações de sinal, o cliente oferece suporte a retries e callbacks declarativos:

client.get("/telemetry")
      .timeout(3000)          // Timeout de 3 segundos nesta requisição
      .retry(2)                // Tenta até 2 vezes caso ocorra falha de rede
      .onSuccess([](int code) {
          Serial.printf("Sucesso! HTTP Code: %d\n", code);
      })
      .onError([](int code, const char* msg) {
          Serial.printf("Falha na requisição (%d): %s\n", code, msg);
      })
      .getBody("status", &statusVar);
Enter fullscreen mode Exit fullscreen mode

5. Gerenciamento de Conexão e Memória TLS

O Keep-Alive mantém o socket e o buffer TLS (~45 KB) aquecidos para máxima agilidade. Se o seu dispositivo vai entrar em modo de baixo consumo (Deep Sleep) ou passar um longo período sem comunicação, é possível liberar os buffers a qualquer momento:

// Requisições consecutivas aproveitando o Keep-Alive
client.get("/sync/1").getBody("val", &v1);
client.get("/sync/2").getBody("val", &v2);

// Libera os buffers TLS da RAM antes de um delay longo ou deep sleep
client.end();
Enter fullscreen mode Exit fullscreen mode

Principais Vantagens do ESP32-HTTP-Client

  • Elimina vazamentos e fragmentação de heap: Reduz falhas e travamentos causados por concatenação excessiva de String e alocações dinâmicas.
  • Reduz o consumo energético: Requisições até 12x mais rápidas diminuem o tempo de atividade do rádio Wi-Fi.
  • Código limpo e conciso: A API fluente simplifica blocos complexos de código em chamadas declarativas.
  • Projetado para produção: Suporte completo aos métodos REST (GET, POST, PUT, PATCH, DELETE) e validação via testes unitários automatizados.

Links e Recursos Oficiais

Top comments (0)