diff options
author | Scott Murray <scott.murray@konsulko.com> | 2020-01-14 15:52:49 -0500 |
---|---|---|
committer | Scott Murray <scott.murray@konsulko.com> | 2020-01-14 15:52:49 -0500 |
commit | 754a92db4fac110a62ddb5549fd50dd001d1a859 (patch) | |
tree | 576fb69829ece13873b93f0caac13c5eae78969c | |
parent | f567ef6ddec3390bf0c9546b246e8e2a35389fbe (diff) |
Integrate navigation voice capability usehalibut_8.0.6halibut_8.0.5halibut/8.0.6halibut/8.0.58.0.68.0.5halibut
Add code to pull in the voice capabilities binding, subscribe to the
existing setDestination and cancelNavigation events, and use the data
that comes from them to set/clear the destination waypoint.
Bug-AGL: SPEC-3107
Signed-off-by: Scott Murray <scott.murray@konsulko.com>
Change-Id: Iaeb0283492cc89e8cff1a1558cab7554e32e3142
-rw-r--r-- | binding/navigation-api.c | 136 | ||||
-rw-r--r-- | conf.d/wgt/config.xml.in | 4 |
2 files changed, 129 insertions, 11 deletions
diff --git a/binding/navigation-api.c b/binding/navigation-api.c index e2aa6b1..1774e29 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,7 +79,7 @@ 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); + struct navigation_state *ns = navigation_get_userdata(); json_object *jresp = json_object_new_object(); const char *value; afb_event_t event; @@ -128,12 +136,11 @@ 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), *tmp = NULL; - + json_object *tmp = NULL; if (json_object_deep_copy(jresp, (json_object **) &tmp, NULL)) return; @@ -167,9 +174,14 @@ static void broadcast(afb_req_t request, const char *name, gboolean cache) 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) @@ -181,21 +193,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) { @@ -203,6 +293,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"); @@ -215,6 +327,7 @@ static int init(afb_api_t api) } afb_api_set_userdata(api, ns); + g_api = api; g_rw_lock_init(&ns->rw_lock); @@ -252,5 +365,6 @@ static const afb_verb_t binding_verbs[] = { const afb_binding_t afbBindingV3 = { .api = "navigation", .verbs = binding_verbs, + .onevent = onevent, .init = init, }; diff --git a/conf.d/wgt/config.xml.in b/conf.d/wgt/config.xml.in index 485407e..c0c1cfd 100644 --- a/conf.d/wgt/config.xml.in +++ b/conf.d/wgt/config.xml.in @@ -17,6 +17,10 @@ </feature> <feature name="urn:AGL:widget:required-api"> + <param name="vshl-capabilities" value="ws" /> + </feature> + + <feature name="urn:AGL:widget:required-binding"> <param name="@WIDGET_ENTRY_POINT@" value="local" /> </feature> </widget> |