From 6b8fb6e710f73559c8d3686d71dbd174ca8daac6 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Tue, 28 Nov 2017 18:44:50 -0800 Subject: binding: gps: add replay support for GPS traces Allow agl-service-gps to enter into demo mode using an previously recorded JSON GPS trace. This is entered by symlinking or copying a recorded trace log from the binding to ~/app-data/agl-service-gps/recording.log Bug-AGL: SPEC-1139 Change-Id: I5e1ac147000320035219b9183e4aeae1d9123429 Signed-off-by: Matt Ranostay --- binding/afm-gps-binding.c | 82 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 4 deletions(-) diff --git a/binding/afm-gps-binding.c b/binding/afm-gps-binding.c index f2a48fd..2ceb13f 100644 --- a/binding/afm-gps-binding.c +++ b/binding/afm-gps-binding.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #define AFB_BINDING_VERSION 2 #include @@ -39,7 +41,8 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; struct { FILE *current_file; - char buffer[32]; + char buffer[512]; + int replaying; int count; } recording; @@ -78,6 +81,10 @@ static json_object *populate_json_data(json_object *jresp) { json_object *value = NULL; + if (recording.replaying) { + return json_tokener_parse(recording.buffer); + } + if (data.fix.mode != MODE_3D) { json_object_put(jresp); return NULL; @@ -162,6 +169,11 @@ static void record(struct afb_req request) const char *value = afb_req_value(request, "state"); bool record = false; + if (recording.replaying) { + afb_req_fail(request, "failed", "Current in replaying mode"); + return; + } + if (!value) { pthread_mutex_lock(&mutex); jresp = gps_recording_state(json_object_new_object()); @@ -289,13 +301,25 @@ static void *data_poll(void *ptr) return NULL; } -static int init() +static void replay_thread(union sigval arg) +{ + FILE *fp = recording.current_file; + char *s = fgets(recording.buffer, sizeof(recording.buffer), fp); + + if (s == NULL) { + if (feof(fp)) + rewind(fp); + return; + } + + afb_event_push(location_event, json_tokener_parse(s)); +} + +static int gps_init() { const char *host, *port; int ret, tries = 5; - location_event = afb_daemon_make_event("location"); - host = getenv("AFBGPS_HOST") ? : "localhost"; port = getenv("AFBGPS_SERVICE") ? : "2947"; @@ -313,6 +337,56 @@ static int init() return pthread_create(&thread, NULL, &data_poll, NULL); } +static int replay_init() +{ + timer_t timer_id; + struct itimerspec ts; + struct sigevent se; + int ret; + + recording.current_file = fopen("recording.log", "r"); + if (recording.current_file == NULL) + return -EINVAL; + + se.sigev_notify = SIGEV_THREAD; + se.sigev_value.sival_ptr = &timer_id; + se.sigev_notify_function = replay_thread; + se.sigev_notify_attributes = NULL; + + // TODO: Allow detecting of an non-static 1 Hz GPS trace log + + ts.it_value.tv_sec = 1; + ts.it_value.tv_nsec = 0; + + ts.it_interval.tv_sec = 1; + ts.it_interval.tv_nsec = 0; + + ret = timer_create(CLOCK_REALTIME, &se, &timer_id); + if (ret < 0) + return ret; + + return timer_settime(timer_id, 0, &ts, NULL); +} + +/* + * Test to see if in demo mode first, then enable if not enable gpsd + */ + +static int init() +{ + int ret; + location_event = afb_daemon_make_event("location"); + + ret = replay_init(); + + if (!ret) + recording.replaying = 1; + else + gps_init(); + + return 0; +} + static const struct afb_verb_v2 binding_verbs[] = { { .verb = "location", .callback = get_data, .info = "Get GNSS data" }, { .verb = "record", .callback = record, .info = "Record GPS data" }, -- cgit 1.2.3-korg