diff --git a/API.md b/API.md index 592b989..59c986e 100644 --- a/API.md +++ b/API.md @@ -31,7 +31,7 @@ List users. If _user_ is specified, lists that user's devices. If both _user_ an ## `locations` -Here comes the actual data. This lists users' locations and requires both _user_ and _device_. Output format is JSON unless a different _format_ is given (`csv`, `json`, `geojson`, `xml`, and `linestring` are supported). +Here comes the actual data. This lists users' locations and requires both _user_ and _device_. Output format is JSON unless a different _format_ is given (`csv`, `json`, `geojson`, `geojsonpoi`, `xml`, and `linestring` are supported). In order to limit the number of records returned, use _limit_ which causes a reverse search through the `.rec` files; this can be used to find the last N positions. diff --git a/README.md b/README.md index 0db2af7..c56c0ab 100644 --- a/README.md +++ b/README.md @@ -508,6 +508,7 @@ The Recorder's built-in WebSocket server updates a map as it receives publishes * JSON * GeoJSON (points) +* GeoJSON (points) for Points of Interest only * GeoJSON (line string) * CSV * GPX diff --git a/http.c b/http.c index 18cd5dc..0c36860 100644 --- a/http.c +++ b/http.c @@ -1186,6 +1186,8 @@ static int dispatch(struct mg_connection *conn, const char *uri) if ((ret = mg_get_var(conn, "format", buf, sizeof(buf))) > 0) { if (!strcmp(buf, "geojson")) otype = GEOJSON; + else if (!strcmp(buf, "geojsonpoi")) + otype = GEOJSONPOI; else if (!strcmp(buf, "json")) otype = JSON; else if (!strcmp(buf, "linestring")) @@ -1290,7 +1292,17 @@ static int dispatch(struct mg_connection *conn, const char *uri) return (json_response(conn, geoline)); } else if (otype == GEOJSON) { - JsonNode *geojson = geo_json(locs); + JsonNode *geojson = geo_json(locs, false); + + json_delete(obj); + if (geojson != NULL) { + return (json_response(conn, geojson)); + } + json_delete(obj); + return send_status(conn, 422, "geojson failed"); + + } else if (otype == GEOJSONPOI) { // POI only + JsonNode *geojson = geo_json(locs, true); json_delete(obj); if (geojson != NULL) { diff --git a/ocat.c b/ocat.c index b240af2..6a1d23b 100644 --- a/ocat.c +++ b/ocat.c @@ -63,6 +63,7 @@ void usage(char *prog) printf(" --format json -f output format (default: JSON)\n"); printf(" csv (overrides $OCAT_FORMAT\n"); printf(" geojson Geo-JSON points\n"); + printf(" geojsonpoi Geo-JSON points, POI only\n"); printf(" linestring Geo-JSON LineString\n"); printf(" gpx\n"); printf(" xml\n"); @@ -261,6 +262,8 @@ int main(int argc, char **argv) otype = JSON; else if (!strcmp(optarg, "geojson")) otype = GEOJSON; + else if (!strcmp(optarg, "geojsonpoi")) + otype = GEOJSONPOI; else if (!strcmp(optarg, "linestring")) otype = LINESTRING; else if (!strcmp(optarg, "raw")) @@ -498,7 +501,19 @@ int main(int argc, char **argv) } } else if (otype == GEOJSON) { - JsonNode *geojson = geo_json(locs); + JsonNode *geojson = geo_json(locs, false); + char *js; + + if (geojson != NULL) { + js = json_stringify(geojson, JSON_INDENT); + if (js != NULL) { + printf("%s\n", js); + free(js); + } + json_delete(geojson); + } + } else if (otype == GEOJSONPOI) { // POI only + JsonNode *geojson = geo_json(locs, true); char *js; if (geojson != NULL) { diff --git a/storage.c b/storage.c index e0bb255..bb36e5e 100644 --- a/storage.c +++ b/storage.c @@ -919,7 +919,7 @@ void locations(char *filename, JsonNode *obj, JsonNode *arr, time_t s_lo, time_t * */ -static void append_to_feature_array(JsonNode *features, double lat, double lon, char *tid, char *addr, long tst, long vel, long acc) +static void append_to_feature_array(JsonNode *features, double lat, double lon, char *tid, char *addr, long tst, long vel, long acc, char *poi, char *isotst) { JsonNode *geom, *props, *f = json_mkobject(); @@ -933,11 +933,16 @@ static void append_to_feature_array(JsonNode *features, double lat, double lon, json_append_member(geom, "coordinates", coords); props = json_mkobject(); - json_append_member(props, "name", json_mkstring(tid)); + if (poi && *poi) { + json_append_member(props, "name", json_mkstring(poi)); + } else { + json_append_member(props, "name", json_mkstring(tid)); + json_append_member(props, "vel", json_mknumber(vel)); + json_append_member(props, "tst", json_mknumber(tst)); + json_append_member(props, "acc", json_mknumber(acc)); + } json_append_member(props, "address", json_mkstring(addr)); - json_append_member(props, "vel", json_mknumber(vel)); - json_append_member(props, "tst", json_mknumber(tst)); - json_append_member(props, "acc", json_mknumber(acc)); + json_append_member(props, "isotst", json_mkstring(isotst)); json_append_member(f, "geometry", geom); json_append_member(f, "properties", props); @@ -945,7 +950,7 @@ static void append_to_feature_array(JsonNode *features, double lat, double lon, json_append_element(features, f); } -JsonNode *geo_json(JsonNode *location_array) +JsonNode *geo_json(JsonNode *location_array, bool poi_only) { JsonNode *one, *j; JsonNode *feature_array, *fcollection; @@ -959,9 +964,15 @@ JsonNode *geo_json(JsonNode *location_array) json_foreach(one, location_array) { double lat = 0.0, lon = 0.0; - char *addr = "", *tid = ""; + char *addr = "", *tid = "", *poi = "", *isotst = ""; long tst = 0, vel = 0, acc = 0; + if (poi_only) { + if ((j = json_find_member(one, "poi")) == NULL) { + continue; + } + poi = j->string_; + } if ((j = json_find_member(one, "lat")) != NULL) { lat = j->number_; } @@ -974,6 +985,9 @@ JsonNode *geo_json(JsonNode *location_array) if ((j = json_find_member(one, "addr")) != NULL) { addr = j->string_; } + if ((j = json_find_member(one, "isotst")) != NULL) { + isotst = j->string_; + } if ((j = json_find_member(one, "tst")) != NULL) { tst = j->number_; } @@ -984,7 +998,7 @@ JsonNode *geo_json(JsonNode *location_array) acc = j->number_; } - append_to_feature_array(feature_array, lat, lon, tid, addr, tst, vel, acc); + append_to_feature_array(feature_array, lat, lon, tid, addr, tst, vel, acc, poi, isotst); } json_append_member(fcollection, "features", feature_array); diff --git a/storage.h b/storage.h index d196962..9b11820 100644 --- a/storage.h +++ b/storage.h @@ -17,6 +17,7 @@ typedef enum { RAWPAYLOAD, LINESTRING, XML, + GEOJSONPOI, } output_type; /* JSON payload types */ @@ -45,7 +46,7 @@ JsonNode *lister(char *username, char *device, time_t s_lo, time_t s_hi, int rev JsonNode *multilister(JsonNode *udpairs, time_t s_lo, time_t s_hi, int reverse); void locations(char *filename, JsonNode *obj, JsonNode *arr, time_t s_lo, time_t s_hi, output_type otype, int limit, JsonNode *fields, char *username, char *device); int make_times(char *time_from, time_t *s_lo, char *time_to, time_t *s_to, int hours); -JsonNode *geo_json(JsonNode *json); +JsonNode *geo_json(JsonNode *json, bool poi_only); JsonNode *geo_linestring(JsonNode *location_array); JsonNode *kill_datastore(char *username, char *device); JsonNode *last_users(char *user, char *device, JsonNode *fields);