# 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: 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.2.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" } } ``` ## 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": "..."}`.