binding: add preinit function to load the config
[apps/agl-service-can-low-level.git] / low-can-binding / binding / low-can-cb.cpp
1 /*
2  * Copyright (C) 2015, 2018 "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 <wrap-json.h>
28 #include <systemd/sd-event.h>
29 #include <ctl-config.h>
30 #include "openxc.pb.h"
31 #include "application.hpp"
32 #include "../can/can-encoder.hpp"
33 #include "../can/can-bus.hpp"
34 #include "../can/signals.hpp"
35 #include "../can/message/message.hpp"
36 #include "../utils/signals.hpp"
37 #include "../diagnostic/diagnostic-message.hpp"
38 #include "../utils/openxc-utils.hpp"
39 #include "../utils/signals.hpp"
40
41 #ifdef USE_FEATURE_J1939
42         #include "../can/message/j1939-message.hpp"
43         #include <linux/can/j1939.h>
44 #endif
45
46 ///*****************************************************************************
47 ///
48 ///             Controller Definitions and Callbacks
49 ///
50 ///****************************************************************************/
51
52 int config_low_can(afb_api_t apiHandle, CtlSectionT *section, json_object *json_obj)
53 {
54         AFB_DEBUG("Config %s", json_object_to_json_string(json_obj));
55         CtlConfigT *ctrlConfig;
56
57         ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle);
58         if(!ctrlConfig)
59                 return -1;
60
61         if(!section->handle)
62                 return -1;
63
64         application_t *application = (application_t*) section->handle;
65
66
67         int active_message_set;
68         const char *diagnotic_bus = nullptr;
69
70         if(wrap_json_unpack(json_obj, "{si, ss}",
71                               "active_message_set", &active_message_set,
72                               "diagnostic_bus", &diagnotic_bus))
73                 return -1;
74
75         application->set_active_message_set((uint8_t)active_message_set);
76
77         /// Initialize Diagnostic manager that will handle obd2 requests.
78         /// We pass by default the first CAN bus device to its Initialization.
79         if(! application_t::instance().get_diagnostic_manager().initialize(diagnotic_bus))
80         {
81                 AFB_ERROR("Diagnostic Manager: error at initialization");
82                 return -1;
83         }
84
85         return 0;
86 }
87
88 CtlSectionT ctlSections_[] = {
89         [0]={.key="config" , .uid="config", .info=nullptr,
90                  .loadCB=config_low_can,
91                  .handle=nullptr,
92                  .actions=nullptr},
93         [1]={.key="plugins" , .uid="plugins", .info=nullptr,
94                 .loadCB=PluginConfig,
95                 .handle=nullptr,
96                 .actions=nullptr},
97 };
98
99 ///*****************************************************************************
100 ///
101 ///             Subscription and unsubscription
102 ///
103 ///****************************************************************************/
104
105 /// @brief This will determine if an event handle needs to be created and checks if
106 /// we got a valid afb_event to get subscribe or unsubscribe. After that launch the subscription or unsubscription
107 /// against the application framework using that event handle.
108 static int subscribe_unsubscribe_signal(afb_req_t request,
109                                         bool subscribe,
110                                         std::shared_ptr<low_can_subscription_t>& can_subscription,
111                                         map_subscription& s)
112 {
113         int ret = 0;
114         int sub_index = can_subscription->get_index();
115         bool subscription_exists = s.count(sub_index);
116
117         // Susbcription part
118         if(subscribe)
119         {
120                 /* There is no valid request to subscribe so this must be an
121                  * internal permanent diagnostic request. Skip the subscription
122                  * part and don't register it into the current "low-can"
123                  * subsciptions.
124                  */
125                 if(! request)
126                 {
127                         return 0;
128                 }
129
130                 // Event doesn't exist , so let's create it
131                 if ((ret = can_subscription->subscribe(request)) < 0)
132                         return ret;
133
134                 if(! subscription_exists)
135                                 s[sub_index] = can_subscription;
136
137                 return ret;
138         }
139
140         // Unsubscrition part
141         if(! subscription_exists)
142         {
143                 AFB_NOTICE("There isn't any valid subscriptions for that request.");
144                 return ret;
145         }
146         else if (subscription_exists &&
147                  ! afb_event_is_valid(s[sub_index]->get_event()) )
148         {
149                 AFB_NOTICE("Event isn't valid, no need to unsubscribed.");
150                 return ret;
151         }
152
153         if( (ret = s[sub_index]->unsubscribe(request)) < 0)
154                 return ret;
155         s.find(sub_index)->second->set_index(-1);
156         s.erase(sub_index);
157         return ret;
158 }
159
160 static int add_to_event_loop(std::shared_ptr<low_can_subscription_t>& can_subscription)
161 {
162                 struct sd_event_source* event_source = nullptr;
163                 return ( sd_event_add_io(afb_daemon_get_event_loop(),
164                         &event_source,
165                         can_subscription->get_socket()->socket(),
166                         EPOLLIN,
167                         read_message,
168                         can_subscription.get()));
169 }
170
171 static int subscribe_unsubscribe_diagnostic_messages(afb_req_t request,
172                                                      bool subscribe,
173                                                      list_ptr_diag_msg_t diagnostic_messages,
174                                                      struct event_filter_t& event_filter,
175                                                      map_subscription& s,
176                                                      bool perm_rec_diag_req)
177 {
178         int rets = 0;
179         application_t& app = application_t::instance();
180         diagnostic_manager_t& diag_m = app.get_diagnostic_manager();
181
182         for(const auto& sig : diagnostic_messages)
183         {
184                 DiagnosticRequest* diag_req = new DiagnosticRequest(sig->build_diagnostic_request());
185                 event_filter.frequency = event_filter.frequency == 0 ? sig->get_frequency() : event_filter.frequency;
186                 std::shared_ptr<low_can_subscription_t> can_subscription;
187
188                 auto it =  std::find_if(s.begin(), s.end(), [&sig](std::pair<int, std::shared_ptr<low_can_subscription_t> > sub)
189                 {
190                         return (! sub.second->get_diagnostic_message().empty());
191                 });
192                 can_subscription = it != s.end() ?
193                         it->second :
194                         std::make_shared<low_can_subscription_t>(low_can_subscription_t(event_filter));
195                 // If the requested diagnostic message is not supported by the car then unsubcribe it
196                 // no matter what we want, worst case will be a failed unsubscription but at least we won't
197                 // poll a PID for nothing.
198                 if(sig->get_supported() && subscribe)
199                 {
200                         if (!app.is_engine_on())
201                                 AFB_WARNING("signal: Engine is off, %s won't received responses until it's on",  sig->get_name().c_str());
202
203                         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);
204                         if(can_subscription->create_rx_filter(sig) < 0)
205                                 return -1;
206                         AFB_DEBUG("Signal: %s subscribed", sig->get_name().c_str());
207                         if(it == s.end() && add_to_event_loop(can_subscription) < 0)
208                         {
209                                 diag_m.cleanup_request(
210                                         diag_m.find_recurring_request(*diag_req), true);
211                                 AFB_WARNING("signal: %s isn't supported. Canceling operation.",  sig->get_name().c_str());
212                                 return -1;
213                         }
214                 }
215                 else
216                 {
217                         if(sig->get_supported())
218                         {
219                                 AFB_DEBUG("%s cancelled due to unsubscribe", sig->get_name().c_str());
220                         }
221                         else
222                         {
223                                 AFB_WARNING("signal: %s isn't supported. Canceling operation.", sig->get_name().c_str());
224                                 return -1;
225                         }
226                 }
227                 int ret = subscribe_unsubscribe_signal(request, subscribe, can_subscription, s);
228                 if(ret < 0)
229                         return ret;
230
231                 rets++;
232         }
233         return rets;
234 }
235
236 static int subscribe_unsubscribe_signals(afb_req_t request,
237                                          bool subscribe,
238                                          list_ptr_signal_t signals,
239                                          struct event_filter_t& event_filter,
240                                          map_subscription& s)
241 {
242         int rets = 0;
243         for(const auto& sig: signals)
244         {
245                 auto it =  std::find_if(s.begin(), s.end(), [&sig, &event_filter](std::pair<int, std::shared_ptr<low_can_subscription_t> > sub)
246                 {
247                         return sub.second->is_signal_subscription_corresponding(sig, event_filter) ;
248                 });
249                 std::shared_ptr<low_can_subscription_t> can_subscription;
250                 if(it != s.end())
251                         can_subscription = it->second;
252                 else
253                 {
254                         can_subscription = std::make_shared<low_can_subscription_t>(low_can_subscription_t(event_filter));
255                         if(can_subscription->create_rx_filter(sig) < 0)
256                                 return -1;
257                         if(add_to_event_loop(can_subscription) < 0)
258                                 return -1;
259                 }
260
261                 if(subscribe_unsubscribe_signal(request, subscribe, can_subscription, s) < 0)
262                         return -1;
263
264                 rets++;
265                 AFB_DEBUG("%s Signal: %s %ssubscribed", sig->get_message()->is_fd() ? "FD": "", sig->get_name().c_str(), subscribe ? "":"un");
266         }
267         return rets;
268 }
269
270 ///
271 /// @brief subscribe to all signals in the vector signals
272 ///
273 /// @param[in] afb_req request : contains original request use to subscribe or unsubscribe
274 /// @param[in] subscribe boolean value, which chooses between a subscription operation or an unsubscription
275 /// @param[in] signals -  struct containing vectors with signal_t and diagnostic_messages to subscribe
276 /// @param[in] event_filter - stuct containing filter on the signal
277 ///
278 /// @return Number of correctly subscribed signal
279 ///
280 static int subscribe_unsubscribe_signals(afb_req_t request,
281                                          bool subscribe,
282                                          const struct utils::signals_found& signals,
283                                          struct event_filter_t& event_filter)
284 {
285         int rets = 0;
286         utils::signals_manager_t& sm = utils::signals_manager_t::instance();
287
288         std::lock_guard<std::mutex> subscribed_signals_lock(sm.get_subscribed_signals_mutex());
289         map_subscription& s = sm.get_subscribed_signals();
290
291         rets += subscribe_unsubscribe_diagnostic_messages(request, subscribe, signals.diagnostic_messages, event_filter, s, false);
292         rets += subscribe_unsubscribe_signals(request, subscribe, signals.signals, event_filter, s);
293
294         return rets;
295 }
296
297 static event_filter_t generate_filter(json_object* args)
298 {
299         event_filter_t event_filter;
300         struct json_object  *filter, *obj;
301
302                 // computes the filter
303         if (json_object_object_get_ex(args, "filter", &filter))
304         {
305                 if (json_object_object_get_ex(filter, "frequency", &obj)
306                 && (json_object_is_type(obj, json_type_double) || json_object_is_type(obj, json_type_int)))
307                         event_filter.frequency = (float)json_object_get_double(obj);
308                 if (json_object_object_get_ex(filter, "min", &obj)
309                 && (json_object_is_type(obj, json_type_double) || json_object_is_type(obj, json_type_int)))
310                         event_filter.min = (float)json_object_get_double(obj);
311                 if (json_object_object_get_ex(filter, "max", &obj)
312                 && (json_object_is_type(obj, json_type_double) || json_object_is_type(obj, json_type_int)))
313                         event_filter.max = (float)json_object_get_double(obj);
314                 if (json_object_object_get_ex(filter, "rx_id", &obj)
315                 && (json_object_is_type(obj, json_type_int)))
316                         event_filter.rx_id = (canid_t) json_object_get_int(obj);
317                 if (json_object_object_get_ex(filter, "tx_id", &obj)
318                 && (json_object_is_type(obj, json_type_int)))
319                         event_filter.tx_id = (canid_t) json_object_get_int(obj);
320         }
321         return event_filter;
322 }
323
324
325 static int one_subscribe_unsubscribe_events(afb_req_t request, bool subscribe, const std::string& tag, json_object* args)
326 {
327         int ret = 0;
328         struct utils::signals_found sf;
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
334
335 #ifdef USE_FEATURE_ISOTP
336         if(sf.signals.size() > 1)
337         {
338                 sf.signals.remove_if([](std::shared_ptr<signal_t> x){
339                         bool isotp = x->get_message()->is_isotp();
340                         if(isotp)
341                                 AFB_NOTICE("ISO TP messages need to be subscribed one by one (rx, tx)");
342
343                         return isotp;
344                 });
345         }
346 #endif
347
348         if (sf.signals.empty() && sf.diagnostic_messages.empty())
349         {
350                 AFB_NOTICE("No signal(s) found for %s.", tag.c_str());
351                 ret = -1;
352         }
353         else
354         {
355                 event_filter_t event_filter = generate_filter(args);
356                 ret = subscribe_unsubscribe_signals(request, subscribe, sf, event_filter);
357         }
358         return ret;
359 }
360
361 static int one_subscribe_unsubscribe_id(afb_req_t request, bool subscribe, const uint32_t& id, json_object *args)
362 {
363         int ret = 0;
364         std::shared_ptr<message_definition_t> message_definition = application_t::instance().get_message_definition(id);
365         struct utils::signals_found sf;
366
367         if(message_definition)
368                 sf.signals = list_ptr_signal_t(message_definition->get_signals().begin(), message_definition->get_signals().end());
369
370         if(sf.signals.empty())
371         {
372                 AFB_NOTICE("No signal(s) found for %d.", id);
373                 ret = -1;
374         }
375         else
376         {
377                 event_filter_t event_filter = generate_filter(args);
378                 ret = subscribe_unsubscribe_signals(request, subscribe, sf, event_filter);
379         }
380
381         return ret;
382 }
383
384
385 static int process_one_subscribe_args(afb_req_t request, bool subscribe, json_object *args)
386 {
387         int rc = 0, rc2=0;
388         json_object *x = nullptr, *event = nullptr, *id = nullptr;
389
390
391         // 2 cases : ID(PGN) and event
392
393         json_object_object_get_ex(args,"event",&event);
394         json_bool test_id = json_object_object_get_ex(args,"id",&id);
395         if(!test_id)
396                 test_id = json_object_object_get_ex(args,"pgn",&id);
397
398         if(     args == NULL || (id && ((std::string)json_object_get_string(id)).compare("*") == 0))
399         {
400                 rc = one_subscribe_unsubscribe_events(request, subscribe, "*", args);
401         }
402         else
403         {
404                 if(event)
405                 {
406                         if (json_object_get_type(event) != json_type_array) // event is set before and check if it's an array
407                         {
408                                 rc = one_subscribe_unsubscribe_events(request, subscribe, json_object_get_string(event), args);
409                         }
410                         else // event is set and it's not an array
411                         {
412                                 for (int i = 0 ; i < json_object_array_length(event); i++)
413                                 {
414                                         x = json_object_array_get_idx(event, i);
415                                         rc2 = one_subscribe_unsubscribe_events(request, subscribe, json_object_get_string(x), args);
416                                         if (rc >= 0)
417                                                 rc = rc2 >= 0 ? rc + rc2 : rc2;
418                                 }
419                         }
420                 }
421
422                 if(id)
423                 {
424                         if (json_object_get_type(id) != json_type_array) // id is set before and check if it's an array
425                         {
426                                 rc = one_subscribe_unsubscribe_id(request, subscribe, json_object_get_int(id), args);
427                         }
428                         else // event is set and it's not an array
429                         {
430                                 for (int i = 0 ; i < json_object_array_length(id); i++)
431                                 {
432                                         x = json_object_array_get_idx(id, i);
433                                         rc2 = one_subscribe_unsubscribe_id(request, subscribe, json_object_get_int(x), args);
434                                         if (rc >= 0)
435                                                 rc = rc2 >= 0 ? rc + rc2 : rc2;
436                                 }
437                         }
438                 }
439         }
440         return rc;
441 }
442
443 static void do_subscribe_unsubscribe(afb_req_t request, bool subscribe)
444 {
445         int rc = 0;
446         struct json_object *args, *x;
447
448         args = afb_req_json(request);
449         if (json_object_get_type(args) == json_type_array)
450         {
451                 for(int i = 0; i < json_object_array_length(args); i++)
452                 {
453                         x = json_object_array_get_idx(args, i);
454                         rc += process_one_subscribe_args(request, subscribe, x);
455                 }
456         }
457         else
458         {
459                 rc += process_one_subscribe_args(request, subscribe, args);
460         }
461
462         if (rc >= 0)
463                 afb_req_success(request, NULL, NULL);
464         else
465                 afb_req_fail(request, "error", NULL);
466 }
467
468 void auth(afb_req_t request)
469 {
470         afb_req_session_set_LOA(request, 1);
471         afb_req_success(request, NULL, NULL);
472 }
473
474 void subscribe(afb_req_t request)
475 {
476         do_subscribe_unsubscribe(request, true);
477 }
478
479 void unsubscribe(afb_req_t request)
480 {
481         do_subscribe_unsubscribe(request, false);
482 }
483
484 /*
485 static int send_frame(struct canfd_frame& cfd, const std::string& bus_name, socket_type type)
486 {
487         if(bus_name.empty())
488         {
489                 return -1;
490         }
491
492         std::map<std::string, std::shared_ptr<low_can_subscription_t> >& cd = application_t::instance().get_can_devices();
493
494         if( cd.count(bus_name) == 0)
495         {
496                 cd[bus_name] = std::make_shared<low_can_subscription_t>(low_can_subscription_t());
497         }
498
499
500         if(type == socket_type::BCM)
501         {
502                 return low_can_subscription_t::tx_send(*cd[bus_name], cfd, bus_name);
503         }
504         else if(type == socket_type::J1939)
505         {
506                 return low_can_subscription_t::j1939_send(*cd[bus_name], cfd, bus_name);
507         }
508         else{
509                 return -1;
510         }
511 }
512 */
513 static int send_message(message_t *message, const std::string& bus_name, uint32_t flags, event_filter_t &event_filter, std::shared_ptr<signal_t> signal)
514 {
515         if(bus_name.empty())
516                 return -1;
517
518         std::map<std::string, std::shared_ptr<low_can_subscription_t> >& cd = application_t::instance().get_can_devices();
519
520         if( cd.count(bus_name) == 0)
521                 cd[bus_name] = std::make_shared<low_can_subscription_t>(low_can_subscription_t(event_filter));
522
523         cd[bus_name]->set_signal(signal);
524
525
526         if(flags&BCM_PROTOCOL)
527                 return low_can_subscription_t::tx_send(*cd[bus_name], message, bus_name);
528 #ifdef USE_FEATURE_ISOTP
529         else if(flags&ISOTP_PROTOCOL)
530                 return low_can_subscription_t::isotp_send(*cd[bus_name], message, bus_name);
531 #endif
532 #ifdef USE_FEATURE_J1939
533         else if(flags&J1939_PROTOCOL)
534                 return low_can_subscription_t::j1939_send(*cd[bus_name], message, bus_name);
535 #endif
536         else
537                 return -1;
538 }
539
540
541 static void write_raw_frame(afb_req_t request, const std::string& bus_name, message_t *message,
542                             struct json_object *can_data, uint32_t flags, event_filter_t &event_filter)
543 {
544
545         struct utils::signals_found sf;
546
547         utils::signals_manager_t::instance().lookup_signals_by_id(message->get_id(), application_t::instance().get_all_signals(), sf.signals);
548
549         if( !sf.signals.empty() )
550         {
551                 AFB_DEBUG("ID WRITE RAW : %d", sf.signals.front()->get_message()->get_id());
552                 if(flags & BCM_PROTOCOL)
553                 {
554                         if(sf.signals.front()->get_message()->is_fd())
555                         {
556                                 AFB_DEBUG("CANFD_MAX_DLEN");
557                                 message->set_flags(CAN_FD_FRAME);
558                                 message->set_maxdlen(CANFD_MAX_DLEN);
559                         }
560                         else
561                         {
562                                 AFB_DEBUG("CAN_MAX_DLEN");
563                                 message->set_maxdlen(CAN_MAX_DLEN);
564                         }
565
566                         if(sf.signals.front()->get_message()->is_isotp())
567                         {
568                                 flags = ISOTP_PROTOCOL;
569                                 message->set_maxdlen(MAX_ISOTP_FRAMES * message->get_maxdlen());
570                         }
571                 }
572
573 #ifdef USE_FEATURE_J1939
574                 if(flags&J1939_PROTOCOL)
575                         message->set_maxdlen(J1939_MAX_DLEN);
576 #endif
577
578                 if(message->get_length() > 0 && message->get_length() <= message->get_maxdlen())
579                 {
580                         std::vector<uint8_t> data;
581                         for (int i = 0 ; i < message->get_length() ; i++)
582                         {
583                                 struct json_object *one_can_data = json_object_array_get_idx(can_data, i);
584                                 data.push_back((json_object_is_type(one_can_data, json_type_int)) ?
585                                                 (uint8_t)json_object_get_int(one_can_data) : 0);
586                         }
587                         message->set_data(data);
588                 }
589                 else
590                 {
591                         if(flags&BCM_PROTOCOL)
592                                 afb_req_fail(request, "Invalid", "Frame BCM");
593                         else if(flags&J1939_PROTOCOL)
594                                 afb_req_fail(request, "Invalid", "Frame J1939");
595                         else if(flags&ISOTP_PROTOCOL)
596                                 afb_req_fail(request, "Invalid", "Frame ISOTP");
597                         else
598                                 afb_req_fail(request, "Invalid", "Frame");
599
600                         return;
601                 }
602
603                 if(! send_message(message, application_t::instance().get_can_bus_manager().get_can_device_name(bus_name), flags, event_filter, sf.signals.front()))
604                         afb_req_success(request, nullptr, "Message correctly sent");
605                 else
606                         afb_req_fail(request, "Error", "sending the message. See the log for more details.");
607         }
608         else
609         {
610                 afb_req_fail(request, "Error", "no find id in signals. See the log for more details.");
611         }
612
613 }
614
615 static void write_frame(afb_req_t request, const std::string& bus_name, json_object *json_value, event_filter_t &event_filter)
616 {
617         message_t *message;
618         uint32_t id;
619         uint32_t length;
620         struct json_object *can_data = nullptr;
621         std::vector<uint8_t> data;
622
623         AFB_DEBUG("JSON content %s", json_object_get_string(json_value));
624
625         if(!wrap_json_unpack(json_value, "{si, si, so !}",
626                                   "can_id", &id,
627                                   "can_dlc", &length,
628                                   "can_data", &can_data))
629         {
630                 message = new can_message_t(0, id, length, false, 0, data, 0);
631                 write_raw_frame(request, bus_name, message, can_data, BCM_PROTOCOL, event_filter);
632         }
633 #ifdef USE_FEATURE_J1939
634         else if(!wrap_json_unpack(json_value, "{si, si, so !}",
635                                   "pgn", &id,
636                                   "length", &length,
637                                   "data", &can_data))
638         {
639                 message = new j1939_message_t(length, data, 0, J1939_NO_NAME, (pgn_t)id, J1939_NO_ADDR);
640                 write_raw_frame(request, bus_name, message, can_data, J1939_PROTOCOL, event_filter);
641         }
642 #endif
643         else
644         {
645                 afb_req_fail(request, "Invalid", "Frame object malformed");
646                 return;
647         }
648         delete message;
649 }
650
651 static void write_signal(afb_req_t request, const std::string& name, json_object *json_value, event_filter_t &event_filter)
652 {
653         struct canfd_frame cfd;
654         struct utils::signals_found sf;
655         signal_encoder encoder = nullptr;
656         bool send = true;
657
658         ::memset(&cfd, 0, sizeof(cfd));
659
660         openxc_DynamicField search_key = build_DynamicField(name);
661         sf = utils::signals_manager_t::instance().find_signals(search_key);
662         openxc_DynamicField dynafield_value = build_DynamicField(json_value);
663
664         if (sf.signals.empty())
665         {
666                 afb_req_fail_f(request, "No signal(s) found for %s. Message not sent.", name.c_str());
667                 return;
668         }
669
670         std::shared_ptr<signal_t> sig = sf.signals.front();
671         if(! sig->get_writable())
672         {
673                 afb_req_fail_f(request, "%s isn't writable. Message not sent.", sig->get_name().c_str());
674                 return;
675         }
676
677         uint64_t value = (encoder = sig->get_encoder()) ?
678                         encoder(*sig, dynafield_value, &send) :
679                         encoder_t::encode_DynamicField(*sig, dynafield_value, &send);
680
681         uint32_t flags = INVALID_FLAG;
682
683         if(sig->get_message()->is_j1939())
684                 flags = J1939_PROTOCOL;
685         else if(sig->get_message()->is_isotp())
686                 flags = ISOTP_PROTOCOL;
687         else
688                 flags = BCM_PROTOCOL;
689
690 //      cfd = encoder_t::build_frame(sig, value);
691         message_t *message = encoder_t::build_message(sig, value, false, false);
692
693         if(! send_message(message, sig->get_message()->get_bus_device_name(), flags, event_filter, sig) && send)
694                 afb_req_success(request, nullptr, "Message correctly sent");
695         else
696                 afb_req_fail(request, "Error", "Sending the message. See the log for more details.");
697
698         if(sig->get_message()->is_j1939())
699 #ifdef USE_FEATURE_J1939
700                 delete (j1939_message_t*) message;
701 #else
702                 afb_req_fail(request, "Warning", "J1939 not implemented in your kernel.");
703 #endif
704         else
705                 delete (can_message_t*) message;
706 }
707
708 void write(afb_req_t request)
709 {
710         struct json_object* args = nullptr, *json_value = nullptr, *name = nullptr;
711         args = afb_req_json(request);
712
713         if(args != NULL)
714         {
715                 event_filter_t event_filter = generate_filter(args);
716
717                 if(json_object_object_get_ex(args,"bus_name",&name))
718                 {
719                         if(json_object_object_get_ex(args,"frame",&json_value))
720                                 write_frame(request, (std::string)json_object_get_string(name), json_value, event_filter);
721                         else
722                                 afb_req_fail(request, "Error", "Request argument malformed");
723                 }
724                 else if(json_object_object_get_ex(args,"signal_name",&name))
725                 {
726                         if(json_object_object_get_ex(args,"signal_value",&json_value))
727                                 write_signal(request, (std::string)json_object_get_string(name), json_value, event_filter);
728                         else
729                                 afb_req_fail(request, "Error", "Request argument malformed");
730                 }
731                 else
732                 {
733                         afb_req_fail(request, "Error", "Request argument malformed");
734                 }
735         }
736         else
737         {
738                 afb_req_fail(request, "Error", "Request argument null");
739         }
740 }
741
742 static struct json_object *get_signals_value(const std::string& name)
743 {
744         struct utils::signals_found sf;
745         struct json_object *ans = nullptr;
746
747         openxc_DynamicField search_key = build_DynamicField(name);
748         sf = utils::signals_manager_t::instance().find_signals(search_key);
749
750         if (sf.signals.empty())
751         {
752                 AFB_WARNING("No signal(s) found for %s.", name.c_str());
753                 return NULL;
754         }
755         ans = json_object_new_array();
756         for(const auto& sig: sf.signals)
757         {
758                 struct json_object *jobj = json_object_new_object();
759                 json_object_object_add(jobj, "event", json_object_new_string(sig->get_name().c_str()));
760                 json_object_object_add(jobj, "value", json_object_new_double(sig->get_last_value()));
761                 json_object_array_add(ans, jobj);
762         }
763
764         return ans;
765 }
766 void get(afb_req_t request)
767 {
768         int rc = 0;
769         struct json_object* args = nullptr,
770                 *json_name = nullptr;
771         json_object *ans = nullptr;
772
773         args = afb_req_json(request);
774
775         // Process about Raw CAN message on CAN bus directly
776         if (args != nullptr &&
777                 (json_object_object_get_ex(args, "event", &json_name) && json_object_is_type(json_name, json_type_string) ))
778         {
779                 ans = get_signals_value(json_object_get_string(json_name));
780                 if (!ans)
781                         rc = -1;
782         }
783         else
784         {
785                 AFB_ERROR("Request argument malformed. Please use the following syntax:");
786                 rc = -1;
787         }
788
789         if (rc >= 0)
790                 afb_req_success(request, ans, NULL);
791         else
792                 afb_req_fail(request, "error", NULL);
793 }
794
795
796 static struct json_object *list_can_message(const std::string& name)
797 {
798         struct utils::signals_found sf;
799         struct json_object *ans = nullptr;
800
801         openxc_DynamicField search_key = build_DynamicField(name);
802         sf = utils::signals_manager_t::instance().find_signals(search_key);
803
804         if (sf.signals.empty() && sf.diagnostic_messages.empty())
805         {
806                 AFB_WARNING("No signal(s) found for %s.", name.c_str());
807                 return NULL;
808         }
809         ans = json_object_new_array();
810         for(const auto& sig: sf.signals)
811         {
812                 json_object_array_add(ans,
813                         json_object_new_string(sig->get_name().c_str()));
814         }
815         for(const auto& sig: sf.diagnostic_messages)
816         {
817                 json_object_array_add(ans,
818                         json_object_new_string(sig->get_name().c_str()));
819         }
820
821         return ans;
822 }
823
824 void list(afb_req_t request)
825 {
826         int rc = 0;
827         json_object *ans = nullptr;
828         struct json_object* args = nullptr,
829                 *json_name = nullptr;
830         args = afb_req_json(request);
831         const char *name;
832         if ((args != nullptr) &&
833                 (json_object_object_get_ex(args, "event", &json_name) && json_object_is_type(json_name, json_type_string)))
834                 name = json_object_get_string(json_name);
835         else
836                 name = "*";
837
838         ans = list_can_message(name);
839         if (!ans)
840                 rc = -1;
841
842         if (rc >= 0)
843                 afb_req_success(request, ans, NULL);
844         else
845                 afb_req_fail(request, "error", NULL);
846
847 }
848
849 /// @brief Initialize the binding.
850 ///
851 /// @param[in] service Structure which represent the Application Framework Binder.
852 ///
853 /// @return Exit code, zero if success.
854 int init_binding(afb_api_t api)
855 {
856         int ret = 1;
857         application_t& application = application_t::instance();
858         can_bus_t& can_bus_manager = application.get_can_bus_manager();
859
860         if(application.get_message_set().empty())
861         {
862                 AFB_ERROR("No message_set defined");
863                 return -1;
864         }
865
866
867         can_bus_manager.set_can_devices();
868         can_bus_manager.start_threads();
869         utils::signals_manager_t& sm = utils::signals_manager_t::instance();
870
871         // Add a recurring dignostic message request to get engine speed at all times.
872         openxc_DynamicField search_key = build_DynamicField("diagnostic_messages.engine.speed");
873         struct utils::signals_found sf = sm.find_signals(search_key);
874
875         if(sf.signals.empty() && sf.diagnostic_messages.size() == 1)
876         {
877                 afb_req_t request = nullptr;
878
879                 struct event_filter_t event_filter;
880                 event_filter.frequency = sf.diagnostic_messages.front()->get_frequency();
881
882                 map_subscription& s = sm.get_subscribed_signals();
883
884                 subscribe_unsubscribe_diagnostic_messages(request, true, sf.diagnostic_messages, event_filter, s, true);
885         }
886
887
888 #ifdef USE_FEATURE_J1939
889         std::string j1939_bus;
890         vect_ptr_msg_def_t current_messages_definition = application.get_messages_definition();
891         for(std::shared_ptr<message_definition_t> message_definition: current_messages_definition)
892         {
893                 if(message_definition->is_j1939())
894                 {
895                         if (j1939_bus == message_definition->get_bus_device_name() )
896                                 continue;
897                         j1939_bus = message_definition->get_bus_device_name();
898
899                         std::shared_ptr<low_can_subscription_t> low_can_j1939 = std::make_shared<low_can_subscription_t>();
900                         application.set_subscription_address_claiming(low_can_j1939);
901
902                         ret = low_can_subscription_t::open_socket(*low_can_j1939,
903                                                                   j1939_bus,
904                                                                   J1939_ADDR_CLAIM_PROTOCOL);
905
906                         if(ret < 0)
907                         {
908                                 AFB_ERROR("Error open socket address claiming for j1939 protocol");
909                                 return -1;
910                         }
911                         add_to_event_loop(low_can_j1939);
912                         break;
913                 }
914         }
915 #endif
916
917         if(ret)
918                 AFB_ERROR("There was something wrong with CAN device Initialization.");
919
920         return ret;
921 }
922
923 int load_conf(afb_api_t api)
924 {
925         int ret = 0;
926         CtlConfigT *ctlConfig;
927         const char *dirList = getenv("CONTROL_CONFIG_PATH");
928         std::string bindingDirPath = GetBindingDirPath(api);
929         std::string filepath = bindingDirPath + "/etc";
930
931         if (!dirList)
932                 dirList=CONTROL_CONFIG_PATH;
933
934         filepath.append(":");
935         filepath.append(dirList);
936         const char *configPath = CtlConfigSearch(api, filepath.c_str(), "control");
937
938         if (!configPath)
939         {
940                 AFB_ERROR_V3("CtlPreInit: No control-* config found invalid JSON %s ", filepath.c_str());
941                 return -1;
942         }
943
944         // create one API per file
945         ctlConfig = CtlLoadMetaData(api, configPath);
946         if (!ctlConfig)
947         {
948                 AFB_ERROR_V3("CtrlPreInit No valid control config file in:\n-- %s", configPath);
949                 return -1;
950         }
951
952         // Save the config in the api userdata field
953         afb_api_set_userdata(api, ctlConfig);
954
955         setExternalData(ctlConfig, (void*) &application_t::instance());
956         ret= CtlLoadSections(api, ctlConfig, ctlSections_);
957
958         return ret;
959 }