From cdc8ecc6c8fcad4db982ef39a5322c3a5153e0f8 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Wed, 13 Sep 2017 21:21:33 -0700 Subject: binding: geofence: add dwell transition support Add support for detecting loitering in geofence and issue a dwell transition event. Also allow the loitering time to be configurable. Bug-AGL: SPEC-900 Change-Id: I3247b8efbbb90c2336884300b54984dad3efc407 Signed-off-by: Matt Ranostay --- binding/afm-geofence-binding.c | 76 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/binding/afm-geofence-binding.c b/binding/afm-geofence-binding.c index a154147..7c148ef 100644 --- a/binding/afm-geofence-binding.c +++ b/binding/afm-geofence-binding.c @@ -32,20 +32,26 @@ #define AFB_BINDING_VERSION 2 #include +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(void *)) +#define SECS_TO_USECS(x) (x * 1000000) +#define USECS_TO_SECS(x) (x / 1000000) + static struct afb_event fence_event; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static GList *fences = NULL; -#define ARRAY_SIZE(x) (sizeof(x)/sizeof(void *)) +static long dwell_transition_in_usecs = SECS_TO_USECS(20); /* * @name - geofence name * @triggered - geofence is currently triggered + * @timestamp - timestamp of last geofence 'entered' transition * @bbox - struct of bounding box coordinates */ struct geofence { gchar *name; bool triggered; + gint64 timestamp; struct { double min_latitude, max_latitude; double min_longitude, max_longitude; @@ -180,6 +186,7 @@ static void add_fence(struct afb_req request) } fence->name = g_strdup(name); + fence->timestamp = -1; fences = g_list_append(fences, fence); pthread_mutex_unlock(&mutex); @@ -241,6 +248,8 @@ static void list_fences(struct afb_req request) json_object_object_add(item, "within", json_object_new_boolean(g->triggered)); + json_object_object_add(item, "dwell", + json_object_new_boolean(g->triggered && g->timestamp == -1)); json_object_object_add(item, "bbox", json_bbox); json_object_object_add(jresp, g->name, item); } @@ -277,6 +286,49 @@ static int init() return 0; } +static inline bool dwell_transition_state(struct geofence *g) +{ + // zero dwell_transition_in_usecs means disabled + if (dwell_transition_in_usecs == 0) + return false; + + if (g->timestamp == -1) + return false; + + if ((g_get_monotonic_time() - g->timestamp) < dwell_transition_in_usecs) + return false; + + return true; +} + +static void dwell_transition(struct afb_req request) +{ + const char *value = afb_req_value(request, "value"); + json_object *jresp = NULL; + + pthread_mutex_lock(&mutex); + + if (value) { + long seconds = strtol(value, NULL, 10); + if (seconds < 0) { + afb_req_fail(request, "failed", "invalid input"); + pthread_mutex_unlock(&mutex); + return; + } + + dwell_transition_in_usecs = SECS_TO_USECS(seconds); + } + + jresp = json_object_new_object(); + json_object_object_add(jresp, "seconds", + json_object_new_int64(USECS_TO_SECS(dwell_transition_in_usecs))); + + pthread_mutex_unlock(&mutex); + + afb_req_success(request, jresp, + "loitering time in seconds to enter dwell transition"); +} + static void onevent(const char *event, struct json_object *object) { json_object *val = NULL; @@ -304,16 +356,29 @@ static void onevent(const char *event, struct json_object *object) struct json_object *jresp; bool current = within_bounding_box(latitude, longitude, g); - if (current == g->triggered) + if (current == g->triggered && !dwell_transition_state(g)) continue; jresp = json_object_new_object(); - g->triggered = current; json_object_object_add(jresp, "name", json_object_new_string(g->name)); - json_object_object_add(jresp, "state", - json_object_new_string(current ? "entered" : "exited")); + + if (current && g->triggered) { + json_object_object_add(jresp, "state", + json_object_new_string("dwell")); + g->timestamp = -1; + } else if (current) { + json_object_object_add(jresp, "state", + json_object_new_string("entered")); + g->timestamp = g_get_monotonic_time(); + } else { + json_object_object_add(jresp, "state", + json_object_new_string("exited")); + g->timestamp = -1; + } + + g->triggered = current; afb_event_push(fence_event, jresp); } @@ -327,6 +392,7 @@ static const struct afb_verb_v2 binding_verbs[] = { { .verb = "add_fence", .callback = add_fence, .info = "Add geofence" }, { .verb = "remove_fence", .callback = remove_fence, .info = "Remove geofence" }, { .verb = "list_fences", .callback = list_fences, .info = "List all curent geofences" }, + { .verb = "dwell_transition", .callback = dwell_transition, .info = "Set/get dwell transition delay" }, { } }; -- cgit 1.2.3-korg