Endpoints de Pontos de Controle
Pontos de Controle são dispositivos IoT (ESP32) que gerenciam a aeração de múltiplos viveiros. Eles utilizam um sistema de Shadow State para sincronização:
target_status: Estado desejado comandado pelo Appcurrent_status: Estado real reportado pelo ESP32
Todos os endpoints requerem autenticação.
Authorization: Bearer <token>Objeto Control Point
Seção intitulada “Objeto Control Point”{ "id": "550e8400-e29b-41d4-a716-446655440000", "farm_id": "farm-uuid", "cod": "CP-001", "target_status": "ON", "current_status": "OFF", "device_id": "AERA_ESP32_001", "consumption": 1.5, "last_command_at": "2025-11-21T15:45:00Z", "last_heartbeat": "2025-11-21T15:44:30Z", "created_at": "2025-11-21T10:30:00Z", "updated_at": "2025-11-21T15:45:00Z"}| Campo | Tipo | Descrição |
|---|---|---|
id | UUID | Identificador do ponto de controle |
farm_id | UUID | Fazenda associada |
cod | string | Código único do ponto de controle |
target_status | enum | Estado desejado (ON / OFF) |
current_status | enum | Estado real do dispositivo (ON / OFF) |
device_id | string | Identificador do dispositivo ESP32 |
consumption | float | Consumo de energia atual |
last_command_at | datetime | Timestamp do último comando |
last_heartbeat | datetime | Timestamp do último heartbeat do ESP32 |
created_at | datetime | Data de criação |
updated_at | datetime | Data da última atualização |
POST /control-points/
Seção intitulada “POST /control-points/”Cria um novo ponto de controle.
Requisição
Seção intitulada “Requisição”POST /api/v1/control-points/Authorization: Bearer <token>Content-Type: application/json{ "farm_id": "farm-uuid", "cod": "CP-001", "target_status": "OFF", "device_id": "AERA_ESP32_001"}Parâmetros do Body
Seção intitulada “Parâmetros do Body”| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
farm_id | UUID | ✅ | ID da fazenda |
cod | string | ✅ | Código único do ponto de controle |
target_status | enum | ✅ | Status inicial (ON / OFF) |
device_id | string | ❌ | Identificador do dispositivo ESP32 |
Resposta 201 Created
Seção intitulada “Resposta 201 Created”{ "id": "cp-uuid", "farm_id": "farm-uuid", "cod": "CP-001", "target_status": "OFF", "current_status": null, "device_id": "AERA_ESP32_001", "created_at": "2025-11-21T10:30:00Z", "updated_at": null}Possíveis Erros
Seção intitulada “Possíveis Erros”| Status | Detalhe |
|---|---|
400 | Erro de validação |
GET /control-points/
Seção intitulada “GET /control-points/”Lista todos os pontos de controle do usuário atual.
Requisição
Seção intitulada “Requisição”GET /api/v1/control-points/Authorization: Bearer <token>Resposta 200 OK
Seção intitulada “Resposta 200 OK”[ { "id": "cp-uuid", "farm_id": "farm-uuid", "cod": "CP-001", "target_status": "ON", "current_status": "ON", "device_id": "AERA_ESP32_001", "last_heartbeat": "2025-11-21T15:44:30Z" }]GET /control-points/{control_point_id}
Seção intitulada “GET /control-points/{control_point_id}”Obtém detalhes de um ponto de controle.
Parâmetros de URL
Seção intitulada “Parâmetros de URL”| Parâmetro | Tipo | Descrição |
|---|---|---|
control_point_id | UUID | ID do ponto de controle |
Requisição
Seção intitulada “Requisição”GET /api/v1/control-points/cp-uuidAuthorization: Bearer <token>Resposta 200 OK
Seção intitulada “Resposta 200 OK”{ "id": "cp-uuid", "farm_id": "farm-uuid", "cod": "CP-001", "target_status": "ON", "current_status": "OFF", "device_id": "AERA_ESP32_001", "consumption": 1.5, "last_command_at": "2025-11-21T15:45:00Z", "last_heartbeat": "2025-11-21T15:44:30Z", "created_at": "2025-11-21T10:30:00Z", "updated_at": "2025-11-21T15:45:00Z"}Possíveis Erros
Seção intitulada “Possíveis Erros”| Status | Detalhe |
|---|---|
404 | Ponto de controle não encontrado |
PUT /control-points/{control_point_id}
Seção intitulada “PUT /control-points/{control_point_id}”Atualiza um ponto de controle.
Requisição
Seção intitulada “Requisição”PUT /api/v1/control-points/cp-uuidAuthorization: Bearer <token>Content-Type: application/json{ "cod": "CP-001-UPDATED", "device_id": "AERA_ESP32_002"}Parâmetros do Body
Seção intitulada “Parâmetros do Body”Todos os campos são opcionais:
| Campo | Tipo | Descrição |
|---|---|---|
cod | string | Novo código |
device_id | string | Novo ID do dispositivo |
Resposta 200 OK
Seção intitulada “Resposta 200 OK”Retorna o objeto do ponto de controle atualizado.
Possíveis Erros
Seção intitulada “Possíveis Erros”| Status | Detalhe |
|---|---|
404 | Ponto de controle não encontrado |
DELETE /control-points/{control_point_id}
Seção intitulada “DELETE /control-points/{control_point_id}”Exclui um ponto de controle.
Requisição
Seção intitulada “Requisição”DELETE /api/v1/control-points/cp-uuidAuthorization: Bearer <token>Resposta 204 No Content
Seção intitulada “Resposta 204 No Content”Sem corpo de resposta.
Possíveis Erros
Seção intitulada “Possíveis Erros”| Status | Detalhe |
|---|---|
404 | Ponto de controle não encontrado |
POST /control-points/{control_point_id}/turn-on
Seção intitulada “POST /control-points/{control_point_id}/turn-on”Liga o ponto de controle (define target_status como ON).
Requisição
Seção intitulada “Requisição”POST /api/v1/control-points/cp-uuid/turn-onAuthorization: Bearer <token>Resposta 200 OK
Seção intitulada “Resposta 200 OK”{ "id": "cp-uuid", "target_status": "ON", "current_status": "OFF", "last_command_at": "2025-11-21T15:45:00Z"}Possíveis Erros
Seção intitulada “Possíveis Erros”| Status | Detalhe |
|---|---|
404 | Ponto de controle não encontrado |
POST /control-points/{control_point_id}/turn-off
Seção intitulada “POST /control-points/{control_point_id}/turn-off”Desliga o ponto de controle (define target_status como OFF).
Requisição
Seção intitulada “Requisição”POST /api/v1/control-points/cp-uuid/turn-offAuthorization: Bearer <token>Resposta 200 OK
Seção intitulada “Resposta 200 OK”{ "id": "cp-uuid", "target_status": "OFF", "current_status": "ON", "last_command_at": "2025-11-21T15:46:00Z"}Possíveis Erros
Seção intitulada “Possíveis Erros”| Status | Detalhe |
|---|---|
404 | Ponto de controle não encontrado |
Endpoint de Heartbeat (IoT)
Seção intitulada “Endpoint de Heartbeat (IoT)”POST /devices/heartbeat
Seção intitulada “POST /devices/heartbeat”Recebe heartbeat do dispositivo ESP32 e retorna o status desejado.
Requisição
Seção intitulada “Requisição”POST /api/v1/devices/heartbeatContent-Type: application/json{ "device_id": "AERA_ESP32_001", "current_status": "OFF"}Parâmetros do Body
Seção intitulada “Parâmetros do Body”| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
device_id | string | ✅ | Identificador único do ESP32 |
current_status | string | ✅ | Estado atual do dispositivo (ON / OFF) |
Resposta 200 OK
Seção intitulada “Resposta 200 OK”{ "target_status": "ON"}Possíveis Erros
Seção intitulada “Possíveis Erros”| Status | Detalhe |
|---|---|
404 | Control point com este device_id não encontrado |
Fluxo do Shadow State
Seção intitulada “Fluxo do Shadow State”┌─────────────┐ 1. Heartbeat ┌─────────────┐│ ESP32 │ ───────────────►│ Backend ││ (Campo) │ current_status │ (FastAPI) ││ │◄─────────────── │ │└─────────────┘ target_status └─────────────┘ │ │ │ 2. Compara estados │ │ target ≠ current? │ │ │ ▼ │ ┌─────────────┐ │ │ Executa │ │ │ Comando │ │ └─────────────┘ │ │ │ │ 3. Próximo heartbeat │ │ confirma execução │ └──────────────────────────────┘