binding: add preinit function to load the config 99/23199/6
authorRomain Forlot <romain.forlot@iot.bzh>
Sat, 9 Nov 2019 17:09:30 +0000 (18:09 +0100)
committerRomain Forlot <romain.forlot@iot.bzh>
Thu, 9 Jan 2020 13:39:56 +0000 (14:39 +0100)
Make as the others bindings using controller and load its configuration file
at preinit step.

diagnostic-manager: Change way to initialize the diag bus

This was kind of hardcoded and now, it is initialized by a configuration key
of the controller configuration JSON file.

Bug-AGL: SPEC-2988

Change-Id: I344c1982893e47600a0b8cd03542de8069a42d24
Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
low-can-binding/binding/application.hpp
low-can-binding/binding/low-can-apidef.json
low-can-binding/binding/low-can-cb.cpp
low-can-binding/binding/low-can-subscription.cpp
low-can-binding/diagnostic/diagnostic-manager.cpp
low-can-binding/diagnostic/diagnostic-manager.hpp

index 7b4732c..3438c6a 100644 (file)
@@ -65,8 +65,6 @@ class application_t
 
                std::map<std::string, std::shared_ptr<low_can_subscription_t> >& get_can_devices();
 
-               const std::string get_diagnostic_bus() const;
-
                diagnostic_manager_t& get_diagnostic_manager() ;
 
                uint8_t get_active_message_set() const;
index 5f52837..ba539b0 100644 (file)
@@ -12,6 +12,7 @@
                        "postfix": "",
                        "start": null ,
                        "onevent": null,
+                       "preninit": "loadConf",
                        "init": "init_binding",
                        "scope": "",
                        "private": false
index 5b351b5..0672e71 100644 (file)
@@ -26,6 +26,7 @@
 #include <thread>
 #include <wrap-json.h>
 #include <systemd/sd-event.h>
+#include <ctl-config.h>
 #include "openxc.pb.h"
 #include "application.hpp"
 #include "../can/can-encoder.hpp"
        #include "../can/message/j1939-message.hpp"
        #include <linux/can/j1939.h>
 #endif
-///******************************************************************************
+
+///*****************************************************************************
 ///
-///            SystemD event loop Callbacks
+///            Controller Definitions and Callbacks
 ///
-///*******************************************************************************/
+///****************************************************************************/
 
-void on_no_clients(std::shared_ptr<low_can_subscription_t> can_subscription, uint32_t pid, map_subscription& s)
+int config_low_can(afb_api_t apiHandle, CtlSectionT *section, json_object *json_obj)
 {
-       bool is_permanent_recurring_request = false;
-
-       if( ! can_subscription->get_diagnostic_message().empty() && can_subscription->get_diagnostic_message(pid) != nullptr)
-       {
-               DiagnosticRequest diag_req = can_subscription->get_diagnostic_message(pid)->build_diagnostic_request();
-               active_diagnostic_request_t* adr = application_t::instance().get_diagnostic_manager().find_recurring_request(diag_req);
-               if( adr != nullptr)
-               {
-                       is_permanent_recurring_request = adr->get_permanent();
-
-                       if(! is_permanent_recurring_request)
-                               application_t::instance().get_diagnostic_manager().cleanup_request(adr, true);
-               }
-       }
+       AFB_DEBUG("Config %s", json_object_to_json_string(json_obj));
+       CtlConfigT *ctrlConfig;
 
-       if(! is_permanent_recurring_request)
-               on_no_clients(can_subscription, s);
-}
-
-void on_no_clients(std::shared_ptr<low_can_subscription_t> can_subscription, map_subscription& s)
-{
-       auto it = s.find(can_subscription->get_index());
-       s.erase(it);
-}
+       ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle);
+       if(!ctrlConfig)
+               return -1;
 
-static void push_n_notify(std::shared_ptr<message_t> m)
-{
-       can_bus_t& cbm = application_t::instance().get_can_bus_manager();
-       {
-               std::lock_guard<std::mutex> can_message_lock(cbm.get_can_message_mutex());
-               cbm.push_new_can_message(m);
-       }
-       cbm.get_new_can_message_cv().notify_one();
-}
+       if(!section->handle)
+               return -1;
 
