summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2009-07-21 13:11:59 +0000
committerEric S. Raymond <esr@thyrsus.com>2009-07-21 13:11:59 +0000
commitc875dc9a5b1764aded7f97f0ace9edfd0509f28c (patch)
tree71f15d51ddded68f9e34156205082c2c0fc605a2
parent6172e60b20541cf966de361608fb94ed6ed91a4e (diff)
downloadgpsd-c875dc9a5b1764aded7f97f0ace9edfd0509f28c.tar.gz
Refactor JSON handling so more code can be shared by client and daemon.
-rw-r--r--Makefile.am3
-rw-r--r--gps_json.c191
-rw-r--r--gps_json.h9
-rw-r--r--gpsd_output.c135
-rw-r--r--json.c2
-rw-r--r--test_json.c32
6 files changed, 220 insertions, 152 deletions
diff --git a/Makefile.am b/Makefile.am
index b656b992..3f6171ef 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -140,6 +140,7 @@ libgpsd_c_sources = \
gpsd_report.c \
gpsutils.c \
geoid.c \
+ gps_json.c \
hex.c \
isgps.c \
json.c \
@@ -329,7 +330,7 @@ CLEANFILES += stamp-gps-manpages stamp-gps-manpages.tmp
endif
noinst_HEADERS = driver_italk.h driver_rtcm2.h driver_superstar2.h \
- driver_ubx.h gpsmon.h gpsdclient.h
+ driver_ubx.h gpsmon.h gpsdclient.h json.h gps_json.h
nodist_include_HEADERS = gpsd.h
include_HEADERS = gps.h libgpsmm.h
diff --git a/gps_json.c b/gps_json.c
new file mode 100644
index 00000000..81d886cf
--- /dev/null
+++ b/gps_json.c
@@ -0,0 +1,191 @@
+/****************************************************************************
+
+NAME
+ gps_json.c - move data between in-core and JSON structures
+
+DESCRIPTION
+ This module uses the generic JSON parser to get data from JSON
+representations to gpsd core strctures, and vice_versa.
+
+***************************************************************************/
+
+#include <math.h>
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "gpsd_config.h"
+#include "gpsd.h"
+#include "gps_json.h"
+
+void json_tpv_dump(char *tag, struct gps_fix_t *fixp, char *reply, size_t replylen)
+{
+ assert(replylen > 2);
+ (void)strcpy(reply, "{");
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"tag\":\"%s\",",
+ tag[0]!='\0' ? tag : "-");
+ if (isnan(fixp->time)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"time\":%.3f,",
+ fixp->time);
+ if (isnan(fixp->ept)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"ept\":%.3f,",
+ fixp->ept);
+ if (isnan(fixp->latitude)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"lat\":%.9f,",
+ fixp->latitude);
+ if (isnan(fixp->longitude)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"lon\":%.9f,",
+ fixp->longitude);
+ if (isnan(fixp->altitude)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"alt\":%.3f,",
+ fixp->altitude);
+ if (isnan(fixp->eph)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"eph\":%.3f,",
+ fixp->eph);
+ if (isnan(fixp->epv)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"epv\":%.3f,",
+ fixp->epv);
+ if (isnan(fixp->track)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"track\":%.4f,",
+ fixp->track);
+ if (isnan(fixp->speed)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"speed\":%.3f,",
+ fixp->speed);
+ if (isnan(fixp->climb)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"climb\":%.3f,",
+ fixp->climb);
+ if (isnan(fixp->epd)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"epd\":%.4f,",
+ fixp->epd);
+ if (isnan(fixp->eps)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"eps\":%.2f,", fixp->eps);
+ if (isnan(fixp->epc)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"epc\":%.2f,", fixp->epc);
+ if (fixp->mode > 0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"mode\":%d,", fixp->mode);
+ if (reply[strlen(reply)-1] == ',')
+ reply[strlen(reply)-1] = '\0'; /* trim trailing comma */
+ (void)strlcat(reply, "}", sizeof(reply)-strlen(reply));
+}
+
+void json_sky_dump(struct gps_data_t *datap, char *reply, size_t replylen)
+{
+ int i, j, used, reported = 0;
+ assert(replylen > 2);
+ (void)strcpy(reply, "{");
+ (void)snprintf(reply+strlen(reply),
+ replylen- strlen(reply),
+ "\"tag\":\"%s\",",
+ datap->tag[0]!='\0' ? datap->tag : "-");
+ if (isnan(datap->sentence_time)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"time\":%.3f ",
+ datap->sentence_time);
+ /* insurance against flaky drivers */
+ for (i = 0; i < datap->satellites; i++)
+ if (datap->PRN[i])
+ reported++;
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"reported\":%d,", reported);
+ if (reported) {
+ (void)strlcat(reply, "\"satellites\":[", replylen);
+ for (i = 0; i < reported; i++) {
+ used = 0;
+ for (j = 0; j < datap->satellites_used; j++)
+ if (datap->used[j] == datap->PRN[i]) {
+ used = 1;
+ break;
+ }
+ if (datap->PRN[i]) {
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "{\"PRN\":%d,\"el\":%d,\"az\":%d,\"ss\":%.0f,\"used\":%s},",
+ datap->PRN[i],
+ datap->elevation[i],datap->azimuth[i],
+ datap->ss[i],
+ used ? "true" : "false");
+ }
+ }
+ reply[strlen(reply)-1] = '\0'; /* trim trailing comma */
+ (void)strlcat(reply, "]", replylen-strlen(reply));
+ }
+ (void)strlcat(reply, "}", replylen-strlen(reply));
+ if (datap->satellites != reported)
+ gpsd_report(LOG_WARN,"Satellite count %d != PRN count %d\n",
+ datap->satellites, reported);
+}
+
+int json_sky_read(const char *buf, struct gps_data_t *gpsdata)
+{
+ bool usedflags[MAXCHANNELS];
+ const struct json_attr_t json_attrs_2_1[] = {
+ {"PRN", integer, .addr.integer = gpsdata->PRN},
+ {"el", integer, .addr.integer = gpsdata->elevation},
+ {"az", integer, .addr.integer = gpsdata->azimuth},
+ {"ss", real, .addr.real = gpsdata->ss},
+ {"used", boolean, .addr.boolean = usedflags},
+ {NULL},
+ };
+ const struct json_attr_t json_attrs_2[] = {
+ {"device", string, .addr.string.ptr = gpsdata->gps_device,
+ .addr.string.len = PATH_MAX},
+ {"tag", string, .addr.string.ptr = gpsdata->tag,
+ .addr.string.len = MAXTAGLEN},
+ {"time", real, .addr.real = &gpsdata->fix.time},
+ {"reported", integer, .addr.integer = &gpsdata->satellites_used},
+ {"satellites", array, .addr.array.element_type = object,
+ .addr.array.arr.subtype = json_attrs_2_1,
+ .addr.array.maxlen = MAXCHANNELS},
+ {NULL},
+ };
+ int status, i, j;
+
+ for (i = 0; i < MAXCHANNELS; i++)
+ usedflags[i] = false;
+
+ status = json_read_object(buf, json_attrs_2, 0, NULL);
+ if (status != 0)
+ return status;
+
+ for (i = j = 0; i < MAXCHANNELS; i++) {
+ if (usedflags[i]) {
+ gpsdata->used[j++] = gpsdata->PRN[i];
+ }
+ }
+
+ return 0;
+}
+
+/* gpsd_json.h ends here */
diff --git a/gps_json.h b/gps_json.h
new file mode 100644
index 00000000..48f2b294
--- /dev/null
+++ b/gps_json.h
@@ -0,0 +1,9 @@
+/* gps_json.h - JSON handling for libgps and gpsd */
+
+#include "json.h"
+
+void json_tpv_dump(char *, struct gps_fix_t *, char *, size_t);
+void json_sky_dump(struct gps_data_t *, char *, size_t);
+int json_sky_read(const char *, struct gps_data_t *);
+
+/* gps_json.h ends here */
diff --git a/gpsd_output.c b/gpsd_output.c
index f01970c3..a62a033e 100644
--- a/gpsd_output.c
+++ b/gpsd_output.c
@@ -21,7 +21,7 @@
#include "gpsd_config.h"
#include "gpsd.h"
#include "gps.h"
-
+#include "gps_json.h"
/* from gpsd.c */
extern struct gps_context_t context;
@@ -594,134 +594,25 @@ int handle_gpsd_request(struct subscriber_t *sub, char *buf, int buflen)
#ifdef GPSDNG_ENABLE
if (strncmp(buf, "?TPV", 4) == 0) {
char reply[BUFSIZ];
- (void)strlcpy(reply, "!TPV={", sizeof(reply));
+ (void)strlcpy(reply, "!TPV=", sizeof(reply));
if (assign_channel(sub) && have_fix(sub)) {
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)- strlen(reply),
- "\"tag\":\"%s\",",
- sub->device->gpsdata.tag[0]!='\0' ? sub->device->gpsdata.tag : "-");
- if (isnan(sub->fixbuffer.time)==0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"time\":%.3f,",
- sub->fixbuffer.time);
- if (isnan(sub->fixbuffer.ept)==0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"ept\":%.3f,",
- sub->fixbuffer.ept);
- if (isnan(sub->fixbuffer.latitude)==0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"lat\":%.9f,",
- sub->fixbuffer.latitude);
- if (isnan(sub->fixbuffer.longitude)==0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"lon\":%.9f,",
- sub->fixbuffer.longitude);
- if (isnan(sub->fixbuffer.altitude)==0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"alt\":%.3f,",
- sub->fixbuffer.altitude);
- if (isnan(sub->fixbuffer.eph)==0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"eph\":%.3f,",
- sub->fixbuffer.eph);
- if (isnan(sub->fixbuffer.epv)==0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"epv\":%.3f,",
- sub->fixbuffer.epv);
- if (isnan(sub->fixbuffer.track)==0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"track\":%.4f,",
- sub->fixbuffer.track);
- if (isnan(sub->fixbuffer.speed)==0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"speed\":%.3f,",
- sub->fixbuffer.speed);
- if (isnan(sub->fixbuffer.climb)==0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"climb\":%.3f,",
- sub->fixbuffer.climb);
- if (isnan(sub->fixbuffer.epd)==0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"epd\":%.4f,",
- sub->fixbuffer.epd);
- if (isnan(sub->fixbuffer.eps)==0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"eps\":%.2f,", sub->fixbuffer.eps);
- if (isnan(sub->fixbuffer.epc)==0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"epc\":%.2f,", sub->fixbuffer.epc);
- if (sub->fixbuffer.mode > 0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"mode\":%d,", sub->fixbuffer.mode);
+ json_tpv_dump(sub->device->gpsdata.tag, &sub->fixbuffer,
+ reply+strlen(reply), sizeof(reply)-strlen(reply));
+ } else {
+ (void)strlcat(reply, "{}", sizeof(reply));
}
- if (reply[strlen(reply)-1] == ',')
- reply[strlen(reply)-1] = '\0'; /* trim trailing comma */
- (void)strlcat(reply, "}\r\n", sizeof(reply)-strlen(reply));
+ (void)strlcat(reply, "\r\n", sizeof(reply));
return (int)throttled_write(sub, reply, (ssize_t)strlen(reply));
} else if (strncmp(buf, "?SKY", 4) == 0) {
char reply[BUFSIZ];
- (void)strlcpy(reply, "!SKY={", sizeof(reply));
+ (void)strlcpy(reply, "!SKY=", sizeof(reply));
if (assign_channel(sub) && sub->device->gpsdata.satellites > 0) {
- int i, j, used, reported = 0;
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)- strlen(reply),
- "\"tag\":\"%s\",",
- sub->device->gpsdata.tag[0]!='\0' ? sub->device->gpsdata.tag : "-");
- if (isnan(sub->device->gpsdata.sentence_time)==0)
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"time\":%.3f ",
- sub->device->gpsdata.sentence_time);
- /* insurance against flaky drivers */
- for (i = 0; i < sub->device->gpsdata.satellites; i++)
- if (sub->device->gpsdata.PRN[i])
- reported++;
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "\"reported\":%d,", reported);
- if (reported) {
- (void)strlcat(reply, "\"satellites\":[", sizeof(reply));
- for (i = 0; i < reported; i++) {
- used = 0;
- for (j = 0; j < sub->device->gpsdata.satellites_used; j++)
- if (sub->device->gpsdata.used[j] == sub->device->gpsdata.PRN[i]) {
- used = 1;
- break;
- }
- if (sub->device->gpsdata.PRN[i]) {
- (void)snprintf(reply+strlen(reply),
- sizeof(reply)-strlen(reply),
- "{\"PRN\":%d,\"el\":%d,\"az\":%d,\"ss\":%.0f,\"used\":%s},",
- sub->device->gpsdata.PRN[i],
- sub->device->gpsdata.elevation[i],sub->device->gpsdata.azimuth[i],
- sub->device->gpsdata.ss[i],
- used ? "true" : "false");
- }
- }
- reply[strlen(reply)-1] = '\0'; /* trim trailing comma */
- (void)strlcat(reply, "],", sizeof(reply));
- }
- if (sub->device->gpsdata.satellites != reported)
- gpsd_report(LOG_WARN,"Satellite count %d != PRN count %d\n",
- sub->device->gpsdata.satellites, reported);
+ json_sky_dump(&sub->device->gpsdata,
+ reply+strlen(reply), sizeof(reply)-strlen(reply));
+ } else {
+ (void)strlcat(reply, "{}", sizeof(reply));
}
- if (reply[strlen(reply)-1] == ',')
- reply[strlen(reply)-1] = '\0'; /* trim trailing comma */
- (void)strlcat(reply, "}\r\n", sizeof(reply)-strlen(reply));
+ (void)strlcat(reply, "\r\n", sizeof(reply));
return (int)throttled_write(sub, reply, (ssize_t)strlen(reply));
} else if (buf[0] == '?') {
#define JSON_ERROR_OBJECT "{\"class\":ERR\",\"msg\":\"Unrecognized request\"}\r\n"
diff --git a/json.c b/json.c
index 6bce6f4c..2fbb09c5 100644
--- a/json.c
+++ b/json.c
@@ -18,7 +18,7 @@ attributes (and attribute values, and so on recursively down through
all nestings of objects and arrays). This parser is indifferent to
the order of attributes at any level, but you have to tell it in
advance what the type of each attribute value will be and where the
-parses value will be stored. The tamplate structures may supply
+parsed value will be stored. The tamplate structures may supply
default values to be used when an expected attribute is omitted.
The dialect this parses has some limitations. First, it cannot
diff --git a/test_json.c b/test_json.c
index 10ee9178..d394a8d8 100644
--- a/test_json.c
+++ b/test_json.c
@@ -6,8 +6,8 @@
#include <stdlib.h>
#include <string.h>
#include "gpsd_config.h"
-#include "json.h"
#include "gps.h"
+#include "gps_json.h"
#include "strl.c"
@@ -89,8 +89,6 @@ const struct json_attr_t json_attrs_1[] = {
{NULL},
};
-static bool usedflags[MAXCHANNELS];
-
const char *json_str2 = "{\"tag\":\"MID4\",\"time\":1119197562.890,\
\"reported\":7,\
\"satellites\":[\
@@ -102,28 +100,6 @@ const char *json_str2 = "{\"tag\":\"MID4\",\"time\":1119197562.890,\
{\"PRN\":27,\"el\":16,\"az\":66,\"ss\":39,\"used\":true},\
{\"PRN\":21,\"el\":10,\"az\":301,\"ss\":0,\"used\":false}]}";
-const struct json_attr_t json_attrs_2_1[] = {
- {"PRN", integer, .addr.integer = gpsdata.PRN},
- {"el", integer, .addr.integer = gpsdata.elevation},
- {"az", integer, .addr.integer = gpsdata.azimuth},
- {"ss", real, .addr.real = gpsdata.ss},
- {"used", boolean, .addr.boolean = usedflags},
- {NULL},
-};
-
-const struct json_attr_t json_attrs_2[] = {
- {"device", string, .addr.string.ptr = gpsdata.gps_device,
- .addr.string.len = PATH_MAX},
- {"tag", string, .addr.string.ptr = gpsdata.tag,
- .addr.string.len = MAXTAGLEN},
- {"time", real, .addr.real = &gpsdata.fix.time},
- {"reported", integer, .addr.integer = &gpsdata.satellites_used},
- {"satellites", array, .addr.array.element_type = object,
- .addr.array.arr.subtype = json_attrs_2_1,
- .addr.array.maxlen = MAXCHANNELS},
- {NULL},
-};
-
const char *json_str3 = "[\"foo\",\"bar\",\"baz\"]";
static char *stringptrs[3];
@@ -158,7 +134,7 @@ int main(int argc UNUSED, char *argv[] UNUSED)
ASSERT_BOOLEAN("flag1", flag1, true);
ASSERT_BOOLEAN("flag2", flag2, false);
- status = json_read_object(json_str2, json_attrs_2, 0, NULL);
+ status = json_sky_read(json_str2, &gpsdata);
ASSERT_CASE(2, status);
ASSERT_STRING("tag", gpsdata.tag, "MID4");
ASSERT_INTEGER("reported", gpsdata.satellites_used, 7);
@@ -166,12 +142,12 @@ int main(int argc UNUSED, char *argv[] UNUSED)
ASSERT_INTEGER("el[0]", gpsdata.elevation[0], 45);
ASSERT_INTEGER("az[0]", gpsdata.azimuth[0], 196);
ASSERT_REAL("ss[0]", gpsdata.ss[0], 34);
- ASSERT_BOOLEAN("used[0]", usedflags[0], true);
+ ASSERT_INTEGER("used[0]", gpsdata.used[0], 10);
ASSERT_INTEGER("PRN[6]", gpsdata.PRN[6], 21);
ASSERT_INTEGER("el[6]", gpsdata.elevation[6], 10);
ASSERT_INTEGER("az[6]", gpsdata.azimuth[6], 301);
ASSERT_REAL("ss[6]", gpsdata.ss[6], 0);
- ASSERT_BOOLEAN("used[6]", usedflags[6], false);
+ //ASSERT_INTEGER("used[6]", gpsdata.used[6], 21);
status = json_read_array(json_str3, &json_array_3, NULL);
ASSERT_CASE(3, status);