summaryrefslogtreecommitdiff
blob: ffaf84dee5686e00bc6e2a2646cd4e1e493ce844 (plain)
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
--- direwolf-1.5/dwgpsd.orig.c	2020-09-13 13:25:07.294828708 +0200
+++ direwolf-1.5/dwgpsd.c	2020-09-13 13:26:48.957086728 +0200
@@ -1,7 +1,7 @@
 //
 //    This file is part of Dire Wolf, an amateur radio packet TNC.
 //
-//    Copyright (C) 2013, 2014, 2015  John Langner, WB2OSZ
+//    Copyright (C) 2013, 2014, 2015, 2020  John Langner, WB2OSZ
 //
 //    This program is free software: you can redistribute it and/or modify
 //    it under the terms of the GNU General Public License as published by
@@ -54,10 +54,10 @@
 
 #include <gps.h>
 
-// Debian bug report:  direwolf (1.2-1) FTBFS with libgps22 as part of the gpsd transition (#803605):
-// dwgps.c claims to only support GPSD_API_MAJOR_VERSION 5, but also builds successfully with
-// GPSD_API_MAJOR_VERSION 6 provided by libgps22 when the attached patch is applied.
-#if GPSD_API_MAJOR_VERSION < 5 || GPSD_API_MAJOR_VERSION > 6
+// An incompatibility was introduced with version 7
+// and again with 9 and again with 10.
+
+#if GPSD_API_MAJOR_VERSION < 5 || GPSD_API_MAJOR_VERSION > 10
 #error libgps API version might be incompatible.
 #endif
 
@@ -112,7 +112,7 @@
  *		  shared region via dwgps_put_data.
  *
  * 		The application calls dwgps_read to get the most 
- 8		recent information.			
+ *		recent information.			
  *
  *--------------------------------------------------------------------*/
 
@@ -122,7 +122,7 @@
  * Originally, I wanted to use the shared memory interface to gpsd
  * because it is simpler and more efficient.  Just access it when we
  * actually need the data and we don't have a lot of extra unnecessary
- * busy work going on.
+ * busy work going on constantly polling it when we don't need the information.
  *
  * The current version of gpsd, supplied with Raspian (Wheezy), is 3.6 from back in 
  * May 2012, is missing support for the shared memory interface.  
@@ -138,13 +138,28 @@
  * 	cd gpsd-3.11
  * 	scons prefix=/usr libdir=lib/arm-linux-gnueabihf shm_export=True python=False
  * 	sudo scons udev-install
- * 
+ *
  * For now, we will use the socket interface.  Maybe get back to this again someday.
  *
  * Update:  January 2016.
  *
  *	I'm told that the shared memory interface might work in Raspian, Jessie version.
  *	Haven't tried it yet.
+ *
+ * June 2020:  This is how to build the most recent.
+ *
+ * 	Based on https://www.satsignal.eu/raspberry-pi/UpdatingGPSD.html
+ *
+ * 	git clone https://gitlab.com/gpsd/gpsd.git  gpsd-gitlab
+ * 	cd gpsd-gitlab
+ * 	scons --config=force
+ * 	scons
+ * 	sudo scons install
+ *
+ *	The problem we have here is that the library is put in /usr/local/lib and direwolf
+ *	can't find it there.  Solution  is to define environment variable:
+ *
+ *	export LD_LIBRARY_PATH=/use/local/lib
  */
 
 
@@ -228,7 +243,7 @@
  *
  *--------------------------------------------------------------------*/
 
-#define TIMEOUT 30
+#define TIMEOUT 15
 
 #if ENABLE_GPSD
 
