4

I would like a dead-simple way to query my gps location from a usb dongle from the unix command line.

Right now, I know I've got a functioning software and hardware system, as evidenced by the success of the cgps command in showing me my position. I'd now like to be able to make short requests for my gps location (lat,long in decimals) from the command line. my usb serial's path is /dev/ttyUSB0 and I'm using a Global Sat dongle that outputs generic NMEA sentences

How might I accomplish this?

Thanks

boulder_ruby
  • 38,457
  • 9
  • 79
  • 100

5 Answers5

5

telnet 127.0.0.1 2947

?WATCH={"enable":true}

?POLL;

gives you your answer, but you still need to separate the wheat from the chaff. It also assumes the gps is not coming in from a cold start.

A short script could be called, e.g.;

#!/bin/bash
exec 2>/dev/null
# get positions
gpstmp=/tmp/gps.data
gpspipe -w -n 40 >$gpstmp"1"&
ppid=$!
sleep 10
kill -9 $ppid
cat $gpstmp"1"|grep -om1 "[-]\?[[:digit:]]\{1,3\}\.[[:digit:]]\{9\}" >$gpstmp
size=$(stat -c%s $gpstmp)
if [ $size -gt 10 ]; then
   cat $gpstmp|sed -n -e 1p >/tmp/gps.lat
   cat $gpstmp|sed -n -e 2p >/tmp/gps.lon
fi
rm $gpstmp $gpstmp"1"  

This will cause 40 sentences to be output and then grep lat/lon to temporary files and then clean up.

Or, from GPS3 github repository place the alpha gps3.py in the same directory as, and execute, the following Python2.7-3.4 script.

from time import sleep
import gps3

the_connection = gps3.GPSDSocket()
the_fix = gps3.DataStream()

try:
    for new_data in the_connection:
        if new_data:
            the_fix.refresh(new_data)
        if not isinstance(the_fix.TPV['lat'], str):  # check for valid data
            speed = the_fix.TPV['speed']
            latitude = the_fix.TPV['lat']
            longitude = the_fix.TPV['lon']
            altitude = the_fix.TPV['alt']
            print('Latitude:', latitude, 'Longitude:', longitude)
            sleep(1)
except KeyboardInterrupt:
    the_connection.close()
    print("\nTerminated by user\nGood Bye.\n")

If you want it to close after one iteration also import sys and then replace sleep(1) with sys.exit()

Nodak
  • 929
  • 1
  • 8
  • 14
  • my usb serial's path is `/dev/ttyUSB0`. Could you craft this answer to work with that? – boulder_ruby Feb 08 '15 at 01:53
  • For the shell script, I changed `gpstemp`'s string to "/dev/ttyUSB0" and ran it, but the program returned nothing. No errors though – boulder_ruby Feb 08 '15 at 01:55
  • You're using gpsd to provide the data. `gpspipe` calls the gpsd to pipe output to the temporary file (`gpstmp=/tmp/gps.data`). You don't see any errors because they are (would be) sent off into the ether. Paste the bash script into, e.g., `ll.sh` ; call the script `sh ./ll.sh` go to `/tmp/gps.lat` & `/tmp/gps.lon` for your output...or remove the file redirect (`>/tmp/gps.lat`, etc.) for output in the terminal. – Nodak Feb 08 '15 at 02:41
  • 1
    ok, the `-n` option is the key. `gpspipe -r -n 40 > temp.txt` got me started. thanks – boulder_ruby Feb 08 '15 at 18:25
4

much easier solution:

$ gpspipe -w -n 10 |   grep -m 1 lon
{"class":"TPV","device":"tcp://localhost:4352","mode":2,"lat":11.1111110000,"lon":22.222222222}

source

eadmaster
  • 1,347
  • 13
  • 23
2

You can use my script : gps.sh return "x,y"

#!/bin/bash
x=$(gpspipe -w -n 10 |grep lon|tail -n1|cut -d":" -f9|cut -d"," -f1)
y=$(gpspipe -w -n 10 |grep lon|tail -n1|cut -d":" -f10|cut -d"," -f1)
echo "$x,$y" 

sh gps.sh 43.xx4092000,6.xx1269167

1

Putting a few of the bits of different answers together with a bit more jq work, I like this version:

$ gpspipe -w -n 10 | grep -m 1 TPV | jq -r '[.lat, .lon] | @csv'
40.xxxxxx054,-79.yyyyyy367    

Explanation:

(1) use grep -m 1 after invoking gpspipe, as used by @eadmaster's answer, because the grep will exit as soon as the first match is found. This gets you results faster instead of having to wait for 10 lines (or using two invocations of gpspipe).

(2) use jq to extract both fields simultaneously; the @csv formatter is more readable. Note the use of jq -r (raw output), so that the output is not put in quotes. Otherwise the output would be "40.xxxx,-79.xxxx" - which might be fine or better for some applications.

(3) Search for the TPV field by name for clarity. This is the "time, position, velocity" record, which is the one we want for extracting the current lat & lon. Just searching for "lat" or "lon" risks getting confused by the GST object that some GPSes may supply, and in that object, 'lat' and 'lon' are the standard deviation of the position error, not the position itself.

dga
  • 21,757
  • 3
  • 44
  • 51
0

Improving on eadmaster's answer here is a more elegant solution:

gpspipe -w -n 10 | jq -r '.lon' | grep "[[:digit:]]" | tail -1

Explanation:

  1. Ask from gpsd 10 times the data
  2. Parse the received JSONs using jq
  3. We want only numeric values, so filter using grep
  4. We want the last received value, so use tail for that

Example:

$ gpspipe -w -n 10 | jq -r '.lon' | grep "[[:digit:]]" | tail -1
28.853181286