Automation with Firetv/Emby

I need some help. We use Emby server with firetv’s throughout our house. My 3 year old has special needs… We have finally gotten her to stay in her room until her clock turns green at 7am… then she runs down the stair and wakes me up… “papa I want a show…” I’d like to be able to automate launching the emby app on a firetv stick and then starting one of several movies, at 7am on the tv in her room. Any takers on how to do this? I have the firetv’s connected to home assistant. Thanks in advance to anyone that can help!
/Rob

I don’t know anything about the emby integration, but you can launch a Fire TV app using the media_player.select_source service and providing the app ID as the source parameter; see here for documentation.

Also, the firetv component will be renamed to androidtv in the next release. It should detect that it’s a Fire TV device, not an Android TV device, but you can help it out by adding device_class: firetv to your config.

I figured it out, thanks

Do you mind sharing how?

at what level explanation are you looking?

You need to generate an API key for your emby server.

For each FireTV or FireTV Stick, you need to create a command line sensor that includes the device ID in the curl call to the Emby API.

I use Postman to find this information. The GET call for my setup looks like this:

http://tv.domain.com:8096/emby/Devices

and headers:
X-Emby-Token=xxxxxxx
Content-Type=application/json


The Response should look like this:
{
“Items”: [
{
“Name”: “SMG965U”,
“Id”: “63e06b564b84b016”,
“LastUserName”: “Rob”,
“AppName”: “Emby for Android Mobile”,
“AppVersion”: “3.0.48”,
“LastUserId”: “70ed5f4b409f4dcd83526a04bc25e0a8”,
“DateLastActivity”: “2019-05-19T21:49:35.0000000Z”,
“IconUrl”: “https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/android.png
},
{
“Name”: “Hedrick Living Room”,
“Id”: “4a31382947bbd1a2”,
“LastUserName”: “Family”,
“AppName”: “AndroidTv”,
“AppVersion”: “1.6.94a”,
“LastUserId”: “0588ff12bc3e45fdbaeee9fc15d27a09”,
“DateLastActivity”: “2019-05-19T21:47:06.0000000Z”,
“IconUrl”: “https://mediabrowser.github.io/Emby.AndroidTv/appicon.png
},
{
“Name”: “Playroom”,
“Id”: “66a3382525ce0893”,
“LastUserName”: “Olivia”,
“AppName”: “AndroidTv”,
“AppVersion”: “1.6.94a”,
“LastUserId”: “81839facd92b4c86991c3088275a859b”,
“DateLastActivity”: “2019-05-19T21:26:23.0000000Z”,
“IconUrl”: “https://mediabrowser.github.io/Emby.AndroidTv/appicon.png
},

You want the Id from this information for each device you want to control.

  - platform: command_line
    name: embysessionplayroom
    command: "curl -H \"Content-Type: application/json\" -H \"X-Emby-Token: xxxxxxxxxxxxxxxxxxx\" -X GET \"http://tv.domain.com:8096/emby/Sessions\" | jq -r '.[] | select(.DeviceId==\"66a3382525ce0893\") | .Id'"
    scan_interval: 4

Make sure you escape all quotes inside the command with a backslash as I have

This sensor will report back the unique session id later.

You need to also get the Id for the user you want to login as.

Use the same method as for devices, but your GET is
http://tv.domain.com:8096/emby/Users

Finally, you need a list of Movies and their ID’s that the user you want to control is allow to watch.
Same headers as above
http://tv.chucklehead.lol:8096/emby/Users/USERIDGUID/Items?Recursive=true&IncludeItemTypes=Movie

Create an input_select for the movies. Make sure you remove illegal characters.

  firetv_movies:
    name: firetv_movies
    options:
      - Cinderella
      - Despicable Me
      - Despicable Me 2
      - Despicable Me 3
      - Finding Nemo
      - Frosty the Snowman
      - Frozen
      - Harry Potter and the Philosophers Stone
      - Lady and the Tramp
      - Madagascar
      - Madagascar 3 Europes Most Wanted
      - Madagascar Escape 2 Africa
      - Monsters, Inc.
      - One Hundred and One Dalmatians
      - Pinocchio
      - Pocahontas
      - Rudolph the Red-Nosed Reindeer
      - Snow White and the Seven Dwarfs
      - The Lion King
      - The Little Mermaid
      - Willy Wonka & the Chocolate Factory
    initial: The Little Mermaid
    icon: mdi:movie

Create an input_datetime

  liv_trigger_time:
    name: "turn on liv show"
    has_date: false
    has_time: true
    initial: '07:00'

In your configuration.yaml make sure you can control the firestick thru the androidtv platform

  - platform: androidtv
    name: Olivias Room
    host: 172.17.17.5
    adbkey: !secret adbkey_olivia

There are several automations that need to be created. Before I did this I connected to all my firesticks via adb and changed the configuration so that they never go to sleep or turn off… This is important.

This is what my final card looks like:
image

Create the rest_command:

  emby_start_show:
    url: http://tv.domain.com:8096/emby/Sessions/{{ session }}/Playing?ItemIds={{ show }}&PlayCommand=PlayNow&api_key={{ token }}
    method: POST
    headers:
      accept: '*/*'
      Content-Type: 'application/json'
    payload: '{"ControllingUserId":"{{ userid }}","SubtitleStreamIndex":0,"AudioStreamIndex":0,"StartIndex":0}'

Create the automation’s:

- id: '155648556587'
  alias: call automations for olivia device at time
  initial_state: true
  trigger:
  - platform: template
    value_template: '{{ states.sensor.time.state == (states.input_datetime.liv_trigger_time.attributes.timestamp
      | int | timestamp_custom("%H:%M", False)) }}'
  action:
  - service: automation.trigger
    entity_id: automation.launch_emby_on_olivia_device
  - service: automation.trigger
    entity_id: automation.play_emby_show_on_olivia_device
  - service: automation.trigger
    entity_id: automation.turn_olivias_tv_on

