Files
harbour-aira/docs/PROTOCOL.md
T

196 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# API del bridge
Servizio: `~/workspace/Carlo/Aira/aira_bridge.py` (Python, solo `pyairahome`).
Traduce HTTP/1.1 + JSON in gRPC verso il cloud Aira. Tutte le rotte tranne
`/health` richiedono:
```
Authorization: Bearer <token>
```
Token: generato al primo avvio in `~/.hermes/profiles/carlo/aira_bridge.json`.
## GET /health
Nessuna autenticazione: serve a distinguere "server irraggiungibile" da
"token sbagliato".
```json
{"ok": true, "version": "0.4.0"}
```
## GET /summary
Valori pronti per la dashboard.
```json
{
"ok": true,
"summary": {
"outdoor_temperature": 18.1,
"indoor_temperature": 22.5,
"dhw_current": 51.0,
"dhw_target": 55.0,
"operating_status": "OPERATING_STATUS_AUTO",
"away_mode": false,
"night_mode": false,
"manual_mode": false,
"force_heating": false,
"force_heating_remaining": "0s",
"inline_heater": false,
"hot_water_heating": true,
"configured_modes": "PUMP_MODE_STATE_HEATING",
"pump_active_state": "PUMP_ACTIVE_STATE_IDLE",
"outdoor_defrost": false,
"signature_lights": true,
"led_pattern": "LED_PATTERN_NORMAL",
"zones": 1,
"zone1_setpoint": 19.0,
"zone1_temperature": 23.0,
"zone1_mode": "PUMP_MODE_STATE_HEATING",
"zone1_cooling_setpoint": 22.0,
"zone2_setpoint": 0.0,
"zone2_temperature": 0.0,
"zone2_mode": "PUMP_MODE_STATE_IDLE",
"zone2_cooling_setpoint": 0.0,
"errors_count": 0,
"pump_updated": "2026-10-09 18:52:17.199340",
"device_id": "1f4b26",
"device_uuid": "1f4b26c4-1800-4b21-8ea2-236925a92aeb",
"version_platform": "6.10.0",
"version_connectivity": "3.30.1",
"version_climate_control": "3.9.12",
"version_outdoor_unit": "1.30.0",
"version_outdoor_eeprom": "0.114.0",
"connected_via": "Cloud",
"timezone": "Europe/Rome",
"thermostats_count": 1,
"thermostat_zone": 1,
"thermostat_article": "201884",
"thermostat_temperature": 22.8,
"thermostat_humidity": 73.3,
"thermostat_rssi": -79,
"thermostat_battery_low": false
}
}
```
Il blocco del dispositivo serve alle pagine "Impianto" e "Accessori" dell'app:
`device_id` sono le prime 6 cifre dell'UUID (come le mostra l'app ufficiale),
`connected_via` è la via di connessione, le `version_*` sono le versioni del
software e i campi `thermostat_*` descrivono il termostato a parete (assenti se
l'impianto non ne ha: in quel caso `thermostats_count` è 0 e gli altri sono
`null`). Il termostato manda i decimali come interi (228 = 22,8 °C): la
conversione la fa il bridge, non l'app.
## GET /stats
I numeri che Aira calcola nel cloud: sono gli stessi della scheda "Dati"
dell'app ufficiale (verificati sullo stesso periodo). Il bridge li tiene in
cache per **10 minuti** (`ttl`), perché sono quattro chiamate e cambiano
lentamente.
```json
{
"ok": true,
"stats": {
"period_days": 30,
"currency": "EUR",
"month": {
"label": "2026-10",
"heat_kwh": 70.8,
"energy_kwh": 29.3,
"cop_heating": null,
"cop_dhw": 4.42
},
"cop_monthly": [
{"month": "2026-09", "heating_cop": null, "dhw_cop": 4.42, "avg_outdoor": 21.8}
],
"insights": [
{"date": "2026-10-01", "energy_kwh": 29.3, "heat_kwh": 70.8}
],
"savings": {"amount": 21.78, "co2_kg": 38.1, "show": true, "points": 31},
"smart_tariff": {"amount": 2.71, "hours": 180},
"monthly_savings": [{"month": "2026-09", "amount": 3.52}]
}
}
```
- `month`: l'ultimo periodo con dati — calore prodotto (`heat_kwh`), elettricità
usata (`energy_kwh`) ed efficienza (COP) di acqua calda e riscaldamento.
**`null` significa "nessun dato"**: su un impianto recente il riscaldamento può
non averne ancora (mentre l'acqua calda sì). `label` è il mese `AAAA-MM`.
- `cop_monthly` e `monthly_savings`: le serie mese per mese, per il dettaglio.
- `savings`: risparmio in bolletta sugli ultimi `period_days` giorni (30), CO₂
evitata e numero di punti usati dal calcolo; `show` è il permesso di Aira a
mostrare il dato.
- `smart_tariff`: il risparmio del mese mobile dovuto allo Smart Tariff Control.
- Questa rotta è di **sola lettura**: non invia nessun comando all'impianto.
## GET /state
Stato completo e grezzo dal cloud (42 campi: curve climatiche per zona,
versioni firmware, schedulazioni, errori). Per diagnostica.
## GET /commands
Elenco dei comandi ammessi con i loro parametri.
## POST /command
```json
{"id": "set_hot_water_target", "value": 55}
```
Risposta: `{"ok": true, "id": "...", "result": {...}}`.
### Comandi ammessi
| id | value | effetto |
|---|---|---|
| `ping` | — | verifica che l'impianto risponda |
| `set_hot_water_target` | 45–60 | temperatura ACS obiettivo |
| `set_heating_setpoint` | 5–30 | temperatura obiettivo della casa (zona, default 1) |
| `set_cooling_setpoint` | 5–30 | temperatura obiettivo del raffrescamento (zona, default 1) |
| `hot_water_boost_on` / `hot_water_boost_off` | — | boost ACS una tantum |
| `hot_water_heating_on` / `hot_water_heating_off` | — | riscaldamento ACS |
| `away_mode_on` / `away_mode_off` | — | modalità assenza |
| `night_mode_1h` | — | night mode per un'ora |
| `force_heating_on` / `force_heating_off` | — | riscaldamento forzato |
| `heating_on` / `heating_off` | — | funzione riscaldamento |
| `legionella_cycle` | — | ciclo antilegionella |
### Riscaldamento: come si invia il comando per zona
Il messaggio `ZoneTemperatures` contiene **sempre entrambe** le zone:
```json
{"id": "set_heating_setpoint", "value": 21.5, "zone": 1}
```
`zone` è opzionale (default 1) e accetta 1 o 2. La zona che non si sta
modificando viene rimandata con il **suo valore attuale**, letto dall'ultimo
stato disponibile: inviarla a zero la spegnerebbe. Per questo il bridge tiene
in memoria l'ultima lettura, e il comando va costruito con quel contesto.
Il campo `kind` distingue riscaldamento (`1`) da raffrescamento (`2`).
### Perché una whitelist
La libreria espone ~90 comandi, fra cui `FactoryReset`, `InstallFirmware`,
`RebootDevice`, `RotateCertificate`, `SetWifiCredentials`. Restano **fuori di
proposito**: un client mobile non deve poter riformattare l'impianto per un tap
sbagliato.
## Errori
| stato | significato |
|---|---|
| 400 | comando non ammesso, oppure valore fuori intervallo |
| 401 | token mancante o errato |
| 404 | rotta sconosciuta |
| 502 | il bridge non ha potuto parlare con il cloud (dettaglio in `error`) |
Formato: `{"ok": false, "error": "..."}`.