Volevo controllare la Google TV di casa da Home Assistant: accenderla, aprire un'app, alzare il volume a un valore preciso, farle dire un avviso a voce. Sembra un lavoro da una sola integrazione, invece nessuna fa tutto bene. Alla fine ne uso tre insieme, ognuna per quello che sa fare davvero. Home Assistant gira in Docker, e questo aggiunge un paio di problemi di rete che conviene conoscere prima.

Negli esempi uso dei segnaposto: <IP-TV> è l'indirizzo della TV sulla rete di casa, <IP-PC> quello del PC che fa girare Home Assistant, <MAC-TV> l'indirizzo fisico della scheda di rete della TV. Le entità sono media_player.<tv_remote>, media_player.<tv_cast> e media_player.<tv_adb>: tre lettori multimediali per la stessa TV, uno per integrazione.

🧩 Perché tre integrazioni e non una

  • Android TV Remote: sa se la TV è accesa o spenta, quale app è in primo piano, la accende e la spegne, alza e abbassa il volume a scatti. Non sa impostare il volume a un valore preciso. Ne ho già parlato nella guida sulla scheda Android TV Remote.
  • Google Cast: imposta il volume a un valore preciso con media_player.volume_set e fa parlare la TV con la sintesi vocale (tts.speak).
  • Android Debug Bridge (ADB): manda comandi diretti al sistema della TV, fa gli screenshot e apre le app in modo affidabile. Il suo stato però può restare «off» anche a TV accesa: per sapere se la TV è accesa non va usato.
Cosa voglio fareIntegrazione da usare
Sapere se la TV è accesaAndroid TV Remote
Sapere quale app è apertaAndroid TV Remote
Accendere e spegnereAndroid TV Remote (più Wake-on-LAN per accendere)
Volume su e giù a scattiAndroid TV Remote
Volume a un valore precisoGoogle Cast
Sintesi vocale sulla TVGoogle Cast
Aprire un'appADB
Screenshot dello schermoADB
Comandi diretti al sistemaADB

La documentazione di Home Assistant suggerisce anche di unire più lettori in uno con l'integrazione Universal Media Player. In questa guida li tengo separati e scelgo nelle automazioni quale usare per ogni azione: così è chiaro chi fa cosa, e se una integrazione cade le altre continuano a funzionare.

🐳 Google Cast non trova la TV: Docker in rete bridge

Google Cast scopre i dispositivi con l'mDNS, cioè con messaggi multicast sulla rete locale. Con il container Docker in rete bridge quei messaggi non arrivano dentro il container: la TV c'è, ma Home Assistant non la vede da solo e l'integrazione non propone nessun dispositivo.

La soluzione è dirgli dove guardare. In Impostazioni, Dispositivi e servizi, Google Cast, Configura: nel campo degli host noti (known hosts) si aggiunge l'indirizzo della TV, <IP-TV>. Da lì in poi Cast la interroga direttamente. Per questo conviene dare alla TV un indirizzo fisso nel router: se cambia, Cast la perde di nuovo.

🌐 L'URL interno di Home Assistant

Quando Home Assistant manda un avviso vocale o un'immagine alla TV con Cast, non le spedisce il file: le dà un indirizzo da cui scaricarlo. È la TV che va a prenderlo su Home Assistant. Se l'URL interno è impostato in automatico, in Docker può risultare l'indirizzo interno del container, uno di quelli che cominciano con 172. La TV quell'indirizzo non lo raggiunge.

⚠️ Il sintomo da riconoscere

  • Lanci tts.speak verso la TV, nel log non c'è nessun errore, ma la TV non dice niente e non riceve niente.
  • La causa quasi sempre è l'URL interno: la TV prova a scaricare il file da un indirizzo che sulla rete di casa non esiste.
  • Rimedio: in Impostazioni, Sistema, Rete, nel campo dell'URL interno si toglie l'automatico e si scrive l'indirizzo del PC sulla rete locale, per esempio http://<IP-PC>:8123.

Con l'URL giusto, il volume e la voce sono due azioni semplici:

- action: media_player.volume_set
  target:
    entity_id: media_player.<tv_cast>
  data:
    volume_level: 0.25

- action: tts.speak
  target:
    entity_id: tts.<motore_tts>
  data:
    media_player_entity_id: media_player.<tv_cast>
    message: "La lavatrice ha finito"

volume_level va da 0 a 1: 0.25 è un quarto del volume massimo. Il motore della sintesi vocale è quello che hai già configurato in Home Assistant.

