NHL API Custom Component - Track your favorite hockey team in Home Assistant!

Looks like the SHL API is well documented. I don’t have the time or appetite to take that on right now but someone could easily do so. They can even re-use some of my code as the endpoints look similar.

1 Like

Just a tip. I’ve been using this for a few years now (thanks Jay) however it has brought me some sadness. In the past I had dealt with the constant reminder that there wasn’t any hockey during the summer with a conditional card that only displayed the Lovelace card if a game was scheduled. It seems that this year the NHL updated the schedule earlier than in the past. I added another condition using the Seasons integration set to astronomical seasons. Summer is from late June to late September. Perfect for hiding the card during the offseason.

2 Likes

It looks like the api may have moved or been removed (hopefully not).

After a restart, my sensors all broke, and looking for the api at statsapi.web.nhl.com returns nothing. Looks like it is not resolving on any DNS either :frowning:

Yup, I hope this isn’t what I think it is…

1 Like

I’ve done a bit of digging, but ultimately do not have enough know-how to be really helpful…

It looks like the API has been moved, and the endpoints appear to be different as well.

I’ve been able to find a weekly schedule for the league: https://api-web.nhle.com/v1/schedule/2023-09-23
a weekly schedule by team using team abbreviations: https://api-web.nhle.com/v1/club-schedule/ari/week/2023-09-30
a list of teams (not sure how I stumbled on this, but it doesn’t really make sense): https://api-web.nhle.com/v1/schedule-calendar/2023-09-23
game information from a gamecenter page: https://api-web.nhle.com/v1/gamecenter/2023010001/landing

edit:
it will redirect to the current week by using /now instead of /[date] as well.

I found all of these just clicking around in my dev tools, so they’re probably already known… We probably also won’t know how goals and scores are formatted until a game is live, but it’s looking like this may need a pretty massive overhaul to keep working…

further edit: I just spotted the issue in the github and it looks like there’s already an effort to re map the endpoints, which is good news!

Just a side note. You can use this which uses ESPN APIs for both standings and live scoring. The live scoring component is through the TeamTracker integration and the rest I created using REST sensors to the ESPN endpoints for NHL, NBA, MLB and NFL.

We have a discord group working on mapping out the new API. See Unable to access API. (#110) · Issues · Drew Hynes / nhlapi · GitLab for more information. Once we’ve figured out all the new endpoints, I will release a new version of the component. Thanks for your patience all!

1 Like

Good news everyone!

Version 0.11.0 is now available on HACS. This version uses the new API and endpoints. I did my best to keep the experience like-for-like but there are some breaking changes. Please see the release notes for details.

Notably, the team_id configuration key has been replaced with team_abbrev which corresponds to the team’s 3 letter abbreviations (TOR, MTL, COL, CBJ, etc.). The full list of abbreviations can be found in the repo but should be intuitive as they are the same ones used by the NHL and major networks during broadcasts.

Upgrade through HACS, change your config and enjoy the season!

4 Likes

Is there any chance you could do a video of the install? I’m having a hard time as a newbie to try and get any of this to work. I was able to get one score tracking app working (Team Tracker) but I’d really like to get the NHL API program to work. When trying to install via HACS, then going to my addons page, I get this error. Even after adding the config yaml…

If you’ve added the config values and you’ve installed via HACS, you just need to restart Home Assistant and then you’re ready to go.

So then I just go back to the devices and services page and it should load?

No. You will see the sensor in your entities. If you left the name key out of your configuration, then the device ID will be sensor.nhl_sensor otherwise, it will be sensor.whatever you named it. You can then display the information in a card.

Thanks! I can see the sensor now. Now I just need to figure out how to create an automation! I only have LED bulbs installed for now, so I need a way for them to flash 2 different colors. For instance I’m a wild fan, so red and green. I’ve seen a few blueprints but they only seem to create notifications for your phone instead of lights.

WHile this is not written for this NHL specific component as I use the TeamTracker one, here is what I use for one specific team scoring (Detroit Lions in NFL).

  1. Store the current state of several lights
  2. Flash lights several times using the team colors (which are available in the TeamTracker sensor)
  3. Restore the lights back to the way they were
alias: Lions Score
sequence:
  - service: scene.create
    data:
      snapshot_entities:
        - switch.switchlinc_relay_dual_band_1f_a8_f1
        - switch.switchlinc_relay_dual_band_1f_ad_f7
        - light.triangle_leds
        - light.pergola_leds
        - light.table_leds
      scene_id: nfl_game_score_lights_capture
  - service: homeassistant.turn_on
    data: {}
    target:
      entity_id:
        - switch.switchlinc_relay_dual_band_1f_a8_f1
        - switch.switchlinc_relay_dual_band_1f_ad_f7
  - delay:
      hours: 0
      minutes: 0
      seconds: 5
      milliseconds: 0
  - repeat:
      count: "5"
      sequence:
        - parallel:
            - service: light.turn_on
              data_template:
                brightness_pct: 100
                transition: 0
                rgbw_color:
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[0][1:3]
                    | int(base=16) }}
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[0][3:5]
                    | int(base=16) }}
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[0][5:7]
                    | int(base=16) }}
                  - 255
              target:
                entity_id:
                  - light.triangle_leds
            - service: light.turn_on
              data_template:
                brightness_pct: 100
                transition: 0
                rgbw_color:
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[0][1:3]
                    | int(base=16) }}
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[0][3:5]
                    | int(base=16) }}
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[0][5:7]
                    | int(base=16) }}
                  - 255
              target:
                entity_id:
                  - light.table_leds
            - service: light.turn_on
              data_template:
                brightness_pct: 100
                transition: 0
                rgbww_color:
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[0][1:3]
                    | int(base=16) }}
                  - >-
                    {{ state_attr('ssensor.detroit_lions','team_colors')[0][3:5]
                    | int(base=16) }}
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[0][5:7]
                    | int(base=16) }}
              target:
                entity_id:
                  - light.pergola_leds
        - delay:
            hours: 0
            minutes: 0
            seconds: 5
            milliseconds: 0
        - parallel:
            - service: light.turn_on
              data_template:
                brightness_pct: 100
                transition: 0
                rgbw_color:
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[1][1:3]
                    | int(base=16) }}
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[1][3:5]
                    | int(base=16) }}
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[1][5:7]
                    | int(base=16) }}
                  - 255
              target:
                entity_id:
                  - light.triangle_leds
            - service: light.turn_on
              data_template:
                brightness_pct: 100
                transition: 0
                rgbw_color:
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[1][1:3]
                    | int(base=16) }}
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[1][3:5]
                    | int(base=16) }}
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[1][5:7]
                    | int(base=16) }}
                  - 255
              target:
                entity_id:
                  - light.table_leds
            - service: light.turn_on
              data_template:
                brightness_pct: 100
                transition: 0
                rgbw_color:
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[1][1:3]
                    | int(base=16) }}
                  - >-
                    {{ state_attr('sensor.detroit_lions','team_colors')[1][3:5]
                    | int(base=16) }}
                  - >-
                    {{ state_attr('ssensor.detroit_lions','team_colors')[1][5:7]
                    | int(base=16) }}
              target:
                entity_id:
                  - light.pergola_leds
            - delay:
                hours: 0
                minutes: 0
                seconds: 5
                milliseconds: 0
  - service: scene.turn_on
    target:
      entity_id: scene.nfl_game_score_lights_capture
    data: {}
