Aggiunta documentazione completa del progetto: - Architettura e flusso dati - Setup e configurazione - API REST con esempi JSON - Configurazione canali Shelly EM - Stack tecnologico
172 lines
4.6 KiB
Markdown
172 lines
4.6 KiB
Markdown
# ShellyDash ⚡
|
||
|
||
Dashboard web per il monitoraggio in tempo reale di un impianto fotovoltaico con **Shelly EM Gen3**.
|
||
|
||
Legge i dati da un Shelly EM (2 pinze: produzione pannelli e consumo casa/rete) via **Shelly Cloud API v2**, li memorizza su SQLite e li visualizza su una dashboard con gauge a lancetta semi-circolare e grafico storico.
|
||
|
||
## Funzionalità
|
||
|
||
- **Due gauge analogici**: produzione pannelli (0–6000W, verde) e consumo casa (0–3000W, ambra), con scala graduata e lancetta
|
||
- **Surplus/deficit** istantaneo: produzione − consumo
|
||
- **Energia odierna**: prodotto, consumato, immesso in rete
|
||
- **Grafico storico**: 24h / 3gg / 7gg produzione + consumo
|
||
- **API REST JSON** per automazioni e integrazioni
|
||
- **Auto-refresh** ogni 15 secondi
|
||
- **Tema scuro**, UI in italiano
|
||
|
||
## Architettura
|
||
|
||
```
|
||
shellydash/
|
||
├── app.py ← Entrypoint Flask (6 route API + serve frontend)
|
||
├── shelly_client.py ← Client HTTP per Shelly Cloud API v2
|
||
├── database.py ← SQLite (WAL mode), schema readings
|
||
├── poller.py ← Thread background polling periodico
|
||
├── templates/
|
||
│ └── index.html ← Dashboard: gauge Chart.js custom + grafico storico
|
||
├── data/
|
||
│ └── shellydash.db ← SQLite (gitignorato)
|
||
├── .env ← Credenziali Shelly (gitignorato)
|
||
├── AGENTS.md ← Istruzioni per AI agent
|
||
└── requirements.txt ← flask, requests, python-dotenv
|
||
```
|
||
|
||
### Flusso dati
|
||
|
||
```
|
||
Shelly Cloud
|
||
↕ HTTP POST (auth_key)
|
||
poller.poll_once() ← ogni 15s (thread background)
|
||
↕
|
||
shelly_client.py ← parse readings (em1:0, em1:1)
|
||
↕
|
||
database.py (SQLite) ← INSERT storico
|
||
↕
|
||
app._latest_parsed (dict) ← cache in-memory per /api/status
|
||
↕
|
||
app.py → /api/status ← da cache (risposta immediata)
|
||
→ /api/history ← da DB (storico)
|
||
→ /api/energy/* ← da DB (aggregazioni)
|
||
→ / → templates/index.html
|
||
```
|
||
|
||
## Setup
|
||
|
||
### Prerequisiti
|
||
|
||
- Python 3.14+
|
||
- Shelly EM Gen3 connesso al cloud Shelly
|
||
- Chiave API Cloud (trovabile in App Shelly → Impostazioni → Casa → Cloud)
|
||
|
||
### Installazione
|
||
|
||
```bash
|
||
cd /home/codex/shellydash
|
||
python3 -m venv venv
|
||
venv/bin/pip install -r requirements.txt
|
||
```
|
||
|
||
### Configurazione
|
||
|
||
Crea un file `.env` nella root del progetto (non tracciato in git):
|
||
|
||
```env
|
||
SHELLY_SERVER="https://shelly-255-eu.shelly.cloud"
|
||
SHELLY_AUTH_KEY="la_tua_auth_key"
|
||
SHELLY_DEVICE_ID="id_dispositivo"
|
||
POLL_INTERVAL=15
|
||
FLASK_PORT=5050
|
||
FLASK_HOST="0.0.0.0"
|
||
```
|
||
|
||
### Avvio
|
||
|
||
```bash
|
||
venv/bin/python3 app.py
|
||
```
|
||
|
||
Apri il browser su `http://localhost:5050`.
|
||
|
||
## API REST
|
||
|
||
Tutte le API restituiscono JSON con campo `ok` booleano.
|
||
|
||
### `GET /api/status`
|
||
Letture live in tempo reale (dalla cache del poller).
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"ts": 1722520000,
|
||
"production_w": 1735.4,
|
||
"consumption_w": 134.4,
|
||
"delta_w": 1601.0,
|
||
"voltage": 229.8,
|
||
"ch0_current": 7.55,
|
||
"ch1_current": 0.59,
|
||
"ch0_pf": 0.99,
|
||
"ch1_pf": 0.85,
|
||
"temperature": 59.6,
|
||
"wifi_rssi": -67,
|
||
"online": true
|
||
}
|
||
```
|
||
|
||
### `GET /api/history?hours=24`
|
||
Array di readings storici dal database.
|
||
|
||
### `GET /api/energy/today`
|
||
Energia odierna in kWh.
|
||
|
||
### `GET /api/energy/monthly`
|
||
Breakdown giornaliero del mese corrente.
|
||
|
||
### `GET /api/delta`
|
||
Surplus/deficit booleano (utile per automazioni).
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"delta_w": 1601.0,
|
||
"production_w": 1735.4,
|
||
"consumption_w": 134.4,
|
||
"surplus": true
|
||
}
|
||
```
|
||
|
||
## Shelly EM — Configurazione canali
|
||
|
||
Il progetto è tarato su un **Shelly EM Gen3** (S3EM-002CXCEU) con una singola unità e **due pinze**:
|
||
|
||
| Canale | ID | Misura | Segno |
|
||
|---|---|---|---|
|
||
| Produzione | `em1:0` | Uscita inverter → potenza generata | Sempre positivo |
|
||
| Consumo | `em1:1` | Ingresso inverter → prelievo/rete | Negativo = consumo, Positivo = immissione |
|
||
|
||
L'API normalizza automaticamente: `consumption_w = abs(ch1)` quando ch1 è negativo.
|
||
|
||
## Frontend
|
||
|
||
- **Framework**: nessuno — vanilla JavaScript
|
||
- **Grafici**: Chart.js 4.4.7 via CDN
|
||
- **Gauge**: plugin Chart.js custom (`gaugePlugin`) con disegno su canvas di:
|
||
- Scala graduata (tacche maggiori ogni 1000W, minori ogni 500W)
|
||
- Lancetta rotante
|
||
- Valore numerico al centro
|
||
- **Tema**: scuro (#0f172a sfondo)
|
||
- **Refresh**: `setInterval(refreshAll, 15000)`
|
||
|
||
## Stack tecnologico
|
||
|
||
| Componente | Tecnologia |
|
||
|---|---|
|
||
| Backend | Python 3.14, Flask 3.1 |
|
||
| Database | SQLite (WAL mode) |
|
||
| Cloud API | Shelly Cloud Control API v2 |
|
||
| Frontend | HTML5, CSS3, Chart.js 4.4 (CDN) |
|
||
| Ambiente | venv |
|
||
|
||
## Licenza
|
||
|
||
Progetto privato — uso personale.
|