c5a0138ec1305b54eb650f794577981a4c9733e1
[apps/agl-service-can-low-level.git] / low-can-binding / binding / low-can-cb.cpp
1 /*
2  * Copyright (C) 2015, 2016 "IoT.bzh"
3  * Author "Romain Forlot" <romain.forlot@iot.bzh>
4  * Author "Loic Collignon" <loic.collignon@iot.bzh>
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *       http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include "low-can-hat.hpp"
20 #include "low-can-apidef.h"
21
22 #include <map>
23 #include <queue>
24 #include <mutex>
25 #include <vector>
26 #include <thread>
27 #include <json-c/json.h>
28 #include <systemd/sd-event.h>
29
30 #include "openxc.pb.h"
31 #include "application.hpp"
32 #include "../can/can-encoder.hpp"
33 #include "../can/can-bus.hpp"
34 #include "../can/can-signals.hpp"
35 #include "../can/can-message.hpp"
36 #include "../utils/signals.hpp"
37 #include "../diagnostic/diagnostic-message.hpp"
38 #include "../utils/openxc-utils.hpp"
39
40 ///******************************************************************************
41 ///
42 ///             SystemD event loop Callbacks
43 ///
44 ///*******************************************************************************/
45
46 void on_no_clients(std::shared_ptr<low_can_subscription_t> can_subscription, uint32_t pid, std::map<int, std::shared_ptr<low_can_subscription_t> >& s)
47 {
48         bool is_permanent_recurring_request = false;
49
50         if( ! can_subscription->get_diagnostic_message().empty() && can_subscription->get_diagnostic_message(pid) != nullptr)
51         {
52                 DiagnosticRequest diag_req = can_subscription->get_diagnostic_message(pid)->build_diagnostic_request();
53                 active_diagnostic_request_t* adr = application_t::instance().get_diagnostic_manager().find_recurring_request(diag_req);
54                 if( adr != nullptr)
55                 {
56                         is_permanent_recurring_request = adr->get_permanent();
57
58                         if(! is_permanent_recurring_request)
59                                 application_t::instance().get_diagnostic_manager().cleanup_request(adr, true);
60                 }
61         }
62
63         if(! is_permanent_recurring_request)
64                 on_no_clients(can_subscription, s);
65 }
66
67 void on_no_clients(std::shared_ptr<low_can_subscription_t> can_subscription, std::map<int, std::shared_ptr<low_can_subscription_t> >& s)
68 {
69         auto it = s.find(can_subscription->get_index());
70         s.erase(it);
71 }
72
73 static void push_n_notify(const can_message_t& cm)
74 {
75         can_bus_t& cbm = application_t::instance().get_can_bus_manager();
76         {
77                 std::lock_guard<std::mutex> can_message_lock(cbm.get_can_message_mutex());
78                 cbm.push_new_can_message(cm);
79         }
80         cbm.get_new_can_message_cv().notify_one();
81 }
82
83 int read_message(sd_event_source *event_source, int fd, uint32_t revents, void *userdata)
84 {
85         low_can_subscription_t* can_subscription = (low_can_subscription_t*)userdata;
86         if ((revents & EPOLLIN) != 0)
87         {
88                 can_message_t cm;
89                 utils::socketcan_bcm_t& s = can_subscription->get_socket();
90                 s >> cm;
91
92                 // Sure we got a valid CAN message ?
93                 if(! cm.get_id() == 0 && ! cm.get_length() == 0)
94                         {push_n_notify(cm);}
95         }
96
97         // check if error or hangup
98         if ((revents & (EPOLLERR|EPOLLRDHUP|EPOLLHUP)) != 0)
99         {
100                 sd_event_source_unref(event_source);
101                 can_subscription->get_socket().close();
102         }
103         return 0;
104 }
105
106 ///******************************************************************************
107 ///
108 ///             Subscription and unsubscription
109 ///
110 ///*******************************************************************************/
111
112 static int make_subscription_unsubscription(afb_req_t request,
113                                             std::shared_ptr<low_can_subscription_t>& can_subscription,
114                                             std::map<int, std::shared_ptr<low_can_subscription_t> >& s,
115                                             bool subscribe)
116 {
117         /* Make the subscription or unsubscription to the event (if request is not null) */
118         if(request &&
119            ((subscribe ? afb_req_subscribe : afb_req_unsubscribe)(request, s[can_subscription->get_index()]->get_event())) < 0)
120         {
121                 AFB_ERROR("Operation goes wrong for signal: %s", can_subscription->get_name().c_str());
122                 return -1;
123         }
124         return 0;
125 }
126
127 static int create_event_handle(std::shared_ptr<low_can_subscription_t>& can_subscription,
128                                std::map<int, std::shared_ptr<low_can_subscription_t> >& s)
129 {
130         int sub_index = can_subscription->get_index();
131         can_subscription->set_event(afb_daemon_make_event(can_subscription->get_name().c_str()));
132         s[sub_index] = can_subscription;
133         if (!afb_event_is_valid(s[sub_index]->get_event()))
134         {
135                 AFB_ERROR("Can't create an event for %s, something goes wrong.", can_subscription->get_name().c_str());
136                 return -1;
137         }
138         return 0;
139 }
140
141 /// @brief This will determine if an event handle needs to be created and checks if
142 /// we got a valid afb_event to get subscribe or unsubscribe. After that launch the subscription or unsubscription
143 /// against the application framework using that event handle.
144 static int subscribe_unsubscribe_signal(afb_req_t request,
145                                         bool subscribe,
146                                         std::shared_ptr<low_can_subscription_t>& can_subscription,
147                                         std::map<int, std::shared_ptr<low_can_subscription_t> >& s)
148 {
149         int ret = -1;
150         int sub_index = can_subscription->get_index();
151
152         if (can_subscription && s.find(sub_index) != s.end())
153         {
154                 if (!afb_event_is_valid(s[sub_index]->get_event()) && !subscribe)
155                 {
156                         AFB_NOTICE("Event isn't valid, no need to unsubscribed.");
157                         ret = -1;
158                 }
159                 ret = 0;
160         }
161         else
162         {
163                 /* Event doesn't exist , so let's create it */
164                 s[sub_index] = can_subscription;
165                 ret = create_event_handle(can_subscription, s);
166         }
167
168         // Checks if the event handler is correctly created, if it is, it
169         // performs the subscription or unsubscription operations.
170         if (ret < 0)
171                 return ret;
172         return make_subscription_unsubscription(request, can_subscription, s, subscribe);
173 }
174
175 static int add_to_event_loop(std::shared_ptr<low_can_subscription_t>& can_subscription)
176 {
177                 struct sd_event_source* event_source = nullptr;
178                 return ( sd_event_add_io(afb_daemon_get_event_loop(),
179                         &event_source,
180                         can_subscription->get_socket().socket(),
181                         EPOLLIN,
182                         read_message,
183                         can_subscription.get()));
184 }
185
186 static int subscribe_unsubscribe_diagnostic_messages(afb_req_t request,
187                                                      bool subscribe,
188                                                      std::vector<std::shared_ptr<diagnostic_message_t> > diagnostic_messages,
189                                                      struct event_filter_t& event_filter,
190                                                      std::map<int, std::shared_ptr<low_can_subscription_t> >& s,
191                                                      bool perm_rec_diag_req)
192 {
193         int rets = 0;
194         application_t& app = application_t::instance();
195         diagnostic_manager_t& diag_m = app.get_diagnostic_manager();
196
197         for(const auto& sig : diagnostic_messages)
198         {
199                 DiagnosticRequest* diag_req = new DiagnosticRequest(sig->build_diagnostic_request());
200                 event_filter.frequency = event_filter.frequency == 0 ? sig->get_frequency() : event_filter.frequency;
201                 std::shared_ptr<low_can_subscription_t> can_subscription;
202
203                 auto it =  std::find_if(s.begin(), s.end(), [&sig](std::pair<int, std::shared_ptr<low_can_subscription_t> > sub){ return (! sub.second->get_diagnostic_message().empty());});
204                 can_subscription = it != s.end() ?
205                         it->second :
206                         std::make_shared<low_can_subscription_t>(low_can_subscription_t(event_filter));
207                 // If the requested diagnostic message is not supported by the car then unsubcribe it
208                 // no matter what we want, worst case will be a failed unsubscription but at least we won't
209                 // poll a PID for nothing.
210                 if(sig->get_supported() && subscribe)
211                 {
212                         if (!app.isEngineOn())
213                                 AFB_WARNING("signal: Engine is off, %s won't received responses until it's on",  sig->get_name().c_str());
214
215                         diag_m.add_recurring_request(diag_req, sig->get_name().c_str(), false, sig->get_decoder(), sig->get_callback(), event_filter.frequency, perm_rec_diag_req);
216                         if(can_subscription->create_rx_filter(sig) < 0)
217                                 {return -1;}
218                         AFB_DEBUG("Signal: %s subscribed", sig->get_name().c_str());
219                         if(it == s.end() && add_to_event_loop(can_subscription) < 0)
220                         {
221                                 diag_m.cleanup_request(
222                                         diag_m.find_recurring_request(*diag_req), true);
223                                 AFB_WARNING("signal: %s isn't supported. Canceling operation.",  sig->get_name().c_str());
224                                 return -1;
225                         }
226                 }
227                 else
228                 {
229                         if(sig->get_supported())
230                         {AFB_DEBUG("%s cancelled due to unsubscribe", sig->get_name().c_str());}
231                         else
232                         {
233                                 AFB_WARNING("signal: %s isn't supported. Canceling operation.", sig->get_name().c_str());
234                                 return -1;
235                         }
236                 }
237                 int ret = subscribe_unsubscribe_signal(request, subscribe, can_subscription, s);
238                 if(ret < 0)
239                         return ret;
240
241                 rets++;
242         }
243
244         return rets;
245 }
246
247 static int subscribe_unsubscribe_can_signals(afb_req_t request,
248                                              bool subscribe,
249                                              std::vector<std::shared_ptr<can_signal_t> > can_signals,
250                                              struct event_filter_t& event_filter,
251                                              std::map<int, std::shared_ptr<low_can_subscription_t> >& s)
252 {
253         int rets = 0;
254         for(const auto& sig: can_signals)
255         {
256                 auto it =  std::find_if(s.begin(), s.end(), [&sig, &event_filter](std::pair<int, std::shared_ptr<low_can_subscription_t> > sub){ return sub.second->is_signal_subscription_corresponding(sig, event_filter) ; });
257                 std::shared_ptr<low_can_subscription_t> can_subscription;
258                 if(it != s.end())
259                 {
260                          can_subscription = it->second;
261                 }
262                 else
263                 {
264                          can_subscription = std::make_shared<low_can_subscription_t>(low_can_subscription_t(event_filter));
265                         if(can_subscription->create_rx_filter(sig) < 0)
266                                 {return -1;}
267                         if(add_to_event_loop(can_subscription) < 0)
268                                 {return -1;}
269                 }
270
271                 if(subscribe_unsubscribe_signal(request, subscribe, can_subscription, s) < 0)
272                         {return -1;}
273
274                 rets++;
275                 AFB_DEBUG("signal: %s subscribed", sig->get_name().c_str());
276         }
277         return rets;
278 }
279
280 ///
281 /// @brief subscribe to all signals in the vector signals
282 ///
283 /// @param[in] afb_req request : contains original request use to subscribe or unsubscribe
284 /// @param[in] subscribe boolean value, which chooses between a subscription operation or an unsubscription
285 /// @param[in] signals -  struct containing vectors with can_signal_t and diagnostic_messages to subscribe
286 ///
287 /// @return Number of correctly subscribed signal
288 ///
289 static int subscribe_unsubscribe_signals(afb_req_t request,
290                                          bool subscribe,
291                                          const struct utils::signals_found& signals,
292                                          struct event_filter_t& event_filter)
293 {
294         int rets = 0;
295         utils::signals_manager_t& sm = utils::signals_manager_t::instance();
296
297         std::lock_guard<std::mutex> subscribed_signals_lock(sm.get_subscribed_signals_mutex());
298         std::map<int, std::shared_ptr<low_can_subscription_t> >& s = sm.get_subscribed_signals();
299
300         rets += subscribe_unsubscribe_diagnostic_messages(request, subscribe, signals.diagnostic_messages, event_filter, s, false);
301         rets += subscribe_unsubscribe_can_signals(request, subscribe, signals.can_signals, event_filter, s);
302
303         return rets;
304 }
305
306 static int one_subscribe_unsubscribe(afb_req_t request,
307                                      bool subscribe,
308                                      const std::string& tag,
309                                      json_object* args)
310 {
311         int ret = 0;
312         struct event_filter_t event_filter;
313         struct json_object  *filter, *obj;
314         struct utils::signals_found sf;
315
316         // computes the filter
317         if (json_object_object_get_ex(args, "filter", &filter))
318         {
319                 if (json_object_object_get_ex(filter, "frequency", &obj)
320                 && (json_object_is_type(obj, json_type_double) || json_object_is_type(obj, json_type_int)))
321                         {event_filter.frequency = (float)json_object_get_double(obj);}
322                 if (json_object_object_get_ex(filter, "min", &obj)
323                 && (json_object_is_type(obj, json_type_double) || json_object_is_type(obj, json_type_int)))
324                         {event_filter.min = (float)json_object_get_double(obj);}
325                 if (json_object_object_get_ex(filter, "max", &obj)
326                 && (json_object_is_type(obj, json_type_double) || json_object_is_type(obj, json_type_int)))
327                         {event_filter.max = (float)json_object_get_double(obj);}
328         }
329
330         // subscribe or unsubscribe
331         openxc_DynamicField search_key = build_DynamicField(tag);
332         sf = utils::signals_manager_t::instance().find_signals(search_key);
333         if (sf.can_signals.empty() && sf.diagnostic_messages.empty())
334         {
335                 AFB_NOTICE("No signal(s) found for %s.", tag.c_str());
336                 ret = -1;
337         }
338         else
339                 {ret = subscribe_unsubscribe_signals(request, subscribe, sf, event_filter);}
340
341         return ret;
342 }
343 static int process_one_subscribe_args(afb_req_t request, bool subscribe, json_object *args)
344 {
345         int rc = 0, rc2=0;
346         json_object *x = nullptr, *event = nullptr;
347         if(args == NULL ||
348                 !json_object_object_get_ex(args, "event", &event))
349         {
350                 rc = one_subscribe_unsubscribe(request, subscribe, "*", args);
351         }
352         else if (json_object_get_type(event) != json_type_array)
353         {
354                 rc = one_subscribe_unsubscribe(request, subscribe, json_object_get_string(event), args);
355         }
356         else
357         {
358                 for (int i = 0 ; i < json_object_array_length(event); i++)
359                 {
360                         x = json_object_array_get_idx(event, i);
361                         rc2 = one_subscribe_unsubscribe(request, subscribe, json_object_get_string(x), args);
362                         if (rc >= 0)
363                                 rc = rc2 >= 0 ? rc + rc2 : rc2;
364                 }
365         }
366         return rc;
367 }
368
369 static void do_subscribe_unsubscribe(afb_req_t request, bool subscribe)
370 {
371         int rc = 0;
372         struct json_object *args, *x;
373
374         args = afb_req_json(request);
375         if (json_object_get_type(args) == json_type_array)
376         {
377                 for(int i = 0; i < json_object_array_length(args); i++)
378                 {
379                         x = json_object_array_get_idx(args, i);
380                         rc += process_one_subscribe_args(request, subscribe, x);
381                 }
382         }
383         else
384         {
385                 rc += process_one_subscribe_args(request, subscribe, args);
386         }
387
388         if (rc >= 0)
389                 afb_req_success(request, NULL, NULL);
390         else
391                 afb_req_fail(request, "error", NULL);
392 }
393
394 void auth(afb_req_t request)
395 {
396         afb_req_session_set_LOA(request, 1);
397         afb_req_success(request, NULL, NULL);
398 }
399
400 void subscribe(afb_req_t request)
401 {
402         do_subscribe_unsubscribe(request, true);
403 }
404
405 void unsubscribe(afb_req_t request)
406 {
407         do_subscribe_unsubscribe(request, false);
408 }
409
410 static int send_frame(const std::string& bus_name, const struct can_frame& cf)
411 {
412         std::map<std::string, std::shared_ptr<low_can_socket_t> >& cd = application_t::instance().get_can_devices();
413
414         if( cd.count(bus_name) == 0)
415                 {cd[bus_name] = std::make_shared<low_can_socket_t>(low_can_socket_t());}
416
417         return cd[bus_name]->tx_send(cf, bus_name);
418 }
419
420 static int write_raw_frame(const std::string& bus_name, uint32_t can_id, uint8_t can_dlc, struct json_object* can_data)
421 {
422         int rc = 0;
423         struct can_frame cf;
424
425         ::memset(&cf, 0, sizeof(cf));
426
427         cf.can_id = can_id;
428         cf.can_dlc = can_dlc;
429
430         struct json_object *x;
431         size_t n = json_object_array_length(can_data);
432         if(n <= 8)
433         {
434                 for (int i = 0 ; i < n ; i++)
435                 {
436                         x = json_object_array_get_idx(can_data, i);
437                         cf.data[i] = json_object_get_type(x) == json_type_int ? (uint8_t)json_object_get_int(x) : 0;
438                 }
439         }
440
441         const std::string found_device = application_t::instance().get_can_bus_manager().get_can_device_name(bus_name);
442         if( ! found_device.empty())
443         {
444                 rc = send_frame(found_device, cf);
445         }
446
447         return rc;
448 }
449 static int write_signal(const std::string& name, uint64_t value)
450 {
451         int rc = 0;
452         struct can_frame cf;
453         struct utils::signals_found sf;
454
455         ::memset(&cf, 0, sizeof(cf));
456
457         openxc_DynamicField search_key = build_DynamicField(name);
458         sf = utils::signals_manager_t::instance().find_signals(search_key);
459
460         if (sf.can_signals.empty())
461         {
462                 AFB_WARNING("No signal(s) found for %s. Message not sent.", name.c_str());
463                 rc = -1;
464         }
465         else
466         {
467                 for(const auto& sig: sf.can_signals)
468                 {
469                         if(sig->get_writable())
470                         {
471                                 cf = encoder_t::build_frame(sig, value);
472                                 const std::string bus_name = sig->get_message()->get_bus_device_name();
473                                 rc = send_frame(bus_name, cf);
474                         }
475                         else
476                         {
477                                 AFB_WARNING("%s isn't writable. Message not sent.", sig->get_name().c_str());
478                                 return -1;
479                         }
480                 }
481         }
482
483         return rc;
484 }
485
486 void write(afb_req_t request)
487 {
488         int rc = 0;
489         struct json_object* args = nullptr,
490                 *json_name = nullptr,
491                 *json_value = nullptr;
492
493         args = afb_req_json(request);
494
495         // Process about Raw CAN message on CAN bus directly
496         if (args != NULL &&
497                 (json_object_object_get_ex(args, "bus_name", &json_name) && json_object_is_type(json_name, json_type_string) ) &&
498                 (json_object_object_get_ex(args, "frame", &json_value) && json_object_is_type(json_value, json_type_object) ))
499         {
500                 struct json_object* json_can_id = nullptr,
501                         *json_can_dlc = nullptr,
502                         *json_can_data = nullptr;
503
504                 if( (json_object_object_get_ex(json_value, "can_id", &json_can_id) && (json_object_is_type(json_can_id, json_type_double) || json_object_is_type(json_can_id, json_type_int))) &&
505                         (json_object_object_get_ex(json_value, "can_dlc", &json_can_dlc) && (json_object_is_type(json_can_dlc, json_type_double) || json_object_is_type(json_can_dlc, json_type_int))) &&
506                         (json_object_object_get_ex(json_value, "can_data", &json_can_data) && json_object_is_type(json_can_data, json_type_array) ))
507                 {
508                         rc = write_raw_frame(json_object_get_string(json_name),
509                                 json_object_get_int(json_can_id),
510                                 (uint8_t)json_object_get_int(json_can_dlc),
511                                 json_can_data);
512                 }
513                 else
514                 {
515                         AFB_ERROR("Frame object malformed (must be \n \"frame\": {\"can_id\": int, \"can_dlc\": int, \"can_data\": [ int, int , int, int ,int , int ,int ,int]}");
516                         rc = -1;
517                 }
518         }
519         // Search signal then encode value.
520         else if(args != NULL &&
521                 (json_object_object_get_ex(args, "signal_name", &json_name) && json_object_is_type(json_name, json_type_string)) &&
522                 (json_object_object_get_ex(args, "signal_value", &json_value) && (json_object_is_type(json_value, json_type_double) || json_object_is_type(json_value, json_type_int))))
523         {
524                 rc = write_signal(json_object_get_string(json_name),
525                         (uint64_t)json_object_get_double(json_value));
526         }
527         else
528         {
529                 AFB_ERROR("Request argument malformed. Please use the following syntax:");
530                 rc = -1;
531         }
532
533         if (rc >= 0)
534                 afb_req_success(request, NULL, NULL);
535         else
536                 afb_req_fail(request, "error", NULL);
537 }
538
539 static struct json_object *get_signals_value(const std::string& name)
540 {
541         struct utils::signals_found sf;
542         struct json_object *ans = nullptr;
543
544         openxc_DynamicField search_key = build_DynamicField(name);
545         sf = utils::signals_manager_t::instance().find_signals(search_key);
546
547         if (sf.can_signals.empty())
548         {
549                 AFB_WARNING("No signal(s) found for %s.", name.c_str());
550                 return NULL;
551         }
552         ans = json_object_new_array();
553         for(const auto& sig: sf.can_signals)
554         {
555                 struct json_object *jobj = json_object_new_object();
556                 json_object_object_add(jobj, "event", json_object_new_string(sig->get_name().c_str()));
557                 json_object_object_add(jobj, "value", json_object_new_double(sig->get_last_value()));
558                 json_object_array_add(ans, jobj);
559         }
560
561         return ans;
562 }
563 void get(afb_req_t request)
564 {
565         int rc = 0;
566         struct json_object* args = nullptr,
567                 *json_name = nullptr;
568         json_object *ans = nullptr;
569
570         args = afb_req_json(request);
571
572         // Process about Raw CAN message on CAN bus directly
573         if (args != nullptr &&
574                 (json_object_object_get_ex(args, "event", &json_name) && json_object_is_type(json_name, json_type_string) ))
575         {
576                 ans = get_signals_value(json_object_get_string(json_name));
577                 if (!ans)
578                         rc = -1;
579         }
580         else
581         {
582                 AFB_ERROR("Request argument malformed. Please use the following syntax:");
583                 rc = -1;
584         }
585
586         if (rc >= 0)
587                 afb_req_success(request, ans, NULL);
588         else
589                 afb_req_fail(request, "error", NULL);
590 }
591
592
593 static struct json_object *list_can_message(const std::string& name)
594 {
595         struct utils::signals_found sf;
596         struct json_object *ans = nullptr;
597
598         openxc_DynamicField search_key = build_DynamicField(name);
599         sf = utils::signals_manager_t::instance().find_signals(search_key);
600
601         if (sf.can_signals.empty() && sf.diagnostic_messages.empty())
602         {
603                 AFB_WARNING("No signal(s) found for %s.", name.c_str());
604                 return NULL;
605         }
606         ans = json_object_new_array();
607         for(const auto& sig: sf.can_signals)
608         {
609                 json_object_array_add(ans,
610                         json_object_new_string(sig->get_name().c_str()));
611         }
612         for(const auto& sig: sf.diagnostic_messages)
613         {
614                 json_object_array_add(ans,
615                         json_object_new_string(sig->get_name().c_str()));
616         }
617
618         return ans;
619 }
620
621 void list(afb_req_t request)
622 {
623         int rc = 0;
624         json_object *ans = nullptr;
625         struct json_object* args = nullptr,
626                 *json_name = nullptr;
627         args = afb_req_json(request);
628         const char *name;
629         if ((args != nullptr) &&
630                 (json_object_object_get_ex(args, "event", &json_name) && json_object_is_type(json_name, json_type_string)))
631         {
632                 name = json_object_get_string(json_name);
633         }
634         else
635         {
636                 name = "*";
637         }
638
639         ans = list_can_message(name);
640         if (!ans)
641                 rc = -1;
642
643         if (rc >= 0)
644                 afb_req_success(request, ans, NULL);
645         else
646                 afb_req_fail(request, "error", NULL);
647 }
648
649 /// @brief Initialize the binding.
650 ///
651 /// @param[in] service Structure which represent the Application Framework Binder.
652 ///
653 /// @return Exit code, zero if success.
654 int init_binding(afb_api_t api)
655 {
656         uint32_t ret = 1;
657         can_bus_t& can_bus_manager = application_t::instance().get_can_bus_manager();
658
659         can_bus_manager.set_can_devices();
660         can_bus_manager.start_threads();
661
662         /// Initialize Diagnostic manager that will handle obd2 requests.
663         /// We pass by default the first CAN bus device to its Initialization.
664         /// TODO: be able to choose the CAN bus device that will be use as Diagnostic bus.
665         if(application_t::instance().get_diagnostic_manager().initialize())
666                 ret = 0;
667
668         // Add a recurring dignostic message request to get engine speed at all times.
669         openxc_DynamicField search_key = build_DynamicField("diagnostic_messages.engine.speed");
670         struct utils::signals_found sf = utils::signals_manager_t::instance().find_signals(search_key);
671
672         if(sf.can_signals.empty() && sf.diagnostic_messages.size() == 1)
673         {
674                 afb_req_t request = nullptr;
675
676                 struct event_filter_t event_filter;
677                 event_filter.frequency = sf.diagnostic_messages.front()->get_frequency();
678
679                 utils::signals_manager_t& sm = utils::signals_manager_t::instance();
680                 std::map<int, std::shared_ptr<low_can_subscription_t> >& s = sm.get_subscribed_signals();
681
682                 subscribe_unsubscribe_diagnostic_messages(request, true, sf.diagnostic_messages, event_filter, s, true);
683         }
684
685         if(ret)
686                 AFB_ERROR("There was something wrong with CAN device Initialization.");
687
688         return ret;
689 }