Google Assistant media player support using IFTTT recipes
Tested on HA version 0.83
This is a setup I use to allow Google Assistant to send commands to my broadlink and/or openmqttgateway IR devices to control my PVR and TV. It allows full channel, volume, pause and power control. I use custom components that create media_players from IR devices such as the broadlink. See the project here:
The script below will allow a lot of versatility to control many devices using IFTTT rules, including media players. Note, i’ve only used this for channel, volume and pause/play control. I also use amazon smart home to accomplish the same thing but instead use a custom smart_home alexa component in addition to the media player ones.
I use the webhook api instead of the services one since it allows me to have dedicated key that can only be used by webhooks. I don’t use the legacy auth method. The first step is to setup webhooks in HA using the docs in this link:
https://www.home-assistant.io/components/ifttt/.
I wish IFTTT would allow the ability to send an Auth header in their webhooks as it would allow us to send the bearer token encrypted with the data payload. I really hate sending the key in the clear with the url. Unfortunately, they didnt and I don’t get why. Nevertheless, webhooks on HA with a unique key is what we have, so that’s what I use.
Once you have the URL with associated webhook id , you can then go to IFTTT and using that generated URL,
you can then create your control recipes. For example , I created a new google assistant trigger using the phrase config “Say a phrase with a number” and setup the phrase as “tune to channel #” . I then used a json body as below:
{ "service": "media_player.play_media", "entity_id": "media_player.tv","media_content_id":" {{NumberField}}","media_content_type":"channel" }
For the HA side, the ifttt docs in the url above show an example of a simple automation that will consume a basic switch/light type of control that only sends an on or off command. For media players, more attributes are required. I didnt want to go the route of creating a separate automation with conditional rules to catch all the possible types of actions and services i wanted to consume so I modified the automation a bit and added a simple python script in the mix. I had hoped to be able to do this only using if - else rules in the action scripts but it does not allow the ability to arbitrarily choose what attributes to send, only the values of the fixed attributes. If there is a way, I couldnt see it. Anyhow, this was unsuitable for what I needed.
This is what I came up with. The HA config is below. Create a directiory called “python_scripts” in your HA config directory and place the ifttt_hook.py there. Then add the automation below to your automations.yaml file. As a final step, add the config line “python_script:” to your configuration.yaml file to activate python scripts as services.
#This automation will consume an ifttt webhook event and create a service call to a the python script below. Every possible attribute that we want to be able to use in a recipe is iterated in the data_template. Not all values will be used for any particular service. It will be the job of the python script to remove any empty ones. This is so that we can use one generic universal automation script for any possible ifttt recipe used without having to create separate automation/action sequences for every service we want to run. If you need other attributes such as seek_position, etc. you can add them to the automation and in your ifttt recipe. For example switches only need the entity_id, while media_play will use the entity_id, media_content_type and media_content_id attributes.
/automations.yaml
- alias: Consume IFTTT - pythonscript
trigger:
platform: event
event_type: ifttt_webhook_received
event_data:
action: call_service
action:
service_template: python_script.ifttt_hook
data_template:
entity_id: '{{ trigger.event.data.entity_id }}'
service: '{{ trigger.event.data.service }}'
media_content_id: '{{ trigger.event.data.media_content_id }}'
media_content_type: '{{ trigger.event.data.media_content_type }}'
volume_level: '{{ trigger.event.data.volume_level }}'
is_volume_muted: '{{ trigger.event.data.is_volume_muted }}'
source: '{{ trigger.event.data.source }}'
#This script will get called by the ifttt automation above and will remove all empty dictionary values as well as the
service name and webhook_id. This will leave only the service data values sent by the ifttt recipe to be used by the service to be called (as entered in the IFTTT json recipe payload). It will then call the requested service with the filtered attributes.
/python_scripts/ifttt_hook.py
service_name=data.get('service')
service_data={k: v for k, v in data.items() if v }
service_data.pop('service',None)
service_data.pop('webhook_id',None)
if service_name is not None:
domain,service=service_name.split('.')
hass.services.call(domain,service,service_data,False)
/configuration.yaml
python_script: