#gps #gpsd #devices #navigation #replace #ais #nmea2000

app rgpsd

A minimal replacement for gpsd in rust

2 releases

0.1.1 Dec 22, 2022
0.1.0 Dec 22, 2022

#345 in Science

Custom license

65KB
1K SLoC

gpsd

This is a rewrite of the C-based gpsd, which is pretty central to navigation. I use it to read packets from my NMEA2000 device as well as read from a backup GPS device; especially important to me is the NMEA 2000 canbus to GPS and AIS messages that opencpn can understand.

As it turns out, the C gpsd NMEA2000 driver doesn't currently parse AIS messages and translate them. It only seems to support GPS messages and some heading information. Looks like there is code there, it just doesn't seem to work. Worse yet, every now and then, it just quits. Restarting gpsd resolves the issue. The code is stricky, so it's just easier to start over in a memory safe language.

How to run it

Run with: cargo run --release -- -D 3 -N -s 4800 /dev/ttyUSB0 (use your device and speed though)

The -D 3 specifies debugging level messages, which include device open and close messages. If you just want info level, you can leave this off.

Current state

Currently it does just enough to make opencpn happy reading from it.

  • The GPS device is opened and messages are forwarded to the channel, even if there are no subscribers. This is a waste of power. It shouldn't even open the GPS device until there is at least one listener, like what gpsd does, unless you specify nowait. As it turns out, though, nowait is the default in most distros. So maybe this isn't so bad.
  • There's no working auto speed detection for serial devices yet, so you must specify a speed on the command line.

Hotlist of things to do next:

  • Baudrate detection.
  • Read NMEA 2000 messages and translate them to nmea 0183. In particular, I'd like to generate AIS messages.
  • Implement hotplug. This should actually be pretty easy once baud rate detection is done.

Low priority stuff:

  • SIRF devices aren't supported, but detection of them is implemented
  • No support for json messages as expected by cgps and othere
  • No support for polling
  • No detection of GPS devices
  • PPS devices aren't supported
  • Several obscure devices aren't supported (Garmin TXT mode for example)

There are a few things we are already doing better than gpsd did:

  • Connecting and then issuing some commands, but not actually getting any output, puts you on a 60 second timer for disconnection. This is more aggressive than gpsd, which seems to have some complex rules for whether to disconnect you or not. This might matter for clients that POLL, but if they aren't polling at least once per minute, they should probably disconnect and reconnect.
  • Received requests don't have to come all at once. To see this error in gpsd, telnet to it, send ?W then hit CTRL-D which pushes that packet out to gpsd, without a newline, resulting in an "invalid command" error. This implementation parses "commands" which mean that partial commands will just wait for their completion.
  • Rather than making so many system calls and delays to change the speed during auto baud rate detection, just close the device and reopen it at the new speed.

Timing info

So I can't even get more than a second of CPU after running for a few hours now. Compared to gpsd, which took about 1 minute of CPU every hour, I'm very happy wih the performance. Timings, on my Dell i5, YMMV.

Dependencies

~11–23MB
~332K SLoC