The TV turn on action is for my harmony IR device to turn on the TV

- id: '15855573698'
  alias: launch emby on olivia device
  trigger: []
  condition:
  - condition: state
    entity_id: automation.call_automations_for_olivia_device_at_time
    state: 'on'
  action:
  - service: script.adb_start_emby_on_device
    data_template:
      device: '{% if is_state(''input_select.firetv_device'',''Olivias Room'') %}
        media_player.olivias_room {% elif is_state(''input_select.firetv_device'',''Playroom'') %}
        media_player.play_room {% elif is_state(''input_select.firetv_device'',''Bathroom'') %}
        media_player.bathroom {% else %} media_player.olivias_room {% endif %}

- id: '15857596587'
  alias: play emby show on olivia device
  trigger: []
  condition:
  - condition: state
    entity_id: automation.call_automations_for_olivia_device_at_time
    state: 'on'
  action:
  - wait_template: "{{ not is_state('sensor.embysessionolivia', '') }}"
  - service: rest_command.emby_start_show
    data_template:
      show: '{% if is_state(''input_select.firetv_movies'',''Cinderella'') %} 24959
        {% elif is_state(''input_select.firetv_movies'',''Despicable Me'') %} 60872
        {% elif is_state(''input_select.firetv_movies'',''Despicable Me 2'') %} 67305
        {% elif is_state(''input_select.firetv_movies'',''Despicable Me 3'') %} 67175
        {% elif is_state(''input_select.firetv_movies'',''Finding Nemo'') %} 60819
        {% elif is_state(''input_select.firetv_movies'',''Frosty the Snowman'') %}
        36271 {% elif is_state(''input_select.firetv_movies'',''Frozen'') %} 24954
        {% elif is_state(''input_select.firetv_movies'',''Harry Potter and the Philosophers
        Stone'') %} 67224 {% elif is_state(''input_select.firetv_movies'',''Lady and
        the Tramp'') %} 24957 {% elif is_state(''input_select.firetv_movies'',''Madagascar'')
        %} 60841 {% elif is_state(''input_select.firetv_movies'',''Madagascar 3 Europes
        Most Wanted'') %} 67174 {% elif is_state(''input_select.firetv_movies'',''Madagascar
        Escape 2 Africa'') %} 67155 {% elif is_state(''input_select.firetv_movies'',''Monsters,
        Inc.'') %} 24958 {% elif is_state(''input_select.firetv_movies'',''One Hundred
        and One Dalmatians'') %} 50077 {% elif is_state(''input_select.firetv_movies'',''Pinocchio'')
        %} 24950 {% elif is_state(''input_select.firetv_movies'',''Pocahontas'') %}
        24953 {% elif is_state(''input_select.firetv_movies'',''Rudolph the Red-Nosed
        Reindeer'') %} 36272 {% elif is_state(''input_select.firetv_movies'',''Snow
        White and the Seven Dwarfs'') %} 24952 {% elif is_state(''input_select.firetv_movies'',''The
        Lion King'') %} 57496 {% elif is_state(''input_select.firetv_movies'',''The
        Little Mermaid'') %} 24956 {% elif is_state(''input_select.firetv_movies'',''Willy
        Wonka & the Chocolate Factory'') %} 92962 {% else %} 60819 {% endif %}

        '
      token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      userid: 81839facd92b4c86991c3088275a859b
      session: '{{ states.sensor.embysessionolivia.state }}'

