From 4fa142602e88f10db244bbf3e9b9b50a87726ff5 Mon Sep 17 00:00:00 2001 From: MarzellT Date: Thu, 15 Aug 2024 17:25:05 +0200 Subject: [PATCH] fixes writing config failing if file doesn't exist and adds component information to the config Signed-off-by: MarzellT --- modules/OCPPConfiguration/CMakeLists.txt | 2 +- .../OCPPConfiguration/OCPPConfiguration.cpp | 8 +- .../OCPPConfiguration/OCPPConfiguration.hpp | 11 +- modules/OCPPConfiguration/config-mapping.yaml | 125 +++++++----------- .../example_module/example_userImpl.cpp | 16 --- modules/OCPPConfiguration/main/emptyImpl.cpp | 16 +++ .../emptyImpl.hpp} | 20 +-- .../OCPPConfiguration/main/event_handler.cpp | 10 +- .../OCPPConfiguration/main/event_handler.hpp | 3 + .../OCPPConfiguration/main/mapping_reader.cpp | 8 +- .../OCPPConfiguration/main/mapping_reader.hpp | 3 +- modules/OCPPConfiguration/main/util.cpp | 53 ++++++-- modules/OCPPConfiguration/main/util.hpp | 5 +- modules/OCPPConfiguration/manifest.yaml | 6 +- 14 files changed, 142 insertions(+), 144 deletions(-) delete mode 100644 modules/OCPPConfiguration/example_module/example_userImpl.cpp create mode 100644 modules/OCPPConfiguration/main/emptyImpl.cpp rename modules/OCPPConfiguration/{example_module/example_userImpl.hpp => main/emptyImpl.hpp} (68%) diff --git a/modules/OCPPConfiguration/CMakeLists.txt b/modules/OCPPConfiguration/CMakeLists.txt index d63bac7749..02f6a51a20 100644 --- a/modules/OCPPConfiguration/CMakeLists.txt +++ b/modules/OCPPConfiguration/CMakeLists.txt @@ -17,7 +17,7 @@ target_link_libraries(${MODULE_NAME} target_sources(${MODULE_NAME} PRIVATE - "example_module/example_userImpl.cpp" + "main/emptyImpl.cpp" "main/mapping_reader.cpp" "main/util.cpp" "main/event_handler.cpp" diff --git a/modules/OCPPConfiguration/OCPPConfiguration.cpp b/modules/OCPPConfiguration/OCPPConfiguration.cpp index ea5b6851f3..46be34cabd 100644 --- a/modules/OCPPConfiguration/OCPPConfiguration.cpp +++ b/modules/OCPPConfiguration/OCPPConfiguration.cpp @@ -7,15 +7,11 @@ namespace module { void OCPPConfiguration::init() { - invoke_init(*p_example_module); + invoke_init(*p_main); } void OCPPConfiguration::ready() { - invoke_ready(*p_example_module); - -// auto attached = false; -// while (!attached) { -// }; + invoke_ready(*p_main); const auto mapping_file_path = std::filesystem::path{config.mapping_file_path}; event_handler = std::make_unique(mapping_file_path); diff --git a/modules/OCPPConfiguration/OCPPConfiguration.hpp b/modules/OCPPConfiguration/OCPPConfiguration.hpp index 5d4ded79e0..c58ad66f50 100644 --- a/modules/OCPPConfiguration/OCPPConfiguration.hpp +++ b/modules/OCPPConfiguration/OCPPConfiguration.hpp @@ -11,7 +11,7 @@ #include "ld-ev.hpp" // headers for provided interface implementations -#include +#include // headers for required interface implementations #include @@ -32,14 +32,11 @@ struct Conf { class OCPPConfiguration : public Everest::ModuleBase { public: OCPPConfiguration() = delete; - OCPPConfiguration(const ModuleInfo& info, std::unique_ptr p_example_module, + OCPPConfiguration(const ModuleInfo& info, std::unique_ptr p_main, std::unique_ptr r_ocpp_module, Conf& config) : - ModuleBase(info), - p_example_module(std::move(p_example_module)), - r_ocpp_module(std::move(r_ocpp_module)), - config(config){}; + ModuleBase(info), p_main(std::move(p_main)), r_ocpp_module(std::move(r_ocpp_module)), config(config){}; - const std::unique_ptr p_example_module; + const std::unique_ptr p_main; const std::unique_ptr r_ocpp_module; const Conf& config; diff --git a/modules/OCPPConfiguration/config-mapping.yaml b/modules/OCPPConfiguration/config-mapping.yaml index 0bcf677348..2f4fc2f5b0 100644 --- a/modules/OCPPConfiguration/config-mapping.yaml +++ b/modules/OCPPConfiguration/config-mapping.yaml @@ -1,100 +1,75 @@ AllowOfflineTxForUnknownId: - config_key: allow_offline_tx_for_unknown_id - module_name: testAllowOfflineTxForUnknownId - module_config_key: allow_offline_tx_for_unknown_id_config + module_id: allow_offline_tx_for_unknown_id + config_key: allow_offline_tx_for_unknown_id_config AuthorizationCacheEnabled: - config_key: authorization_cache_enabled - module_name: testAuthCacheEnabled - module_config_key: authorization_cache_enabled_config + module_id: authorization_cache_enabled + config_key: authorization_cache_enabled_config AuthorizeRemoteTxRequests: - config_key: authorize_remote_tx_requests - module_name: testAuthorizeRemoteTxRequests - module_config_key: authorize_remote_tx_requests_config + module_id: authorize_remote_tx_requests + config_key: authorize_remote_tx_requests_config BlinkRepeat: - config_key: blink_repeat - module_name: testBlinkRepeat - module_config_key: blink_repeat_config + module_id: blink_repeat + config_key: blink_repeat_config ClockAlignedDataInterval: - config_key: clock_aligned_data_interval - module_name: testClockAlignedDataInterval - module_config_key: clock_aligned_data_interval_config + module_id: clock_aligned_data_interval + config_key: clock_aligned_data_interval_config ConnectionTimeOut: - config_key: connection_time_out - module_name: testConnectionTimeOut - module_config_key: connection_time_out_config + module_id: connection_time_out + config_key: connection_time_out_config ConnectorPhaseRotation: - config_key: connector_phase_rotation - module_name: testConnectorPhaseRotation - module_config_key: connector_phase_rotation_config + module_id: connector_phase_rotation + config_key: connector_phase_rotation_config HeartbeatInterval: - config_key: heartbeat_interval - module_name: testHeartbeatInterval - module_config_key: heartbeat_interval_config + module_id: heartbeat_interval + config_key: heartbeat_interval_config LightIntensity: - config_key: light_intensity - module_name: testLightIntensity - module_config_key: light_intensity_config + module_id: light_intensity + config_key: light_intensity_config LocalAuthorizeOffline: - config_key: local_authorize_offline - module_name: testLocalAuthorizeOffline - module_config_key: local_authorize_offline_config + module_id: local_authorize_offline + config_key: local_authorize_offline_config LocalPreAuthorize: - config_key: local_pre_authorize - module_name: testLocalPreAuthorize - module_config_key: local_pre_authorize_config + module_id: local_pre_authorize + config_key: local_pre_authorize_config MaxEnergyOnInvalidId: - config_key: max_energy_on_invalid_id - module_name: testMaxEnergyOnInvalidId - module_config_key: max_energy_on_invalid_id_config + module_id: max_energy_on_invalid_id + config_key: max_energy_on_invalid_id_config MeterValuesAlignedData: - config_key: meter_values_aligned_data - module_name: testMeterValuesAlignedData - module_config_key: meter_values_aligned_data_config + module_id: meter_values_aligned_data + config_key: meter_values_aligned_data_config MeterValuesSampledData: - config_key: meter_values_sampled_data - module_name: testMeterValuesSampledData - module_config_key: meter_values_sampled_data_config + module_id: meter_values_sampled_data + config_key: meter_values_sampled_data_config MeterValueSampleInterval: - config_key: meter_value_sample_interval - module_name: testMeterValueSampleInterval - module_config_key: meter_value_sample_interval_config + module_id: meter_value_sample_interval + config_key: meter_value_sample_interval_config MinimumStatusDuration: - config_key: minimum_status_duration - module_name: testMinimumStatusDuration - module_config_key: minimum_status_duration_config + module_id: minimum_status_duration + config_key: minimum_status_duration_config ResetRetries: - config_key: reset_retries - module_name: testResetRetries - module_config_key: reset_retries_config + module_id: reset_retries + config_key: reset_retries_config StopTransactionOnEVSideDisconnect: - config_key: stop_transaction_on_ev_side_disconnect - module_name: testStopTransactionOnEVSideDisconnect - module_config_key: stop_transaction_on_ev_side_disconnect_config + module_id: stop_transaction_on_ev_side_disconnect + config_key: stop_transaction_on_ev_side_disconnect_config StopTransactionOnInvalidId: - config_key: stop_transaction_on_invalid_id - module_name: testStopTransactionOnInvalidId - module_config_key: stop_transaction_on_invalid_id_config + module_id: stop_transaction_on_invalid_id + config_key: stop_transaction_on_invalid_id_config StopTxnAlignedData: - config_key: stop_txn_aligned_data - module_name: testStopTxnAlignedData - module_config_key: stop_txn_aligned_data_config + module_id: stop_txn_aligned_data + config_key: stop_txn_aligned_data_config StopTxnSampledData: - config_key: stop_txn_sampled_data - module_name: testStopTxnSampledData - module_config_key: stop_txn_sampled_data_config + module_id: stop_txn_sampled_data + config_key: stop_txn_sampled_data_config TransactionMessageAttempts: - config_key: transaction_message_attempts - module_name: testTransactionMessageAttempts - module_config_key: transaction_message_attempts_config + module_id: transaction_message_attempts + config_key: transaction_message_attempts_config TransactionMessageRetryInterval: - config_key: transaction_message_retry_interval - module_name: testTransactionMessageRetryInterval - module_config_key: transaction_message_retry_interval_config + module_id: transaction_message_retry_interval + config_key: transaction_message_retry_interval_config UnlockConnectorOnEVSideDisconnect: - config_key: unlock_connector_on_ev_side_disconnect - module_name: testUnlockConnectorOnEVSideDisconnect - module_config_key: unlock_connector_on_ev_side_disconnect_config + module_id: unlock_connector_on_ev_side_disconnect + config_key: unlock_connector_on_ev_side_disconnect_config WebsocketPingInterval: - config_key: websocket_ping_interval - module_name: testWebsocketPingInterval - module_config_key: websocket_ping_interval_config + module_id: websocket_ping_interval + config_key: websocket_ping_interval_config diff --git a/modules/OCPPConfiguration/example_module/example_userImpl.cpp b/modules/OCPPConfiguration/example_module/example_userImpl.cpp deleted file mode 100644 index c809db36ff..0000000000 --- a/modules/OCPPConfiguration/example_module/example_userImpl.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Pionix GmbH and Contributors to EVerest - -#include "example_userImpl.hpp" - -namespace module { -namespace example_module { - -void example_userImpl::init() { -} - -void example_userImpl::ready() { -} - -} // namespace example_module -} // namespace module diff --git a/modules/OCPPConfiguration/main/emptyImpl.cpp b/modules/OCPPConfiguration/main/emptyImpl.cpp new file mode 100644 index 0000000000..fe6fdfaa07 --- /dev/null +++ b/modules/OCPPConfiguration/main/emptyImpl.cpp @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest + +#include "emptyImpl.hpp" + +namespace module { +namespace main { + +void emptyImpl::init() { +} + +void emptyImpl::ready() { +} + +} // namespace main +} // namespace module \ No newline at end of file diff --git a/modules/OCPPConfiguration/example_module/example_userImpl.hpp b/modules/OCPPConfiguration/main/emptyImpl.hpp similarity index 68% rename from modules/OCPPConfiguration/example_module/example_userImpl.hpp rename to modules/OCPPConfiguration/main/emptyImpl.hpp index c660b1d4dc..49ce1834bf 100644 --- a/modules/OCPPConfiguration/example_module/example_userImpl.hpp +++ b/modules/OCPPConfiguration/main/emptyImpl.hpp @@ -1,14 +1,14 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright Pionix GmbH and Contributors to EVerest -#ifndef EXAMPLE_MODULE_EXAMPLE_USER_IMPL_HPP -#define EXAMPLE_MODULE_EXAMPLE_USER_IMPL_HPP +#ifndef MAIN_EMPTY_IMPL_HPP +#define MAIN_EMPTY_IMPL_HPP // // AUTO GENERATED - MARKED REGIONS WILL BE KEPT // template version 3 // -#include +#include #include "../OCPPConfiguration.hpp" @@ -17,15 +17,15 @@ // ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1 namespace module { -namespace example_module { +namespace main { struct Conf {}; -class example_userImpl : public example_userImplBase { +class emptyImpl : public emptyImplBase { public: - example_userImpl() = delete; - example_userImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer& mod, Conf& config) : - example_userImplBase(ev, "example_module"), mod(mod), config(config){}; + emptyImpl() = delete; + emptyImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer& mod, Conf& config) : + emptyImplBase(ev, "main"), mod(mod), config(config){}; // ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1 // insert your public definitions here @@ -54,7 +54,7 @@ class example_userImpl : public example_userImplBase { // insert other definitions here // ev@3d7da0ad-02c2-493d-9920-0bbbd56b9876:v1 -} // namespace example_module +} // namespace main } // namespace module -#endif // EXAMPLE_MODULE_EXAMPLE_USER_IMPL_HPP +#endif // MAIN_EMPTY_IMPL_HPP diff --git a/modules/OCPPConfiguration/main/event_handler.cpp b/modules/OCPPConfiguration/main/event_handler.cpp index 834a2343c3..a532691e6d 100644 --- a/modules/OCPPConfiguration/main/event_handler.cpp +++ b/modules/OCPPConfiguration/main/event_handler.cpp @@ -13,8 +13,10 @@ EventHandler::EventHandler(const std::filesystem::path& config_mapping_path) : void EventHandler::handleEvent(const types::ocpp::EventData& event_data, const std::string& user_config_path_string) { - // lookup event in event_map + // todo(tm): needs a way to handle ocpp 2.0.1 component variable combinations + // maybe add this to the mapping file const auto& event_name = event_data.component_variable.variable.name; + const auto& component = event_data.component_variable.component; const auto& everest_module_mapping_opt = find_event_in_map_or_log_error(event_name); if (!everest_module_mapping_opt.has_value()) { @@ -23,10 +25,12 @@ void EventHandler::handleEvent(const types::ocpp::EventData& event_data, const s const auto& everest_module_mapping = everest_module_mapping_opt.value(); - // write event to config + write_event_to_config(event_data, user_config_path_string, everest_module_mapping, component); +} +void EventHandler::write_event_to_config(const types::ocpp::EventData& event_data, const std::string& user_config_path_string, const EverestModuleMapping& everest_module_mapping, const types::ocpp::Component& component) { const auto user_config_path = std::filesystem::path{user_config_path_string}; auto tree = Util::load_existing_user_config(user_config_path); - tree = Util::write_value_to_tree(everest_module_mapping, event_data.actual_value, tree); + Util::write_value_to_tree(everest_module_mapping, event_data.actual_value, component, 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 24808bd4da..149af0481a 100644 --- a/modules/OCPPConfiguration/main/event_handler.hpp +++ b/modules/OCPPConfiguration/main/event_handler.hpp @@ -18,6 +18,9 @@ class EventHandler { const EverestModuleMapping find_event_in_map(const std::string& event_name) const; OcppToEverestModuleMapping event_map; + void write_event_to_config(const types::ocpp::EventData& event_data, const std::string& user_config_path_string, + const EverestModuleMapping& everest_module_mapping, + const types::ocpp::Component& component); }; } // namespace module diff --git a/modules/OCPPConfiguration/main/mapping_reader.cpp b/modules/OCPPConfiguration/main/mapping_reader.cpp index 776dd5cf55..41ebe43e43 100644 --- a/modules/OCPPConfiguration/main/mapping_reader.cpp +++ b/modules/OCPPConfiguration/main/mapping_reader.cpp @@ -15,15 +15,13 @@ EverestModuleMapping MappingReader::parseMappingNode(const ryml::NodeRef& node) return std::string{val.str, val.len}; }; + const auto module_id_node = node["module_id"]; const auto config_key_node = node["config_key"]; - const auto module_name_node = node["module_name"]; - const auto module_config_key_node = node["module_config_key"]; + const auto module_id = parse_node(module_id_node); const auto config_key = parse_node(config_key_node); - const auto module_name = parse_node(module_name_node); - const auto module_config_key = parse_node(module_config_key_node); - return {config_key, module_name, module_config_key}; + return {module_id, config_key}; } OcppToEverestModuleMapping MappingReader::readMapping(const std::filesystem::path& file_path) { diff --git a/modules/OCPPConfiguration/main/mapping_reader.hpp b/modules/OCPPConfiguration/main/mapping_reader.hpp index e972f6f23e..de9f1f9d38 100644 --- a/modules/OCPPConfiguration/main/mapping_reader.hpp +++ b/modules/OCPPConfiguration/main/mapping_reader.hpp @@ -13,9 +13,8 @@ namespace module { struct EverestModuleMapping { + std::string module_id; std::string config_key; - std::string module_name; - std::string module_config_key; }; using OcppToEverestModuleMapping = std::unordered_map; diff --git a/modules/OCPPConfiguration/main/util.cpp b/modules/OCPPConfiguration/main/util.cpp index e262da671f..52326f4fce 100644 --- a/modules/OCPPConfiguration/main/util.cpp +++ b/modules/OCPPConfiguration/main/util.cpp @@ -3,6 +3,7 @@ #include "util.hpp" #include "everest/logging.hpp" +#include "generated/types/ocpp.hpp" #include #include #include @@ -18,7 +19,7 @@ ryml::Tree load_existing_user_config(const std::filesystem::path& user_config_fi } // file doesn't exist catch (const std::runtime_error& e) { - return ryml::Tree(); + return {}; } } @@ -42,8 +43,10 @@ void save_tree_to_yaml_file(const ryml::Tree& tree, const std::filesystem::path& } file << tree; } -ryml::Tree write_value_to_tree(const EverestModuleMapping& module_mapping, const std::string& config_value, - const ryml::Tree& config_tree) { +void add_component_if_exists(const types::ocpp::Component& component, c4::yml::NodeRef& module_id_node); +void write_value_to_tree(const EverestModuleMapping& module_mapping, const std::string& config_value, + const types::ocpp::Component& component, ryml::Tree& config_tree) { + auto root = config_tree.rootref(); if (!root.is_map()) { root |= ryml::MAP; // mark root as map @@ -52,23 +55,45 @@ ryml::Tree write_value_to_tree(const EverestModuleMapping& module_mapping, const auto active_modules = root["active_modules"]; active_modules |= ryml::MAP; // mark active_modules as map - const auto config_key_csubstr = ryml::to_csubstr(module_mapping.config_key.c_str()); - auto config_key_node = active_modules[config_key_csubstr]; - config_key_node |= ryml::MAP; // mark config_key as map + const auto module_id_csubstr = ryml::to_csubstr(module_mapping.module_id.c_str()); + auto module_id_node = active_modules[module_id_csubstr]; + module_id_node |= ryml::MAP; // mark module_id as map - const auto module_name_csubstr = ryml::to_csubstr(module_mapping.module_name.c_str()); - auto module_node = config_key_node[module_name_csubstr]; - module_node |= ryml::MAP; // mark module as map + // component + add_component_if_exists(component, module_id_node); - auto config_module_node = module_node["config_module"]; + auto config_module_node = module_id_node["config_module"]; config_module_node |= ryml::MAP; - const auto module_config_key_csubstr = ryml::to_csubstr(module_mapping.module_config_key.c_str()); - auto module_config_key_node = config_module_node[module_config_key_csubstr]; + const auto config_key_csubstr = ryml::to_csubstr(module_mapping.config_key.c_str()); + auto config_key_node = config_module_node[config_key_csubstr]; const auto config_value_csubstr = ryml::to_csubstr(config_value.c_str()); - module_config_key_node << config_value_csubstr; + config_key_node << config_value_csubstr; +} + +void add_component_if_exists(const types::ocpp::Component& component, c4::yml::NodeRef& module_id_node) { + if (component.name.empty()) { + if (module_id_node.has_child("component")) { + module_id_node.remove_child("component"); + } + return; + } + + const auto component_name_csubstr = ryml::to_csubstr(component.name.c_str()); + const auto component_instance_csubstr = + ryml::to_csubstr(component.instance.has_value() ? component.instance.value().c_str() : ""); + const auto component_evse_csubstr = + ryml::to_csubstr(component.evse.has_value() ? std::to_string(component.evse.value().id).c_str() : ""); + + auto component_node = module_id_node["component"]; + component_node |= ryml::MAP; + auto component_name_node = component_node["name"]; - return config_tree; + component_name_node << component_name_csubstr; + auto component_instance_node = component_node["instance"]; + component_instance_node << component_instance_csubstr; + auto component_evse_node = component_node["evse_id"]; + component_evse_node << component_evse_csubstr; } } // namespace Util diff --git a/modules/OCPPConfiguration/main/util.hpp b/modules/OCPPConfiguration/main/util.hpp index 8fae6c065a..c1444a2bab 100644 --- a/modules/OCPPConfiguration/main/util.hpp +++ b/modules/OCPPConfiguration/main/util.hpp @@ -3,6 +3,7 @@ #pragma once +#include "generated/types/ocpp.hpp" #include "mapping_reader.hpp" #include "utils/yaml_loader.hpp" #include @@ -18,8 +19,8 @@ ryml::Tree load_existing_user_config(const std::filesystem::path& user_config_fi ryml::Tree load_yaml_file(const std::filesystem::path& file_path); void save_tree_to_yaml_file(const ryml::Tree& tree, const std::filesystem::path& file_path); -ryml::Tree write_value_to_tree(const EverestModuleMapping& module_mapping, const std::string& config_value, - const ryml::Tree& config_tree); +void write_value_to_tree(const EverestModuleMapping& module_mapping, const std::string& config_value, + const types::ocpp::Component& component, ryml::Tree& config_tree); }; // namespace Util } // namespace module \ No newline at end of file diff --git a/modules/OCPPConfiguration/manifest.yaml b/modules/OCPPConfiguration/manifest.yaml index 3f3822627a..17fc5ca148 100644 --- a/modules/OCPPConfiguration/manifest.yaml +++ b/modules/OCPPConfiguration/manifest.yaml @@ -21,9 +21,9 @@ config: type: string default: "config-mapping.yaml" provides: - example_module: - interface: example_user - description: "todo: what should it provide?" + main: + interface: empty + description: "doesn't provide anything" requires: ocpp_module: interface: ocpp