Backend RESTful para plataforma IoT agrícola — dispositivos ESP32 + painel web React
- Visão Geral
- Arquitetura
- Stack Tecnológico
- Modelo de Dados
- Endpoints da API
- Autenticação
- Variáveis de Ambiente
- Rodando Localmente
- Docker
- Documentação Swagger
- Autor
O AgroSense API é o coração de uma plataforma IoT voltada para o agronegócio. Ele conecta dispositivos ESP32 instalados em campo (sensores de temperatura, umidade, pH, etc.) a um painel de controle web, permitindo:
- Registro e autenticação de usuários com JWT
- Registro de dispositivos ESP32 via token de API (
X-Agro-Token) - Recebimento de leituras de sensores em formato JSONB livre
- Gerenciamento de projetos agrupando múltiplos dispositivos
- Configuração remota de atuadores com flag
newConfigpara o ESP32 buscar atualizações - Documentação interativa via Swagger UI
[ ESP32 - Campo ]
| X-Agro-Token
▼
┌─────────────┐ JWT Bearer Token ┌──────────────┐
│ AgroSense │◄──────────────────────────►│ React Web │
│ API │ │ Client │
└──────┬──────┘ └──────────────┘
│
┌──────▼──────┐
│ PostgreSQL │
│ (JSONB) │
└─────────────┘
O projeto segue Clean Architecture organizada por pacotes:
br.com.agrosense.api
│
├── config/ ← Configurações (Security, Swagger, JWT)
│
├── domain/
│ └── entity/ ← Entidades JPA (User, Project, Device, Measurement, InstitutionalDomain)
│
├── application/
│ ├── dto/
│ │ ├── request/ ← DTOs de entrada (Java Records + Jakarta Validation)
│ │ └── response/ ← DTOs de saída (Java Records)
│ ├── service/ ← Interfaces dos serviços
│ ├── service/impl/ ← Implementações (retornam DTOs, nunca entidades)
│ └── mapper/ ← MapStruct (ProjectMapper, DeviceMapper, MeasurementMapper)
│
├── infrastructure/
│ ├── repository/ ← Spring Data JPA Repositories
│ ├── security/ ← JwtService, JwtAuthFilter, ApiTokenAuthFilter, UserDetailsServiceImpl
│ └── exception/ ← GlobalExceptionHandler (@RestControllerAdvice), ErrorResponseDTO
│
└── web/
└── controller/ ← AuthController, HardwareController, ProjectController, DeviceController
Regra de ouro: Controllers não contêm lógica de negócio. Services nunca retornam entidades.
| Tecnologia | Versão | Função |
|---|---|---|
| Java | 21 | Linguagem principal |
| Spring Boot | 3.4.0 | Framework principal |
| Spring Security | (BOM) | Autenticação e autorização |
| Spring Data JPA | (BOM) | Acesso a dados |
| Spring Validation | (BOM) | Validação de DTOs |
| PostgreSQL | 15+ | Banco de dados relacional com JSONB |
| Flyway | 10+ | Migrations de banco de dados |
| JJWT | 0.12.3 | Geração e validação de JWT |
| MapStruct | 1.5.5.Final | Mapeamento entidade ↔ DTO |
| Lombok | 1.18.34 | Redução de boilerplate |
| SpringDoc OpenAPI | (BOM) | Geração automática do Swagger |
| Docker Compose | — | Orquestração local |
Migrations Flyway em src/main/resources/db/migration/:
V1 ─ users
V2 ─ institutional_domains
V3 ─ projects
V4 ─ devices
V5 ─ measurements
-- Diagrama simplificado
users (id UUID, name, email UNIQUE, password_hash, api_token UNIQUE)
│
├──< projects (id, title, description, owner_id → users)
│ │
│ └──< devices (id, mac_address UNIQUE, owner_id, project_id,
│ nickname, manifest JSONB, config JSONB,
│ last_seen, config_updated_at, last_data_at)
│ │
│ └──< measurements (id, device_id, timestamp, data JSONB)
│
└── institutional_domains (domínios permitidos: ufmg.br, usp.br, gmail.com...)Colunas JSONB (
manifest,config,data) usam@JdbcTypeCode(SqlTypes.JSON)+Map<String, Object>.
| Método | Rota | Descrição | Auth |
|---|---|---|---|
POST |
/api/v1/auth/register |
Cria novo usuário | Público |
POST |
/api/v1/auth/login |
Retorna access_token + refresh_token |
Público |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
POST |
/api/v1/hw/manifest |
Registra/atualiza dispositivo com manifesto | X-Agro-Token |
POST |
/api/v1/hw/data |
Envia leitura de sensores (JSONB livre) | X-Agro-Token |
A resposta de
/hw/dataincluinew_config: truequandoconfig_updated_at > last_data_at, sinalizando ao ESP32 que há configuração nova para buscar.
| Método | Rota | Descrição | Auth |
|---|---|---|---|
POST |
/api/v1/projects |
Cria projeto | JWT Bearer |
GET |
/api/v1/projects |
Lista projetos do usuário | JWT Bearer |
GET |
/api/v1/projects/{id} |
Detalha projeto | JWT Bearer |
PATCH |
/api/v1/projects/{id} |
Atualiza projeto | JWT Bearer |
DELETE |
/api/v1/projects/{id} |
Remove projeto | JWT Bearer |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
GET |
/api/v1/devices |
Lista dispositivos do usuário | JWT Bearer |
GET |
/api/v1/devices/{id} |
Detalha dispositivo | JWT Bearer |
PATCH |
/api/v1/devices/{id} |
Atualiza nickname/config/project | JWT Bearer |
DELETE |
/api/v1/devices/{id} |
Remove dispositivo | JWT Bearer |
GET |
/api/v1/devices/{id}/measurements |
Lista leituras do dispositivo | JWT Bearer |
A API possui dois mecanismos de autenticação:
Authorization: Bearer <access_token>access_tokenexpira em 15 minutos (900000ms)refresh_tokenexpira em 7 dias (604800000ms)- Algoritmo: HMAC-SHA256 com chave ≥ 256 bits
X-Agro-Token: <api_token>- Token gerado no registro do usuário, armazenado em
users.api_token - Usado exclusivamente nas rotas
/api/v1/hw/** - Sem expiração — identifica o proprietário do dispositivo
| Variável | Padrão | Descrição |
|---|---|---|
DATABASE_URL |
jdbc:postgresql://localhost:5432/agrosense |
URL de conexão PostgreSQL |
DATABASE_USER |
agrosense |
Usuário do banco |
DATABASE_PASS |
agrosense |
Senha do banco |
JWT_SECRET |
(inseguro — troque em produção) | Chave HMAC-SHA256 (≥ 256 bits) |
- Java 21+
- Maven 3.9+ (ou use o wrapper
./mvnw) - PostgreSQL 15+ ou Docker
1. Clone o repositório
git clone https://github.com/Cardosofiles/agro-sense-server.git
cd agro-sense-server2. Suba o banco de dados com Docker
docker compose up db -dAguarde o healthcheck passar:
pg_isready -U agrosense
3. Configure as variáveis de ambiente (opcional — os defaults já funcionam localmente)
export DATABASE_URL=jdbc:postgresql://localhost:5432/agrosense
export DATABASE_USER=agrosense
export DATABASE_PASS=agrosense
export JWT_SECRET=minha-chave-super-secreta-com-mais-de-256-bits-aqui-ok4. Compile e execute
# Build (sem testes)
./mvnw clean package -DskipTests
# Rodar
./mvnw spring-boot:run5. Verifique
http://localhost:8080/swagger-ui.html
docker compose up --buildServiços provisionados:
| Serviço | Container | Porta |
|---|---|---|
| PostgreSQL 15 | agrosense-db |
5432 |
| AgroSense API | agrosense-api |
8080 |
A API aguarda o banco ficar saudável (
depends_on: condition: service_healthy) antes de iniciar.
docker compose up db -ddocker compose down
# Para remover também o volume de dados:
docker compose down -v# Build (skip tests)
./mvnw clean package -DskipTests
# Rodar localmente
./mvnw spring-boot:run
# Todos os testes
./mvnw test
# Teste específico
./mvnw test -Dtest=AuthServiceImplTestCom a aplicação rodando, acesse:
| URL | Descrição |
|---|---|
http://localhost:8080/swagger-ui.html |
Interface Swagger UI |
http://localhost:8080/v3/api-docs |
Especificação OpenAPI JSON |
Desenvolvido por Cardosofiles