Tie it all together with a UI-Lovelace card like this:
- title: Automation
icon: ‘mdi:home-automation’
panel: false
path: automation
theme: default
type: vertical-stack
cards:
- type: custom:compact-custom-header
main_config: false
disable: false
header: true
menu: show
background_image: true
notifications: show
voice: hide
options: clock
clock_format: 12
exceptions:
- conditions:
user: dashboard
config:
show_tabs: 12
- type: entities
title: Olivia Automation
show_header_toggle: false
entities:
- entity: automation.call_automations_for_olivia_device_at_time
name: Enable/Disable

          - entity: input_datetime.liv_trigger_time
            name: Time

          - entity: input_select.firetv_device
            name: Device

          - entity: input_select.firetv_movies
            name: Movie
4 Likes

Wow, thank you for the detailed reply. I’ll give it a go!

An update: I wanted to make this a little more dynamic and also wanted to be able to shuffle episode of key tv shows like Paw Patrol. So I created a tag in each series called kids.
image

Then I created a Rest Sensor that polls the emby api for series with the tag for kids and makes the ‘state’ of said sensor a comma delimited string of name and id… IE ‘Doc McStuffins:8554,Some Show:1234’

  - platform: rest
    resource: http://tv.domain.com:8096/emby/Items?Recursive=true&IncludeItemTypes=Series&Tags=kids
    method: GET
    scan_interval: 1800
    headers:
      Content-Type: 'application/json'
      X-Emby-Token: 'xxxxxxxxxxxxxxxxxxxxxxx'
    name: emby_kids_series
    value_template: >
      {% for item in value_json.Items -%}
        {{ item.Name }}:{{item.Id}}{% if not loop.last %},{% endif %}
      {%- endfor %}

At system startup, after the Rest Sensor is populated, my automation calls back to the local Home Assistant API and updates the Menu Choices for TV Show with the name values from the Rest API.

  update_firetv_shows:
    url: "http://localhost:8123/api/services/input_select/set_options"
    method: POST
    headers:
      content-type: "application/json"
      Authorization: "Bearer xxxxxxxxxxxxxxxxxxxxxxxxx"
    payload: >-
      {
        "entity_id": [
          "input_select.firetv_shows"
        ],
        "options": [
      {% set temp =states.sensor.emby_kids_series.state.split(',') %}
      {%- for item in temp %}
          "{{item.split(':')[0]}}"{% if not loop.last %}, {% endif %}
      {%- endfor %}
        ]
      }

If TV Show is selected, The automation will pass The SeriesId, UserId, API Token and SessionId to a home assistant script,

