How do I actually make a TV Remote Control work well in the GUI

Ok, first you need to install the custom button card: Lovelace: Button card

You will also need the custom:hui-element card, 🔹 hui-element - Use built-in elements in the wrong place this allows us to use things like horizontal stacks in entities cards.

Then at the top of the raw edit mode paste these button templates:

button_card_templates:
  icon_button:
    aspect_ratio: 4/3
    color_type: icon
    hold_action:
      action: none
    layout: vertical
    show_label: false
    show_name: false
    show_state: false
    styles:
      card:
        - border-radius: 10px
        - border: solid 1px var(--primary-color)
        - box-shadow: none
        - padding: 6px 6px
        - margin: 0px 0px
        - '--paper-card-background-color': 'rgba(0, 0, 0, 0)'
      icon:
        - width: 28px
      name:
        - justify-self: middle
        - align-self: end
        - font-size: 14px
        - padding: 0px 0px
        - color: var(--secondary-text-color)
    tap_action:
      action: call-service
  menu_button:
    aspect_ratio: 4/3
    color_type: icon
    hold_action:
      action: none
    layout: vertical
    show_label: false
    show_name: true
    show_state: false
    styles:
      card:
        - border-radius: 10px
        - border: solid 1px var(--primary-color)
        - box-shadow: none
        - padding: 6px 6px
        - margin: 0px 0px
        - '--paper-card-background-color': 'rgba(0, 0, 0, 0)'
      icon:
        - width: 28px
      name:
        - justify-self: middle
        - align-self: end
        - font-size: 14px
        - padding: 0px 0px
        - color: var(--secondary-text-color)
    tap_action:
      action: call-service

We can then use the templates to build our remotes. These are just a bunch of buttons in horizontal stacks in an entities card. The advantage of the entities card (rather than a vertical stack) is that it can have a title and has a border. e.g. my TV remote card:

