Tuesday, May 30, 2017

Introducing gps-share

So yesterday, I rolled out the first release of gps-share.

gps-share is a utility to share your GPS device on local network. It has two goals:

  • Share your GPS device on the local network so that all machines in your home or office can make use of it.
  • Enable support for standalone (i-e not part of a cellular modem) GPS devices in Geoclue. Since Geoclue has been able to make use of network NMEA sources since 2015, gps-share works out of the box with Geoclue.

The latter means that it is a replacement for GPSD and Gypsy. While "why not GPSD?" has already been documented, Gypsy has been unmaintained for many years now. I did not feel like reviving a dead project and I really wanted to code in Rust language so I decided to create gps-share.

Dependencies


While cargo manages the Rust crates gps-share depend on, you'll also
need the following on your host:

  • libdbus
  • libudev
  • libcap
  • xz-libs

Supported devices


gps-share currently only supports GPS devices that present themselves as serial port (RS232). Many USB are expected to work out of the box but bluetooth devices need manual intervention to be mounted as serial port devices through rfcomm command. The following command worked on my Fedora 25 machine for a TomTom Wireless GPS MkII.


sudo rfcomm connect 0 00:0D:B5:70:54:75

gps-share can autodetect the device to use if it's already mounted as a serial port but it assumes a baudrate of 38400. You can manually set the device node to use by passing the device node path as argument and set the baudrate using the '-b' commandline option. Pass '--help' for a full list of supported options.

6 comments:

Unknown said...

I recently found my TomTom MkII battery was dead (won't hold charge). A good choice. Working on this, I made a systemd unit for connecting the tomtom

Unit]
Description=Serial to TomTom GPS
After=bluetooth.service
Requires=bluetooth.service

[Service]
ExecStart=/usr/bin/rfcomm watch 00:0D:B5:70:61:54 1
Restart=on-failure
RestartSec=5s
RemainAfterExit=yes

[Install]
WantedBy=gps-share.service

zeenix said...

"I recently found my TomTom MkII battery was dead (won't hold charge)."

Same here actually and took me a while to figure out why the device won't send me any data on the port.

Thanks for the systemd unit file. I'll likely advertise that on gps-share homepage but I'm also looking into making bluetooth devices work out of the box. Unfortunately it will require gps-share to take over the management of all serialport devices but I hear that they are not so common and I guess not many folks would have booth GPS and bluetooth serial port devices at the same time.

BTW, would it not be possible for your unit file to watch for serialport class instead of a specific device?

Unknown said...

Well, in my use, I'm trying to hook up gpsd, xastir, and a ham radio TNC (also a serial connection).

I believe a bluetooth device requires pairing to the system, so you cannot make bluetooth work "out-of-the-box". I realize I made a mistake in the above, missing a step: Instead of gps-share.service in the "wantedBy", put "multi-user.target". This means that there will be a bluetooth connection listener waiting for the gps-mouse whenever the system is booted.

Next, you need a udev rule. From my reading, the bluetooth serial connection comes up with the MAC of the bluetooth device - therefore, we can target it specifically:
SUBSYSTEM=="tty", ATTRS{address}=="00:0D:B5:70:61:54", SYMLINK+="gps%n", TAG+="systemd", ENV{SYSTEMD_WANTS}="gpsdctl@%k.service"

As for gpsdctl@ttyUSBn.service, if you're unfamiliar, it uses the device in %k to add the serial port to gpsd's list. You would do something similar, I think. Is there a gps-share.socket listening for device names?

zeenix said...

> I believe a bluetooth device requires pairing to the system, so you cannot make bluetooth work "out-of-the-box".

Which can be done by the system (GNOME e.g), can't it? If not, gps-share can handle it. In any case, I don't think that's a blocker for out-of-the-box experience.

> As for gpsdctl@ttyUSBn.service, if you're unfamiliar,
> it uses the device in %k to add the serial port to gpsd's list.

Thanks but that's the thing, it assumes all tty USB devices are GPS and hence let GPSD complete takes them over (right?). I would really not want to do that.

> You would do something similar, I think. Is there a gps-share.socket listening for device names?

No, not at the moment at least.

Unknown said...

>Thanks but that's the thing, it assumes all tty USB devices are GPS and hence let GPSD complete takes them over (right?).

No. GPSd ordinarily probes the serial ports, then releases them. With the gpsdctl@xyz.service, it passes "xyz" to gpsdctl on bluetooth connect, which causes only that one serial port to be connected, and that only when the bluetooth puck is turned on and in range as connected by the bluetooth rfcomm watch.

zeenix said...

Ah I misread in a hurry, you're talking of the bluez udev rule while I was talking of the very generic rule at the top of the 99-gpsd.rules file:

# Prolific Technology, Inc. PL2303 Serial Port [linux module: pl2303]
ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", SYMLINK+="gps%n", TAG+="systemd", ENV{SYSTEMD_WANTS}="gpsdctl@%k.service"


It's good that GPSD releases the devices after probing them but the fact remains that it will probe devices that it really shouldn't be touching and there will be conflict with other services/apps (e.g ModemManager). I understand it can't be helped if you want to support simple GPS devices out of the box, without having to have GPSD running but I don't feel too eager about it.

As for the udev rule for bluetooth device, the mac address will be different for each device out there so the only way to make this work would be for gps-share to install the rule itself (while running) but to do that, it first needs to know of the device and find out its mac address. If it has to talk to bluez and probe the device first to do that anyway, I don't see much point of adding the udev rule. That'd add more moving parts for not much benefit. Keep in mind that I want the gps-share to be running when it probes/connects to devices (for the USB case) anyway.

As for making bluetooth devices out of the box, gps-share (when it's running) just need to register itself as the profile manager for the bluetooth serial port class with bluez.