Protótipo mínimo para controlar uma fechadura inteligente baseada em ESP32: a interface web envia um comando de desbloqueio, o backend regista o comando em memória, e o dispositivo obtém o comando por HTTP (polling) e confirma a execução (ack).
- Backend: Python 3.12+ com FastAPI
- Frontend: HTML, CSS e JavaScript (vanilla), servido como ficheiros estáticos
- Dados: armazenamento em memória (sem base de dados)
- Comunicação: REST sobre HTTP
app/
├── main.py # Aplicação FastAPI, CORS, estáticos
├── config.py # Tokens por dispositivo (env)
├── deps.py # Validação Bearer nas rotas do dispositivo
├── routes/
│ ├── control.py # POST /control/unlock
│ └── device.py # GET/POST /device/{id}/…
├── services/
│ └── command_service.py # Comandos em memória (pending → sent → executed)
└── static/
├── index.html
├── styles.css
└── app.js
requirements.txt
- Python 3.12 ou superior (recomendado)
pipe ambiente virtual (opcional mas recomendado)
Na raiz do repositório:
# 1. Criar e ativar ambiente virtual (opcional)
python3 -m venv .venv
source .venv/bin/activate # Linux / macOS
# .venv\Scripts\activate # Windows
# 2. Instalar dependências
pip install -r requirements.txt
# 3. Arrancar o servidor
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000- Interface: http://127.0.0.1:8000/ (redireciona para
/static/index.html) - Documentação interativa da API: http://127.0.0.1:8000/docs
Por defeito existe um token de desenvolvimento para esp32-1. Em produção, defina JSON com device_id → token:
export SMART_LOCK_DEVICE_TOKENS='{"esp32-1":"o-seu-token-seguro"}'
uvicorn app.main:app --host 0.0.0.0 --port 8000As rotas sob /device/... exigem o header:
Authorization: Bearer <token>
| Método | Caminho | Descrição |
|---|---|---|
POST |
/control/unlock |
Corpo: {"device_id":"esp32-1"}. Cria comando unlock como pending. |
GET |
/device/{device_id}/commands |
Devolve o comando pending mais antigo e marca-o como sent; se não houver, {"command":null}. |
POST |
/device/{device_id}/ack |
Corpo: {"command_id":"<uuid>"}. Marca como executed (só se estiver sent). |
# Criar comando (como a UI)
curl -s -X POST http://127.0.0.1:8000/control/unlock \
-H 'Content-Type: application/json' \
-d '{"device_id":"esp32-1"}'
# Polling (ajuste o token se usar SMART_LOCK_DEVICE_TOKENS)
curl -s http://127.0.0.1:8000/device/esp32-1/commands \
-H 'Authorization: Bearer dev-token-change-in-production'
# Confirmação após “executar” no dispositivo
curl -s -X POST http://127.0.0.1:8000/device/esp32-1/ack \
-H 'Authorization: Bearer dev-token-change-in-production' \
-H 'Content-Type: application/json' \
-d '{"command_id":"<uuid-do-poll>"}'O servidor regista em nível INFO a criação do comando, a entrega no GET e a execução no ack.
- Os dados perdem-se ao reiniciar o processo (memória).
- A rota
/control/unlocké pensada para a UI de protótipo; num sistema real convém proteger também com autenticação ou rede confinada.
Projeto de protótipo; ajuste a licença conforme a sua organização.