entities:
  - card_type: horizontal-stack
    cards:
      - entity: script.lounge_tv_on
        name: 'On'
        tap_action:
          service: script.lounge_tv_on
        template: menu_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_off
        name: 'Off'
        tap_action:
          service: script.lounge_tv_off
        template: menu_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_input_tv
        name: TV
        tap_action:
          service: script.lounge_tv_input_tv
        template: menu_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_input_kodi
        icon: 'mdi:kodi'
        name: Movie
        tap_action:
          service: script.lounge_tv_input_kodi
        template: menu_button
        type: 'custom:button-card'
    type: 'custom:hui-element'
  - card_type: horizontal-stack
    cards:
      - entity: script.lounge_tv_play
        name: Play
        tap_action:
          service: script.lounge_tv_play
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_pause
        name: Pause
        tap_action:
          service: script.lounge_tv_pause
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_stop
        name: Stop
        tap_action:
          service: script.lounge_tv_stop
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_rec
        name: Record
        styles:
          icon:
            - color: red
        tap_action:
          service: script.lounge_tv_rec
        template: icon_button
        type: 'custom:button-card'
    type: 'custom:hui-element'
  - card_type: horizontal-stack
    cards:
      - entity: script.lounge_tv_menu
        name: Menu
        tap_action:
          service: script.lounge_tv_menu
        template: menu_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_rewind
        name: Rewind
        tap_action:
          service: script.lounge_tv_rewind
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_ffwd
        name: F-Forwad
        tap_action:
          service: script.lounge_tv_ffwd
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_ch_up
        name: Ch Up
        tap_action:
          service: script.lounge_tv_ch_up
        template: menu_button
        type: 'custom:button-card'
    type: 'custom:hui-element'
  - card_type: horizontal-stack
    cards:
      - entity: script.lounge_tv_option
        name: Options
        tap_action:
          service: script.lounge_tv_option
        template: menu_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_skip_back
        name: Skip Back
        tap_action:
          service: script.lounge_tv_skip_back
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_skip_fwd
        name: Skip Fwd
        tap_action:
          service: script.lounge_tv_skip_fwd
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_last_ch
        name: Last Ch
        tap_action:
          service: script.lounge_tv_last_ch
        template: menu_button
        type: 'custom:button-card'
    type: 'custom:hui-element'
  - card_type: horizontal-stack
    cards:
      - entity: script.lounge_tv_guide
        name: Guide
        tap_action:
          service: script.lounge_tv_guide
        template: menu_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_info
        icon: 'mdi:information-outline'
        name: Info
        tap_action:
          service: script.lounge_tv_info
        template: menu_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_up
        icon: 'mdi:arrow-up-bold'
        name: Up
        styles:
          card:
            - background: var(--secondary-background-color-alpha)
        tap_action:
          service: script.lounge_tv_up
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_ch_dn
        name: Ch Dn
        tap_action:
          service: script.lounge_tv_ch_dn
        template: menu_button
        type: 'custom:button-card'
    type: 'custom:hui-element'
  - card_type: horizontal-stack
    cards:
      - entity: script.lounge_tv_media
        icon: 'mdi:folder-multiple-image'
        name: Media
        tap_action:
          service: script.lounge_tv_media
        template: menu_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_left
        icon: 'mdi:arrow-left-bold'
        name: Left
        styles:
          card:
            - background: var(--secondary-background-color-alpha)
        tap_action:
          service: script.lounge_tv_left
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_ok
        name: Ok
        tap_action:
          service: script.lounge_tv_ok
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_right
        icon: 'mdi:arrow-right-bold'
        name: Right
        styles:
          card:
            - background: var(--secondary-background-color-alpha)
        tap_action:
          service: script.lounge_tv_right
        template: icon_button
        type: 'custom:button-card'
    type: 'custom:hui-element'
  - card_type: horizontal-stack
    cards:
      - entity: script.lounge_tv_www
        name: Internet
        tap_action:
          service: script.lounge_tv_www
        template: menu_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_return
        name: Return
        tap_action:
          service: script.lounge_tv_return
        template: menu_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_down
        icon: 'mdi:arrow-down-bold'
        name: Down
        styles:
          card:
            - background: var(--secondary-background-color-alpha)
        tap_action:
          service: script.lounge_tv_down
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_exit
        name: Exit
        tap_action:
          service: script.lounge_tv_exit
        template: menu_button
        type: 'custom:button-card'
    type: 'custom:hui-element'
  - card_type: horizontal-stack
    cards:
      - entity: script.lounge_tv_red
        name: Red
        styles:
          icon:
            - color: red
        tap_action:
          service: script.lounge_tv_red
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_green
        name: Green
        styles:
          icon:
            - color: '#00ff00'
        tap_action:
          service: script.lounge_tv_green
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_yellow
        name: Yellow
        styles:
          icon:
            - color: yellow
        tap_action:
          service: script.lounge_tv_yellow
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_tv_blue
        name: Blue
        styles:
          icon:
            - color: blue
        tap_action:
          service: script.lounge_tv_blue
        template: icon_button
        type: 'custom:button-card'
    type: 'custom:hui-element'
show_header_toggle: false
title: TV Remote
type: entities

In my case the scripts the buttons call send IR commands to an iTach but the process is similar for the RM (or any other method that can be scripted). Here are a few example scripts:

lounge_tv_down:
  sequence:
    service: remote.send_command
    data:
      entity_id: remote.lounge_tv
      command: "Down"

lounge_tv_exit:
  sequence:
    service: remote.send_command
    data:
      entity_id: remote.lounge_tv
      command: "Exit"

lounge_tv_ffwd:
  sequence:
    service: remote.send_command
    data:
      entity_id: remote.lounge_tv
      command: "FFwd"

Note that there is no icon specified anywhere. This is because the previous method I used had the icons assigned to scripts in customize:

script.lounge_tv_down:
  icon: mdi:arrow-down-bold-circle
  friendly_name: Down
script.lounge_tv_exit:
  icon: mdi:backspace
  friendly_name: Exit
script.lounge_tv_ffwd:
  icon: mdi:fast-forward

You don’t have to do it this way. Yo can specify an icon in the button card. e.g. here’s the card for the Kodi remote that does not use customize for the icons:

