As I wrote in Part 1 of Building Your Own Sports Ticker, one of the more difficult parts of this project was getting the sports data to show it on the ticker. This headache was solved when I encountered the custom Home Assistant component, ha-teamtracker. You can install it using HACS or the Home Assistant Community Store.

Setup HA-TeamTracker

Go ahead and install the custom component and configure it as you need. See the documentation on the project's GitHub page here.

Find the Data in Home Assistant.

HA-TeamTracker's entities set up a bunch of valuable Attributes. They work differently depending on what state the sports team is in (before a game, in a game, and after a game).

I will try to revise this with a better in-game example in the future, but currently, I have a sensor setup for "All NBA" games - which will essentially show the details of whatever the latest NBA game is or was. Here are all of the available attributes for the Post Game:

attribution: Data provided by ESPN
sport: basketball
league: NBA
league_logo: https://a.espncdn.com/i/teamlogos/leagues/500/nba.png
team_abbr: MIN
opponent_abbr: SAC
event_name: MIN @ SAC
date: 2023-12-24T03:00Z
kickoff_in: 19 hours ago
venue: Golden 1 Center
location: Sacramento, CA
tv_network: null
odds: null
overunder: null
team_name: Timberwolves
team_id: "16"
team_record: 22-6
team_rank: null
team_homeaway: away
team_logo: https://a.espncdn.com/i/teamlogos/nba/500/scoreboard/min.png
team_colors:
  - "#266092"
  - "#79bc43"
team_score: "110"
team_win_probability: null
team_winner: true
team_timeouts: null
opponent_name: Kings
opponent_id: "23"
opponent_record: 17-11
opponent_rank: null
opponent_homeaway: home
opponent_logo: https://a.espncdn.com/i/teamlogos/nba/500/scoreboard/sac.png
opponent_colors:
  - "#5a2d81"
  - "#6a7a82"
opponent_score: "98"
opponent_win_probability: null
opponent_winner: false
opponent_timeouts: null
quarter: 4
clock: Final
possession: null
last_play: null
down_distance_text: null
outs: null
balls: null
strikes: null
on_first: null
on_second: null
on_third: null
team_shots_on_target: null
team_total_shots: null
opponent_shots_on_target: null
opponent_total_shots: null
team_sets_won: null
opponent_sets_won: null
last_update: "2023-12-24 16:35:19-06:00"
api_message: null
icon: mdi:basketball
friendly_name: All NBA Games

As you can see- there are a ton of valuable bits that we can use for Home Assistant and our Sports Ticker. I use the kickoff_in attribute to announce text-to-speech reminders of when games will start and the tv_network attribute to tell us what channel the game will be on - Using the Harmony component, we can even turn on our TV and set it to the proper channel for the game! I also use the team_colors to turn on lights to the color of our team.

HA-TeamTracker also has a lovely Lovelace Dashboard card you can install and use, too:

Use the Sports data for the ticker

In the previous article, we setup a input_text helper entity to drive what we see on the Sports Ticker. Whatever we put into this entity is what we'll see. We'll use a lot of templates in Home Assistant to accomplish this. I'll share how I show sports scores on both my mini and my larger Sports Tickers using automation:

I use the following for my larger Sports Ticker in my home theater- I have more space to show the current time of day and the game clock as it comes from HA-TeamTracker. This automation follows two different teams I set up Creighton Basketball and Duke Basketball. If the sensor for either team changes state, this automation triggers. I only want the Sports Ticker to update when the TeamTracker sensor is IN - meaning a game is in progress. You can see in the actions that we are setting the input_text value to a string of text generated using the attributes from the HA-TeamTracker sensor (whichever sensor triggered this automation).

alias: Sports Ticker - In-Game Status
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.creightmmb
      - sensor.dukembb
condition:
  - condition: or
      conditions:
        - condition: state
          entity_id: sensor.creightmmb
          state: IN
        - condition: state
          entity_id: sensor.dukembb
          state: IN
action:
  - service: input_text.set_value
    data:
      value: |-
        {% set time = now().strftime('%I:%M') %} {{ time }} |
         {{state_attr(trigger.entity_id, 'team_abbr')  }}:{{
          state_attr(trigger.entity_id, 'team_score')  }}  {{
          state_attr(trigger.entity_id, 'opponent_score')  }}:{{
          state_attr(trigger.entity_id, 'opponent_abbr')  }} | {{
          state_attr(trigger.entity_id, 'clock')  }}
    target:
      entity_id: input_text.sportsticker2text
  - service: homeassistant.turn_on
    data: {}
    target:
      entity_id: switch.sports_ticker2_power_switch
mode: single

And here is the result!

This was during the Duke-Baylor game recently (shoutout to SentinelOne!)

The sensor data updates every 10 seconds when a game is in progress. That also means the ticker updates every 10 seconds. So it's not quite real-time, but it's close enough to be helpful. Imagine if you changed the channel away from your game- you can still keep tabs on the score. Or if you're in a commercial break, you can see the score if you didn't catch it before it went to break.

For the smaller Sports ticker, I have less room, so I only show the score:

alias: Sports Ticker - In-Game progress
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.creightmmb
      - sensor.dukembb
condition:
  - condition: or
    conditions:
      - condition: state
        entity_id: sensor.creightmmb
        state: IN
      - condition: state
        entity_id: sensor.dukembb
        state: IN
action:
  - service: input_text.set_value
    data:
      value: >-
        {{ state_attr(trigger.entity_id, 'team_abbr')  }}:{{
        state_attr(trigger.entity_id, 'team_score')  }}-{{
        state_attr(trigger.entity_id, 'opponent_score')  }}
    target:
      entity_id: input_text.sportstickertext
  - service: homeassistant.turn_on
    data: {}
    target:
      entity_id: switch.sports_ticker_power_switch
mode: single

More than just a Sports Ticker

It isn't just for sports! The MAX digit display is super useful for all sorts of things! I try to use it in conjunction with TTS announcements as a visual messaging panel as well. I'll scroll across the same text used for the TTS announcement for a few minutes and then turn it off.

How about monitoring your grill?

I have a Meater thermometer, and it's setup in Home Assistant. (in fact, the only reason why I ended up getting a Meater is because of the Home Assistant component). When the Meater component lights up, I light up the sports ticker to keep track of the temperatures without looking at my phone. I cannot tell you how useful this one is. It's easy to glance down at the internal and ambient temps while I'm watching TV.

First, setup the Meater component in Home Assistant, then set up an automation to show the temps on the Sports Ticker:

alias: Meater - Turn on ticker
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.meater_probe_internal
  - platform: state
    entity_id:
      - sensor.meater_probe_ambient
condition:
  - condition: not
    conditions:
      - condition: state
        entity_id: sensor.meater_probe_cooking
        state: unavailable
action:
  - service: input_text.set_value
    data:
      value: >-
        {{ states.sensor.meater_probe_internal.state  }} {{
        states.sensor.meater_probe_ambient.state  }}
    target:
      entity_id: input_text.sportstickertext
  - service: homeassistant.turn_on
    data: {}
    target:
      entity_id: switch.sports_ticker_power_switch
mode: single

This automation is really straightforward. As soon as sensor.meater_probe_internal or sensor.meater_probe_ambient to anything other than unavaliable, the helper text entity is set with both values of the Internal probe first and the value of the ambient probe second. It just shows me the two numbers with a space in between like this:

To recap, see Part 1 about building a Sports Ticker here.