EFA Departure Monitor on the command line

I just hacked together a small shell script that gets departures from my local public transportation service. It will list upcoming departures at a stop. You can find the script here.

Getting Started

You can either use the stop name:

$ ./efa-dm.sh "Dortmund Hbf"

Or you can use the stop ID:

$ ./efa-dm.sh 20000131

By default, it will simply print upcoming departures as a tab-separated list.

$ ./efa-dm.sh -n 3 "Essen Rüttenscheider Stern"
1       2018    3       5       16      20      2018    3       5       16      21      101     Essen Helenenstr.
2       2018    3       5       16      21      2018    3       5       16      22      108     Essen Altenessen Bf Schleife
2       2018    3       5       16      22                                              U11     Essen Messe W.-Süd/Gruga
Column Meaning
1 minutes left until departure
2 scheduled departure (year)
3 scheduled departure (month)
4 scheduled departure (day)
5 scheduled departure (hour)
6 scheduled departure (minute)
6 predicted actual departure (year)
8 predicted actual departure (month)
9 predicted actual departure (day)
10 predicted actual departure (hour)
11 predicted actual departure (minute)
12 line name
13 direction

You can also use the -p flag to get the pretty-printed version:

$ ./efa-dm.sh -p -n 3 "Essen Rüttenscheider Stern"
16:20(+1) 101 Essen Helenenstr. in 1 min
16:21 108 Essen Altenessen Bf Schleife in 1 min
16:22 U11 Essen Messe W.-Süd/Gruga in 2 min


Here’s a list of all command line options:

$ ./efa-dm.sh -h
Usage: ./efa-dm.sh [-p] [-d] [-a <API_ENDPOINT>] [-n <NUM_DEPARTS>] [-t <TIME_OFFSET>] <STOP_NAME>
  -h                 Show this help
  -p                 Petty-printed output (instead of tab-separated values)
  -d                 Debug mode (output server reply and exit)
  -a <API_ENDPOINT>  Use API endpoint at this URL
  -n <NUM_DEPARTS>   Limit the number of departures (default: 8)
  -t <TIME_OFFSET>   Skip departures in next X minutes (default: 0)

Services that use EFA

Here’s a list of other public transportation services that also use the Elektronische Fahrplanauskunft (EFA) system and thus can also by queried by the script as well:

  • Verkehrsverbund Rhein-Ruhr (VRR), Germany http://efa.vrr.de/standard/XSLT_DM_REQUEST

  • Verkehrs- und Tarifverbund Stuttgart (VVS), Germany http://www2.vvs.de/vvs/XSLT_DM_REQUEST

  • Münchner Verkehrs- und Tarifverbund (MVV), Germany http://efa.mvv-muenchen.de/mobile/XSLT_DM_REQUEST

  • Nahverkehrsgesellschaft Baden-Württemberg (NVBW), Germany http://www.efa-bw.de/nvbw/XSLT_DM_REQUEST

  • Regional Transportation Authority (RTA) Chicago, USA http://tripplanner.rtachicago.com/ccg3/XSLT_DM_REQUEST

Departure Monitor in Polybar

You can easily use this script as a polybar module:

type = custom/script
exec = /path/to/efa-dm.sh -p -t 4 -n 1 "Essen Hbf"
format = <label>
; In case this is a bus stop:
;  format =  <label>
; For a subway station:
;  format =  <label>
interval = 60

Fixing WiFi Multicast Flooding in bridged networks

I’m using MPD and PulseAudio’s RTP multicasting to get a seamless multi-room audio experience.

Unfortunately, if you’re using a network bridge to connect your wired and wireless LAN, using multicast RTP might have unintended consequences: All WiFi clients are flooded with multicast traffic, which can bring down the entire wireless network.

When multicast transmission arrives at the receiver’s LAN, it is flooded to every Ethernet switch port unless flooding reduction such as IGMP snooping is employed (Section 2.7). (RFC 5110, Section 2 “Multicast Routing”, page 4)

