Hello everyone, I’ve been getting quite a few messages about my harmony setup, so I decided to create this post to give it more visibility.
I attempted to create a ‘minimalist’ approach to an interface that works identical to the harmony remotes activities. That being, when one activity is turned on, all others are off. This functionality is built into the harmony remote and it can be quite difficult to replicate in the Home Assistant user interface.
The second thing to note here is that I also use a receiver. My harmony activities turn on my receiver, set the correct input, and adjust volume. That’s why my interface also shows my receiver. The interface consists of 2 Lovelace cards, both which are picture-glance cards. Each card has a row of toggles that have specific tasks. On the harmony card, the toggles represent each activity. On the receiver card, the toggles represent an on/off for each zone. The zones for the receiver are areas of my house in which the sound comes through. Zone 1 being the living room and zone 2 being the dining room. You’ll also notice 2 icons that represent google home. When these are turned on, google home transmits sound through my receiver. So lets take a look at the interface.
Powered Off
This is what the interface looks like when the system is powered off. Notice all the toggles on the bottom of each card is dark in color. This means they are off.
Xbox One is On
You’ll notice that a volume slider appears for the receiver and now a info box appears with the Xbox Activites that are detected.
Playstation is On and Zone 2 is On.
You’ll notice that the xbox information is gone and now I have 2 volume sliders, one for each zone. I suppose I should rename those zones to the actual names, like Living Room Volume and Dining Room Volume.
Ok, so now here is the configuration:
Harmony Setup
remote:
- platform: harmony
name: living_room
host: !secret remote_host
This is located inside configuration.yaml. I do not use discovery because I don’t like dealing with things changing on the fly.
The available harmony activities inside harmony_living_room.conf:
Activities
26592473 - Switch
-1 - PowerOff
24089909 - PS4
24103421 - Xbox One
24090202 - Wii U
24090353 - PC
30947237 - TV
Reciever Setup
media_player:
- platform: yamaha
host: !secret yamaha_host
source_ignore:
- AV1
- AV2
- AV3
- AV4
- AV5
- AV6
- Pandora
- Rhapsody
- SiriusXM
- Spotify
- Tuner
- USB
- V-AUX
source_names:
HDMI1: "Xbox One"
HDMI2: "Playstation 4"
HDMI3: "Wii U"
HDMI4: "PC"
HDMI5: "Switch"
AUDIO1: "Phone"
AUDIO2: "Echo"
This is located inside configuration.yaml. Again I avoid discovery.
Template Switches (the toggles on the Lovelace picture-glance cards)
switch: !include switch.yaml
This is located inside configuration.yaml. The contents of the switch.yaml are:
- platform: template
switches:
# ZONE 1 MEDIA SWITCH
zone_1:
value_template: "{{ is_state('media_player.yamaha_receiver', 'on') }}"
turn_on:
service: media_player.turn_on
entity_id: media_player.yamaha_receiver
turn_off:
service: media_player.turn_off
entity_id: media_player.yamaha_receiver
# ZONE 2 MEDIA SWITCH
zone_2:
value_template: "{{ is_state('media_player.yamaha_receiver_zone_2', 'on') }}"
turn_on:
service: media_player.turn_on
entity_id: media_player.yamaha_receiver_zone_2
turn_off:
service: media_player.turn_off
entity_id: media_player.yamaha_receiver_zone_2
# XBOX HARMONY ACTIVITY
xbox_one:
value_template: "{{ is_state_attr('remote.living_room', 'current_activity', 'Xbox One') }}"
turn_on:
service: remote.turn_on
data:
entity_id: remote.living_room
activity: 'Xbox One'
turn_off:
service: remote.turn_on
data:
entity_id: remote.living_room
activity: 'PowerOff'
# PLAYSTATION HARMONY ACTIVITY
ps4:
value_template: "{{ is_state_attr('remote.living_room', 'current_activity', 'PS4') }}"
turn_on:
service: remote.turn_on
data:
entity_id: remote.living_room
activity: 'PS4'
turn_off:
service: remote.turn_on
data:
entity_id: remote.living_room
activity: 'PowerOff'
# WII U HARMONY ACTIVITY
wii_u:
value_template: "{{ is_state_attr('remote.living_room', 'current_activity', 'Wii U') }}"
turn_on:
service: remote.turn_on
data:
entity_id: remote.living_room
activity: 'Wii U'
turn_off:
service: remote.turn_on
data:
entity_id: remote.living_room
activity: 'PowerOff'
# PC HARMONY ACTIVITY
pc:
value_template: "{{ is_state_attr('remote.living_room', 'current_activity', 'PC') }}"
turn_on:
service: remote.turn_on
data:
entity_id: remote.living_room
activity: 'PC'
turn_off:
service: remote.turn_on
data:
entity_id: remote.living_room
activity: 'PowerOff'
# SWITCH HARMONY ACTIVITY
switch:
value_template: "{{ is_state_attr('remote.living_room', 'current_activity', 'Switch') }}"
turn_on:
service: remote.turn_on
data:
entity_id: remote.living_room
activity: 'Switch'
turn_off:
service: remote.turn_on
data:
entity_id: remote.living_room
activity: 'PowerOff'
# TV HARMONY ACTIVITY
tv:
value_template: "{{ is_state_attr('remote.living_room', 'current_activity', 'TV') }}"
turn_on:
service: remote.turn_on
data:
entity_id: remote.living_room
activity: 'TV'
turn_off:
service: remote.turn_on
data:
entity_id: remote.living_room
activity: 'PowerOff'
# AUDIO 1, USED FOR ECHO AND MUSIC ZONE 1
audio_1:
value_template: "{{ is_state_attr('media_player.yamaha_receiver', 'source', 'Echo') and is_state('switch.floating_outlet_switch', 'on') }}"
turn_on:
- service: switch.turn_on
entity_id: switch.floating_outlet_switch
- service: media_player.turn_on
entity_id: media_player.yamaha_receiver
- service: media_player.select_source
data:
entity_id: media_player.yamaha_receiver
source: Echo
- service: media_player.volume_set
data:
entity_id: media_player.yamaha_receiver
volume_level: 0.7
turn_off:
- service: switch.turn_off
entity_id: switch.floating_outlet_switch
- service: media_player.turn_off
entity_id: media_player.yamaha_receiver
# AUDIO 2, USED FOR ECHO AND MUSIC ZONE 2
audio_2:
value_template: "{{ is_state_attr('media_player.yamaha_receiver_zone_2', 'source', 'Echo') and is_state('switch.floating_outlet_switch', 'on') }}"
turn_on:
- service: switch.turn_on
entity_id: switch.floating_outlet_switch
- service: media_player.turn_on
entity_id: media_player.yamaha_receiver_zone_2
- service: media_player.select_source
data:
entity_id: media_player.yamaha_receiver_zone_2
source: Echo
- service: media_player.volume_set
data:
entity_id: media_player.yamaha_receiver_zone_2
volume_level: 0.7
turn_off:
- service: switch.turn_off
entity_id: switch.floating_outlet_switch
- service: media_player.turn_off
entity_id: media_player.yamaha_receiver_zone_2
Volume Sliders
Disclaimer: I use appdaemon for my automation. These automations are what I would use if I used normal volume configuration (these could contain typos):
input_number: !include input_number.yaml
This is located inside configuration.yaml. The contents of the input_number.yaml are:
yamaha_receiver:
name: Zone 1 Volume
initial: -80
min: -80
max: 0
step: 5
unit_of_measurement: dB
yamaha_receiver_zone_2:
name: Zone 2 Volume
initial: -80
min: -80
max: 0
step: 5
unit_of_measurement: dB
The units of dB are negative, that’s why this is such a weird setup. My receiver shows the volume as negative so I’m emulating that here. Media_players only accept volume levels between 0 and 1. So because of that, I need to convert decibels to a 0 to 1 representation. That is handled by these automations:
- alias: Zone 1 Volume (Media to Slider)
trigger:
- platform: state
entity_id: media_player.yamaha_receiver
condition:
- condition: template
value_template: >
# convert to decibel.
{% set converted = ( -1.0 + trigger.to_state.attributes.volume_level | float ) * 100.0 | round(0.0) %}
# Removes feedback loop
{{ converted != states('input_number.yamaha_receiver') | float }}
action:
service: input_number.set_value
data_template:
entity_id: input_number.yamaha_receiver
value: >
{{ ( ( -1.0 + trigger.to_state.attributes.volume_level | float ) * 100.0 ) | round(0.0) }}
- alias: Zone 1 Volume (Slider to Media)
trigger:
- platform: state
entity_id: input_number.yamaha_receiver
condition:
- condition: template
value_template: >
# convert from decibel.
{% set converted = (1.0 - trigger.to_state.state | float / 100.0) | round(2) %}
# Removes feedback loop
{{ converted != state_attr('media_player.yamaha_receiver','volume_level') | float }}
action:
- service: media_player.volume_set
data_template:
entity_id: media_player.yamaha_receiver
volume_level: >
{{ (1.0 - trigger.to_state.state | float / 100.0) | round(2) }}
- alias: Zone 2 Volume (Media to Slider)
trigger:
- platform: state
entity_id: media_player.yamaha_receiver_zone_2
condition:
- condition: template
value_template: >
# convert to decibel.
{% set converted = ( -1.0 + trigger.to_state.attributes.volume_level | float ) * 100.0 | round(0.0) %}
# Removes feedback loop
{{ converted != states('input_number.yamaha_receiver_zone_2') | float }}
action:
service: input_number.set_value
data_template:
entity_id: input_number.yamaha_receiver_zone_2
value: >
{{ ( ( -1.0 + trigger.to_state.attributes.volume_level | float ) * 100.0 ) | round(0.0) }}
- alias: Zone 2 Volume (Slider to Media)
trigger:
- platform: state
entity_id: input_number.yamaha_receiver_zone_2
condition:
- condition: template
value_template: >
# convert from decibel.
{% set converted = (1.0 - trigger.to_state.state | float / 100.0) | round(2) %}
# Removes feedback loop
{{ converted != state_attr('media_player.yamaha_receiver_zone_2','volume_level') | float }}
action:
- service: media_player.volume_set
data_template:
entity_id: media_player.yamaha_receiver_zone_2
volume_level: >
{{ (1.0 - trigger.to_state.state | float / 100.0) | round(2) }}
Template Sensor
This will help Lovelace properly change the image. This is needed because when your remote is off, the activity is blank. We need to have a sensor that always has information so lovelace doesn’t get screwed up!
sensor:
- platform: template
sensors:
harmony_activity:
value_template: >
{% if is_state("remote.living_room", 'on') %}
{{ states.remote.living_room.attributes.current_activity }}
{% else %}
PowerOff
{% endif %}
Lovelace
This interface uses all cards that are provided by Lovelace, no custom cards are needed.
Here is ui-lovelace.yaml (stripped to just the items needed for this setup)
title: Petros Setup
views:
- icon: mdi:television
title: Entertainment
id: entertainment
cards:
- type: vertical-stack
cards:
- type: picture-glance
title: Harmony
entities:
- switch.xbox_one
- switch.ps4
- switch.wii_u
- switch.pc
- switch.switch
- switch.tv
state_image:
"PowerOff": /local/images/power_off.png
"Xbox One": /local/images/xbox_one_logo.png
"PS4": /local/images/playstation_logo.png
"Wii U": /local/images/wiiu_logo.png
"PC": /local/images/windows_logo.png
"Switch": /local/images/nintendo_switch_logo.png
"TV": /local/images/sony_logo.png
entity: sensor.harmony_activity
- type: entity-filter
entities:
- sensor.xbox_live_name
- sensor.xbox_current
state_filter:
- 'Online'
- 'Home'
- 'Netflix'
show_empty: false
- type: vertical-stack
cards:
- type: picture-glance
title: Yamaha Receiver
entities:
- switch.zone_1
- switch.audio_1
- switch.zone_2
- switch.audio_2
image: /local/images/rxv677.png
- type: conditional
conditions:
- entity: switch.zone_1
state: 'on'
- entity: switch.zone_2
state: 'on'
card:
type: entities
entities:
- entity: input_number.yamaha_receiver
name: Zone 1 Volume
- entity: input_number.yamaha_receiver_zone_2
name: Zone 2 Volume
- type: conditional
conditions:
- entity: switch.zone_1
state: 'on'
- entity: switch.zone_2
state: 'off'
card:
type: entities
entities:
- entity: input_number.yamaha_receiver
name: Volume
- type: conditional
conditions:
- entity: switch.zone_1
state: 'off'
- entity: switch.zone_2
state: 'on'
card:
type: entities
entities:
- entity: input_number.yamaha_receiver_zone_2
name: Volume