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
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
|
diff --git a/lora_pkt_fwd/Makefile b/lora_pkt_fwd/Makefile
index 1330d62..dda589e 100644
--- a/lora_pkt_fwd/Makefile
+++ b/lora_pkt_fwd/Makefile
@@ -22,7 +22,7 @@ RELEASE_VERSION := `cat ../VERSION`
CC := $(CROSS_COMPILE)gcc
AR := $(CROSS_COMPILE)ar
-CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I.
+MORECFLAGS := -Wall -Wextra -std=c99 -Iinc -I. -isystem =/usr/include/gps
VFLAG := -D VERSION_STRING="\"$(RELEASE_VERSION)\""
### Constants for Lora concentrator HAL library
@@ -38,7 +38,7 @@ LGW_INC += $(LGW_PATH)/inc/loragw_gps.h
### Linking options
-LIBS := -lloragw -lrt -lpthread -lm
+LIBS := -lloragw -lrt -lpthread -lm -lgps
### General build targets
@@ -54,12 +54,14 @@ $(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: src/%.c $(INCLUDES) | $(OBJDIR)
- $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@
+ @echo compile $@
+ $(CC) -c $(CFLAGS) $(MORECFLAGS) -I$(LGW_PATH)/inc $< -o $@
### Main program compilation and assembly
$(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) $(INCLUDES) | $(OBJDIR)
- $(CC) -c $(CFLAGS) $(VFLAG) -I$(LGW_PATH)/inc $< -o $@
+ @echo compile $@
+ $(CC) -c $(CFLAGS) $(MORECFLAGS) $(VFLAG) -I$(LGW_PATH)/inc $< -o $@
$(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a $(OBJDIR)/parson.o $(OBJDIR)/base64.o $(OBJDIR)/jitqueue.o $(OBJDIR)/timersync.o
$(CC) -L$(LGW_PATH) $< $(OBJDIR)/parson.o $(OBJDIR)/base64.o $(OBJDIR)/jitqueue.o $(OBJDIR)/timersync.o -o $@ $(LIBS)
diff --git a/lora_pkt_fwd/src/lora_pkt_fwd.c b/lora_pkt_fwd/src/lora_pkt_fwd.c
index 801f28d..6bca482 100644
--- a/lora_pkt_fwd/src/lora_pkt_fwd.c
+++ b/lora_pkt_fwd/src/lora_pkt_fwd.c
@@ -156,10 +156,10 @@ static bool xtal_correct_ok = false; /* set true when XTAL correction is stable
static double xtal_correct = 1.0;
/* GPS configuration and synchronization */
-static char gps_tty_path[64] = "\0"; /* path of the TTY port GPS is connected on */
-static int gps_tty_fd = -1; /* file descriptor of the GPS TTY port */
+static bool use_gps = false; /* Use the GPSD stream */
static bool gps_enabled = false; /* is GPS enabled on that gateway ? */
-
+static struct gps_data_t gpsdata;
+static struct fixsource_t source;
/* GPS time reference */
static pthread_mutex_t mx_timeref = PTHREAD_MUTEX_INITIALIZER; /* control access to GPS time reference */
static bool gps_ref_valid; /* is GPS reference acceptable (ie. not too old) */
@@ -747,13 +747,6 @@ static int parse_gateway_configuration(const char * conf_file) {
}
MSG("INFO: packets received with no CRC will%s be forwarded\n", (fwd_nocrc_pkt ? "" : " NOT"));
- /* GPS module TTY path (optional) */
- str = json_object_get_string(conf_obj, "gps_tty_path");
- if (str != NULL) {
- strncpy(gps_tty_path, str, sizeof gps_tty_path);
- MSG("INFO: GPS serial port path is configured to \"%s\"\n", gps_tty_path);
- }
-
/* get reference coordinates */
val = json_object_get_value(conf_obj, "ref_latitude");
if (val != NULL) {
@@ -772,6 +765,17 @@ static int parse_gateway_configuration(const char * conf_file) {
}
/* Gateway GPS coordinates hardcoding (aka. faking) option */
+ val = json_object_get_value(conf_obj, "gps");
+ if (json_value_get_type(val) == JSONBoolean) {
+ use_gps = (bool)json_value_get_boolean(val);
+ if (use_gps == true) {
+ MSG("INFO: GPS is enabled\n");
+ } else {
+ MSG("INFO: GPS is disabled\n");
+ }
+ }
+
+ /* Gateway GPS coordinates hardcoding (aka. faking) option */
val = json_object_get_value(conf_obj, "fake_gps");
if (json_value_get_type(val) == JSONBoolean) {
gps_fake_enable = (bool)json_value_get_boolean(val);
@@ -1098,14 +1102,14 @@ int main(void)
}
/* Start GPS a.s.a.p., to allow it to lock */
- if (gps_tty_path[0] != '\0') { /* do not try to open GPS device if no path set */
- i = lgw_gps_enable(gps_tty_path, "ubx7", 0, &gps_tty_fd); /* HAL only supports u-blox 7 for now */
+ if (use_gps == true) {
+ int i = lgw_gps_enable(&gpsdata, &source);
if (i != LGW_GPS_SUCCESS) {
- printf("WARNING: [main] impossible to open %s for GPS sync (check permissions)\n", gps_tty_path);
+ printf("WARNING: [main] impossible to open for GPS sync (Check GPSD)\n");
gps_enabled = false;
gps_ref_valid = false;
} else {
- printf("INFO: [main] TTY port %s open for GPS synchronization\n", gps_tty_path);
+ printf("INFO: [main] GPSD polling open for GPS synchronization\n");
gps_enabled = true;
gps_ref_valid = false;
}
@@ -1413,7 +1417,7 @@ int main(void)
pthread_cancel(thrid_gps); /* don't wait for GPS thread */
pthread_cancel(thrid_valid); /* don't wait for validation thread */
- i = lgw_gps_disable(gps_tty_fd);
+ i = lgw_gps_disable(&gpsdata);
if (i == LGW_HAL_SUCCESS) {
MSG("INFO: GPS closed successfully\n");
} else {
@@ -2683,7 +2731,7 @@ static void gps_process_sync(void) {
i = lgw_gps_sync(&time_reference_gps, trig_tstamp, utc, gps_time);
pthread_mutex_unlock(&mx_timeref);
if (i != LGW_GPS_SUCCESS) {
- MSG("WARNING: [gps] GPS out of sync, keeping previous time reference\n");
+// MSG("WARNING: [gps] GPS out of sync, keeping previous time reference\n");
}
}
@@ -2691,7 +2695,7 @@ static void gps_process_coords(void) {
/* position variable */
struct coord_s coord;
struct coord_s gpserr;
- int i = lgw_gps_get(NULL, NULL, &coord, &gpserr);
+ int i = lgw_gps_get(NULL, NULL, &coord, &gpserr);
/* update gateway coordinates */
pthread_mutex_lock(&mx_meas_gps);
@@ -2707,96 +2711,88 @@ static void gps_process_coords(void) {
}
void thread_gps(void) {
- /* serial variables */
char serial_buff[128]; /* buffer to receive GPS data */
- size_t wr_idx = 0; /* pointer to end of chars in buffer */
-
- /* variables for PPM pulse GPS synchronization */
enum gps_msg latest_msg; /* keep track of latest NMEA message parsed */
-
- /* initialize some variables before loop */
- memset(serial_buff, 0, sizeof serial_buff);
-
+ memset(serial_buff, 0, sizeof serial_buff); /* initialize some variables before loop */
+ fd_set fds;
+ char delim[4] = "$";
+ char *token[254];
while (!exit_sig && !quit_sig) {
- size_t rd_idx = 0;
- size_t frame_end_idx = 0;
-
- /* blocking non-canonical read on serial port */
- ssize_t nb_char = read(gps_tty_fd, serial_buff + wr_idx, LGW_GPS_MIN_MSG_SIZE);
- if (nb_char <= 0) {
- MSG("WARNING: [gps] read() returned value %d\n", nb_char);
+ int r = 0;
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000;
+ FD_ZERO(&fds);
+ FD_SET(gpsdata.gps_fd, &fds);
+ errno = 0;
+ r = select(gpsdata.gps_fd+1, &fds, NULL, NULL, &tv);
+ if (r == -1 && errno != EINTR) {
+ MSG("gpspipe: select error %s(%d)\n", strerror(errno), errno);
+ exit(EXIT_FAILURE);
+ } else if (r == 0)
continue;
- }
- wr_idx += (size_t)nb_char;
- /*******************************************
- * Scan buffer for UBX/NMEA sync chars and *
- * attempt to decode frame if one is found *
- *******************************************/
- while(rd_idx < wr_idx) {
+ /* reading directly from the socket avoids decode overhead */
+ errno = 0;
+ r = (int)read(gpsdata.gps_fd, serial_buff, sizeof(serial_buff));
+ if (r > 0) {
+ int i = 0;
size_t frame_size = 0;
-
- /* Scan buffer for UBX sync char */
- if(serial_buff[rd_idx] == (char)LGW_GPS_UBX_SYNC_CHAR) {
-
- /***********************
- * Found UBX sync char *
- ***********************/
- latest_msg = lgw_parse_ubx(&serial_buff[rd_idx], (wr_idx - rd_idx), &frame_size);
-
- if (frame_size > 0) {
- if (latest_msg == INCOMPLETE) {
- /* UBX header found but frame appears to be missing bytes */
- frame_size = 0;
- } else if (latest_msg == INVALID) {
- /* message header received but message appears to be corrupted */
- MSG("WARNING: [gps] could not get a valid message from GPS (no time)\n");
- frame_size = 0;
- } else if (latest_msg == UBX_NAV_TIMEGPS) {
- gps_process_sync();
+ for (i = 0; i < r; i++) {
+ if (serial_buff[i] == (char)LGW_GPS_UBX_SYNC_CHAR) {
+ /***********************
+ * Found UBX sync char *
+ ***********************/
+ size_t ubx_size = (uint8_t)serial_buff[i+4];
+ ubx_size |= (uint8_t)serial_buff[i+5] << 8;
+ ubx_size += 8;
+ if (ubx_size < 27){
+ latest_msg = lgw_parse_ubx(&serial_buff[i], ubx_size , &frame_size);
}
- }
- } else if(serial_buff[rd_idx] == LGW_GPS_NMEA_SYNC_CHAR) {
- /************************
- * Found NMEA sync char *
- ************************/
- /* scan for NMEA end marker (LF = 0x0a) */
- char* nmea_end_ptr = memchr(&serial_buff[rd_idx],(int)0x0a, (wr_idx - rd_idx));
-
- if(nmea_end_ptr) {
- /* found end marker */
- frame_size = nmea_end_ptr - &serial_buff[rd_idx] + 1;
- latest_msg = lgw_parse_nmea(&serial_buff[rd_idx], frame_size);
-
- if(latest_msg == INVALID || latest_msg == UNKNOWN) {
- /* checksum failed */
- frame_size = 0;
- } else if (latest_msg == NMEA_RMC) { /* Get location from RMC frames */
- gps_process_coords();
+ if (frame_size > 0) {
+ if(latest_msg == INVALID || latest_msg == UNKNOWN) {
+ /* checksum failed */
+ frame_size = 0;
+ } else if (latest_msg == UBX_NAV_TIMEGPS) {
+ gps_process_sync();
+ }
+ }
+ } else if((serial_buff[i] == LGW_GPS_NMEA_SYNC_CHAR) && (serial_buff[i+1] == 0x47) && (serial_buff[i+2] == 0x50)){
+ /************************
+ * Found NMEA sync char *
+ ************************/
+ int k, l= 0;
+ token[0] = strtok(serial_buff, delim);
+
+ while (token[l] != NULL) {
+ l++;
+ token[l] = strtok(NULL, delim);
+ }
+ for (k=0; k<=l-1; k++) {
+ if ((strlen(token[k]) > 66) && (strlen(token[k]) < 74)){
+ latest_msg = lgw_parse_nmea(token[k], strlen(token[k]));
+ if(latest_msg == INVALID || latest_msg == UNKNOWN) {
+ /* checksum failed */
+ frame_size = 0;
+ } else if (latest_msg == NMEA_RMC) {
+ /* Get location from RMC frames */
+ gps_process_coords();
+ }
+ }
}
}
}
-
- if(frame_size > 0) {
- /* At this point message is a checksum verified frame
- we're processed or ignored. Remove frame from buffer */
- rd_idx += frame_size;
- frame_end_idx = rd_idx;
+ } else {
+ if (r == -1) {
+ if (errno == EAGAIN)
+ continue;
+ else {
+ MSG(stderr, "gpspipe: read error %s(%d)\n", strerror(errno), errno);
+ exit(EXIT_FAILURE);
+ }
} else {
- rd_idx++;
+ exit(EXIT_SUCCESS);
}
- } /* ...for(rd_idx = 0... */
-
- if(frame_end_idx) {
- /* Frames have been processed. Remove bytes to end of last processed frame */
- memcpy(serial_buff, &serial_buff[frame_end_idx], wr_idx - frame_end_idx);
- wr_idx -= frame_end_idx;
- } /* ...for(rd_idx = 0... */
-
- /* Prevent buffer overflow */
- if((sizeof(serial_buff) - wr_idx) < LGW_GPS_MIN_MSG_SIZE) {
- memcpy(serial_buff, &serial_buff[LGW_GPS_MIN_MSG_SIZE], wr_idx - LGW_GPS_MIN_MSG_SIZE);
- wr_idx -= LGW_GPS_MIN_MSG_SIZE;
}
}
MSG("\nINFO: End of GPS thread\n");
|