Coverage Report

Created: 2024-02-25 06:36

/src/gpsd/gpsd-3.25.1~dev/libgps/rtcm2_json.c
Line
Count
Source
1
/****************************************************************************
2
3
NAME
4
   rtcm2_json.c - deserialize RTCM2 JSON
5
6
DESCRIPTION
7
   This module uses the generic JSON parser to get data from RTCM2
8
representations to libgps structures.
9
10
PERMISSIONS
11
   This file is Copyright 2010 by the GPSD project
12
   SPDX-License-Identifier: BSD-2-clause
13
14
***************************************************************************/
15
16
#include "../include/gpsd_config.h"  /* must be before all includes */
17
18
#include <math.h>
19
#include <stddef.h>
20
#include <stdio.h>
21
#include <string.h>
22
23
#include "../include/gpsd.h"
24
25
#ifdef SOCKET_EXPORT_ENABLE
26
#include "../include/gps_json.h"
27
28
/* common fields in every RTCM2 message */
29
30
int json_rtcm2_read(const char *buf,
31
                    char *path, size_t pathlen, struct rtcm2_t *rtcm2,
32
                    const char **endptr)
33
319
{
34
35
319
    static char *stringptrs[NITEMS(rtcm2->words)];
36
319
    static char stringstore[sizeof(rtcm2->words) * 2];
37
319
    static int stringcount;
38
39
/* *INDENT-OFF* */
40
319
#define RTCM2_HEADER \
41
3.50k
        {"class",          t_check,    .dflt.check = "RTCM2"}, \
42
3.50k
        {"type",           t_uinteger, .addr.uinteger = &rtcm2->type}, \
43
3.50k
        {"device",         t_string,   .addr.string = path, \
44
3.50k
                                          .len = pathlen}, \
45
3.50k
        {"station_id",     t_uinteger, .addr.uinteger = &rtcm2->refstaid}, \
46
3.50k
        {"zcount",         t_real,     .addr.real = &rtcm2->zcount, \
47
3.50k
                                          .dflt.real = NAN}, \
48
3.50k
        {"seqnum",         t_uinteger, .addr.uinteger = &rtcm2->seqnum}, \
49
3.50k
        {"length",         t_uinteger, .addr.uinteger = &rtcm2->length}, \
50
3.50k
        {"station_health", t_uinteger, .addr.uinteger = &rtcm2->stathlth},
51
52
319
    int status = 0, satcount = 0;
53
54
319
    const struct json_attr_t rtcm1_satellite[] = {
55
319
        {"ident",     t_uinteger, STRUCTOBJECT(struct gps_rangesat_t, ident)},
56
319
        {"udre",      t_uinteger, STRUCTOBJECT(struct gps_rangesat_t, udre)},
57
319
        {"iod",       t_uinteger, STRUCTOBJECT(struct gps_rangesat_t, iod)},
58
319
        {"prc",       t_real,     STRUCTOBJECT(struct gps_rangesat_t, prc)},
59
319
        {"rrc",       t_real,     STRUCTOBJECT(struct gps_rangesat_t, rrc)},
60
319
        {NULL},
61
319
    };
62
319
    const struct json_attr_t json_rtcm1[] = {
63
319
        RTCM2_HEADER
64
319
        {"satellites", t_array, STRUCTARRAY(rtcm2->gps_ranges.sat,
65
319
                                            rtcm1_satellite, &satcount)},
66
319
        {NULL},
67
319
    };
68
69
319
    const struct json_attr_t json_rtcm3[] = {
70
319
        RTCM2_HEADER
71
319
        {"x",              t_real,    .addr.real = &rtcm2->ref_sta.x,
72
319
                                         .dflt.real = NAN},
73
319
        {"y",              t_real,    .addr.real = &rtcm2->ref_sta.y,
74
319
                                         .dflt.real = NAN},
75
319
        {"z",              t_real,    .addr.real = &rtcm2->ref_sta.z,
76
319
                                         .dflt.real = NAN},
77
319
        {NULL},
78
319
    };
79
80
    /*
81
     * Beware! Needs to stay synchronized with a corresponding
82
     * name array in the RTCM2 JSON dump code. This interpretation of
83
     * NAVSYSTEM_GALILEO is assumed from RTCM3, it's not actually
84
     * documented in RTCM 2.1.
85
     */
86
319
    const struct json_enum_t system_table[] = {
87
319
        {"GPS", 0}, {"GLONASS", 1}, {"GALILEO", 2}, {"UNKNOWN", 3}, {NULL}
88
319
    };
89
319
    const struct json_attr_t json_rtcm4[] = {
90
319
        RTCM2_HEADER
91
319
        {"valid",          t_boolean, .addr.boolean = &rtcm2->reference.valid},
92
319
        {"system",         t_integer, .addr.integer = &rtcm2->reference.system,
93
319
                                         .map=system_table},
94
319
        {"sense",          t_integer, .addr.integer = &rtcm2->reference.sense},
95
319
        {"datum",          t_string,  .addr.string = rtcm2->reference.datum,
96
319
                                         .len = sizeof(rtcm2->reference.datum)},
97
319
        {"dx",             t_real,    .addr.real = &rtcm2->reference.dx,
98
319
                                         .dflt.real = NAN},
99
319
        {"dy",             t_real,    .addr.real = &rtcm2->reference.dy,
100
319
                                         .dflt.real = NAN},
101
319
        {"dz",             t_real,    .addr.real = &rtcm2->reference.dz,
102
319
                                         .dflt.real = NAN},
103
319
        {NULL},
104
319
    };
105
106
319
    const struct json_attr_t rtcm5_satellite[] = {
107
319
        {"ident",       t_uinteger, STRUCTOBJECT(struct consat_t, ident)},
108
319
        {"iodl",        t_boolean,  STRUCTOBJECT(struct consat_t, iodl)},
109
319
        {"health",      t_uinteger, STRUCTOBJECT(struct consat_t, health)},
110
319
        {"snr",         t_integer,  STRUCTOBJECT(struct consat_t, snr)},
111
319
        {"health_en",   t_boolean,  STRUCTOBJECT(struct consat_t, health_en)},
112
319
        {"new_data",    t_boolean,  STRUCTOBJECT(struct consat_t, new_data)},
113
319
        {"los_warning", t_boolean,  STRUCTOBJECT(struct consat_t, los_warning)},
114
319
        {"tou",         t_uinteger, STRUCTOBJECT(struct consat_t, tou)},
115
319
        {NULL},
116
319
    };
117
319
    const struct json_attr_t json_rtcm5[] = {
118
319
        RTCM2_HEADER
119
319
        {"satellites", t_array, STRUCTARRAY(rtcm2->conhealth.sat,
120
319
                                            rtcm5_satellite, &satcount)},
121
319
        {NULL},
122
319
    };
123
124
319
    const struct json_attr_t json_rtcm6[] = {
125
319
        RTCM2_HEADER
126
        // No-op or keepalive message
127
319
        {NULL},
128
319
    };
129
130
319
    const struct json_attr_t rtcm7_satellite[] = {
131
319
        {"lat",         t_real,     STRUCTOBJECT(struct station_t, latitude)},
132
319
        {"lon",         t_real,     STRUCTOBJECT(struct station_t, longitude)},
133
319
        {"range",       t_uinteger, STRUCTOBJECT(struct station_t, range)},
134
319
        {"frequency",   t_real,     STRUCTOBJECT(struct station_t, frequency)},
135
319
        {"health",      t_uinteger, STRUCTOBJECT(struct station_t, health)},
136
319
        {"station_id",  t_uinteger, STRUCTOBJECT(struct station_t, station_id)},
137
319
        {"bitrate",     t_uinteger, STRUCTOBJECT(struct station_t, bitrate)},
138
319
        {NULL},
139
319
    };
140
319
    const struct json_attr_t json_rtcm7[] = {
141
319
        RTCM2_HEADER
142
319
        {"satellites", t_array, STRUCTARRAY(rtcm2->almanac.station,
143
319
                                            rtcm7_satellite, &satcount)},
144
319
        {NULL},
145
319
    };
146
147
319
    const struct json_attr_t json_rtcm13[] = {
148
319
        RTCM2_HEADER
149
319
        {"status",       t_boolean,  .addr.boolean = &rtcm2->xmitter.status},
150
319
        {"rangeflag",    t_boolean,  .addr.boolean = &rtcm2->xmitter.rangeflag},
151
319
        {"lat",          t_real,     .addr.real = &rtcm2->xmitter.lat,
152
319
                                        .dflt.real = NAN},
153
319
        {"lon",          t_real,     .addr.real = &rtcm2->xmitter.lon,
154
319
                                        .dflt.real = NAN},
155
319
        {"range",        t_uinteger, .addr.uinteger = &rtcm2->xmitter.range},
156
319
        {NULL},
157
319
    };
158
159
319
    const struct json_attr_t json_rtcm14[] = {
160
319
        RTCM2_HEADER
161
319
        {"week",              t_uinteger,
162
319
                              .addr.uinteger = &rtcm2->gpstime.week},
163
319
        {"hour",              t_uinteger,
164
319
                              .addr.uinteger = &rtcm2->gpstime.hour},
165
319
        {"leapsecs",          t_uinteger,
166
319
                              .addr.uinteger = &rtcm2->gpstime.leapsecs},
167
319
        {NULL},
168
319
    };
169
170
319
    const struct json_attr_t json_rtcm16[] = {
171
319
        RTCM2_HEADER
172
319
        {"message",        t_string,  .addr.string = rtcm2->message,
173
319
                                         .len = sizeof(rtcm2->message)},
174
319
        {NULL},
175
319
    };
176
177
319
    const struct json_attr_t rtcm31_satellite[] = {
178
319
        {"ident",     t_uinteger,
179
319
                              STRUCTOBJECT(struct glonass_rangesat_t, ident)},
180
319
        {"udre",      t_uinteger,
181
319
                              STRUCTOBJECT(struct glonass_rangesat_t, udre)},
182
319
        {"change",    t_boolean,
183
319
                              STRUCTOBJECT(struct glonass_rangesat_t, change)},
184
319
        {"tod",       t_uinteger, STRUCTOBJECT(struct glonass_rangesat_t, tod)},
185
319
        {"prc",       t_real,     STRUCTOBJECT(struct glonass_rangesat_t, prc)},
186
319
        {"rrc",       t_real,     STRUCTOBJECT(struct glonass_rangesat_t, rrc)},
187
319
        {NULL},
188
319
    };
189
319
    const struct json_attr_t json_rtcm31[] = {
190
319
        RTCM2_HEADER
191
319
        {"satellites", t_array, STRUCTARRAY(rtcm2->glonass_ranges.sat,
192
319
                                            rtcm31_satellite, &satcount)},
193
319
        {NULL},
194
319
    };
195
196
319
    const struct json_attr_t json_rtcm2_fallback[] = {
197
319
        RTCM2_HEADER
198
319
        {"data",         t_array, .addr.array.element_type = t_string,
199
319
                         .addr.array.arr.strings.ptrs = stringptrs,
200
319
                         .addr.array.arr.strings.store = stringstore,
201
319
                         .addr.array.arr.strings.storelen = sizeof(stringstore),
202
319
                         .addr.array.count = &stringcount,
203
319
                         .addr.array.maxlen = NITEMS(stringptrs)},
204
319
        {NULL},
205
319
    };
206
207
319
#undef RTCM2_HEADER
208
/* *INDENT-ON* */
209
210
319
    memset(rtcm2, '\0', sizeof(struct rtcm2_t));
211
212
319
    if (strstr(buf, "\"type\":1,") != NULL
213
319
        || strstr(buf, "\"type\":9,") != NULL) {
214
6
        status = json_read_object(buf, json_rtcm1, endptr);
215
6
        if (status == 0)
216
1
            rtcm2->gps_ranges.nentries = (unsigned)satcount;
217
313
    } else if (strstr(buf, "\"type\":3,") != NULL) {
218
89
        status = json_read_object(buf, json_rtcm3, endptr);
219
89
        if (status == 0) {
220
84
            rtcm2->ref_sta.valid = (isfinite(rtcm2->ref_sta.x) != 0)
221
84
                && (isfinite(rtcm2->ref_sta.y) != 0)
222
84
                && (isfinite(rtcm2->ref_sta.z) != 0);
223
84
        }
224
224
    } else if (strstr(buf, "\"type\":4,") != NULL) {
225
93
        status = json_read_object(buf, json_rtcm4, endptr);
226
93
        if (status == 0)
227
3
            rtcm2->reference.valid = (isfinite(rtcm2->reference.dx) != 0)
228
3
                && (isfinite(rtcm2->reference.dy) != 0)
229
3
                && (isfinite(rtcm2->reference.dz) != 0);
230
131
    } else if (strstr(buf, "\"type\":5,") != NULL) {
231
4
        status = json_read_object(buf, json_rtcm5, endptr);
232
4
        if (status == 0)
233
1
            rtcm2->conhealth.nentries = (unsigned)satcount;
234
127
    } else if (strstr(buf, "\"type\":6,") != NULL) {
235
1
        status = json_read_object(buf, json_rtcm6, endptr);
236
126
    } else if (strstr(buf, "\"type\":7,") != NULL) {
237
6
        status = json_read_object(buf, json_rtcm7, endptr);
238
6
        if (status == 0)
239
1
            rtcm2->almanac.nentries = (unsigned)satcount;
240
120
    } else if (strstr(buf, "\"type\":13,") != NULL) {
241
1
        status = json_read_object(buf, json_rtcm13, endptr);
242
119
    } else if (strstr(buf, "\"type\":14,") != NULL) {
243
1
        status = json_read_object(buf, json_rtcm14, endptr);
244
118
    } else if (strstr(buf, "\"type\":16,") != NULL) {
245
1
        status = json_read_object(buf, json_rtcm16, endptr);
246
117
    } else if (strstr(buf, "\"type\":31,") != NULL) {
247
5
        status = json_read_object(buf, json_rtcm31, endptr);
248
5
        if (status == 0)
249
1
            rtcm2->glonass_ranges.nentries = (unsigned)satcount;
250
112
    } else {
251
112
        int n;
252
112
        status = json_read_object(buf, json_rtcm2_fallback, endptr);
253
2.82k
        for (n = 0; n < NITEMS(rtcm2->words); n++) {
254
2.74k
            if (n >= stringcount) {
255
2.54k
                rtcm2->words[n] = 0;
256
2.54k
            } else {
257
200
                unsigned int u;
258
200
                int fldcount = sscanf(stringptrs[n], "0x%08x\n", &u);
259
200
                if (fldcount != 1)
260
25
                    return JSON_ERR_MISC;
261
175
                else
262
175
                    rtcm2->words[n] = (isgps30bits_t) u;
263
200
            }
264
2.74k
        }
265
112
    }
266
294
    return status;
267
319
}
268
#endif /* SOCKET_EXPORT_ENABLE */
269
270
/* rtcm2_json.c ends here */
271
272
// vim: set expandtab shiftwidth=4