File: example3.go

package info (click to toggle)
gpsd 3.27-1.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 44,056 kB
  • sloc: ansic: 74,438; python: 16,521; sh: 890; cpp: 848; php: 225; makefile: 197; perl: 111; javascript: 26; xml: 11
file content (194 lines) | stat: -rw-r--r-- 5,371 bytes parent folder | download | duplicates (2)
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()
}