If you don’t wanto to set up IGMP snooping, you have two alternatives: You can either

  1. un-bridge Ethernet and WiFi interfaces and switch to a routed approach, or
  2. filter out multicast packets on their way from wired interface to wireless.

Since (1) has other implications that I’d rather avoid (e.g. blocking broadcast traffic, too, so that service autodiscovery won’t work anymore), so I chose the second approach.

This can easily be archieved using ebtables, which allow link layer filtering on Linux bridge interfaces.

My router is running OpenWRT, which does not with ebtables by default, so it needs to be installed first:

# opkg update
# opkg install ebtables

This is how my bridge setup looks like:

# brctl show
bridge name     bridge id               STP enabled     interfaces
br-lan          7fff.12345678abcd       no              eth0.1
br-wan          7fff.12345678abcd       no              eth0.2

eth0.1, wlan0 and wlan1 are bridged. It’s a dual band router that has wifi interfaces for both the 2.4 GHz (wlan0) and the 5 GHz band (wlan1).

Now the filter rules need to be added. One rule for each wifi interface is necessary:

# ebtables -A FORWARD -o wlan0 -d Multicast -j DROP
# ebtables -A FORWARD -o wlan1 -d Multicast -j DROP

These rules tell ebtables to drop all Multicast packets if their output device in either wlan0 or wlan1.

The effect is immediately noticeable. Before setting up multicast filtering the wifi interfaces were quite busy:

WiFi traffic with multicast filtering

Afterwards, there’s a lot less going on:

WiFi traffic without multicast filtering

To make the filtering permanent, simply add the ebtables commands to /etc/firewall.user.

Upgrading iLO 4 on a HPE ProLiant MicroServer from Linux

I recently got my hands on a ProLiant MicroServer Gen8 by Hewlett Packard Enterprise (HPE). As I always do when setting up a server I checked if the device needs a firmware upgrade.

And indeed it did: It’s version of Integrated Lights-Out (iLO) 4, its built-in server provisioning and management software, is affected by CVE-2017-12542, which is a solid 10.0 on the CVSS 2.0 score chart.

So I decided to update it. Fortunately, the iLO web interface has a page where firmware upgrades can be uploaded. Since it’s in an isolated network, using the web interface should not pose a security problem.

On the other hand, locating the proper firmware file to upload was not as easy as it should be. It’s Hewlett-Packard, after all.

In case someone else is looking for the iLO 4 *.bin file, here’s what I did:

  1. Visit the iLO 4 support page, but do not select OS-Independent (it’s not in there). Select “Red Hat Enterprise Linux 7” instead (direct link)
  2. Open the “Firmware - LOM (Lights-Out Management)” section and download hp-firmware-ilo4-2.55-1.1.i386.rpm.
  3. To extract the actual firmware file from the RPM, use this command:
$ rpm2cpio hp-firmware-ilo4-2.55-1.1.i386.rpm | bsdtar -x -s'|.*/||' -f - ./usr/lib/i386-linux-gnu/hp-firmware-ilo4-2.55-1.1/ilo4_255.bin

The resulting file (ìlo4_255.bin) can then be uploaded to the web interface:

iLO 4 Upgrade Process

After the upgrade process finishes, you’ll be redirected to the brand new login screen:

iLO 4 after upgrade

Generating syntax diagrams using the LaTeX rail package

If you ever had the need to add syntax specifications to your document, you basically have two options: Either write down the syntax in the Backus-Naur form (BNF) (or one of its derivatives) or opt for a more graphical approach by adding “railroad diagrams”. In my opinon, the latter are easier to grasp for less experienced readers and also look quite nice.

In LaTeX, you can use the rail package to generate those diagrams from EBNF rules:

decl : 'def' identifier '=' ( expression + ';' )
     | 'type' identifier '=' type

This will result in something like this:

Railroad diagram