- id: '158575965865'
  alias: play emby show on olivia device2
  trigger: []
  condition:
  - condition: state
    entity_id: automation.call_automations_for_olivia_device_at_time
    state: 'on'
  - condition: state
    entity_id: input_select.firetv_media_select
    state: 'TV Show'
  action:
  - wait_template: "{{ not is_state('sensor.embysessionolivia', '') }}"
  - service: script.get_seasons_for_series
    data_template:
      show: '{% set temp =states.sensor.emby_kids_series.state.split('','') %}
        {%- for item in temp %}
        {% if states.input_select.firetv_shows.state == item.split('':'')[0] %}
        {{item.split('':'')[1]}}
        {% endif %}
        {%- endfor %}'
      token: b7cee43a658b40ff8e40c2a6e3e7dd55
      userid: 81839facd92b4c86991c3088275a859b
      session: '{{ states.sensor.embysessionolivia.state }}'

  get_seasons_for_series:
    sequence:
      - service: shell_command.get_episodes_cmd
        data_template:
          show: '{{ show }}'
          token: '{{ token }}'
          userid: '{{ userid }}'
          session: '{{ session }}'

Which then passes the variables to a shell_command…

get_episodes_cmd: bash /home/rob/scripts/get_episodes.sh {{show}} {{token}} {{userid}} {{session}}

The bash script pulls all the episodes in the series and puts the Id’s into an array… then it randomly selects 10 Id’s and concatenates then into a string like ‘ItemIds=1234&ItemIds=5678’. This is passes this string into the emby api call to launch the playlist.

seasons=$1
token=$2
userid=$3
session=$4
set -a arr
for i in $(echo $seasons | sed "s/,/ /g")
do
    arr+=( $(curl -H "Content-Type: application/json" -H "X-Emby-Token: $token" -X GET "http://tv.chucklehead.lol:8096/emby/Items?&Recursive=true&ParentId=$i&IncludeItemTypes=episode" | jq -r '.[][]? | .Id') )
done
result=''
size=${#arr[@]}
for ((i=1;i<=10;i++)); do
  index="$(($RANDOM % $size))"
  rand="${arr[$index]}"
  result="$result$rand,"
done
result=${result::-1}
curl -X POST "http://tv.chucklehead.lol:8096/emby/Sessions/$session/Playing?ItemIds=$result&PlayCommand=PlayNow&api_key=$token" -H "accept: */*" \
  -H "Content-Type: application/json" -d "{\"ControllingUserId\":\"$userid\",\"SubtitleStreamIndex\":0,\"AudioStreamIndex\":0,\"MediaSourceId\":\"string\",\"StartIndex\":0}"
3 Likes

first of all thank you very much for sharing this and the detailed instructions. I’m using Jellifyn and this works with it as well.
I was able to follow your first set of instructions and got it working.
I then attempted the dynamic sensor and I’m stuck.
The sensor.emby_kids_series doesnt work for me. I populated your resource in Postman and got “object reference not set to an instance of an object”
If I try it like this:
http://192.168.1.100:8096/emby/Users/userid/Items?Recursive=true&IncludeItemTypes=Movie&Tags=kids

it works. I get the filtered information.

The problem is that if I try to use it like that in HA as rest, it doesnt work because of the 255 characters limiation.

Any workaround you maybe able to suggest is welcome

Thank you again

Edit: so the problem is not that it cant run the sensor. The problem is the string back is over 255 char in my case. If I tag a couple of videos, it works.
So this limitation doesnt let the sensor work

1 Like

Anyone know if its possible to make so it automatically starts to cast media to a speaker?
Im using this for music =)

Have you figured out how to cast music to a speaker? I would be interested in a solution too

No, i got logitech media server in docker with chromecast addon. Works perfect with home assistant too =)

Cheers for the quick reply. I will look into it

Np, plugin name is “chromecast bridge”

I’d like to thank you for writing this, it’s really helped me wrap my head around accessing Emby’s API for the first time, and I don’t think I’d have been able to get my NFC tags working without this post.

One area I’m kind of getting stumped on is playing a random episode of a particular show.

I’m not using a drop-down or anything like what you’re using for your setup, but I have NFC tags that each play a certain title. So far I’ve limited myself to each tag playing a specific movie, but when it comes to TV shows, I’d like each tag to start playback of a particular show, but a random episode of said show.

What do you think would be the best way of going about this? I’d only need it to play a single episode and then stop until the tag is scanned again and then play another random episode of the same show.

EDIT:

I ended up figuring this out on my own, and it turned out to be much easier than I thought! All I had to do was find out the range of numbers for the ID’s of the episodes that I wanted and template them so a random episode would be chosen for show:

show: '{{ range(614262,614301)| random }}'