/src/gpsd/gpsd-3.27.6~dev/libgps/libgps_json.c
Line | Count | Source |
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 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 or double is valid |
20 | | */ |
21 | | |
22 | | #include "../include/gpsd_config.h" // must be before all includes |
23 | | |
24 | | #include <assert.h> // for assert() :-( |
25 | | #include <math.h> |
26 | | #include <stdbool.h> |
27 | | #include <stddef.h> |
28 | | #include <string.h> |
29 | | |
30 | | #include "../include/gpsd.h" |
31 | | #include "../include/strfuncs.h" |
32 | | #include "../include/gps_json.h" |
33 | | #include "../include/timespec.h" |
34 | | |
35 | | static int json_tpv_read(const char *buf, struct gps_data_t *gpsdata, |
36 | | const char **endptr) |
37 | 425 | { |
38 | 425 | int ret; |
39 | | |
40 | 425 | const struct json_attr_t json_attrs_1[] = { |
41 | | // *INDENT-OFF* |
42 | 425 | {"class", t_check, .dflt.check = "TPV"}, |
43 | 425 | {"alt", t_real, .addr.real = &gpsdata->fix.altitude, |
44 | 425 | .dflt.real = NAN}, // DEPRECATED, undefined |
45 | 425 | {"altHAE", t_real, .addr.real = &gpsdata->fix.altHAE, |
46 | 425 | .dflt.real = NAN}, |
47 | 425 | {"altMSL", t_real, .addr.real = &gpsdata->fix.altMSL, |
48 | 425 | .dflt.real = NAN}, |
49 | 425 | {"ant", t_integer, .addr.integer = &gpsdata->fix.ant_stat, |
50 | 425 | .dflt.integer = 0}, |
51 | 425 | {"antPwr", t_integer, .addr.integer = &gpsdata->fix.ant_power, |
52 | 425 | .dflt.integer = 0}, |
53 | 425 | {"baseS", t_integer, .addr.integer = &gpsdata->fix.base.status, |
54 | 425 | .dflt.integer = STATUS_UNK}, // aka zero |
55 | 425 | {"baseE", t_real, .addr.real = &gpsdata->fix.base.east, |
56 | 425 | .dflt.real = NAN}, |
57 | 425 | {"baseN", t_real, .addr.real = &gpsdata->fix.base.north, |
58 | 425 | .dflt.real = NAN}, |
59 | 425 | {"baseU", t_real, .addr.real = &gpsdata->fix.base.up, |
60 | 425 | .dflt.real = NAN}, |
61 | 425 | {"baseL", t_real, .addr.real = &gpsdata->fix.base.length, |
62 | 425 | .dflt.real = NAN}, |
63 | 425 | {"baseC", t_real, .addr.real = &gpsdata->fix.base.course, |
64 | 425 | .dflt.real = NAN}, |
65 | 425 | {"climb", t_real, .addr.real = &gpsdata->fix.climb, |
66 | 425 | .dflt.real = NAN}, |
67 | 425 | {"clockbias", t_longint, .addr.longint = &gpsdata->fix.clockbias, |
68 | 425 | .dflt.longint = 0}, |
69 | 425 | {"clockdrift", t_longint, .addr.longint = &gpsdata->fix.clockdrift, |
70 | 425 | .dflt.longint = 0}, |
71 | 425 | {"datum", t_string, .addr.string = gpsdata->fix.datum, |
72 | 425 | .len = sizeof(gpsdata->fix.datum)}, |
73 | 425 | {"device", t_string, .addr.string = gpsdata->dev.path, |
74 | 425 | .len = sizeof(gpsdata->dev.path)}, |
75 | 425 | {"depth", t_real, .addr.real = &gpsdata->fix.depth, |
76 | 425 | .dflt.real = NAN}, |
77 | 425 | {"dgpsAge", t_real, .addr.real = &gpsdata->fix.dgps_age, |
78 | 425 | .dflt.real = NAN}, |
79 | 425 | {"dgpsRatio", t_real, .addr.real = &gpsdata->fix.base.ratio, |
80 | 425 | .dflt.real = NAN}, |
81 | 425 | {"dgpsSta", t_integer, .addr.integer = &gpsdata->fix.dgps_station, |
82 | 425 | .dflt.integer = -1}, |
83 | 425 | {"ecefx", t_real, .addr.real = &gpsdata->fix.ecef.x, |
84 | 425 | .dflt.real = NAN}, |
85 | 425 | {"ecefy", t_real, .addr.real = &gpsdata->fix.ecef.y, |
86 | 425 | .dflt.real = NAN}, |
87 | 425 | {"ecefz", t_real, .addr.real = &gpsdata->fix.ecef.z, |
88 | 425 | .dflt.real = NAN}, |
89 | 425 | {"ecefvx", t_real, .addr.real = &gpsdata->fix.ecef.vx, |
90 | 425 | .dflt.real = NAN}, |
91 | 425 | {"ecefvy", t_real, .addr.real = &gpsdata->fix.ecef.vy, |
92 | 425 | .dflt.real = NAN}, |
93 | 425 | {"ecefvz", t_real, .addr.real = &gpsdata->fix.ecef.vz, |
94 | 425 | .dflt.real = NAN}, |
95 | 425 | {"ecefpAcc", t_real, .addr.real = &gpsdata->fix.ecef.pAcc, |
96 | 425 | .dflt.real = NAN}, |
97 | 425 | {"ecefvAcc", t_real, .addr.real = &gpsdata->fix.ecef.vAcc, |
98 | 425 | .dflt.real = NAN}, |
99 | 425 | {"epc", t_real, .addr.real = &gpsdata->fix.epc, |
100 | 425 | .dflt.real = NAN}, |
101 | 425 | {"epd", t_real, .addr.real = &gpsdata->fix.epd, |
102 | 425 | .dflt.real = NAN}, |
103 | 425 | {"eph", t_real, .addr.real = &gpsdata->fix.eph, |
104 | 425 | .dflt.real = NAN}, |
105 | 425 | {"eps", t_real, .addr.real = &gpsdata->fix.eps, |
106 | 425 | .dflt.real = NAN}, |
107 | 425 | {"ept", t_real, .addr.real = &gpsdata->fix.ept, |
108 | 425 | .dflt.real = NAN}, |
109 | 425 | {"epx", t_real, .addr.real = &gpsdata->fix.epx, |
110 | 425 | .dflt.real = NAN}, |
111 | 425 | {"epy", t_real, .addr.real = &gpsdata->fix.epy, |
112 | 425 | .dflt.real = NAN}, |
113 | 425 | {"epv", t_real, .addr.real = &gpsdata->fix.epv, |
114 | 425 | .dflt.real = NAN}, |
115 | 425 | {"geoidSep", t_real, .addr.real = &gpsdata->fix.geoid_sep, |
116 | 425 | .dflt.real = NAN}, |
117 | 425 | {"lat", t_real, .addr.real = &gpsdata->fix.latitude, |
118 | 425 | .dflt.real = NAN}, |
119 | 425 | {"jam", t_integer, .addr.integer = &gpsdata->fix.jam, |
120 | 425 | .dflt.integer = -1}, |
121 | 425 | {"leapseconds", t_integer, .addr.integer = &gpsdata->leap_seconds, |
122 | 425 | .dflt.integer = 0}, |
123 | 425 | {"lon", t_real, .addr.real = &gpsdata->fix.longitude, |
124 | 425 | .dflt.real = NAN}, |
125 | 425 | {"magtrack", t_real, .addr.real = &gpsdata->fix.magnetic_track, |
126 | 425 | .dflt.real = NAN}, |
127 | 425 | {"magvar", t_real, .addr.real = &gpsdata->fix.magnetic_var, |
128 | 425 | .dflt.real = NAN}, |
129 | 425 | {"mode", t_integer, .addr.integer = &gpsdata->fix.mode, |
130 | 425 | .dflt.integer = MODE_NOT_SEEN}, |
131 | 425 | {"relD", t_real, .addr.real = &gpsdata->fix.NED.relPosD, |
132 | 425 | .dflt.real = NAN}, |
133 | 425 | {"relE", t_real, .addr.real = &gpsdata->fix.NED.relPosE, |
134 | 425 | .dflt.real = NAN}, |
135 | 425 | {"relN", t_real, .addr.real = &gpsdata->fix.NED.relPosN, |
136 | 425 | .dflt.real = NAN}, |
137 | 425 | {"relH", t_real, .addr.real = &gpsdata->fix.NED.relPosH, |
138 | 425 | .dflt.real = NAN}, |
139 | 425 | {"relL", t_real, .addr.real = &gpsdata->fix.NED.relPosL, |
140 | 425 | .dflt.real = NAN}, |
141 | 425 | {"temp", t_real, .addr.real = &gpsdata->fix.temp, |
142 | 425 | .dflt.real = NAN}, |
143 | 425 | {"time", t_time, .addr.ts = &gpsdata->fix.time, |
144 | 425 | .dflt.ts = {0, 0}}, |
145 | 425 | {"track", t_real, .addr.real = &gpsdata->fix.track, |
146 | 425 | .dflt.real = NAN}, |
147 | 425 | {"sep", t_real, .addr.real = &gpsdata->fix.sep, |
148 | 425 | .dflt.real = NAN}, |
149 | 425 | {"speed", t_real, .addr.real = &gpsdata->fix.speed, |
150 | 425 | .dflt.real = NAN}, |
151 | 425 | {"status", t_integer, .addr.integer = &gpsdata->fix.status, |
152 | 425 | .dflt.integer = STATUS_UNK}, |
153 | 425 | {"velD", t_real, .addr.real = &gpsdata->fix.NED.velD, |
154 | 425 | .dflt.real = NAN}, |
155 | 425 | {"velE", t_real, .addr.real = &gpsdata->fix.NED.velE, |
156 | 425 | .dflt.real = NAN}, |
157 | 425 | {"velN", t_real, .addr.real = &gpsdata->fix.NED.velN, |
158 | 425 | .dflt.real = NAN}, |
159 | 425 | {"wanglem", t_real, .addr.real = &gpsdata->fix.wanglem, |
160 | 425 | .dflt.real = NAN}, |
161 | 425 | {"wangler", t_real, .addr.real = &gpsdata->fix.wangler, |
162 | 425 | .dflt.real = NAN}, |
163 | 425 | {"wanglet", t_real, .addr.real = &gpsdata->fix.wanglet, |
164 | 425 | .dflt.real = NAN}, |
165 | 425 | {"wspeedr", t_real, .addr.real = &gpsdata->fix.wspeedr, |
166 | 425 | .dflt.real = NAN}, |
167 | 425 | {"wspeedt", t_real, .addr.real = &gpsdata->fix.wspeedt, |
168 | 425 | .dflt.real = NAN}, |
169 | 425 | {"wtemp", t_real, .addr.real = &gpsdata->fix.wtemp, |
170 | 425 | .dflt.real = NAN}, |
171 | | // ignore unknown keys, for cross-version compatibility |
172 | 425 | {"", t_ignore}, |
173 | | |
174 | 425 | {NULL}, |
175 | | // *INDENT-ON* |
176 | 425 | }; |
177 | | |
178 | 425 | ret = json_read_object(buf, json_attrs_1, endptr); |
179 | 425 | return ret; |
180 | 425 | } |
181 | | |
182 | | static int json_noise_read(const char *buf, struct gps_data_t *gpsdata, |
183 | | const char **endptr) |
184 | 314 | { |
185 | 314 | int ret; |
186 | | |
187 | 314 | const struct json_attr_t json_attrs_1[] = { |
188 | | // *INDENT-OFF* |
189 | 314 | {"class", t_check, .dflt.check = "GST"}, |
190 | 314 | {"device", t_string, .addr.string = gpsdata->dev.path, |
191 | 314 | .len = sizeof(gpsdata->dev.path)}, |
192 | 314 | {"time", t_time, .addr.ts = &gpsdata->gst.utctime, |
193 | 314 | .dflt.ts = {0, 0}}, |
194 | 314 | {"alt", t_real, .addr.real = &gpsdata->gst.alt_err_deviation, |
195 | 314 | .dflt.real = NAN}, |
196 | 314 | {"lat", t_real, .addr.real = &gpsdata->gst.lat_err_deviation, |
197 | 314 | .dflt.real = NAN}, |
198 | 314 | {"lon", t_real, .addr.real = &gpsdata->gst.lon_err_deviation, |
199 | 314 | .dflt.real = NAN}, |
200 | 314 | {"major", t_real, .addr.real = &gpsdata->gst.smajor_deviation, |
201 | 314 | .dflt.real = NAN}, |
202 | 314 | {"minor", t_real, .addr.real = &gpsdata->gst.sminor_deviation, |
203 | 314 | .dflt.real = NAN}, |
204 | 314 | {"orient", t_real, .addr.real = &gpsdata->gst.smajor_orientation, |
205 | 314 | .dflt.real = NAN}, |
206 | 314 | {"rms", t_real, .addr.real = &gpsdata->gst.rms_deviation, |
207 | 314 | .dflt.real = NAN}, |
208 | 314 | {"ve", t_real, .addr.real = &gpsdata->gst.ve_err_deviation, |
209 | 314 | .dflt.real = NAN}, |
210 | 314 | {"vn", t_real, .addr.real = &gpsdata->gst.vn_err_deviation, |
211 | 314 | .dflt.real = NAN}, |
212 | 314 | {"vu", t_real, .addr.real = &gpsdata->gst.vu_err_deviation, |
213 | 314 | .dflt.real = NAN}, |
214 | | // ignore unknown keys, for cross-version compatibility |
215 | 314 | {"", t_ignore}, |
216 | 314 | {NULL}, |
217 | | // *INDENT-ON* |
218 | 314 | }; |
219 | | |
220 | 314 | ret = json_read_object(buf, json_attrs_1, endptr); |
221 | | |
222 | 314 | return ret; |
223 | 314 | } |
224 | | |
225 | | // decode a RAW messages into gpsdata.raw |
226 | | static int json_raw_read(const char *buf, struct gps_data_t *gpsdata, |
227 | | const char **endptr) |
228 | 132 | { |
229 | 132 | int measurements; |
230 | | // initialized to shut up clang |
231 | 132 | double mtime_s = 0.0, mtime_ns = 0.0; |
232 | | |
233 | 132 | const struct json_attr_t json_attrs_meas[] = { |
234 | | // *INDENT-OFF* |
235 | 132 | {"gnssid", t_ubyte, STRUCTOBJECT(struct meas_t, gnssid)}, |
236 | 132 | {"svid", t_ubyte, STRUCTOBJECT(struct meas_t, svid)}, |
237 | 132 | {"sigid", t_ubyte, STRUCTOBJECT(struct meas_t, sigid), |
238 | 132 | .dflt.ubyte = 0}, |
239 | 132 | {"snr", t_ubyte, STRUCTOBJECT(struct meas_t, snr)}, |
240 | 132 | {"freqid", t_ubyte, STRUCTOBJECT(struct meas_t, freqid), |
241 | 132 | .dflt.ubyte = 0}, |
242 | 132 | {"obs", t_string, STRUCTOBJECT(struct meas_t, obs_code), |
243 | 132 | .len = sizeof(gpsdata->raw.meas[0].obs_code)}, |
244 | 132 | {"lli", t_ubyte, STRUCTOBJECT(struct meas_t, lli), |
245 | 132 | .dflt.ubyte = 0}, |
246 | 132 | {"locktime", t_uinteger, STRUCTOBJECT(struct meas_t, locktime), |
247 | 132 | .dflt.uinteger = 0}, |
248 | 132 | {"carrierphase", t_real, STRUCTOBJECT(struct meas_t, carrierphase), |
249 | 132 | .dflt.real = NAN}, |
250 | 132 | {"pseudorange", t_real, STRUCTOBJECT(struct meas_t, pseudorange), |
251 | 132 | .dflt.real = NAN}, |
252 | 132 | {"doppler", t_real, STRUCTOBJECT(struct meas_t, doppler), |
253 | 132 | .dflt.real = NAN}, |
254 | 132 | {"c2c", t_real, STRUCTOBJECT(struct meas_t, c2c), |
255 | 132 | .dflt.real = NAN}, |
256 | 132 | {"l2c", t_real, STRUCTOBJECT(struct meas_t, l2c), |
257 | 132 | .dflt.real = NAN}, |
258 | | // ignore unknown keys, for cross-version compatibility |
259 | 132 | {"", t_ignore}, |
260 | | // *INDENT-ON* |
261 | 132 | {NULL}, |
262 | 132 | }; |
263 | 132 | const struct json_attr_t json_attrs_raw[] = { |
264 | | // *INDENT-OFF* |
265 | 132 | {"class", t_check, .dflt.check = "RAW"}, |
266 | 132 | {"device", t_string, .addr.string = gpsdata->dev.path, |
267 | 132 | .len = sizeof(gpsdata->dev.path)}, |
268 | 132 | {"time", t_real, .addr.real = &mtime_s, |
269 | 132 | .dflt.real = NAN}, |
270 | 132 | {"nsec", t_real, .addr.real = &mtime_ns, |
271 | 132 | .dflt.real = NAN}, |
272 | 132 | {"rawdata", t_array, STRUCTARRAY(gpsdata->raw.meas, |
273 | 132 | json_attrs_meas, &measurements)}, |
274 | | // ignore unknown keys, for cross-version compatibility |
275 | 132 | {"", t_ignore}, |
276 | 132 | {NULL}, |
277 | | // *INDENT-ON* |
278 | 132 | }; |
279 | 132 | int status; |
280 | | |
281 | 132 | memset(&gpsdata->raw, 0, sizeof(gpsdata->raw)); |
282 | | |
283 | 132 | status = json_read_object(buf, json_attrs_raw, endptr); |
284 | 132 | if (0 != status) { |
285 | 111 | return status; |
286 | 111 | } |
287 | 21 | gpsdata->set |= RAW_SET; |
288 | 21 | if (0 == isfinite(mtime_s) || |
289 | 20 | 0 == isfinite(mtime_ns)) { |
290 | 20 | return status; |
291 | 20 | } |
292 | 1 | gpsdata->raw.mtime.tv_sec = (time_t)mtime_s; |
293 | 1 | gpsdata->raw.mtime.tv_nsec = (long)mtime_ns; |
294 | | |
295 | 1 | return 0; |
296 | 21 | } |
297 | | |
298 | | static int json_sky_read(const char *buf, struct gps_data_t *gpsdata, |
299 | | const char **endptr) |
300 | 187 | { |
301 | | |
302 | 187 | const struct json_attr_t json_attrs_satellites[] = { |
303 | | // *INDENT-OFF* |
304 | 187 | {"PRN", t_short, STRUCTOBJECT(struct satellite_t, PRN)}, |
305 | 187 | {"az", t_real, STRUCTOBJECT(struct satellite_t, azimuth), |
306 | 187 | .dflt.real = NAN}, |
307 | 187 | {"el", t_real, STRUCTOBJECT(struct satellite_t, elevation), |
308 | 187 | .dflt.real = NAN}, |
309 | 187 | {"freqid", t_byte, STRUCTOBJECT(struct satellite_t, freqid), |
310 | 187 | .dflt.byte = -1}, |
311 | 187 | {"gnssid", t_ubyte, STRUCTOBJECT(struct satellite_t, gnssid)}, |
312 | 187 | {"health", t_ubyte, STRUCTOBJECT(struct satellite_t, health), |
313 | 187 | .dflt.ubyte = SAT_HEALTH_UNK}, |
314 | 187 | {"pr", t_real, STRUCTOBJECT(struct satellite_t, pr), |
315 | 187 | .dflt.real = NAN}, |
316 | 187 | {"prRate", t_real, STRUCTOBJECT(struct satellite_t, prRate), |
317 | 187 | .dflt.real = NAN}, |
318 | 187 | {"prRes", t_real, STRUCTOBJECT(struct satellite_t, prRes), |
319 | 187 | .dflt.real = NAN}, |
320 | 187 | {"ss", t_real, STRUCTOBJECT(struct satellite_t, ss), |
321 | 187 | .dflt.real = NAN}, |
322 | 187 | {"sigid", t_ubyte, STRUCTOBJECT(struct satellite_t, sigid)}, |
323 | 187 | {"svid", t_ubyte, STRUCTOBJECT(struct satellite_t, svid)}, |
324 | 187 | {"used", t_boolean, STRUCTOBJECT(struct satellite_t, used)}, |
325 | | // ignore unknown keys, for cross-version compatibility |
326 | 187 | {"", t_ignore}, |
327 | | // *INDENT-ON* |
328 | 187 | {NULL}, |
329 | 187 | }; |
330 | | |
331 | 187 | int nSat = -1; // Use nSat only to know if sats are in SKY |
332 | | |
333 | 187 | const struct json_attr_t json_attrs_2[] = { |
334 | | // *INDENT-OFF* |
335 | 187 | {"class", t_check, .dflt.check = "SKY"}, |
336 | 187 | {"device", t_string, .addr.string = gpsdata->dev.path, |
337 | 187 | .len = sizeof(gpsdata->dev.path)}, |
338 | 187 | {"gdop", t_real, .addr.real = &gpsdata->dop.gdop, |
339 | 187 | .dflt.real = NAN}, |
340 | 187 | {"hdop", t_real, .addr.real = &gpsdata->dop.hdop, |
341 | 187 | .dflt.real = NAN}, |
342 | 187 | {"nSat", t_integer, .addr.integer = &nSat, |
343 | 187 | .dflt.integer = -1}, |
344 | 187 | {"pdop", t_real, .addr.real = &gpsdata->dop.pdop, |
345 | 187 | .dflt.real = NAN}, |
346 | 187 | {"tdop", t_real, .addr.real = &gpsdata->dop.tdop, |
347 | 187 | .dflt.real = NAN}, |
348 | 187 | {"vdop", t_real, .addr.real = &gpsdata->dop.vdop, |
349 | 187 | .dflt.real = NAN}, |
350 | 187 | {"xdop", t_real, .addr.real = &gpsdata->dop.xdop, |
351 | 187 | .dflt.real = NAN}, |
352 | 187 | {"ydop", t_real, .addr.real = &gpsdata->dop.ydop, |
353 | 187 | .dflt.real = NAN}, |
354 | 187 | {"satellites", t_array, |
355 | 187 | STRUCTARRAY(gpsdata->skyview, |
356 | 187 | json_attrs_satellites, |
357 | 187 | &gpsdata->satellites_visible)}, |
358 | 187 | {"time", t_time, .addr.ts = &gpsdata->skyview_time, |
359 | 187 | .dflt.ts = {0, 0}}, |
360 | 187 | {"uSat", t_integer, .addr.integer = &gpsdata->satellites_used, |
361 | 187 | .dflt.integer = 0}, |
362 | | // ignore unknown keys, for cross-version compatibility |
363 | 187 | {"", t_ignore}, |
364 | 187 | {NULL}, |
365 | | // *INDENT-ON* |
366 | 187 | }; |
367 | 187 | int status, i; |
368 | | |
369 | 187 | memset(&gpsdata->skyview, 0, sizeof(gpsdata->skyview)); |
370 | | |
371 | 187 | status = json_read_object(buf, json_attrs_2, endptr); |
372 | 187 | if (0 != status) { |
373 | 64 | return status; |
374 | 64 | } |
375 | | |
376 | 123 | if (1 == isfinite(gpsdata->dop.hdop) || |
377 | 122 | 1 == isfinite(gpsdata->dop.xdop) || |
378 | 121 | 1 == isfinite(gpsdata->dop.ydop) || |
379 | 120 | 1 == isfinite(gpsdata->dop.vdop) || |
380 | 119 | 1 == isfinite(gpsdata->dop.tdop) || |
381 | 118 | 1 == isfinite(gpsdata->dop.pdop) || |
382 | 117 | 1 == isfinite(gpsdata->dop.gdop)) { |
383 | | // got at least one DOP |
384 | 7 | gpsdata->set |= DOP_SET; |
385 | 7 | } |
386 | | |
387 | 123 | gpsdata->satellites_visible = 0; |
388 | | |
389 | 123 | if (-1 == nSat) { |
390 | | // no sats in the SKY, likely just dops. Maybe uSat |
391 | 17 | gpsdata->set &= ~SATELLITE_SET; |
392 | 17 | return 0; |
393 | 17 | } |
394 | 106 | gpsdata->satellites_used = 0; |
395 | | |
396 | 106 | gpsdata->set |= SATELLITE_SET; |
397 | | // recalculate used and visible, do not use nSat, uSat |
398 | 19.6k | for (i = 0; i < MAXCHANNELS; i++) { |
399 | 19.5k | if (0 < gpsdata->skyview[i].PRN) { |
400 | 1.30k | gpsdata->satellites_visible++; |
401 | 1.30k | } |
402 | 19.5k | if (gpsdata->skyview[i].used) { |
403 | 1.29k | gpsdata->satellites_used++; |
404 | 1.29k | } |
405 | 19.5k | } |
406 | | |
407 | 106 | return 0; |
408 | 123 | } |
409 | | |
410 | | // decode class ATT, almost the same as IMU |
411 | | static int json_att_read(const char *buf, struct gps_data_t *gpsdata, |
412 | | const char **endptr) |
413 | 70 | { |
414 | 70 | struct attitude_t *datap = &gpsdata->attitude; |
415 | | |
416 | 70 | const struct json_attr_t json_attrs_1[] = { |
417 | | // *INDENT-OFF* |
418 | 70 | {"class", t_check, .dflt.check = "ATT"}, |
419 | 70 | {"device", t_string, .addr.string = gpsdata->dev.path, |
420 | 70 | .len = sizeof(gpsdata->dev.path)}, |
421 | 70 | {"acc_len", t_real, .addr.real = &datap->acc_len, |
422 | 70 | .dflt.real = NAN}, |
423 | 70 | {"acc_x", t_real, .addr.real = &datap->acc_x, |
424 | 70 | .dflt.real = NAN}, |
425 | 70 | {"acc_y", t_real, .addr.real = &datap->acc_y, |
426 | 70 | .dflt.real = NAN}, |
427 | 70 | {"acc_z", t_real, .addr.real = &datap->acc_z, |
428 | 70 | .dflt.real = NAN}, |
429 | 70 | {"baseS", t_integer, .addr.integer = &datap->base.status, |
430 | 70 | .dflt.integer = STATUS_UNK}, // aka zero |
431 | 70 | {"baseE", t_real, .addr.real = &datap->base.east, |
432 | 70 | .dflt.real = NAN}, |
433 | 70 | {"baseN", t_real, .addr.real = &datap->base.north, |
434 | 70 | .dflt.real = NAN}, |
435 | 70 | {"baseU", t_real, .addr.real = &datap->base.up, |
436 | 70 | .dflt.real = NAN}, |
437 | 70 | {"baseL", t_real, .addr.real = &datap->base.length, |
438 | 70 | .dflt.real = NAN}, |
439 | 70 | {"baseC", t_real, .addr.real = &datap->base.course, |
440 | 70 | .dflt.real = NAN}, |
441 | 70 | {"dgpsRatio", t_real, .addr.real = &datap->base.ratio, |
442 | 70 | .dflt.real = NAN}, |
443 | 70 | {"depth", t_real, .addr.real = &datap->depth, |
444 | 70 | .dflt.real = NAN}, |
445 | 70 | {"dip", t_real, .addr.real = &datap->dip, |
446 | 70 | .dflt.real = NAN}, |
447 | 70 | {"gyro_temp", t_real, .addr.real = &datap->gyro_x, |
448 | 70 | .dflt.real = NAN}, |
449 | 70 | {"gyro_x", t_real, .addr.real = &datap->gyro_x, |
450 | 70 | .dflt.real = NAN}, |
451 | 70 | {"gyro_y", t_real, .addr.real = &datap->gyro_y, |
452 | 70 | .dflt.real = NAN}, |
453 | 70 | {"gyro_z", t_real, .addr.real = &datap->gyro_z, |
454 | 70 | .dflt.real = NAN}, |
455 | 70 | {"heading", t_real, .addr.real = &datap->heading, |
456 | 70 | .dflt.real = NAN}, |
457 | 70 | {"mag_len", t_real, .addr.real = &datap->mag_len, |
458 | 70 | .dflt.real = NAN}, |
459 | 70 | {"mag_st", t_character, .addr.character = &datap->mag_st}, |
460 | 70 | {"mag_x", t_real, .addr.real = &datap->mag_x, |
461 | 70 | .dflt.real = NAN}, |
462 | 70 | {"mag_y", t_real, .addr.real = &datap->mag_y, |
463 | 70 | .dflt.real = NAN}, |
464 | 70 | {"mag_z", t_real, .addr.real = &datap->mag_z, |
465 | 70 | .dflt.real = NAN}, |
466 | 70 | {"mheading", t_real, .addr.real = &datap->mheading, |
467 | 70 | .dflt.real = NAN}, |
468 | 70 | {"msg", t_string, .addr.string = datap->msg, |
469 | 70 | .len = sizeof(datap->msg)}, |
470 | 70 | {"pitch_st", t_character, .addr.character = &datap->pitch_st}, |
471 | 70 | {"pitch", t_real, .addr.real = &datap->pitch, |
472 | 70 | .dflt.real = NAN}, |
473 | 70 | {"roll_st", t_character, .addr.character = &datap->roll_st}, |
474 | 70 | {"roll", t_real, .addr.real = &datap->roll, |
475 | 70 | .dflt.real = NAN}, |
476 | 70 | {"temp", t_real, .addr.real = &datap->temp, |
477 | 70 | .dflt.real = NAN}, |
478 | 70 | {"time", t_time, .addr.ts = &datap->mtime, .dflt.ts = {0, 0}}, |
479 | 70 | {"timeTag", t_ulongint, .addr.ulongint = &datap->timeTag, |
480 | 70 | .dflt.ulongint = 0}, |
481 | 70 | {"yaw_st", t_character, .addr.character = &datap->yaw_st}, |
482 | 70 | {"yaw", t_real, .addr.real = &datap->yaw, .dflt.real = NAN}, |
483 | | |
484 | | // ignore unknown keys, for cross-version compatibility |
485 | 70 | {"", t_ignore}, |
486 | 70 | {NULL}, |
487 | | // *INDENT-ON* |
488 | 70 | }; |
489 | | |
490 | 70 | return json_read_object(buf, json_attrs_1, endptr); |
491 | 70 | } |
492 | | |
493 | | // decode class IMU, almost the ame as ATT |
494 | | static int json_imu_read(const char *buf, struct gps_data_t *gpsdata, |
495 | | const char **endptr) |
496 | 47 | { |
497 | | // the client only uses the first slot. |
498 | 47 | struct attitude_t *datap = &gpsdata->imu[0]; |
499 | | |
500 | 47 | const struct json_attr_t json_attrs_1[] = { |
501 | | // *INDENT-OFF* |
502 | 47 | {"class", t_check, .dflt.check = "IMU"}, |
503 | 47 | {"device", t_string, .addr.string = gpsdata->dev.path, |
504 | 47 | .len = sizeof(gpsdata->dev.path)}, |
505 | 47 | {"acc_len", t_real, .addr.real = &datap->acc_len, |
506 | 47 | .dflt.real = NAN}, |
507 | 47 | {"acc_x", t_real, .addr.real = &datap->acc_x, |
508 | 47 | .dflt.real = NAN}, |
509 | 47 | {"acc_y", t_real, .addr.real = &datap->acc_y, |
510 | 47 | .dflt.real = NAN}, |
511 | 47 | {"acc_z", t_real, .addr.real = &datap->acc_z, |
512 | 47 | .dflt.real = NAN}, |
513 | 47 | {"depth", t_real, .addr.real = &datap->depth, |
514 | 47 | .dflt.real = NAN}, |
515 | 47 | {"dip", t_real, .addr.real = &datap->dip, |
516 | 47 | .dflt.real = NAN}, |
517 | 47 | {"gyro_temp", t_real, .addr.real = &datap->gyro_temp, |
518 | 47 | .dflt.real = NAN}, |
519 | 47 | {"gyro_x", t_real, .addr.real = &datap->gyro_x, |
520 | 47 | .dflt.real = NAN}, |
521 | 47 | {"gyro_y", t_real, .addr.real = &datap->gyro_y, |
522 | 47 | .dflt.real = NAN}, |
523 | 47 | {"gyro_z", t_real, .addr.real = &datap->gyro_z, |
524 | 47 | .dflt.real = NAN}, |
525 | 47 | {"heading", t_real, .addr.real = &datap->heading, |
526 | 47 | .dflt.real = NAN}, |
527 | 47 | {"mag_len", t_real, .addr.real = &datap->mag_len, |
528 | 47 | .dflt.real = NAN}, |
529 | 47 | {"mag_st", t_character, .addr.character = &datap->mag_st}, |
530 | 47 | {"mag_x", t_real, .addr.real = &datap->mag_x, |
531 | 47 | .dflt.real = NAN}, |
532 | 47 | {"mag_y", t_real, .addr.real = &datap->mag_y, |
533 | 47 | .dflt.real = NAN}, |
534 | 47 | {"mag_z", t_real, .addr.real = &datap->mag_z, |
535 | 47 | .dflt.real = NAN}, |
536 | 47 | {"msg", t_string, .addr.string = datap->msg, |
537 | 47 | .len = sizeof(datap->msg)}, |
538 | 47 | {"pitch_st", t_character, .addr.character = &datap->pitch_st}, |
539 | 47 | {"pitch", t_real, .addr.real = &datap->pitch, |
540 | 47 | .dflt.real = NAN}, |
541 | 47 | {"roll_st", t_character, .addr.character = &datap->roll_st}, |
542 | 47 | {"roll", t_real, .addr.real = &datap->roll, |
543 | 47 | .dflt.real = NAN}, |
544 | 47 | {"temp", t_real, .addr.real = &datap->temp, |
545 | 47 | .dflt.real = NAN}, |
546 | 47 | {"time", t_time, .addr.ts = &datap->mtime, .dflt.ts = {0, 0}}, |
547 | 47 | {"timeTag", t_ulongint, .addr.ulongint = &datap->timeTag, |
548 | 47 | .dflt.ulongint = 0}, |
549 | 47 | {"yaw_st", t_character, .addr.character = &datap->yaw_st}, |
550 | 47 | {"yaw", t_real, .addr.real = &datap->yaw, .dflt.real = NAN}, |
551 | | |
552 | | // ignore unknown keys, for cross-version compatibility |
553 | 47 | {"", t_ignore}, |
554 | 47 | {NULL}, |
555 | | // *INDENT-ON* |
556 | 47 | }; |
557 | | |
558 | 47 | return json_read_object(buf, json_attrs_1, endptr); |
559 | 47 | } |
560 | | |
561 | | static int json_devicelist_read(const char *buf, struct gps_data_t *gpsdata, |
562 | | const char **endptr) |
563 | 87 | { |
564 | 87 | const struct json_attr_t json_attrs_subdevices[] = { |
565 | | // *INDENT-OFF* |
566 | 87 | {"class", t_check, .dflt.check = "DEVICE"}, |
567 | 87 | {"path", t_string, STRUCTOBJECT(struct devconfig_t, path), |
568 | 87 | .len = sizeof(gpsdata->devices.list[0].path)}, |
569 | 87 | {"activated", t_time, |
570 | 87 | STRUCTOBJECT(struct devconfig_t, activated)}, |
571 | 87 | {"flags", t_integer, STRUCTOBJECT(struct devconfig_t, flags)}, |
572 | 87 | {"driver", t_string, STRUCTOBJECT(struct devconfig_t, driver), |
573 | 87 | .len = sizeof(gpsdata->devices.list[0].driver)}, |
574 | 87 | {"hexdata", t_string, STRUCTOBJECT(struct devconfig_t, hexdata), |
575 | 87 | .len = sizeof(gpsdata->devices.list[0].hexdata)}, |
576 | 87 | {"sernum", t_string, STRUCTOBJECT(struct devconfig_t, sernum), |
577 | 87 | .len = sizeof(gpsdata->devices.list[0].sernum)}, |
578 | 87 | {"subtype", t_string, STRUCTOBJECT(struct devconfig_t, subtype), |
579 | 87 | .len = sizeof(gpsdata->devices.list[0].subtype)}, |
580 | 87 | {"subtype1", t_string, STRUCTOBJECT(struct devconfig_t, subtype1), |
581 | 87 | .len = sizeof(gpsdata->devices.list[0].subtype1)}, |
582 | 87 | {"native", t_integer, STRUCTOBJECT(struct devconfig_t, driver_mode), |
583 | 87 | .dflt.integer = -1}, |
584 | 87 | {"bps", t_uinteger, STRUCTOBJECT(struct devconfig_t, baudrate), |
585 | 87 | .dflt.uinteger = DEVDEFAULT_BPS}, |
586 | 87 | {"parity", t_character, STRUCTOBJECT(struct devconfig_t, parity), |
587 | 87 | .dflt.character = DEVDEFAULT_PARITY}, |
588 | 87 | {"stopbits", t_uinteger, STRUCTOBJECT(struct devconfig_t, stopbits), |
589 | 87 | .dflt.integer = DEVDEFAULT_STOPBITS}, |
590 | 87 | {"cycle", t_timespec, STRUCTOBJECT(struct devconfig_t, cycle), |
591 | 87 | .dflt.ts = {0,0}}, |
592 | 87 | {"mincycle", t_timespec, STRUCTOBJECT(struct devconfig_t, mincycle), |
593 | 87 | .dflt.ts = {0,0}}, |
594 | | // ignore unknown keys, for cross-version compatibility |
595 | 87 | {"", t_ignore}, |
596 | 87 | {NULL}, |
597 | | // *INDENT-ON* |
598 | 87 | }; |
599 | 87 | const struct json_attr_t json_attrs_devices[] = { |
600 | 87 | {"class", t_check,.dflt.check = "DEVICES"}, |
601 | 87 | {"devices", t_array, STRUCTARRAY(gpsdata->devices.list, |
602 | 87 | json_attrs_subdevices, |
603 | 87 | &gpsdata->devices.ndevices)}, |
604 | | // ignore unknown keys, for cross-version compatibility |
605 | 87 | {"", t_ignore}, |
606 | 87 | {NULL}, |
607 | 87 | }; |
608 | 87 | int status; |
609 | | |
610 | 87 | memset(&gpsdata->devices, 0, sizeof(gpsdata->devices)); |
611 | 87 | status = json_read_object(buf, json_attrs_devices, endptr); |
612 | 87 | if (status != 0) { |
613 | 77 | return status; |
614 | 77 | } |
615 | | |
616 | | // json.c should ensure this never happens |
617 | 87 | assert(MAXUSERDEVS >= gpsdata->devices.ndevices); |
618 | | |
619 | 10 | (void)clock_gettime(CLOCK_REALTIME, &gpsdata->devices.time); |
620 | 10 | return 0; |
621 | 10 | } |
622 | | |
623 | | static int json_version_read(const char *buf, struct gps_data_t *gpsdata, |
624 | | const char **endptr) |
625 | 16 | { |
626 | 16 | const struct json_attr_t json_attrs_version[] = { |
627 | | // *INDENT-OFF* |
628 | 16 | {"class", t_check, .dflt.check = "VERSION"}, |
629 | 16 | {"release", t_string, .addr.string = gpsdata->version.release, |
630 | 16 | .len = sizeof(gpsdata->version.release)}, |
631 | 16 | {"rev", t_string, .addr.string = gpsdata->version.rev, |
632 | 16 | .len = sizeof(gpsdata->version.rev)}, |
633 | 16 | {"proto_major", t_integer, |
634 | 16 | .addr.integer = &gpsdata->version.proto_major}, |
635 | 16 | {"proto_minor", t_integer, |
636 | 16 | .addr.integer = &gpsdata->version.proto_minor}, |
637 | 16 | {"remote", t_string, .addr.string = gpsdata->version.remote, |
638 | 16 | .len = sizeof(gpsdata->version.remote)}, |
639 | | // ignore unknown keys, for cross-version compatibility |
640 | 16 | {"", t_ignore}, |
641 | 16 | {NULL}, |
642 | | // *INDENT-ON* |
643 | 16 | }; |
644 | 16 | int status; |
645 | | |
646 | 16 | memset(&gpsdata->version, 0, sizeof(gpsdata->version)); |
647 | 16 | status = json_read_object(buf, json_attrs_version, endptr); |
648 | | |
649 | 16 | return status; |
650 | 16 | } |
651 | | |
652 | | static int json_error_read(const char *buf, struct gps_data_t *gpsdata, |
653 | | const char **endptr) |
654 | 8 | { |
655 | 8 | const struct json_attr_t json_attrs_error[] = { |
656 | | // *INDENT-OFF* |
657 | 8 | {"class", t_check, .dflt.check = "ERROR"}, |
658 | 8 | {"message", t_string, .addr.string = gpsdata->error, |
659 | 8 | .len = sizeof(gpsdata->error)}, |
660 | | // ignore unknown keys, for cross-version compatibility |
661 | 8 | {"", t_ignore}, |
662 | 8 | {NULL}, |
663 | | // *INDENT-ON* |
664 | 8 | }; |
665 | 8 | int status; |
666 | | |
667 | 8 | memset(&gpsdata->error, 0, sizeof(gpsdata->error)); |
668 | 8 | status = json_read_object(buf, json_attrs_error, endptr); |
669 | 8 | if (status != 0) |
670 | 6 | return status; |
671 | | |
672 | 2 | return status; |
673 | 8 | } |
674 | | |
675 | | int json_toff_read(const char *buf, struct gps_data_t *gpsdata, |
676 | | const char **endptr) |
677 | 2.80k | { |
678 | 2.80k | int real_sec = 0, real_nsec = 0, clock_sec = 0, clock_nsec = 0; |
679 | 2.80k | const struct json_attr_t json_attrs_toff[] = { |
680 | | // *INDENT-OFF* |
681 | 2.80k | {"class", t_check, .dflt.check = "TOFF"}, |
682 | 2.80k | {"device", t_string, .addr.string = gpsdata->dev.path, |
683 | 2.80k | .len = sizeof(gpsdata->dev.path)}, |
684 | 2.80k | {"real_sec", t_integer, .addr.integer = &real_sec, |
685 | 2.80k | .dflt.integer = 0}, |
686 | 2.80k | {"real_nsec", t_integer, .addr.integer = &real_nsec, |
687 | 2.80k | .dflt.integer = 0}, |
688 | 2.80k | {"clock_sec", t_integer, .addr.integer = &clock_sec, |
689 | 2.80k | .dflt.integer = 0}, |
690 | 2.80k | {"clock_nsec",t_integer, .addr.integer = &clock_nsec, |
691 | 2.80k | .dflt.integer = 0}, |
692 | | // ignore unknown keys, for cross-version compatibility |
693 | 2.80k | {"", t_ignore}, |
694 | 2.80k | {NULL}, |
695 | | // *INDENT-ON* |
696 | 2.80k | }; |
697 | 2.80k | int status; |
698 | | |
699 | 2.80k | memset(&gpsdata->toff, 0, sizeof(gpsdata->toff)); |
700 | 2.80k | status = json_read_object(buf, json_attrs_toff, endptr); |
701 | 2.80k | gpsdata->toff.real.tv_sec = (time_t)real_sec; |
702 | 2.80k | gpsdata->toff.real.tv_nsec = (long)real_nsec; |
703 | 2.80k | gpsdata->toff.clock.tv_sec = (time_t)clock_sec; |
704 | 2.80k | gpsdata->toff.clock.tv_nsec = (long)clock_nsec; |
705 | 2.80k | if (status != 0) |
706 | 560 | return status; |
707 | | |
708 | 2.24k | return status; |
709 | 2.80k | } |
710 | | |
711 | | int json_pps_read(const char *buf, struct gps_data_t *gpsdata, |
712 | | const char **endptr) |
713 | 38 | { |
714 | 38 | int real_sec = 0, real_nsec = 0, clock_sec = 0, clock_nsec = 0, precision=0; |
715 | 38 | int qErr = 0; |
716 | | |
717 | 38 | const struct json_attr_t json_attrs_pps[] = { |
718 | | // *INDENT-OFF* |
719 | 38 | {"class", t_check, .dflt.check = "PPS"}, |
720 | 38 | {"device", t_string, .addr.string = gpsdata->dev.path, |
721 | 38 | .len = sizeof(gpsdata->dev.path)}, |
722 | 38 | {"real_sec", t_integer, .addr.integer = &real_sec, |
723 | 38 | .dflt.integer = 0}, |
724 | 38 | {"real_nsec", t_integer, .addr.integer = &real_nsec, |
725 | 38 | .dflt.integer = 0}, |
726 | 38 | {"clock_sec", t_integer, .addr.integer = &clock_sec, |
727 | 38 | .dflt.integer = 0}, |
728 | 38 | {"clock_nsec",t_integer, .addr.integer = &clock_nsec, |
729 | 38 | .dflt.integer = 0}, |
730 | 38 | {"precision", t_integer, .addr.integer = &precision, |
731 | 38 | .dflt.integer = 0}, |
732 | 38 | {"qErr", t_integer, .addr.integer = &qErr, |
733 | 38 | .dflt.integer = 0}, |
734 | | // ignore unknown keys, for cross-version compatibility |
735 | 38 | {"", t_ignore}, |
736 | 38 | {NULL}, |
737 | | // *INDENT-ON* |
738 | 38 | }; |
739 | 38 | int status; |
740 | | |
741 | 38 | memset(&gpsdata->pps, 0, sizeof(gpsdata->pps)); |
742 | 38 | status = json_read_object(buf, json_attrs_pps, endptr); |
743 | | |
744 | | // This is good until GPS are more than nanosec accurate |
745 | 38 | gpsdata->pps.real.tv_sec = (time_t)real_sec; |
746 | 38 | gpsdata->pps.real.tv_nsec = (long)real_nsec; |
747 | 38 | gpsdata->pps.clock.tv_sec = (time_t)clock_sec; |
748 | 38 | gpsdata->pps.clock.tv_nsec = (long)clock_nsec; |
749 | | // hope qErr fits in int |
750 | 38 | gpsdata->qErr = (long)qErr; |
751 | | |
752 | | // FIXME: precision is currently parsed but discarded |
753 | 38 | return status; |
754 | 38 | } |
755 | | |
756 | | int json_oscillator_read(const char *buf, struct gps_data_t *gpsdata, |
757 | | const char **endptr) |
758 | 11 | { |
759 | 11 | bool running = false, reference = false, disciplined = false; |
760 | 11 | int delta = 0; |
761 | 11 | const struct json_attr_t json_attrs_osc[] = { |
762 | | // *INDENT-OFF* |
763 | 11 | {"class", t_check, .dflt.check = "OSC"}, |
764 | 11 | {"device", t_string, .addr.string = gpsdata->dev.path, |
765 | 11 | .len = sizeof(gpsdata->dev.path)}, |
766 | 11 | {"running", t_boolean, .addr.boolean = &running, |
767 | 11 | .dflt.boolean = false}, |
768 | 11 | {"reference", t_boolean, .addr.boolean = &reference, |
769 | 11 | .dflt.boolean = false}, |
770 | 11 | {"disciplined", t_boolean, .addr.boolean = &disciplined, |
771 | 11 | .dflt.boolean = false}, |
772 | 11 | {"delta", t_integer, .addr.integer = &delta, |
773 | 11 | .dflt.integer = 0}, |
774 | | // ignore unknown keys, for cross-version compatibility |
775 | 11 | {"", t_ignore}, |
776 | 11 | {NULL}, |
777 | | // *INDENT-ON* |
778 | 11 | }; |
779 | 11 | int status; |
780 | | |
781 | 11 | memset(&gpsdata->osc, 0, sizeof(gpsdata->osc)); |
782 | 11 | status = json_read_object(buf, json_attrs_osc, endptr); |
783 | | |
784 | 11 | gpsdata->osc.running = running; |
785 | 11 | gpsdata->osc.reference = reference; |
786 | 11 | gpsdata->osc.disciplined = disciplined; |
787 | 11 | gpsdata->osc.delta = delta; |
788 | | |
789 | 11 | return status; |
790 | 11 | } |
791 | | |
792 | | /* Test for JSON read status values that should be treated as a go-ahead |
793 | | * for further processing. JSON_BADATTR - to allow JSON attributes unknown |
794 | | * to this version of the library, for forward compatibility, is an obvious |
795 | | * thing to go here. |
796 | | * Until microjson is fixed to allow t_array as t_ignore, mask that too. |
797 | | */ |
798 | 3.70k | #define FILTER(n) (((n) == JSON_ERR_BADATTR || \ |
799 | 3.70k | (n) == JSON_ERR_NOARRAY) ? 0 : n) |
800 | 1.53k | #define PASS(n) (0 == FILTER(n)) |
801 | | |
802 | | /* the only entry point - unpack a JSON object into gpsdata_t substructures |
803 | | * |
804 | | * Returns: 0 if OK |
805 | | * -1 on unknown |
806 | | * JSON_ERR_xx code |
807 | | */ |
808 | | int libgps_json_unpack(const char *buf, |
809 | | struct gps_data_t *gpsdata, const char **end) |
810 | 2.77k | { |
811 | 2.77k | int status; |
812 | 2.77k | const char *classtag = strstr(buf, "\"class\":"); |
813 | | |
814 | 2.77k | if (NULL == classtag) { |
815 | 397 | return -1; |
816 | 397 | } |
817 | | |
818 | 2.37k | if (str_starts_with(classtag, "\"class\":\"TPV\"")) { |
819 | 425 | status = json_tpv_read(buf, gpsdata, end); |
820 | 425 | gpsdata->set = STATUS_SET; |
821 | 425 | if (0 != gpsdata->fix.time.tv_sec) { |
822 | 246 | gpsdata->set |= TIME_SET; |
823 | 246 | } |
824 | 425 | if (0 != isfinite(gpsdata->fix.ept)) { |
825 | 2 | gpsdata->set |= TIMERR_SET; |
826 | 2 | } |
827 | 425 | if (0 != isfinite(gpsdata->fix.longitude)) { |
828 | 2 | gpsdata->set |= LATLON_SET; |
829 | 2 | } |
830 | 425 | if (0 != isfinite(gpsdata->fix.altitude) || |
831 | 424 | 0 != isfinite(gpsdata->fix.altHAE) || |
832 | 422 | 0 != isfinite(gpsdata->fix.depth) || |
833 | 421 | 0 != isfinite(gpsdata->fix.altMSL)) { |
834 | 5 | gpsdata->set |= ALTITUDE_SET; |
835 | 5 | } |
836 | 425 | if (0 != isfinite(gpsdata->fix.epx) && |
837 | 3 | 0 != isfinite(gpsdata->fix.epy)) { |
838 | 2 | gpsdata->set |= HERR_SET; |
839 | 2 | } |
840 | 425 | if (0 != isfinite(gpsdata->fix.epv)) { |
841 | 2 | gpsdata->set |= VERR_SET; |
842 | 2 | } |
843 | 425 | if (0 != isfinite(gpsdata->fix.track)) { |
844 | 1 | gpsdata->set |= TRACK_SET; |
845 | 1 | } |
846 | 425 | if (0 != isfinite(gpsdata->fix.magnetic_track) || |
847 | 424 | 0 != isfinite(gpsdata->fix.magnetic_var)) { |
848 | 2 | gpsdata->set |= MAGNETIC_TRACK_SET; |
849 | 2 | } |
850 | 425 | if (0 != isfinite(gpsdata->fix.speed)) { |
851 | 1 | gpsdata->set |= SPEED_SET; |
852 | 1 | } |
853 | 425 | if (0 != isfinite(gpsdata->fix.climb)) { |
854 | 1 | gpsdata->set |= CLIMB_SET; |
855 | 1 | } |
856 | 425 | if (0 != isfinite(gpsdata->fix.epd)) { |
857 | 1 | gpsdata->set |= TRACKERR_SET; |
858 | 1 | } |
859 | 425 | if (0 != isfinite(gpsdata->fix.eps)) { |
860 | 1 | gpsdata->set |= SPEEDERR_SET; |
861 | 1 | } |
862 | 425 | if (0 != isfinite(gpsdata->fix.epc)) { |
863 | 2 | gpsdata->set |= CLIMBERR_SET; |
864 | 2 | } |
865 | 425 | if (MODE_NOT_SEEN != gpsdata->fix.mode) { |
866 | 47 | gpsdata->set |= MODE_SET; |
867 | 47 | } |
868 | 425 | if (0 != isfinite(gpsdata->fix.wanglem) || |
869 | 423 | 0 != isfinite(gpsdata->fix.wangler) || |
870 | 422 | 0 != isfinite(gpsdata->fix.wanglet) || |
871 | 421 | 0 != isfinite(gpsdata->fix.wspeedr) || |
872 | 420 | 0 != isfinite(gpsdata->fix.wspeedt)) { |
873 | 6 | gpsdata->set |= NAVDATA_SET; |
874 | 6 | } |
875 | 425 | if (0 != isfinite(gpsdata->fix.NED.relPosN) || |
876 | 424 | 0 != isfinite(gpsdata->fix.NED.relPosE) || |
877 | 423 | 0 != isfinite(gpsdata->fix.NED.relPosD) || |
878 | 422 | 0 != isfinite(gpsdata->fix.NED.relPosH) || |
879 | 421 | 0 != isfinite(gpsdata->fix.NED.relPosL) || |
880 | 420 | 0 != isfinite(gpsdata->fix.NED.velN) || |
881 | 419 | 0 != isfinite(gpsdata->fix.NED.velE) || |
882 | 418 | 0 != isfinite(gpsdata->fix.NED.velD)) { |
883 | 8 | gpsdata->set |= NED_SET; |
884 | 8 | } |
885 | 425 | if ((0 != isfinite(gpsdata->fix.ecef.x)) && |
886 | 3 | (0 != isfinite(gpsdata->fix.ecef.y)) && |
887 | 2 | (0 != isfinite(gpsdata->fix.ecef.z))) { |
888 | | // All, or none. Clients can just do their own isfinite()s |
889 | 1 | gpsdata->set |= ECEF_SET; |
890 | 1 | } |
891 | 425 | if ((0 != isfinite(gpsdata->fix.ecef.vx)) && |
892 | 3 | (0 != isfinite(gpsdata->fix.ecef.vy)) && |
893 | 2 | (0 != isfinite(gpsdata->fix.ecef.vz))) { |
894 | | // All, or none. Clients can just do their own isfinite()s |
895 | 1 | gpsdata->set |= VECEF_SET; |
896 | 1 | } |
897 | 425 | return FILTER(status); |
898 | 425 | } |
899 | 1.95k | if (str_starts_with(classtag, "\"class\":\"GST\"")) { |
900 | 314 | status = json_noise_read(buf, gpsdata, end); |
901 | 314 | if (PASS(status)) { |
902 | 292 | gpsdata->set &= ~UNION_SET; |
903 | 292 | gpsdata->set |= GST_SET; |
904 | 292 | } |
905 | 314 | return FILTER(status); |
906 | 314 | } |
907 | 1.63k | if (str_starts_with(classtag, "\"class\":\"SKY\"")) { |
908 | 187 | status = json_sky_read(buf, gpsdata, end); |
909 | 187 | return FILTER(status); |
910 | 187 | } |
911 | 1.45k | if (str_starts_with(classtag, "\"class\":\"ATT\"")) { |
912 | 70 | status = json_att_read(buf, gpsdata, end); |
913 | 70 | if (PASS(status)) { |
914 | 38 | gpsdata->set |= ATTITUDE_SET; |
915 | 38 | } |
916 | 70 | return FILTER(status); |
917 | 70 | } |
918 | 1.38k | if (str_starts_with(classtag, "\"class\":\"IMU\"")) { |
919 | 47 | status = json_imu_read(buf, gpsdata, end); |
920 | 47 | if (PASS(status)) { |
921 | 18 | gpsdata->set |= IMU_SET; |
922 | 18 | } |
923 | 47 | return FILTER(status); |
924 | 47 | } |
925 | 1.33k | if (str_starts_with(classtag, "\"class\":\"DEVICES\"")) { |
926 | 87 | status = json_devicelist_read(buf, gpsdata, end); |
927 | 87 | if (PASS(status)) { |
928 | 11 | gpsdata->set &= ~UNION_SET; |
929 | 11 | gpsdata->set |= DEVICELIST_SET; |
930 | 11 | } |
931 | 87 | return FILTER(status); |
932 | 87 | } |
933 | 1.24k | if (str_starts_with(classtag, "\"class\":\"DEVICE\"")) { |
934 | 15 | status = json_device_read(buf, &gpsdata->dev, end); |
935 | 15 | if (PASS(status)) |
936 | 4 | gpsdata->set |= DEVICE_SET; |
937 | 15 | return FILTER(status); |
938 | 15 | } |
939 | 1.23k | if (str_starts_with(classtag, "\"class\":\"WATCH\"")) { |
940 | 50 | status = json_watch_read(buf, &gpsdata->policy, end); |
941 | 50 | if (PASS(status)) { |
942 | 44 | gpsdata->set &= ~UNION_SET; |
943 | 44 | gpsdata->set |= POLICY_SET; |
944 | 44 | } |
945 | 50 | return FILTER(status); |
946 | 50 | } |
947 | 1.18k | if (str_starts_with(classtag, "\"class\":\"VERSION\"")) { |
948 | 16 | status = json_version_read(buf, gpsdata, end); |
949 | 16 | if (status == 0) { |
950 | 4 | gpsdata->set &= ~UNION_SET; |
951 | 4 | gpsdata->set |= VERSION_SET; |
952 | 4 | } |
953 | 16 | return FILTER(status); |
954 | 16 | } |
955 | 1.16k | if (str_starts_with(classtag, "\"class\":\"RTCM2\"")) { |
956 | 283 | status = json_rtcm2_read(buf, |
957 | 283 | gpsdata->dev.path, sizeof(gpsdata->dev.path), |
958 | 283 | &gpsdata->rtcm2, end); |
959 | 283 | if (PASS(status)) { |
960 | 112 | gpsdata->set &= ~UNION_SET; |
961 | 112 | gpsdata->set |= RTCM2_SET; |
962 | 112 | } |
963 | 283 | return FILTER(status); |
964 | 283 | } |
965 | 884 | if (str_starts_with(classtag, "\"class\":\"RTCM3\"")) { |
966 | 136 | status = json_rtcm3_read(buf, |
967 | 136 | gpsdata->dev.path, sizeof(gpsdata->dev.path), |
968 | 136 | &gpsdata->rtcm3, end); |
969 | 136 | if (PASS(status)) { |
970 | 38 | gpsdata->set &= ~UNION_SET; |
971 | 38 | gpsdata->set |= RTCM3_SET; |
972 | 38 | } |
973 | 136 | return FILTER(status); |
974 | 136 | } |
975 | 748 | #ifdef AIVDM_ENABLE |
976 | 748 | if (str_starts_with(classtag, "\"class\":\"AIS\"")) { |
977 | 318 | status = json_ais_read(buf, |
978 | 318 | gpsdata->dev.path, sizeof(gpsdata->dev.path), |
979 | 318 | &gpsdata->ais, end); |
980 | 318 | if (PASS(status)) { |
981 | 192 | gpsdata->set &= ~UNION_SET; |
982 | 192 | gpsdata->set |= AIS_SET; |
983 | 192 | } |
984 | 318 | return FILTER(status); |
985 | 318 | } |
986 | 430 | #endif // AIVDM_ENABLE |
987 | 430 | if (str_starts_with(classtag, "\"class\":\"ERROR\"")) { |
988 | 8 | status = json_error_read(buf, gpsdata, end); |
989 | 8 | if (PASS(status)) { |
990 | 3 | gpsdata->set &= ~UNION_SET; |
991 | 3 | gpsdata->set |= ERROR_SET; |
992 | 3 | } |
993 | 8 | return FILTER(status); |
994 | 8 | } |
995 | 422 | if (str_starts_with(classtag, "\"class\":\"TOFF\"")) { |
996 | 28 | status = json_toff_read(buf, gpsdata, end); |
997 | 28 | if (PASS(status)) { |
998 | 16 | gpsdata->set &= ~UNION_SET; |
999 | 16 | gpsdata->set |= TOFF_SET; |
1000 | 16 | } |
1001 | 28 | return FILTER(status); |
1002 | 28 | } |
1003 | 394 | if (str_starts_with(classtag, "\"class\":\"PPS\"")) { |
1004 | 38 | status = json_pps_read(buf, gpsdata, end); |
1005 | 38 | if (PASS(status)) { |
1006 | 26 | gpsdata->set &= ~UNION_SET; |
1007 | 26 | gpsdata->set |= PPS_SET; |
1008 | 26 | } |
1009 | 38 | return FILTER(status); |
1010 | 38 | } |
1011 | 356 | if (str_starts_with(classtag, "\"class\":\"OSC\"")) { |
1012 | 11 | status = json_oscillator_read(buf, gpsdata, end); |
1013 | 11 | if (PASS(status)) { |
1014 | 5 | gpsdata->set &= ~UNION_SET; |
1015 | 5 | gpsdata->set |= OSCILLATOR_SET; |
1016 | 5 | } |
1017 | 11 | return FILTER(status); |
1018 | 11 | } |
1019 | 345 | if (str_starts_with(classtag, "\"class\":\"RAW\"")) { |
1020 | 132 | status = json_raw_read(buf, gpsdata, end); |
1021 | 132 | if (PASS(status)) { |
1022 | 24 | gpsdata->set &= ~UNION_SET; |
1023 | 24 | gpsdata->set |= RAW_SET; |
1024 | 24 | } |
1025 | 132 | return FILTER(status); |
1026 | 132 | } |
1027 | | // else, unknown class type |
1028 | 213 | return -1; |
1029 | 345 | } |
1030 | | |
1031 | | |
1032 | | |
1033 | | // vim: set expandtab shiftwidth=4 |