1 /****************************************************************************
2
3 NAME
4 libgps_json.c - deserialize gpsd data coming from the server
5
6 DESCRIPTION
7 This module uses the generic JSON parser to get data from JSON
8 representations to libgps structures.
9
10 PERMISSIONS
11 Written by Eric S. Raymond, 2009
12 This file is Copyright (c) 2009-2018 by the GPSD project
13 SPDX-License-Identifier: BSD-2-clause
14
15 ***************************************************************************/
16
17 /* isfinite() needs _POSIX_C_SOURCE >= 200112L
18 * isnan(+Inf) is false, isfinite(+Inf) is false
19 * use isfinite() to make sure a float is valid
20 */
21
22 #include "gpsd_config.h" /* must be before all includes */
23
24 #include <math.h>
25 #include <stdbool.h>
26 #include <stddef.h>
27 #include <string.h>
28
29 #include "gpsd.h"
30 #include "strfuncs.h"
31 #ifdef SOCKET_EXPORT_ENABLE
32 #include "gps_json.h"
33 #include "timespec.h"
34
json_tpv_read(const char * buf,struct gps_data_t * gpsdata,const char ** endptr)35 static int json_tpv_read(const char *buf, struct gps_data_t *gpsdata,
36 const char **endptr)
37 {
38 int leapseconds; /* FIXME, unused... */
39 int ret;
40
41 const struct json_attr_t json_attrs_1[] = {
42 /* *INDENT-OFF* */
43 {"class", t_check, .dflt.check = "TPV"},
44 {"device", t_string, .addr.string = gpsdata->dev.path,
45 .len = sizeof(gpsdata->dev.path)},
46 {"time", t_time, .addr.ts = &gpsdata->fix.time,
47 .dflt.ts = {0, 0}},
48 {"leapseconds", t_integer, .addr.integer = &leapseconds,
49 .dflt.integer = 0},
50 {"ept", t_real, .addr.real = &gpsdata->fix.ept,
51 .dflt.real = NAN},
52 {"lon", t_real, .addr.real = &gpsdata->fix.longitude,
53 .dflt.real = NAN},
54 {"lat", t_real, .addr.real = &gpsdata->fix.latitude,
55 .dflt.real = NAN},
56 {"alt", t_real, .addr.real = &gpsdata->fix.altitude,
57 .dflt.real = NAN}, // DEPRECATED, undefined
58 {"altHAE", t_real, .addr.real = &gpsdata->fix.altHAE,
59 .dflt.real = NAN},
60 {"altMSL", t_real, .addr.real = &gpsdata->fix.altMSL,
61 .dflt.real = NAN},
62 {"datum", t_string, .addr.string = gpsdata->fix.datum,
63 .len = sizeof(gpsdata->fix.datum)},
64 {"epc", t_real, .addr.real = &gpsdata->fix.epc,
65 .dflt.real = NAN},
66 {"epd", t_real, .addr.real = &gpsdata->fix.epd,
67 .dflt.real = NAN},
68 {"eph", t_real, .addr.real = &gpsdata->fix.eph,
69 .dflt.real = NAN},
70 {"eps", t_real, .addr.real = &gpsdata->fix.eps,
71 .dflt.real = NAN},
72 {"epx", t_real, .addr.real = &gpsdata->fix.epx,
73 .dflt.real = NAN},
74 {"epy", t_real, .addr.real = &gpsdata->fix.epy,
75 .dflt.real = NAN},
76 {"epv", t_real, .addr.real = &gpsdata->fix.epv,
77 .dflt.real = NAN},
78 {"track", t_real, .addr.real = &gpsdata->fix.track,
79 .dflt.real = NAN},
80 {"magtrack", t_real, .addr.real = &gpsdata->fix.magnetic_track,
81 .dflt.real = NAN},
82 {"magvar", t_real, .addr.real = &gpsdata->fix.magnetic_var,
83 .dflt.real = NAN},
84 {"speed", t_real, .addr.real = &gpsdata->fix.speed,
85 .dflt.real = NAN},
86 {"climb", t_real, .addr.real = &gpsdata->fix.climb,
87 .dflt.real = NAN},
88 {"ecefx", t_real, .addr.real = &gpsdata->fix.ecef.x,
89 .dflt.real = NAN},
90 {"ecefy", t_real, .addr.real = &gpsdata->fix.ecef.y,
91 .dflt.real = NAN},
92 {"ecefz", t_real, .addr.real = &gpsdata->fix.ecef.z,
93 .dflt.real = NAN},
94 {"ecefvx", t_real, .addr.real = &gpsdata->fix.ecef.vx,
95 .dflt.real = NAN},
96 {"ecefvy", t_real, .addr.real = &gpsdata->fix.ecef.vy,
97 .dflt.real = NAN},
98 {"ecefvz", t_real, .addr.real = &gpsdata->fix.ecef.vz,
99 .dflt.real = NAN},
100 {"ecefpAcc", t_real, .addr.real = &gpsdata->fix.ecef.vAcc,
101 .dflt.real = NAN},
102 {"ecefvAcc", t_real, .addr.real = &gpsdata->fix.ecef.pAcc,
103 .dflt.real = NAN},
104 {"mode", t_integer, .addr.integer = &gpsdata->fix.mode,
105 .dflt.integer = MODE_NOT_SEEN},
106 {"sep", t_real, .addr.real = &gpsdata->fix.sep,
107 .dflt.real = NAN},
108 {"status", t_integer, .addr.integer = &gpsdata->status,
109 .dflt.integer = STATUS_FIX},
110 {"relN", t_real, .addr.real = &gpsdata->fix.NED.relPosN,
111 .dflt.real = NAN},
112 {"relE", t_real, .addr.real = &gpsdata->fix.NED.relPosE,
113 .dflt.real = NAN},
114 {"relD", t_real, .addr.real = &gpsdata->fix.NED.relPosD,
115 .dflt.real = NAN},
116 {"velN", t_real, .addr.real = &gpsdata->fix.NED.relPosN,
117 .dflt.real = NAN},
118 {"velE", t_real, .addr.real = &gpsdata->fix.NED.relPosE,
119 .dflt.real = NAN},
120 {"velD", t_real, .addr.real = &gpsdata->fix.NED.relPosD,
121 .dflt.real = NAN},
122 {"geoidSep", t_real, .addr.real = &gpsdata->fix.geoid_sep,
123 .dflt.real = NAN},
124 {"depth", t_real, .addr.real = &gpsdata->fix.depth,
125 .dflt.real = NAN},
126 {"dgpsAge", t_real, .addr.real = &gpsdata->fix.dgps_age,
127 .dflt.real = NAN},
128 {"dgpsSta", t_integer, .addr.integer = &gpsdata->fix.dgps_station,
129 .dflt.integer = -1},
130 // ignore unkown keys, for cross-version compatibility
131 {"", t_ignore},
132
133 {NULL},
134 /* *INDENT-ON* */
135 };
136
137 ret = json_read_object(buf, json_attrs_1, endptr);
138 return ret;
139 }
140
json_noise_read(const char * buf,struct gps_data_t * gpsdata,const char ** endptr)141 static int json_noise_read(const char *buf, struct gps_data_t *gpsdata,
142 const char **endptr)
143 {
144 int ret;
145
146 const struct json_attr_t json_attrs_1[] = {
147 /* *INDENT-OFF* */
148 {"class", t_check, .dflt.check = "GST"},
149 {"device", t_string, .addr.string = gpsdata->dev.path,
150 .len = sizeof(gpsdata->dev.path)},
151 {"time", t_time, .addr.ts = &gpsdata->gst.utctime,
152 .dflt.ts = {0, 0}},
153 {"rms", t_real, .addr.real = &gpsdata->gst.rms_deviation,
154 .dflt.real = NAN},
155 {"major", t_real, .addr.real = &gpsdata->gst.smajor_deviation,
156 .dflt.real = NAN},
157 {"minor", t_real, .addr.real = &gpsdata->gst.sminor_deviation,
158 .dflt.real = NAN},
159 {"orient", t_real, .addr.real = &gpsdata->gst.smajor_orientation,
160 .dflt.real = NAN},
161 {"lat", t_real, .addr.real = &gpsdata->gst.lat_err_deviation,
162 .dflt.real = NAN},
163 {"lon", t_real, .addr.real = &gpsdata->gst.lon_err_deviation,
164 .dflt.real = NAN},
165 {"alt", t_real, .addr.real = &gpsdata->gst.alt_err_deviation,
166 .dflt.real = NAN},
167 {NULL},
168 /* *INDENT-ON* */
169 };
170
171 ret = json_read_object(buf, json_attrs_1, endptr);
172
173 return ret;
174 }
175
176 /* decode a RAW messages into gpsdata.raw */
json_raw_read(const char * buf,struct gps_data_t * gpsdata,const char ** endptr)177 static int json_raw_read(const char *buf, struct gps_data_t *gpsdata,
178 const char **endptr)
179 {
180 int measurements;
181 double mtime_s, mtime_ns;
182
183 const struct json_attr_t json_attrs_meas[] = {
184 /* *INDENT-OFF* */
185 {"gnssid", t_ubyte, STRUCTOBJECT(struct meas_t, gnssid)},
186 {"svid", t_ubyte, STRUCTOBJECT(struct meas_t, svid)},
187 {"sigid", t_ubyte, STRUCTOBJECT(struct meas_t, sigid),
188 .dflt.ubyte = 0},
189 {"snr", t_ubyte, STRUCTOBJECT(struct meas_t, snr)},
190 {"freqid", t_ubyte, STRUCTOBJECT(struct meas_t, freqid),
191 .dflt.ubyte = 0},
192 {"obs", t_string, STRUCTOBJECT(struct meas_t, obs_code),
193 .len = sizeof(gpsdata->raw.meas[0].obs_code)},
194 {"lli", t_ubyte, STRUCTOBJECT(struct meas_t, lli),
195 .dflt.ubyte = 0},
196 {"locktime", t_uinteger, STRUCTOBJECT(struct meas_t, locktime),
197 .dflt.uinteger = 0},
198 {"carrierphase", t_real, STRUCTOBJECT(struct meas_t, carrierphase),
199 .dflt.real = NAN},
200 {"pseudorange", t_real, STRUCTOBJECT(struct meas_t, pseudorange),
201 .dflt.real = NAN},
202 {"doppler", t_real, STRUCTOBJECT(struct meas_t, doppler),
203 .dflt.real = NAN},
204 {"c2c", t_real, STRUCTOBJECT(struct meas_t, c2c),
205 .dflt.real = NAN},
206 {"l2c", t_real, STRUCTOBJECT(struct meas_t, l2c),
207 .dflt.real = NAN},
208 /* *INDENT-ON* */
209 {NULL},
210 };
211 const struct json_attr_t json_attrs_raw[] = {
212 /* *INDENT-OFF* */
213 {"class", t_check, .dflt.check = "RAW"},
214 {"device", t_string, .addr.string = gpsdata->dev.path,
215 .len = sizeof(gpsdata->dev.path)},
216 {"time", t_real, .addr.real = &mtime_s,
217 .dflt.real = NAN},
218 {"nsec", t_real, .addr.real = &mtime_ns,
219 .dflt.real = NAN},
220 {"rawdata", t_array, STRUCTARRAY(gpsdata->raw.meas,
221 json_attrs_meas, &measurements)},
222 {NULL},
223 /* *INDENT-ON* */
224 };
225 int status;
226
227 memset(&gpsdata->raw, 0, sizeof(gpsdata->raw));
228
229 status = json_read_object(buf, json_attrs_raw, endptr);
230 if (status != 0)
231 return status;
232 if (0 == isfinite(mtime_s) || 0 == isfinite(mtime_ns))
233 return status;
234 gpsdata->raw.mtime.tv_sec = (time_t)mtime_s;
235 gpsdata->raw.mtime.tv_nsec = (long)mtime_ns;
236
237 return 0;
238 }
239
json_sky_read(const char * buf,struct gps_data_t * gpsdata,const char ** endptr)240 static int json_sky_read(const char *buf, struct gps_data_t *gpsdata,
241 const char **endptr)
242 {
243
244 const struct json_attr_t json_attrs_satellites[] = {
245 /* *INDENT-OFF* */
246 {"PRN", t_short, STRUCTOBJECT(struct satellite_t, PRN)},
247 {"el", t_real, STRUCTOBJECT(struct satellite_t, elevation),
248 .dflt.real = NAN},
249 {"az", t_real, STRUCTOBJECT(struct satellite_t, azimuth),
250 .dflt.real = NAN},
251 {"ss", t_real, STRUCTOBJECT(struct satellite_t, ss),
252 .dflt.real = NAN},
253 {"used", t_boolean, STRUCTOBJECT(struct satellite_t, used)},
254 {"gnssid", t_ubyte, STRUCTOBJECT(struct satellite_t, gnssid)},
255 {"svid", t_ubyte, STRUCTOBJECT(struct satellite_t, svid)},
256 {"sigid", t_ubyte, STRUCTOBJECT(struct satellite_t, sigid)},
257 {"freqid", t_byte, STRUCTOBJECT(struct satellite_t, freqid),
258 .dflt.byte = -1},
259 {"health", t_ubyte, STRUCTOBJECT(struct satellite_t, health),
260 .dflt.ubyte = SAT_HEALTH_UNK},
261 /* *INDENT-ON* */
262 {NULL},
263 };
264 const struct json_attr_t json_attrs_2[] = {
265 /* *INDENT-OFF* */
266 {"class", t_check, .dflt.check = "SKY"},
267 {"device", t_string, .addr.string = gpsdata->dev.path,
268 .len = sizeof(gpsdata->dev.path)},
269 {"time", t_time, .addr.ts = &gpsdata->skyview_time,
270 .dflt.ts = {0, 0}},
271 {"hdop", t_real, .addr.real = &gpsdata->dop.hdop,
272 .dflt.real = NAN},
273 {"xdop", t_real, .addr.real = &gpsdata->dop.xdop,
274 .dflt.real = NAN},
275 {"ydop", t_real, .addr.real = &gpsdata->dop.ydop,
276 .dflt.real = NAN},
277 {"vdop", t_real, .addr.real = &gpsdata->dop.vdop,
278 .dflt.real = NAN},
279 {"tdop", t_real, .addr.real = &gpsdata->dop.tdop,
280 .dflt.real = NAN},
281 {"pdop", t_real, .addr.real = &gpsdata->dop.pdop,
282 .dflt.real = NAN},
283 {"gdop", t_real, .addr.real = &gpsdata->dop.gdop,
284 .dflt.real = NAN},
285 {"satellites", t_array,
286 STRUCTARRAY(gpsdata->skyview,
287 json_attrs_satellites,
288 &gpsdata->satellites_visible)},
289 {NULL},
290 /* *INDENT-ON* */
291 };
292 int status, i;
293
294 memset(&gpsdata->skyview, 0, sizeof(gpsdata->skyview));
295
296 status = json_read_object(buf, json_attrs_2, endptr);
297 if (status != 0)
298 return status;
299
300 gpsdata->satellites_used = 0;
301 gpsdata->satellites_visible = 0;
302 for (i = 0; i < MAXCHANNELS; i++) {
303 if(gpsdata->skyview[i].PRN > 0)
304 gpsdata->satellites_visible++;
305 if (gpsdata->skyview[i].used) {
306 gpsdata->satellites_used++;
307 }
308 }
309
310 return 0;
311 }
312
json_att_read(const char * buf,struct gps_data_t * gpsdata,const char ** endptr)313 static int json_att_read(const char *buf, struct gps_data_t *gpsdata,
314 const char **endptr)
315 {
316 const struct json_attr_t json_attrs_1[] = {
317 /* *INDENT-OFF* */
318 {"class", t_check, .dflt.check = "ATT"},
319 {"device", t_string, .addr.string = gpsdata->dev.path,
320 .len = sizeof(gpsdata->dev.path)},
321 {"heading", t_real, .addr.real = &gpsdata->attitude.heading,
322 .dflt.real = NAN},
323 {"mag_st", t_character, .addr.character = &gpsdata->attitude.mag_st},
324 {"pitch", t_real, .addr.real = &gpsdata->attitude.pitch,
325 .dflt.real = NAN},
326 {"pitch_st", t_character, .addr.character = &gpsdata->attitude.pitch_st},
327 {"roll", t_real, .addr.real = &gpsdata->attitude.roll,
328 .dflt.real = NAN},
329 {"roll_st", t_character, .addr.character = &gpsdata->attitude.roll_st},
330 {"yaw", t_real, .addr.real = &gpsdata->attitude.yaw,
331 .dflt.real = NAN},
332 {"yaw_st", t_character, .addr.character = &gpsdata->attitude.yaw_st},
333
334 {"dip", t_real, .addr.real = &gpsdata->attitude.dip,
335 .dflt.real = NAN},
336 {"mag_len", t_real, .addr.real = &gpsdata->attitude.mag_len,
337 .dflt.real = NAN},
338 {"mag_x", t_real, .addr.real = &gpsdata->attitude.mag_x,
339 .dflt.real = NAN},
340 {"mag_y", t_real, .addr.real = &gpsdata->attitude.mag_y,
341 .dflt.real = NAN},
342 {"mag_z", t_real, .addr.real = &gpsdata->attitude.mag_z,
343 .dflt.real = NAN},
344 {"acc_len", t_real, .addr.real = &gpsdata->attitude.acc_len,
345 .dflt.real = NAN},
346 {"acc_x", t_real, .addr.real = &gpsdata->attitude.acc_x,
347 .dflt.real = NAN},
348 {"acc_y", t_real, .addr.real = &gpsdata->attitude.acc_y,
349 .dflt.real = NAN},
350 {"acc_z", t_real, .addr.real = &gpsdata->attitude.acc_z,
351 .dflt.real = NAN},
352 {"gyro_x", t_real, .addr.real = &gpsdata->attitude.gyro_x,
353 .dflt.real = NAN},
354 {"gyro_y", t_real, .addr.real = &gpsdata->attitude.gyro_y,
355 .dflt.real = NAN},
356
357 {"temp", t_real, .addr.real = &gpsdata->attitude.temp,
358 .dflt.real = NAN},
359 {"depth", t_real, .addr.real = &gpsdata->attitude.depth,
360 .dflt.real = NAN},
361 {NULL},
362 /* *INDENT-ON* */
363 };
364
365 return json_read_object(buf, json_attrs_1, endptr);
366 }
367
json_devicelist_read(const char * buf,struct gps_data_t * gpsdata,const char ** endptr)368 static int json_devicelist_read(const char *buf, struct gps_data_t *gpsdata,
369 const char **endptr)
370 {
371 const struct json_attr_t json_attrs_subdevices[] = {
372 /* *INDENT-OFF* */
373 {"class", t_check, .dflt.check = "DEVICE"},
374 {"path", t_string, STRUCTOBJECT(struct devconfig_t, path),
375 .len = sizeof(gpsdata->devices.list[0].path)},
376 {"activated", t_time, STRUCTOBJECT(struct devconfig_t, activated)},
377 {"activated", t_real, STRUCTOBJECT(struct devconfig_t, activated)},
378 {"flags", t_integer, STRUCTOBJECT(struct devconfig_t, flags)},
379 {"driver", t_string, STRUCTOBJECT(struct devconfig_t, driver),
380 .len = sizeof(gpsdata->devices.list[0].driver)},
381 {"hexdata", t_string, STRUCTOBJECT(struct devconfig_t, hexdata),
382 .len = sizeof(gpsdata->devices.list[0].hexdata)},
383 {"subtype", t_string, STRUCTOBJECT(struct devconfig_t, subtype),
384 .len = sizeof(gpsdata->devices.list[0].subtype)},
385 {"subtype1", t_string, STRUCTOBJECT(struct devconfig_t, subtype1),
386 .len = sizeof(gpsdata->devices.list[0].subtype1)},
387 {"native", t_integer, STRUCTOBJECT(struct devconfig_t, driver_mode),
388 .dflt.integer = -1},
389 {"bps", t_uinteger, STRUCTOBJECT(struct devconfig_t, baudrate),
390 .dflt.uinteger = DEVDEFAULT_BPS},
391 {"parity", t_character, STRUCTOBJECT(struct devconfig_t, parity),
392 .dflt.character = DEVDEFAULT_PARITY},
393 {"stopbits", t_uinteger, STRUCTOBJECT(struct devconfig_t, stopbits),
394 .dflt.integer = DEVDEFAULT_STOPBITS},
395 {"cycle", t_real, STRUCTOBJECT(struct devconfig_t, cycle),
396 .dflt.real = NAN},
397 {"mincycle", t_real, STRUCTOBJECT(struct devconfig_t, mincycle),
398 .dflt.real = NAN},
399 // ignore unkown keys, for cross-version compatibility
400 {"", t_ignore},
401 {NULL},
402 /* *INDENT-ON* */
403 };
404 const struct json_attr_t json_attrs_devices[] = {
405 {"class", t_check,.dflt.check = "DEVICES"},
406 {"devices", t_array, STRUCTARRAY(gpsdata->devices.list,
407 json_attrs_subdevices,
408 &gpsdata->devices.ndevices)},
409 {NULL},
410 };
411 int status;
412
413 memset(&gpsdata->devices, 0, sizeof(gpsdata->devices));
414 status = json_read_object(buf, json_attrs_devices, endptr);
415 if (status != 0) {
416 return status;
417 }
418
419 (void)clock_gettime(CLOCK_REALTIME, &gpsdata->devices.time);
420 return 0;
421 }
422
json_version_read(const char * buf,struct gps_data_t * gpsdata,const char ** endptr)423 static int json_version_read(const char *buf, struct gps_data_t *gpsdata,
424 const char **endptr)
425 {
426 const struct json_attr_t json_attrs_version[] = {
427 /* *INDENT-OFF* */
428 {"class", t_check, .dflt.check = "VERSION"},
429 {"release", t_string, .addr.string = gpsdata->version.release,
430 .len = sizeof(gpsdata->version.release)},
431 {"rev", t_string, .addr.string = gpsdata->version.rev,
432 .len = sizeof(gpsdata->version.rev)},
433 {"proto_major", t_integer, .addr.integer = &gpsdata->version.proto_major},
434 {"proto_minor", t_integer, .addr.integer = &gpsdata->version.proto_minor},
435 {"remote", t_string, .addr.string = gpsdata->version.remote,
436 .len = sizeof(gpsdata->version.remote)},
437 {NULL},
438 /* *INDENT-ON* */
439 };
440 int status;
441
442 memset(&gpsdata->version, 0, sizeof(gpsdata->version));
443 status = json_read_object(buf, json_attrs_version, endptr);
444
445 return status;
446 }
447
json_error_read(const char * buf,struct gps_data_t * gpsdata,const char ** endptr)448 static int json_error_read(const char *buf, struct gps_data_t *gpsdata,
449 const char **endptr)
450 {
451 const struct json_attr_t json_attrs_error[] = {
452 /* *INDENT-OFF* */
453 {"class", t_check, .dflt.check = "ERROR"},
454 {"message", t_string, .addr.string = gpsdata->error,
455 .len = sizeof(gpsdata->error)},
456 {NULL},
457 /* *INDENT-ON* */
458 };
459 int status;
460
461 memset(&gpsdata->error, 0, sizeof(gpsdata->error));
462 status = json_read_object(buf, json_attrs_error, endptr);
463 if (status != 0)
464 return status;
465
466 return status;
467 }
468
json_toff_read(const char * buf,struct gps_data_t * gpsdata,const char ** endptr)469 int json_toff_read(const char *buf, struct gps_data_t *gpsdata,
470 const char **endptr)
471 {
472 int real_sec = 0, real_nsec = 0, clock_sec = 0, clock_nsec = 0;
473 const struct json_attr_t json_attrs_toff[] = {
474 /* *INDENT-OFF* */
475 {"class", t_check, .dflt.check = "TOFF"},
476 {"device", t_string, .addr.string = gpsdata->dev.path,
477 .len = sizeof(gpsdata->dev.path)},
478 {"real_sec", t_integer, .addr.integer = &real_sec,
479 .dflt.integer = 0},
480 {"real_nsec", t_integer, .addr.integer = &real_nsec,
481 .dflt.integer = 0},
482 {"clock_sec", t_integer, .addr.integer = &clock_sec,
483 .dflt.integer = 0},
484 {"clock_nsec",t_integer, .addr.integer = &clock_nsec,
485 .dflt.integer = 0},
486 {NULL},
487 /* *INDENT-ON* */
488 };
489 int status;
490
491 memset(&gpsdata->toff, 0, sizeof(gpsdata->toff));
492 status = json_read_object(buf, json_attrs_toff, endptr);
493 gpsdata->toff.real.tv_sec = (time_t)real_sec;
494 gpsdata->toff.real.tv_nsec = (long)real_nsec;
495 gpsdata->toff.clock.tv_sec = (time_t)clock_sec;
496 gpsdata->toff.clock.tv_nsec = (long)clock_nsec;
497 if (status != 0)
498 return status;
499
500 return status;
501 }
502
json_pps_read(const char * buf,struct gps_data_t * gpsdata,const char ** endptr)503 int json_pps_read(const char *buf, struct gps_data_t *gpsdata,
504 const char **endptr)
505 {
506 int real_sec = 0, real_nsec = 0, clock_sec = 0, clock_nsec = 0, precision=0;
507 int qErr = 0;
508
509 const struct json_attr_t json_attrs_pps[] = {
510 /* *INDENT-OFF* */
511 {"class", t_check, .dflt.check = "PPS"},
512 {"device", t_string, .addr.string = gpsdata->dev.path,
513 .len = sizeof(gpsdata->dev.path)},
514 {"real_sec", t_integer, .addr.integer = &real_sec,
515 .dflt.integer = 0},
516 {"real_nsec", t_integer, .addr.integer = &real_nsec,
517 .dflt.integer = 0},
518 {"clock_sec", t_integer, .addr.integer = &clock_sec,
519 .dflt.integer = 0},
520 {"clock_nsec",t_integer, .addr.integer = &clock_nsec,
521 .dflt.integer = 0},
522 {"precision", t_integer, .addr.integer = &precision,
523 .dflt.integer = 0},
524 {"qErr", t_integer, .addr.integer = &qErr,
525 .dflt.integer = 0},
526 {NULL},
527 /* *INDENT-ON* */
528 };
529 int status;
530
531 memset(&gpsdata->pps, 0, sizeof(gpsdata->pps));
532 status = json_read_object(buf, json_attrs_pps, endptr);
533
534 /* This is good until GPS are more than nanosec accurate */
535 gpsdata->pps.real.tv_sec = (time_t)real_sec;
536 gpsdata->pps.real.tv_nsec = (long)real_nsec;
537 gpsdata->pps.clock.tv_sec = (time_t)clock_sec;
538 gpsdata->pps.clock.tv_nsec = (long)clock_nsec;
539 // hope qErr fits in int
540 gpsdata->qErr = (long)qErr;
541
542 /* FIXME: precision is currently parsed but discarded */
543 return status;
544 }
545
json_oscillator_read(const char * buf,struct gps_data_t * gpsdata,const char ** endptr)546 int json_oscillator_read(const char *buf, struct gps_data_t *gpsdata,
547 const char **endptr)
548 {
549 bool running = false, reference = false, disciplined = false;
550 int delta = 0;
551 const struct json_attr_t json_attrs_osc[] = {
552 /* *INDENT-OFF* */
553 {"class", t_check, .dflt.check = "OSC"},
554 {"device", t_string, .addr.string = gpsdata->dev.path,
555 .len = sizeof(gpsdata->dev.path)},
556 {"running", t_boolean, .addr.boolean = &running,
557 .dflt.boolean = false},
558 {"reference", t_boolean, .addr.boolean = &reference,
559 .dflt.boolean = false},
560 {"disciplined", t_boolean, .addr.boolean = &disciplined,
561 .dflt.boolean = false},
562 {"delta", t_integer, .addr.integer = &delta,
563 .dflt.integer = 0},
564 {NULL},
565 /* *INDENT-ON* */
566 };
567 int status;
568
569 memset(&gpsdata->osc, 0, sizeof(gpsdata->osc));
570 status = json_read_object(buf, json_attrs_osc, endptr);
571
572 gpsdata->osc.running = running;
573 gpsdata->osc.reference = reference;
574 gpsdata->osc.disciplined = disciplined;
575 gpsdata->osc.delta = delta;
576
577 return status;
578 }
579
580 // Test for JSON read status values that should be treated as a go-ahead
581 // for further processing. JSON_BADATTR - to allow JSON attributes uknown
582 // to this version of the library, for forward compatibility, is an obvious
583 // thing to go here.
584 #define PASS(n) (((n) == 0) || ((n) == JSON_ERR_BADATTR))
585 #define FILTER(n) ((n) == JSON_ERR_BADATTR ? 0 : n)
586
libgps_json_unpack(const char * buf,struct gps_data_t * gpsdata,const char ** end)587 int libgps_json_unpack(const char *buf,
588 struct gps_data_t *gpsdata, const char **end)
589 /* the only entry point - unpack a JSON object into gpsdata_t substructures */
590 {
591 int status;
592 char *classtag = strstr(buf, "\"class\":");
593
594 if (classtag == NULL)
595 return -1;
596 if (str_starts_with(classtag, "\"class\":\"TPV\"")) {
597 status = json_tpv_read(buf, gpsdata, end);
598 gpsdata->set = STATUS_SET;
599 if (0 != gpsdata->fix.time.tv_sec)
600 gpsdata->set |= TIME_SET;
601 if (isfinite(gpsdata->fix.ept) != 0)
602 gpsdata->set |= TIMERR_SET;
603 if (isfinite(gpsdata->fix.longitude) != 0)
604 gpsdata->set |= LATLON_SET;
605 if (0 != isfinite(gpsdata->fix.altitude) ||
606 0 != isfinite(gpsdata->fix.altHAE) ||
607 0 != isfinite(gpsdata->fix.depth) ||
608 0 != isfinite(gpsdata->fix.altMSL)) {
609 gpsdata->set |= ALTITUDE_SET;
610 }
611 if (isfinite(gpsdata->fix.epx) != 0 && isfinite(gpsdata->fix.epy) != 0)
612 gpsdata->set |= HERR_SET;
613 if (isfinite(gpsdata->fix.epv) != 0)
614 gpsdata->set |= VERR_SET;
615 if (isfinite(gpsdata->fix.track) != 0)
616 gpsdata->set |= TRACK_SET;
617 if (0 != isfinite(gpsdata->fix.magnetic_track) ||
618 0 != isfinite(gpsdata->fix.magnetic_var))
619 gpsdata->set |= MAGNETIC_TRACK_SET;
620 if (isfinite(gpsdata->fix.speed) != 0)
621 gpsdata->set |= SPEED_SET;
622 if (isfinite(gpsdata->fix.climb) != 0)
623 gpsdata->set |= CLIMB_SET;
624 if (isfinite(gpsdata->fix.epd) != 0)
625 gpsdata->set |= TRACKERR_SET;
626 if (isfinite(gpsdata->fix.eps) != 0)
627 gpsdata->set |= SPEEDERR_SET;
628 if (isfinite(gpsdata->fix.epc) != 0)
629 gpsdata->set |= CLIMBERR_SET;
630 if (gpsdata->fix.mode != MODE_NOT_SEEN)
631 gpsdata->set |= MODE_SET;
632 return FILTER(status);
633 } else if (str_starts_with(classtag, "\"class\":\"GST\"")) {
634 status = json_noise_read(buf, gpsdata, end);
635 if (PASS(status)) {
636 gpsdata->set &= ~UNION_SET;
637 gpsdata->set |= GST_SET;
638 }
639 return FILTER(status);
640 } else if (str_starts_with(classtag, "\"class\":\"SKY\"")) {
641 status = json_sky_read(buf, gpsdata, end);
642 if (PASS(status))
643 gpsdata->set |= SATELLITE_SET;
644 return FILTER(status);
645 } else if (str_starts_with(classtag, "\"class\":\"ATT\"")) {
646 status = json_att_read(buf, gpsdata, end);
647 if (PASS(status)) {
648 gpsdata->set &= ~UNION_SET;
649 gpsdata->set |= ATTITUDE_SET;
650 }
651 return FILTER(status);
652 } else if (str_starts_with(classtag, "\"class\":\"DEVICES\"")) {
653 status = json_devicelist_read(buf, gpsdata, end);
654 if (PASS(status)) {
655 gpsdata->set &= ~UNION_SET;
656 gpsdata->set |= DEVICELIST_SET;
657 }
658 return FILTER(status);
659 } else if (str_starts_with(classtag, "\"class\":\"DEVICE\"")) {
660 status = json_device_read(buf, &gpsdata->dev, end);
661 if (PASS(status))
662 gpsdata->set |= DEVICE_SET;
663 return FILTER(status);
664 } else if (str_starts_with(classtag, "\"class\":\"WATCH\"")) {
665 status = json_watch_read(buf, &gpsdata->policy, end);
666 if (PASS(status)) {
667 gpsdata->set &= ~UNION_SET;
668 gpsdata->set |= POLICY_SET;
669 }
670 return FILTER(status);
671 } else if (str_starts_with(classtag, "\"class\":\"VERSION\"")) {
672 status = json_version_read(buf, gpsdata, end);
673 if (status == 0) {
674 gpsdata->set &= ~UNION_SET;
675 gpsdata->set |= VERSION_SET;
676 }
677 return FILTER(status);
678 #ifdef RTCM104V2_ENABLE
679 } else if (str_starts_with(classtag, "\"class\":\"RTCM2\"")) {
680 status = json_rtcm2_read(buf,
681 gpsdata->dev.path, sizeof(gpsdata->dev.path),
682 &gpsdata->rtcm2, end);
683 if (PASS(status)) {
684 gpsdata->set &= ~UNION_SET;
685 gpsdata->set |= RTCM2_SET;
686 }
687 return FILTER(status);
688 #endif /* RTCM104V2_ENABLE */
689 #ifdef RTCM104V3_ENABLE
690 } else if (str_starts_with(classtag, "\"class\":\"RTCM3\"")) {
691 status = json_rtcm3_read(buf,
692 gpsdata->dev.path, sizeof(gpsdata->dev.path),
693 &gpsdata->rtcm3, end);
694 if (PASS(status)) {
695 gpsdata->set &= ~UNION_SET;
696 gpsdata->set |= RTCM3_SET;
697 }
698 return FILTER(status);
699 #endif /* RTCM104V3_ENABLE */
700 #ifdef AIVDM_ENABLE
701 } else if (str_starts_with(classtag, "\"class\":\"AIS\"")) {
702 status = json_ais_read(buf,
703 gpsdata->dev.path, sizeof(gpsdata->dev.path),
704 &gpsdata->ais, end);
705 if (PASS(status)) {
706 gpsdata->set &= ~UNION_SET;
707 gpsdata->set |= AIS_SET;
708 }
709 return FILTER(status);
710 #endif /* AIVDM_ENABLE */
711 } else if (str_starts_with(classtag, "\"class\":\"ERROR\"")) {
712 status = json_error_read(buf, gpsdata, end);
713 if (PASS(status)) {
714 gpsdata->set &= ~UNION_SET;
715 gpsdata->set |= ERROR_SET;
716 }
717 return FILTER(status);
718 } else if (str_starts_with(classtag, "\"class\":\"TOFF\"")) {
719 status = json_pps_read(buf, gpsdata, end);
720 if (PASS(status)) {
721 gpsdata->set &= ~UNION_SET;
722 gpsdata->set |= TOFF_SET;
723 }
724 return FILTER(status);
725 } else if (str_starts_with(classtag, "\"class\":\"PPS\"")) {
726 status = json_pps_read(buf, gpsdata, end);
727 if (PASS(status)) {
728 gpsdata->set &= ~UNION_SET;
729 gpsdata->set |= PPS_SET;
730 }
731 return FILTER(status);
732 } else if (str_starts_with(classtag, "\"class\":\"OSC\"")) {
733 status = json_oscillator_read(buf, gpsdata, end);
734 if (PASS(status)) {
735 gpsdata->set &= ~UNION_SET;
736 gpsdata->set |= OSCILLATOR_SET;
737 }
738 return FILTER(status);
739 } else if (str_starts_with(classtag, "\"class\":\"RAW\"")) {
740 status = json_raw_read(buf, gpsdata, end);
741 if (PASS(status)) {
742 gpsdata->set &= ~UNION_SET;
743 gpsdata->set |= RAW_SET;
744 }
745 return FILTER(status);
746 } else
747 return -1;
748 }
749
750
751 #endif /* SOCKET_EXPORT_ENABLE */
752
753 /* libgps_json.c ends here */
754