In casa ci sono undici telecamere a batteria: due Arlo e nove Blink. Home Assistant le vede tutte, e da qualche giorno manda gli avvisi su WhatsApp tramite un gateway, OpenWA, che gira in Docker accanto a lui. Mancavano due cose: vedere cosa ha fatto scattare un avviso di movimento senza aprire nessuna app, e poter chiedere a una telecamera «fammi vedere adesso» scrivendo un messaggio.
Ora l'avviso di movimento arriva con la foto, e al numero di casa si può scrivere telecamere, ricevere l'elenco e rispondere con un numero per avere uno scatto nuovo.
Prima condizione: un gateway che sappia mandare foto
Il testo su WhatsApp funzionava da tempo, le foto no. Il motore che OpenWA usava, basato su un browser che pilota WhatsApp Web, non riusciva più a caricare né a scaricare file. Ho fatto passare il gateway al motore Baileys, che parla direttamente con i server di WhatsApp; il racconto completo è in una guida a parte. Da lì l'invio di immagini ha cominciato a funzionare.
Una sola avvertenza pratica: l'immagine va mandata in base64. L'invio per indirizzo web esiste, ma la validazione dell'API richiede un dominio vero e rifiuta un nome di container come homeassistant.
La foto negli avvisi
Tutti gli avvisi passano da un solo script, che impagina il messaggio e decide i canali. Gli ho aggiunto un campo foto: se l'automazione indica una telecamera, lo script scatta uno snapshot una volta sola e lo usa per tutti i canali.
- action: script.avviso
data:
evento: movimento_cam1
foto: camera.cam1
titolo: "Movimento rilevato"
messaggio: "📍 Telecamera *CAM1*"
Due dettagli su dove salvare il file. Home Assistant permette di scrivere snapshot solo in cartelle ammesse; la più ovvia, /config/www, è pubblicata senza autenticazione all'indirizzo /local/, e una foto di casa lì non la voglio. In un'installazione Docker è ammessa anche /media, interna al container: per una foto usa e getta va benissimo.
L'app di Home Assistant sul telefono riceve invece l'immagine direttamente dalla telecamera, passando nella notifica il percorso del proxy:
data:
image: /api/camera_proxy/camera.cam1
E se lo snapshot non riesce? Lo script sovrascrive sempre lo stesso file, quindi un errore lascerebbe lì la foto della volta prima. Lo script che invia controlla l'età del file: se ha più di due minuti non la manda, e il messaggio parte comunque come solo testo. Meglio nessuna foto che la foto di un altro momento.
Le telecamere a richiesta
Il comando funziona in due tempi. Scrivendo telecamere arriva l'elenco numerato:
📷 TELECAMERE
━━━━━━━━━━━━━━
1. CAM1 (Arlo)
2. CAM2 (Arlo)
3. Caldaia (Blink)
…
👉 Rispondi con il numero o il nome.
Rispondendo con un numero, o con il nome, Home Assistant sveglia quella telecamera, le fa scattare una foto nuova e la manda come risposta. Funziona anche in un colpo solo: foto caldaia.
L'elenco viene da un sensore template che raccoglie le telecamere delle due integrazioni, Arlo prima e Blink poi, ciascuna in ordine di nome. L'elenco mandato su WhatsApp e quello usato per interpretare il numero sono lo stesso, quindi la numerazione non può sfasarsi. Per ogni telecamera il sensore calcola anche una chiave senza spazi e simboli, così «fuori magazzino», «Fuori - Magazzino» e «fuorimagazzino» vengono riconosciuti come lo stesso nome; la ricerca prova prima il nome esatto e poi quello contenuto, così «magazzino» non sceglie per sbaglio «fuori magazzino».
Arlo e Blink scattano in modo diverso
«Foto nuova» vuol dire cose diverse per le due marche, e l'ho verificato nel codice delle integrazioni invece di supporlo.
Per Arlo c'è un servizio che sveglia la telecamera, aspetta l'immagine e la scrive su file: quando la chiamata finisce, la foto è pronta.
- action: aarlo.camera_request_snapshot_to_file
target:
entity_id: camera.cam1
data:
filename: /media/richiesta_cam1.jpg
Per Blink si chiede uno scatto, si aspetta qualche secondo, si aggiorna l'entità e solo allora si salva lo snapshot:
- action: blink.trigger_camera
target:
entity_id: camera.caldaia
- delay: "00:00:06"
- action: homeassistant.update_entity
target:
entity_id: camera.caldaia
- action: camera.snapshot
target:
entity_id: camera.caldaia
data:
filename: /media/richiesta_caldaia.jpg
Lo script parte in background: il messaggio WhatsApp viene accettato subito, e la foto arriva dopo una decina di secondi, il tempo che serve a una telecamera a batteria per svegliarsi.
Due bug che vale la pena raccontare
Il numero che non era un numero. Alla prima prova vera, scrivendo telecamere e poi 1, la risposta era «non ho capito». I nomi invece funzionavano, e per questo nei primi test non me n'ero accorto. Quando arriva l'elenco salvo chi l'ha chiesto e quando, come testo: 1|1792059658. Il destinatario lo calcola un template che restituisce «1», e qui sta il punto: Home Assistant converte il risultato dei template nel tipo che gli sembra giusto, quindi la variabile diventava il numero 1. Il confronto tra il testo «1» letto dall'entità e il numero 1 era sempre falso.
# prima: sempre falso
a[0] == dest
# dopo
a[0] == dest | string
L'ho trovato riproducendo il calcolo nell'editor dei template, dove la variabile era testo e tutto risultava vero: la differenza tra i due ambienti era proprio il tipo.
L'attesa che si chiudeva troppo presto. Dopo la prima foto, un secondo numero riceveva di nuovo «non ho capito». Avevo scritto io di azzerare l'attesa dopo ogni scelta, pensando a una richiesta alla volta; chi guarda le telecamere ne vuole vedere tre di fila. Ora ogni scelta rinnova i cinque minuti, e l'elenco vale finché non passano cinque minuti senza richieste.
In sintesi
- Le foto su WhatsApp dipendono dal gateway: con alcuni motori il testo funziona e i file no.
- Gli snapshot vanno in una cartella ammessa ma non pubblica;
/config/wwwè visibile da fuori. - Meglio un avviso senza foto che con la foto sbagliata: controllare l'età del file.
- «Foto nuova» per Arlo e per Blink si ottiene in modi diversi: va letto nel codice dell'integrazione.
- Nei template di Home Assistant un «1» può diventare un numero: nei confronti con il testo,
| string.