Files
shellydash/AGENTS.md
T
truetype b078b850f8 Initial commit: ShellyDash dashboard fotovoltaico
Flask app con gauge Chart.js custom, polling Shelly Cloud API v2,
storico SQLite, due widget gauge (produzione/consumo) con scala graduata.
2026-07-14 20:38:18 +02:00

87 lines
3.5 KiB
Markdown

# shellydash — AGENTS.md
## Quick start
```bash
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_w` nelle 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 annotations` in ogni .py
- Type hints ovunque
- Logging via `logging.getLogger("shellydash.*")`
- `.env` non tracciato in git (`.gitignore` lo 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
```bash
# 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/status` risponda.
- Il DB è in `data/shellydash.db` — escluso da git.
- `POLL_INTERVAL` in `.env` (default 15s).
- Non ci sono test (repo in fase iniziale).
- Il device Shelly deve essere online e connesso al cloud.