Skip to main content

Home Assistant + Android TV = fun

Here's a quick setup guide for controlling your Android TV from within Home Assistant. I've used it to control a genuine Android TV (Philips 7304) and an Odroid N2 running Android TV. For this to work you need ADB access. It can usually be enabled from within Developer Settings. The great part is - you don't need root access!

The most important things are described in the androidtv component for Home Assistant: https://www.home-assistant.io/integrations/androidtv/

Make sure you go through the adb setup.

My configuration is simple (inside configuration.yaml):
media_player:
  - platform: androidtv
    name: TV Bedroom ATV
    host: 192.168.1.61
    device_class: androidtv


Once Home Assistant restarts, your TV might require you to accept the connection (adb authentication). This happens only once (or until you reset your ATV to factory settings).

Once running the integration will show you the current ATV state (on or off) and allows you to turn it on or off.

Together with the history_stats sensor, it helps you keep an eye on tv viewing time:

sensor:
  - platform: history_stats
    name: TV Bedroom view time
    entity_id: media_player.tv_bedroom_atv
    state: 'on'
    type: time
    start: '{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}'
    end: '{{ now() }}'


So, yesterday the kids watched TV for just half an hour. Nice.

You can also create a virtual remote and inject keystrokes from within Home Assistant.
Let's define some scripts inside scripts.yaml:
'atv_bedroom_home':
  alias: ATV Bedroom Home
  sequence:
    - service: androidtv.adb_command
      data:
        entity_id: media_player.tv_bedroom_atv
        command: "HOME"
'atv_bedroom_up':
  alias: ATV Bedroom Up
  sequence:
    - service: androidtv.adb_command
      data:
         entity_id: media_player.tv_bedroom_atv
         command: "UP"
'atv_bedroom_down':
  alias: ATV Bedroom Down
  sequence:
    - service: androidtv.adb_command
      data:
         entity_id: media_player.tv_bedroom_atv
         command: "DOWN"
'atv_bedroom_left':
  alias: ATV Bedroom Left
  sequence:
    - service: androidtv.adb_command
      data:
         entity_id: media_player.tv_bedroom_atv
         command: "LEFT"
'atv_bedroom_right':
  alias: ATV Bedroom Right
  sequence:
    - service: androidtv.adb_command
      data:
         entity_id: media_player.tv_bedroom_atv
         command: "RIGHT"
'atv_bedroom_center':
  alias: ATV Bedroom Center
  sequence:
    - service: androidtv.adb_command
      data:
         entity_id: media_player.tv_bedroom_atv
         command: "CENTER"
'atv_bedroom_exit':
  alias: ATV Bedroom Exit
  sequence:
    - service: androidtv.adb_command
      data:
         entity_id: media_player.tv_bedroom_atv
         command: "EXIT"
'atv_bedroom_back':
  alias: ATV Bedroom Back
  sequence:
    - service: androidtv.adb_command
      data:
         entity_id: media_player.tv_bedroom_atv
         command: "BACK"
'atv_bedroom_menu':
  alias: ATV Bedroom Menu
  sequence:
    - service: androidtv.adb_command
      data:
         entity_id: media_player.tv_bedroom_atv
         command: "MENU"
'atv_bedroom_volup':
  alias: ATV Bedroom Volume Up
  sequence:
    - service: androidtv.adb_command
      data:
         entity_id: media_player.tv_bedroom_atv
         command: "VOLUME_UP"
'atv_bedroom_voldown':
  alias: ATV Bedroom Volume Down
  sequence:
    - service: androidtv.adb_command
      data:
         entity_id: media_player.tv_bedroom_atv
         command: "VOLUME_DOWN"
'atv_bedroom_power':
  alias: ATV Bedroom Power
  sequence:
    - service: androidtv.adb_command
      data:
         entity_id: media_player.tv_bedroom_atv
         command: "POWER"
'atv_bedroom_reboot':
  alias: ATV Bedroom Reboot
  sequence:
    - service: androidtv.adb_command
      data:
         entity_id: media_player.tv_bedroom_atv
         command: "reboot"


Once you restart Home Assistant you'll be able to add the scripts as buttons inside Lovelace UI. You can paste the config below as a custom card:

