diff options
Diffstat (limited to 'low-can-binding')
-rw-r--r-- | low-can-binding/CMakeLists.txt | 2 | ||||
-rw-r--r-- | low-can-binding/binding/low-can-cb.cpp | 81 | ||||
-rw-r--r-- | low-can-binding/can/can-bus.cpp | 8 | ||||
-rw-r--r-- | low-can-binding/can/can-bus.hpp | 1 | ||||
-rw-r--r-- | low-can-binding/can/message-definition.cpp | 4 | ||||
-rw-r--r-- | low-can-binding/utils/config-parser.cpp | 68 | ||||
-rw-r--r-- | low-can-binding/utils/config-parser.hpp | 44 |
7 files changed, 194 insertions, 14 deletions
diff --git a/low-can-binding/CMakeLists.txt b/low-can-binding/CMakeLists.txt index 38ac4b3d..7f73339d 100644 --- a/low-can-binding/CMakeLists.txt +++ b/low-can-binding/CMakeLists.txt @@ -59,6 +59,7 @@ PROJECT_TARGET_ADD(low-can) #utils/socketcan-raw.cpp utils/socketcan-bcm.cpp utils/converter.cpp + utils/config-parser.cpp ) add_library(${TARGET_NAME} SHARED ${SOURCES_LIB} ${SOURCES_J1939} ${SOURCES_ISOTP}) @@ -70,6 +71,7 @@ PROJECT_TARGET_ADD(low-can) ) TARGET_LINK_LIBRARIES(${TARGET_NAME} + ini-config openxc-message-format uds-c isotp-c diff --git a/low-can-binding/binding/low-can-cb.cpp b/low-can-binding/binding/low-can-cb.cpp index d994dd24..32adac86 100644 --- a/low-can-binding/binding/low-can-cb.cpp +++ b/low-can-binding/binding/low-can-cb.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2015, 2018 "IoT.bzh" + * Copyright (C) 2021 Konsulko Group * Author "Romain Forlot" <romain.forlot@iot.bzh> * Author "Loic Collignon" <loic.collignon@iot.bzh> * @@ -23,6 +24,7 @@ #include <queue> #include <mutex> #include <vector> +#include <set> #include <thread> #include <algorithm> #include <wrap-json.h> @@ -37,7 +39,7 @@ #include "../utils/signals.hpp" #include "../diagnostic/diagnostic-message.hpp" #include "../utils/openxc-utils.hpp" -#include "../utils/signals.hpp" +#include "../utils/config-parser.hpp" #ifdef USE_FEATURE_J1939 #include "../can/message/j1939-message.hpp" @@ -56,7 +58,7 @@ int config_low_can(afb_api_t apiHandle, CtlSectionT *section, json_object *json_ CtlConfigT *ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle); int active_message_set = 0; json_object *dev_mapping = nullptr; - const char *diagnotic_bus = nullptr; + const char *diagnostic_bus = nullptr; if(! ctrlConfig || ! ctrlConfig->external) return -1; @@ -64,35 +66,86 @@ int config_low_can(afb_api_t apiHandle, CtlSectionT *section, json_object *json_ application_t *application = (application_t*) ctrlConfig->external; if(wrap_json_unpack(json_obj, "{si, s?s}", - "active_message_set", &active_message_set, - "diagnostic_bus", &diagnotic_bus)) + "active_message_set", &active_message_set, + "diagnostic_bus", &diagnostic_bus)) { + AFB_ERROR("active_message_set and/or diagnostic_bus missing in controller JSON"); + return -1; + } + + if(active_message_set < 0 || + active_message_set > (application->get_messages_definition().size() - 1)) { + AFB_ERROR("Invalid active message set %d", active_message_set); return -1; + } + application->set_active_message_set((uint8_t) active_message_set); + + utils::config_parser_t conf_file("/etc/dev-mapping.conf"); + if(conf_file.check_conf()) + { + // If a mapping file in /etc exists, use it + AFB_INFO("Using /etc/dev-mapping.conf"); + application->get_can_bus_manager().set_can_devices(conf_file.get_devices_name()); + } else { + // Use whatever configuration is in the controller JSON + if(wrap_json_unpack(json_obj, "{so}", + "dev-mapping", &dev_mapping)) { + AFB_ERROR("No device mapping in controller JSON"); + return -1; + } + + application->get_can_bus_manager().set_can_devices(dev_mapping); + } + + // Find all required buses + std::set<std::string> buses; + std::set<std::string> j1939_buses; + vect_ptr_msg_def_t msg_defs = application->get_messages_definition(); + for(std::shared_ptr<message_definition_t> &msg_def : msg_defs) { + if(!msg_def->is_j1939()) + buses.insert(msg_def->get_bus_name()); + else + j1939_buses.insert(msg_def->get_bus_name()); + } +#ifdef USE_FEATURE_J1939 + // NOTE: With C++17 just: buses.merge(j1939_buses) + for(auto it = begin(j1939_buses); it != end(j1939_buses); ++it) + buses.insert(*it); +#endif - application->set_active_message_set((uint8_t)active_message_set); + // Check that required buses have device mappings + for(auto it = begin(buses); it != end(buses); ++it) { + std::string dev = application->get_can_bus_manager().get_can_device_name(*it); + if(dev == "") { + AFB_ERROR("No CAN device defined for bus \"%s\"", it->c_str()); + return -1; + } + AFB_INFO("Using CAN device %s for bus \"%s\"", dev.c_str(), it->c_str()); + } - if(wrap_json_unpack(json_obj, "{so}", - "dev-mapping", &dev_mapping)) + // Check that diagnostic bus is one of the configured buses + if(diagnostic_bus && buses.count(diagnostic_bus) == 0) { + AFB_ERROR("No CAN device mapping defined for diagnostic bus \"%s\"", diagnostic_bus); return -1; - application->get_can_bus_manager().set_can_devices(dev_mapping); + } /// Initialize Diagnostic manager that will handle obd2 requests. /// We pass by default the first CAN bus device to its Initialization. - if(! diagnotic_bus || application_t::instance().get_diagnostic_manager().initialize(diagnotic_bus)) + if(! diagnostic_bus || application_t::instance().get_diagnostic_manager().initialize(diagnostic_bus)) AFB_WARNING("Diagnostic Manager: not initialized. No diagnostic messages will be processed."); 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, + [0]={.key="plugins" , .uid="plugins", .info=nullptr, .loadCB=PluginConfig, .handle=nullptr, .actions=nullptr}, + [1]={.key="config" , .uid="config", .info=nullptr, + .loadCB=config_low_can, + .handle=nullptr, + .actions=nullptr}, [2]={.key=nullptr , .uid=nullptr, .info=nullptr, .loadCB=nullptr, .handle=nullptr, diff --git a/low-can-binding/can/can-bus.cpp b/low-can-binding/can/can-bus.cpp index 40e080f8..11b7770c 100644 --- a/low-can-binding/can/can-bus.cpp +++ b/low-can-binding/can/can-bus.cpp @@ -69,6 +69,14 @@ void can_bus_t::set_can_devices(json_object *mapping) } } +/// @brief Fills the CAN device map member with given values +/// +/// @param[in] mapping configuration section. +void can_bus_t::set_can_devices(const std::vector<std::pair<std::string, std::string> >& mapping) +{ + can_devices_mapping_ = mapping; +} + /// @brief Take a decoded message to determine if its value complies with the desired /// filters. /// diff --git a/low-can-binding/can/can-bus.hpp b/low-can-binding/can/can-bus.hpp index 5aa7a1d5..88b1dd4e 100644 --- a/low-can-binding/can/can-bus.hpp +++ b/low-can-binding/can/can-bus.hpp @@ -70,6 +70,7 @@ public: ~can_bus_t(); void set_can_devices(json_object *mapping); + void set_can_devices(const std::vector<std::pair<std::string, std::string> >& mapping); int get_can_device_index(const std::string& bus_name) const; const std::string get_can_device_name(const std::string& id_name) const; diff --git a/low-can-binding/can/message-definition.cpp b/low-can-binding/can/message-definition.cpp index dab502af..051c2d3c 100644 --- a/low-can-binding/can/message-definition.cpp +++ b/low-can-binding/can/message-definition.cpp @@ -56,6 +56,10 @@ message_definition_t::message_definition_t(const std::string bus, signals_{signals} {} +const std::string message_definition_t::get_bus_name() const{ + return bus_; +} + const std::string message_definition_t::get_bus_device_name() const { return application_t::instance().get_can_bus_manager() diff --git a/low-can-binding/utils/config-parser.cpp b/low-can-binding/utils/config-parser.cpp new file mode 100644 index 00000000..589f0340 --- /dev/null +++ b/low-can-binding/utils/config-parser.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015, 2016 ,2017 "IoT.bzh" + * Copyright (C) 2021 Konsulko Group + * Author "Romain Forlot" <romain.forlot@iot.bzh> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "config-parser.hpp" + +#include "../binding/low-can-hat.hpp" + +namespace utils +{ + /// @brief constructor using path to file + config_parser_t::config_parser_t(std::string conf_file) + : filepath_{conf_file}, config_content_{} + { + config_content_.read_file(conf_file); + } + + const std::string& config_parser_t::filepath() const + { + return filepath_; + } + + /// @brief read the conf_file_ and parse it into an INIReader object + /// to search into later. + bool config_parser_t::check_conf() + { + if (config_content_.size() <= 0) + { + AFB_INFO("Cannot load INI config file: %s.", filepath_.c_str()); + return false; + } + AFB_DEBUG("Configuration file parsed"); + return true; + } + + /// @brief Public method to access devices_name_ vector. If vector size equal 0 + /// then it will parses the configuration file content to fill it. It could be empty even + /// after parsing if content file just don't have a correct "canbus" directive so you + /// have to test the returned value. + /// + /// @return A const vector with string of linux CAN devices. + const std::vector<std::pair<std::string, std::string> > config_parser_t::get_devices_name() + { + std::vector<std::pair<std::string, std::string> > devices_name; + + std::map<std::string, std::string> bus_mapping = config_content_.get_keys("CANbus-mapping"); + for(const auto& busIt : bus_mapping ) + { + devices_name.push_back(std::make_pair(busIt.first, busIt.second)); + } + + return devices_name; + } +} diff --git a/low-can-binding/utils/config-parser.hpp b/low-can-binding/utils/config-parser.hpp new file mode 100644 index 00000000..3115e9bd --- /dev/null +++ b/low-can-binding/utils/config-parser.hpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015, 2016 ,2017 "IoT.bzh" + * Author "Romain Forlot" <romain.forlot@iot.bzh> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <string> +#include <vector> +#include <utility> +#include "ini-config.hpp" + +namespace utils +{ + /// @brief A configuration file parser that handle INI configuration + /// file format. + class config_parser_t + { + private: + const std::string filepath_; /*!< filepath_ - Path to the config file*/ + ini_config config_content_; /*!< config_content_ - Parsed content of INI file.*/ + + public: + config_parser_t(config_parser_t&&) = default; + config_parser_t(const config_parser_t&) = default; + explicit config_parser_t(std::string conf_file); + + const std::string& filepath() const; + bool check_conf(); + const std::vector<std::pair<std::string, std::string> > get_devices_name(); + }; +} |