DIY goal light using a Raspberry Pi

Bradenhayes
6 min readApr 13, 2022

--

I love to watch hockey and I always want to know when my favourite team scores. However, I did not want to spend 200$ on the Budweiser red goal light which is always sold out anyway:https://www.shopbeergear.ca/products/budweiser-red-light.

So, I decided to make my own. I realized there must be an API out there for all things NHL that I could use, so I browsed the internet and found an awesome one: https://gitlab.com/dword4/nhlapi.

All I needed to find was a light bulb that I could use in rooms around my condo so that I could connect to it from Python. This is the one I used and it works great: https://amzn.to/3M45xks (Kasa Smart Light Bulbs KL125P2)

Here is a demo of what the light looks like when the game starts:

Here is a demo of what the light looks like when a goal is scored:

Now let’s get into the code.

We will be using the Python Kasa library which you can read about here: https://github.com/python-kasa/python-kasa. This is how we will be connecting to the light bulb and controlling it.

First, open a terminal and run the following command:

$ pip install python-kasa

There are a few more libraries that we will use:

import asyncio
from kasa import SmartBulb
import time
import requests
import json
import schedule
from datetime import datetime
from datetime import timedelta
import pytz
from multiprocessing import Process

So we have to install these. Next in the terminal enter:

$ pip install time
$ pip install requests
$ pip install schedule
$ pip install datetime
$ pip install pytz
$ pip install asyncio
$ pip install multiprocessing

Now that you have installed all of the libraries it is time to start coding!

You need to find the IP addresses of your bulb(s), so once you have connected them to the Kasa app using the instructions that came with the light bulbs you can find their IP addresses by running the following Python script:

You will get an output similar to the following:

Where 192.168.2.135 is the IP address of one bulb and 192.168.2.134 is the IP address of the other bulb.

I have one bulb in my room when I watch the games on my laptop while I am doing work and one in my living room when I watch games on my TV. So I named them to correspond to this.

The top of your code will look like the following:

Next, we will make the main method that will be run when we run the Python script. This main method will start a scheduler that will run a method which will check every morning at 6 am if your favourite team is playing on that day!

As you can see we set the game_link variable to the return value of the function gamesToday(). In the following function, we will get the link to the game so that we can get the live stream of the game. We then call the method live_game() and pass it the link of the game as a parameter so that we can poll to see: 1. If the game has started and 2. If our favourite team has scored!

Next, we will add this function gamesToday() to our Python script.

In this function, we will get the current date and use it as the parameters in the URL to find if our team plays. As you can see one of the parameters in the URL is “teamId=3”. This is the team ID for the New York Rangers. To find all of the team IDs just use this URL in any browser: https://statsapi.web.nhl.com/api/v1/teams

As you can see this function will parse through the received JSON data to check if there is a game today (the length of the dates array is greater than 0 meaning yes, there is a game). If there is, it will return the link to the API’s live game feed, otherwise, it will return 0 which lets the Python script know there is no game today.

Now, if there is a game we will call the method live_game() with the URL of the game as explained earlier. This function looks like the following.

How this function works is it grabs the time that the game will start, which is returned in the following format: T00:00:00.000Z

Now you will have to change this time to whatever your time zone is. I am located in the US/Eastern timezone so I use this in the following line of code:

d = datetime.fromisoformat(game_time[:-1]).astimezone(pytz.timezone("US/Eastern"))

Then I also have to subtract by 4 as my time zone is 4 hours behind the time the API returns. Next, we will enter an infinite loop where we will check if it is game time yet. If it is, the Python script will create and start 2 separate processes. One is for blinking the light in the living room and one is for blinking the light in the bedroom. The reason that this is multiprocessesed is that otherwise, the lights would run one after the other instead of at the same time.

The first process that is created and started will call the living_room_start_callback() method and the second process will call the bed_room_start_callback() method. Each of these functions will start an asyncio event loop so that we can call our asyncio functions which will light up our bulbs.

These asyncio functions look like the following:

These functions will each use a “try and except” block. This prevents the script from failing and crashing if any of the light bulbs are off. Another reason that multiprocessing is needed is that if the living room bulb (the function that is called first) is off, the Python script would attempt to connect to it for around 10 seconds before moving on to the bedroom light. However, since we have muiltiprocessed these, then there is no waiting. As you can see in the above code, the bulbs will flash blue 5 times before returning to their default state.

Next, we will continue to check the API to see: 1. If the game has finished yet and 2. If our favourite team has scored! If they have scored then we create 2 processes to match what we did for the game starting code. Here, multiprocessing is even more essential as it prevents the lights from activating late and after the goal has been scored. These processes will call the following functions:

As you can see in the code above, asyncio event loops are created again and they will call the code which will actually flicker our bulbs red! This is seen in the following code:

As you can see, these functions are very similar to the game started light flickering with the difference on the following line:

await bulb_living_room.set_hsv(0,100,50)

The three parameters (0,100,50) stand for the Hue, Saturation and Lightness. 0 Hue is for the colour red and 180 Hue is for the colour cyan.

And there you have it, a goal light! If anyone wants, I can add in audio so that in addition to the light flickering red your speaker will also play a goal horn when your team scores!

Here is the GitHub repository for the project: https://github.com/bradenhayes/Raspberry-Pi-Goal-Light/blob/main/GoalLight

I appreciate you taking the time to read about this project and I hope you have fun implementing it yourself! I also really appreciate any feedback on the project, the code or the article itself!

--

--