Skip to content

Commit

Permalink
adds schema for validating the mapping files
Browse files Browse the repository at this point in the history
Signed-off-by: MarzellT <[email protected]>
  • Loading branch information
MarzellT committed Sep 12, 2024
1 parent 6d9795b commit 10db827
Show file tree
Hide file tree
Showing 12 changed files with 114 additions and 38 deletions.
1 change: 1 addition & 0 deletions modules/OCPPConfiguration/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,5 @@ target_compile_definitions(
)

add_subdirectory(mappings)
add_subdirectory(mapping_schemas)
# ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1
9 changes: 5 additions & 4 deletions modules/OCPPConfiguration/OCPPConfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ void OCPPConfiguration::init() {
void OCPPConfiguration::ready() {
invoke_ready(*p_main);

const auto mapping_file_path = std::filesystem::path{config.mapping_file_name};

try {
event_handler = std::make_unique<EventHandler>(mapping_file_path);
event_handler = std::make_unique<EventHandler>(config.mapping_file_name, config.schema_file_name);
} catch (const std::runtime_error& e) {
EVLOG_warning << "Failed to create event handler: " << e.what() << ".\nNo events will be handled!";
EVLOG_warning << "Failed to create event handler: " << e.what() << "No events will be handled!";
return;
} catch (const std::exception& e) {
EVLOG_warning << "Failed to create event handler: " << e.what() << "No events will be handled!";
return;
}

Expand Down
1 change: 1 addition & 0 deletions modules/OCPPConfiguration/OCPPConfiguration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ namespace module {
struct Conf {
std::string user_config_file_name;

Check notice on line 27 in modules/OCPPConfiguration/OCPPConfiguration.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/OCPPConfiguration/OCPPConfiguration.hpp#L27

struct member 'Conf::user_config_file_name' is never used.
std::string mapping_file_name;

Check notice on line 28 in modules/OCPPConfiguration/OCPPConfiguration.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/OCPPConfiguration/OCPPConfiguration.hpp#L28

struct member 'Conf::mapping_file_name' is never used.
std::string schema_file_name;

Check notice on line 29 in modules/OCPPConfiguration/OCPPConfiguration.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/OCPPConfiguration/OCPPConfiguration.hpp#L29

struct member 'Conf::schema_file_name' is never used.
};

class OCPPConfiguration : public Everest::ModuleBase {
Expand Down
13 changes: 10 additions & 3 deletions modules/OCPPConfiguration/doc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Configuration Options

The following configuration options are available:

.. _user_config_path:
.. _user_config_name:

**user_config_file_name**
- **Description**: File name of the user configuration file.
Expand All @@ -21,8 +21,15 @@ The following configuration options are available:
parameters into this file in the installation directory. If this file shouldn't exist it will be
automatically created.

.. _mapping_file_path:
.. _mapping_file_name:

**mapping_file_name**
- **Description**: Name of the mapping file.
This file has to be in the `mappings` directory of this module which will be installed.
This file has to be in the `mappings` directory of this module which will be installed.

.. _schema_file_name:

**schema_file_name**
- **Description**: Name of the schema file.
This file has to be in the `mapping_schemas` directory of this module which will be installed.
This should probably be set to the default.
23 changes: 0 additions & 23 deletions modules/OCPPConfiguration/docs/index.rst

This file was deleted.

5 changes: 3 additions & 2 deletions modules/OCPPConfiguration/main/event_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@

namespace module {

EventHandler::EventHandler(const std::filesystem::path& config_mapping_file_name) :
config_mapping(mapping_reader::read_mapping(config_mapping_file_name)) {
EventHandler::EventHandler(const std::filesystem::path& config_mapping_file_name,
const std::filesystem::path& mapping_schema_file_name) :
config_mapping(mapping_reader::read_mapping(config_mapping_file_name, mapping_schema_file_name)) {
}

void EventHandler::try_handle_event(const types::ocpp::EventData& event_data,
Expand Down
4 changes: 3 additions & 1 deletion modules/OCPPConfiguration/main/event_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ class EventHandler {
* Create an EventHandler with the given mapping file.
*
* @param config_mapping_file_name Name of the mapping file.
* @param mapping_schema_file_name Name of the schema file.
*/
explicit EventHandler(const std::filesystem::path& config_mapping_file_name);
EventHandler(const std::filesystem::path& config_mapping_file_name,
const std::filesystem::path& mapping_schema_file_name);

/**
* Try to handle the given event. If successful, the event will be written to the user configuration file given.
Expand Down
22 changes: 19 additions & 3 deletions modules/OCPPConfiguration/main/mapping_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
#include "mapping_reader.hpp"
#include "everest/logging.hpp"
#include "util.hpp"
#include <nlohmann/json-schema.hpp>
#include <nlohmann/json.hpp>

#include <iostream>

namespace module {
namespace {
OcppToEverestConfigMapping parse_mapping(const c4::yml::NodeRef& root);
void validate_mapping_schema(const std::filesystem::path& mapping_path, const std::filesystem::path& schema_path);
std::pair<ComponentVariable, EverestConfigMapping> parse_mapping_node(const c4::yml::NodeRef& mapping_node);
EverestConfigMapping parse_maps_to_node(const ryml::NodeRef& node);
types::ocpp::Component parse_component_node(const c4::yml::NodeRef& node);
Expand All @@ -27,6 +29,16 @@ OcppToEverestConfigMapping parse_mapping(const c4::yml::NodeRef& root) {
return mapping;
}

void validate_mapping_schema(const std::filesystem::path& mapping_path, const std::filesystem::path& schema_path) {
const auto config_as_json = Everest::load_yaml(mapping_path);
const auto schema_as_json = Everest::load_yaml(schema_path);

// validate the mapping file with the schema
auto validator = nlohmann::json_schema::json_validator{};
validator.set_root_schema(schema_as_json);
validator.validate(config_as_json);
}

std::pair<ComponentVariable, EverestConfigMapping> parse_mapping_node(const c4::yml::NodeRef& mapping_node) {
auto component_variable = parse_component_variable_node(mapping_node["ocpp_definition"]);
auto module_mapping = parse_maps_to_node(mapping_node["everest_definition"]);
Expand Down Expand Up @@ -111,8 +123,12 @@ EverestConfigMapping parse_maps_to_node(const ryml::NodeRef& node) {

} // namespace

OcppToEverestConfigMapping mapping_reader::read_mapping(const std::filesystem::path& file_name) {
const auto mapping_file_path = MAPPING_INSTALL_DIRECTORY / file_name;
OcppToEverestConfigMapping mapping_reader::read_mapping(const std::filesystem::path& mapping_file_name,
const std::filesystem::path& schema_file_name) {
const auto mapping_file_path = MAPPING_INSTALL_DIRECTORY / mapping_file_name;
const auto mapping_schema_file_path = MAPPING_SCHEMA_INSTALL_DIRECTORY / schema_file_name;

validate_mapping_schema(mapping_file_path, mapping_schema_file_path);

const auto tree = util::load_yaml_file(mapping_file_path);
const auto root = tree.rootref();
Expand Down
8 changes: 6 additions & 2 deletions modules/OCPPConfiguration/main/mapping_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@ namespace mapping_reader {
/**
* Reads the mapping file and returns the mapping.
*
* @param file_name The file name of the mapping file.
* @param mapping_file_name The file name of the mapping file.
* @param schema_file_name The file name of the schema file.
* @return The mapping.
* @throws std::runtime_error if the files can't be opened.
* @throws std::exception if the schema validation fails.
*/
OcppToEverestConfigMapping read_mapping(const std::filesystem::path& file_name);
OcppToEverestConfigMapping read_mapping(const std::filesystem::path& mapping_file_name,
const std::filesystem::path& schema_file_name);

}; // namespace mapping_reader

Expand Down
4 changes: 4 additions & 0 deletions modules/OCPPConfiguration/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ config:
description: Name of the mapping file (in the `mappings` directory).
type: string
default: "example-config-mapping.yaml"
schema_file_name:
description: Name of the schema file (in the `mapping_schemas` directory).
type: string
default: "mapping_schema.yaml"
provides:
main:
interface: empty
Expand Down
10 changes: 10 additions & 0 deletions modules/OCPPConfiguration/mapping_schemas/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copy all schema files (yaml) to the install directory
# and add a compile definition to it so the path can be used in code.

set("${PROJECT_NAME}_${MODULE_NAME}_MAPPING_SCHEMA_DIR" "${CMAKE_INSTALL_PREFIX}/etc/everest/ocpp-configuration/mapping_schemas")

install(DIRECTORY "."
DESTINATION "${${PROJECT_NAME}_${MODULE_NAME}_MAPPING_SCHEMA_DIR}"
FILES_MATCHING PATTERN "*.yaml")

target_compile_definitions(${MODULE_NAME} PRIVATE MAPPING_SCHEMA_INSTALL_DIRECTORY="${${PROJECT_NAME}_${MODULE_NAME}_MAPPING_SCHEMA_DIR}")
52 changes: 52 additions & 0 deletions modules/OCPPConfiguration/mapping_schemas/mapping_schema.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
$schema: http://json-schema.org/draft-07/schema#
description: Json schema for OCPP to Everest configuration mapping
type: array
items:
type: object
required:
- ocpp_definition
- everest_definition
properties:
ocpp_definition:
type: object
required:
- variable
properties:
component:
type: object
required:
- name
properties:
name:
type: string
instance:
type: string
evse:
type: object
required:
- id
properties:
id:
type: integer
connector_id:
type: integer
variable:
type: object
required:
- name
properties:
name:
type: string
instance:
type: string
everest_definition:
type: object
required:
- module_id
- config_param
properties:
module_id:
type: string
config_param:
type: string
additionalProperties: false

0 comments on commit 10db827

Please sign in to comment.