Endpoints de Dispositivos IoT
Visão Geral
Seção intitulada “Visão Geral”A API de Dispositivos IoT gerencia a comunicação entre dispositivos ESP32 e o backend usando o padrão Shadow State. Os dispositivos reportam seu status atual e recebem os estados alvo desejados.
POST /devices/heartbeat
Seção intitulada “POST /devices/heartbeat”Recebe heartbeat de dispositivos ESP32.
O dispositivo envia seu status atual e recebe o status alvo em que deveria estar.
Requisição
Seção intitulada “Requisição”POST /api/v1/devices/heartbeatContent-Type: application/json{ "device_id": "ESP32-001-A1B2C3", "current_status": "ON"}Parâmetros do Body
Seção intitulada “Parâmetros do Body”| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
device_id | string | ✅ | Identificador único do hardware |
current_status | string | ✅ | Estado atual do relé (ON ou OFF) |
Resposta 200 OK
Seção intitulada “Resposta 200 OK”{ "target_status": "OFF"}Conceito Shadow State
Seção intitulada “Conceito Shadow State”| Campo | Descrição |
|---|---|
current_status | Realidade - o que o ESP32 reporta |
target_status | Desejo - o que o App comandou |
Fluxo de Exemplo
Seção intitulada “Fluxo de Exemplo”┌─────────────┐ ┌─────────────┐│ ESP32 │ │ Backend │└──────┬──────┘ └──────┬──────┘ │ │ │ POST /heartbeat │ │ {device_id, current_status: ON} │ │────────────────────────────────>│ │ │ │ {target_status: OFF} │ │<────────────────────────────────│ │ │ │ [ESP32 desliga relé] │ │ │ │ POST /heartbeat │ │ {device_id, current_status: OFF}│ │────────────────────────────────>│ │ │ │ {target_status: OFF} │ │<────────────────────────────────│ │ │ │ [Estados iguais - sem ação] │ │ │GET /devices/status/{device_id}
Seção intitulada “GET /devices/status/{device_id}”Obtém o status atual de um dispositivo específico.
Parâmetros de Path
Seção intitulada “Parâmetros de Path”| Parâmetro | Tipo | Descrição |
|---|---|---|
device_id | string | Identificador do dispositivo |
Requisição
Seção intitulada “Requisição”GET /api/v1/devices/status/{device_id}Resposta 200 OK
Seção intitulada “Resposta 200 OK”{ "device_id": "ESP32-001-A1B2C3", "current_status": "ON", "target_status": "ON", "last_heartbeat": "2026-02-19T10:30:00Z", "is_online": true}Intervalo de Heartbeat
Seção intitulada “Intervalo de Heartbeat”Configuração recomendada de heartbeat:
| Ambiente | Intervalo | Timeout |
|---|---|---|
| Produção | 30 segundos | 60 segundos |
| Desenvolvimento | 10 segundos | 30 segundos |
Exemplo de Implementação ESP32
Seção intitulada “Exemplo de Implementação ESP32”#include <WiFi.h>#include <HTTPClient.h>#include <ArduinoJson.h>
const char* DEVICE_ID = "ESP32-001-A1B2C3";const char* API_URL = "https://api.aeraplus.com/v1/devices/heartbeat";const int RELAY_PIN = 5;
bool currentStatus = false;
void sendHeartbeat() { HTTPClient http; http.begin(API_URL); http.addHeader("Content-Type", "application/json");
// Criar corpo da requisição StaticJsonDocument<200> requestDoc; requestDoc["device_id"] = DEVICE_ID; requestDoc["current_status"] = currentStatus ? "ON" : "OFF";
String requestBody; serializeJson(requestDoc, requestBody);
// Enviar requisição POST int httpCode = http.POST(requestBody);
if (httpCode == 200) { String response = http.getString();
// Parsear resposta StaticJsonDocument<200> responseDoc; deserializeJson(responseDoc, response);
String targetStatus = responseDoc["target_status"]; bool shouldBeOn = (targetStatus == "ON");
// Comparar e executar se diferente if (shouldBeOn != currentStatus) { digitalWrite(RELAY_PIN, shouldBeOn ? HIGH : LOW); currentStatus = shouldBeOn; Serial.printf("Status alterado para: %s\n", targetStatus.c_str()); } }
http.end();}
void setup() { Serial.begin(115200); pinMode(RELAY_PIN, OUTPUT);
// Conectar ao WiFi...}
void loop() { sendHeartbeat(); delay(30000); // intervalo de 30 segundos}Estratégia de Reconexão
Seção intitulada “Estratégia de Reconexão”O firmware implementa backoff exponencial para reconexão:
| Tentativa | Delay |
|---|---|
| 1 | 5 segundos |
| 2 | 10 segundos |
| 3 | 30 segundos |
| 4+ | 1 minuto |
Modo Fail-Safe
Seção intitulada “Modo Fail-Safe”Quando o dispositivo perde conexão ou reinicia:
- Estado fail-safe configurável - Estado padrão ao reiniciar
- Execução local de agendamentos - Agendamento baseado em RTC continua
- Restauração de estado - Na reconexão, estado sincroniza com backend