I came across an article about smart mirrors a while ago and have wanted to build myself one ever since. Smart mirror (usually) works by placing a display behind a two-way mirror and configure it show time-sensitive information, such as the weather or upcoming appointments. There are many different custom builds out there and many of them seem to be based on an open source framework called MagicMirror2. It’s quite simple framework for displaying useful data on a display, but it removes the need of doing everything by yourself. It’s also highly modular, making it extendable to fit to your needs.
One of the key features of a smart mirror for me is to be able to see the railway traffic information in real time. I commute to work by train and have often found myself arriving already late to the train station when all the trains are delayed. If I could glance through the timetable when doing my morning chores, I could easily see if I would need to hurry. Good thing I live in Finland and especially in Helsinki, where a lot of the public data have been published for free. This includes the real time rail traffic information from the Finnish Traffic Authority. You can even get the real time location of the trains, but I only needed the estimated time of arrival of all the trains stopping at my station.
MagicMirror has numerous modules for showing traffic information, but none of them worked in Finland. Therefore, I needed to build my own module, which would load the traffic data from the APIs provided by the Finnish Traffic Authority. The modules are loaded from modules folder and they should register themselves by calling the Module.register function as follows:
When the module is placed on the screen, the user can pass parameters to it using the config object. The defaults object in the module registration, defines the default values for the parameters, if there are none in the user’s config.js file. My module has only three required parameters:
- station: Name of the station of which the timetable is shown
- minutesBeforeDeparture: How far into the future the timetable is shown
- maximumEntries: Number of results to be shown
For the real time rail traffic info, I turned to the Digi Traffic API from where you can get a list of all the stations, information about the trains and causes for delays:
- List of stations: https://rata.digitraffic.fi/api/v1/doc/index.html#Liikennepaikkatiedot (In Finnish)
- Departing trains on single station: https://rata.digitraffic.fi/api/v1/doc/index.html#LiikennepaikansaapuvatjalahtevatjunatAikavali (In Finnish)
- Causes of delays: https://rata.digitraffic.fi/api/v1/doc/index.html#Syykoodit (In Finnish)
Loading data is done with a helper script that MagicMirror loads for modules. It just connects to the Digi Traffic API and communicates with the module using an integrated socket system.
The API returns all the trains that stop at the given station and their timetable. Since we’re only interested in one particular station, we must iterate through the timetable and find out when each train arrives at the correct station. The last stop is obviously the last entry in the timetable array and is needed for showing the destination for the train.
The API results are not ordered by time of arrival, so we must first iterate through all the results and then later on sort them by time (not visible in the gist above).
Above is a screenshot of the module running on Raspberry Pi 3. Looks great, but still has a few minor issues:
- Only the short code is shown for the destination station
- Causes of delays are not shown
- Looks dull
The actual names of the station must be loaded using another API, since the timetable API only returns the short codes for the stations. Since the stations hardly change, they’re only loaded on startup and stored in a cache array.
Same goes to the causes of the delays. If they cause is known, it should be shown in the mirror. The causes are also loaded once and stored in a simple index from where they can be queried by their codes.
Only the last entry of the timetable array seems to have the information about the cause.
MagicMirror calls getDom method of the module, whenever it needs to update the information on the screen. The method creates a table element that holds the traffic data that were loaded previously.
Here’s how the final version would look in my hallway mirror. This is still just a concept photo, since I haven’t built the actual mirror yet.