Flask app con gauge Chart.js custom, polling Shelly Cloud API v2, storico SQLite, due widget gauge (produzione/consumo) con scala graduata.
3.5 KiB
3.5 KiB
shellydash — AGENTS.md
Quick start
cd /home/codex/shellydash
venv/bin/python3 app.py # avvia su 0.0.0.0:5050
Il .env carica automaticamente via load_dotenv() in app.py e poller.py.
Stack
- Python 3.14, Flask 3.1, SQLite, Chart.js 4.4 (CDN)
- Venv:
venv/(già creato) - Dipendenze:
flask,requests,python-dotenv
Architettura
| File | Ruolo |
|---|---|
app.py |
Entrypoint Flask, 6 route API + serve templates/index.html |
shelly_client.py |
Chiamate HTTP POST a Shelly Cloud Control API v2 |
database.py |
SQLite with WAL mode, schema readings, energy aggregations |
poller.py |
Thread background: poll Shelly ogni 15s → insert DB + cache latest_parsed |
templates/index.html |
Dashboard HTML + JS (Chart.js gauge custom plugin, storico, energia) |
Flusso dati
Shelly Cloud ← poller.poll_once() (ogni 15s) → database.py (SQLite)
→ app._latest_parsed (dict, in-memory)
→ /api/status (da cache, non DB)
→ /api/history (da DB)
API endpoints
| Route | Descrizione | Fonte dati |
|---|---|---|
GET /api/status |
Letture live (produzione, consumo, delta, V, A, PF, temp) | cache poller |
GET /api/history?hours=24 |
Array timestamp → produzione/consumo | DB |
GET /api/energy/today |
Energia odierna (prodotta, consumata, immessa) | DB (differenza energy counter) |
GET /api/energy/monthly |
Breakdown giornaliero mese corrente | DB |
GET /api/delta |
Surplus/deficit booleano per automazioni | cache poller |
Shelly EM — assetto canali
- Un solo device con ID
d885ac0b5860(Shelly EM Gen3, modello S3EM-002CXCEU) em1:0→ produzione pannelli (pinza sull'uscita inverter)em1:1→ consumo casa/rete (pinza sull'ingresso inverter, valori negativi = prelievo)consumption_wnelle API =abs(ch1)quando negativo- Auth via
auth_key(parametro query?auth_key=...), non email/password - Endpoint:
https://shelly-255-eu.shelly.cloud/v2/devices/api/{action}
Convenzioni codice
from __future__ import annotationsin ogni .py- Type hints ovunque
- Logging via
logging.getLogger("shellydash.*") .envnon tracciato in git (.gitignorelo esclude)
Frontend (index.html)
- Non usa framework JS — vanilla JS con Chart.js via CDN
- Gauge semi-circolare con lancetta: plugin Chart.js custom (
gaugePlugin), non libreria esterna - Due widget gauge:
#gaugeProd(produzione, max 6000W, verde) e#gaugeCons(consumo, max 3000W, ambra) - Scala graduata con tacche maggiori (1000W) e minori (500W) disegnate su canvas
- Auto-refresh ogni 15s via
setInterval(refreshAll, 15000) - UI in italiano, tema scuro (#0f172a sfondo)
Comandi utili
# Avviare
venv/bin/python3 app.py
# Test API singola
curl -s http://localhost:5050/api/status | python3 -m json.tool
# Verificare import (senza avviare server)
venv/bin/python3 -c "from app import app; print('ok')"
# Installare nuove dipendenze
venv/bin/pip install <package>
# E aggiungere a requirements.txt
Note operative
- Il poller parte in un thread dopo il primo
poller.poll_once(). Serve almeno un poll riuscito prima che/api/statusrisponda. - Il DB è in
data/shellydash.db— escluso da git. POLL_INTERVALin.env(default 15s).- Non ci sono test (repo in fase iniziale).
- Il device Shelly deve essere online e connesso al cloud.