Pular para o conteúdo

Endpoints de Dispositivos IoT

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.


Recebe heartbeat de dispositivos ESP32.

O dispositivo envia seu status atual e recebe o status alvo em que deveria estar.

POST /api/v1/devices/heartbeat
Content-Type: application/json
{
"device_id": "ESP32-001-A1B2C3",
"current_status": "ON"
}
CampoTipoObrigatórioDescrição
device_idstringIdentificador único do hardware
current_statusstringEstado atual do relé (ON ou OFF)
{
"target_status": "OFF"
}
CampoDescrição
current_statusRealidade - o que o ESP32 reporta
target_statusDesejo - o que o App comandou
┌─────────────┐ ┌─────────────┐
│ 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] │
│ │

Obtém o status atual de um dispositivo específico.

ParâmetroTipoDescrição
device_idstringIdentificador do dispositivo
GET /api/v1/devices/status/{device_id}
{
"device_id": "ESP32-001-A1B2C3",
"current_status": "ON",
"target_status": "ON",
"last_heartbeat": "2026-02-19T10:30:00Z",
"is_online": true
}

Configuração recomendada de heartbeat:

AmbienteIntervaloTimeout
Produção30 segundos60 segundos
Desenvolvimento10 segundos30 segundos

#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
}

O firmware implementa backoff exponencial para reconexão:

TentativaDelay
15 segundos
210 segundos
330 segundos
4+1 minuto

Quando o dispositivo perde conexão ou reinicia:

  1. Estado fail-safe configurável - Estado padrão ao reiniciar
  2. Execução local de agendamentos - Agendamento baseado em RTC continua
  3. Restauração de estado - Na reconexão, estado sincroniza com backend