mode: single

This script is called with a trigger on the score change > 1 (so I don’t get extra points also, just TDs, FGs and Safety). Now this certainly could be more generic by calling the script with the entity to get the colors and enable for all scoring but that would be crazy for football, hockey, etc. It could be simplified too especially if all the lights are the same type and just send one command to change them.

Hi love it whats the configuration for this?

I am new to HA and the NHL API is a big reason I am trying to learn it. I am really struggeling to get an automation to trigger when my tacted team scores. I can trigger the automation manually and it works fine. The sensor shows the Tracked Team Scored Last attribute change to true, but the automation never triggers. I am thinking there may have been a slight change in HA since the documentation has been published since most guides I have looked at online have the automation.yaml structured differently than I see it in my HA when I create one with the visual editor.

Here is what I have in the configuration.yaml:

# Loads default set of integrations. Do not remove. 
default_config:

# Load frontend themes from the themes folder
frontend:
  themes: !include_dir_merge_named themes

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

sensor:
  - platform: nhl_api
    team_abbrev: BOS
    name: Bruins
    scan_interval: 30

Here is the trigger part of the automations.yaml:

alias: Bruins Goal Announcement
description: Announce Bruins Goal
trigger:
  - platform: state
    entity_id:
      - sensor.bruins
    attribute: goal_tracked_team
    to: "true"
condition: []
action:
  - service: media_player.play_media
    metadata: {}
    data:
      media_content_type: sound
      media_content_id: air_horn_03
    target:
      entity_id: media_player.michael_s_echo

If I try and use the example in the documentation:

 alias: 'Bruins Goal Announcement'
  trigger:
    platform: event
    event_type: nhl_goal
    event_data:
      goal_tracked_team: true
  action:
    service: tts.google_translate_say
    entity_id: media_player.michael_s_echo
    data:
      message: 'The bruins scored!'

I get this error at the top:
Message malformed: extra keys not allowed @ data['0']

Any help on what I am doing wrong would be appreciated.

This spacing looks wrong.

Thank you so much, that was it, I had some spacing issues I couldn’t see the dots clearly on the screen I was using. I really appreciate it.

1 Like

I am having one final issue related to implementing this integration…
When adding the Lovelace card, I get an error for the template sensors:
Entity not available: sensor.template_away_team
Entity not available: sensor.template_home_team
image

Here is the configuration.yaml:

# Loads default set of integrations. Do not remove. 
default_config:

# Load frontend themes from the themes folder
frontend:
  themes: !include_dir_merge_named themes

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

#NHL API Sensor for Bruins... GO BRUINS!
sensor:
  - platform: nhl_api
    team_abbrev: BOS
    name: Bruins
    scan_interval: 15

template:
  - sensor:
    - unique_id: away_team
      name: '{{ states.sensor.bruins.attributes.get("away_name", "") }}'
      state: '{{ states.sensor.bruins.attributes.get("away_score", "") }}'
      picture: '{{ states.sensor.bruins.attributes.get("away_logo", "") }}'
  - sensor:
    - unique_id: home_team
      name: '{{ states.sensor.bruins.attributes.get("home_name", "") }}'
      state: '{{ states.sensor.bruins.attributes.get("home_score", "") }}'
      picture: '{{ states.sensor.bruins.attributes.get("home_logo", "") }}'

And here is the ui-lovelace.yaml :

type: entities
show_header_toggle: false
entities:
  - entity: sensor.bruins
  - entity: sensor.template_away_team
  - entity: sensor.template_home_team

Given my last issue, I did check the spacing really carefully, but I am not seeing anything off…

In the card code, remove the word template from sensor.template_away_team and sensor.template_home_team.