You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

754 lines
32KB

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