-int read_message(sd_event_source *event_source, int fd, uint32_t revents, void *userdata)
-{
+       application_t *application = (application_t*) section->handle;
 
-       low_can_subscription_t* can_subscription = (low_can_subscription_t*)userdata;
 
+       int active_message_set;
+       const char *diagnotic_bus = nullptr;
 
-       if ((revents & EPOLLIN) != 0)
-       {
-               utils::signals_manager_t& sm = utils::signals_manager_t::instance();
-               std::lock_guard<std::mutex> subscribed_signals_lock(sm.get_subscribed_signals_mutex());
-               if(can_subscription->get_index() != -1)
-               {
-                       std::shared_ptr<utils::socketcan_t> s = can_subscription->get_socket();
-                       if(s->socket() && s->socket() != -1)
-                       {
-                               std::shared_ptr<message_t> message = s->read_message();
+       if(wrap_json_unpack(json_obj, "{si, ss}",
+                             "active_message_set", &active_message_set,
+                             "diagnostic_bus", &diagnotic_bus))
+               return -1;
 
-                               // Sure we got a valid CAN message ?
-                               if (! message->get_id() == 0 && ! message->get_length() == 0 && !(message->get_flags()&INVALID_FLAG))
-                               {
-                                       push_n_notify(message);
-                               }
-                       }
-               }
-       }
+       application->set_active_message_set((uint8_t)active_message_set);
 
-       // check if error or hangup
-       if ((revents & (EPOLLERR | EPOLLRDHUP | EPOLLHUP)) != 0)
+       /// Initialize Diagnostic manager that will handle obd2 requests.
+       /// We pass by default the first CAN bus device to its Initialization.
+       if(! application_t::instance().get_diagnostic_manager().initialize(diagnotic_bus))
        {
-               sd_event_source_unref(event_source);
-               can_subscription->get_socket()->close();
+               AFB_ERROR("Diagnostic Manager: error at initialization");
+               return -1;
        }
 
        return 0;
 }
 
-///******************************************************************************
+CtlSectionT ctlSections_[] = {
+       [0]={.key="config" , .uid="config", .info=nullptr,
+                .loadCB=config_low_can,
+                .handle=nullptr,
+                .actions=nullptr},
+       [1]={.key="plugins" , .uid="plugins", .info=nullptr,
+               .loadCB=PluginConfig,
+               .handle=nullptr,
+               .actions=nullptr},
+};
+
+///*****************************************************************************
 ///
 ///            Subscription and unsubscription
 ///
-///*******************************************************************************/
+///****************************************************************************/
 
 /// @brief This will determine if an event handle needs to be created and checks if
 /// we got a valid afb_event to get subscribe or unsubscribe. After that launch the subscription or unsubscription
@@ -881,16 +857,17 @@ int init_binding(afb_api_t api)
        application_t& application = application_t::instance();
        can_bus_t& can_bus_manager = application.get_can_bus_manager();
 
+       if(application.get_message_set().empty())
+       {
+               AFB_ERROR("No message_set defined");
+               return -1;
+       }
+
+
        can_bus_manager.set_can_devices();
        can_bus_manager.start_threads();
        utils::signals_manager_t& sm = utils::signals_manager_t::instance();
 
-       /// Initialize Diagnostic manager that will handle obd2 requests.
-       /// We pass by default the first CAN bus device to its Initialization.
-       /// TODO: be able to choose the CAN bus device that will be use as Diagnostic bus.
-       if(application_t::instance().get_diagnostic_manager().initialize())
-               ret = 0;
-
        // Add a recurring dignostic message request to get engine speed at all times.
        openxc_DynamicField search_key = build_DynamicField("diagnostic_messages.engine.speed");
        struct utils::signals_found sf = sm.find_signals(search_key);
