Here’s my recently finished (is anything ever finished?) Harmony setup, maybe it’ll inspire or assist someone.
My setup
I have a simple harmony setup, mainly TV, Soundbar and Playstation.
In TV mode I might be watching a smart TV App or casting to a chromecast in one of the HDMI sockets. Unlike the other TV in my house CEC doesn’t work so I can’t control the chromecast with the TV (pause etc.) or the TV from chromecast (power on).
In music mode the TV is off (as is the chromecast as it’s powered by the TV’s USB), the soundbar is on and a Google Home hub pairs over bluetooth.
My family are easily confused and can never remember whether (for example) they have to press pause on the harmony remote or say “ok Google, pause chromecast” / use their phones to pause. So, I want home assistant to provide them with a single, context aware, remote control. So when they press pause / play / stop etc. it does it no matter what the source is.
It’s designed to look best on the various phones my family have, but the screen shots are from a desktop. This makes it look like a bit of a space waster
Basically, there’s a vertical-stack-in-card with one picture-elements card at the top for the activities and 3 conditional picture-elements cards which so up depending on what activity is selected. Check code comments for more detail on that.
The buttons are styled using a YAML anchor to reduce the repetition and enable changes for all buttons to be made in one place.
The activity buttons are switches which lets me toggle activities on and off.
Most of the other buttons just run the remote.send_command to send the relevant Harmony command.
The Play, Pause and Stop buttons update an input_text field. When the state of this changes it triggers a node-red flow which works out exactly what needs to be played, paused or stopped.
The config’s below - I split mine using includes to keep things simple. But I’ve put the name of the “master” file against each element for those that find it useful.
Harmony Switches (the icon templates are a hold-over from a different way of doing it and not required) (configuration.yaml)
- platform: template
switches:
lounge_tv:
friendly_name: Lounge TV
value_template: "{{ is_state_attr('remote.lounge', 'current_activity', 'TV') }}"
turn_on:
service: remote.turn_on
data:
entity_id: remote.lounge
activity: 'TV'
turn_off:
service: remote.turn_on
data:
entity_id: remote.lounge
activity: 'PowerOff'
icon_template: >-
{% if is_state_attr('remote.lounge', 'current_activity', 'TV') %}
mdi:television-classic
{% else %}
mdi:television-classic-off
{% endif %}
soundbar:
friendly_name: Soundbar
value_template: "{{ is_state_attr('remote.lounge', 'current_activity', 'Soundbar') }}"
turn_on:
service: remote.turn_on
data:
entity_id: remote.lounge
activity: 'Soundbar'
turn_off:
service: remote.turn_on
data:
entity_id: remote.lounge
activity: 'PowerOff'
icon_template: >-
{% if is_state_attr('remote.lounge', 'current_activity', 'Soundbar') %}
mdi:music
{% else %}
mdi:music-off
{% endif %}
ps3:
friendly_name: PS4
value_template: "{{ is_state_attr('remote.lounge', 'current_activity', 'PS4') }}"
turn_on:
service: remote.turn_on
data:
entity_id: remote.lounge
activity: 'PS4'
turn_off:
service: remote.turn_on
data:
entity_id: remote.lounge
activity: 'PowerOff'
icon_template: >-
{% if is_state_attr('remote.lounge', 'current_activity', 'PS4') %}
mdi:playstation
{% else %}
mdi:playstation
{% endif %}
The text input thingy (configuration.yaml)
input_text:
remote_command:
name: Remote Command
The main remote control (ui-lovelace.yaml) - big but there’s a lot of repetitive bits so it’s really not complicated. There’s some comments to help as well.
# Harmony Remote Control
# Vertical-stack-in-card makes a 'dynamic' remote control where the buttons change according to the activity
- type: custom:vertical-stack-in-card
title: Lounge Entertainment
cards:
# Set Harmony Activity, this section always shows
# Harmony Activities are configured as template switches
- type: picture-elements
image: /local/images/short-empty.png?v2.2
elements:
- type: image
entity: switch.lounge_tv
tap_action:
action: toggle
image: /local/images/remote/tv.svg?v1
state_filter:
"on": invert(.5) sepia(1) saturate(8) hue-rotate(10deg)
style:
top: 50%
left: 20%
# Reuse these values with <<: *style_anchor in the style section for each button
<<: &style_anchor
width: 2em
height: 2em
padding: 15px
background-color: var(--paper-item-icon-color)
border-radius: 50%
box-shadow: 0 3px 5px -1px rgba(0,0,0,.2), 0 6px 10px 0 rgba(0,0,0,.14), 0 1px 18px 0 rgba(0,0,0,.12)
- type: image
entity: switch.soundbar
tap_action:
action: toggle
image: /local/images/remote/music.svg?v1
state_filter:
"on": invert(.5) sepia(1) saturate(8) hue-rotate(10deg)
style:
<<: *style_anchor
top: 50%
left: 50%
- type: image
entity: switch.ps3
tap_action:
action: toggle
image: /local/images/remote/ps4.svg?v1
state_filter:
"on": invert(.5) sepia(1) saturate(8) hue-rotate(10deg)
style:
<<: *style_anchor
top: 50%
left: 80%
# Display full remote when Harmony's TV Activity is on
# Commands sent straight to Harmony with remote.send_command
# Info, such as the Device ID come from config/harmony_XXXX.conf
- type: conditional
conditions:
- entity: switch.lounge_tv
state: "on"
card:
type: picture-elements
image: /local/images/empty.png?v2.4
elements:
- type: image # Menu
tap_action:
action: call-service
service: remote.send_command
service_data:
entity_id: remote.lounge
device: 29590173
command: SmartHub
image: /local/images/remote/menu.svg?v1
style:
<<: *style_anchor
top: 15%
left: 20%
- type: image # Exit
entity: media_player.lounge_chromecast
tap_action:
action: call-service
service: remote.send_command
service_data:
entity_id: remote.lounge
device: 29590173
command: Exit
image: /local/images/remote/cast.svg?v1 # using a cast image as exit only gets used to quit apps an watch cast content
state_filter: # light up the button when chromecast is playing (as a nudge if the TV's sitting in an app)
playing: invert(.5) sepia(1) saturate(8) hue-rotate(10deg)
paused: invert(.5) sepia(1) saturate(8) hue-rotate(10deg)
style:
<<: *style_anchor
top: 15%
left: 50%
- type: image # Back
tap_action:
action: call-service
service: remote.send_command
service_data:
entity_id: remote.lounge
device: 29590173
command: Return
image: /local/images/remote/back.svg?v1
style:
<<: *style_anchor
top: 15%
left: 80%
- type: image # Up
tap_action:
action: call-service
service: remote.send_command
service_data:
entity_id: remote.lounge
device: 29590173
command: DirectionUp
image: /local/images/remote/up.svg?v1
style:
<<: *style_anchor
top: 44%
left: 50%
- type: image # Left
tap_action:
action: call-service
service: remote.send_command
service_data:
entity_id: remote.lounge
device: 29590173
command: DirectionLeft
image: /local/images/remote/left.svg?v1
style:
<<: *style_anchor
top: 65%
left: 32%
- type: image # OK
tap_action:
action: call-service
service: remote.send_command
service_data:
entity_id: remote.lounge
device: 29590173
command: Select
image: /local/images/remote/return.svg?v1
style:
<<: *style_anchor
top: 65%
left: 50%
- type: image # Right
tap_action:
action: call-service
service: remote.send_command
service_data:
entity_id: remote.lounge
device: 29590173
command: DirectionRight
image: /local/images/remote/right.svg?v1
style:
<<: *style_anchor
top: 65%
left: 68%
- type: image # Down
tap_action:
action: call-service
service: remote.send_command
service_data:
entity_id: remote.lounge
device: 29590173
command: DirectionDown
image: /local/images/remote/down.svg?v1
style:
<<: *style_anchor
top: 86%
left: 50%
# Display Play / Pause / Stop when TV or Soundbar is active
# These set the value of an input_text field which triggers a node-red flow which either:
# - sends harmony remote commands if watching TV app (TV is on / chromecast inactive)
# - controls chromecast if casting to it (TV is on / chromecast active)
# - controls google home if listening to music (TV is off / speaker is on)
- type: conditional
conditions:
- entity: remote.lounge
state: "on"
- entity: switch.ps3
state: "off"
card:
type: picture-elements
image: /local/images/short-empty.png?v2.1
elements:
- type: image # Play
tap_action:
action: call-service
service: input_text.set_value
service_data:
entity_id: input_text.remote_command
value: play
image: /local/images/remote/play.svg?v1
style:
<<: *style_anchor
top: 50%
left: 20%
- type: image # Pause
tap_action:
action: call-service
service: input_text.set_value
service_data:
entity_id: input_text.remote_command
value: pause
image: /local/images/remote/pause.svg?v1
style:
<<: *style_anchor
top: 50%
left: 50%
- type: image # Stop
entity: input_boolean.remote_stop
tap_action:
action: call-service
service: input_text.set_value
service_data:
entity_id: input_text.remote_command
value: stop
image: /local/images/remote/stop.svg?v1
style:
<<: *style_anchor
top: 50%
left: 80%
# Display volume controls when any Activity is on
- type: conditional
conditions:
- entity: remote.lounge
state: "on"
card:
type: picture-elements
image: /local/images/short-empty.png?v2.1
elements:
- type: image # Volume Up
tap_action:
action: call-service
service: remote.send_command
service_data:
entity_id: remote.lounge
device: 29590173
command: VolumeUp
image: /local/images/remote/volup.svg?v1
style:
<<: *style_anchor
top: 40%
left: 80%
- type: image # Mute
tap_action:
action: call-service
service: remote.send_command
service_data:
entity_id: remote.lounge
device: 29590173
command: Mute
image: /local/images/remote/mute.svg?v1
style:
<<: *style_anchor
top: 40%
left: 50%
- type: image # Volume Down
tap_action:
action: call-service
service: remote.send_command
service_data:
entity_id: remote.lounge
device: 29590173
command: VolumeDown
image: /local/images/remote/voldown.svg?v1
style:
<<: *style_anchor
top: 40%
left: 20%
Node-Red flow - I’ll share if anyone’s interested but it might be kind of niche for my situation. I expect scripts / automations would also work but I’m too lazy to learn how to do them.
Enjoy, hope this helps someone.