Connecting to Nvidia Shield (or other Android TV) via Bluetooth for media control, wake/sleep

Hi All,

I’m aware of the solutions requiring the use of ADB and if things become dire, I’ll go down that road, but I wanted to see if there’s a way to connect my HA instance to my Nvidia Shield TV. It’s the later version, so no IR receiver, unfortunately.

I’m worried that eventually my Harmony setup will die and they’ll stop supporting it entirely. To get ahead of that, I’m wondering if there’s a way to use HA to connect to it and control media (wake, sleep, play/pause/stop, Home, OK, back - standard android buttons). I do have a BT proxy already created, but haven’t seen a way to add the Nvidia Shield as an integration.

Harmony simulates a Bluetooth keyboard when it connects to the Shield, so I figure there’s got to be a similar integration in HA, but I haven’t found anything yet. I did try googling this for a while, but came up with nothing.

Are there any good solutions?

I’m in exactly the same situation, fearing the moment when my beloved Harmony will die :frowning:

I’m using

  • an ESP32 as a bluetooth remote controllable through HA. See ESPHome BLE Keyboard
  • cheap bluetooth and/or RF remotes that talk to HA via the “keyboard remote” integration (Keyboard Remote - Home Assistant)
  • an integration of my own that simulates the “activities” of an Harmony

to “emulate” the Harmony.

1 Like

Awesome, this gives me a starting point.

Do you have any more info on the remotes, use of keyboard remote, and integration you use? Or have a github?

This is an example of remote: https://www.aliexpress.com/item/1005003624384228.html
I also tried RF “airmouse” remotes that work fine.
Currently, I’m using an old BT FireTV remote I had laying around :wink:

That’s an example for keyboard_remote. Nothing fancy, it basically create HA events from keyboard events.

keyboard_remote:
- device_name: 'Amazon Fire TV Remote Keyboard'
  emulate_key_hold: true
  type:
    - 'key_up'
    - 'key_down'
    - 'key_hold'
- device_name: 'B06B Consumer Control'
  emulate_key_hold: true
  type:
    - 'key_up'
    - 'key_down'
    - 'key_hold'
- device_name: '2.4G Composite Devic'
  type:
    - 'key_up'
    - 'key_down'
    - 'key_hold'
- device_name: '2.4G Composite Devic Consumer Control'
  type:
    - 'key_up'
    - 'key_down'
- device_name: '2.4G Composite Devic System Control'
  type:
    - 'key_up'
    - 'key_down'

That’s the integration.
I never made any publicity because I don’t want to support it, honestly :wink:

This is what I use for shield with state_automate.
The “button.*” entities are created by ESPhome. The numbers are from the keyboard events.

state_automate:
  - name: Automate Airmouse
    event_type: keyboard_remote_command_received
    event_value: key_code
    event_data:
      type: key_down | key_hold
    activities: !include_dir_list state_automate/airmouse
❯ cat 01-shield_tv_esp.yaml
name: "TV Shield (ESP)"
states state: !include ../include/common_states.yaml
states power: !include ../include/common_power.yaml
states tv: !include ../include/common_tv.yaml
states:
  # - enter:
  #   - service: media_player.turn_on
  #     target:
  #       entity_id: media_player.shield_atv
  #   - service: media_player.turn_on
  #     target:
  #       entity_id: media_player.sony_tv
  #   - service: media_player.select_source
  #     target:
  #       entity_id: media_player.sony_tv
  #     data:
  #       source: "HDMI 2/MHL"
  #   - service: media_player.turn_on
  #     target:
  #       entity_id: media_player.onkyo
  #   - service: media_player.select_source
  #     target:
  #       entity_id: media_player.onkyo
  #     data:
  #       source: "ARC"
  # - leave:
  #   - service: media_player.turn_off
  #     target:
  #       entity_id: media_player.shield_atv
  #   - service: media_player.turn_off
  #     target:
  #       entity_id: media_player.sony_tv
  #   - service: media_player.turn_off
  #     target:
  #       entity_id: media_player.onkyo
  #
  # PLAY_PAUSE
  - 164:
    - service: androidtv.adb_command
      target:
        entity_id: media_player.shield_atv
      data:
        command: input keyevent 85
  # SEARCH (MI remote)
  - 217:
    - service: androidtv.adb_command
      target:
        entity_id: media_player.shield_atv
      data:
        command: input keyevent 85
  # NEXT
  - 163:
    - service: androidtv.adb_command
      target:
        entity_id: media_player.shield_atv
      data:
        command: input keyevent 87
  # PREVIOUS
  - 165:
    - service: androidtv.adb_command
      target:
        entity_id: media_player.shield_atv
      data:
        command: input keyevent 88
  # # FORWARD
  # - 208:
  #   - service: androidtv.adb_command
  #     target:
  #       entity_id: media_player.shield_atv
  #     data:
  #       command: input keyevent 90
  # # REWIND
  # - 168:
  #   - service: androidtv.adb_command
  #     target:
  #       entity_id: media_player.shield_atv
  #     data:
  #       command: input keyevent 89

  # REWIND
  - 168:
    - service: remote.send_command
      target:
        entity_id: remote.sony_bravia_tv
      data:
        command: VolumeDown
  # FORWARD
  - 208:
    - service: remote.send_command
      target:
        entity_id: remote.sony_bravia_tv
      data:
        command: VolumeUp

  # COMPOSE
  - 127:
    - service: androidtv.adb_command
      target:
        entity_id: media_player.shield_atv
      data:
        command: MENU
  # MENU
  - 139:
    - service: androidtv.adb_command
      target:
        entity_id: media_player.shield_atv
      data:
        command: MENU
  # APPSELECT
  - 580:
    - service: androidtv.adb_command
      target:
        entity_id: media_player.shield_atv
      data:
        command: MENU
  # HOMEPAGE
  - 172:
    - service: androidtv.adb_command
      target:
        entity_id: media_player.shield_atv
      data:
        command: HOME
  # OK
  - 28:
    - service: button.press
      target:
        entity_id: button.return
  # KPENTER
  - 96:
    - service: button.press
      target:
        entity_id: button.return
  # SELECT
  - 353:
    - service: button.press
      target:
        entity_id: button.return
  # BACK
  - 158:
    - service: button.press
      target:
        entity_id: button.esc
  # UP
  - 103:
    - service: button.press
      target:
        entity_id: button.up_arrow
  # DOWN
  - 108:
    - service: button.press
      target:
        entity_id: button.down_arrow
  # LEFT
  - 105:
    - service: button.press
      target:
        entity_id: button.left_arrow
  # RIGHT
  - 106:
    - service: button.press
      target:
        entity_id: button.right_arrow
  # PAGEUP
  - 104:
    - service: button.press
      target:
        entity_id: button.page_up
  # PAGEDOWN
  - 109:
    - service: button.press
      target:
        entity_id: button.page_down

1 Like

Holy moly, good stuff! Thank you, I’m going to have my work cut out for me trying to understand all the bits and pieces, but this is great.

On my nVidia shieldTV (2019) I ended up having to use a combination of media_player (for simple turn on/of, volume) - and adb_command to launch apps. Rather messy and very crude.
Biggest issue was that I could launch the apps using adb - but not control them except by simulating sequences of remote control keypresses.