@@ -942,3 +919,41 @@ int init_binding(afb_api_t api)
 
        return ret;
 }
+
+int load_conf(afb_api_t api)
+{
+       int ret = 0;
+       CtlConfigT *ctlConfig;
+       const char *dirList = getenv("CONTROL_CONFIG_PATH");
+       std::string bindingDirPath = GetBindingDirPath(api);
+       std::string filepath = bindingDirPath + "/etc";
+
+       if (!dirList)
+               dirList=CONTROL_CONFIG_PATH;
+
+       filepath.append(":");
+       filepath.append(dirList);
+       const char *configPath = CtlConfigSearch(api, filepath.c_str(), "control");
+
+       if (!configPath)
+       {
+               AFB_ERROR_V3("CtlPreInit: No control-* config found invalid JSON %s ", filepath.c_str());
+               return -1;
+       }
+
+       // create one API per file
+       ctlConfig = CtlLoadMetaData(api, configPath);
+       if (!ctlConfig)
+       {
+               AFB_ERROR_V3("CtrlPreInit No valid control config file in:\n-- %s", configPath);
+               return -1;
+       }
+
+       // Save the config in the api userdata field
+       afb_api_set_userdata(api, ctlConfig);
+
+       setExternalData(ctlConfig, (void*) &application_t::instance());
+       ret= CtlLoadSections(api, ctlConfig, ctlSections_);
+
+       return ret;
+}
index 8c0a07c..2cb5baf 100644 (file)
@@ -370,7 +370,7 @@ int low_can_subscription_t::open_socket(low_can_subscription_t &subscription, co
                        if( subscription.signal_ )
                                ret = subscription.socket_->open(subscription.signal_->get_message()->get_bus_device_name());
                        else if(! subscription.diagnostic_message_.empty())
-                               ret = subscription.socket_->open(application_t::instance().get_diagnostic_bus());
+                               ret = subscription.socket_->open(application_t::instance().get_diagnostic_manager().get_bus_name());
                        else if(! bus_name.empty())
                                ret = subscription.socket_->open(bus_name);
 
index 91dba47..f3c513c 100644 (file)
@@ -56,16 +56,19 @@ diagnostic_manager_t::~diagnostic_manager_t()
 ///
 /// this will initialize DiagnosticShims and cancel all active requests
 ///  if there are any.
-bool diagnostic_manager_t::initialize()
+bool diagnostic_manager_t::initialize(std::string diagnostic_bus)
 {
-       // Mandatory to set the bus before intialize shims.
-       bus_ = application_t::instance().get_diagnostic_bus();
-
-       init_diagnostic_shims();
-       reset();
+       if (! diagnostic_bus.empty())
+       {
+               bus_ = diagnostic_bus;
+               init_diagnostic_shims();
+               reset();
 
-       initialized_ = true;
-       AFB_DEBUG("Diagnostic Manager initialized");
+               AFB_DEBUG("Diagnostic Manager initialized");
+               initialized_ = true;
+               return initialized_;
+       }
+       AFB_ERROR("Diagnostic Manager missing its bus name in the config");
        return initialized_;
 }
 
index 784bcd7..c0a8255 100644 (file)
@@ -33,7 +33,7 @@
 #define DIAGNOSTIC_RESPONSE_ARBITRATION_ID_OFFSET 0x8
 
 ///
-/// @brief The core structure for running the diagnostics module of the binding.
+/// @brief The binding structure for running the diagnostics module of the binding.
 ///
 /// This stores details about the active requests and shims required to connect
 /// the diagnostics library to the CAN device.
@@ -54,11 +54,12 @@ private:
 
        static bool shims_send(const uint32_t arbitration_id, const uint8_t* data, const uint8_t size);
        static void shims_logger(const char* m, ...);
+
 public:
        diagnostic_manager_t();
        ~diagnostic_manager_t();
 
-       bool initialize();
+       bool initialize(std::string diagnostic_bus);
 
        const std::string get_bus_name() const;
        const std::string get_bus_device_name() const;