For my office commute, I rely on the train. While trains generally operate on schedule, occasional delays occur. When they’re running late, I’d like to be notified so I can adjust the timing of my walk to the station.

Before I decided to roll out my own, I was using National Rail app’s alerting feature. At some point National Rail removed this option. I tried multiple other train apps, but they were “slow”. When I say slow, I mean the UX, performance on mobile connection.

This is a series of blog posts that chronicle my journey to create a solution that is tailor made to suite my requirements. So lets talk about some of the requirements.

Requirements

  • Lightweight - Solution has to work with poor or slower mobile connections
  • Only information I care about
    • Departure time
    • On time, delayed or cancelled
    • Platform number
  • I only care about train running status only during a narrow time window and direction
    • Morning trains reaching office by 9 am
    • Evening trains to home leaving after 5pm
  • Easy to host on something like Raspberry Pi

Source

UK’s National rail gives anyone access to near real time train running status for free in a nice API via https://raildata.org.uk. For this little project I needed " Live Arrival and Departure Boards". Using this API one can query the trains between any two stations in a 2 hour time window.

Access to the API is controlled by unique client key. One can obtain the client key by simply subscribing to the required data sets. In my case I subscribed to Live Arrival and Departure Boards.

Implementation notes

Train tracker is going to be a Java application on Linux launched using Systemd and exposed to the internet via Cloudflare Argo tunnel.

I chose this stack because this is what I am most comfortable with. Java standard library comes with a HTTP client (since Java 11) and Server (since Java 18), as a result I just need Gson (handling JSON) as the only runtime dependency. Development dependencies are going to be Junit and mockito.

Train tracker will have two modes of operation, refresher and server.

Refresher

As the name suggests, this mode is responsible to refresh the train running status. During each run refersher is going to read a config file, construct a request with the correct parameters, parse the response gracefully, and write out a HTML file from a template.

Server

In this mode, Train tracker is going to use the Java built in HttpServer introduced in Java 18 to server the sole HTML file generated from the Refresher.

Systemd Timer

Systemd comes with a Timer that is as powerful as Cron. This will kick up the refresher every 5 minutes in the morning time window and later during the evening time window. During other times, I don’t really care about the running status. API is rate limited, but I want to be as efficient as possible.

Systemd Unit

Train tracker server is going to be started using a conventional Systemd Unit.

Show me the code

All the code for this project can be found on Github.