From 630c48cd5f42e347524499025b4ed898e9201fed Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Fri, 27 Sep 2024 15:31:14 +0200 Subject: [PATCH 01/22] WIP: make mappings available outside of errors Signed-off-by: Kai-Uwe Hermann --- include/framework/ModuleAdapter.hpp | 4 ++ include/framework/everest.hpp | 10 +++++ include/framework/runtime.hpp | 8 ++-- include/utils/config.hpp | 4 +- include/utils/types.hpp | 11 ++++- lib/config.cpp | 23 +++++++---- lib/everest.cpp | 63 +++++++++++++++++++---------- lib/runtime.cpp | 21 +++++++--- lib/types.cpp | 3 +- 9 files changed, 104 insertions(+), 43 deletions(-) diff --git a/include/framework/ModuleAdapter.hpp b/include/framework/ModuleAdapter.hpp index b91c4c8c..d4c45484 100644 --- a/include/framework/ModuleAdapter.hpp +++ b/include/framework/ModuleAdapter.hpp @@ -92,6 +92,8 @@ struct ModuleAdapter { using ExtMqttSubscribeFunc = std::function; using TelemetryPublishFunc = std::function; + using GetMappingFunc = std::function()>; + using GetImplMappingFunc = std::function(const std::string&)>; CallFunc call; PublishFunc publish; @@ -107,6 +109,8 @@ struct ModuleAdapter { ExtMqttSubscribeFunc ext_mqtt_subscribe; std::vector registered_commands; TelemetryPublishFunc telemetry_publish; + GetMappingFunc get_mapping; + GetImplMappingFunc get_impl_mapping; void check_complete() { // FIXME (aw): I should throw if some of my handlers are not set diff --git a/include/framework/everest.hpp b/include/framework/everest.hpp index b0f7252f..98740a3e 100644 --- a/include/framework/everest.hpp +++ b/include/framework/everest.hpp @@ -142,6 +142,16 @@ class Everest { /// \returns true if telemetry is enabled bool is_telemetry_enabled(); + /// + /// \returns the 3 tier model mappings for this module + /// + std::optional get_3_tier_model_mapping(); + + /// + /// \returns the 3 tier model mapping for the given \p impl_id + /// + std::optional get_3_tier_model_mapping(const std::string& impl_id); + /// /// \brief Chccks if all commands of a module that are listed in its manifest are available /// diff --git a/include/framework/runtime.hpp b/include/framework/runtime.hpp index 918a9cd9..e3ff65d6 100644 --- a/include/framework/runtime.hpp +++ b/include/framework/runtime.hpp @@ -134,14 +134,16 @@ void populate_module_info_path_from_runtime_settings(ModuleInfo&, std::shared_pt struct ModuleCallbacks { std::function register_module_adapter; - std::function(const json& connections)> everest_register; + std::function( + const std::map>& requirement_connections)> + everest_register; std::function init; std::function ready; ModuleCallbacks() = default; ModuleCallbacks(const std::function& register_module_adapter, - const std::function(const json& connections)>& everest_register, + const std::function(const std::map>& requirement_connections)>& everest_register, const std::function& init, const std::function& ready); }; @@ -164,7 +166,7 @@ class ModuleLoader { public: explicit ModuleLoader(int argc, char* argv[], ModuleCallbacks callbacks) : - ModuleLoader(argc, argv, callbacks, {"undefined project", "undefined version", "undefined git version"}){}; + ModuleLoader(argc, argv, callbacks, {"undefined project", "undefined version", "undefined git version"}) {}; explicit ModuleLoader(int argc, char* argv[], ModuleCallbacks callbacks, const VersionInformation version_information); diff --git a/include/utils/config.hpp b/include/utils/config.hpp index e5d0202e..61293881 100644 --- a/include/utils/config.hpp +++ b/include/utils/config.hpp @@ -147,9 +147,9 @@ class Config { json resolve_requirement(const std::string& module_id, const std::string& requirement_id) const; /// - /// \returns a list of Requirements for \p module_id + /// \returns a map of RequirementConnections for \p module_id /// - std::list get_requirements(const std::string& module_id) const; + std::map> get_requirement_connections(const std::string& module_id); /// /// \brief checks if the config contains the given \p module_id diff --git a/include/utils/types.hpp b/include/utils/types.hpp index e3d2afc4..dbc34b90 100644 --- a/include/utils/types.hpp +++ b/include/utils/types.hpp @@ -105,10 +105,17 @@ struct ModuleTierMappings { }; struct Requirement { - Requirement(const std::string& requirement_id_, size_t index_); + Requirement() = default; + Requirement(const std::string& requirement_id_, size_t index_, std::optional mapping = std::nullopt); bool operator<(const Requirement& rhs) const; std::string id; - size_t index; + size_t index = 0; + std::optional mapping; +}; + +struct RequirementConnection { + Requirement requirement; + std::string requirement_module_id; }; struct ImplementationIdentifier { diff --git a/lib/config.cpp b/lib/config.cpp index b455d662..434425d6 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -705,23 +705,31 @@ json Config::resolve_requirement(const std::string& module_id, const std::string return module_config["connections"][requirement_id]; } -std::list Config::get_requirements(const std::string& module_id) const { +std::map> Config::get_requirement_connections(const std::string& module_id) { BOOST_LOG_FUNCTION(); - std::list res; + std::map> res; std::string module_name = get_module_name(module_id); for (const std::string& req_id : Config::keys(this->manifests.at(module_name).at("requires"))) { + std::vector requirement_connections; json resolved_req = this->resolve_requirement(module_id, req_id); if (!resolved_req.is_array()) { - Requirement req(req_id, 0); - res.push_back(req); + auto resolved_module_id = resolved_req.at("module_id"); + auto resolved_impl_id = resolved_req.at("implementation_id"); + const auto mapping = this->get_3_tier_model_mapping(resolved_module_id, resolved_impl_id); + Requirement req(req_id, 0, mapping); + requirement_connections.push_back({req, resolved_module_id}); } else { for (int i = 0; i < resolved_req.size(); i++) { - Requirement req(req_id, i); - res.push_back(req); + auto resolved_module_id = resolved_req.at(i).at("module_id"); + auto resolved_impl_id = resolved_req.at(i).at("implementation_id"); + const auto mapping = this->get_3_tier_model_mapping(resolved_module_id, resolved_impl_id); + Requirement req(req_id, i, mapping); + requirement_connections.push_back({req, resolved_module_id}); } } + res[req_id] = requirement_connections; } return res; @@ -823,7 +831,8 @@ std::optional Config::get_3_tier_model_mapping(const std::string& modul } auto& mapping = module_tier_mappings.value(); if (mapping.implementations.find(impl_id) == mapping.implementations.end()) { - return std::nullopt; + // if no specific implementation mapping is given, use the module mapping + return mapping.module; } return mapping.implementations.at(impl_id); } diff --git a/lib/everest.cpp b/lib/everest.cpp index 8d870dc6..650545e8 100644 --- a/lib/everest.cpp +++ b/lib/everest.cpp @@ -158,30 +158,33 @@ Everest::Everest(std::string module_id_, const Config& config_, bool validate_da } // setup error_databases, error_managers and error_state_monitors for all requirements - for (const Requirement& req : config.get_requirements(module_id)) { - // setup shared database - std::shared_ptr error_database = std::make_shared(); - - // setup error manager - std::string interface_name = this->module_manifest.at("requires").at(req.id).at("interface"); - json interface_def = this->config.get_interface_definition(interface_name); - std::list allowed_error_types; - for (const auto& error_namespace_it : interface_def["errors"].items()) { - for (const auto& error_name_it : error_namespace_it.value().items()) { - allowed_error_types.push_back(error_namespace_it.key() + "/" + error_name_it.key()); + for (const auto& requirement_connections : config.get_requirement_connections(module_id)) { + for (const RequirementConnection& req_con : requirement_connections.second) { + auto& req = req_con.requirement; + // setup shared database + std::shared_ptr error_database = std::make_shared(); + + // setup error manager + std::string interface_name = this->module_manifest.at("requires").at(req.id).at("interface"); + json interface_def = this->config.get_interface_definition(interface_name); + std::list allowed_error_types; + for (const auto& error_namespace_it : interface_def["errors"].items()) { + for (const auto& error_name_it : error_namespace_it.value().items()) { + allowed_error_types.push_back(error_namespace_it.key() + "/" + error_name_it.key()); + } } + error::ErrorManagerReq::SubscribeErrorFunc subscribe_error_func = + [this, req](const error::ErrorType& type, const error::ErrorCallback& callback, + const error::ErrorCallback& clear_callback) { + this->subscribe_error(req, type, callback, clear_callback); + }; + this->req_error_managers[req] = std::make_shared( + std::make_shared(this->config.get_error_map()), error_database, allowed_error_types, + subscribe_error_func); + + // setup error state monitor + this->req_error_state_monitors[req] = std::make_shared(error_database); } - error::ErrorManagerReq::SubscribeErrorFunc subscribe_error_func = - [this, req](const error::ErrorType& type, const error::ErrorCallback& callback, - const error::ErrorCallback& clear_callback) { - this->subscribe_error(req, type, callback, clear_callback); - }; - this->req_error_managers[req] = std::make_shared( - std::make_shared(this->config.get_error_map()), error_database, allowed_error_types, - subscribe_error_func); - - // setup error state monitor - this->req_error_state_monitors[req] = std::make_shared(error_database); } // register handler for global ready signal @@ -252,6 +255,22 @@ void Everest::register_on_ready_handler(const std::function& handler) { this->on_ready = std::make_unique>(handler); } +std::optional Everest::get_3_tier_model_mapping() { + return this->module_tier_mappings; +} + +std::optional Everest::get_3_tier_model_mapping(const std::string& impl_id) { + if (not this->module_tier_mappings.has_value()) { + return std::nullopt; + } + auto& mapping = this->module_tier_mappings.value(); + if (mapping.implementations.find(impl_id) == mapping.implementations.end()) { + // if no specific implementation mapping is given, use the module mapping + return mapping.module; + } + return mapping.implementations.at(impl_id); +} + void Everest::check_code() { BOOST_LOG_FUNCTION(); diff --git a/lib/runtime.cpp b/lib/runtime.cpp index ee6ccbff..be2069f8 100644 --- a/lib/runtime.cpp +++ b/lib/runtime.cpp @@ -383,10 +383,12 @@ RuntimeSettings::RuntimeSettings(const std::string& prefix_, const std::string& } } -ModuleCallbacks::ModuleCallbacks(const std::function& register_module_adapter, - const std::function(const json& connections)>& everest_register, - const std::function& init, - const std::function& ready) : +ModuleCallbacks::ModuleCallbacks( + const std::function& register_module_adapter, + const std::function( + const std::map>& requirement_connections)>& everest_register, + const std::function& init, + const std::function& ready) : register_module_adapter(register_module_adapter), everest_register(everest_register), init(init), ready(ready) { } @@ -495,11 +497,18 @@ int ModuleLoader::initialize() { return everest.telemetry_publish(category, subcategory, type, telemetry); }; + module_adapter.get_mapping = [&everest]() { + return everest.get_3_tier_model_mapping(); + }; + + module_adapter.get_impl_mapping = [&everest](const std::string& impl_id) { + return everest.get_3_tier_model_mapping(impl_id); + }; + this->callbacks.register_module_adapter(module_adapter); // FIXME (aw): would be nice to move this config related thing toward the module_init function - std::vector cmds = - this->callbacks.everest_register(config.get_main_config()[this->module_id]["connections"]); + std::vector cmds = this->callbacks.everest_register(config.get_requirement_connections(this->module_id)); for (auto const& command : cmds) { everest.provide_cmd(command); diff --git a/lib/types.cpp b/lib/types.cpp index a764eded..cb6b349a 100644 --- a/lib/types.cpp +++ b/lib/types.cpp @@ -13,7 +13,8 @@ TypedHandler::TypedHandler(HandlerType type_, std::shared_ptr handler_) TypedHandler("", "", type_, handler_) { } -Requirement::Requirement(const std::string& requirement_id_, size_t index_) : id(requirement_id_), index(index_) { +Requirement::Requirement(const std::string& requirement_id_, size_t index_, std::optional mapping) : + id(requirement_id_), index(index_), mapping(mapping) { } bool Requirement::operator<(const Requirement& rhs) const { From 0105d03ddbcf272e62484b43131b718ba6c36959 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Sun, 6 Oct 2024 09:23:34 +0200 Subject: [PATCH 02/22] Add stream operators for (optional) Mapping for easier debugging Signed-off-by: Kai-Uwe Hermann --- include/utils/types.hpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/include/utils/types.hpp b/include/utils/types.hpp index dbc34b90..83e354ef 100644 --- a/include/utils/types.hpp +++ b/include/utils/types.hpp @@ -96,6 +96,30 @@ struct Mapping { } }; +/// \brief Writes the string representation of the given Mapping \p mapping to the given output stream \p os +/// \returns an output stream with the Mapping written to +inline std::ostream& operator<<(std::ostream& os, const Mapping& mapping) { + os << "Mapping(evse: " << mapping.evse; + if (mapping.connector.has_value()) { + os << ", connector: " << mapping.connector.value(); + } + os << ")"; + + return os; +} + +/// \brief Writes the string representation of the given Mapping \p mapping to the given output stream \p os +/// \returns an output stream with the Mapping written to +inline std::ostream& operator<<(std::ostream& os, const std::optional& mapping) { + if (mapping.has_value()) { + os << mapping.value(); + } else { + os << "Mapping(charging station)"; + } + + return os; +} + /// \brief A 3 tier mapping for a module and its individual implementations struct ModuleTierMappings { std::optional module; ///< Mapping of the whole module to an EVSE id and optional Connector id. If this is From b67b7b17619de3824f83dbae02e85aed8da2311f Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Sun, 6 Oct 2024 09:58:35 +0200 Subject: [PATCH 03/22] Add module mapping to module info Signed-off-by: Kai-Uwe Hermann --- include/utils/types.hpp | 41 +++++++++++++++++++++-------------------- lib/runtime.cpp | 4 ++++ 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/include/utils/types.hpp b/include/utils/types.hpp index 83e354ef..ca2afc1c 100644 --- a/include/utils/types.hpp +++ b/include/utils/types.hpp @@ -64,26 +64,6 @@ enum class QOS { QOS2 ///< Exactly once delivery }; -struct ModuleInfo { - struct Paths { - std::filesystem::path etc; - std::filesystem::path libexec; - std::filesystem::path share; - }; - - std::string name; - std::vector authors; - std::string license; - std::string id; - Paths paths; - bool telemetry_enabled; - bool global_errors_enabled; -}; - -struct TelemetryConfig { - int id; -}; - /// \brief A Mapping that can be used to map a module or implementation to a specific EVSE or optionally to a Connector struct Mapping { int evse; ///< The EVSE id @@ -128,6 +108,27 @@ struct ModuleTierMappings { implementations; ///< Mappings for the individual implementations of the module }; +struct ModuleInfo { + struct Paths { + std::filesystem::path etc; + std::filesystem::path libexec; + std::filesystem::path share; + }; + + std::string name; + std::vector authors; + std::string license; + std::string id; + Paths paths; + bool telemetry_enabled; + bool global_errors_enabled; + std::optional mapping; +}; + +struct TelemetryConfig { + int id; +}; + struct Requirement { Requirement() = default; Requirement(const std::string& requirement_id_, size_t index_, std::optional mapping = std::nullopt); diff --git a/lib/runtime.cpp b/lib/runtime.cpp index be2069f8..b59573f6 100644 --- a/lib/runtime.cpp +++ b/lib/runtime.cpp @@ -518,6 +518,10 @@ int ModuleLoader::initialize() { auto module_info = config.get_module_info(this->module_id); populate_module_info_path_from_runtime_settings(module_info, rs); module_info.telemetry_enabled = everest.is_telemetry_enabled(); + auto module_mappings = everest.get_3_tier_model_mapping(); + if (module_mappings.has_value()) { + module_info.mapping = module_mappings.value().module; + } this->callbacks.init(module_configs, module_info); From 9dd6f7f7d464d158b207a6a245a7a30d089103a8 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Sun, 6 Oct 2024 10:01:19 +0200 Subject: [PATCH 04/22] Bump version to 0.18 Signed-off-by: Kai-Uwe Hermann --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 95681497..56925f5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.14) project(everest-framework - VERSION 0.17.2 + VERSION 0.18.0 DESCRIPTION "The open operating system for e-mobility charging stations" LANGUAGES CXX C ) From 557932c30108ce09b3670f01cb49c5d5092b681f Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Tue, 15 Oct 2024 17:24:07 +0200 Subject: [PATCH 05/22] clang-format Signed-off-by: Kai-Uwe Hermann --- include/framework/runtime.hpp | 6 ++++-- lib/config.cpp | 3 ++- lib/everest.cpp | 4 ++-- lib/runtime.cpp | 4 +--- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/framework/runtime.hpp b/include/framework/runtime.hpp index e3ff65d6..628f3df9 100644 --- a/include/framework/runtime.hpp +++ b/include/framework/runtime.hpp @@ -143,7 +143,9 @@ struct ModuleCallbacks { ModuleCallbacks() = default; ModuleCallbacks(const std::function& register_module_adapter, - const std::function(const std::map>& requirement_connections)>& everest_register, + const std::function( + const std::map>& requirement_connections)>& + everest_register, const std::function& init, const std::function& ready); }; @@ -166,7 +168,7 @@ class ModuleLoader { public: explicit ModuleLoader(int argc, char* argv[], ModuleCallbacks callbacks) : - ModuleLoader(argc, argv, callbacks, {"undefined project", "undefined version", "undefined git version"}) {}; + ModuleLoader(argc, argv, callbacks, {"undefined project", "undefined version", "undefined git version"}){}; explicit ModuleLoader(int argc, char* argv[], ModuleCallbacks callbacks, const VersionInformation version_information); diff --git a/lib/config.cpp b/lib/config.cpp index 434425d6..39de0062 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -705,7 +705,8 @@ json Config::resolve_requirement(const std::string& module_id, const std::string return module_config["connections"][requirement_id]; } -std::map> Config::get_requirement_connections(const std::string& module_id) { +std::map> +Config::get_requirement_connections(const std::string& module_id) { BOOST_LOG_FUNCTION(); std::map> res; diff --git a/lib/everest.cpp b/lib/everest.cpp index 650545e8..b9587d40 100644 --- a/lib/everest.cpp +++ b/lib/everest.cpp @@ -179,8 +179,8 @@ Everest::Everest(std::string module_id_, const Config& config_, bool validate_da this->subscribe_error(req, type, callback, clear_callback); }; this->req_error_managers[req] = std::make_shared( - std::make_shared(this->config.get_error_map()), error_database, allowed_error_types, - subscribe_error_func); + std::make_shared(this->config.get_error_map()), error_database, + allowed_error_types, subscribe_error_func); // setup error state monitor this->req_error_state_monitors[req] = std::make_shared(error_database); diff --git a/lib/runtime.cpp b/lib/runtime.cpp index b59573f6..ce3a1f8e 100644 --- a/lib/runtime.cpp +++ b/lib/runtime.cpp @@ -497,9 +497,7 @@ int ModuleLoader::initialize() { return everest.telemetry_publish(category, subcategory, type, telemetry); }; - module_adapter.get_mapping = [&everest]() { - return everest.get_3_tier_model_mapping(); - }; + module_adapter.get_mapping = [&everest]() { return everest.get_3_tier_model_mapping(); }; module_adapter.get_impl_mapping = [&everest](const std::string& impl_id) { return everest.get_3_tier_model_mapping(impl_id); From 9edf536e09cde364c296be605603d3202a4758f8 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 16 Oct 2024 18:24:25 +0200 Subject: [PATCH 06/22] Rename RequirementConnection to Fulfillment Signed-off-by: Kai-Uwe Hermann --- everestpy/src/everest/misc.hpp | 7 +------ include/framework/runtime.hpp | 4 ++-- include/utils/config.hpp | 4 ++-- include/utils/types.hpp | 6 ++++-- lib/config.cpp | 14 +++++++------- lib/everest.cpp | 6 +++--- lib/runtime.cpp | 4 ++-- 7 files changed, 21 insertions(+), 24 deletions(-) diff --git a/everestpy/src/everest/misc.hpp b/everestpy/src/everest/misc.hpp index aad3d2d7..366505b2 100644 --- a/everestpy/src/everest/misc.hpp +++ b/everestpy/src/everest/misc.hpp @@ -6,6 +6,7 @@ #include #include +#include class RuntimeSession { public: @@ -28,12 +29,6 @@ class RuntimeSession { static std::unique_ptr create_config_instance(std::shared_ptr rs); }; -struct Fulfillment { - std::string module_id; - std::string implementation_id; - Requirement requirement; -}; - struct Interface { std::vector variables; std::vector commands; diff --git a/include/framework/runtime.hpp b/include/framework/runtime.hpp index 628f3df9..762d7627 100644 --- a/include/framework/runtime.hpp +++ b/include/framework/runtime.hpp @@ -135,7 +135,7 @@ void populate_module_info_path_from_runtime_settings(ModuleInfo&, std::shared_pt struct ModuleCallbacks { std::function register_module_adapter; std::function( - const std::map>& requirement_connections)> + const std::map>& fulfillments)> everest_register; std::function init; std::function ready; @@ -144,7 +144,7 @@ struct ModuleCallbacks { ModuleCallbacks(const std::function& register_module_adapter, const std::function( - const std::map>& requirement_connections)>& + const std::map>& fulfillments)>& everest_register, const std::function& init, const std::function& ready); diff --git a/include/utils/config.hpp b/include/utils/config.hpp index 61293881..deaa99e8 100644 --- a/include/utils/config.hpp +++ b/include/utils/config.hpp @@ -147,9 +147,9 @@ class Config { json resolve_requirement(const std::string& module_id, const std::string& requirement_id) const; /// - /// \returns a map of RequirementConnections for \p module_id + /// \returns a map of Fulfillments for \p module_id /// - std::map> get_requirement_connections(const std::string& module_id); + std::map> get_fulfillments(const std::string& module_id); /// /// \brief checks if the config contains the given \p module_id diff --git a/include/utils/types.hpp b/include/utils/types.hpp index ca2afc1c..1f9a814c 100644 --- a/include/utils/types.hpp +++ b/include/utils/types.hpp @@ -138,9 +138,11 @@ struct Requirement { std::optional mapping; }; -struct RequirementConnection { +/// \brief Describes a how a requirement is fulfilled by a connection to another module and its implementation +struct Fulfillment { + std::string module_id; + std::string implementation_id; Requirement requirement; - std::string requirement_module_id; }; struct ImplementationIdentifier { diff --git a/lib/config.cpp b/lib/config.cpp index 39de0062..9b121994 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -705,32 +705,32 @@ json Config::resolve_requirement(const std::string& module_id, const std::string return module_config["connections"][requirement_id]; } -std::map> -Config::get_requirement_connections(const std::string& module_id) { +std::map> +Config::get_fulfillments(const std::string& module_id) { BOOST_LOG_FUNCTION(); - std::map> res; + std::map> res; std::string module_name = get_module_name(module_id); for (const std::string& req_id : Config::keys(this->manifests.at(module_name).at("requires"))) { - std::vector requirement_connections; + std::vector fulfillments; json resolved_req = this->resolve_requirement(module_id, req_id); if (!resolved_req.is_array()) { auto resolved_module_id = resolved_req.at("module_id"); auto resolved_impl_id = resolved_req.at("implementation_id"); const auto mapping = this->get_3_tier_model_mapping(resolved_module_id, resolved_impl_id); Requirement req(req_id, 0, mapping); - requirement_connections.push_back({req, resolved_module_id}); + fulfillments.push_back({resolved_module_id, resolved_impl_id, req}); } else { for (int i = 0; i < resolved_req.size(); i++) { auto resolved_module_id = resolved_req.at(i).at("module_id"); auto resolved_impl_id = resolved_req.at(i).at("implementation_id"); const auto mapping = this->get_3_tier_model_mapping(resolved_module_id, resolved_impl_id); Requirement req(req_id, i, mapping); - requirement_connections.push_back({req, resolved_module_id}); + fulfillments.push_back({resolved_module_id, resolved_impl_id, req}); } } - res[req_id] = requirement_connections; + res[req_id] = fulfillments; } return res; diff --git a/lib/everest.cpp b/lib/everest.cpp index b9587d40..ac021bde 100644 --- a/lib/everest.cpp +++ b/lib/everest.cpp @@ -158,9 +158,9 @@ Everest::Everest(std::string module_id_, const Config& config_, bool validate_da } // setup error_databases, error_managers and error_state_monitors for all requirements - for (const auto& requirement_connections : config.get_requirement_connections(module_id)) { - for (const RequirementConnection& req_con : requirement_connections.second) { - auto& req = req_con.requirement; + for (const auto& fulfillments : config.get_fulfillments(module_id)) { + for (const Fulfillment& fulfillment : fulfillments.second) { + auto& req = fulfillment.requirement; // setup shared database std::shared_ptr error_database = std::make_shared(); diff --git a/lib/runtime.cpp b/lib/runtime.cpp index ce3a1f8e..4ae3c37f 100644 --- a/lib/runtime.cpp +++ b/lib/runtime.cpp @@ -386,7 +386,7 @@ RuntimeSettings::RuntimeSettings(const std::string& prefix_, const std::string& ModuleCallbacks::ModuleCallbacks( const std::function& register_module_adapter, const std::function( - const std::map>& requirement_connections)>& everest_register, + const std::map>& fulfillments)>& everest_register, const std::function& init, const std::function& ready) : register_module_adapter(register_module_adapter), everest_register(everest_register), init(init), ready(ready) { @@ -506,7 +506,7 @@ int ModuleLoader::initialize() { this->callbacks.register_module_adapter(module_adapter); // FIXME (aw): would be nice to move this config related thing toward the module_init function - std::vector cmds = this->callbacks.everest_register(config.get_requirement_connections(this->module_id)); + std::vector cmds = this->callbacks.everest_register(config.get_fulfillments(this->module_id)); for (auto const& command : cmds) { everest.provide_cmd(command); From e90e60f2d3ac21b316aab433d7751b41259c4fbc Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Wed, 16 Oct 2024 18:32:21 +0200 Subject: [PATCH 07/22] clang-format Signed-off-by: Kai-Uwe Hermann --- include/framework/runtime.hpp | 15 +++++++-------- lib/config.cpp | 3 +-- lib/runtime.cpp | 4 ++-- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/include/framework/runtime.hpp b/include/framework/runtime.hpp index 762d7627..fe6d6483 100644 --- a/include/framework/runtime.hpp +++ b/include/framework/runtime.hpp @@ -134,20 +134,19 @@ void populate_module_info_path_from_runtime_settings(ModuleInfo&, std::shared_pt struct ModuleCallbacks { std::function register_module_adapter; - std::function( - const std::map>& fulfillments)> + std::function(const std::map>& fulfillments)> everest_register; std::function init; std::function ready; ModuleCallbacks() = default; - ModuleCallbacks(const std::function& register_module_adapter, - const std::function( - const std::map>& fulfillments)>& - everest_register, - const std::function& init, - const std::function& ready); + ModuleCallbacks( + const std::function& register_module_adapter, + const std::function(const std::map>& fulfillments)>& + everest_register, + const std::function& init, + const std::function& ready); }; struct VersionInformation { diff --git a/lib/config.cpp b/lib/config.cpp index 9b121994..a20b1772 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -705,8 +705,7 @@ json Config::resolve_requirement(const std::string& module_id, const std::string return module_config["connections"][requirement_id]; } -std::map> -Config::get_fulfillments(const std::string& module_id) { +std::map> Config::get_fulfillments(const std::string& module_id) { BOOST_LOG_FUNCTION(); std::map> res; diff --git a/lib/runtime.cpp b/lib/runtime.cpp index 4ae3c37f..bc0653b7 100644 --- a/lib/runtime.cpp +++ b/lib/runtime.cpp @@ -385,8 +385,8 @@ RuntimeSettings::RuntimeSettings(const std::string& prefix_, const std::string& ModuleCallbacks::ModuleCallbacks( const std::function& register_module_adapter, - const std::function( - const std::map>& fulfillments)>& everest_register, + const std::function(const std::map>& fulfillments)>& + everest_register, const std::function& init, const std::function& ready) : register_module_adapter(register_module_adapter), everest_register(everest_register), init(init), ready(ready) { From 7d0b0e4ca6fca2ca7a8bf3654dba095652ed7033 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Thu, 17 Oct 2024 17:59:42 +0200 Subject: [PATCH 08/22] Remove get_imple_mapping from ModuleAdapter Functionality now provided via a free helper function with the same name Signed-off-by: Kai-Uwe Hermann --- include/framework/ModuleAdapter.hpp | 2 -- include/framework/everest.hpp | 12 +++++++----- lib/everest.cpp | 25 +++++++++++++------------ lib/runtime.cpp | 4 ---- 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/include/framework/ModuleAdapter.hpp b/include/framework/ModuleAdapter.hpp index d4c45484..e925a799 100644 --- a/include/framework/ModuleAdapter.hpp +++ b/include/framework/ModuleAdapter.hpp @@ -93,7 +93,6 @@ struct ModuleAdapter { using TelemetryPublishFunc = std::function; using GetMappingFunc = std::function()>; - using GetImplMappingFunc = std::function(const std::string&)>; CallFunc call; PublishFunc publish; @@ -110,7 +109,6 @@ struct ModuleAdapter { std::vector registered_commands; TelemetryPublishFunc telemetry_publish; GetMappingFunc get_mapping; - GetImplMappingFunc get_impl_mapping; void check_complete() { // FIXME (aw): I should throw if some of my handlers are not set diff --git a/include/framework/everest.hpp b/include/framework/everest.hpp index 98740a3e..d9af9fa1 100644 --- a/include/framework/everest.hpp +++ b/include/framework/everest.hpp @@ -147,11 +147,6 @@ class Everest { /// std::optional get_3_tier_model_mapping(); - /// - /// \returns the 3 tier model mapping for the given \p impl_id - /// - std::optional get_3_tier_model_mapping(const std::string& impl_id); - /// /// \brief Chccks if all commands of a module that are listed in its manifest are available /// @@ -249,6 +244,13 @@ class Everest { /// void subscribe_global_all_errors(const error::ErrorCallback& callback, const error::ErrorCallback& clear_callback); }; + +/// +/// \returns the 3 tier model mapping from a \p module_tier_mapping for the given \p impl_id +/// +std::optional get_impl_mapping(std::optional module_tier_mappings, + const std::string& impl_id); + } // namespace Everest #endif // FRAMEWORK_EVEREST_HPP diff --git a/lib/everest.cpp b/lib/everest.cpp index ac021bde..3861b0d6 100644 --- a/lib/everest.cpp +++ b/lib/everest.cpp @@ -259,18 +259,6 @@ std::optional Everest::get_3_tier_model_mapping() { return this->module_tier_mappings; } -std::optional Everest::get_3_tier_model_mapping(const std::string& impl_id) { - if (not this->module_tier_mappings.has_value()) { - return std::nullopt; - } - auto& mapping = this->module_tier_mappings.value(); - if (mapping.implementations.find(impl_id) == mapping.implementations.end()) { - // if no specific implementation mapping is given, use the module mapping - return mapping.module; - } - return mapping.implementations.at(impl_id); -} - void Everest::check_code() { BOOST_LOG_FUNCTION(); @@ -1095,4 +1083,17 @@ bool Everest::check_arg(ArgumentType arg_types, json manifest_arg) { } return true; } + +std::optional get_impl_mapping(std::optional module_tier_mappings, + const std::string& impl_id) { + if (not module_tier_mappings.has_value()) { + return std::nullopt; + } + auto& mapping = module_tier_mappings.value(); + if (mapping.implementations.find(impl_id) == mapping.implementations.end()) { + // if no specific implementation mapping is given, use the module mapping + return mapping.module; + } + return mapping.implementations.at(impl_id); +} } // namespace Everest diff --git a/lib/runtime.cpp b/lib/runtime.cpp index bc0653b7..12fd470f 100644 --- a/lib/runtime.cpp +++ b/lib/runtime.cpp @@ -499,10 +499,6 @@ int ModuleLoader::initialize() { module_adapter.get_mapping = [&everest]() { return everest.get_3_tier_model_mapping(); }; - module_adapter.get_impl_mapping = [&everest](const std::string& impl_id) { - return everest.get_3_tier_model_mapping(impl_id); - }; - this->callbacks.register_module_adapter(module_adapter); // FIXME (aw): would be nice to move this config related thing toward the module_init function From acac5bd303da17e0cc55c9e636a55a926ce20cea Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Thu, 17 Oct 2024 18:01:25 +0200 Subject: [PATCH 09/22] Move mapping member from Requirement to Fulfilment re-introduce get_requirements function Signed-off-by: Kai-Uwe Hermann --- include/utils/config.hpp | 8 ++++++- include/utils/types.hpp | 4 ++-- lib/config.cpp | 30 +++++++++++++++++++++---- lib/everest.cpp | 47 +++++++++++++++++++--------------------- lib/types.cpp | 4 ++-- 5 files changed, 59 insertions(+), 34 deletions(-) diff --git a/include/utils/config.hpp b/include/utils/config.hpp index deaa99e8..4d6f7b4d 100644 --- a/include/utils/config.hpp +++ b/include/utils/config.hpp @@ -147,8 +147,14 @@ class Config { json resolve_requirement(const std::string& module_id, const std::string& requirement_id) const; /// - /// \returns a map of Fulfillments for \p module_id + /// \returns a list of Requirements for \p module_id + /// + std::list get_requirements(const std::string& module_id) const; + /// + /// \brief A Fulfillment is a combination of a Requirement and the module and implementation ids where this is + /// implemented + /// \returns a map of Fulfillments for \p module_id std::map> get_fulfillments(const std::string& module_id); /// diff --git a/include/utils/types.hpp b/include/utils/types.hpp index 1f9a814c..11116f44 100644 --- a/include/utils/types.hpp +++ b/include/utils/types.hpp @@ -131,11 +131,10 @@ struct TelemetryConfig { struct Requirement { Requirement() = default; - Requirement(const std::string& requirement_id_, size_t index_, std::optional mapping = std::nullopt); + Requirement(const std::string& requirement_id_, size_t index_); bool operator<(const Requirement& rhs) const; std::string id; size_t index = 0; - std::optional mapping; }; /// \brief Describes a how a requirement is fulfilled by a connection to another module and its implementation @@ -143,6 +142,7 @@ struct Fulfillment { std::string module_id; std::string implementation_id; Requirement requirement; + std::optional mapping; }; struct ImplementationIdentifier { diff --git a/lib/config.cpp b/lib/config.cpp index a20b1772..da38f5dd 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -705,6 +705,28 @@ json Config::resolve_requirement(const std::string& module_id, const std::string return module_config["connections"][requirement_id]; } +std::list Config::get_requirements(const std::string& module_id) const { + BOOST_LOG_FUNCTION(); + + std::list res; + + std::string module_name = get_module_name(module_id); + for (const std::string& req_id : Config::keys(this->manifests.at(module_name).at("requires"))) { + json resolved_req = this->resolve_requirement(module_id, req_id); + if (!resolved_req.is_array()) { + Requirement req(req_id, 0); + res.push_back(req); + } else { + for (int i = 0; i < resolved_req.size(); i++) { + Requirement req(req_id, i); + res.push_back(req); + } + } + } + + return res; +} + std::map> Config::get_fulfillments(const std::string& module_id) { BOOST_LOG_FUNCTION(); @@ -718,15 +740,15 @@ std::map> Config::get_fulfillments(const s auto resolved_module_id = resolved_req.at("module_id"); auto resolved_impl_id = resolved_req.at("implementation_id"); const auto mapping = this->get_3_tier_model_mapping(resolved_module_id, resolved_impl_id); - Requirement req(req_id, 0, mapping); - fulfillments.push_back({resolved_module_id, resolved_impl_id, req}); + Requirement req(req_id, 0); + fulfillments.push_back({resolved_module_id, resolved_impl_id, req, mapping}); } else { for (int i = 0; i < resolved_req.size(); i++) { auto resolved_module_id = resolved_req.at(i).at("module_id"); auto resolved_impl_id = resolved_req.at(i).at("implementation_id"); const auto mapping = this->get_3_tier_model_mapping(resolved_module_id, resolved_impl_id); - Requirement req(req_id, i, mapping); - fulfillments.push_back({resolved_module_id, resolved_impl_id, req}); + Requirement req(req_id, i); + fulfillments.push_back({resolved_module_id, resolved_impl_id, req, mapping}); } } res[req_id] = fulfillments; diff --git a/lib/everest.cpp b/lib/everest.cpp index 3861b0d6..30b16816 100644 --- a/lib/everest.cpp +++ b/lib/everest.cpp @@ -158,33 +158,30 @@ Everest::Everest(std::string module_id_, const Config& config_, bool validate_da } // setup error_databases, error_managers and error_state_monitors for all requirements - for (const auto& fulfillments : config.get_fulfillments(module_id)) { - for (const Fulfillment& fulfillment : fulfillments.second) { - auto& req = fulfillment.requirement; - // setup shared database - std::shared_ptr error_database = std::make_shared(); - - // setup error manager - std::string interface_name = this->module_manifest.at("requires").at(req.id).at("interface"); - json interface_def = this->config.get_interface_definition(interface_name); - std::list allowed_error_types; - for (const auto& error_namespace_it : interface_def["errors"].items()) { - for (const auto& error_name_it : error_namespace_it.value().items()) { - allowed_error_types.push_back(error_namespace_it.key() + "/" + error_name_it.key()); - } + for (const Requirement& req : config.get_requirements(module_id)) { + // setup shared database + std::shared_ptr error_database = std::make_shared(); + + // setup error manager + std::string interface_name = this->module_manifest.at("requires").at(req.id).at("interface"); + json interface_def = this->config.get_interface_definition(interface_name); + std::list allowed_error_types; + for (const auto& error_namespace_it : interface_def["errors"].items()) { + for (const auto& error_name_it : error_namespace_it.value().items()) { + allowed_error_types.push_back(error_namespace_it.key() + "/" + error_name_it.key()); } - error::ErrorManagerReq::SubscribeErrorFunc subscribe_error_func = - [this, req](const error::ErrorType& type, const error::ErrorCallback& callback, - const error::ErrorCallback& clear_callback) { - this->subscribe_error(req, type, callback, clear_callback); - }; - this->req_error_managers[req] = std::make_shared( - std::make_shared(this->config.get_error_map()), error_database, - allowed_error_types, subscribe_error_func); - - // setup error state monitor - this->req_error_state_monitors[req] = std::make_shared(error_database); } + error::ErrorManagerReq::SubscribeErrorFunc subscribe_error_func = + [this, req](const error::ErrorType& type, const error::ErrorCallback& callback, + const error::ErrorCallback& clear_callback) { + this->subscribe_error(req, type, callback, clear_callback); + }; + this->req_error_managers[req] = std::make_shared( + std::make_shared(this->config.get_error_map()), error_database, allowed_error_types, + subscribe_error_func); + + // setup error state monitor + this->req_error_state_monitors[req] = std::make_shared(error_database); } // register handler for global ready signal diff --git a/lib/types.cpp b/lib/types.cpp index cb6b349a..7a3f71ad 100644 --- a/lib/types.cpp +++ b/lib/types.cpp @@ -13,8 +13,8 @@ TypedHandler::TypedHandler(HandlerType type_, std::shared_ptr handler_) TypedHandler("", "", type_, handler_) { } -Requirement::Requirement(const std::string& requirement_id_, size_t index_, std::optional mapping) : - id(requirement_id_), index(index_), mapping(mapping) { +Requirement::Requirement(const std::string& requirement_id_, size_t index_) : + id(requirement_id_), index(index_) { } bool Requirement::operator<(const Requirement& rhs) const { From 9877ce6b6b64c763c8ef5bc226e53243c8099e76 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Thu, 17 Oct 2024 18:13:24 +0200 Subject: [PATCH 10/22] Rename function so it doesn't share a name with another one returning a different type Signed-off-by: Kai-Uwe Hermann --- include/utils/config.hpp | 2 +- lib/config.cpp | 4 ++-- lib/everest.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/utils/config.hpp b/include/utils/config.hpp index 4d6f7b4d..d1014deb 100644 --- a/include/utils/config.hpp +++ b/include/utils/config.hpp @@ -204,7 +204,7 @@ class Config { // /// \returns the 3 tier model mappings for the given \p module_id - std::optional get_3_tier_model_mappings(const std::string& module_id); + std::optional get_module_3_tier_model_mappings(const std::string& module_id); // /// \returns the 3 tier model mapping for the given \p module_id and \p impl_id diff --git a/lib/config.cpp b/lib/config.cpp index da38f5dd..36b408da 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -839,7 +839,7 @@ std::unordered_map Config::get_3_tier_model_map return this->tier_mappings; } -std::optional Config::get_3_tier_model_mappings(const std::string& module_id) { +std::optional Config::get_module_3_tier_model_mappings(const std::string& module_id) { if (this->tier_mappings.find(module_id) == this->tier_mappings.end()) { return std::nullopt; } @@ -847,7 +847,7 @@ std::optional Config::get_3_tier_model_mappings(const std::s } std::optional Config::get_3_tier_model_mapping(const std::string& module_id, const std::string& impl_id) { - auto module_tier_mappings = this->get_3_tier_model_mappings(module_id); + auto module_tier_mappings = this->get_module_3_tier_model_mappings(module_id); if (not module_tier_mappings.has_value()) { return std::nullopt; } diff --git a/lib/everest.cpp b/lib/everest.cpp index 30b16816..92be9b3e 100644 --- a/lib/everest.cpp +++ b/lib/everest.cpp @@ -81,7 +81,7 @@ Everest::Everest(std::string module_id_, const Config& config_, bool validate_da this->global_error_state_monitor = nullptr; } - this->module_tier_mappings = config.get_3_tier_model_mappings(this->module_id); + this->module_tier_mappings = config.get_module_3_tier_model_mappings(this->module_id); // setup error_managers, error_state_monitors, error_factories and error_databases for all implementations for (const std::string& impl : Config::keys(this->module_manifest.at("provides"))) { From b13012415d7f602563a6640700e5304bb122b5fd Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Thu, 17 Oct 2024 18:38:59 +0200 Subject: [PATCH 11/22] Make more mapping related variables&functions const Signed-off-by: Kai-Uwe Hermann --- include/utils/config.hpp | 6 +++--- lib/config.cpp | 38 +++++++++++++++++++------------------- lib/everest.cpp | 10 +++++----- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/include/utils/config.hpp b/include/utils/config.hpp index d1014deb..1f626a28 100644 --- a/include/utils/config.hpp +++ b/include/utils/config.hpp @@ -155,7 +155,7 @@ class Config { /// \brief A Fulfillment is a combination of a Requirement and the module and implementation ids where this is /// implemented /// \returns a map of Fulfillments for \p module_id - std::map> get_fulfillments(const std::string& module_id); + std::map> get_fulfillments(const std::string& module_id) const; /// /// \brief checks if the config contains the given \p module_id @@ -204,11 +204,11 @@ class Config { // /// \returns the 3 tier model mappings for the given \p module_id - std::optional get_module_3_tier_model_mappings(const std::string& module_id); + std::optional get_module_3_tier_model_mappings(const std::string& module_id) const; // /// \returns the 3 tier model mapping for the given \p module_id and \p impl_id - std::optional get_3_tier_model_mapping(const std::string& module_id, const std::string& impl_id); + std::optional get_3_tier_model_mapping(const std::string& module_id, const std::string& impl_id) const; /// /// \brief turns then given \p module_id into a printable identifier diff --git a/lib/config.cpp b/lib/config.cpp index 36b408da..46133b4e 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -710,9 +710,9 @@ std::list Config::get_requirements(const std::string& module_id) co std::list res; - std::string module_name = get_module_name(module_id); + const std::string module_name = get_module_name(module_id); for (const std::string& req_id : Config::keys(this->manifests.at(module_name).at("requires"))) { - json resolved_req = this->resolve_requirement(module_id, req_id); + const json resolved_req = this->resolve_requirement(module_id, req_id); if (!resolved_req.is_array()) { Requirement req(req_id, 0); res.push_back(req); @@ -727,25 +727,25 @@ std::list Config::get_requirements(const std::string& module_id) co return res; } -std::map> Config::get_fulfillments(const std::string& module_id) { +std::map> Config::get_fulfillments(const std::string& module_id) const { BOOST_LOG_FUNCTION(); std::map> res; - std::string module_name = get_module_name(module_id); + const std::string module_name = get_module_name(module_id); for (const std::string& req_id : Config::keys(this->manifests.at(module_name).at("requires"))) { std::vector fulfillments; - json resolved_req = this->resolve_requirement(module_id, req_id); + const json resolved_req = this->resolve_requirement(module_id, req_id); if (!resolved_req.is_array()) { - auto resolved_module_id = resolved_req.at("module_id"); - auto resolved_impl_id = resolved_req.at("implementation_id"); + const auto resolved_module_id = resolved_req.at("module_id"); + const auto resolved_impl_id = resolved_req.at("implementation_id"); const auto mapping = this->get_3_tier_model_mapping(resolved_module_id, resolved_impl_id); Requirement req(req_id, 0); fulfillments.push_back({resolved_module_id, resolved_impl_id, req, mapping}); } else { for (int i = 0; i < resolved_req.size(); i++) { - auto resolved_module_id = resolved_req.at(i).at("module_id"); - auto resolved_impl_id = resolved_req.at(i).at("implementation_id"); + const auto resolved_module_id = resolved_req.at(i).at("module_id"); + const auto resolved_impl_id = resolved_req.at(i).at("implementation_id"); const auto mapping = this->get_3_tier_model_mapping(resolved_module_id, resolved_impl_id); Requirement req(req_id, i); fulfillments.push_back({resolved_module_id, resolved_impl_id, req, mapping}); @@ -839,19 +839,19 @@ std::unordered_map Config::get_3_tier_model_map return this->tier_mappings; } -std::optional Config::get_module_3_tier_model_mappings(const std::string& module_id) { +std::optional Config::get_module_3_tier_model_mappings(const std::string& module_id) const { if (this->tier_mappings.find(module_id) == this->tier_mappings.end()) { return std::nullopt; } return this->tier_mappings.at(module_id); } -std::optional Config::get_3_tier_model_mapping(const std::string& module_id, const std::string& impl_id) { - auto module_tier_mappings = this->get_module_3_tier_model_mappings(module_id); +std::optional Config::get_3_tier_model_mapping(const std::string& module_id, const std::string& impl_id) const { + const auto module_tier_mappings = this->get_module_3_tier_model_mappings(module_id); if (not module_tier_mappings.has_value()) { return std::nullopt; } - auto& mapping = module_tier_mappings.value(); + const auto& mapping = module_tier_mappings.value(); if (mapping.implementations.find(impl_id) == mapping.implementations.end()) { // if no specific implementation mapping is given, use the module mapping return mapping.module; @@ -1203,11 +1203,11 @@ void Config::resolve_all_requirements() { void Config::parse_3_tier_model_mapping() { for (auto& element : this->main.items()) { const auto& module_id = element.key(); - auto impl_info = this->extract_implementation_info(module_id); - auto provides = this->manifests.at(impl_info.at("module_name")).at("provides"); + const auto impl_info = this->extract_implementation_info(module_id); + const auto provides = this->manifests.at(impl_info.at("module_name")).at("provides"); ModuleTierMappings module_tier_mappings; - auto& module_config = element.value(); + const auto& module_config = element.value(); if (module_config.contains("evse")) { auto mapping = Mapping(module_config.at("evse").get()); if (module_config.contains("connector")) { @@ -1215,12 +1215,12 @@ void Config::parse_3_tier_model_mapping() { } module_tier_mappings.module = mapping; } - auto& mapping = module_config.at("mapping"); + const auto& mapping = module_config.at("mapping"); // an empty mapping means it is mapped to the charging station and gets no specific mapping attached if (not mapping.empty()) { for (auto& tier_mapping : mapping.items()) { - auto impl_id = tier_mapping.key(); - auto tier_mapping_value = tier_mapping.value(); + const auto impl_id = tier_mapping.key(); + const auto tier_mapping_value = tier_mapping.value(); if (provides.contains(impl_id)) { if (tier_mapping_value.contains("connector")) { module_tier_mappings.implementations[impl_id] = Mapping( diff --git a/lib/everest.cpp b/lib/everest.cpp index 92be9b3e..f72545c7 100644 --- a/lib/everest.cpp +++ b/lib/everest.cpp @@ -112,14 +112,14 @@ Everest::Everest(std::string module_id_, const Config& config_, bool validate_da std::optional mapping; if (this->module_tier_mappings.has_value()) { - auto& module_tier_mapping = this->module_tier_mappings.value(); + const auto& module_tier_mapping = this->module_tier_mappings.value(); // start with the module mapping and overwrite it (partially) with the implementation mapping mapping = module_tier_mapping.module; - auto impl_mapping = config.get_3_tier_model_mapping(this->module_id, impl); + const auto impl_mapping = config.get_3_tier_model_mapping(this->module_id, impl); if (impl_mapping.has_value()) { if (mapping.has_value()) { auto& mapping_value = mapping.value(); - auto& impl_mapping_value = impl_mapping.value(); + const auto& impl_mapping_value = impl_mapping.value(); if (mapping_value.evse != impl_mapping_value.evse) { EVLOG_warning << fmt::format("Mapping value mismatch. {} ({}) evse ({}) != {} mapping evse " "({}). Setting evse={}, please fix this in the config.", @@ -132,8 +132,8 @@ Everest::Everest(std::string module_id_, const Config& config_, bool validate_da mapping_value.connector = impl_mapping_value.connector; } if (mapping_value.connector.has_value() and impl_mapping_value.connector.has_value()) { - auto& mapping_value_connector_value = mapping_value.connector.value(); - auto& impl_mapping_value_connector_value = impl_mapping_value.connector.value(); + const auto& mapping_value_connector_value = mapping_value.connector.value(); + const auto& impl_mapping_value_connector_value = impl_mapping_value.connector.value(); if (mapping_value_connector_value != impl_mapping_value_connector_value) { EVLOG_warning << fmt::format("Mapping value mismatch. {} ({}) connector ({}) != {} mapping connector " From 44baf44f4806fc2b203c17f580dc1c83d01078fd Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Thu, 17 Oct 2024 19:20:21 +0200 Subject: [PATCH 12/22] Add reworded comment Signed-off-by: Kai-Uwe Hermann --- include/utils/types.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/utils/types.hpp b/include/utils/types.hpp index 11116f44..954532b5 100644 --- a/include/utils/types.hpp +++ b/include/utils/types.hpp @@ -137,7 +137,8 @@ struct Requirement { size_t index = 0; }; -/// \brief Describes a how a requirement is fulfilled by a connection to another module and its implementation +/// \brief A Fulfillment relates a Requirement to its connected implementation, identified via its module and +/// implementation id. It additionally provides access to the Mapping associated with the Requirement. struct Fulfillment { std::string module_id; std::string implementation_id; From 501f01f06b247213ab95e51526098ebe8c4d06f2 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Thu, 17 Oct 2024 19:21:14 +0200 Subject: [PATCH 13/22] clang-format Signed-off-by: Kai-Uwe Hermann --- lib/config.cpp | 3 ++- lib/types.cpp | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/config.cpp b/lib/config.cpp index 46133b4e..5d3de276 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -846,7 +846,8 @@ std::optional Config::get_module_3_tier_model_mappings(const return this->tier_mappings.at(module_id); } -std::optional Config::get_3_tier_model_mapping(const std::string& module_id, const std::string& impl_id) const { +std::optional Config::get_3_tier_model_mapping(const std::string& module_id, + const std::string& impl_id) const { const auto module_tier_mappings = this->get_module_3_tier_model_mappings(module_id); if (not module_tier_mappings.has_value()) { return std::nullopt; diff --git a/lib/types.cpp b/lib/types.cpp index 7a3f71ad..a764eded 100644 --- a/lib/types.cpp +++ b/lib/types.cpp @@ -13,8 +13,7 @@ TypedHandler::TypedHandler(HandlerType type_, std::shared_ptr handler_) TypedHandler("", "", type_, handler_) { } -Requirement::Requirement(const std::string& requirement_id_, size_t index_) : - id(requirement_id_), index(index_) { +Requirement::Requirement(const std::string& requirement_id_, size_t index_) : id(requirement_id_), index(index_) { } bool Requirement::operator<(const Requirement& rhs) const { From 8c3fecad97dd4c2f99a5c286ed6af09bc4a2616d Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Fri, 18 Oct 2024 12:36:14 +0200 Subject: [PATCH 14/22] Add resolve_requirements that is used as a basis for refactored get_requirements and get_fulfillments Signed-off-by: Kai-Uwe Hermann --- include/utils/config.hpp | 7 +++++ lib/config.cpp | 56 ++++++++++++++++++++-------------------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/include/utils/config.hpp b/include/utils/config.hpp index 1f626a28..ca87cd66 100644 --- a/include/utils/config.hpp +++ b/include/utils/config.hpp @@ -146,6 +146,13 @@ class Config { /// \returns a json object that contains the requirement json resolve_requirement(const std::string& module_id, const std::string& requirement_id) const; + /// + /// \brief resolves all Requirements of the given \p module_id to their Fulfillments + /// + /// \returns a map indexed by Requirements + std::map resolve_requirements(const std::string& module_id) const; + + /// /// \returns a list of Requirements for \p module_id /// diff --git a/lib/config.cpp b/lib/config.cpp index 5d3de276..7d065969 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -705,25 +705,42 @@ json Config::resolve_requirement(const std::string& module_id, const std::string return module_config["connections"][requirement_id]; } -std::list Config::get_requirements(const std::string& module_id) const { - BOOST_LOG_FUNCTION(); +std::map Config::resolve_requirements(const std::string& module_id) const { + std::map requirements; - std::list res; - - const std::string module_name = get_module_name(module_id); - for (const std::string& req_id : Config::keys(this->manifests.at(module_name).at("requires"))) { + const auto module_name = get_module_name(module_id); + for (const auto& req_id : Config::keys(this->manifests.at(module_name).at("requires"))) { const json resolved_req = this->resolve_requirement(module_id, req_id); if (!resolved_req.is_array()) { + const auto resolved_module_id = resolved_req.at("module_id"); + const auto resolved_impl_id = resolved_req.at("implementation_id"); + const auto mapping = this->get_3_tier_model_mapping(resolved_module_id, resolved_impl_id); Requirement req(req_id, 0); - res.push_back(req); + requirements[req] = {resolved_module_id, resolved_impl_id, req, mapping}; } else { for (int i = 0; i < resolved_req.size(); i++) { + const auto resolved_module_id = resolved_req.at(i).at("module_id"); + const auto resolved_impl_id = resolved_req.at(i).at("implementation_id"); + const auto mapping = this->get_3_tier_model_mapping(resolved_module_id, resolved_impl_id); Requirement req(req_id, i); - res.push_back(req); + requirements[req] = {resolved_module_id, resolved_impl_id, req, mapping}; } } } + return requirements; +} + +std::list Config::get_requirements(const std::string& module_id) const { + BOOST_LOG_FUNCTION(); + + std::list res; + + for (const auto& [requirement, fulfillment] : this->resolve_requirements(module_id)) { + res.push_back(requirement); + (void)fulfillment; // fulfillment is not used here + } + return res; } @@ -732,26 +749,9 @@ std::map> Config::get_fulfillments(const s std::map> res; - const std::string module_name = get_module_name(module_id); - for (const std::string& req_id : Config::keys(this->manifests.at(module_name).at("requires"))) { - std::vector fulfillments; - const json resolved_req = this->resolve_requirement(module_id, req_id); - if (!resolved_req.is_array()) { - const auto resolved_module_id = resolved_req.at("module_id"); - const auto resolved_impl_id = resolved_req.at("implementation_id"); - const auto mapping = this->get_3_tier_model_mapping(resolved_module_id, resolved_impl_id); - Requirement req(req_id, 0); - fulfillments.push_back({resolved_module_id, resolved_impl_id, req, mapping}); - } else { - for (int i = 0; i < resolved_req.size(); i++) { - const auto resolved_module_id = resolved_req.at(i).at("module_id"); - const auto resolved_impl_id = resolved_req.at(i).at("implementation_id"); - const auto mapping = this->get_3_tier_model_mapping(resolved_module_id, resolved_impl_id); - Requirement req(req_id, i); - fulfillments.push_back({resolved_module_id, resolved_impl_id, req, mapping}); - } - } - res[req_id] = fulfillments; + const auto& resolved_requirements = this->resolve_requirements(module_id); + for (const auto& [requirement, fulfillment] : this->resolve_requirements(module_id)) { + res[requirement.id].push_back(fulfillment); } return res; From 61b9281194f78250f92725be84cfbfd17d4f5c7d Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Fri, 18 Oct 2024 15:54:16 +0200 Subject: [PATCH 15/22] Remove code that isn't used Signed-off-by: Kai-Uwe Hermann --- lib/config.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/config.cpp b/lib/config.cpp index 7d065969..10745c67 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -749,7 +749,6 @@ std::map> Config::get_fulfillments(const s std::map> res; - const auto& resolved_requirements = this->resolve_requirements(module_id); for (const auto& [requirement, fulfillment] : this->resolve_requirements(module_id)) { res[requirement.id].push_back(fulfillment); } From 5d542d3f1a594e8cc2ca2b57ade8f220354e1e90 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Mon, 21 Oct 2024 11:18:38 +0200 Subject: [PATCH 16/22] Introduce RequirementInitializer and RequirementInitialization These can be used in (generated) user code to initialize requirements with their fulfillments and optional mappings Signed-off-by: Kai-Uwe Hermann --- include/framework/runtime.hpp | 6 ++---- include/utils/config.hpp | 7 ++++++- include/utils/types.hpp | 11 ++++++++++- lib/config.cpp | 13 +++++++++++++ lib/runtime.cpp | 6 +++--- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/include/framework/runtime.hpp b/include/framework/runtime.hpp index fe6d6483..b0bb595f 100644 --- a/include/framework/runtime.hpp +++ b/include/framework/runtime.hpp @@ -134,8 +134,7 @@ void populate_module_info_path_from_runtime_settings(ModuleInfo&, std::shared_pt struct ModuleCallbacks { std::function register_module_adapter; - std::function(const std::map>& fulfillments)> - everest_register; + std::function(const RequirementInitialization& requirement_init)> everest_register; std::function init; std::function ready; @@ -143,8 +142,7 @@ struct ModuleCallbacks { ModuleCallbacks( const std::function& register_module_adapter, - const std::function(const std::map>& fulfillments)>& - everest_register, + const std::function(const RequirementInitialization& requirement_init)>& everest_register, const std::function& init, const std::function& ready); }; diff --git a/include/utils/config.hpp b/include/utils/config.hpp index ca87cd66..ffe8e3c5 100644 --- a/include/utils/config.hpp +++ b/include/utils/config.hpp @@ -152,7 +152,6 @@ class Config { /// \returns a map indexed by Requirements std::map resolve_requirements(const std::string& module_id) const; - /// /// \returns a list of Requirements for \p module_id /// @@ -164,6 +163,12 @@ class Config { /// \returns a map of Fulfillments for \p module_id std::map> get_fulfillments(const std::string& module_id) const; + /// + /// \brief A RequirementInitialization contains everything needed to initialize a requirement in user code. This + /// includes the Requirement, its Fulfillment and an optional Mapping + /// \returns a RequirementInitialization + RequirementInitialization get_requirement_initialization(const std::string& module_id) const; + /// /// \brief checks if the config contains the given \p module_id /// diff --git a/include/utils/types.hpp b/include/utils/types.hpp index 954532b5..c9c614e1 100644 --- a/include/utils/types.hpp +++ b/include/utils/types.hpp @@ -138,7 +138,7 @@ struct Requirement { }; /// \brief A Fulfillment relates a Requirement to its connected implementation, identified via its module and -/// implementation id. It additionally provides access to the Mapping associated with the Requirement. +/// implementation id. struct Fulfillment { std::string module_id; std::string implementation_id; @@ -146,6 +146,15 @@ struct Fulfillment { std::optional mapping; }; +/// \brief Contains everything that's needed to initialize a requirement in user code +struct RequirementInitializer { + Requirement requirement; + Fulfillment fulfillment; + std::optional mapping; +}; + +using RequirementInitialization = std::map>; + struct ImplementationIdentifier { ImplementationIdentifier(const std::string& module_id_, const std::string& implementation_id_, std::optional mapping_ = std::nullopt); diff --git a/lib/config.cpp b/lib/config.cpp index 10745c67..809a71d2 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -756,6 +756,19 @@ std::map> Config::get_fulfillments(const s return res; } +RequirementInitialization Config::get_requirement_initialization(const std::string& module_id) const { + BOOST_LOG_FUNCTION(); + + RequirementInitialization res; + + for (const auto& [requirement, fulfillment] : this->resolve_requirements(module_id)) { + const auto& mapping = this->get_3_tier_model_mapping(fulfillment.module_id, fulfillment.implementation_id); + res[requirement.id].push_back({requirement, fulfillment, mapping}); + } + + return res; +} + bool Config::contains(const std::string& module_id) const { BOOST_LOG_FUNCTION(); return this->main.contains(module_id); diff --git a/lib/runtime.cpp b/lib/runtime.cpp index 12fd470f..89b2dfce 100644 --- a/lib/runtime.cpp +++ b/lib/runtime.cpp @@ -385,8 +385,7 @@ RuntimeSettings::RuntimeSettings(const std::string& prefix_, const std::string& ModuleCallbacks::ModuleCallbacks( const std::function& register_module_adapter, - const std::function(const std::map>& fulfillments)>& - everest_register, + const std::function(const RequirementInitialization& requirement_init)>& everest_register, const std::function& init, const std::function& ready) : register_module_adapter(register_module_adapter), everest_register(everest_register), init(init), ready(ready) { @@ -502,7 +501,8 @@ int ModuleLoader::initialize() { this->callbacks.register_module_adapter(module_adapter); // FIXME (aw): would be nice to move this config related thing toward the module_init function - std::vector cmds = this->callbacks.everest_register(config.get_fulfillments(this->module_id)); + std::vector cmds = + this->callbacks.everest_register(config.get_requirement_initialization(this->module_id)); for (auto const& command : cmds) { everest.provide_cmd(command); From 26473f75d64105565064aa0b14434520dfff3982 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Mon, 21 Oct 2024 11:21:28 +0200 Subject: [PATCH 17/22] Remove redundant mapping from Fulfillment Signed-off-by: Kai-Uwe Hermann --- include/utils/types.hpp | 1 - lib/config.cpp | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/include/utils/types.hpp b/include/utils/types.hpp index c9c614e1..940af72f 100644 --- a/include/utils/types.hpp +++ b/include/utils/types.hpp @@ -143,7 +143,6 @@ struct Fulfillment { std::string module_id; std::string implementation_id; Requirement requirement; - std::optional mapping; }; /// \brief Contains everything that's needed to initialize a requirement in user code diff --git a/lib/config.cpp b/lib/config.cpp index 809a71d2..5d2b54f3 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -714,16 +714,14 @@ std::map Config::resolve_requirements(const std::strin if (!resolved_req.is_array()) { const auto resolved_module_id = resolved_req.at("module_id"); const auto resolved_impl_id = resolved_req.at("implementation_id"); - const auto mapping = this->get_3_tier_model_mapping(resolved_module_id, resolved_impl_id); Requirement req(req_id, 0); - requirements[req] = {resolved_module_id, resolved_impl_id, req, mapping}; + requirements[req] = {resolved_module_id, resolved_impl_id, req}; } else { for (int i = 0; i < resolved_req.size(); i++) { const auto resolved_module_id = resolved_req.at(i).at("module_id"); const auto resolved_impl_id = resolved_req.at(i).at("implementation_id"); - const auto mapping = this->get_3_tier_model_mapping(resolved_module_id, resolved_impl_id); Requirement req(req_id, i); - requirements[req] = {resolved_module_id, resolved_impl_id, req, mapping}; + requirements[req] = {resolved_module_id, resolved_impl_id, req}; } } } From 000efd55901c2871eceb3cd544d5fe05a4022ee1 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Mon, 21 Oct 2024 11:36:50 +0200 Subject: [PATCH 18/22] Turn operator< of Requirement into free function Signed-off-by: Kai-Uwe Hermann --- include/utils/types.hpp | 3 ++- lib/types.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/utils/types.hpp b/include/utils/types.hpp index 940af72f..a4ecf522 100644 --- a/include/utils/types.hpp +++ b/include/utils/types.hpp @@ -132,11 +132,12 @@ struct TelemetryConfig { struct Requirement { Requirement() = default; Requirement(const std::string& requirement_id_, size_t index_); - bool operator<(const Requirement& rhs) const; std::string id; size_t index = 0; }; +bool operator<(const Requirement& lhs, const Requirement& rhs); + /// \brief A Fulfillment relates a Requirement to its connected implementation, identified via its module and /// implementation id. struct Fulfillment { diff --git a/lib/types.cpp b/lib/types.cpp index a764eded..6916c982 100644 --- a/lib/types.cpp +++ b/lib/types.cpp @@ -16,11 +16,11 @@ TypedHandler::TypedHandler(HandlerType type_, std::shared_ptr handler_) Requirement::Requirement(const std::string& requirement_id_, size_t index_) : id(requirement_id_), index(index_) { } -bool Requirement::operator<(const Requirement& rhs) const { - if (id < rhs.id) { +bool operator<(const Requirement& lhs, const Requirement& rhs) { + if (lhs.id < rhs.id) { return true; - } else if (id == rhs.id) { - return (index < rhs.index); + } else if (lhs.id == rhs.id) { + return (lhs.index < rhs.index); } else { return false; } From cd20aab8334f43e4e86397be6147c042b745a155 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Mon, 21 Oct 2024 17:24:15 +0200 Subject: [PATCH 19/22] Remove constructors of Requirement Signed-off-by: Kai-Uwe Hermann --- include/utils/types.hpp | 2 -- lib/config.cpp | 9 +++++---- lib/types.cpp | 3 --- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/include/utils/types.hpp b/include/utils/types.hpp index a4ecf522..08f24e47 100644 --- a/include/utils/types.hpp +++ b/include/utils/types.hpp @@ -130,8 +130,6 @@ struct TelemetryConfig { }; struct Requirement { - Requirement() = default; - Requirement(const std::string& requirement_id_, size_t index_); std::string id; size_t index = 0; }; diff --git a/lib/config.cpp b/lib/config.cpp index 5d2b54f3..793dd041 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest +// Copyright Pionix GmbH and Contributors to EVerest #include +#include #include #include #include @@ -714,13 +715,13 @@ std::map Config::resolve_requirements(const std::strin if (!resolved_req.is_array()) { const auto resolved_module_id = resolved_req.at("module_id"); const auto resolved_impl_id = resolved_req.at("implementation_id"); - Requirement req(req_id, 0); + auto req = Requirement{req_id, 0}; requirements[req] = {resolved_module_id, resolved_impl_id, req}; } else { - for (int i = 0; i < resolved_req.size(); i++) { + for (std::size_t i = 0; i < resolved_req.size(); i++) { const auto resolved_module_id = resolved_req.at(i).at("module_id"); const auto resolved_impl_id = resolved_req.at(i).at("implementation_id"); - Requirement req(req_id, i); + auto req = Requirement{req_id, i}; requirements[req] = {resolved_module_id, resolved_impl_id, req}; } } diff --git a/lib/types.cpp b/lib/types.cpp index 6916c982..f4644667 100644 --- a/lib/types.cpp +++ b/lib/types.cpp @@ -13,9 +13,6 @@ TypedHandler::TypedHandler(HandlerType type_, std::shared_ptr handler_) TypedHandler("", "", type_, handler_) { } -Requirement::Requirement(const std::string& requirement_id_, size_t index_) : id(requirement_id_), index(index_) { -} - bool operator<(const Requirement& lhs, const Requirement& rhs) { if (lhs.id < rhs.id) { return true; From 6084d349f360c5cbef929d7b5882d6003c4d0b43 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Mon, 21 Oct 2024 21:59:42 +0200 Subject: [PATCH 20/22] Remove ugly void cast Signed-off-by: Kai-Uwe Hermann --- lib/config.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/config.cpp b/lib/config.cpp index 793dd041..f640b144 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -737,7 +737,6 @@ std::list Config::get_requirements(const std::string& module_id) co for (const auto& [requirement, fulfillment] : this->resolve_requirements(module_id)) { res.push_back(requirement); - (void)fulfillment; // fulfillment is not used here } return res; From 59644d3a0e6ff241ab114940d6a3d935a045b253 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Mon, 21 Oct 2024 21:59:58 +0200 Subject: [PATCH 21/22] More const auto(&) usage Signed-off-by: Kai-Uwe Hermann --- lib/config.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/config.cpp b/lib/config.cpp index f640b144..1735e9e7 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -709,19 +709,19 @@ json Config::resolve_requirement(const std::string& module_id, const std::string std::map Config::resolve_requirements(const std::string& module_id) const { std::map requirements; - const auto module_name = get_module_name(module_id); + const auto& module_name = get_module_name(module_id); for (const auto& req_id : Config::keys(this->manifests.at(module_name).at("requires"))) { - const json resolved_req = this->resolve_requirement(module_id, req_id); + const auto& resolved_req = this->resolve_requirement(module_id, req_id); if (!resolved_req.is_array()) { - const auto resolved_module_id = resolved_req.at("module_id"); - const auto resolved_impl_id = resolved_req.at("implementation_id"); - auto req = Requirement{req_id, 0}; + const auto& resolved_module_id = resolved_req.at("module_id"); + const auto& resolved_impl_id = resolved_req.at("implementation_id"); + const auto req = Requirement{req_id, 0}; requirements[req] = {resolved_module_id, resolved_impl_id, req}; } else { for (std::size_t i = 0; i < resolved_req.size(); i++) { - const auto resolved_module_id = resolved_req.at(i).at("module_id"); - const auto resolved_impl_id = resolved_req.at(i).at("implementation_id"); - auto req = Requirement{req_id, i}; + const auto& resolved_module_id = resolved_req.at(i).at("module_id"); + const auto& resolved_impl_id = resolved_req.at(i).at("implementation_id"); + const auto req = Requirement{req_id, i}; requirements[req] = {resolved_module_id, resolved_impl_id, req}; } } From 2f45d4566009057e7428050b3e1a0213e12eddb3 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Mon, 21 Oct 2024 22:17:26 +0200 Subject: [PATCH 22/22] Fix everestrs build after removal of Requirement constructor Signed-off-by: Kai-Uwe Hermann --- everestrs/everestrs/src/everestrs_sys.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/everestrs/everestrs/src/everestrs_sys.cpp b/everestrs/everestrs/src/everestrs_sys.cpp index 08e7a65f..931a85fe 100644 --- a/everestrs/everestrs/src/everestrs_sys.cpp +++ b/everestrs/everestrs/src/everestrs_sys.cpp @@ -108,14 +108,14 @@ void Module::provide_command(const Runtime& rt, rust::String implementation_id, void Module::subscribe_variable(const Runtime& rt, rust::String implementation_id, size_t index, rust::String name) const { - const Requirement req(std::string(implementation_id), index); + const auto req = Requirement{std::string(implementation_id), index}; handle_->subscribe_var(req, std::string(name), [&rt, implementation_id, index, name](json args) { rt.handle_variable(implementation_id, index, name, json2blob(args)); }); } JsonBlob Module::call_command(rust::Str implementation_id, size_t index, rust::Str name, JsonBlob blob) const { - const Requirement req(std::string(implementation_id), index); + const auto req = Requirement{std::string(implementation_id), index}; json return_value = handle_->call_cmd(req, std::string(name), json::parse(blob.data.begin(), blob.data.end())); return json2blob(return_value);