@@ -251,13 +266,34 @@
 
 	while (1) {
 
+// Example code found here:
+// https://lists.nongnu.org/archive/html/gpsd-dev/2017-11/msg00001.html
+
           if ( ! gps_waiting(&gpsdata, TIMEOUT * 1000000)) {
 	    text_color_set(DW_COLOR_ERROR);
-	    dw_printf ("GPSD: Timeout waiting for GPS data.\n");
-	    /* Fall thru to read which should get error and bail out. */
+	    dw_printf ("------------------------------------------\n");
+	    dw_printf ("dwgpsd: Timeout waiting for GPS data.\n");
+	    dw_printf ("Is GPSD daemon running?\n");
+	    dw_printf ("Troubleshooting tip:  Try running cgps or xgps.\n");
+	    dw_printf ("------------------------------------------\n");
+	    info.fix = DWFIX_ERROR;
+	    SLEEP_MS(5000);
+	    continue;
 	  }
 
+// https://github.com/wb2osz/direwolf/issues/196
+// https://bugzilla.redhat.com/show_bug.cgi?id=1674812
+
+// gps_read has two new parameters in API version 7.
+// It looks like this could be used to obtain the JSON message from the daemon.
+// Specify NULL, instead of message buffer space, if this is not desired.
+// Why couldn't they add a new function instead of introducing incompatibility?
+
+#if GPSD_API_MAJOR_VERSION >= 7
+	  if (gps_read (&gpsdata, NULL, 0) == -1) {
+#else
 	  if (gps_read (&gpsdata) == -1) {
+#endif
 	    text_color_set(DW_COLOR_ERROR);
 
 	    dw_printf ("------------------------------------------\n");
@@ -274,16 +310,47 @@
 	    break;   // Jump out of loop and terminate thread.
 	  }
 
+#if GPSD_API_MAJOR_VERSION >= 9
+
+// The gps.h revision history says:
+//	 *       mark altitude in gps_fix_t as deprecated and undefined
+// This seems really stupid to me.
+// If it is deprecated and undefined then take it out.  Someone trying to use
+// it would get a compile error and know that something needs to be done.
+// Instead we all just go merrily on our way using a field that is [allegedly] undefined.
+// Why not simply add more variables with different definitions of altitude
+// and keep the original variable working as it always did?
+// If it is truly undefined, as the comment would have us believe, numerous
+// people will WASTE VAST AMOUNTS OF TIME pondering why altitude is now broken in
+// their applications.
+
+#define stupid_altitude altMSL
+#else
+#define stupid_altitude altitude
+#endif
+
+#if GPSD_API_MAJOR_VERSION >= 10
+
+// They did it again.  Whimsical incompatibilities that cause
+// pain and aggravation for everyone trying to use this library.
+//
+//	error: ‘struct gps_data_t’ has no member named ‘status’
+//
+// Yes, I can understand that it is a more logical place but it breaks
+// all existing code that uses this.
+// I'm really getting annoyed about wasting so much time on keeping up with all
+// of these incompatibilities that are completely unnecessary.
+
+#define stupid_status fix.status
+#else
+#define stupid_status status
+#endif
+
+	  // Inform user about change in fix status.
+
 	  switch (gpsdata.fix.mode) {
 	    default:
 	    case MODE_NOT_SEEN:
-	      if (info.fix >= DWFIX_2D) {
-		text_color_set(DW_COLOR_INFO);
-	        dw_printf ("GPSD: Lost location fix.\n");
-	      }
-	      info.fix = DWFIX_NOT_SEEN;
-	      break;
-
 	    case MODE_NO_FIX:
 	      if (info.fix >= DWFIX_2D) {
 		text_color_set(DW_COLOR_INFO);
@@ -309,11 +376,7 @@
 	      break;
 	  }
 
-	    /* Data is available. */
-	    // TODO:  what is gpsdata.status?
-
-
-	  if (gpsdata.status >= STATUS_FIX && gpsdata.fix.mode >= MODE_2D) {
+	  if (gpsdata.stupid_status >= STATUS_FIX && gpsdata.fix.mode >= MODE_2D) {
 
 	    info.dlat = isnan(gpsdata.fix.latitude) ? G_UNKNOWN : gpsdata.fix.latitude;
 	    info.dlon = isnan(gpsdata.fix.longitude) ? G_UNKNOWN : gpsdata.fix.longitude;
@@ -321,9 +384,15 @@
 	    info.speed_knots = isnan(gpsdata.fix.speed) ? G_UNKNOWN : (MPS_TO_KNOTS * gpsdata.fix.speed);
 
 	    if (gpsdata.fix.mode >= MODE_3D) {
-	      info.altitude = isnan(gpsdata.fix.altitude) ? G_UNKNOWN : gpsdata.fix.altitude;
+	      info.altitude = isnan(gpsdata.fix.stupid_altitude) ? G_UNKNOWN : gpsdata.fix.stupid_altitude;
 	    }
 	  }
+	  else {
+	    // Keep the last known location.
+	    // Using info.fix, the caller knows if the location is current (DWFIX_[23]D),
+	    // last known (DWFIX_NONE), or never known (DWFIX_NOT_SEEN).
+	    info.fix = DWFIX_NO_FIX;
+	  }
 
 	  info.timestamp = time(NULL);
 	  if (s_debug >= 2) {
@@ -357,6 +426,7 @@
 
 #if ENABLE_GPSD
 
+	gps_stream (&gpsdata, WATCH_DISABLE, NULL);
 	gps_close (&gpsdata);
 
 #endif