diff --git a/modules/OCPPConfiguration/main/event_handler.cpp b/modules/OCPPConfiguration/main/event_handler.cpp index eb0e94a3dd..120967a1ed 100644 --- a/modules/OCPPConfiguration/main/event_handler.cpp +++ b/modules/OCPPConfiguration/main/event_handler.cpp @@ -9,7 +9,7 @@ namespace module { EventHandler::EventHandler(const std::filesystem::path& config_mapping_path) : - config_mapping(MappingReader::read_mapping(config_mapping_path)) { + config_mapping(mapping_reader::read_mapping(config_mapping_path)) { } void EventHandler::try_handle_event(const types::ocpp::EventData& event_data, @@ -45,7 +45,7 @@ void EventHandler::write_event_to_config(const types::ocpp::EventData& event_dat const std::string& user_config_path_string, const EverestConfigMapping& everest_module_mapping) { const auto user_config_path = std::filesystem::path{user_config_path_string}; - auto tree = util::load_existing_user_config(user_config_path); + auto tree = util::try_to_load_existing_user_config(user_config_path); util::write_value_to_tree(everest_module_mapping, event_data.actual_value, tree); util::save_tree_to_yaml_file(tree, user_config_path); } diff --git a/modules/OCPPConfiguration/main/event_handler.hpp b/modules/OCPPConfiguration/main/event_handler.hpp index 3e5852e5ba..b126ec8a8c 100644 --- a/modules/OCPPConfiguration/main/event_handler.hpp +++ b/modules/OCPPConfiguration/main/event_handler.hpp @@ -8,10 +8,34 @@ namespace module { +/** + * Handles incoming events and writes them to the user configuration. + * + * The EventHandler builds an in memory dictionary out of the mapping file. + * It uses this dictionary to look up given events and write them to the user configuration with their values. + */ class EventHandler { public: - EventHandler(const std::filesystem::path& config_mapping_path); - void try_handle_event(const types::ocpp::EventData& event_data, const std::string& user_config_path_string) noexcept; + /** + * Create an EventHandler with the given mapping file. + * + * @param config_mapping_path Path to the mapping file. + */ + explicit EventHandler(const std::filesystem::path& config_mapping_path); + + /** + * Try to handle the given event. If successful, the event will be written to the user configuration file given. + * + * @param event_data The event to handle. Usually received from the OCPP module. + * @param user_config_path_string The path to the user configuration file. This file will be read from and written + * to. + */ + void try_handle_event(const types::ocpp::EventData& event_data, + const std::string& user_config_path_string) noexcept; + + /** + * Get the unique monitor variables that are used by this EventHandler. + */ std::vector get_monitor_variables() const noexcept; private: diff --git a/modules/OCPPConfiguration/main/everest_config_mapping.hpp b/modules/OCPPConfiguration/main/everest_config_mapping.hpp index 4d6e75308e..8a5387840e 100644 --- a/modules/OCPPConfiguration/main/everest_config_mapping.hpp +++ b/modules/OCPPConfiguration/main/everest_config_mapping.hpp @@ -45,9 +45,12 @@ template <> struct std::hash { namespace module { +/** + * Data structure to hold the user configuration mapping information. + */ struct EverestConfigMapping { - std::string module_id; - std::string config_param; + std::string module_id; /// The module id as defined in the everest config schema. + std::string config_param; /// The key for the `config_module` mapping in the config file. }; } // namespace module diff --git a/modules/OCPPConfiguration/main/mapping_reader.cpp b/modules/OCPPConfiguration/main/mapping_reader.cpp index e5d8f31590..993ca1a111 100644 --- a/modules/OCPPConfiguration/main/mapping_reader.cpp +++ b/modules/OCPPConfiguration/main/mapping_reader.cpp @@ -7,16 +7,16 @@ #include namespace module { -OcppToEverestConfigMapping MappingReader::read_mapping(const std::filesystem::path& file_path) { - const auto hacked_file_path = - std::filesystem::path{"modules"} / "OCPPConfiguration" / file_path; // TODO: this is very hacky - - const auto tree = util::load_yaml_file(hacked_file_path); - const auto root = tree.rootref(); - - return parse_mapping(root); -} -OcppToEverestConfigMapping MappingReader::parse_mapping(const c4::yml::NodeRef& root) { +namespace { +OcppToEverestConfigMapping parse_mapping(const c4::yml::NodeRef& root); +std::pair parse_mapping_node(const c4::yml::NodeRef& mapping_node); +EverestConfigMapping parse_maps_to_node(const ryml::NodeRef& node); +types::ocpp::Component parse_component_node(const c4::yml::NodeRef& node); +std::optional parse_evse_node(const c4::yml::NodeRef node); +Variable parse_variable_node(const c4::yml::NodeRef node); +ComponentVariable parse_component_variable_node(const c4::yml::NodeRef& node); + +OcppToEverestConfigMapping parse_mapping(const c4::yml::NodeRef& root) { auto mapping = OcppToEverestConfigMapping{}; for (const auto& mapping_node : root) { @@ -25,14 +25,14 @@ OcppToEverestConfigMapping MappingReader::parse_mapping(const c4::yml::NodeRef& } return mapping; } -std::pair -MappingReader::parse_mapping_node(const c4::yml::NodeRef& mapping_node) { + +std::pair parse_mapping_node(const c4::yml::NodeRef& mapping_node) { auto component_variable = parse_component_variable_node(mapping_node["ocpp_definition"]); auto module_mapping = parse_maps_to_node(mapping_node["everest_definition"]); return {std::move(component_variable), std::move(module_mapping)}; } -ComponentVariable MappingReader::parse_component_variable_node(const c4::yml::NodeRef& node) { +ComponentVariable parse_component_variable_node(const c4::yml::NodeRef& node) { // component is optional auto component = node.has_child("component") ? parse_component_node(node["component"]) : Component{}; @@ -41,7 +41,7 @@ ComponentVariable MappingReader::parse_component_variable_node(const c4::yml::No return {std::move(component), std::move(variable)}; } -Component MappingReader::parse_component_node(const c4::yml::NodeRef& node) { +Component parse_component_node(const c4::yml::NodeRef& node) { auto evse = node.has_child("evse") ? parse_evse_node(node["evse"]) : std::nullopt; const auto instance_optinal_val = node.has_child("instance") ? std::optional{node["instance"].val()} : std::nullopt; @@ -53,7 +53,7 @@ Component MappingReader::parse_component_node(const c4::yml::NodeRef& node) { return {std::move(component_name), std::move(instance), std::move(evse)}; } -Variable MappingReader::parse_variable_node(const c4::yml::NodeRef node) { +Variable parse_variable_node(const c4::yml::NodeRef node) { const auto node_has_name = node.has_child("name"); if (!node_has_name) { throw std::runtime_error("Variable node must have a name"); @@ -76,7 +76,7 @@ Variable MappingReader::parse_variable_node(const c4::yml::NodeRef node) { return {std::move(variable_name), std::move(instance)}; } -std::optional MappingReader::parse_evse_node(const c4::yml::NodeRef node) { +std::optional parse_evse_node(const c4::yml::NodeRef node) { if (!node.has_child("id")) { throw std::runtime_error("EVSE node must have an id"); } @@ -92,7 +92,7 @@ std::optional MappingReader::parse_evse_node(const c4::yml::N return types::ocpp::EVSE{std::move(id), std::move(connector_id)}; } -EverestConfigMapping MappingReader::parse_maps_to_node(const ryml::NodeRef& node) { +EverestConfigMapping parse_maps_to_node(const ryml::NodeRef& node) { const auto parse_node = [](const auto& node) { const auto val = node.val(); @@ -108,4 +108,16 @@ EverestConfigMapping MappingReader::parse_maps_to_node(const ryml::NodeRef& node return {module_id, config_param}; } -} // namespace module \ No newline at end of file +} // namespace + +OcppToEverestConfigMapping mapping_reader::read_mapping(const std::filesystem::path& file_path) { + const auto hacked_file_path = + std::filesystem::path{"modules"} / "OCPPConfiguration" / file_path; // TODO: this is very hacky + + const auto tree = util::load_yaml_file(hacked_file_path); + const auto root = tree.rootref(); + + return parse_mapping(root); +} + +} // namespace module diff --git a/modules/OCPPConfiguration/main/mapping_reader.hpp b/modules/OCPPConfiguration/main/mapping_reader.hpp index 963a2036e3..48baa40bab 100644 --- a/modules/OCPPConfiguration/main/mapping_reader.hpp +++ b/modules/OCPPConfiguration/main/mapping_reader.hpp @@ -20,18 +20,19 @@ using types::ocpp::Variable; using OcppToEverestConfigMapping = std::unordered_map; -class MappingReader { -public: - static OcppToEverestConfigMapping read_mapping(const std::filesystem::path& file_path); - -private: - static std::pair parse_mapping_node(const c4::yml::NodeRef& mapping_node); - static EverestConfigMapping parse_maps_to_node(const ryml::NodeRef& node); - static types::ocpp::Component parse_component_node(const c4::yml::NodeRef& node); - static std::optional parse_evse_node(const c4::yml::NodeRef node); - static Variable parse_variable_node(const c4::yml::NodeRef node); - static ComponentVariable parse_component_variable_node(const c4::yml::NodeRef& node); - static OcppToEverestConfigMapping parse_mapping(const c4::yml::NodeRef& root); -}; +/** + * Collection of functions to read the mapping file. + */ +namespace mapping_reader { + +/** + * Reads the mapping file and returns the mapping. + * + * @param file_path The path to the mapping file. + * @return The mapping. + */ +OcppToEverestConfigMapping read_mapping(const std::filesystem::path& file_path); + +}; // namespace mapping_reader } // namespace module \ No newline at end of file diff --git a/modules/OCPPConfiguration/main/util.cpp b/modules/OCPPConfiguration/main/util.cpp index 77bdadb4b3..3536742aee 100644 --- a/modules/OCPPConfiguration/main/util.cpp +++ b/modules/OCPPConfiguration/main/util.cpp @@ -12,7 +12,7 @@ namespace module { namespace util { -ryml::Tree load_existing_user_config(const std::filesystem::path& user_config_file_path) { +ryml::Tree try_to_load_existing_user_config(const std::filesystem::path& user_config_file_path) noexcept { try { // file exists return load_yaml_file(user_config_file_path); @@ -68,5 +68,5 @@ void write_value_to_tree(const EverestConfigMapping& module_mapping, const std:: config_param_node << config_value_csubstr; } -} // namespace Util +} // namespace util } // namespace module \ No newline at end of file diff --git a/modules/OCPPConfiguration/main/util.hpp b/modules/OCPPConfiguration/main/util.hpp index e8ef428e8e..f65db12994 100644 --- a/modules/OCPPConfiguration/main/util.hpp +++ b/modules/OCPPConfiguration/main/util.hpp @@ -14,13 +14,41 @@ namespace module { namespace util { -ryml::Tree load_existing_user_config(const std::filesystem::path& user_config_file_path); +/** + * Try to load the existing user configuration file. + * + * @param user_config_file_path The path to the user configuration file. + * @return The loaded tree or an empty tree if the file doesn't exist. + */ +ryml::Tree try_to_load_existing_user_config(const std::filesystem::path& user_config_file_path) noexcept; +/** + * Load a YAML file. + * + * @param file_path The path to the YAML file. + * @return The loaded tree. + * @throws std::runtime_error if the file can't be opened. + */ ryml::Tree load_yaml_file(const std::filesystem::path& file_path); + +/** + * Save a tree to a YAML file. + * + * @param tree The tree to save. + * @param file_path The path to the file. + * @throws std::runtime_error if the file can't be opened. + */ void save_tree_to_yaml_file(const ryml::Tree& tree, const std::filesystem::path& file_path); +/** + * Write a value to the tree. The tree is modified in place. + * + * @param module_mapping The module mapping. + * @param config_value The value to write. + * @param config_tree The tree to write to. + */ void write_value_to_tree(const EverestConfigMapping& module_mapping, const std::string& config_value, ryml::Tree& config_tree); -}; // namespace Util +}; // namespace util } // namespace module \ No newline at end of file