1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
/*
Example3 is a sample gpsd client, demonstrating the gpsd module.
This command will connect to a GPSD daemon, and report the messages
received.
Usage:
example3 [flags]
The flags are:
-dev
The device to ask GPSD for. Default "nil".
-host
The GPSD server address (IP). Default "localhost".
-port
The GPSD server port. Default: 2947.
-prot
The GPSD protocol. Default: 'gpsd'.
'gpsd', IP
'gpsd4' IPv4 only,
'gpsd6' IPv6 only.
-v
-verbosity
The verbosity of the logging (0 to 9_. Default 0.
Warning: Go math does not implement IEEE 754! Different versions
of Go, on different platforms, will produce slightly different
retults.
This file is Copyright The GPSD Project
SPDX-License-Identifier: BSD-2-clause
*/
package main
import (
"flag" // flag.Parse(), etc. For command line flags.
"fmt" // fmt.Printf()
"gpsd" // local "vendored" copy
"math/rand" // for rand.Intn()
"os" // for os.Stderr(), os.Exit()
"sort" // for sort.Sort()
"sync" // for sync.WaitGroup
"time" // for time.Second
)
var (
verbosity int // requested log verbosity level
)
/* main() -- the heart of the client
*
* Exits when connection to the gpsd daemon is lost.
*/
func main() {
var gpsdDev string // gpsd device to read
var gpsdHost string // gpsd host to read
var gpsdPort string // gpsd port
var gpsdProt string // gpsd protocol
flag.StringVar(&gpsdDev, "dev", "", "GPSD device")
flag.StringVar(&gpsdHost, "host", "localhost",
"GPSD server address (IP)")
flag.StringVar(&gpsdPort, "port", "2947", "GPSD server port")
flag.StringVar(&gpsdProt, "prot", "gpsd",
"GPSD protocol. "+
"'gpsd', 'gpsd4' IPv4 only, 'gpsd6' IPv6 only")
vHelp := "Verbosity (0-9)"
flag.IntVar(&verbosity, "v", 0, vHelp)
flag.IntVar(&verbosity, "verbosity", 0, vHelp)
flag.Parse()
// Start logging, set verbosity
GLog := gpsd.NewLog(os.Stderr, "example3: ")
GLog.LogLevel = gpsd.LogLvl(verbosity)
// Create a connection context
var gpsdConn = new(gpsd.Context)
gpsdConn.GLog = GLog
switch gpsdProt {
case "gpsd":
gpsdConn.Type = "tcp"
case "gpsd4":
gpsdConn.Type = "tcp4"
case "gpsd6":
gpsdConn.Type = "tcp6"
default:
GLog.Log(gpsd.LOG_ERROR, "Unknown protocol %s\n", gpsdProt)
os.Exit(2)
}
// Who to connect to
gpsdConn.Device = gpsdDev
gpsdConn.Host = gpsdHost
gpsdConn.Port = gpsdPort
// What to ask for
gpsdConn.Watch.Device = gpsdDev // Yeah, this duplicates gpsdConn.Device
gpsdConn.Watch.Enable = true
gpsdConn.Watch.Json = true
gpsdConn.Watch.Pps = true
/* Use a wait group to wait until the go routine connected to
* the gpsd daemon exits.
*/
var wg sync.WaitGroup
// Decoded messaage data is returned on gpsDataChan
gpsDataChan := make(chan interface{}, 10)
/* Start a go routine that connects to the gpsd daemon,
* and asks for gpsd JSON messages. The decoded JSON is
* sent into the gpsDataChan channel.
*/
wg.Add(1)
go func(gpsdHost string, gpsDataChan chan interface{}) {
defer wg.Done()
for {
gpsd.ConnGPSD(gpsdConn, gpsDataChan)
// lost connection, wait, then retry
time.Sleep(time.Duration(rand.Intn(5)+1) *
time.Second)
}
}(gpsdHost, gpsDataChan)
// Create go routine to receive the decoded messages.
go func(gpsDataChan chan interface{}) {
for {
data := <-gpsDataChan
GLog.Log(gpsd.LOG_IO, "Got %+v\n", data)
switch t := data.(type) {
case *gpsd.DEVICES:
devices := data.(*gpsd.DEVICES)
fmt.Printf("DEVICES\n")
// Sort devices?
for _, device := range devices.Devices {
fmt.Printf(" DEVICE %s Driver %s "+
"Subtype %s %s\n",
device.Path, device.Driver,
device.Subtype, device.Subtype1)
}
case *gpsd.ERROR:
errormsg := data.(*gpsd.ERROR)
fmt.Printf("ERROR %s\n", errormsg.Message)
case *gpsd.PPS:
pps := data.(*gpsd.PPS)
fmt.Printf("PPS Clock %v.%09d Real %v.%09d\n",
pps.Real_sec, pps.Real_nsec,
pps.Clock_sec, pps.Clock_nsec)
case *gpsd.SKY:
sky := data.(*gpsd.SKY)
fmt.Printf("SKY Time %s\n",
sky.Time)
sort.Sort(gpsd.ByGNSS(sky.Satellites))
for _, sat := range sky.Satellites {
fmt.Printf(" %s %d " +
"Az %s El %s Snr %s Used %s\n",
sat.Gnssid, sat.Svid,
sat.Az, sat.El, sat.Ss,
sat.HlthUsed())
}
case *gpsd.TOFF:
toff := data.(*gpsd.TOFF)
fmt.Printf("TOFF Clock %v.%09d Real %v.%09d\n",
toff.Real_sec, toff.Real_nsec,
toff.Clock_sec, toff.Clock_nsec)
case *gpsd.TPV:
tpv := data.(*gpsd.TPV)
fmt.Printf("TPV Time %s Mode %d Lat %f "+
" Lon %f\n",
tpv.Time, tpv.Mode, tpv.Lat, tpv.Lon)
case *gpsd.WATCH:
watch := data.(*gpsd.WATCH)
fmt.Printf("WATCH enable %v json %v\n",
watch.Enable, watch.Json)
case *gpsd.VERSION:
ver := data.(*gpsd.VERSION)
fmt.Printf("VERSION Release %s\n",
ver.Release)
default:
// Ignore other message classes. For now.
GLog.Log(gpsd.LOG_SHOUT, "Ignoring type %v\n",
t)
}
}
}(gpsDataChan)
// wait until all the readers are done
wg.Wait()
}
|