From 5432551d3e90f7c4827b795e7d1048581d4cb46e Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Wed, 1 May 2013 11:23:06 -0400 Subject: Start on support for unpacking RTCM3 JSON. Only the 1001 sentence so far, with two fields missing. Not usable for production yet, but gets infrastructure in place. --- SConstruct | 3 +- gps_json.h | 2 ++ libgps_json.c | 11 ++++++ rtcm3_json.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 rtcm3_json.c diff --git a/SConstruct b/SConstruct index 0e07a034..b0af78fd 100644 --- a/SConstruct +++ b/SConstruct @@ -699,6 +699,7 @@ libgps_sources = [ "libgps_sock.c", "netlib.c", "rtcm2_json.c", + "rtcm3_json.c", "shared_json.c", "strl.c", ] @@ -859,7 +860,7 @@ if qt_env: # infamous "Two environments with different actions were specified # for the same target" error. for src in libgps_sources: - if src not in ('ais_json.c','json.c','libgps_json.c','rtcm2_json.c','shared_json.c'): + if src not in ('ais_json.c','json.c','libgps_json.c','rtcm2_json.c','rtcm3_json.c','shared_json.c'): compile_with = qt_env['CXX'] compile_flags = qt_flags else: diff --git a/gps_json.h b/gps_json.h index 3a071827..15eb0394 100644 --- a/gps_json.h +++ b/gps_json.h @@ -35,6 +35,8 @@ void json_aivdm_dump(const struct ais_t *, /*@null@*/const char *, bool, /*@out@*/char *, size_t); int json_rtcm2_read(const char *, char *, size_t, struct rtcm2_t *, /*@null@*/const char **); +int json_rtcm3_read(const char *, char *, size_t, struct rtcm3_t *, + /*@null@*/const char **); int json_ais_read(const char *, char *, size_t, struct ais_t *, /*@null@*/const char **); int libgps_json_unpack(const char *, struct gps_data_t *, diff --git a/libgps_json.c b/libgps_json.c index 09141f76..8ffa3434 100644 --- a/libgps_json.c +++ b/libgps_json.c @@ -452,6 +452,17 @@ int libgps_json_unpack(const char *buf, } return status; #endif /* RTCM104V2_ENABLE */ +#ifdef RTCM104V3_ENABLE + } else if (STARTSWITH(classtag, "\"class\":\"RTCM3\"")) { + status = json_rtcm3_read(buf, + gpsdata->dev.path, sizeof(gpsdata->dev.path), + &gpsdata->rtcm3, end); + if (status == 0) { + gpsdata->set &= ~UNION_SET; + gpsdata->set |= RTCM3_SET; + } + return status; +#endif /* RTCM104V3_ENABLE */ #ifdef AIVDM_ENABLE } else if (STARTSWITH(classtag, "\"class\":\"AIS\"")) { status = json_ais_read(buf, diff --git a/rtcm3_json.c b/rtcm3_json.c new file mode 100644 index 00000000..70cd3279 --- /dev/null +++ b/rtcm3_json.c @@ -0,0 +1,114 @@ +/**************************************************************************** + +NAME + rtcm3_json.c - deserialize RTCM3 JSON + +DESCRIPTION + This module uses the generic JSON parser to get data from RTCM3 +representations to libgps structures. + +PERMISSIONS + This file is Copyright (c) 2013 by the GPSD project + BSD terms apply: see the file COPYING in the distribution root for details. + +***************************************************************************/ + +#include +#include +#include +#include + +#include "gpsd.h" + +#ifdef SOCKET_EXPORT_ENABLE +#include "gps_json.h" + +int json_rtcm3_read(const char *buf, + char *path, size_t pathlen, struct rtcm3_t *rtcm3, + /*@null@*/ const char **endptr) +{ + + static char *stringptrs[NITEMS(rtcm3->rtcmtypes.data)]; + static char stringstore[sizeof(rtcm3->rtcmtypes.data) * 2]; + static int stringcount; + +/* *INDENT-OFF* */ +#define RTCM3_HEADER \ + {"class", t_check, .dflt.check = "RTCM3"}, \ + {"type", t_uinteger, .addr.uinteger = &rtcm3->type}, \ + {"device", t_string, .addr.string = path, \ + .len = pathlen}, \ + {"length", t_uinteger, .addr.uinteger = &rtcm3->length}, + + int status = 0, satcount = 0; + + /*@ -fullinitblock @*/ + const struct json_attr_t rtcm1001_satellite[] = { + {"ident", t_uinteger, STRUCTOBJECT(struct rtcm3_1001_t, ident)}, + {"ind", t_uinteger, STRUCTOBJECT(struct rtcm3_1001_t, L1.indicator)}, + {"prange", t_real, STRUCTOBJECT(struct rtcm3_1001_t, L1.pseudorange)}, + {"delta", t_real, STRUCTOBJECT(struct rtcm3_1001_t, L1.rangediff)}, + + {"lockt", t_uinteger, STRUCTOBJECT(struct rtcm3_1001_t, L1.locktime)}, + {NULL}, + }; + /*@-type@*//* STRUCTARRAY confuses splint */ +#define R1001 &rtcm3->rtcmtypes.rtcm3_1001.header + const struct json_attr_t json_rtcm1001[] = { + RTCM3_HEADER + //{"station_id", t_uinteger, .addr.uinteger = R1001.station_id}, \ + {"tow", t_uinteger, .addr.uinteger = R1001.tow}, \ + {"sync", t_boolean, .addr.boolean = R1001.sync}, + {"smoothing", t_boolean, .addr.boolean = R1001.smoothing}, + //{"interval", t_uinteger, .addr.uinteger = R1001.interval}, + {"satellites", t_array, STRUCTARRAY(rtcm3->rtcmtypes.rtcm3_1001.rtk_data, + rtcm1001_satellite, &satcount)}, + {NULL}, + }; +#undef R1001 + /*@+type@*/ + + /*@-type@*//* complex union array initislizations confuses splint */ + const struct json_attr_t json_rtcm3_fallback[] = { + RTCM3_HEADER + {"data", t_array, .addr.array.element_type = t_string, + .addr.array.arr.strings.ptrs = stringptrs, + .addr.array.arr.strings.store = stringstore, + .addr.array.arr.strings.storelen = sizeof(stringstore), + .addr.array.count = &stringcount, + .addr.array.maxlen = NITEMS(stringptrs)}, + {NULL}, + }; + /*@+type@*/ + /*@ +fullinitblock @*/ + +#undef RTCM3_HEADER +/* *INDENT-ON* */ + + memset(rtcm3, '\0', sizeof(struct rtcm3_t)); + + if (strstr(buf, "\"type\":1001,") != NULL) { + status = json_read_object(buf, json_rtcm1001, endptr); + if (status == 0) + rtcm3->rtcmtypes.rtcm3_1003.header.satcount = (unsigned)satcount; + } else { + int n; + status = json_read_object(buf, json_rtcm3_fallback, endptr); + for (n = 0; n < NITEMS(rtcm3->rtcmtypes.data); n++) { + if (n >= stringcount) { + rtcm3->rtcmtypes.data[n] = 0; + } else { + unsigned int u; + int fldcount = sscanf(stringptrs[n], "0x%02x\n", &u); + if (fldcount != 1) + return JSON_ERR_MISC; + else + rtcm3->rtcmtypes.data[n] = (unsigned char)u; + } + } + } + return status; +} +#endif /* SOCKET_EXPORT_ENABLE */ + +/* rtcm3_json.c ends here */ -- cgit v1.2.1