cards:
  - cards:
      - entity: media_player.tv_bedroom_atv
        icon: 'mdi:power'
        name: Power
        tap_action:
          action: call-service
          service: media_player.toggle
          service_data:
            entity_id: media_player.tv_bedroom_atv
        type: entity-button
      - entity: script.atv_bedroom_power
        icon: 'mdi:power'
        name: ATV Power
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.atv_bedroom_power
        type: entity-button
      - entity: script.atv_bedroom_reboot
        icon: 'mdi:power'
        name: ATV Reboot
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.atv_bedroom_reboot
        type: entity-button
    type: horizontal-stack
  - cards:
      - entity: script.atv_bedroom_volup
        icon: 'mdi:volume-plus'
        name: Vol+
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.atv_bedroom_volup
        type: entity-button
      - entity: script.atv_bedroom_up
        icon: 'mdi:arrow-up-bold'
        name: Up
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.atv_bedroom_up
        type: entity-button
      - entity: media_player.tv_bedroom_atv
        icon: 'mdi:video-input-hdmi'
        name: Kodi
        tap_action:
          action: call-service
          service: media_player.select_source
          service_data:
            entity_id: media_player.tv_bedroom_atv
            source: org.xbmc.kodi
        type: entity-button
    type: horizontal-stack
  - cards:
      - entity: script.atv_bedroom_left
        icon: 'mdi:arrow-left-bold'
        name: Left
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.atv_bedroom_left
        type: entity-button
      - entity: script.atv_bedroom_center
        icon: 'mdi:bullseye-arrow'
        name: Enter
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.atv_bedroom_center
        type: entity-button
      - entity: script.atv_bedroom_right
        icon: 'mdi:arrow-right-bold'
        name: Right
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.atv_bedroom_right
        type: entity-button
    type: horizontal-stack
  - cards:
      - entity: script.atv_bedroom_voldown
        icon: 'mdi:volume-minus'
        name: Vol-
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.atv_bedroom_voldown
        type: entity-button
      - entity: script.atv_bedroom_down
        icon: 'mdi:arrow-down-bold'
        name: Down
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.atv_bedroom_down
        type: entity-button
      - entity: script.atv_bedroom_exit
        icon: 'mdi:exit-to-app'
        name: Exit
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.atv_bedroom_exit
        type: entity-button
    type: horizontal-stack
  - cards:
      - entity: script.atv_bedroom_back
        icon: 'mdi:exit-to-app'
        name: Back
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.atv_bedroom_back
        type: entity-button
      - entity: script.atv_bedroom_home
        icon: 'mdi:home'
        name: ATV Home
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.atv_bedroom_home
        type: entity-button
      - entity: script.atv_bedroom_menu
        icon: 'mdi:menu'
        name: ATV Menu
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.atv_bedroom_menu
        type: entity-button
    type: horizontal-stack
type: vertical-stack

Note that at one point I defined a button that starts Kodi (or brings it into foreground), and also I have a reboot button (that works without confirmation).

This is what you should get in Lovelace:
That should make navigation easier.

You can also use the scripts as actions in various automations.

Next step is to use adb to get a screenshot of what's currently on the screen and display it as a webcam in Home Assistant. This will require extending the androidtv component code. Also interesting would be to log what app is being used on screen (to better understand what the kids are doing when unsupervised) :)

Comments

Hei said…
Hi I found a few issues with this method, it normally takes 2-3 seconds for the command to be sent which makes the control sluggish. Also I could not get the channel list button to work as well
molman said…
Found this possible answer to your slowness issues.

https://community.home-assistant.io/t/androidtv-adb-command-slow-delay-when-sending-command/214214
Unknown said…
thank you so much ive been trying to set this up and had no idea what i was doing wrong
Unknown said…
You do realize you have bugs in the Lovelace card right? Check the entity, you put scripts instead of the entity.
Matt said…
This is awesome. Did you ever figure out how to get screenshots of what was being played?

Popular posts from this blog

SmokePing + InfluxDB export + docker + slaves + Grafana = fun

I've been working for a while on this project - with the purpose of getting SmokePing measurements from different hosts (slaves) into InfluxDB so that we can better graph them with Grafana. The slaves run multiple Smokeping instances inside Docker so that they have separate networking (measure through different uplinks, independently). This will not be a comprehensive configuration guide, but a quick "how to" to handle setup and basic troubleshooting. It assumes you already know how to set up and operate a regular Smokeping install with or without slaves and that you are fluent in Smokeping configuration syntax, know your way around Docker and aren't a stranger from InfluxDB and Grafana (sorry, there's a lot of information to take in). 1. Getting Smokeping with InfluxDB support - you can get it either from the official page (most changes have been merged) - https://github.com/oetiker/SmokePing (PR discussion here: https://github.com/oetiker/SmokePing/issues/

Installing Home Assistant Supervised on an old 32bit HP laptop

 I've received a challenge from my former boss: an old HP laptop that was born in 2005:  an HP-Compaq NC6220 ( https://www.pocket-lint.com/laptops/reviews/hp/68181-hp-compaq-nc6220-notebook-laptop/ ). The specs are abysmal: So, i386, 1.7GHz single-core CPU (remember those?), 1G of DDR2 RAM (2x512M) and a 40GB ATA (not SATA!) drive. But hey, at least it has a serial port!  The challenge is to install HomeAssistant ( https://www.home-assistant.io/ ) on it so that he can monitor some Zigbee temperature sensors and relays (via a gateway). The first hurdle was to remove the BIOS password - following this nice guide: https://www.youtube.com/watch?v=ZaGKyb0ntSg Next-up - install HASSOS. Unfortunately, it doesn't support i386, but only x86_64... So, I went the Home Assistant Supervised route, and installed Debian 11 i386 edition from a netinstall USB ( https://cdimage.debian.org/debian-cd/current/i386/iso-cd/debian-11.6.0-i386-netinst.iso ).   Once Debian was up and running (didn't