X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fnavigation-api.c;h=07e5216a544f83e3792d4b7203ff8effe05d7580;hb=refs%2Ftags%2Fkoi%2F10.93.0;hp=19913a1102954a2d74b9ded6d6067ef2112882d7;hpb=2d9012ea413e3bce98f4f616a875a1a21cccbb81;p=apps%2Fagl-service-navigation.git diff --git a/binding/navigation-api.c b/binding/navigation-api.c index 19913a1..07e5216 100644 --- a/binding/navigation-api.c +++ b/binding/navigation-api.c @@ -33,9 +33,17 @@ #include "navigation-api.h" -struct navigation_state *navigation_get_userdata(afb_req_t request) { - afb_api_t api = afb_req_get_api(request); - return afb_api_get_userdata(api); +afb_api_t g_api; + +static const char *vshl_capabilities_events[] = { + "setDestination", + "cancelNavigation", + NULL, +}; + +struct navigation_state *navigation_get_userdata(void) +{ + return afb_api_get_userdata(g_api); } static afb_event_t get_event_from_value(struct navigation_state *ns, @@ -71,8 +79,8 @@ static json_object **get_storage_from_value(struct navigation_state *ns, static void navigation_subscribe_unsubscribe(afb_req_t request, gboolean unsub) { - struct navigation_state *ns = navigation_get_userdata(request); - json_object *jresp = json_object_new_object(); + struct navigation_state *ns = navigation_get_userdata(); + json_object *jresp = NULL; const char *value; afb_event_t event; int rc; @@ -113,6 +121,7 @@ static void navigation_subscribe_unsubscribe(afb_req_t request, return; } + jresp = json_object_new_object(); afb_req_success_f(request, jresp, "Navigation %s to event \"%s\"", !unsub ? "subscribed" : "unsubscribed", value); @@ -128,47 +137,52 @@ static void unsubscribe(afb_req_t request) navigation_subscribe_unsubscribe(request, TRUE); } -static void broadcast(afb_req_t request, const char *name, gboolean cache) +static void broadcast(json_object *jresp, const char *name, gboolean cache) { - struct navigation_state *ns = navigation_get_userdata(request); + struct navigation_state *ns = navigation_get_userdata(); afb_event_t event = get_event_from_value(ns, name); - json_object *jresp = afb_req_json(request); + json_object *tmp = NULL; + + if (json_object_deep_copy(jresp, (json_object **) &tmp, NULL)) + return; if (cache) { - json_object **storage = get_storage_from_value(ns, name); + json_object **storage; g_rw_lock_writer_lock(&ns->rw_lock); + storage = get_storage_from_value(ns, name); + if (*storage) json_object_put(*storage); + *storage = NULL; // increment reference for storage - json_object_get(jresp); - *storage = jresp; + json_object_get(tmp); + *storage = tmp; // increment reference for event - json_object_get(jresp); - afb_event_push(event, jresp); + json_object_get(tmp); + afb_event_push(event, tmp); g_rw_lock_writer_unlock(&ns->rw_lock); return; } - g_rw_lock_reader_lock(&ns->rw_lock); - - // increment reference for event - json_object_get(jresp); - afb_event_push(event, jresp); - - g_rw_lock_reader_unlock(&ns->rw_lock); + afb_event_push(event, tmp); } static void broadcast_status(afb_req_t request) { - broadcast(request, "status", TRUE); + json_object *jresp = afb_req_json(request); + broadcast(jresp, "status", TRUE); afb_req_success(request, NULL, "Broadcast status send"); + + // NOTE: If the Alexa SDK API for pushing local navigation + // updates gets exposed, send update to vshl-capabilities + // here. } static void broadcast_position(afb_req_t request) @@ -180,21 +194,99 @@ static void broadcast_position(afb_req_t request) if (position && !g_strcmp0(position, "car")) cache = TRUE; - broadcast(request, "position", cache); + json_object *jresp = afb_req_json(request); + broadcast(jresp, "position", cache); afb_req_success(request, NULL, "Broadcast position send"); + + // NOTE: If the Alexa SDK API for pushing local navigation + // updates gets exposed, send update to vshl-capabilities + // here. } static void broadcast_waypoints(afb_req_t request) { - broadcast(request, "waypoints", TRUE); + json_object *jresp = afb_req_json(request); + broadcast(jresp, "waypoints", TRUE); afb_req_success(request, NULL, "Broadcast waypoints send"); + + // NOTE: If the Alexa SDK API for pushing local navigation + // updates gets exposed, send update to vshl-capabilities + // here. +} + +static void handle_setDestination_event(struct json_object *object) +{ + json_object *jdest = NULL; + json_object_object_get_ex(object, "destination", &jdest); + if(!jdest) { + AFB_WARNING("setDestination event missing destination element"); + return; + } + + json_object *jcoord = NULL; + json_object_object_get_ex(jdest, "coordinate", &jcoord); + if(!jcoord) { + AFB_WARNING("setDestination event missing coordinate element"); + return; + } + + json_object *jlat = NULL; + json_object_object_get_ex(jcoord, "latitudeInDegrees", &jlat); + if(!jlat) + return; + errno = 0; + double lat = json_object_get_double(jlat); + if(errno != 0) + return; + + json_object *jlon = NULL; + json_object_object_get_ex(jcoord, "longitudeInDegrees", &jlon); + if(!jlon) + return; + double lon = json_object_get_double(jlon); + if(errno != 0) + return; + + json_object *jobj = json_object_new_object(); + json_object *jpoints = json_object_new_array(); + json_object *jpoint = json_object_new_object(); + jlat = json_object_new_double(lat); + jlon = json_object_new_double(lon); + json_object_object_add(jpoint, "latitude", jlat); + json_object_object_add(jpoint, "longitude", jlon); + json_object_array_add(jpoints, jpoint); + json_object_object_add(jobj, "points", jpoints); + broadcast(jobj, "waypoints", TRUE); +} + +static void handle_cancelNavigation_event(struct json_object *object) +{ + json_object *jobj = json_object_new_object(); + json_object *jstate = json_object_new_string("stop"); + json_object_object_add(jobj, "state", jstate); + broadcast(jobj, "status", TRUE); +} + +static void onevent(afb_api_t api, const char *event, struct json_object *object) +{ + if(!event) + return; + + if(strcmp(event, "vshl-capabilities/setDestination") == 0) { + handle_setDestination_event(object); + } else if(strcmp(event, "vshl-capabilities/cancelNavigation") == 0) { + handle_cancelNavigation_event(object); + } else { + AFB_WARNING("Unhandled vshl-capabilities event"); + } } static int init(afb_api_t api) { struct navigation_state *ns; + int rc; ns = g_try_malloc0(sizeof(*ns)); if (!ns) { @@ -202,6 +294,28 @@ static int init(afb_api_t api) return -ENOMEM; } + rc = afb_daemon_require_api("vshl-capabilities", 1); + if (!rc) { + const char **tmp = vshl_capabilities_events; + json_object *args = json_object_new_object(); + json_object *actions = json_object_new_array(); + + while (*tmp) { + json_object_array_add(actions, json_object_new_string(*tmp++)); + } + json_object_object_add(args, "actions", actions); + if(json_object_array_length(actions)) { + rc = afb_api_call_sync(api, "vshl-capabilities", "navigation/subscribe", + args, NULL, NULL, NULL); + if(rc != 0) + AFB_WARNING("afb_api_call_sync returned %d", rc); + } else { + json_object_put(args); + } + } else { + AFB_WARNING("unable to initialize vshl-capabilities binding"); + } + ns->status_event = afb_daemon_make_event("status"); ns->position_event = afb_daemon_make_event("position"); ns->waypoints_event = afb_daemon_make_event("waypoints"); @@ -214,6 +328,7 @@ static int init(afb_api_t api) } afb_api_set_userdata(api, ns); + g_api = api; g_rw_lock_init(&ns->rw_lock); @@ -251,5 +366,6 @@ static const afb_verb_t binding_verbs[] = { const afb_binding_t afbBindingV3 = { .api = "navigation", .verbs = binding_verbs, + .onevent = onevent, .init = init, };