Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter
- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
This commit is contained in:
@@ -0,0 +1,407 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright Pionix GmbH and Contributors to EVerest
|
||||
#ifndef UTILS_CONFIG_HPP
|
||||
#define UTILS_CONFIG_HPP
|
||||
|
||||
#include <filesystem>
|
||||
#include <list>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <nlohmann/json-schema.hpp>
|
||||
|
||||
#include <utils/config/mqtt_settings.hpp>
|
||||
#include <utils/config/settings.hpp>
|
||||
#include <utils/config/storage_userconfig.hpp>
|
||||
#include <utils/config_cache.hpp>
|
||||
|
||||
#include <utils/error.hpp>
|
||||
#include <utils/error/error_type_map.hpp>
|
||||
#include <utils/module_config.hpp>
|
||||
#include <utils/types.hpp>
|
||||
|
||||
namespace Everest {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
using everest::config::ModuleConfig;
|
||||
using everest::config::ModuleConfigurations;
|
||||
|
||||
struct ManagerSettings;
|
||||
struct RuntimeSettings;
|
||||
|
||||
///
|
||||
/// \brief A structure that contains all available schemas
|
||||
///
|
||||
struct Schemas {
|
||||
nlohmann::json config; ///< The config schema
|
||||
nlohmann::json manifest; ///< The manifest scheme
|
||||
nlohmann::json interface; ///< The interface schema
|
||||
nlohmann::json type; ///< The type schema
|
||||
nlohmann::json error_declaration_list; ///< The error-declaration-list schema
|
||||
};
|
||||
|
||||
struct Validators {
|
||||
nlohmann::json_schema::json_validator config;
|
||||
nlohmann::json_schema::json_validator manifest;
|
||||
nlohmann::json_schema::json_validator type;
|
||||
nlohmann::json_schema::json_validator interface;
|
||||
nlohmann::json_schema::json_validator error_declaration_list;
|
||||
};
|
||||
|
||||
struct SchemaValidation {
|
||||
Schemas schemas;
|
||||
Validators validators;
|
||||
};
|
||||
|
||||
struct ImplementationInfo {
|
||||
std::string module_id;
|
||||
std::string module_name;
|
||||
std::string impl_id;
|
||||
std::string impl_intf;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief A simple json schema loader that uses the builtin draft7 schema of
|
||||
/// the json schema validator when it encounters it, throws an exception
|
||||
/// otherwise
|
||||
void loader(const nlohmann::json_uri& uri, nlohmann::json& schema);
|
||||
|
||||
///
|
||||
/// \brief An extension to the default format checker of the json schema
|
||||
/// validator supporting uris
|
||||
void format_checker(const std::string& format, const std::string& value);
|
||||
|
||||
///
|
||||
/// \brief loads and validates a json schema at the provided \p path
|
||||
///
|
||||
/// \returns the loaded json schema as a json object as well as a related schema validator
|
||||
std::tuple<nlohmann::json, nlohmann::json_schema::json_validator> load_schema(const fs::path& path);
|
||||
|
||||
///
|
||||
/// \brief loads the config.json and manifest.json in the schemes subfolder of
|
||||
/// the provided \p schemas_dir
|
||||
///
|
||||
/// \returns the loaded configs and related validators
|
||||
SchemaValidation load_schemas(const fs::path& schemas_dir);
|
||||
|
||||
/// \brief Serializes the given \p module_configuration and related data to JSON.
|
||||
///
|
||||
/// Includes the module's config, mappings (own and connected), and telemetry if present.
|
||||
///
|
||||
/// \param module_id ID of the module to serialize.
|
||||
/// \param module_configurations Map of all module configurations.
|
||||
/// \return JSON object with the serialized module configuration.
|
||||
json get_serialized_module_config(std::string_view module_id, const ModuleConfigurations& module_configurations);
|
||||
|
||||
///
|
||||
/// \brief Base class for configs
|
||||
///
|
||||
class ConfigBase {
|
||||
protected:
|
||||
ModuleConfigurations module_configs;
|
||||
nlohmann::json settings;
|
||||
|
||||
nlohmann::json manifests;
|
||||
nlohmann::json interfaces;
|
||||
nlohmann::json interface_definitions;
|
||||
nlohmann::json types;
|
||||
Schemas schemas;
|
||||
// experimental caches
|
||||
std::map<std::string, std::string, std::less<>> module_names;
|
||||
|
||||
error::ErrorTypeMap error_map;
|
||||
|
||||
const MQTTSettings mqtt_settings;
|
||||
|
||||
public:
|
||||
///
|
||||
/// \brief Create a ConfigBase with the provided \p mqtt_settings
|
||||
explicit ConfigBase(const MQTTSettings& mqtt_settings) : mqtt_settings(mqtt_settings){};
|
||||
|
||||
///
|
||||
/// \brief turns then given \p module_id into a printable identifier
|
||||
///
|
||||
/// \returns a string with the printable identifier
|
||||
std::string printable_identifier(std::string_view module_id) const;
|
||||
|
||||
///
|
||||
/// \brief turns then given \p module_id and \p impl_id into a printable identifier
|
||||
///
|
||||
/// \returns a string with the printable identifier
|
||||
std::string printable_identifier(std::string_view module_id, std::string_view impl_id) const;
|
||||
|
||||
///
|
||||
/// \returns the module name matching the provided \p module_id
|
||||
std::string get_module_name(std::string_view module_id) const;
|
||||
|
||||
///
|
||||
/// \brief turns the given \p module_id and \p impl_id into a mqtt prefix
|
||||
///
|
||||
std::string mqtt_prefix(std::string_view module_id, std::string_view impl_id);
|
||||
|
||||
///
|
||||
/// \brief turns the given \p module_id into a mqtt prefix
|
||||
///
|
||||
std::string mqtt_module_prefix(std::string_view module_id) const;
|
||||
|
||||
///
|
||||
/// \returns a json object that contains the main config
|
||||
const ModuleConfigurations& get_module_configurations() const;
|
||||
|
||||
///
|
||||
/// \brief checks if the config contains the given \p module_id
|
||||
bool contains(std::string_view module_id) const;
|
||||
|
||||
///
|
||||
/// \returns a json object that contains the manifests
|
||||
const nlohmann::json& get_manifests() const;
|
||||
|
||||
///
|
||||
/// \returns a json object that contains the interface definitions
|
||||
const nlohmann::json& get_interface_definitions() const;
|
||||
|
||||
///
|
||||
/// \returns a json object that contains the available interfaces
|
||||
const nlohmann::json& get_interfaces() const;
|
||||
|
||||
///
|
||||
/// \returns a json object that contains the settings
|
||||
const nlohmann::json& get_settings() const;
|
||||
|
||||
///
|
||||
/// \returns an object that contains the schemas
|
||||
const Schemas& get_schemas() const;
|
||||
|
||||
///
|
||||
/// \returns an object that contains the error types
|
||||
const error::ErrorTypes& get_error_types() const;
|
||||
|
||||
///
|
||||
/// \returns a json object that contains the types
|
||||
const nlohmann::json& get_types() const;
|
||||
|
||||
///
|
||||
/// \return the cached mapping of module ids to module names
|
||||
const std::map<std::string, std::string, std::less<>>& get_module_names() const;
|
||||
|
||||
///
|
||||
/// \brief checks if the given \p module_id provides the requirement given in \p requirement_id
|
||||
///
|
||||
/// \returns a json object that contains the requirement
|
||||
std::vector<Fulfillment> resolve_requirement(std::string_view module_id, std::string_view 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(std::string_view module_id) const;
|
||||
|
||||
///
|
||||
/// \returns a list of Requirements for \p module_id
|
||||
std::list<Requirement> get_requirements(std::string_view 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(std::string_view module_id) const;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Config intended to be created by the manager for validation and serialization. Contains config and
|
||||
/// manifest parsing
|
||||
///
|
||||
class ManagerConfig : public ConfigBase {
|
||||
private:
|
||||
const ManagerSettings& ms;
|
||||
Validators validators;
|
||||
std::unique_ptr<nlohmann::json_schema::json_validator> draft7_validator;
|
||||
std::unique_ptr<everest::config::UserConfigStorage> user_config_storage;
|
||||
std::map<everest::config::ConfigurationParameterIdentifier, everest::config::GetConfigurationParameterResponse>
|
||||
database_get_config_parameter_response_cache;
|
||||
|
||||
nlohmann::json apply_user_config_and_defaults();
|
||||
|
||||
///
|
||||
/// \brief loads and validates the manifest of the \p module_config
|
||||
void load_and_validate_manifest(ModuleConfig& module_config);
|
||||
|
||||
///
|
||||
/// \brief loads and validates the given file \p file_path with the schema \p schema
|
||||
///
|
||||
/// \returns the loaded json and how long the validation took in ms
|
||||
std::tuple<nlohmann::json, int64_t> load_and_validate_with_schema(const fs::path& file_path,
|
||||
const nlohmann::json& schema);
|
||||
|
||||
///
|
||||
/// \brief resolves inheritance tree of json interface \p intf_name, throws an exception if variables or
|
||||
/// commands would be overwritten
|
||||
///
|
||||
/// \returns the resulting interface definition
|
||||
nlohmann::json resolve_interface(std::string_view intf_name);
|
||||
|
||||
///
|
||||
/// \brief loads the contents of the interface file referenced by the give \p intf_name from disk and validates
|
||||
/// its contents
|
||||
///
|
||||
/// \returns a json object containing the interface definition
|
||||
nlohmann::json load_interface_file(std::string_view intf_name);
|
||||
|
||||
///
|
||||
/// \brief loads the contents of an error or an error list referenced by the given \p reference.
|
||||
///
|
||||
/// \returns a list of json objects containing the error definitions
|
||||
std::list<nlohmann::json> resolve_error_ref(std::string_view reference);
|
||||
|
||||
///
|
||||
/// \brief replaces all error references in the given \p interface_json with the actual error definitions
|
||||
///
|
||||
/// \returns the interface_json with replaced error references
|
||||
nlohmann::json replace_error_refs(nlohmann::json& interface_json);
|
||||
|
||||
///
|
||||
/// \brief resolves all requirements (connections) of the modules in the main config
|
||||
void resolve_all_requirements();
|
||||
|
||||
///
|
||||
/// \brief parses the provided \p config resolving types, errors, manifests, requirements and 3 tier module
|
||||
/// mappings
|
||||
void parse(ModuleConfigurations& module_configs);
|
||||
|
||||
///
|
||||
/// \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.
|
||||
/// Alternatively you can set individual mappings for implementations.
|
||||
/// mapping:
|
||||
/// 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.
|
||||
void parse_3_tier_model_mapping();
|
||||
|
||||
public:
|
||||
///
|
||||
/// \brief Create a ManagerConfig from the provided ManagerSettings \p ms
|
||||
explicit ManagerConfig(const ManagerSettings& ms);
|
||||
|
||||
/// \brief Sets the config \p value associated with the \p identifier
|
||||
/// \returns if the setting of the value was successful or not
|
||||
everest::config::SetConfigStatus
|
||||
set_config_value(const everest::config::ConfigurationParameterIdentifier& identifier,
|
||||
const everest::config::ConfigEntry& value);
|
||||
|
||||
/// \brief Gets the configuration parameter associated with the \p identifier
|
||||
/// \returns a result containing the configuration item or an error
|
||||
everest::config::GetConfigurationParameterResponse
|
||||
get_config_value(const everest::config::ConfigurationParameterIdentifier& identifier);
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Contains intended to be used by modules using a pre-parsed and validated config json serialized from
|
||||
/// ManagerConfig
|
||||
///
|
||||
class Config : public ConfigBase {
|
||||
private:
|
||||
ModuleConfig module_config;
|
||||
std::map<std::string, ModuleTierMappings, std::less<>> tier_mappings;
|
||||
std::optional<TelemetryConfig> telemetry_config;
|
||||
std::map<std::string, ConfigCache, std::less<>> module_config_cache;
|
||||
|
||||
void populate_module_config_cache();
|
||||
|
||||
void populate_error_map();
|
||||
|
||||
public:
|
||||
///
|
||||
/// \brief creates a new Config object form the given \p mqtt_settings and \p config
|
||||
explicit Config(const MQTTSettings& mqtt_settings, const nlohmann::json& config);
|
||||
|
||||
///
|
||||
/// \returns object that contains the module config options
|
||||
ModuleConfig get_module_config() const;
|
||||
|
||||
///
|
||||
/// \returns the ErrorTypeMap
|
||||
error::ErrorTypeMap get_error_map() const;
|
||||
|
||||
///
|
||||
/// \returns true if the module \p module_name provides the implementation \p impl_id
|
||||
bool module_provides(std::string_view module_name, std::string_view impl_id);
|
||||
|
||||
///
|
||||
/// \returns the commands that the modules \p module_name implements from the given implementation \p impl_id
|
||||
const nlohmann::json& get_module_cmds(std::string_view module_name, std::string_view impl_id);
|
||||
|
||||
///
|
||||
/// \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(std::string_view module_id) const;
|
||||
|
||||
///
|
||||
/// \returns a map of module config options
|
||||
ModuleConfigs get_module_configs(std::string_view module_id) const;
|
||||
|
||||
//
|
||||
/// \returns the 3 tier model mappings for the given \p module_id
|
||||
std::optional<ModuleTierMappings> get_module_3_tier_model_mappings(std::string_view 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(std::string_view module_id, std::string_view impl_id) const;
|
||||
|
||||
///
|
||||
/// \brief assemble basic information about the module (id, name,
|
||||
/// authors, license)
|
||||
///
|
||||
/// \returns a ModuleInfo object
|
||||
ModuleInfo get_module_info(std::string_view module_id) const;
|
||||
|
||||
///
|
||||
/// \returns a TelemetryConfig if this has been configured
|
||||
std::optional<TelemetryConfig> get_telemetry_config();
|
||||
|
||||
///
|
||||
/// \returns a json object that contains the interface definition
|
||||
nlohmann::json get_interface_definition(std::string_view interface_name) const;
|
||||
|
||||
///
|
||||
/// \brief A json schema loader that can handle type refs and otherwise uses the builtin draft7 schema of
|
||||
/// the json schema validator when it encounters it. Throws an exception
|
||||
/// otherwise
|
||||
void ref_loader(const nlohmann::json_uri& uri, nlohmann::json& schema);
|
||||
|
||||
///
|
||||
/// \brief loads all module manifests relative to the \p main_dir
|
||||
///
|
||||
/// \returns all module manifests as a json object
|
||||
static nlohmann::json load_all_manifests(std::string_view modules_dir, std::string_view schemas_dir);
|
||||
|
||||
///
|
||||
/// \brief Extracts the keys of the provided json \p object
|
||||
///
|
||||
/// \returns a set of object keys
|
||||
static everest::config::Keys keys(const nlohmann::json& object);
|
||||
};
|
||||
} // namespace Everest
|
||||
|
||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
template <> struct adl_serializer<Everest::Schemas> {
|
||||
static void to_json(nlohmann::json& j, const Everest::Schemas& s);
|
||||
|
||||
static void from_json(const nlohmann::json& j, Everest::Schemas& s);
|
||||
};
|
||||
NLOHMANN_JSON_NAMESPACE_END
|
||||
|
||||
#endif // UTILS_CONFIG_HPP
|
||||
Reference in New Issue
Block a user