After some more mucking around on a desktop with GPS setup, and taking some of those experiences over to uConsole. Here are Some updated notes on getting GPS setup properly on uConsole. This also applies to Ubuntu setups. Can't comment on the correctness for other distributions, but it should be able to serve as a guide.
This has some improvement over the older method as it no longer uses gnss-share.
NOTE: i use pam_usb for authentication so it is convienient to use sudo in my scripts so it doesn't acrually prompt for a password everytime i use it. YMMV.
There is a service called geoclue on Ubuntu. You can control that with systemctl under the unit name geoclue. Its configuration file lives in /etc/geoclue/geoclue.conf. To enable a GPS with NMEA strings to work, you need to enable the NMEA source. The key configuration section to enable is the following.
[network-nmea]
enable=true
nmea-socket=/run/gpsd-nmea.sock
Wifi based geolocation also requires an update as the Mozilla location service is no longer available.
Either edit the existing wifi section or add the following.
sudo tee /etc/geoclue/conf.d/99-beacondb.conf <<EOF
[wifi]
enable=true
url=https://api.beacondb.net/v1/geolocate
EOF
This is the same as the legacy instructions.
Troubleshooting should be done with journalctl -f -xu geoclue.
This is the standard GPS daemon for most devices. It also acts as a backend to geoclue as well as shares position over GPSD port 2947. This is also available for installation via apt install gpsd. Also install its related clients and tools via gpsd-clients and gpsd-tools respectively.
Once installed, its configuration is available in /etc/default/gpsd.
The setup is as follows.
DEVICES="/dev/ttyAMA0"
# For my uConsole
GPSD_OPTIONS="-b -F /var/run/gpsd.sock"
# For my desktop
# GPSD_OPTIONS="-n -G -F -b /var/run/gpsd.sock"
USBAUTO="true"
The control commands are
systemctl [start|stop] gpsd
systemctl [start|stop] gpsd.socket
It is important to know that the /var/run/gpsd.sock above is the control socket. it is not the data nmea-socket required for geoclue. We would set that up in another command as shown below.
gpspipe -r | ( read; read; read; cat ) | nc -vklU /var/run/gpsd-nmea.sock > /dev/null 2>&1 &
This needs to be executed as root or under sudo. If using sudo, use the following instead in yoru scripts.
gpspipe -r | ( read; read; read; cat ) | sudo nc -vklU /var/run/gpsd-nmea.sock > /dev/null 2>&1 &
This has to be started only after GPSD is available. The permission for this should also allow the gpsd user to have access by adding the gpsd use to a relavant group. i just gave it 777 permissions.
I have also wrapped everything up in /etc/rc.local so that it can start up correctly when the uConsole boots.
#!/bin/bash
#Controls
GPS=1
# Steps to turn on GPS
if [[ "${GPS}" == "1" ]]; then
# make sure gpsd starts up
systemctl restart gpsd
# removes old nmea socket if it exists
if [ -e "/var/run/gpsd-nmea.sock" ]; then
rm -f "/var/run/gpsd-nmea.sock"
fi
# if control socket exists, GPSD should be up
if [ -e "/var/run/gpsd.sock" ]; then
# create gpsd nmea for goeclue
gpspipe -r | ( read; read; read; cat ) | nc -vklU /var/run/gpsd-nmea.sock > /dev/null 2>&1 &
sleep 1
chmod 777 /var/run/gpsd-nmea.sock
fi
# use user login to run geoclue agent
# for integration of apps
fi
If everything is done correctly, you should be able to start up the geoclue agent and test it with where-am-i.
# run in 2 separate shells
$ /usr/libexec/geoclue-2.0/demos/agent
<watch output>
$ /usr/libexec/geoclue-2.0/demos/where-am-i
<watch output>
where-am-i should show the location output from GPS and not WiFi.
If there are issues, what i have found is that it is mainly a permission issue with nmea-socket file. Check the logs of geoclue. There should be no errors.
Another interesting command is to use gpxlogger to see if the information publishes correctly to dbus.
Make sure that you have a good fix with cgps or xgps. Otherwise, geoclue would still stick with Wifi based positioning. This can take quite a few minutes of your device having line-of-sight to sky.
Once where-am-i shows the right output, gnome-maps should work and it should be using the information from you GPS. If you are confident about it, you can then add a startup script in Ubuntu when your user logs in to start the agent. For example.
#/bin/bash
# example startup script when the user login in Gnome
/usr/libexec/geoclue-2.0/demos/agent > /dev/null 2>&1 &
This extension and installation would allow the GPS position to be fed from gpsd to the browser. This might not be necessary. I have found that my browsers would just request for location and and it just works without the extension. But if it doesn't, refer to https://github.com/sulph68/gpsd-chrome-extension
I have tested with the following
- maps.google.com
- OSM
- Any web browser that uses geolocation DOM API. Be careful how that is enabled.
If using pyGPSClient, it is important to know that it can be configured in different ways. It should NOT be directly connected to the device, i.e. NOT /dev/ttyAMA0, if we want to use it in conjunction with GPSD. So we setup a network socket as a source instead. The default is to use localhost:50010.
Set up a data pipe from GPSD and expose that to a network socket at localhost:50010. This leverages socat. The following script is used to do this. From here on, then we start pygpsclient.sh instead of just pygpsclient.
#!/usr/bin/env bash
# TCP port for the GPS NMEA stream
TCP_PORT=50010
# Function to clean up background processes
cleanup() {
echo "Cleaning up..."
if [[ -n "$GPSPIPE_PID" ]]; then
kill $GPSPIPE_PID 2>/dev/null
fi
if [[ -n "$SOCAT_PID" ]]; then
kill $SOCAT_PID 2>/dev/null
fi
exit 0
}
# Catch exit signals
trap cleanup SIGINT SIGTERM EXIT
# Start gpspipe piped into socat
# Using & to run in background, capturing PIDs
gpspipe -r | socat - TCP-LISTEN:$TCP_PORT,reuseaddr,fork &
PIPELINE_PID=$!
# Extract the process group for easier killing later
GPSPIPE_PID=$(pgrep -P $PIPELINE_PID)
SOCAT_PID=$(pgrep -P $PIPELINE_PID)
echo "GPS -> TCP pipeline started (PID: $PIPELINE_PID)"
echo "Launching PyGPSClient..."
# Launch PyGPSClient
# Wait for it to exit; once it does, cleanup will run
pygpsclient
# When pygpsclient exits, kill the pipeline
kill -9 ${PIPELINE_PID}
Once pygpsclient is started using the script, we then use the TCP socket as a source.
Note: Why do this wrapper? So there is no need to expose another port with information unless the app is started.
This covers getting Meshtastic to play nice with GPSD. Reference
- Create a FIFO for the fake GPS
sudo mkfifo /tmp/ttyGPS
sudo chmod 777 /tmp/ttyGPS
- In the
config.yamlfile formeshtasticdset up
GPS:
SerialPath: /tmp/ttyGPS
Enabled: true
- Create a non buffering NMEA pipe to the fake GPS
gpspipe -d --nmea -B -o /tmp/ttyGPS
- Start
meshtasticd
After a while of probing, starting the meshtastic-mui should result in a proper location fix.
You should be able to continue to use GPSD related tools at the same time.
You can then wrap everything neatly up in a start-meshtastic.sh command. Something like the following.
#!/bin/bash
FAKE_GPS="/tmp/ttyGPS"
STATE="$1"
disable_gpspipe() {
local PID="$(ps -ef | grep -P '^.+gpspipe.+ttyGPS$' | awk '{print $2}')"
if [[ "${PID}" != "" ]]; then
echo "Stopping existing GPS pipe for meshtastic"
kill -9 ${PID}
sleep 1
fi
}
enable_gpspipe () {
if [ ! -e "${FAKE_GPS}" ]; then
echo "(Re)creating FIFO file..."
sudo mkfifo ${FAKE_GPS}
sudo chmod 777 ${FAKE_GPS}
fi
echo "Starting GPS pipe for meshtastic"
# daemon in nmea mode with no buffer output to fake gps
gpspipe -d --nmea -B -o ${FAKE_GPS}
}
restart_gpspipe() {
disable_gpspipe
enable_gpspipe
}
case "$1" in
start)
echo "Enabling LORA antenna"
aiov2_ctl.py LORA on
restart_gpspipe
echo "Meshtasticd: Starting"
sudo systemctl start meshtasticd
;;
stop)
echo "Meshtasticd: Stopping.. Closing connections"
sudo systemctl stop meshtasticd
disable_gpspipe
echo "Disabling LORA antenna"
aiov2_ctl.py LORA off
;;
restart)
echo "Restart: Stopping"
$0 stop
sleep 3
echo "Restart: Starting"
$0 start
sleep 1
;;
status)
echo "Meshtasticd: Status"
sudo systemctl status meshtasticd
;;
*)
echo "Usage: $0 [start|stop|status]"
;;
esac
exit 0
Other services seems to require direct access to the GPS device. As it doesn't support the GPSD protocol, we have to shutdown GPSD before enabling these services. You can do that with the following.
systemctl stop gpsd
systemctl stop gpsd.socket
# optional
kill -9 $(ps -ef | grep -P '^.*\d\snc.+gpsd-nmea.sock$' | awk '{print $2}')
rm -f "/var/run/gpsd-nmea.sock"
When you are done using those service and want GPS to be generally available across the operating system again, you can just execute /etc/rc.local. If using the similar script above, it should bring up the GPS again and make it available to the environment again via geoclue.
Note: At this point, i am not very sure if Meshtastic supports GPSD backend. I have read in some forums that it seems to work, but i have never managed to get it working myself.
Main purpose is to ensure that location is available from device to localhost via TCP.
It will allow geoclue to work properly. and enable support for gnome-maps and geoclue dependent applications.
Project location. Build the application. https://github.com/zeenix/gps-share
Default configuration on network is localhost:10110
Command to start gps-share is
$ $HOME/local/bin/gps-share -b 38400 ${GPS_DEV} > /dev/null 2>&1 &
Note: Baud rate and device should point correctly to the actual serial device.
If installed succesfully, should be able to test with /usr/libexec/geoclue-2.0/demos/where-am-i
Note: To prevent geoclue SOUP error as Mozilla location services is no longer available.
sudo tee /etc/geoclue/conf.d/99-beacondb.conf <<EOF
[wifi]
enable=true
url=https://api.beacondb.net/v1/geolocate
EOF
GPSD allows other popular apps to be able to talk to the GPS device easily. This includes testing apps such as xgps and cgps.
GPSD can be installed using apt. However, the device needs to be changed from normal serial device to network device leveraging gps-share.
# /etc/default/gpsd
# Devices gpsd should collect to at boot time.
# They need to be read/writeable, either by user gpsd or the group dialout.
DEVICES="tcp://localhost:10110"
# Other options you want to pass to gpsd
GPSD_OPTIONS="-b -F /var/run/gpsd.sock"
OPTIONS=""
# Automatically hot add/remove USB GPS devices via gpsdctl
USBAUTO="true"
Geoclue agent needs to be started in the background
/usr/libexec/geoclue-2.0/demos/agent > /dev/null 2>&1 &
Note: GPDD services should be disabled at startup. We do not want the daemon to startup before the network socket from gps-share is enabled. Moreover, the device should only be enabled when user is logged in. I am not interested in reading the GPS device if a user isn't logged in.
$ systemctl disable gpsd
$ systemctl disable gpsd.socket
$ systemctl stop gpsd
$ systemctl stop gpsd.socket
In order to start up gpsd manually in a script, the following command is used.
$ /usr/sbin/gpsd -b tcp://localhost:10110 > /dev/null 2>&1 &
If installed correctly, the test apps like xgps should be able to retrieve satellite position.
If using pyGPSClient, just need to configure the network socket to use localhost:10110. You can save it into the configuration file so that it doesn't need to be changed at every startup.
The following startup script is used either as part of the user login startup script or rc.local.
My configuration makes use of gnome-startup via "Startup Applications", executing a script "startup.sh" upon user login. i do not want to allow the GPS device to be read, typically, before a user login.
My user is also added to the dialout group via sudo usermod -aG dialout [username]
# GPS_DEV points to the serial device path by id
# GPS_DEV="/dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0";
if [ -e "${GPS_DEV}" ]; then
echo "- GPS USB cp210x device possibly found"
echo "- Starting geoclue agent"
/usr/libexec/geoclue-2.0/demos/agent > /dev/null 2>&1 &
echo "- Starting gps-share"
$HOME/local/bin/gps-share -b 38400 ${GPS_DEV} > /dev/null 2>&1 &
echo "- Starting gpsd"
/usr/sbin/gpsd -b tcp://localhost:10110 > /dev/null 2>&1 &
$HOME/local/bin/notify "normal" "GPS Status" "GPS Found: Services started"
else
$HOME/local/bin/notify "normal" "GPS Status" "No GPS device found"
fi
Note: notify command ties to notify-send which allows an alert to be shown on gnome if a GPS device and service is started or not.
If everthing is setup correctly, the following apps should all work at the same time
- xgps
- cgps
- pygpsclient
- gnome-maps
tar1090 support is easy fix , use the pygpsclient options to set up tcp port and then edit /etc/default/readsb and add --net-connector 127.0.0.1,50010,gpsd_in to the end of the net connection line. You could prolly just move the tcp port to the rc.local setup and just leave both running. Also i modified your rc.local to call aiov2_ctl gps on. And modified the pygpsscript to change aiov2_ctl.py to aiov2_ctl as the latest script can install itself so it doesnt need the py anymore