Tracking the NYC subway from my apartment

Jake Zuke
Jake Zuke
Jan 14 · 6 min read
The next two scheduled departure times for the northbound G train departing from Greenpoint Av.

If you’ve ever spent time living in NYC, you probably understand why people say they have a love/hate relationship with living here. There are heaps of things to love: a seemingly infinite number of events that cater to any interest, an incredibly vast selection of food and restaurants to choose from, the diversity of the culture and people, being in awe seeing the skyline every morning, and some incredible architecture — to name a few.

But unfortunately there’s also an equal amount of things to hate: tiny apartments, high cost of living, dirty streets, waiting for the subway, slow walkers, waiting for the subway, the amount of people crowded inside of Trader Joe’s, Waiting. For. The. Subway.

The Problem

I live on the G train in Brooklyn. Once the laughing stock of all of NYC because of its truncated size and lack of direct access to Manhattan. Now the laughing stock of all of NYC because its slightly less truncated size and lack of direct access to Manhattan. It supposedly runs every 7 minutes during rush hour, but sometimes it feels like that is more of a recommendation. If it’s a really unlucky morning, I end up hearing the train approach the station from outside causing me to sprint like a madman down the stairs, fumble around with my MTA card at the turnstile, and jolt down the platform. As mentioned before, since the G train is tiny and doesn’t extend all the way to either of the entrances, it usually ends with me longingly reaching for the closing doors as the train inevitably leaves the station without me and everyone on it is pointing at laughing. Actually, they’re more likely shedding a tear since they see themselves in my defeated facial expressions.

This sequence of events—which happens more often than I care to admit— sometimes ends with me sitting and waiting in excess of 10 minutes, usually sulking in sweat after the unwarranted exercise. The only solution I had to combat this situation was checking my phone every few minutes to see if there is a perfect time to leave. Constantly checking my phone waiting for updates is not my ideal start to the morning.

The Epiphany and Goal

One day at a bar nearby I saw a custom-made LED MTA tracker that had the L train times displayed in real-time. Obsessing over how it looked, I asked where I could get one and the bartender pointed me to the — now defunct — company, NYC Train Sign. Not wanting to pay the full price and apparently get scammed out of my money, the only logical solution was that I needed to figure out how to build one myself.

NYC Train Sign

The Solution & Tech

After researching for countless hours and trying to find the best solution, the only way I figured this would become a reality is if I just bought the equipment I needed and started hacking away. I already had a Raspberry Pi 3 laying around, so next was to figure out the actual display. I wanted a similar look and feel as the one I saw at the bar so I decided on a couple of LED matrices that would live inside of a wooden box. Buying all the electronic components from Adafruit and the lumber from Home Depot, the full list of equipment ended up being:

1 x Raspberry Pi 3
2 x Medium 16 x 32 RGB LED Matrix Panel
1 x Pack of Female to Female jumper wires
1 x Pack of Male to Male jumper wires
1 x 5V 4A (4000mA) switching power supply
1 x Female DC Power adapter - 2.1mm jack to screw terminal block
1 x Plank of wood from Home Depot
Most of the stuff & some other stuff

Out of the research, the libraries that I landed on based on what I know and what I thought I could put together in a reasonable timeline ended up being these two fantastic resources:

1. Node.js MTA-GTFS library
2. Raspberry RGB LED Matrix library

The logic on how I strung everything together is probably less than ideal — however it worked just fine for me.

I started by wiring the LED panels to the Raspberry Pi with the RGB LED library. It took me a few tries of wiring and re-wiring to understand how to properly chain them together without getting weird artifacts popping up on the panels.

With the wiring in place I was able to upload a few of my own static images using the demo utils folder in the RGB LED library & started figuring out how I might want the data to be presented.

Early prototypes

Real-Time Data

After I got the static images working, the challenge was to actually display meaningful data on the panels. I had to read up a bit to further familiarize myself with Javascript Promises to understand how data was getting retrieved and stored from the MTA GTFS Node.js library. After signing up for an MTA API key and knowing I only needed one train headed in one direction, the docs allowed me to write up a pretty simple script to pull the things I needed.

The script fetches the next two scheduled departure times for the uptown G departing from Greenpoint Av, which is wrapped in a setInterval() call for ~every 60 seconds

After getting the script to output the schedule of the next trains, I needed to find the best way to connect it to the RGB library on the Raspberry Pi. There is a Node binding that I couldn’t get to work — so I went for a less obvious route. Knowing how the utils worked after playing around with some demos, I opted to add a couple of Child Processes to my original script in order to execute separate shell scripts that match a specific image in an ‘img’ folder to whatever data is being pulled.

Final hacky solution where the Child Processes run ~every 30 seconds to match up with the offset in time from the wait between images and the overall interval.


Running into some quirks with this specific method, I had to figure out some workarounds to make the display useful and seamless without it crashing. The big issue was making sure the images wouldn’t try to overlap and run two child processes at the same time and to ensure there wasn’t a huge delay between the two requests/images being displayed.

I did this by combining the built in wait flag from the RGB library, that makes a static image wait X amount of time before exiting the display, and a setTimeout() call to the second request from the MTA data that pulls in the next corresponding image.

With my display fully functional I had to make the encasement — which ended up being a a piece of wood cut to dimension of the two LED matrices, stained to match the other furniture in the apartment, and then everything gorilla glued together.

Adding to the greenery

With everything all put together we were in business and could finally determine when to leave the apartment to avoid any long wait time without having to check my phone!

Now the only problem left to solve is determining if there is actually any room on the train on my morning commute. I think it’s safe to assume there isn’t.

Jake Zuke

Written by

Jake Zuke

Product Designer & general maker of stuff —

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade