2 * Copyright (C) 2019 Konsulko Group
3 * Author: Matt Ranostay <matt.ranostay@konsulko.com>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
27 #include <glib/gstdio.h>
29 #include <json-c/json.h>
31 #define AFB_BINDING_VERSION 3
32 #include <afb/afb-binding.h>
34 #include "navigation-api.h"
36 struct navigation_state *navigation_get_userdata(afb_req_t request) {
37 afb_api_t api = afb_req_get_api(request);
38 return afb_api_get_userdata(api);
41 static afb_event_t get_event_from_value(struct navigation_state *ns,
44 if (!g_strcmp0(value, "status"))
45 return ns->status_event;
47 if (!g_strcmp0(value, "position"))
48 return ns->position_event;
50 if (!g_strcmp0(value, "waypoints"))
51 return ns->waypoints_event;
56 static json_object **get_storage_from_value(struct navigation_state *ns,
59 if (!g_strcmp0(value, "status"))
60 return &ns->status_storage;
62 if (!g_strcmp0(value, "position"))
63 return &ns->position_storage;
65 if (!g_strcmp0(value, "waypoints"))
66 return &ns->waypoints_storage;
71 static void navigation_subscribe_unsubscribe(afb_req_t request,
74 struct navigation_state *ns = navigation_get_userdata(request);
75 json_object *jresp = json_object_new_object();
80 value = afb_req_value(request, "value");
82 afb_req_fail_f(request, "failed", "Missing \"value\" event");
86 event = get_event_from_value(ns, value);
88 afb_req_fail_f(request, "failed", "Bad \"value\" event \"%s\"",
95 rc = afb_req_subscribe(request, event);
97 g_rw_lock_reader_lock(&ns->rw_lock);
98 storage = *get_storage_from_value(ns, value);
100 // increment reference counter, and send out cached value
101 json_object_get(storage);
102 afb_event_push(event, storage);
104 g_rw_lock_reader_unlock(&ns->rw_lock);
106 rc = afb_req_unsubscribe(request, event);
109 afb_req_fail_f(request, "failed",
110 "%s error on \"value\" event \"%s\"",
111 !unsub ? "subscribe" : "unsubscribe",
116 afb_req_success_f(request, jresp, "Navigation %s to event \"%s\"",
117 !unsub ? "subscribed" : "unsubscribed",
121 static void subscribe(afb_req_t request)
123 navigation_subscribe_unsubscribe(request, FALSE);
126 static void unsubscribe(afb_req_t request)
128 navigation_subscribe_unsubscribe(request, TRUE);
131 static void broadcast(afb_req_t request, const char *name, gboolean cache)
133 struct navigation_state *ns = navigation_get_userdata(request);
134 afb_event_t event = get_event_from_value(ns, name);
135 json_object *jresp = afb_req_json(request);
138 json_object **storage = get_storage_from_value(ns, name);
140 g_rw_lock_writer_lock(&ns->rw_lock);
143 json_object_put(*storage);
145 // increment reference for storage
146 json_object_get(jresp);
149 g_rw_lock_writer_unlock(&ns->rw_lock);
152 // increment reference for event
153 json_object_get(jresp);
154 afb_event_push(event, jresp);
157 static void broadcast_status(afb_req_t request)
159 broadcast(request, "status", TRUE);
161 afb_req_success(request, NULL, "Broadcast status send");
164 static void broadcast_position(afb_req_t request)
166 const char *position = afb_req_value(request, "position");
167 gboolean cache = FALSE;
169 // only send out a car position event on subscribe
170 if (position && !g_strcmp0(position, "car"))
173 broadcast(request, "position", cache);
175 afb_req_success(request, NULL, "Broadcast position send");
178 static void broadcast_waypoints(afb_req_t request)
180 broadcast(request, "waypoints", TRUE);
182 afb_req_success(request, NULL, "Broadcast waypoints send");
185 static int init(afb_api_t api)
187 struct navigation_state *ns;
189 ns = g_try_malloc0(sizeof(*ns));
191 AFB_ERROR("out of memory allocating navigation state");
195 ns->status_event = afb_daemon_make_event("status");
196 ns->position_event = afb_daemon_make_event("position");
197 ns->waypoints_event = afb_daemon_make_event("waypoints");
199 if (!afb_event_is_valid(ns->status_event) ||
200 !afb_event_is_valid(ns->position_event) ||
201 !afb_event_is_valid(ns->waypoints_event)) {
202 AFB_ERROR("Cannot create events");
206 afb_api_set_userdata(api, ns);
208 g_rw_lock_init(&ns->rw_lock);
213 static const afb_verb_t binding_verbs[] = {
216 .callback = subscribe,
217 .info = "Subscribe to event"
219 .verb = "unsubscribe",
220 .callback = unsubscribe,
221 .info = "Unsubscribe to event"
223 .verb = "broadcast_status",
224 .callback = broadcast_status,
225 .info = "Allows clients to broadcast status events"
227 .verb = "broadcast_position",
228 .callback = broadcast_position,
229 .info = "Broadcast out position event"
231 .verb = "broadcast_waypoints",
232 .callback = broadcast_waypoints,
233 .info = "Broadcast out waypoint event"
239 * description of the binding for afb-daemon
241 const afb_binding_t afbBindingV3 = {
243 .verbs = binding_verbs,