🔌 Attivare ADB sulla TV

  1. Sulla TV apri Impostazioni, Sistema, Informazioni e tocca sette volte il numero di build: compare il messaggio che le opzioni sviluppatore sono attive.
  2. Nelle opzioni sviluppatore attiva il Debug USB, non il «Debug wireless». Il debug wireless usa un abbinamento con codice e porte che cambiano, e Home Assistant non lo supporta. Con il debug USB attivo, ADB ascolta in rete sulla porta 5555.
  3. In Home Assistant aggiungi l'integrazione Android Debug Bridge con l'indirizzo <IP-TV> e la porta 5555.
  4. Al primo collegamento la TV mostra una richiesta: autorizzare la chiave di debug di quel computer. Scegli Consenti sempre, altrimenti la richiesta torna a ogni riconnessione.

Il primo tentativo di configurazione può fallire: Home Assistant prova a collegarsi, la TV aspetta che qualcuno accetti la richiesta sullo schermo e nel frattempo la connessione scade. È normale. Accetti la richiesta con il telecomando e riprovi: al secondo giro entra.

🔒 Una nota di sicurezza

  • Con il debug attivo, la TV accetta comandi ADB dalla rete da qualsiasi computer a cui hai detto «Consenti sempre».
  • Non accettare richieste di autorizzazione che non ti aspetti, e non esporre la porta 5555 fuori dalla rete di casa.

⚡ Accendere la TV dalla rete

Lo spegnimento funziona subito, con media_player.turn_off su Android TV Remote. L'accensione no. Quando è spenta, la TV stacca la rete: nessuna delle tre integrazioni risponde, le entità diventano «non disponibile» e i comandi vanno in timeout. Non si può dire «accenditi» a un dispositivo che non ascolta.

Serve il Wake-on-LAN, in tre passi:

  1. Sulla TV: nelle impostazioni di alimentazione si attiva l'accensione dalla rete in standby. A seconda del modello si chiama Wake on LAN, Wake on Wi-Fi o simile. Se la TV è collegata in Wi-Fi, deve supportare il Wake on WLAN: non tutte lo fanno, e senza quello da spenta non si sveglia.
  2. Home Assistant manda un pacchetto magico Wake-on-LAN in broadcast con il <MAC-TV>. Va bene un piccolo script Python.
  3. Poi aspetta che Android TV Remote torni raggiungibile e manda il comando di accensione vero e proprio.

Lo script, salvato in /config/scripts/wol.py:

#!/usr/bin/env python3
# Uso: wol.py <MAC-TV> <BROADCAST-LAN>
import socket, sys

mac = bytes.fromhex(sys.argv[1].replace(':', '').replace('-', ''))
pacchetto = b'\xff' * 6 + mac * 16
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
    s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    s.sendto(pacchetto, (sys.argv[2], 9))

<BROADCAST-LAN> è l'indirizzo di broadcast della rete di casa (di solito quello della rete con l'ultimo numero a 255). Con Docker in rete bridge è meglio usare questo che il broadcast generico, che può fermarsi alla rete interna del container. Esiste anche l'integrazione Wake on LAN di Home Assistant, che fa la stessa cosa con un'azione già pronta: se nella tua rete il suo pacchetto arriva alla TV, puoi usare quella.

Lo script si richiama con uno shell_command e si mette in una sequenza che aspetta la TV:

shell_command:
  tv_wol: "python3 /config/scripts/wol.py <MAC-TV> <BROADCAST-LAN>"

script:
  accendi_tv:
    sequence:
      - action: shell_command.tv_wol
      - wait_template: "{{ not is_state('media_player.<tv_remote>', 'unavailable') }}"
        timeout: "00:00:40"
        continue_on_timeout: false
      - action: media_player.turn_on
        target:
          entity_id: media_player.<tv_remote>

Il timeout è indicativo: dipende da quanto ci mette la tua TV a riattivare la rete. Se scade, lo script si ferma invece di mandare un comando a vuoto.

📺 Aprire le app

Android TV Remote ha un modo per aprire le app: media_player.play_media con tipo app. Dietro le quinte manda alla TV un link market://launch?id=<pacchetto>. Alcune TV lo ignorano senza dare errori: l'azione risulta eseguita, nel log non c'è niente, ma l'app non si apre e la TV resta dov'è.

La strada affidabile è ADB, con il comando monkey che apre l'app dalla sua schermata d'avvio per la TV:

- action: androidtv.adb_command
  target:
    entity_id: media_player.<tv_adb>
  data:
    command: "monkey -p com.netflix.ninja -c android.intent.category.LEANBACK_LAUNCHER 1"

Per sapere quali pacchetti sono installati si usa lo stesso androidtv.adb_command con pm list packages (aggiungendo -3 si vedono solo le app installate, senza quelle di sistema). La risposta non arriva nel log: finisce nell'attributo adb_response dell'entità ADB, che si legge in Strumenti per sviluppatori, Stati.

Prima di mettere un pacchetto in un'automazione conviene verificare che abbia davvero una schermata d'avvio per la TV:

cmd package resolve-activity --brief -c android.intent.category.LEANBACK_LAUNCHER <pacchetto>

