1 /*
2  * Copyright (C) 2010 Eric S. Raymond.
3  *
4  * This software is distributed under a BSD-style license. See the
5  * file "COPYING" in the top-level directory of the distribution for details.
6  *
7  */
8 
9 /* This simple program shows the basic functionality of the C++ wrapper class */
10 #include <iostream>
11 
12 #include <getopt.h>
13 
14 #include "../libgpsmm.h"
15 #include "../timespec.h"
16 #include "../timespec_str.c"
17 #include "../gpsdclient.c"
18 /*     YES   --->  ^^^^
19  Using .c rather than the .h to embed gpsd_source_spec() source here
20   so that it is compiled in C++ rather than C of the gps library
21  (otherwise fails to link as the signatures are unavailable/different)
22 */
23 using namespace std;
24 
printfinite(double val)25 void printfinite(double val)
26 {
27     if (0 == isfinite(val))
28         (void)fputs(" N/A   ", stdout);
29     else
30         (void)fprintf(stdout, "%6.2f ", val);
31 }
32 
33 /*
34  * We should get libgps_dump_state() from the client library, but
35  * scons has a bug; we can't get it to add -lgps to the link line,
36  * apparently because it doesn't honor parse_flags on a Program()
37  * build of a C++ file.
38  */
libgps_dump_state(struct gps_data_t * collect)39 static void libgps_dump_state(struct gps_data_t *collect)
40 {
41     char ts_str[TIMESPEC_LEN];
42 
43     /* no need to dump the entire state, this is a sanity check */
44 #ifndef USE_QT
45     (void)fprintf(stdout, "flags: (0x%04x) %s\n",
46                   (unsigned int)collect->set, gps_maskdump(collect->set));
47 #endif
48     if (collect->set & ONLINE_SET)
49         (void)fprintf(stdout, "ONLINE: %s\n",
50                       timespec_str(&collect->online, ts_str, sizeof(ts_str)));
51     if (collect->set & TIME_SET)
52         (void)fprintf(stdout, "TIME: %s\n",
53                       timespec_str(&collect->fix.time, ts_str, sizeof(ts_str)));
54 
55     if (collect->set & LATLON_SET)
56         (void)fprintf(stdout, "LATLON: lat/lon: %lf %lf\n",
57                       collect->fix.latitude, collect->fix.longitude);
58     if (collect->set & ALTITUDE_SET)
59         (void)fprintf(stdout, "ALTITUDE: altHAE: %lf  U: climb: %lf\n",
60                       collect->fix.altHAE, collect->fix.climb);
61     if (collect->set & SPEED_SET)
62         (void)fprintf(stdout, "SPEED: %lf\n", collect->fix.speed);
63     if (collect->set & TRACK_SET)
64         (void)fprintf(stdout, "TRACK: track: %lf\n", collect->fix.track);
65     if (collect->set & CLIMB_SET)
66         (void)fprintf(stdout, "CLIMB: climb: %lf\n", collect->fix.climb);
67     if (collect->set & STATUS_SET)
68         (void)fprintf(stdout, "STATUS: status: %d\n", collect->status);
69     if (collect->set & MODE_SET)
70         (void)fprintf(stdout, "MODE: mode: %d\n", collect->fix.mode);
71     if (collect->set & DOP_SET)
72         (void)fprintf(stdout,
73                       "DOP: satellites %d, pdop=%lf, hdop=%lf, vdop=%lf\n",
74                       collect->satellites_used, collect->dop.pdop,
75                       collect->dop.hdop, collect->dop.vdop);
76     if (collect->set & VERSION_SET)
77         (void)fprintf(stdout, "VERSION: release=%s rev=%s proto=%d.%d\n",
78                       collect->version.release,
79                       collect->version.rev,
80                       collect->version.proto_major,
81                       collect->version.proto_minor);
82     if (collect->set & POLICY_SET)
83         (void)fprintf(stdout,
84                       "POLICY: watcher=%s nmea=%s raw=%d scaled=%s timing=%s, devpath=%s\n",
85                       collect->policy.watcher ? "true" : "false",
86                       collect->policy.nmea ? "true" : "false",
87                       collect->policy.raw,
88                       collect->policy.scaled ? "true" : "false",
89                       collect->policy.timing ? "true" : "false",
90                       collect->policy.devpath);
91     if (collect->set & SATELLITE_SET) {
92         int i;
93 
94         (void)fprintf(stdout, "SKY: satellites in view: %d\n",
95                       collect->satellites_visible);
96         for (i = 0; i < collect->satellites_visible; i++) {
97             (void)fprintf(stdout, "    %3d", collect->skyview[i].PRN);
98             printfinite(collect->skyview[i].elevation);
99             printfinite(collect->skyview[i].azimuth);
100             printfinite(collect->skyview[i].ss);
101             (void)fprintf(stdout, collect->skyview[i].used ? " Y\n" : " N\n");
102         }
103     }
104     if (collect->set & DEVICE_SET)
105         (void)fprintf(stdout, "DEVICE: Device is '%s', driver is '%s'\n",
106                       collect->dev.path, collect->dev.driver);
107 #ifdef OLDSTYLE_ENABLE
108     if (collect->set & DEVICEID_SET)
109         (void)fprintf(stdout, "GPSD ID is %s\n", collect->dev.subtype);
110 #endif /* OLDSTYLE_ENABLE */
111     if (collect->set & DEVICELIST_SET) {
112         int i;
113         (void)fprintf(stdout, "DEVICELIST:%d devices:\n",
114                       collect->devices.ndevices);
115         for (i = 0; i < collect->devices.ndevices; i++) {
116             (void)fprintf(stdout, "%d: path='%s' driver='%s'\n",
117                           collect->devices.ndevices,
118                           collect->devices.list[i].path,
119                           collect->devices.list[i].driver);
120         }
121     }
122 }
123 
124 
main(int argc,char * argv[])125 int main(int argc, char *argv[])
126 {
127     uint looper = UINT_MAX;
128 
129     // A typical C++ program may look to use a more native option parsing method
130     //  such as boost::program_options
131     // But for this test program we don't want extra dependencies
132     // Hence use C style getopt for (build) simplicity
133     int option;
134     while ((option = getopt(argc, argv, "l:h?")) != -1) {
135         switch (option) {
136         case 'l':
137             looper = atoi(optarg);
138             break;
139         case '?':
140         case 'h':
141         default:
142             cout << "usage: " << argv[0] << " [-l n]\n";
143             exit(EXIT_FAILURE);
144             break;
145         }
146     }
147 
148     struct fixsource_t source;
149     /* Grok the server, port, and device. */
150     if (optind < argc) {
151         gpsd_source_spec(argv[optind], &source);
152     } else
153         gpsd_source_spec(NULL, &source);
154 
155     //gpsmm gps_rec("localhost", DEFAULT_GPSD_PORT);
156     gpsmm gps_rec(source.server, source.port);
157 
158     if ( !((std::string)source.server == (std::string)GPSD_SHARED_MEMORY ||
159            (std::string)source.server == (std::string)GPSD_DBUS_EXPORT) ) {
160         if (gps_rec.stream(WATCH_ENABLE|WATCH_JSON) == NULL) {
161             cerr << "No GPSD running.\n";
162             return 1;
163         }
164     }
165 
166     // Loop for the specified number of times
167     // If not specified then by default it loops until ll simply goes out of bounds
168     // So with the 5 second wait & a 4 byte uint - this equates to ~680 years
169     //  - long enough for a test program :)
170     for (uint ll = 0; ll < looper; ll++) {
171         struct gps_data_t* newdata;
172 
173         if (!gps_rec.waiting(5000000))
174           continue;
175 
176         if ((newdata = gps_rec.read()) == NULL) {
177             cerr << "Read error.\n";
178             return 1;
179         } else {
180             libgps_dump_state(newdata);
181         }
182     }
183 
184     cout << "Exiting\n";
185     return 0;
186 }
187 
188