Close

How to convince gpsd to talk to your GPS

A project log for SDR in a box

A simple box that will open airwaves for you

piranha32piranha32 08/18/2014 at 06:090 Comments

gpsd is a wonderful tool. It allows many programs to talk to one GPS device, without problems with resource allocation conflicts. The library linked to user apps takes care of parsing all the information and outputs easy to digest numbers.

As awesome as the software is, it has several disadvantages. The most annoying of them is how the program handles detection of  speed on serial port. The authors insist on not allowing to inform the daemon about bit rate and auto-detection not always works as it is supposed to work.

I had a misfortune of dealing with one of such cases. The GPS was sending data at 115.2kbps and gpsd was insisting on talking to it at 4800 or 9600 bits per second. The workaround for this problem was simple: set the port speed to 115200bps and add it to the running daemon:

stty speed 115200  </dev/ttyUSB0
gpsdctl add /dev/ttyUSB0

While this method can be used in interactive work, in embedded system which has to work unattended, adding device manually is completely unacceptable. In this case all the work must be done by the startup scripts.

What are the startup scripts? These are small programs that are executed in a specific order when the OS boots and perform all operations necessary to prepare the computer for work (configure network, start sshd for remote logins, start graphical environment, etc). In the past these used to be small shell scripts, but as systemd replaces the old BSD or SysV style scripts, the startup scripts are replaced by configuration modules, which do not look at all like a piece of executable code. 

The advantage of the new method is flexibility and configurability. No more manual coding of order of execution, independent services can be started in parallel speeding up the start of the system, starting services when they are needed, however all those goodies come at the cost of increased complexity of configuration.

The systemd unit that would add the gps to gpsd has to meet the following criteria:

Using dhcpd script as a template I came up with the following configuration:

[Unit]
Description=add gps device
After=gpsd.service

[Service]
ExecStartPre=/usr/bin/stty speed 115200 -F /dev/ttyUSB0
ExecStart=/usr/sbin/gpsdctl add /dev/ttyUSB0

[Install]
WantedBy=multi-user.target

The most important parts are the After line in Unit section and the entire Service section. The After statement tell the dependency resolver to start our new unit after service gpsd is ready. No more messing with priority levels, systemd takes care of executing configurations in proper order.

The Service section is a bit tricky. The most important line (and for many units the only line in this section) is ExecStart statement: This command starts the main service. However, there is a catch: the action listed here must be a single command, specified with absolute path. No chaining commands with semicolon is allowed ("sh -c" trick might work, though). This means that the two commands have to be run by a separate script (ugly), or I could execute command started before the main statement, using ExecStartPre. There can be many ExecStartPre statements, all of them have to complete successfully. if any of the commands fails, the whole unit fails immediately. There unit can also start post-execution statements started by ExecStartPost (to clean up after the main program), but I don't use this feature here.

The configuration unit has been saved in  /etc/systemd/system/add-gps.service file and added to the list of units executed at startup with

 systemctl add gps-add

More information about configuration statements can be found in systemd service reference manual.

Discussions