Se risponde con il nome di un'attività, monkey la aprirà. Se non trova niente, quel pacchetto non ha un avvio pensato per la TV (succede con servizi di sistema o app per telefono installate per sbaglio).

💡 Una curiosità utile

  • Se il sistema ha «archiviato» un'app poco usata per liberare spazio, il controllo risponde con ReactivateActivity invece dell'attività dell'app.
  • Non è un errore: l'app è ancora lì, ma alla prima apertura la TV la riscarica. La prima volta ci mette di più, poi torna normale.

Alcuni pacchetti noti per Google TV e Android TV (le versioni per TV hanno spesso un nome diverso da quelle per telefono):

Controlla comunque con pm list packages sulla tua TV: un produttore può installare una versione diversa.

📸 Screenshot dello schermo con ADB

Uno screenshot si fa in tre passaggi: la TV scatta e salva l'immagine nella sua memoria, Home Assistant la scarica, poi la si converte in JPEG per mandarla in giro più leggera.

- action: androidtv.adb_command
  target:
    entity_id: media_player.<tv_adb>
  data:
    command: "screencap -p /sdcard/x.png"

- action: androidtv.download
  target:
    entity_id: media_player.<tv_adb>
  data:
    device_path: /sdcard/x.png
    local_path: /media/tv/x.png

Il percorso di destinazione deve essere una cartella che Home Assistant ha il permesso di scrivere: /media di solito lo è. Se rifiuta il percorso, va aggiunto a allowlist_external_dirs nella configurazione. Per la conversione basta un altro script richiamato da uno shell_command; Pillow è già presente nel container di Home Assistant:

import sys
from PIL import Image

Image.open(sys.argv[1]).convert('RGB').save(sys.argv[2], 'JPEG', quality=85)

È lo stesso passaggio che uso per le foto delle telecamere negli avvisi WhatsApp.

⚠️ App protette

  • Le app con DRM, come Netflix, Prime Video e Disney+, spesso bloccano la cattura: lo screenshot esce nero.
  • Non è un errore del comando: con il menu della TV o un'app senza protezione la stessa sequenza funziona.

🔁 ADB caduto dopo la riaccensione

Dopo uno spegnimento e una riaccensione della TV, la connessione ADB di Home Assistant può restare caduta: l'entità ADB resta «non disponibile» anche se la TV è accesa e la porta 5555 è aperta. In quello stato i comandi ADB non arrivano alla TV.

Il rimedio: prima di ogni comando ADB, se l'entità non è disponibile, si chiama homeassistant.update_entity qualche volta, con una pausa di qualche secondo, finché torna disponibile.

- if:
    - condition: state
      entity_id: media_player.<tv_adb>
      state: unavailable
  then:
    - repeat:
        sequence:
          - action: homeassistant.update_entity
            target:
              entity_id: media_player.<tv_adb>
          - delay: "00:00:05"
        until:
          - condition: template
            value_template: >
              {{ not is_state('media_player.<tv_adb>', 'unavailable')
                 or repeat.index >= 5 }}
- action: androidtv.adb_command
  target:
    entity_id: media_player.<tv_adb>
  data:
    command: "monkey -p com.google.android.youtube.tv -c android.intent.category.LEANBACK_LAUNCHER 1"

Il limite di tentativi evita che lo script giri all'infinito se la TV è davvero spenta. Conviene mettere questo blocco in uno script a parte e richiamarlo prima di ogni comando ADB, invece di ripeterlo ovunque.

🐞 Errori che ho fatto

  • Cercare di accendere la TV senza Wake-on-LAN. Da spenta la TV non è in rete, e nessuna integrazione può raggiungerla finché non la svegli con il pacchetto magico.
  • Fidarmi di play_media per aprire le app. L'app non si apriva e nel log non c'era nessun errore. Con ADB e monkey si apre ogni volta.
  • Non controllare ADB dopo la riaccensione. L'entità restava non disponibile con la porta aperta, e i comandi cadevano nel vuoto. Ora ogni comando ADB passa prima dal blocco che la riattiva.

✅ Checklist finale

  1. TV con indirizzo IP fisso nel router.
  2. Android TV Remote configurata: è lei che dice se la TV è accesa.
  3. Google Cast con l'indirizzo della TV tra gli host noti.
  4. URL interno di Home Assistant impostato all'indirizzo del PC sulla rete di casa, non a quello del container.
  5. Opzioni sviluppatore attive, Debug USB acceso, chiave autorizzata con «Consenti sempre».
  6. Integrazione Android Debug Bridge sulla porta 5555.
  7. Accensione dalla rete attiva sulla TV, e Wake on WLAN se è in Wi-Fi.
  8. Script di accensione: pacchetto magico, attesa di Android TV Remote, poi accensione.
  9. App aperte con ADB e monkey, pacchetti verificati con resolve-activity.
  10. Blocco di riconnessione ADB prima di ogni comando ADB.