ugps - OpenWrt GPS Daemon
OpenWrt features a tiny daemon that can use data from NMEA-compliant devices that are supported by the Linux kernel to expose device location data via ubus. ugps can also interpret NMEA time fix sentence data to adjust the system clock to match the current time as received by GPS (and other navigation/positioning systems, such as Galileo or GLONASS, if the receiver supports those) satellites.
While ugps is not as sophisticated as gpsd, it is very lightweight and has very few dependencies.
ugps uses a serial communication protocol to talk to your system's GPS module. If the GPS receiver is connected via a proper serial port, Linux will expose that port via /dev/ttyS0 or a similarly named device node. For USB-based GPS modules, you will have to take care of the proper kernel module to be installed and loaded, and use the resulting device node from that setup.
For the U-Blox AG u-blox 8 USB-based GPS dongle (USB ID 1546:01a8) that was used to write this guide, the appropriate kernel module package is called kmod-usb-acm, and the kernel module's name is cdc_acm. Many other recent modules will require the same driver.
Installation
To install the ugps daemon, it is sufficient to install the ugps package, and any drivers your GPS receiver requires:
# apk add ugps kmod-usb-acm # modprobe cdc_acm
Configuration
ugps configuration is maintained via UCI in /etc/config/gps. The default settings already align with what most users of USB-based GPS hardware will need:
# uci show gps gps.@gps[0]=gps gps.@gps[0].tty='ttyACM0' gps.@gps[0].adjust_time='1' gps.@gps[0].disabled='1'
This default configuration disables the ugps service, for it not to try to start up with an unsuitable configuration. For instance, in case you have a serial GPS receiver on /dev/ttyS2, you would need to set this straight in the configuration before starting the ugps service by running the following commands:
# uci set gps.@gps[0].tty='ttyS2' # uci commit
If you do not want ugps to use NMEA time fix sentences to set and correct a system time that disagrees with the satellites' notion of what time it is, you would want to disable the system clock setting feature by running:
# uci set gps.@gps[0].adjust_time=0 # uci commit
Finally, to enable and start the ugps service which you just set up according to your needs, run these commands:
# uci set gps.@gps[0].disabled=0 # uci commit # service ugps restart uci: Entry not found
The error message produced by restarting the service is harmless, and is issued because an optional baudrate setting in /etc/config/gps is not explicitly set.
To verify that GPS data is flowing in and available to consumers via ubus, the following call should yield some data resembling the provided example output:
# ubus call gps info
{
"age": 0,
"latitude": "46.410000",
"longitude": "14.980000",
"elevation": "242.1",
"course": "",
"speed": "0.521",
"satellites": "12",
"HDOP": "0.89"
}
System Time Synchronization
If a ugps service instance is configured with adjust_time set to 1 (the default), the daemon process will have the -a command line flag show up in the process table, like in this example:
# pgrep -lfa ugps 7285 /usr/sbin/ugps -a /dev/ttyACM0
This flag enables a routine in ugps that will use settimeofday(2) to update the system clock with the GPS-received time if and only if the difference between both values exceeds 3s. Therefore, a ugps-based GPS setup is not suited for precise time-keeping; you would have to deploy gpsd proper (preferably with a tuned ntpd installation/configuration to match) for that use case.