Arquitetura¶
Visão geral¶
O sistema é dividido em três camadas:
- Edge — ESP32 com sensores (ZMPT101B + SCT-013-100) calcula Vrms, Irms, Watts, fator de potência e kWh e publica via MQTT.
- Broker — HiveMQ Cloud (MQTTS, porta 8883) roteia as mensagens.
- Cloud — aplicação Django recebe a telemetria, persiste no PostgreSQL e entrega dashboards, previsões e o assistente WhatsApp.
ESP32 → HiveMQ Cloud (MQTTS) → Django Subscriber → PostgreSQL/TimescaleDB
↓
Views CBV + Templates (web)
REST API — DRF (app Flet)
Webhook Evolution API (WhatsApp)
Apps Django¶
| App | Responsabilidade |
|---|---|
core |
BaseModel com timestamps, configuração central, site público |
accounts |
Modelo de usuário customizado, autenticação por e-mail |
meters |
Cadastro e status dos medidores IoT |
telemetry |
Ingestão MQTT e armazenamento das leituras |
tariffs |
Tarifas da ANEEL e cálculo de custo estimado |
dashboard |
Agregações e gráficos de consumo |
analytics |
Previsão de fatura (forecasting) e desagregação de cargas (NILM, com classificador por usuário + calibração manual) |
assistant |
Chatbot WhatsApp (Evolution API) e chat web, ambos via LangChain/RAG |
api |
Endpoints REST para o app Flet |
O app Flet (flet_app/) é um projeto Python separado; não é uma app Django.
Stack técnica¶
| Camada | Tecnologia |
|---|---|
| Linguagem | Python 3.11 |
| Framework web | Django 5.x (MVT, sem SPA) |
| Templates | Django Template Language |
| Estilização web | TailwindCSS 3.x (darkMode: 'class') |
| Gráficos web | Chart.js |
| REST API | Django REST Framework |
| Autenticação da API | Token (DRF TokenAuthentication) |
| App mobile | Flet (Python) — build Android/iOS |
| Banco de dados | PostgreSQL 16 + extensão TimescaleDB |
| Driver do banco | psycopg (psycopg2-binary) |
| Cliente MQTT | paho-mqtt (management command) |
| Variáveis de ambiente | python-decouple |
| IA — Forecasting | scikit-learn / statsmodels |
| IA — NILM | scikit-learn |
| API de clima | Open-Meteo (variável exógena do forecasting) |
| Assistente | LangChain (RAG) + Evolution API |
Fluxo de dados¶
ESP32 publica telemetria (a cada 5s)
→ HiveMQ Cloud (MQTTS 8883)
→ management command run_mqtt_subscriber (paho-mqtt)
→ service layer (telemetry/services.py)
→ TelemetryReading salvo no PostgreSQL/TimescaleDB
ESP32 publica status (LWT / boot)
→ management command run_mqtt_subscriber
→ atualiza Meter.is_online + cria DeviceStatusEvent
Dashboard web
→ lê TelemetryReading + BillForecast + LoadDisaggregation
→ renderiza via CBV + DTL + Chart.js
App Flet
→ autenticação: POST /api/auth/token/
→ lê dados: GET /api/meters/, /api/meters/{id}/readings/, etc.
WhatsApp
→ usuário mensagem → Evolution API → webhook Django (assistant app)
→ LangChain RAG consulta telemetria e estimativas
→ resposta em linguagem natural enviada de volta
Chat web (botão flutuante na seção Assistente)
→ usuário digita → POST /assistant/chat/ (WebChatView)
→ mesmo pipeline RAG (build_user_context + LangChain)
→ resposta retornada como JSON (sem envio WhatsApp)
→ mensagem persistida com source='web'
Alertas proativos (ver docs/alertas.md)
→ signals (BillForecast, TelemetryReading) + NILM + sync_white_tariff
→ send_proactive_alert (assistant/services.py)
→ WhatsApp (se o usuário já conversou com o bot)
→ AssistantMessage(is_proactive_alert=True)
→ card "Último alerta" no dashboard + histórico do assistente
Banco de dados por ambiente¶
| Ambiente | Imagem | Observação |
|---|---|---|
| Desenvolvimento local | timescale/timescaledb:latest-pg16 |
Hypertable + agregação contínua ativos |
| Produção (IONOS VPS) | postgres:16-alpine |
Migrations TimescaleDB condicionais — ignoradas quando a extensão não está presente |
A tabela TelemetryReading é uma hypertable particionada por measured_at quando o TimescaleDB está disponível. As migrations 0002_hypertable e 0003_continuous_aggregates verificam a existência da função create_hypertable antes de executar, tornando o banco intercambiável.
Deploy em produção (Docker)¶
O sistema roda containerizado via docker-compose.prod.yml em energiasm.online:
nginx:alpine → energia-web (Gunicorn, 4 workers) → postgres:16-alpine
energia-mqtt_subscriber (management command, PYTHONUNBUFFERED=1)
evolution-api:8080 (evoapicloud/evolution-api:latest)
Serviços:
| Serviço | Função |
|---|---|
db |
PostgreSQL 16-alpine — bancos energia_db e evolution_api |
web |
Django + Gunicorn, 4 workers |
mqtt_subscriber |
Management command run_mqtt_subscriber (reconecta recriando mqtt.Client) |
nginx |
Reverse proxy + SSL Let's Encrypt + /media/ |
evolution-api |
Gateway WhatsApp, instância energiabot |
Dockerfile: multi-stage build — gcc/libpq-dev apenas no stage builder; runtime usa só libpq5. Reduz a imagem final em ~200 MB.
requirements.prod.txt: versão de produção sem flet, flake8, black, isort e outras ferramentas de desenvolvimento.
Guia completo: docs/DEPLOY.md.