Skip to content

Commit

Permalink
Merge branch 'main' into fix/compiler-warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
james-ctc authored Nov 5, 2024
2 parents cd740e6 + bb3d3a9 commit fbeab0a
Show file tree
Hide file tree
Showing 14 changed files with 289 additions and 125 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
)
Expand Down
7 changes: 1 addition & 6 deletions everestpy/src/everest/misc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <string>

#include <framework/runtime.hpp>
#include <utils/types.hpp>

class RuntimeSession {
public:
Expand All @@ -28,12 +29,6 @@ class RuntimeSession {
static std::unique_ptr<Everest::Config> create_config_instance(std::shared_ptr<Everest::RuntimeSettings> rs);
};

struct Fulfillment {
std::string module_id;
std::string implementation_id;
Requirement requirement;
};

struct Interface {
std::vector<std::string> variables;
std::vector<std::string> commands;
Expand Down
4 changes: 2 additions & 2 deletions everestrs/everestrs/src/everestrs_sys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions include/framework/ModuleAdapter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ struct ModuleAdapter {
using ExtMqttSubscribeFunc = std::function<UnsubscribeToken(const std::string&, StringHandler)>;
using TelemetryPublishFunc =
std::function<void(const std::string&, const std::string&, const std::string&, const TelemetryMap&)>;
using GetMappingFunc = std::function<std::optional<ModuleTierMappings>()>;

CallFunc call;
PublishFunc publish;
Expand All @@ -107,6 +108,7 @@ struct ModuleAdapter {
ExtMqttSubscribeFunc ext_mqtt_subscribe;
std::vector<cmd> registered_commands;
TelemetryPublishFunc telemetry_publish;
GetMappingFunc get_mapping;

void check_complete() {
// FIXME (aw): I should throw if some of my handlers are not set
Expand Down
12 changes: 12 additions & 0 deletions include/framework/everest.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ class Everest {
/// \returns true if telemetry is enabled
bool is_telemetry_enabled();

///
/// \returns the 3 tier model mappings for this module
///
std::optional<ModuleTierMappings> get_3_tier_model_mapping();

///
/// \brief Chccks if all commands of a module that are listed in its manifest are available
///
Expand Down Expand Up @@ -239,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<Mapping> get_impl_mapping(std::optional<ModuleTierMappings> module_tier_mappings,
const std::string& impl_id);

} // namespace Everest

#endif // FRAMEWORK_EVEREST_HPP
11 changes: 6 additions & 5 deletions include/framework/runtime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,17 @@ void populate_module_info_path_from_runtime_settings(ModuleInfo&, std::shared_pt

struct ModuleCallbacks {
std::function<void(ModuleAdapter module_adapter)> register_module_adapter;
std::function<std::vector<cmd>(const json& connections)> everest_register;
std::function<std::vector<cmd>(const RequirementInitialization& requirement_init)> everest_register;
std::function<void(ModuleConfigs module_configs, const ModuleInfo& info)> init;
std::function<void()> ready;

ModuleCallbacks() = default;

ModuleCallbacks(const std::function<void(ModuleAdapter module_adapter)>& register_module_adapter,
const std::function<std::vector<cmd>(const json& connections)>& everest_register,
const std::function<void(ModuleConfigs module_configs, const ModuleInfo& info)>& init,
const std::function<void()>& ready);
ModuleCallbacks(
const std::function<void(ModuleAdapter module_adapter)>& register_module_adapter,
const std::function<std::vector<cmd>(const RequirementInitialization& requirement_init)>& everest_register,
const std::function<void(ModuleConfigs module_configs, const ModuleInfo& info)>& init,
const std::function<void()>& ready);
};

struct VersionInformation {
Expand Down
31 changes: 27 additions & 4 deletions include/utils/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,17 @@ class Config {

///
/// \brief Parses the 3 tier model mappings in the config
/// A "mapping" can be specified in the following way:
/// You can set a EVSE id called "evse" and Connector id called "connector" for the whole module.
/// Additionally a "mapping" can be specified in the following way:
/// Alternatively you can set individual mappings for implementations.
/// mapping:
/// implementation_id:
/// module:
/// evse: 1
/// connector: 1
/// implementations:
/// implementation_id:
/// evse: 1
/// connector: 1
/// If no mappings are found it will be assumed that the module is mapped to the charging station.
/// If only a module mapping is defined alle implementations are mapped to this module mapping.
/// Implementations can have overwritten mappings.
Expand Down Expand Up @@ -144,11 +149,29 @@ 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<Requirement, Fulfillment> resolve_requirements(const std::string& module_id) const;

///
/// \returns a list of Requirements for \p module_id
///
std::list<Requirement> 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<std::string, std::vector<Fulfillment>> 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
///
Expand Down Expand Up @@ -196,11 +219,11 @@ class Config {

//
/// \returns the 3 tier model mappings for the given \p module_id
std::optional<ModuleTierMappings> get_3_tier_model_mappings(const std::string& module_id);
std::optional<ModuleTierMappings> 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<Mapping> get_3_tier_model_mapping(const std::string& module_id, const std::string& impl_id);
std::optional<Mapping> 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
Expand Down
82 changes: 62 additions & 20 deletions include/utils/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,50 @@ enum class QOS {
QOS2 ///< Exactly once delivery
};

/// \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
std::optional<int> connector; ///< An optional Connector id

Mapping(int evse) : evse(evse) {
}

Mapping(int evse, int connector) : evse(evse), connector(connector) {
}
};

/// \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>& 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<Mapping> module; ///< Mapping of the whole module to an EVSE id and optional Connector id. If this is
///< absent the module is assumed to be mapped to the whole charging station
std::unordered_map<std::string, std::optional<Mapping>>
implementations; ///< Mappings for the individual implementations of the module
};

struct ModuleInfo {
struct Paths {
std::filesystem::path etc;
Expand All @@ -78,38 +122,36 @@ struct ModuleInfo {
Paths paths;
bool telemetry_enabled;
bool global_errors_enabled;
std::optional<Mapping> mapping;
};

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
std::optional<int> connector; ///< An optional Connector id
struct Requirement {
std::string id;
size_t index = 0;
};

Mapping(int evse) : evse(evse) {
}
bool operator<(const Requirement& lhs, const Requirement& rhs);

Mapping(int evse, int connector) : evse(evse), connector(connector) {
}
/// \brief A Fulfillment relates a Requirement to its connected implementation, identified via its module and
/// implementation id.
struct Fulfillment {
std::string module_id;
std::string implementation_id;
Requirement requirement;
};

/// \brief A 3 tier mapping for a module and its individual implementations
struct ModuleTierMappings {
std::optional<Mapping> module; ///< Mapping of the whole module to an EVSE id and optional Connector id. If this is
///< absent the module is assumed to be mapped to the whole charging station
std::unordered_map<std::string, std::optional<Mapping>>
implementations; ///< Mappings for the individual implementations of the module
/// \brief Contains everything that's needed to initialize a requirement in user code
struct RequirementInitializer {
Requirement requirement;
Fulfillment fulfillment;
std::optional<Mapping> mapping;
};

struct Requirement {
Requirement(const std::string& requirement_id_, size_t index_);
bool operator<(const Requirement& rhs) const;
std::string id;
size_t index;
};
using RequirementInitialization = std::map<std::string, std::vector<RequirementInitializer>>;

struct ImplementationIdentifier {
ImplementationIdentifier(const std::string& module_id_, const std::string& implementation_id_,
Expand Down
Loading

0 comments on commit fbeab0a

Please sign in to comment.