Add support for CSV in ocat and GeoJSON in backend

This commit is contained in:
Jan-Piet Mens
2015-08-22 16:42:35 +02:00
parent 3a19a51f2e
commit c766fbc6a7
3 changed files with 187 additions and 2 deletions

89
ocat.c
View File

@@ -5,6 +5,48 @@
#include <time.h>
#include "json.h"
#include "storage.h"
#include "util.h"
void csv_output(JsonNode *json)
{
JsonNode *arr, *one, *j;
time_t tst = 0L;
double lat = 0.0, lon = 0.0;
char *tid = "", *addr;
arr = json_find_member(json, "locations");
json_foreach(one, arr) {
tid = addr = "";
lat = lon = 0.0;
if ((j = json_find_member(one, "tid")) != NULL) {
tid = j->string_;
}
if ((j = json_find_member(one, "addr")) != NULL) {
addr = j->string_;
}
if ((j = json_find_member(one, "tst")) != NULL) {
tst = j->number_;
}
if ((j = json_find_member(one, "lat")) != NULL) {
lat = j->number_;
}
if ((j = json_find_member(one, "lon")) != NULL) {
lon = j->number_;
}
printf("%s,%s,%lf,%lf,%s\n",
isotime(tst),
tid,
lat,
lon,
addr);
}
}
void usage(char *prog)
{
@@ -20,6 +62,7 @@ void usage(char *prog)
printf(" YYYY-MM-DDTHH\n");
printf(" YYYY-MM-DD\n");
printf(" YYYY-MM\n");
printf(" --format json|csv -f output format (default: JSON)\n");
exit(1);
}
@@ -32,6 +75,14 @@ int main(int argc, char **argv)
char *username = NULL, *device = NULL, *time_from = NULL, *time_to = NULL;
JsonNode *json, *obj, *locs;
time_t now, s_lo, s_hi;
typedef enum {
PLAIN = 0,
GEOJSON,
CSV,
JSON,
} output_type;
output_type otype = JSON;
time(&now);
@@ -43,11 +94,12 @@ int main(int argc, char **argv)
{ "device", required_argument, 0, 'd'},
{ "from", required_argument, 0, 'F'},
{ "to", required_argument, 0, 'T'},
{ "format", required_argument, 0, 'f'},
{0, 0, 0, 0}
};
int optindex = 0;
c = getopt_long(argc, argv, "hlu:d:F:T:", long_options, &optindex);
c = getopt_long(argc, argv, "hlu:d:F:T:f:", long_options, &optindex);
if (c == -1)
break;
@@ -67,6 +119,18 @@ int main(int argc, char **argv)
case 'T':
time_to = strdup(optarg);
break;
case 'f':
if (!strcmp(optarg, "json"))
otype = JSON;
else if (!strcmp(optarg, "geojson"))
otype = GEOJSON;
else if (!strcmp(optarg, "csv"))
otype = CSV;
else {
fprintf(stderr, "%s: unrecognized output format\n", progname);
exit(2);
}
break;
case 'h':
case '?':
/* getopt_long already printed message */
@@ -151,7 +215,28 @@ int main(int argc, char **argv)
}
json_append_member(obj, "locations", locs);
printf("%s\n", json_stringify(obj, " "));
if (otype == JSON) {
char *js = json_stringify(obj, " ");
if (js != NULL) {
printf("%s\n", js);
free(js);
}
} else if (otype == CSV) {
csv_output(obj);
} else if (otype == GEOJSON) {
JsonNode *geojson = geo_json(locs);
char *js;
js = json_stringify(geojson, " ");
if (js != NULL) {
printf("%s\n", js);
free(js);
}
}
return (0);
}

View File

@@ -381,3 +381,102 @@ void locations(char *filename, JsonNode *obj, JsonNode *arr, time_t s_lo, time_t
fclose(fp);
}
/*
* We're being passed an array of location objects created in
* locations(). Produce a Geo JSON tree.
*/
/*
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-80.83775386582222,35.24980190252168]
},
"properties": {
"name": "DOUBLE OAKS CENTER",
"address": "1326 WOODWARD AV"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-80.83827000459532,35.25674709224663]
},
"properties": {
"name": "DOUBLE OAKS NEIGHBORHOOD PARK",
"address": "2605 DOUBLE OAKS RD"
}
}
]
}
*/
static void geo_f_array(JsonNode *features, double lat, double lon, char *tid, char *addr)
{
// JsonNode *features = json_mkarray();
JsonNode *f;
JsonNode *geom, *props;
f = json_mkobject();
json_append_member(f, "type", json_mkstring("Feature"));
geom = json_mkobject();
json_append_member(geom, "type", json_mkstring("Point"));
JsonNode *coords = json_mkarray();
json_append_element(coords, json_mknumber(lon)); /* first LON! */
json_append_element(coords, json_mknumber(lat));
json_append_member(geom, "coordinates", coords);
props = json_mkobject();
json_append_member(props, "name", json_mkstring(tid));
json_append_member(props, "address", json_mkstring(addr));
json_append_member(f, "geometry", geom);
json_append_member(f, "properties", props);
json_append_element(features, f);
}
JsonNode *geo_json(JsonNode *location_array)
{
JsonNode *one, *j;
JsonNode *feature_array, *fcollection;
fcollection = json_mkobject();
json_append_member(fcollection, "type", json_mkstring("FeatureCollection"));
feature_array = json_mkarray();
json_foreach(one, location_array) {
double lat = 0.0, lon = 0.0;
char *addr = "", *tid = "";
if ((j = json_find_member(one, "lat")) != NULL) {
lat = j->number_;
}
if ((j = json_find_member(one, "lon")) != NULL) {
lon = j->number_;
}
if ((j = json_find_member(one, "tid")) != NULL) {
tid = j->string_;
}
if ((j = json_find_member(one, "addr")) != NULL) {
addr = j->string_;
}
geo_f_array(feature_array, lat, lon, tid, addr);
}
json_append_member(fcollection, "features", feature_array);
return (fcollection);
}

View File

@@ -8,5 +8,6 @@
JsonNode *lister(char *username, char *device, time_t s_lo, time_t s_hi);
void locations(char *filename, JsonNode *obj, JsonNode *arr, time_t s_lo, time_t s_hi);
int make_times(char *time_from, time_t *s_lo, char *time_to, time_t *s_to);
JsonNode *geo_json(JsonNode *json);
#endif