entities:
  - card_type: horizontal-stack
    cards:
      - entity: script.lounge_kodi_input_home
        icon: 'mdi:home'
        name: Home
        tap_action:
          service: script.lounge_kodi_input_home
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_input_contectx_menu
        icon: 'mdi:menu'
        name: Menu
        tap_action:
          service: script.lounge_kodi_input_contectx_menu
        template: menu_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_input_up
        icon: 'mdi:arrow-up-bold'
        name: Up
        styles:
          card:
            - background: var(--secondary-background-color-alpha)
        tap_action:
          service: script.lounge_kodi_input_up
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_input_info
        icon: 'mdi:information-outline'
        name: Info
        tap_action:
          service: script.lounge_kodi_input_info
        template: menu_button
        type: 'custom:button-card'
    type: 'custom:hui-element'
  - card_type: horizontal-stack
    cards:
      - entity: script.lounge_kodi_player_play_pause
        icon: 'mdi:play-pause'
        name: Play/Pause
        tap_action:
          service: script.lounge_kodi_player_play_pause
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_input_left
        icon: 'mdi:arrow-left-bold'
        name: Left
        styles:
          card:
            - background: var(--secondary-background-color-alpha)
        tap_action:
          service: script.lounge_kodi_input_left
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_input_select
        icon: 'mdi:check-circle-outline'
        name: Ok
        tap_action:
          service: script.lounge_kodi_input_select
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_input_right
        icon: 'mdi:arrow-right-bold'
        name: Right
        styles:
          card:
            - background: var(--secondary-background-color-alpha)
        tap_action:
          service: script.lounge_kodi_input_right
        template: icon_button
        type: 'custom:button-card'
    type: 'custom:hui-element'
  - card_type: horizontal-stack
    cards:
      - entity: script.lounge_kodi_player_stop
        icon: 'mdi:stop'
        name: Stop
        tap_action:
          service: script.lounge_kodi_player_stop
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_input_back
        icon: 'mdi:backburger'
        name: Return
        tap_action:
          service: script.lounge_kodi_input_back
        template: menu_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_input_down
        icon: 'mdi:arrow-down-bold'
        name: Down
        styles:
          card:
            - background: var(--secondary-background-color-alpha)
        tap_action:
          service: script.lounge_kodi_input_down
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_input_next_subtitle
        icon: 'mdi:subtitles-outline'
        name: Subtitle
        tap_action:
          service: script.lounge_kodi_input_next_subtitle
        template: menu_button
        type: 'custom:button-card'
    type: 'custom:hui-element'
  - card_type: horizontal-stack
    cards:
      - entity: script.lounge_kodi_player_rewind
        icon: 'mdi:rewind'
        name: Rewind
        tap_action:
          service: script.lounge_kodi_player_rewind
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_player_fast_fwd
        icon: 'mdi:fast-forward'
        name: Forward
        tap_action:
          service: script.lounge_kodi_player_fast_fwd
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_player_skip_back
        icon: 'mdi:skip-previous'
        name: Skip Back
        tap_action:
          service: script.lounge_kodi_player_skip_back
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_player_skip_fwd
        icon: 'mdi:skip-next'
        name: Skip Fwd
        tap_action:
          service: script.lounge_kodi_player_skip_fwd
        template: icon_button
        type: 'custom:button-card'
    type: 'custom:hui-element'
  - card_type: horizontal-stack
    cards:
      - entity: script.lounge_kodi_player_skip_back_30
        icon: 'mdi:rewind-30'
        name: Back 30s
        tap_action:
          service: script.lounge_kodi_player_skip_back_30
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_player_skip_back_10
        icon: 'mdi:rewind-10'
        name: Back 10s
        tap_action:
          service: script.lounge_kodi_player_skip_back_10
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_player_skip_fwd_10
        icon: 'mdi:fast-forward-10'
        name: Fwd 10s
        tap_action:
          service: script.lounge_kodi_player_skip_fwd_10
        template: icon_button
        type: 'custom:button-card'
      - entity: script.lounge_kodi_player_skip_fwd_30
        icon: 'mdi:fast-forward-30'
        name: Fwd 30s
        tap_action:
          service: script.lounge_kodi_player_skip_fwd_30
        template: icon_button
        type: 'custom:button-card'
    type: 'custom:hui-element'
  - artwork: full-cover
    entity: media_player.lounge_osmc_kodi
    group: true
    hide:
      artwork: false
      controls: true
      icon: true
      name: true
      power: true
      power_state: true
      source: true
      volume: true
    icon: 'mdi:kodi'
    info: scroll
    type: 'custom:mini-media-player'
show_header_toggle: false
title: Kodi Remote
type: entities

Also:

Rimmer: “Mr. Flibble’s very cross. What are we going to do with them Mr. Flibble?”
(…)
Rimmer: “We can’t possibly do that! Who’d clear up the mess?”

:rofl:

18 Likes