To archieve this, the package first generates a *.rai file. We then have to convert the rai file to a *.rao by invoking the accompanying C program named rail.

However, the rail package is fairly old. It has been written by Luc Rooijakkers in 1991 (!) and was updated by Klaus Barthelmann until 1998. Thus, the code is – at least – 19 years old and that really shows: Trying to compile it on modern systems yields a bunch of compilation errors.

Most of the issues stem from missing return types in function declarations and also missing forward declarations. I stepped up and fixed these issues, so that it works with a up-to-date compiler (I tested with gcc (GCC) 6.3.1 on Arch Linux. You can find the result on Github.

I also threw in some Makefile improvements into the mix: You can now use DESTDIR and PREFIX (defaults to /usr/local) when running make install.


Installation should be fairly straighforward. Here’s an example which will install rail into /usr:

$ curl -L https://github.com/Holzhaus/latex-rail/archive/v1.2.1.tar.gz | tar xzvf -

$ cd latex-rail-1.2.1

$ make
bison -y  -dv gram.y
gram.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
cmp -s gram.c y.tab.c || cp y.tab.c gram.c
cmp -s gram.h y.tab.h || cp y.tab.h gram.h
gcc -DYYDEBUG -O   -c -o rail.o rail.c
gcc -DYYDEBUG -O   -c -o gram.o gram.c
flex  -t lex.l > lex.c
gcc -DYYDEBUG -O   -c -o lex.o lex.c
gcc -DYYDEBUG -O rail.o gram.o lex.o -o rail

$ sudo make PREFIX=/usr install
$ sudo mktexlsr

Please note that installing stuff using sudo make install will circumvent your package manager and is usually not a good idea. If you’re using Arch Linux you should use the AUR package instead:

$ pacaur -S latex-rail

Manual compilation and Latexmk support

To generate a document manually, you need to run multiple commands:

  1. Run latex mydoc, which will create mydoc.rai
  2. Run rail mydoc to generate mydoc.rao from mydoc.rai
  3. Run latex mydoc for the final document

If you don’t want to bother with running LaTeX multiple times, you can use latexmk, a perl script to automate the document generation.

To make it work with the rail package, you should create a .latexmkrc in your document folder with this content:

push @file_not_found, '^Package .* Info: No file (.+) on input line \d+\.';
add_cus_dep('rai', 'rao', 0, 'rail');
sub rail {
   my ($base_name, $path, $ext) = fileparse( $_[0], qr/\.[^.\/]*/ );
   pushd $path;
   my $return = system "rail $base_name";
   return $return;

The first line will add the appropriate RegEx to Latexmk’s missing file detection, the second line will instruct latexmk to run the rail subroutine with a *.rai file as input and *.rao file as output.


I you don’t quite like the rail package, you might want to look into one of these alternative packages:

These also an online tool to generate railroad diagrams if you don’t want to do it in LaTeX.

How to create an UEFI-bootable Windows 7 stick from Linux.

In case you rely on Windows-only software or want to play a game that isn’t on Linux yet, you might want to keep Windows 7 on a second partition. Although I didn’t use it for months, I still keep one around just in case.

Unfortunately, it’s not really straightforward to create a UEFI bootable USB installation disk without using Windows. For some strange reason we can’t just dd the ISO image to a USB disk. Instead, we need to use the Windows USB/DVD Download Tool which - incidentally - only runs on Windows.

However, there’s also a way to do this from Linux:

First, you need to create a GPT partition table with a FAT32 partition on your USB pen drive. Then you simple mount the ISO file and copy the files over. After you’ve done that, your need to extract the file 1/Windows/Boot/EFI/bootmgfw.efi from the install.wim file inside /sources folder on the Windows 7 installation ISO and move the extracted file to /EFI/Boot/bootx64.efi on the pen drive.

You don’t have to do this manually: There’s a neat little tool called WinUSB that can do this for you (it even has a GUI if you want it) and my pull request) that adds Windows 7 UEFI support support has just been merged.